Merge branch 'master' into master
This commit is contained in:
commit
3feb4fcc51
|
@ -21,6 +21,7 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: '0'
|
||||
submodules: recursive
|
||||
- name: Run packpack
|
||||
env:
|
||||
|
@ -29,3 +30,13 @@ jobs:
|
|||
DIST: ${{ matrix.os_dist.dist }}
|
||||
DOCKER_REPO: iconzm/packpack
|
||||
run: utils/packpack/startpackpack.sh
|
||||
|
||||
- name: Publish
|
||||
uses: easingthemes/ssh-deploy@main
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ secrets.ZMREPO_SSH_KEY }}
|
||||
ARGS: "-rltgoDzvO"
|
||||
SOURCE: build/
|
||||
REMOTE_HOST: ${{ secrets.ZMREPO_HOST }}
|
||||
REMOTE_USER: ${{ secrets.ZMREPO_SSH_USER }}
|
||||
TARGET: debian/master/mini-dinstall/incoming/
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
ZoneMinder
|
||||
==========
|
||||
|
||||
[![Build Status](https://travis-ci.org/ZoneMinder/zoneminder.png)](https://travis-ci.org/ZoneMinder/zoneminder)
|
||||
[![Bounty Source](https://api.bountysource.com/badge/team?team_id=204&style=bounties_received)](https://www.bountysource.com/teams/zoneminder/issues?utm_source=ZoneMinder&utm_medium=shield&utm_campaign=bounties_received)
|
||||
[![Join Slack](https://github.com/ozonesecurity/ozonebase/blob/master/img/slacksm.png?raw=true)](https://join.slack.com/t/zoneminder-chat/shared_invite/enQtNTU0NDkxMDM5NDQwLTdhZmQ5Y2M2NWQyN2JkYTBiN2ZkMzIzZGQ0MDliMTRmM2FjZWRlYzUwYTQ2MjMwMTVjMzQ1NjYxOTdmMjE2MTE)
|
||||
|
||||
|
@ -25,7 +24,7 @@ https://github.com/ZoneMinder/zmdockerfiles
|
|||
|
||||
This is the recommended method to install ZoneMinder onto your system. ZoneMinder packages are maintained for the following distros:
|
||||
|
||||
- Ubuntu via [Iconnor's PPA](https://launchpad.net/~iconnor)
|
||||
- Ubuntu via [Isaac Connor's PPA](https://launchpad.net/~iconnor)
|
||||
- Debian from their [default repository](https://packages.debian.org/search?searchon=names&keywords=zoneminder)
|
||||
- RHEL/CentOS and clones via [RPM Fusion](http://rpmfusion.org)
|
||||
- Fedora via [RPM Fusion](http://rpmfusion.org)
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit cd7fd49becad6010a1b8466bfebbd93999a39878
|
||||
Subproject commit eab32851421ffe54fec0229c3efc44c642bc8d46
|
|
@ -42,7 +42,8 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}
|
|||
,libswscale5|libswscale4
|
||||
,libswresample3|libswresample2
|
||||
,ffmpeg
|
||||
,libdate-manip-perl, libmime-lite-perl, libmime-tools-perl
|
||||
,libcurl4
|
||||
,libdatetime-perl, libdate-manip-perl, libmime-lite-perl, libmime-tools-perl
|
||||
,libdbd-mysql-perl
|
||||
,libphp-serialization-perl
|
||||
,libmodule-load-conditional-perl
|
||||
|
|
|
@ -35,7 +35,7 @@ Run the following commands.
|
|||
sudo apt install mariadb-server
|
||||
sudo apt install zoneminder
|
||||
|
||||
When mariadb is installed for the first time, it doesn't add a password to the root user. Therefore, for security, it is recommended to run ``mysql secure installation``.
|
||||
By default MariaDB uses `unix socket authentication`_, so no root user password is required (root MariaDB user access only available to local root Linux user). If you wish, you can set a root MariaDB password (and apply other security tweaks) by running `mariadb-secure-installation`_.
|
||||
|
||||
**Step 3:** Setup permissions for zm.conf
|
||||
|
||||
|
@ -337,3 +337,6 @@ Reload Apache to enable your changes and then start ZoneMinder.
|
|||
sudo systemctl start zoneminder
|
||||
|
||||
You are now ready to go with ZoneMinder. Open a browser and type either ``localhost/zm`` one the local machine or ``{IP-OF-ZM-SERVER}/zm`` if you connect from a remote computer.
|
||||
|
||||
.. _unix socket authentication: https://mariadb.com/kb/en/authentication-plugin-unix-socket/
|
||||
.. _mariadb-secure-installation: https://mariadb.com/kb/en/mysql_secure_installation/
|
||||
|
|
|
@ -444,11 +444,6 @@ if ( $version ) {
|
|||
|
||||
print( "\nUpgrading database to version ".ZM_VERSION."\n" );
|
||||
|
||||
# Update config first of all
|
||||
migratePaths();
|
||||
ZoneMinder::Config::loadConfigFromDB();
|
||||
ZoneMinder::Config::saveConfigToDB();
|
||||
|
||||
my $cascade = undef;
|
||||
if ( $cascade || $version eq "1.19.0" ) {
|
||||
# Patch the database
|
||||
|
|
|
@ -245,6 +245,7 @@ class Socket : public CommsBase {
|
|||
}
|
||||
|
||||
virtual ssize_t recv(std::string &msg) const {
|
||||
msg.reserve(ZM_NETWORK_BUFSIZ);
|
||||
std::vector<char> buffer(msg.capacity());
|
||||
ssize_t nBytes;
|
||||
if ((nBytes = ::recv(mSd, buffer.data(), buffer.size(), 0)) < 0) {
|
||||
|
|
|
@ -251,7 +251,7 @@ void zmDbQueue::process() {
|
|||
mCondition.wait(lock);
|
||||
}
|
||||
while (!mQueue.empty()) {
|
||||
if (mQueue.size() > 20) {
|
||||
if (mQueue.size() > 30) {
|
||||
Logger *log = Logger::fetch();
|
||||
Logger::Level db_level = log->databaseLevel();
|
||||
log->databaseLevel(Logger::NOLOG);
|
||||
|
|
|
@ -301,9 +301,9 @@ void Event::updateNotes(const StringSetMap &newNoteSetMap) {
|
|||
} // end if update
|
||||
} // void Event::updateNotes(const StringSetMap &newNoteSetMap)
|
||||
|
||||
void Event::AddPacket(const std::shared_ptr<ZMPacket>&packet) {
|
||||
void Event::AddPacket(ZMLockedPacket *packetlock) {
|
||||
std::unique_lock<std::mutex> lck(packet_queue_mutex);
|
||||
packet_queue.push(packet);
|
||||
packet_queue.push(packetlock);
|
||||
packet_queue_condition.notify_one();
|
||||
}
|
||||
|
||||
|
@ -423,7 +423,7 @@ void Event::AddFrame(Image *image,
|
|||
// If this is the first frame, we should add a thumbnail to the event directory
|
||||
if ((frames == 1) || (score > max_score)) {
|
||||
write_to_db = true; // web ui might show this as thumbnail, so db needs to know about it.
|
||||
Debug(1, "Writing snapshot");
|
||||
Debug(1, "Writing snapshot to %s", snapshot_file.c_str());
|
||||
WriteFrameImage(image, timestamp, snapshot_file.c_str());
|
||||
} else {
|
||||
Debug(1, "Not Writing snapshot because frames %d score %d > max %d", frames, score, max_score);
|
||||
|
@ -435,17 +435,19 @@ void Event::AddFrame(Image *image,
|
|||
if (!alarm_frame_written) {
|
||||
write_to_db = true; // OD processing will need it, so the db needs to know about it
|
||||
alarm_frame_written = true;
|
||||
Debug(1, "Writing alarm image");
|
||||
WriteFrameImage(image, timestamp, alarm_file.c_str());
|
||||
Debug(1, "Writing alarm image to %s", alarm_file.c_str());
|
||||
if (!WriteFrameImage(image, timestamp, alarm_file.c_str())) {
|
||||
Error("Failed to write alarm frame image to %s", alarm_file.c_str());
|
||||
}
|
||||
} else {
|
||||
Debug(3, "Not Writing alarm image because alarm frame already written");
|
||||
}
|
||||
|
||||
if (alarm_image and (save_jpegs & 2)) {
|
||||
std::string event_file = stringtf(staticConfig.analyse_file_format.c_str(), path.c_str(), frames);
|
||||
Debug(1, "Writing analysis frame %d", frames);
|
||||
Debug(1, "Writing analysis frame %d to %s", frames, event_file.c_str());
|
||||
if (!WriteFrameImage(alarm_image, timestamp, event_file.c_str(), true)) {
|
||||
Error("Failed to write analysis frame image");
|
||||
Error("Failed to write analysis frame image to %s", event_file.c_str());
|
||||
}
|
||||
}
|
||||
} // end if is an alarm frame
|
||||
|
@ -682,7 +684,9 @@ void Event::Run() {
|
|||
while (true) {
|
||||
if (!packet_queue.empty()) {
|
||||
Debug(1, "adding packet");
|
||||
this->AddPacket_(packet_queue.front());
|
||||
const ZMLockedPacket * packet_lock = packet_queue.front();
|
||||
this->AddPacket_(packet_lock->packet_);
|
||||
delete packet_lock;
|
||||
packet_queue.pop();
|
||||
} else {
|
||||
if (terminate_ or zm_terminate) {
|
||||
|
|
|
@ -105,7 +105,7 @@ class Event {
|
|||
|
||||
void createNotes(std::string ¬es);
|
||||
|
||||
std::queue<std::shared_ptr<ZMPacket>> packet_queue;
|
||||
std::queue<ZMLockedPacket *> packet_queue;
|
||||
std::mutex packet_queue_mutex;
|
||||
std::condition_variable packet_queue_condition;
|
||||
|
||||
|
@ -134,7 +134,7 @@ class Event {
|
|||
SystemTimePoint EndTime() const { return end_time; }
|
||||
TimePoint::duration Duration() const { return end_time - start_time; };
|
||||
|
||||
void AddPacket(const std::shared_ptr<ZMPacket> &p);
|
||||
void AddPacket(ZMLockedPacket *);
|
||||
void AddPacket_(const std::shared_ptr<ZMPacket> &p);
|
||||
bool WritePacket(const std::shared_ptr<ZMPacket> &p);
|
||||
bool SendFrameImage(const Image *image, bool alarm_frame=false);
|
||||
|
|
|
@ -257,8 +257,8 @@ void zm_dump_stream_format(AVFormatContext *ic, int i, int index, int is_output)
|
|||
Debug(1, "ids [0x%x]", st->id);
|
||||
if (lang)
|
||||
Debug(1, "language (%s)", lang->value);
|
||||
Debug(1, "frames:%d, frame_size:%d stream timebase: %d/%d",
|
||||
st->codec_info_nb_frames, codec->frame_size,
|
||||
Debug(1, "frame_size:%d stream timebase: %d/%d",
|
||||
codec->frame_size,
|
||||
st->time_base.num, st->time_base.den
|
||||
);
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "zm_utils.h"
|
||||
#include <algorithm>
|
||||
#include <fcntl.h>
|
||||
#include <mutex>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
@ -80,6 +81,8 @@ imgbufcpy_fptr_t fptr_imgbufcpy;
|
|||
/* Font */
|
||||
static ZmFont font;
|
||||
|
||||
std::mutex jpeg_mutex;
|
||||
|
||||
void Image::update_function_pointers() {
|
||||
/* Because many loops are unrolled and work on 16 colours/time or 4 pixels/time, we have to meet requirements */
|
||||
if ( pixels % 16 || pixels % 12 ) {
|
||||
|
@ -1083,6 +1086,9 @@ bool Image::WriteJpeg(const std::string &filename,
|
|||
const int &quality_override,
|
||||
SystemTimePoint timestamp,
|
||||
bool on_blocking_abort) const {
|
||||
// jpeg libs are not thread safe
|
||||
std::unique_lock<std::mutex> lck(jpeg_mutex);
|
||||
|
||||
if (config.colour_jpeg_files && (colours == ZM_COLOUR_GRAY8)) {
|
||||
Image temp_image(*this);
|
||||
temp_image.Colourise(ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB);
|
||||
|
@ -1366,6 +1372,8 @@ bool Image::EncodeJpeg(JOCTET *outbuffer, int *outbuffer_size, int quality_overr
|
|||
return temp_image.EncodeJpeg(outbuffer, outbuffer_size, quality_override);
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> lck(jpeg_mutex);
|
||||
|
||||
int quality = quality_override ? quality_override : config.jpeg_stream_quality;
|
||||
|
||||
struct jpeg_compress_struct *cinfo = encodejpg_ccinfo[quality];
|
||||
|
|
|
@ -2321,34 +2321,37 @@ bool Monitor::Analyse() {
|
|||
shared_data->state = state = IDLE;
|
||||
} // end if ( trigger_data->trigger_state != TRIGGER_OFF )
|
||||
|
||||
if (event) event->AddPacket(snap);
|
||||
packetqueue.clearPackets(snap);
|
||||
|
||||
if (snap->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
// Only do these if it's a video packet.
|
||||
shared_data->last_read_index = snap->image_index;
|
||||
analysis_image_count++;
|
||||
}
|
||||
|
||||
if (event) {
|
||||
event->AddPacket(packet_lock);
|
||||
} else {
|
||||
// In the case where people have pre-alarm frames, the web ui will generate the frame images
|
||||
// from the mp4. So no one will notice anyways.
|
||||
if (snap->image and (videowriter == PASSTHROUGH)) {
|
||||
if (!savejpegs) {
|
||||
Debug(1, "Deleting image data for %d", snap->image_index);
|
||||
// Don't need raw images anymore
|
||||
delete snap->image;
|
||||
snap->image = nullptr;
|
||||
}
|
||||
if (snap->analysis_image and !(savejpegs & 2)) {
|
||||
Debug(1, "Deleting analysis image data for %d", snap->image_index);
|
||||
delete snap->analysis_image;
|
||||
snap->analysis_image = nullptr;
|
||||
}
|
||||
}
|
||||
delete packet_lock;
|
||||
}
|
||||
} // end scope for event_lock
|
||||
|
||||
// In the case where people have pre-alarm frames, the web ui will generate the frame images
|
||||
// from the mp4. So no one will notice anyways.
|
||||
if (snap->image and (videowriter == PASSTHROUGH)) {
|
||||
if (!savejpegs) {
|
||||
Debug(1, "Deleting image data for %d", snap->image_index);
|
||||
// Don't need raw images anymore
|
||||
delete snap->image;
|
||||
snap->image = nullptr;
|
||||
}
|
||||
if (snap->analysis_image and !(savejpegs & 2)) {
|
||||
Debug(1, "Deleting analysis image data for %d", snap->image_index);
|
||||
delete snap->analysis_image;
|
||||
snap->analysis_image = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
packetqueue.clearPackets(snap);
|
||||
|
||||
if (snap->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
// Only do these if it's a video packet.
|
||||
shared_data->last_read_index = snap->image_index;
|
||||
analysis_image_count++;
|
||||
}
|
||||
packetqueue.increment_it(analysis_it);
|
||||
delete packet_lock;
|
||||
//packetqueue.unlock(packet_lock);
|
||||
shared_data->last_read_time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
|
||||
|
||||
|
@ -2921,16 +2924,16 @@ Event * Monitor::openEvent(
|
|||
|
||||
// Write out starting packets, do not modify packetqueue it will garbage collect itself
|
||||
while (starting_packet and ((*start_it) != *analysis_it)) {
|
||||
event->AddPacket(starting_packet);
|
||||
event->AddPacket(starting_packet_lock);
|
||||
// Have added the packet, don't want to unlock it until we have locked the next
|
||||
|
||||
packetqueue.increment_it(start_it);
|
||||
if ((*start_it) == *analysis_it) {
|
||||
if (starting_packet_lock) delete starting_packet_lock;
|
||||
//if (starting_packet_lock) delete starting_packet_lock;
|
||||
break;
|
||||
}
|
||||
ZMLockedPacket *lp = packetqueue.get_packet(start_it);
|
||||
delete starting_packet_lock;
|
||||
//delete starting_packet_lock;
|
||||
if (!lp) return nullptr; // only on terminate FIXME
|
||||
starting_packet_lock = lp;
|
||||
starting_packet = lp->packet_;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "zm_config.h"
|
||||
#include "zm_monitor.h"
|
||||
#include "zm_packet.h"
|
||||
#include "zm_signal.h"
|
||||
|
||||
RemoteCameraRtsp::RemoteCameraRtsp(
|
||||
const Monitor *monitor,
|
||||
|
@ -126,8 +127,8 @@ int RemoteCameraRtsp::Disconnect() {
|
|||
|
||||
int RemoteCameraRtsp::PrimeCapture() {
|
||||
Debug(2, "Waiting for sources");
|
||||
for (int i = 0; i < 100 && !rtspThread->hasSources(); i++) {
|
||||
std::this_thread::sleep_for(Microseconds(100));
|
||||
for (int i = 100; i && !zm_terminate && !rtspThread->hasSources(); i--) {
|
||||
std::this_thread::sleep_for(Microseconds(10000));
|
||||
}
|
||||
|
||||
if (!rtspThread->hasSources()) {
|
||||
|
@ -168,8 +169,10 @@ int RemoteCameraRtsp::PrimeCapture() {
|
|||
}
|
||||
} // end foreach stream
|
||||
|
||||
if ( mVideoStreamId == -1 )
|
||||
Fatal("Unable to locate video stream");
|
||||
if ( mVideoStreamId == -1 ) {
|
||||
Error("Unable to locate video stream");
|
||||
return -1;
|
||||
}
|
||||
if ( mAudioStreamId == -1 )
|
||||
Debug(3, "Unable to locate audio stream");
|
||||
|
||||
|
@ -179,17 +182,22 @@ int RemoteCameraRtsp::PrimeCapture() {
|
|||
|
||||
// Find the decoder for the video stream
|
||||
AVCodec *codec = avcodec_find_decoder(mVideoCodecContext->codec_id);
|
||||
if ( codec == nullptr )
|
||||
Panic("Unable to locate codec %d decoder", mVideoCodecContext->codec_id);
|
||||
if ( codec == nullptr ) {
|
||||
Error("Unable to locate codec %d decoder", mVideoCodecContext->codec_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Open codec
|
||||
if ( avcodec_open2(mVideoCodecContext, codec, nullptr) < 0 )
|
||||
Panic("Can't open codec");
|
||||
if ( avcodec_open2(mVideoCodecContext, codec, nullptr) < 0 ) {
|
||||
Error("Can't open codec");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int pSize = av_image_get_buffer_size(imagePixFormat, width, height, 1);
|
||||
|
||||
if ( (unsigned int)pSize != imagesize ) {
|
||||
Fatal("Image size mismatch. Required: %d Available: %llu", pSize, imagesize);
|
||||
Error("Image size mismatch. Required: %d Available: %llu", pSize, imagesize);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@ -208,18 +216,13 @@ int RemoteCameraRtsp::PreCapture() {
|
|||
int RemoteCameraRtsp::Capture(std::shared_ptr<ZMPacket> &zm_packet) {
|
||||
int frameComplete = false;
|
||||
AVPacket *packet = &zm_packet->packet;
|
||||
if ( !zm_packet->image ) {
|
||||
Debug(1, "Allocating image %dx%d %d colours %d", width, height, colours, subpixelorder);
|
||||
zm_packet->image = new Image(width, height, colours, subpixelorder);
|
||||
}
|
||||
|
||||
|
||||
while (!frameComplete) {
|
||||
buffer.clear();
|
||||
if (!rtspThread || rtspThread->IsStopped())
|
||||
if (!rtspThread || rtspThread->IsStopped() || zm_terminate)
|
||||
return -1;
|
||||
|
||||
if ( rtspThread->getFrame(buffer) ) {
|
||||
if (rtspThread->getFrame(buffer)) {
|
||||
Debug(3, "Read frame %d bytes", buffer.size());
|
||||
Hexdump(4, buffer.head(), 16);
|
||||
|
||||
|
@ -254,36 +257,20 @@ int RemoteCameraRtsp::Capture(std::shared_ptr<ZMPacket> &zm_packet) {
|
|||
|
||||
//while ( (!frameComplete) && (buffer.size() > 0) ) {
|
||||
if ( buffer.size() > 0 ) {
|
||||
packet->data = buffer.head();
|
||||
packet->data = (uint8_t*)av_malloc(buffer.size());
|
||||
memcpy(packet->data, buffer.head(), buffer.size());
|
||||
//packet->data = buffer.head();
|
||||
packet->size = buffer.size();
|
||||
bytes += packet->size;
|
||||
buffer -= packet->size;
|
||||
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
gettimeofday(&now, nullptr);
|
||||
packet->pts = packet->dts = now.tv_sec*1000000+now.tv_usec;
|
||||
|
||||
int bytes_consumed = zm_packet->decode(mVideoCodecContext);
|
||||
if ( bytes_consumed < 0 ) {
|
||||
Error("Error while decoding frame %d", frameCount);
|
||||
//Hexdump(Logger::ERROR, buffer.head(), buffer.size()>256?256:buffer.size());
|
||||
}
|
||||
buffer -= packet->size;
|
||||
if ( bytes_consumed ) {
|
||||
zm_dump_video_frame(zm_packet->in_frame, "remote_rtsp_decode");
|
||||
if (!mVideoStream->codecpar->width) {
|
||||
zm_dump_codec(mVideoCodecContext);
|
||||
zm_dump_codecpar(mVideoStream->codecpar);
|
||||
mVideoStream->codecpar->width = zm_packet->in_frame->width;
|
||||
mVideoStream->codecpar->height = zm_packet->in_frame->height;
|
||||
zm_dump_codecpar(mVideoStream->codecpar);
|
||||
}
|
||||
zm_packet->codec_type = mVideoCodecContext->codec_type;
|
||||
zm_packet->stream = mVideoStream;
|
||||
frameComplete = true;
|
||||
Debug(2, "Frame: %d - %d/%d", frameCount, bytes_consumed, buffer.size());
|
||||
packet->data = nullptr;
|
||||
packet->size = 0;
|
||||
}
|
||||
zm_packet->codec_type = mVideoCodecContext->codec_type;
|
||||
zm_packet->stream = mVideoStream;
|
||||
frameComplete = true;
|
||||
Debug(2, "Frame: %d - %d/%d", frameCount, packet->size, buffer.size());
|
||||
}
|
||||
} /* getFrame() */
|
||||
} // end while true
|
||||
|
|
|
@ -277,7 +277,7 @@ void RtpCtrlThread::Run() {
|
|||
TimePoint last_receive = std::chrono::steady_clock::now();
|
||||
bool timeout = false; // used as a flag that we had a timeout, and then sent an RR to see if we wake back up. Real timeout will happen when this is true.
|
||||
|
||||
while (!mTerminate && select.wait() >= 0) {
|
||||
while (!mTerminate && (select.wait() >= 0)) {
|
||||
TimePoint now = std::chrono::steady_clock::now();
|
||||
zm::Select::CommsList readable = select.getReadable();
|
||||
if ( readable.size() == 0 ) {
|
||||
|
|
|
@ -45,8 +45,10 @@ RtpSource::RtpSource(
|
|||
mFrame(65536),
|
||||
mFrameCount(0),
|
||||
mFrameGood(true),
|
||||
prevM(false),
|
||||
mFrameReady(false),
|
||||
mFrameProcessed(false)
|
||||
mFrameProcessed(false),
|
||||
mTerminate(false)
|
||||
{
|
||||
char hostname[256] = "";
|
||||
gethostname(hostname, sizeof(hostname));
|
||||
|
|
|
@ -91,8 +91,6 @@ private:
|
|||
bool mFrameGood;
|
||||
bool prevM;
|
||||
|
||||
bool mTerminate;
|
||||
|
||||
bool mFrameReady;
|
||||
std::condition_variable mFrameReadyCv;
|
||||
std::mutex mFrameReadyMutex;
|
||||
|
@ -100,6 +98,7 @@ private:
|
|||
bool mFrameProcessed;
|
||||
std::condition_variable mFrameProcessedCv;
|
||||
std::mutex mFrameProcessedMutex;
|
||||
bool mTerminate;
|
||||
|
||||
private:
|
||||
void init(uint16_t seq);
|
||||
|
|
|
@ -298,6 +298,14 @@ int main(int argc, char *argv[]) {
|
|||
session->GetMediaSessionId(), xop::channel_1, audioFifoPath);
|
||||
audioSource->setFrequency(monitor->GetAudioFrequency());
|
||||
audioSource->setChannels(monitor->GetAudioChannels());
|
||||
} else if (std::string::npos != audioFifoPath.find("pcm_alaw")) {
|
||||
Debug(1, "Adding G711A source at %dHz %d channels",
|
||||
monitor->GetAudioFrequency(), monitor->GetAudioChannels());
|
||||
session->AddSource(xop::channel_1, xop::G711ASource::CreateNew());
|
||||
audioSource = new ADTS_ZoneMinderFifoSource(rtspServer,
|
||||
session->GetMediaSessionId(), xop::channel_1, audioFifoPath);
|
||||
audioSource->setFrequency(monitor->GetAudioFrequency());
|
||||
audioSource->setChannels(monitor->GetAudioChannels());
|
||||
} else {
|
||||
Warning("Unknown format in %s", audioFifoPath.c_str());
|
||||
}
|
||||
|
|
|
@ -118,7 +118,7 @@ commonprep () {
|
|||
fi
|
||||
fi
|
||||
|
||||
RTSPVER="cd7fd49becad6010a1b8466bfebbd93999a39878"
|
||||
RTSPVER="eab32851421ffe54fec0229c3efc44c642bc8d46"
|
||||
if [ -e "build/RtspServer-${RTSPVER}.tar.gz" ]; then
|
||||
echo "Found existing RtspServer ${RTSPVER} tarball..."
|
||||
else
|
||||
|
|
|
@ -187,6 +187,9 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim
|
|||
|
||||
$col_str = 'E.*, M.Name AS Monitor';
|
||||
$sql = 'SELECT ' .$col_str. ' FROM `Events` AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id'.$where.($sort?' ORDER BY '.$sort.' '.$order:'');
|
||||
if ($filter->limit() and !count($filter->pre_sql_conditions()) and !count($filter->post_sql_conditions())) {
|
||||
$sql .= ' LIMIT '.$filter->limit();
|
||||
}
|
||||
|
||||
$storage_areas = ZM\Storage::find();
|
||||
$StorageById = array();
|
||||
|
@ -213,6 +216,12 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim
|
|||
$unfiltered_rows[] = $row;
|
||||
} # end foreach row
|
||||
|
||||
# Filter limits come before pagination limits.
|
||||
if ($filter->limit() and ($filter->limit() > count($unfiltered_rows))) {
|
||||
ZM\Debug("Filtering rows due to filter->limit " . count($unfiltered_rows)." limit: ".$filter->limit());
|
||||
$unfiltered_rows = array_slice($unfiltered_rows, 0, $filter->limit());
|
||||
}
|
||||
|
||||
ZM\Debug('Have ' . count($unfiltered_rows) . ' events matching base filter.');
|
||||
|
||||
$filtered_rows = null;
|
||||
|
@ -251,8 +260,10 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim
|
|||
$filtered_rows = $unfiltered_rows;
|
||||
} # end if search_filter->terms() > 1
|
||||
|
||||
if ($limit)
|
||||
if ($limit) {
|
||||
ZM\Debug("Filtering rows due to limit " . count($filtered_rows)." offset: $offset limit: $limit");
|
||||
$filtered_rows = array_slice($filtered_rows, $offset, $limit);
|
||||
}
|
||||
|
||||
$returned_rows = array();
|
||||
foreach ($filtered_rows as $row) {
|
||||
|
|
|
@ -38,6 +38,14 @@ function MonitorStream(monitorData) {
|
|||
}
|
||||
return this.element;
|
||||
};
|
||||
this.getFrame = function() {
|
||||
if (this.frame) return this.frame;
|
||||
this.frame = document.getElementById('imageFeed'+this.id);
|
||||
if (!this.frame) {
|
||||
console.error("No frame div for #imageFeed"+this.id);
|
||||
}
|
||||
return this.frame;
|
||||
};
|
||||
|
||||
/* if the img element didn't have a src, this would fill it in, causing it to show. */
|
||||
this.show = function() {
|
||||
|
@ -161,7 +169,7 @@ function MonitorStream(monitorData) {
|
|||
|
||||
this.setup_onclick = function(func) {
|
||||
this.onclick = func;
|
||||
const el = this.getElement();
|
||||
const el = this.getFrame();
|
||||
if (!el) return;
|
||||
el.addEventListener('click', this.onclick, false);
|
||||
};
|
||||
|
|
|
@ -15,7 +15,11 @@ input[name="newMonitor[Path]"],
|
|||
input[name="newMonitor[SecondPath]"],
|
||||
input[name="newMonitor[LabelFormat]"],
|
||||
input[name="newMonitor[ControlDevice]"],
|
||||
input[name="newMonitor[ControlAddress]"] {
|
||||
input[name="newMonitor[ControlAddress]"],
|
||||
input[name="newMonitor[ONVIF_URL]"],
|
||||
input[name="newMonitor[ONVIF_Username]"],
|
||||
input[name="newMonitor[ONVIF_Password]"],
|
||||
input[name="newMonitor[ONVIF_Options]"] {
|
||||
width: 100%;
|
||||
}
|
||||
input[name="newMonitor[LabelFormat]"]{
|
||||
|
|
|
@ -109,7 +109,8 @@ stateStrings[STATE_TAPE] = "<?php echo translate('Record') ?>";
|
|||
<?php
|
||||
global $config;
|
||||
foreach ($config as $name=>$c) {
|
||||
if (!$c['Private'])
|
||||
echo 'const '. $name . ' = \''.$c['Value'].'\''.PHP_EOL;
|
||||
if (!$c['Private']) {
|
||||
echo 'const '. $name . ' = \''.preg_replace('/(\n\r?)/', '\\\\$1', $c['Value']).'\';'.PHP_EOL;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -1,9 +1,3 @@
|
|||
<?php
|
||||
if ( ZM_OPT_USE_GEOLOCATION ) {
|
||||
echo 'var ZM_OPT_GEOLOCATION_TILE_PROVIDER=\''.ZM_OPT_GEOLOCATION_TILE_PROVIDER.'\''.PHP_EOL;
|
||||
echo 'var ZM_OPT_GEOLOCATION_ACCESS_TOKEN=\''.ZM_OPT_GEOLOCATION_ACCESS_TOKEN.'\''.PHP_EOL;
|
||||
}
|
||||
?>
|
||||
var optControl = <?php echo ZM_OPT_CONTROL ?>;
|
||||
var hasOnvif = <?php echo ZM_HAS_ONVIF ?>;
|
||||
var defaultAspectRatio = '<?php echo ZM_DEFAULT_ASPECT_RATIO ?>';
|
||||
|
|
Loading…
Reference in New Issue