From 2cf6ad80895a11148db8c200a5f997426f000e23 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Sat, 8 May 2021 21:14:20 -0400 Subject: [PATCH] Switch ZMPacket * to a shared_ptr. This is so that in LockedPacket we can unlock and then notify and be confident that packet_ won't have been deleted. Change ZMPacket->timestamp to be a timeval instead of timeval *. This might not have been necessary but I like it. No longer cuse the ZMPacket object to wrap the shared image buffers and timestamps. Use a vector for image_buffers. --- dep/RtspServer | 2 +- src/zm_camera.h | 4 +- src/zm_event.cpp | 15 +- src/zm_event.h | 4 +- src/zm_ffmpeg_camera.cpp | 12 +- src/zm_ffmpeg_camera.h | 4 +- src/zm_file_camera.cpp | 4 +- src/zm_file_camera.h | 2 +- src/zm_local_camera.cpp | 30 ++-- src/zm_local_camera.h | 2 +- src/zm_monitor.cpp | 163 ++++++------------ src/zm_monitor.h | 5 +- src/zm_monitorstream.cpp | 51 +++--- src/zm_monitorstream.h | 4 +- src/zm_packet.cpp | 41 +++-- src/zm_packet.h | 9 +- src/zm_packetqueue.cpp | 263 ++++-------------------------- src/zm_packetqueue.h | 22 +-- src/zm_remote_camera.h | 2 +- src/zm_remote_camera_http.cpp | 16 +- src/zm_remote_camera_http.h | 2 +- src/zm_remote_camera_nvsocket.cpp | 14 +- src/zm_remote_camera_nvsocket.h | 2 +- src/zm_remote_camera_rtsp.cpp | 28 ++-- src/zm_remote_camera_rtsp.h | 2 +- src/zm_videostore.cpp | 24 +-- src/zm_videostore.h | 8 +- src/zm_zone.cpp | 2 +- src/zmc.cpp | 1 + web/api/app/Plugin/Crud | 2 +- 30 files changed, 253 insertions(+), 487 deletions(-) diff --git a/dep/RtspServer b/dep/RtspServer index cd7fd49be..d714323e6 160000 --- a/dep/RtspServer +++ b/dep/RtspServer @@ -1 +1 @@ -Subproject commit cd7fd49becad6010a1b8466bfebbd93999a39878 +Subproject commit d714323e693ba106be6af363295d950f50ca15e0 diff --git a/src/zm_camera.h b/src/zm_camera.h index fb117dcfb..f339415e1 100644 --- a/src/zm_camera.h +++ b/src/zm_camera.h @@ -24,6 +24,8 @@ #include #include +#include + class Monitor; class ZMPacket; @@ -133,7 +135,7 @@ public: virtual int PrimeCapture() { return 0; } virtual int PreCapture() = 0; - virtual int Capture(ZMPacket &p) = 0; + virtual int Capture(std::shared_ptr &p) = 0; virtual int PostCapture() = 0; virtual int Close() = 0; }; diff --git a/src/zm_event.cpp b/src/zm_event.cpp index 103320536..c6c16ebd5 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -285,7 +285,7 @@ void Event::createNotes(std::string ¬es) { bool Event::WriteFrameImage( Image *image, - struct timeval timestamp, + timeval timestamp, const char *event_file, bool alarm_frame) const { @@ -299,7 +299,7 @@ bool Event::WriteFrameImage( // stash the image we plan to use in another pointer regardless if timestamped. // exif is only timestamp at present this switches on or off for write Image *ts_image = new Image(*image); - monitor->TimestampImage(ts_image, ×tamp); + monitor->TimestampImage(ts_image, timestamp); rc = ts_image->WriteJpeg(event_file, thisquality, (monitor->Exif() ? timestamp : (timeval){0,0})); delete(ts_image); @@ -311,9 +311,8 @@ bool Event::WriteFrameImage( return rc; } // end Event::WriteFrameImage( Image *image, struct timeval timestamp, const char *event_file, bool alarm_frame ) -bool Event::WritePacket(ZMPacket &packet) { - - if ( videoStore->writePacket(&packet) < 0 ) +bool Event::WritePacket(const std::shared_ptr&packet) { + if (videoStore->writePacket(packet) < 0) return false; return true; } // bool Event::WriteFrameVideo @@ -420,7 +419,7 @@ void Event::updateNotes(const StringSetMap &newNoteSetMap) { } // end if update } // void Event::updateNotes(const StringSetMap &newNoteSetMap) -void Event::AddPacket(ZMPacket *packet) { +void Event::AddPacket(const std::shared_ptr&packet) { have_video_keyframe = have_video_keyframe || ( ( packet->codec_type == AVMEDIA_TYPE_VIDEO ) && @@ -437,8 +436,8 @@ void Event::AddPacket(ZMPacket *packet) { //FIXME if it fails, we should write a jpeg } if ((packet->codec_type == AVMEDIA_TYPE_VIDEO) or packet->image) - AddFrame(packet->image, *(packet->timestamp), packet->zone_stats, packet->score, packet->analysis_image); - end_time = *packet->timestamp; + AddFrame(packet->image, packet->timestamp, packet->zone_stats, packet->score, packet->analysis_image); + end_time = packet->timestamp; return; } diff --git a/src/zm_event.h b/src/zm_event.h index 7d0a334c5..4b058fc8e 100644 --- a/src/zm_event.h +++ b/src/zm_event.h @@ -111,8 +111,8 @@ class Event { const struct timeval &StartTime() const { return start_time; } const struct timeval &EndTime() const { return end_time; } - void AddPacket(ZMPacket *p); - bool WritePacket(ZMPacket &p); + void AddPacket(const std::shared_ptr &p); + bool WritePacket(const std::shared_ptr &p); bool SendFrameImage(const Image *image, bool alarm_frame=false); bool WriteFrameImage( Image *image, diff --git a/src/zm_ffmpeg_camera.cpp b/src/zm_ffmpeg_camera.cpp index b0c1401e7..f6e366911 100644 --- a/src/zm_ffmpeg_camera.cpp +++ b/src/zm_ffmpeg_camera.cpp @@ -189,7 +189,7 @@ int FfmpegCamera::PreCapture() { return 0; } -int FfmpegCamera::Capture(ZMPacket &zm_packet) { +int FfmpegCamera::Capture(std::shared_ptr &zm_packet) { if (!mCanCapture) return -1; start_read_time = time(nullptr); @@ -236,14 +236,14 @@ int FfmpegCamera::Capture(ZMPacket &zm_packet) { ZM_DUMP_STREAM_PACKET(stream, packet, "ffmpeg_camera in"); #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) - zm_packet.codec_type = stream->codecpar->codec_type; + zm_packet->codec_type = stream->codecpar->codec_type; #else - zm_packet.codec_type = stream->codec->codec_type; + zm_packet->codec_type = stream->codec->codec_type; #endif bytes += packet.size; - zm_packet.set_packet(&packet); - zm_packet.stream = stream; - zm_packet.pts = av_rescale_q(packet.pts, stream->time_base, AV_TIME_BASE_Q); + zm_packet->set_packet(&packet); + zm_packet->stream = stream; + zm_packet->pts = av_rescale_q(packet.pts, stream->time_base, AV_TIME_BASE_Q); if ( packet.pts != AV_NOPTS_VALUE ) { if ( stream == mVideoStream ) { if (mFirstVideoPTS == AV_NOPTS_VALUE) diff --git a/src/zm_ffmpeg_camera.h b/src/zm_ffmpeg_camera.h index e6f55b634..df1cb3936 100644 --- a/src/zm_ffmpeg_camera.h +++ b/src/zm_ffmpeg_camera.h @@ -22,6 +22,8 @@ #include "zm_camera.h" +#include + #if HAVE_LIBAVUTIL_HWCONTEXT_H typedef struct DecodeContext { AVBufferRef *hw_device_ref; @@ -93,7 +95,7 @@ class FfmpegCamera : public Camera { int PrimeCapture() override; int PreCapture() override; - int Capture(ZMPacket &p) override; + int Capture(std::shared_ptr &p) override; int PostCapture() override; private: static int FfmpegInterruptCallback(void*ctx); diff --git a/src/zm_file_camera.cpp b/src/zm_file_camera.cpp index af494ce38..2563482f1 100644 --- a/src/zm_file_camera.cpp +++ b/src/zm_file_camera.cpp @@ -87,8 +87,8 @@ int FileCamera::PreCapture() { return 0; } -int FileCamera::Capture( ZMPacket &zm_packet ) { - return zm_packet.image->ReadJpeg(path, colours, subpixelorder) ? 1 : -1; +int FileCamera::Capture(std::shared_ptr &zm_packet) { + return zm_packet->image->ReadJpeg(path, colours, subpixelorder) ? 1 : -1; } int FileCamera::PostCapture() { diff --git a/src/zm_file_camera.h b/src/zm_file_camera.h index 11a5cfe3f..fa923ac67 100644 --- a/src/zm_file_camera.h +++ b/src/zm_file_camera.h @@ -51,7 +51,7 @@ public: void Initialise(); void Terminate(); int PreCapture() override; - int Capture(ZMPacket &p) override; + int Capture(std::shared_ptr &p) override; int PostCapture() override; int Close() override { return 0; }; }; diff --git a/src/zm_local_camera.cpp b/src/zm_local_camera.cpp index 7e97ecd08..b72c38015 100644 --- a/src/zm_local_camera.cpp +++ b/src/zm_local_camera.cpp @@ -2036,16 +2036,16 @@ int LocalCamera::PreCapture() { return 1; } -int LocalCamera::Capture(ZMPacket &zm_packet) { +int LocalCamera::Capture(std::shared_ptr &zm_packet) { // We assume that the avpacket is allocated, and just needs to be filled static uint8_t* buffer = nullptr; int buffer_bytesused = 0; int capture_frame = -1; int captures_per_frame = 1; - if ( channel_count > 1 ) + if (channel_count > 1) captures_per_frame = v4l_captures_per_frame; - if ( captures_per_frame <= 0 ) { + if (captures_per_frame <= 0) { captures_per_frame = 1; Warning("Invalid Captures Per Frame setting: %d", captures_per_frame); } @@ -2191,22 +2191,22 @@ int LocalCamera::Capture(ZMPacket &zm_packet) { } /* prime capture */ - if (!zm_packet.image) { + if (!zm_packet->image) { Debug(4, "Allocating image"); - zm_packet.image = new Image(width, height, colours, subpixelorder); + zm_packet->image = new Image(width, height, colours, subpixelorder); } - if ( conversion_type != 0 ) { + if (conversion_type != 0) { Debug(3, "Performing format conversion %d", conversion_type); /* Request a writeable buffer of the target image */ - uint8_t *directbuffer = zm_packet.image->WriteBuffer(width, height, colours, subpixelorder); - if ( directbuffer == nullptr ) { + uint8_t *directbuffer = zm_packet->image->WriteBuffer(width, height, colours, subpixelorder); + if (directbuffer == nullptr) { Error("Failed requesting writeable buffer for the captured image."); return -1; } #if HAVE_LIBSWSCALE - if ( conversion_type == 1 ) { + if (conversion_type == 1) { Debug(9, "Calling sws_scale to perform the conversion"); /* Use swscale to convert the image directly into the shared memory */ #if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0) @@ -2236,20 +2236,20 @@ int LocalCamera::Capture(ZMPacket &zm_packet) { // Need to store the jpeg data too Debug(9, "Decoding the JPEG image"); /* JPEG decoding */ - zm_packet.image->DecodeJpeg(buffer, buffer_bytesused, colours, subpixelorder); + zm_packet->image->DecodeJpeg(buffer, buffer_bytesused, colours, subpixelorder); } } else { Debug(3, "No format conversion performed. Assigning the image"); /* No conversion was performed, the image is in the V4L buffers and needs to be copied into the shared memory */ - zm_packet.image->Assign(width, height, colours, subpixelorder, buffer, imagesize); + zm_packet->image->Assign(width, height, colours, subpixelorder, buffer, imagesize); } // end if doing conversion or not - zm_packet.packet.stream_index = mVideoStreamId; - zm_packet.stream = mVideoStream; - zm_packet.codec_type = AVMEDIA_TYPE_VIDEO; - zm_packet.keyframe = 1; + zm_packet->packet.stream_index = mVideoStreamId; + zm_packet->stream = mVideoStream; + zm_packet->codec_type = AVMEDIA_TYPE_VIDEO; + zm_packet->keyframe = 1; return 1; } // end int LocalCamera::Capture() diff --git a/src/zm_local_camera.h b/src/zm_local_camera.h index 6d3ff2672..6c64e39d6 100644 --- a/src/zm_local_camera.h +++ b/src/zm_local_camera.h @@ -151,7 +151,7 @@ public: int PrimeCapture() override; int PreCapture() override; - int Capture(ZMPacket &p) override; + int Capture(std::shared_ptr &p) override; int PostCapture() override; int Close() override { return 0; }; diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 97f20c5df..63ce15d60 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -996,12 +996,10 @@ bool Monitor::connect() { if (!camera) LoadCamera(); Debug(3, "Allocating %d image buffers", image_buffer_count); - image_buffer = new ZMPacket[image_buffer_count]; + image_buffer.reserve(image_buffer_count); for (int32_t i = 0; i < image_buffer_count; i++) { - image_buffer[i].image_index = i; - image_buffer[i].timestamp = &(shared_timestamps[i]); - image_buffer[i].image = new Image(width, height, camera->Colours(), camera->SubpixelOrder(), &(shared_images[i*camera->ImageSize()])); - image_buffer[i].image->HoldBuffer(true); /* Don't release the internal buffer or replace it with another */ + image_buffer[i] = new Image(width, height, camera->Colours(), camera->SubpixelOrder(), &(shared_images[i*camera->ImageSize()])); + image_buffer[i]->HoldBuffer(true); /* Don't release the internal buffer or replace it with another */ } if (purpose == CAPTURE) { @@ -1096,16 +1094,10 @@ bool Monitor::disconnect() { } #endif // ZM_MEM_MAPPED - if (image_buffer) { - for ( int32_t i = 0; i < image_buffer_count; i++ ) { - // We delete the image because it is an object pointing to space that won't be free'd. - delete image_buffer[i].image; - image_buffer[i].image = nullptr; - // We don't delete the timestamp because it is just a pointer to shared mem. - image_buffer[i].timestamp = nullptr; - } - delete[] image_buffer; - image_buffer = nullptr; + for ( int32_t i = 0; i < image_buffer_count; i++ ) { + // We delete the image because it is an object pointing to space that won't be free'd. + delete image_buffer[i]; + image_buffer[i] = nullptr; } return true; @@ -1177,19 +1169,18 @@ int Monitor::GetImage(int32_t index, int scale) { Image *image; // If we are going to be modifying the snapshot before writing, then we need to copy it if ( ( scale != ZM_SCALE_BASE ) || ( !config.timestamp_on_capture ) ) { - ZMPacket *snap = &image_buffer[index]; - alarm_image.Assign(*snap->image); + alarm_image.Assign(*image_buffer[index]); - if ( scale != ZM_SCALE_BASE ) { + if (scale != ZM_SCALE_BASE) { alarm_image.Scale(scale); } if ( !config.timestamp_on_capture ) { - TimestampImage(&alarm_image, snap->timestamp); + TimestampImage(&alarm_image, shared_timestamps[index]); } image = &alarm_image; } else { - image = image_buffer[index].image; + image = image_buffer[index]; } static char filename[PATH_MAX]; @@ -1206,15 +1197,15 @@ ZMPacket *Monitor::getSnapshot(int index) const { if ( (index < 0) || (index > image_buffer_count) ) { index = shared_data->last_write_index; } - return &image_buffer[index]; + return new ZMPacket(image_buffer[index], shared_timestamps[index]); return nullptr; } struct timeval Monitor::GetTimestamp(int index) const { ZMPacket *packet = getSnapshot(index); - if ( packet ) - return *packet->timestamp; + if (packet) + return packet->timestamp; static struct timeval null_tv = { 0, 0 }; return null_tv; @@ -1235,58 +1226,6 @@ uint64_t Monitor::GetLastEventId() const { // This function is crap. double Monitor::GetFPS() const { return get_capture_fps(); - // last_write_index is the last capture index. It starts as == image_buffer_count so that the first asignment % image_buffer_count = 0; - int32_t index1 = shared_data->last_write_index; - if ( index1 >= image_buffer_count ) { - // last_write_index only has this value on startup before capturing anything. - return 0.0; - } - Debug(2, "index1(%d)", index1); - ZMPacket *snap1 = &image_buffer[index1]; - if ( !snap1->timestamp->tv_sec ) { - // This should be impossible - Warning("Impossible situation. No timestamp on captured image index was %d, image-buffer_count was (%d)", index1, image_buffer_count); - return 0.0; - } - struct timeval time1 = *snap1->timestamp; - - int32_t fps_image_count = image_buffer_count; - - int32_t index2 = (index1+1)%image_buffer_count; - Debug(2, "index2(%d)", index2); - ZMPacket *snap2 = &image_buffer[index2]; - // the timestamp pointers are initialized on connection, so that's redundant - // tv_sec is probably only zero during the first loop of capturing, so this basically just counts the unused images. - // The problem is that there is no locking, and we set the timestamp before we set last_write_index, - // so there is a small window where the next image can have a timestamp in the future - while ( !snap2->timestamp->tv_sec || tvDiffSec(*snap2->timestamp, *snap1->timestamp) < 0 ) { - if ( index1 == index2 ) { - // All images are uncaptured - return 0.0; - } - index2 = (index2+1)%image_buffer_count; - snap2 = &image_buffer[ index2 ]; - fps_image_count--; - } - struct timeval time2 = *snap2->timestamp; - - double time_diff = tvDiffSec( time2, time1 ); - if ( ! time_diff ) { - Error("No diff between time_diff = %lf (%d:%ld.%ld - %d:%ld.%ld), ibc: %d", - time_diff, index2, time2.tv_sec, time2.tv_usec, index1, time1.tv_sec, time1.tv_usec, image_buffer_count); - return 0.0; - } - double curr_fps = fps_image_count/time_diff; - - if ( curr_fps < 0.0 ) { - Error("Negative FPS %f, time_diff = %lf (%d:%ld.%ld - %d:%ld.%ld), ibc: %d", - curr_fps, time_diff, index2, time2.tv_sec, time2.tv_usec, index1, time1.tv_sec, time1.tv_usec, image_buffer_count); - return 0.0; - } else { - Debug(2, "GetFPS %f, time_diff = %lf (%d:%ld.%ld - %d:%ld.%ld), ibc: %d", - curr_fps, time_diff, index2, time2.tv_sec, time2.tv_usec, index1, time1.tv_sec, time1.tv_usec, image_buffer_count); - } - return curr_fps; } /* I think this returns the # of micro seconds that we should sleep in order to maintain the desired analysis rate */ @@ -1772,7 +1711,7 @@ bool Monitor::Analyse() { // get_analysis_packet will lock the packet and may wait if analysis_it is at the end ZMLockedPacket *packet_lock = packetqueue.get_packet(analysis_it); if (!packet_lock) return false; - ZMPacket *snap = packet_lock->packet_; + std::shared_ptr snap = packet_lock->packet_; // Is it possible for snap->score to be ! -1 ? Not if everything is working correctly if (snap->score != -1) { @@ -1908,7 +1847,7 @@ bool Monitor::Analyse() { } } // end if decoding enabled - struct timeval *timestamp = snap->timestamp; + struct timeval *timestamp = &snap->timestamp; if (Active() and (function == MODECT or function == MOCORD)) { Debug(3, "signal and active and modect"); @@ -2004,7 +1943,7 @@ bool Monitor::Analyse() { // This gets a lock on the starting packet ZMLockedPacket *starting_packet_lock = nullptr; - ZMPacket *starting_packet = nullptr; + std::shared_ptr starting_packet = nullptr; if (*start_it != snap_it) { starting_packet_lock = packetqueue.get_packet(start_it); if (!starting_packet_lock) { @@ -2017,7 +1956,7 @@ bool Monitor::Analyse() { starting_packet = snap; } - event = new Event(this, *(starting_packet->timestamp), "Continuous", noteSetMap); + event = new Event(this, starting_packet->timestamp, "Continuous", noteSetMap); // Write out starting packets, do not modify packetqueue it will garbage collect itself while (starting_packet and ((*start_it) != snap_it)) { event->AddPacket(starting_packet); @@ -2106,7 +2045,7 @@ bool Monitor::Analyse() { (pre_event_count > alarm_frame_count ? pre_event_count : alarm_frame_count) ); ZMLockedPacket *starting_packet_lock = nullptr; - ZMPacket *starting_packet = nullptr; + std::shared_ptr starting_packet = nullptr; if (*start_it != snap_it) { starting_packet_lock = packetqueue.get_packet(start_it); if (!starting_packet_lock) return false; @@ -2115,7 +2054,7 @@ bool Monitor::Analyse() { starting_packet = snap; } - event = new Event(this, *(starting_packet->timestamp), cause, noteSetMap); + event = new Event(this, starting_packet->timestamp, cause, noteSetMap); shared_data->last_event_id = event->Id(); snprintf(video_store_data->event_file, sizeof(video_store_data->event_file), "%s", event->getEventFile()); video_store_data->recording = event->StartTime(); @@ -2522,13 +2461,17 @@ std::vector> Monitor::LoadFfmpegMonitors(const char *fi int Monitor::Capture() { unsigned int index = image_count % image_buffer_count; - ZMPacket *packet = new ZMPacket(); - packet->timestamp = new struct timeval; + Debug(1, "Packeet"); + std::shared_ptr packet = std::make_shared(); + //= new ZMPacket(); + //packet->timestamp = new struct timeval; packet->image_index = image_count; - gettimeofday(packet->timestamp, nullptr); - shared_data->zmc_heartbeat_time = packet->timestamp->tv_sec; - - int captureResult = camera->Capture(*packet); + Debug(1, "Packeet"); + gettimeofday(&(packet->timestamp), nullptr); + Debug(1, "Packeet"); + shared_data->zmc_heartbeat_time = packet->timestamp.tv_sec; + Debug(1, "Capturing"); + int captureResult = camera->Capture(packet); Debug(4, "Back from capture result=%d image count %d", captureResult, image_count); if (captureResult < 0) { @@ -2543,24 +2486,24 @@ int Monitor::Capture() { capture_image->Fill(signalcolor); shared_data->signal = false; shared_data->last_write_index = index; - shared_data->last_write_time = image_buffer[index].timestamp->tv_sec; - image_buffer[index].image->Assign(*capture_image); - *(image_buffer[index].timestamp) = *(packet->timestamp); + shared_data->last_write_time = shared_timestamps[index].tv_sec; + image_buffer[index]->Assign(*capture_image); + shared_timestamps[index] = packet->timestamp; delete capture_image; image_count++; - delete packet; + //delete packet; // What about timestamping it? // Don't want to do analysis on it, but we won't due to signal return -1; - } else if ( captureResult > 0 ) { + } else if (captureResult > 0) { shared_data->signal = true; // Assume if getting packets that we are getting something useful. CheckSignalPoints can correct this later. // If we captured, let's assume signal, Decode will detect further if (!decoding_enabled) { shared_data->last_write_index = index; - shared_data->last_write_time = packet->timestamp->tv_sec; + shared_data->last_write_time = packet->timestamp.tv_sec; } Debug(2, "Have packet stream_index:%d ?= videostream_id: %d q.vpktcount %d event? %d image_count %d", - packet->packet.stream_index, video_stream_id, packetqueue.packet_count(video_stream_id), ( event ? 1 : 0 ), image_count ); + packet->packet.stream_index, video_stream_id, packetqueue.packet_count(video_stream_id), ( event ? 1 : 0 ), image_count); if (packet->codec_type == AVMEDIA_TYPE_VIDEO) { packet->packet.stream_index = video_stream_id; // Convert to packetQueue's index @@ -2590,14 +2533,14 @@ int Monitor::Capture() { packetqueue.queuePacket(packet); } else { Debug(4, "Not Queueing audio packet"); - delete packet; + //delete packet; } // Don't update last_write_index because that is used for live streaming //shared_data->last_write_time = image_buffer[index].timestamp->tv_sec; return 1; } else { Debug(1, "Unknown codec type %d", packet->codec_type); - delete packet; + //delete packet; return 1; } // end if audio @@ -2605,12 +2548,12 @@ int Monitor::Capture() { // Will only be queued if there are iterators allocated in the queue. if ( !packetqueue.queuePacket(packet) ) { - delete packet; + //delete packet; } UpdateCaptureFPS(); } else { // result == 0 // Question is, do we update last_write_index etc? - delete packet; + //delete packet; return 0; } // end if result @@ -2635,7 +2578,7 @@ int Monitor::Capture() { bool Monitor::Decode() { ZMLockedPacket *packet_lock = packetqueue.get_packet(decoder_it); if (!packet_lock) return false; - ZMPacket *packet = packet_lock->packet_; + std::shared_ptr packet = packet_lock->packet_; packetqueue.increment_it(decoder_it); if (packet->codec_type != AVMEDIA_TYPE_VIDEO) { Debug(4, "Not video"); @@ -2758,25 +2701,25 @@ bool Monitor::Decode() { TimestampImage(packet->image, packet->timestamp); } - image_buffer[index].image->Assign(*(packet->image)); - *(image_buffer[index].timestamp) = *(packet->timestamp); + image_buffer[index]->Assign(*(packet->image)); + shared_timestamps[index] = packet->timestamp; } // end if have image packet->decoded = true; shared_data->signal = ( capture_image and signal_check_points ) ? CheckSignal(capture_image) : true; shared_data->last_write_index = index; - shared_data->last_write_time = packet->timestamp->tv_sec; + shared_data->last_write_time = packet->timestamp.tv_sec; packetqueue.unlock(packet_lock); return true; } // end bool Monitor::Decode() -void Monitor::TimestampImage(Image *ts_image, const struct timeval *ts_time) const { +void Monitor::TimestampImage(Image *ts_image, const timeval &ts_time) const { if ( !label_format[0] ) return; // Expand the strftime macros first char label_time_text[256]; tm ts_tm = {}; - strftime(label_time_text, sizeof(label_time_text), label_format.c_str(), localtime_r(&ts_time->tv_sec, &ts_tm)); + strftime(label_time_text, sizeof(label_time_text), label_format.c_str(), localtime_r(&ts_time.tv_sec, &ts_tm)); char label_text[1024]; const char *s_ptr = label_time_text; char *d_ptr = label_text; @@ -2793,7 +2736,7 @@ void Monitor::TimestampImage(Image *ts_image, const struct timeval *ts_time) con found_macro = true; break; case 'f' : - d_ptr += snprintf(d_ptr, sizeof(label_text)-(d_ptr-label_text), "%02ld", ts_time->tv_usec/10000); + d_ptr += snprintf(d_ptr, sizeof(label_text)-(d_ptr-label_text), "%02ld", ts_time.tv_usec/10000); found_macro = true; break; } @@ -3175,21 +3118,21 @@ void Monitor::get_ref_image() { Debug(1, "Waiting for capture daemon lastwriteindex(%d) lastwritetime(%" PRIi64 ")", shared_data->last_write_index, static_cast(shared_data->last_write_time)); - if ( snap_lock and ! snap_lock->packet_->image ) { + if (snap_lock and ! snap_lock->packet_->image) { delete snap_lock; // can't analyse it anyways, incremement packetqueue.increment_it(analysis_it); } //usleep(10000); } - if ( zm_terminate ) + if (zm_terminate) return; - ZMPacket *snap = snap_lock->packet_; + std::shared_ptr snap = snap_lock->packet_; Debug(1, "get_ref_image: packet.stream %d ?= video_stream %d, packet image id %d packet image %p", snap->packet.stream_index, video_stream_id, snap->image_index, snap->image ); // Might not have been decoded yet FIXME - if ( snap->image ) { + if (snap->image) { ref_image.Assign(width, height, camera->Colours(), camera->SubpixelOrder(), snap->image->Buffer(), camera->ImageSize()); Debug(2, "Have ref image about to unlock"); @@ -3197,7 +3140,7 @@ void Monitor::get_ref_image() { Debug(2, "Have no ref image about to unlock"); } delete snap_lock; -} +} // get_ref_image std::vector Monitor::Groups() { // At the moment, only load groups once. diff --git a/src/zm_monitor.h b/src/zm_monitor.h index 0efc8a130..328c4e941 100644 --- a/src/zm_monitor.h +++ b/src/zm_monitor.h @@ -376,8 +376,7 @@ protected: struct timeval *shared_timestamps; unsigned char *shared_images; - ZMPacket *image_buffer; - ZMPacket next_buffer; /* Used by four field deinterlacing */ + std::vector image_buffer; int video_stream_id; // will be filled in PrimeCapture int audio_stream_id; // will be filled in PrimeCapture @@ -583,7 +582,7 @@ public: bool Analyse(); bool Decode(); void DumpImage( Image *dump_image ) const; - void TimestampImage( Image *ts_image, const struct timeval *ts_time ) const; + void TimestampImage(Image *ts_image, const timeval &ts_time) const; void closeEvent(); void Reload(); diff --git a/src/zm_monitorstream.cpp b/src/zm_monitorstream.cpp index 63f85d71b..0df93f963 100644 --- a/src/zm_monitorstream.cpp +++ b/src/zm_monitorstream.cpp @@ -320,13 +320,13 @@ void MonitorStream::processCommand(const CmdMsg *msg) { //updateFrameRate(monitor->GetFPS()); } // end void MonitorStream::processCommand(const CmdMsg *msg) -bool MonitorStream::sendFrame(const char *filepath, struct timeval *timestamp) { +bool MonitorStream::sendFrame(const char *filepath, const timeval ×tamp) { bool send_raw = ((scale>=ZM_SCALE_BASE)&&(zoom==ZM_SCALE_BASE)); if ( ( type != STREAM_JPEG ) || - ( (!config.timestamp_on_capture) && timestamp ) + (!config.timestamp_on_capture) ) send_raw = false; @@ -352,7 +352,7 @@ bool MonitorStream::sendFrame(const char *filepath, struct timeval *timestamp) { if ( (0 > fprintf(stdout, "Content-Length: %d\r\nX-Timestamp: %d.%06d\r\n\r\n", - img_buffer_size, (int)timestamp->tv_sec, (int)timestamp->tv_usec)) + img_buffer_size, (int)timestamp.tv_sec, (int)timestamp.tv_usec)) || (fwrite(img_buffer, img_buffer_size, 1, stdout) != 1) ) { @@ -379,9 +379,9 @@ bool MonitorStream::sendFrame(const char *filepath, struct timeval *timestamp) { return false; } // end bool MonitorStream::sendFrame(const char *filepath, struct timeval *timestamp) -bool MonitorStream::sendFrame(Image *image, struct timeval *timestamp) { +bool MonitorStream::sendFrame(Image *image, const timeval ×tamp) { Image *send_image = prepareImage(image); - if ( !config.timestamp_on_capture && timestamp ) + if (!config.timestamp_on_capture) monitor->TimestampImage(send_image, timestamp); fputs("--" BOUNDARY "\r\n", stdout); @@ -395,8 +395,8 @@ bool MonitorStream::sendFrame(Image *image, struct timeval *timestamp) { static struct timeval base_time; struct DeltaTimeval delta_time; if ( !frame_count ) - base_time = *timestamp; - DELTA_TIMEVAL(delta_time, *timestamp, base_time, DT_PREC_3); + base_time = timestamp; + DELTA_TIMEVAL(delta_time, timestamp, base_time, DT_PREC_3); /* double pts = */ vid_stream->EncodeFrame(send_image->Buffer(), send_image->Size(), config.mpeg_timed_frames, delta_time.delta); } else #endif // HAVE_LIBAVCODEC @@ -437,7 +437,7 @@ bool MonitorStream::sendFrame(Image *image, struct timeval *timestamp) { } if ( ( 0 > fprintf(stdout, "Content-Length: %d\r\nX-Timestamp: %d.%06d\r\n\r\n", - img_buffer_size, (int)timestamp->tv_sec, (int)timestamp->tv_usec) ) + img_buffer_size, (int)timestamp.tv_sec, (int)timestamp.tv_usec) ) || (fwrite(img_buffer, img_buffer_size, 1, stdout) != 1) ) { @@ -462,7 +462,7 @@ bool MonitorStream::sendFrame(Image *image, struct timeval *timestamp) { } // Not mpeg last_frame_sent = TV_2_FLOAT(now); return true; -} // end bool MonitorStream::sendFrame( Image *image, struct timeval *timestamp ) +} // end bool MonitorStream::sendFrame( Image *image, const timeval ×tamp ) void MonitorStream::runStream() { if (type == STREAM_SINGLE) { @@ -595,8 +595,8 @@ void MonitorStream::runStream() { if ( !was_paused ) { int index = monitor->shared_data->last_write_index % monitor->image_buffer_count; Debug(1, "Saving paused image from index %d",index); - paused_image = new Image(*monitor->image_buffer[index].image); - paused_timestamp = *(monitor->image_buffer[index].timestamp); + paused_image = new Image(*monitor->image_buffer[index]); + paused_timestamp = monitor->shared_timestamps[index]; } } else if ( paused_image ) { Debug(1, "Clearing paused_image"); @@ -635,7 +635,7 @@ void MonitorStream::runStream() { if ( temp_index%frame_mod == 0 ) { Debug(2, "Sending delayed frame %d", temp_index); // Send the next frame - if ( ! sendFrame(temp_image_buffer[temp_index].file_name, &temp_image_buffer[temp_index].timestamp) ) { + if (!sendFrame(temp_image_buffer[temp_index].file_name, temp_image_buffer[temp_index].timestamp)) { zm_terminate = true; } memcpy(&last_frame_timestamp, &(swap_image->timestamp), sizeof(last_frame_timestamp)); @@ -652,7 +652,7 @@ void MonitorStream::runStream() { // Send the next frame if ( !sendFrame( temp_image_buffer[temp_read_index].file_name, - &temp_image_buffer[temp_read_index].timestamp + temp_image_buffer[temp_read_index].timestamp ) ) { zm_terminate = true; } @@ -672,7 +672,7 @@ void MonitorStream::runStream() { // Send keepalive Debug(2, "Sending keepalive frame %d", temp_index); // Send the next frame - if ( !sendFrame(temp_image_buffer[temp_index].file_name, &temp_image_buffer[temp_index].timestamp) ) { + if ( !sendFrame(temp_image_buffer[temp_index].file_name, temp_image_buffer[temp_index].timestamp) ) { zm_terminate = true; } // frame_sent = true; @@ -701,21 +701,21 @@ void MonitorStream::runStream() { index, frame_mod, frame_count, paused, delayed); // Send the next frame // - ZMPacket *snap = &monitor->image_buffer[index]; + // Perhaps we should use NOW instead. + last_frame_timestamp = monitor->shared_timestamps[index]; + Image *image = monitor->image_buffer[index]; - if ( !sendFrame(snap->image, snap->timestamp) ) { + if ( !sendFrame(image, last_frame_timestamp) ) { Debug(2, "sendFrame failed, quiting."); zm_terminate = true; break; } - // Perhaps we should use NOW instead. - last_frame_timestamp = *(snap->timestamp); //frame_sent = true; // if ( frame_count == 0 ) { // Chrome will not display the first frame until it receives another. // Firefox is fine. So just send the first frame twice. - if ( !sendFrame(snap->image, snap->timestamp) ) { + if ( !sendFrame(image, last_frame_timestamp) ) { Debug(2, "sendFrame failed, quiting."); zm_terminate = true; break; @@ -730,9 +730,9 @@ void MonitorStream::runStream() { } if ( last_zoom != zoom ) { Debug(2, "Sending 2 frames because change in zoom %d ?= %d", last_zoom, zoom); - if ( !sendFrame(paused_image, &paused_timestamp) ) + if (!sendFrame(paused_image, paused_timestamp)) zm_terminate = true; - if ( !sendFrame(paused_image, &paused_timestamp) ) + if (!sendFrame(paused_image, paused_timestamp)) zm_terminate = true; } else { double actual_delta_time = TV_2_FLOAT(now) - last_frame_sent; @@ -742,7 +742,7 @@ void MonitorStream::runStream() { Debug(2, "Sending keepalive frame because delta time %.2f > 5", actual_delta_time); // Send the next frame - if ( !sendFrame(paused_image, &paused_timestamp) ) + if (!sendFrame(paused_image, paused_timestamp)) zm_terminate = true; } else { Debug(2, "Would have sent keepalive frame, but had no paused_image"); @@ -767,7 +767,7 @@ void MonitorStream::runStream() { temp_image_buffer[temp_index].valid = true; } temp_image_buffer[temp_index].timestamp = monitor->shared_timestamps[index]; - monitor->image_buffer[index].image->WriteJpeg( + monitor->image_buffer[index]->WriteJpeg( temp_image_buffer[temp_index].file_name, config.jpeg_file_quality ); @@ -865,8 +865,7 @@ void MonitorStream::SingleImage(int scale) { } int index = monitor->shared_data->last_write_index % monitor->image_buffer_count; Debug(1, "write index: %d %d", monitor->shared_data->last_write_index, index); - ZMPacket *snap = &(monitor->image_buffer[index]); - Image *snap_image = snap->image; + Image *snap_image = monitor->image_buffer[index]; if ( scale != ZM_SCALE_BASE ) { scaled_image.Assign(*snap_image); @@ -874,7 +873,7 @@ void MonitorStream::SingleImage(int scale) { snap_image = &scaled_image; } if ( !config.timestamp_on_capture ) { - monitor->TimestampImage(snap_image, snap->timestamp); + monitor->TimestampImage(snap_image, monitor->shared_timestamps[index]); } snap_image->EncodeJpeg(img_buffer, &img_buffer_size); diff --git a/src/zm_monitorstream.h b/src/zm_monitorstream.h index 0c1f92777..5730bfc5a 100644 --- a/src/zm_monitorstream.h +++ b/src/zm_monitorstream.h @@ -45,8 +45,8 @@ class MonitorStream : public StreamBase { protected: bool checkSwapPath(const char *path, bool create_path); - bool sendFrame(const char *filepath, struct timeval *timestamp); - bool sendFrame(Image *image, struct timeval *timestamp); + bool sendFrame(const char *filepath, const timeval ×tamp); + bool sendFrame(Image *image, const timeval ×tamp); void processCommand(const CmdMsg *msg) override; void SingleImage(int scale=100); void SingleImageRaw(int scale=100); diff --git a/src/zm_packet.cpp b/src/zm_packet.cpp index 7aef2ddca..c4b39fb87 100644 --- a/src/zm_packet.cpp +++ b/src/zm_packet.cpp @@ -31,7 +31,7 @@ ZMPacket::ZMPacket() : stream(nullptr), in_frame(nullptr), out_frame(nullptr), - timestamp(nullptr), + timestamp({}), buffer(nullptr), image(nullptr), analysis_image(nullptr), @@ -41,6 +41,28 @@ ZMPacket::ZMPacket() : codec_imgsize(0), pts(0), decoded(0) +{ + Debug(1, "ZMPacket"); + av_init_packet(&packet); + packet.size = 0; // So we can detect whether it has been filled. + Debug(1, "ZMPacket"); +} + +ZMPacket::ZMPacket(Image *i, const timeval &tv) : + keyframe(0), + stream(nullptr), + in_frame(nullptr), + out_frame(nullptr), + timestamp(tv), + buffer(nullptr), + image(i), + analysis_image(nullptr), + score(-1), + codec_type(AVMEDIA_TYPE_UNKNOWN), + image_index(-1), + codec_imgsize(0), + pts(0), + decoded(0) { av_init_packet(&packet); packet.size = 0; // So we can detect whether it has been filled. @@ -51,7 +73,7 @@ ZMPacket::ZMPacket(ZMPacket &p) : stream(nullptr), in_frame(nullptr), out_frame(nullptr), - timestamp(nullptr), + timestamp(p.timestamp), buffer(nullptr), image(nullptr), analysis_image(nullptr), @@ -68,18 +90,15 @@ ZMPacket::ZMPacket(ZMPacket &p) : if ( zm_av_packet_ref(&packet, &p.packet) < 0 ) { Error("error refing packet"); } - timestamp = new struct timeval; - *timestamp = *p.timestamp; } ZMPacket::~ZMPacket() { zm_av_packet_unref(&packet); - if ( in_frame ) av_frame_free(&in_frame); - if ( out_frame ) av_frame_free(&out_frame); - if ( buffer ) av_freep(&buffer); - if ( analysis_image ) delete analysis_image; - if ( image ) delete image; - if ( timestamp ) delete timestamp; + if (in_frame) av_frame_free(&in_frame); + if (out_frame) av_frame_free(&out_frame); + if (buffer) av_freep(&buffer); + if (analysis_image) delete analysis_image; + if (image) delete image; } /* returns < 0 on error, 0 on not ready, int bytes consumed on success @@ -227,7 +246,7 @@ AVPacket *ZMPacket::set_packet(AVPacket *p) { Error("error refing packet"); } //ZM_DUMP_PACKET(packet, "zmpacket:"); - gettimeofday(timestamp, nullptr); + gettimeofday(×tamp, nullptr); keyframe = p->flags & AV_PKT_FLAG_KEY; return &packet; } diff --git a/src/zm_packet.h b/src/zm_packet.h index a7deca325..83f74e6b9 100644 --- a/src/zm_packet.h +++ b/src/zm_packet.h @@ -41,6 +41,7 @@ class ZMPacket { public: std::mutex mutex_; + // The condition has to be in the packet because it is shared between locks std::condition_variable condition_; int keyframe; @@ -48,7 +49,7 @@ class ZMPacket { AVPacket packet; // Input packet, undecoded AVFrame *in_frame; // Input image, decoded Theoretically only filled if needed. AVFrame *out_frame; // output image, Only filled if needed. - struct timeval *timestamp; + timeval timestamp; uint8_t *buffer; // buffer used in image Image *image; Image *analysis_image; @@ -69,7 +70,7 @@ class ZMPacket { int is_keyframe() { return keyframe; }; int decode( AVCodecContext *ctx ); - explicit ZMPacket(Image *image); + explicit ZMPacket(Image *image, const timeval &tv); explicit ZMPacket(ZMPacket &packet); ZMPacket(); ~ZMPacket(); @@ -81,11 +82,11 @@ class ZMPacket { class ZMLockedPacket { public: - ZMPacket *packet_; + std::shared_ptr packet_; std::unique_lock lck_; bool locked; - explicit ZMLockedPacket(ZMPacket *p) : + explicit ZMLockedPacket(std::shared_ptr p) : packet_(p), lck_(packet_->mutex_, std::defer_lock), locked(false) { diff --git a/src/zm_packetqueue.cpp b/src/zm_packetqueue.cpp index a1f149bb4..32b944d2b 100644 --- a/src/zm_packetqueue.cpp +++ b/src/zm_packetqueue.cpp @@ -75,8 +75,7 @@ PacketQueue::~PacketQueue() { * Thus it will ensure that the same packet never gets queued twice. */ -bool PacketQueue::queuePacket(ZMPacket* add_packet) { - Debug(4, "packetqueue queuepacket %p %d", add_packet, add_packet->image_index); +bool PacketQueue::queuePacket(std::shared_ptr add_packet) { if (iterators.empty()) { Debug(4, "No iterators so no one needs us to queue packets."); return false; @@ -97,7 +96,7 @@ bool PacketQueue::queuePacket(ZMPacket* add_packet) { if (add_packet->keyframe) { // Have a new keyframe, so delete everything while ((*pktQueue.begin() != add_packet) and (packet_counts[video_stream_id] > max_video_packet_count)) { - ZMPacket *zm_packet = *pktQueue.begin(); + std::shared_ptr zm_packet = *pktQueue.begin(); ZMLockedPacket *lp = new ZMLockedPacket(zm_packet); if (!lp->trylock()) { Debug(1, "Found locked packet when trying to free up video packets. Can't continue"); @@ -129,7 +128,6 @@ bool PacketQueue::queuePacket(ZMPacket* add_packet) { packet_counts[video_stream_id], max_video_packet_count, pktQueue.size()); - delete zm_packet; } // end while } } // end if too many video packets @@ -166,7 +164,7 @@ bool PacketQueue::queuePacket(ZMPacket* add_packet) { return true; } // end bool PacketQueue::queuePacket(ZMPacket* zm_packet) -void PacketQueue::clearPackets(ZMPacket *add_packet) { +void PacketQueue::clearPackets(const std::shared_ptr &add_packet) { // Only do queueCleaning if we are adding a video keyframe, so that we guarantee that there is one. // No good. Have to satisfy two conditions: // 1. packetqueue starts with a video keyframe @@ -211,7 +209,7 @@ void PacketQueue::clearPackets(ZMPacket *add_packet) { if (!keep_keyframes) { // If not doing passthrough, we don't care about starting with a keyframe so logic is simpler while ((*pktQueue.begin() != add_packet) and (packet_counts[video_stream_id] > pre_event_video_packet_count + tail_count)) { - ZMPacket *zm_packet = *pktQueue.begin(); + std::shared_ptr zm_packet = *pktQueue.begin(); ZMLockedPacket *lp = new ZMLockedPacket(zm_packet); if (!lp->trylock()) break; delete lp; @@ -231,7 +229,7 @@ void PacketQueue::clearPackets(ZMPacket *add_packet) { packet_counts[video_stream_id], pre_event_video_packet_count, pktQueue.size()); - delete zm_packet; + //delete zm_packet; } // end while return; } @@ -241,7 +239,11 @@ void PacketQueue::clearPackets(ZMPacket *add_packet) { int video_packets_to_delete = 0; // This is a count of how many packets we will delete so we know when to stop looking // First packet is special because we know it is a video keyframe and only need to check for lock - ZMPacket *zm_packet = *it; + std::shared_ptr zm_packet = *it; + if (zm_packet == add_packet) { + return; + } + Debug(1, "trying lock on first packet"); ZMLockedPacket *lp = new ZMLockedPacket(zm_packet); if (lp->trylock()) { @@ -288,10 +290,10 @@ void PacketQueue::clearPackets(ZMPacket *add_packet) { ( *it == add_packet ), ( next_front == pktQueue.begin() ) ); - if ( next_front != pktQueue.begin() ) { - while ( pktQueue.begin() != next_front ) { - ZMPacket *zm_packet = *pktQueue.begin(); - if ( !zm_packet ) { + if (next_front != pktQueue.begin()) { + while (pktQueue.begin() != next_front) { + std::shared_ptr zm_packet = *pktQueue.begin(); + if (!zm_packet) { Error("NULL zm_packet in queue"); continue; } @@ -306,7 +308,7 @@ void PacketQueue::clearPackets(ZMPacket *add_packet) { pktQueue.size()); pktQueue.pop_front(); packet_counts[zm_packet->packet.stream_index] -= 1; - delete zm_packet; + //delete zm_packet; } } // end if have at least max_video_packet_count video packets remaining // We signal on every packet because someday we may analyze sound @@ -314,116 +316,6 @@ void PacketQueue::clearPackets(ZMPacket *add_packet) { return; } // end voidPacketQueue::clearPackets(ZMPacket* zm_packet) -ZMLockedPacket* PacketQueue::popPacket( ) { - Debug(4, "pktQueue size %zu", pktQueue.size()); - if ( pktQueue.empty() ) { - return nullptr; - } - Debug(4, "poPacket Mutex locking"); - std::unique_lock lck(mutex); - - ZMPacket *zm_packet = pktQueue.front(); - for ( - std::list::iterator iterators_it = iterators.begin(); - iterators_it != iterators.end(); - ++iterators_it - ) { - packetqueue_iterator *iterator_it = *iterators_it; - // Have to check each iterator and make sure it doesn't point to the packet we are about to delete - if ( *(*iterator_it) == zm_packet ) { - Debug(4, "Bumping it because it is at the front that we are deleting"); - ++(*iterators_it); - } - } // end foreach iterator - - ZMLockedPacket *lp = new ZMLockedPacket (zm_packet); - lp->lock(); - - pktQueue.pop_front(); - packet_counts[zm_packet->packet.stream_index] -= 1; - - return lp; -} // popPacket - - -/* Keeps frames_to_keep frames of the provided stream, which theoretically is the video stream - * Basically it starts at the end, moving backwards until it finds the minimum video frame. - * Then it should probably move forward to find a keyframe. The first video frame must always be a keyframe. - * So really frames_to_keep is a maximum which isn't so awesome.. maybe we should go back farther to find the keyframe in which case - * frames_to_keep in a minimum - */ - -unsigned int PacketQueue::clear(unsigned int frames_to_keep, int stream_id) { - Debug(3, "Clearing all but %d frames, queue has %zu", frames_to_keep, pktQueue.size()); - - if ( pktQueue.empty() ) { - return 0; - } - - // If size is <= frames_to_keep since it could contain audio, we can't possibly do anything - if ( pktQueue.size() <= frames_to_keep ) { - return 0; - } - Debug(5, "Locking in clear"); - std::unique_lock lck(mutex); - - packetqueue_iterator it = pktQueue.end()--; // point to last element instead of end - ZMPacket *zm_packet = nullptr; - - while ( (it != pktQueue.begin()) and frames_to_keep ) { - zm_packet = *it; - AVPacket *av_packet = &(zm_packet->packet); - - Debug(3, "Looking at packet with stream index (%d) with keyframe(%d), Image_index(%d) frames_to_keep is (%d)", - av_packet->stream_index, zm_packet->keyframe, zm_packet->image_index, frames_to_keep ); - - // Want frames_to_keep video keyframes. Otherwise, we may not have enough - if ( av_packet->stream_index == stream_id ) { - frames_to_keep --; - } - it --; - } - - // Either at beginning or frames_to_keep == 0 - - if ( it == pktQueue.begin() ) { - if ( frames_to_keep ) { - Warning("Couldn't remove any packets, needed %d", frames_to_keep); - } - mutex.unlock(); - return 0; - } - - int delete_count = 0; - - // Else not at beginning, are pointing at packet before the last video packet - while ( pktQueue.begin() != it ) { - Debug(4, "Deleting a packet from the front, count is (%d), queue size is %zu", - delete_count, pktQueue.size()); - zm_packet = pktQueue.front(); - for ( - std::list::iterator iterators_it = iterators.begin(); - iterators_it != iterators.end(); - ++iterators_it - ) { - packetqueue_iterator *iterator_it = *iterators_it; - // Have to check each iterator and make sure it doesn't point to the packet we are about to delete - if ( *(*iterator_it) == zm_packet ) { - Debug(4, "Bumping it because it is at the front that we are deleting"); - ++(*iterators_it); - } - } // end foreach iterator - packet_counts[zm_packet->packet.stream_index] --; - pktQueue.pop_front(); - //if ( zm_packet->image_index == -1 ) - delete zm_packet; - - delete_count += 1; - } // while our iterator is not the first packet - Debug(3, "Deleted %d packets, %zu remaining", delete_count, pktQueue.size()); - return delete_count; -} // end unsigned int PacketQueue::clear( unsigned int frames_to_keep, int stream_id ) - void PacketQueue::clear() { deleting = true; condition.notify_all(); @@ -431,13 +323,13 @@ void PacketQueue::clear() { std::unique_lock lck(mutex); while (!pktQueue.empty()) { - ZMPacket *packet = pktQueue.front(); + std::shared_ptr packet = pktQueue.front(); // Someone might have this packet, but not for very long and since we have locked the queue they won't be able to get another one ZMLockedPacket *lp = new ZMLockedPacket(packet); lp->lock(); pktQueue.pop_front(); delete lp; - delete packet; + //delete packet; } for ( @@ -449,119 +341,32 @@ void PacketQueue::clear() { *iterator_it = pktQueue.begin(); } // end foreach iterator - if ( packet_counts ) delete[] packet_counts; + if (packet_counts) delete[] packet_counts; packet_counts = nullptr; max_stream_id = -1; condition.notify_all(); } -// clear queue keeping only specified duration of video -- return number of pkts removed -unsigned int PacketQueue::clear(struct timeval *duration, int streamId) { - - if ( pktQueue.empty() ) { - return 0; - } - Debug(4, "Locking in clear"); - std::unique_lock lck(mutex); - - struct timeval keep_from; - std::list::reverse_iterator it = pktQueue.rbegin(); - - struct timeval *t = (*it)->timestamp; - timersub(t, duration, &keep_from); - ++it; - - Debug(3, "Looking for frame before queue keep time with stream id (%d), queue has %zu packets", - streamId, pktQueue.size()); - for ( ; it != pktQueue.rend(); ++it) { - ZMPacket *zm_packet = *it; - AVPacket *av_packet = &(zm_packet->packet); - if ( - (av_packet->stream_index == streamId) - and - timercmp(zm_packet->timestamp, &keep_from, <=) - ) { - Debug(3, "Found frame before keep time with stream index %d at %" PRIi64 ".%" PRIi64, - av_packet->stream_index, - static_cast(zm_packet->timestamp->tv_sec), - static_cast(zm_packet->timestamp->tv_usec)); - break; - } - } - - if ( it == pktQueue.rend() ) { - Debug(1, "Didn't find a frame before queue preserve time. keeping all"); - mutex.unlock(); - return 0; - } - - Debug(3, "Looking for keyframe"); - for ( ; it != pktQueue.rend(); ++it) { - ZMPacket *zm_packet = *it; - AVPacket *av_packet = &(zm_packet->packet); - if ( - (av_packet->flags & AV_PKT_FLAG_KEY) - and - (av_packet->stream_index == streamId) - ) { - Debug(3, "Found keyframe before start with stream index %d at %" PRIi64 ".%" PRIi64, - av_packet->stream_index, - static_cast(zm_packet->timestamp->tv_sec), - static_cast(zm_packet->timestamp->tv_usec)); - break; - } - } - if ( it == pktQueue.rend() ) { - Debug(1, "Didn't find a keyframe before event starttime. keeping all" ); - return 0; - } - - unsigned int deleted_frames = 0; - ZMPacket *zm_packet = nullptr; - while ( distance(it, pktQueue.rend()) > 1 ) { - zm_packet = pktQueue.front(); - for ( - std::list::iterator iterators_it = iterators.begin(); - iterators_it != iterators.end(); - ++iterators_it - ) { - packetqueue_iterator *iterator_it = *iterators_it; - // Have to check each iterator and make sure it doesn't point to the packet we are about to delete - if ( *(*iterator_it) == zm_packet ) { - Debug(4, "Bumping it because it is at the front that we are deleting"); - ++(*iterators_it); - } - } // end foreach iterator - pktQueue.pop_front(); - packet_counts[zm_packet->packet.stream_index] -= 1; - delete zm_packet; - deleted_frames += 1; - } - Debug(3, "Deleted %d frames", deleted_frames); - return deleted_frames; -} - unsigned int PacketQueue::size() { return pktQueue.size(); } int PacketQueue::packet_count(int stream_id) { - if ( stream_id < 0 or stream_id > max_stream_id ) { + if (stream_id < 0 or stream_id > max_stream_id) { Error("Invalid stream_id %d max is %d", stream_id, max_stream_id); return -1; } return packet_counts[stream_id]; } // end int PacketQueue::packet_count(int stream_id) - // Returns a packet. Packet will be locked ZMLockedPacket *PacketQueue::get_packet(packetqueue_iterator *it) { if (deleting or zm_terminate) return nullptr; - Debug(4, "Locking in get_packet using it %p queue end? %d, packet %p", - std::addressof(*it), (*it == pktQueue.end()), *(*it)); + Debug(4, "Locking in get_packet using it %p queue end? %d", + std::addressof(*it), (*it == pktQueue.end())); std::unique_lock lck(mutex); Debug(4, "Have Lock in get_packet"); @@ -582,13 +387,13 @@ ZMLockedPacket *PacketQueue::get_packet(packetqueue_iterator *it) { return nullptr; } - ZMPacket *p = *(*it); + std::shared_ptr p = *(*it); if (!p) { Error("Null p?!"); return nullptr; } - Debug(4, "get_packet using it %p locking index %d, packet %p", - std::addressof(*it), p->image_index, p); + Debug(4, "get_packet using it %p locking index %d", + std::addressof(*it), p->image_index); // Packets are only deleted by packetqueue, so lock must be held. // We shouldn't have to trylock. Someone else might hold the lock but not for long @@ -655,7 +460,7 @@ packetqueue_iterator *PacketQueue::get_event_start_packet_it( iterators.push_back(it); *it = snapshot_it; - ZMPacket *packet = *(*it); + std::shared_ptr packet = *(*it); ZM_DUMP_PACKET(packet->packet, ""); // Step one count back pre_event_count frames as the minimum // Do not assume that snapshot_it is video @@ -702,9 +507,9 @@ packetqueue_iterator *PacketQueue::get_event_start_packet_it( } // end packetqueue_iterator *PacketQueue::get_event_start_packet_it void PacketQueue::dumpQueue() { - std::list::reverse_iterator it; + std::list>::reverse_iterator it; for ( it = pktQueue.rbegin(); it != pktQueue.rend(); ++ it ) { - ZMPacket *zm_packet = *it; + std::shared_ptr zm_packet = *it; ZM_DUMP_PACKET(zm_packet->packet, ""); } } @@ -732,8 +537,8 @@ packetqueue_iterator * PacketQueue::get_video_it(bool wait) { } } - while ( *it != pktQueue.end() ) { - ZMPacket *zm_packet = *(*it); + while (*it != pktQueue.end()) { + std::shared_ptr zm_packet = *(*it); if (!zm_packet) { Error("Null zmpacket in queue!?"); free_it(it); @@ -764,19 +569,19 @@ void PacketQueue::free_it(packetqueue_iterator *it) { } } -bool PacketQueue::is_there_an_iterator_pointing_to_packet(ZMPacket *zm_packet) { +bool PacketQueue::is_there_an_iterator_pointing_to_packet(const std::shared_ptr &zm_packet) { for ( std::list::iterator iterators_it = iterators.begin(); iterators_it != iterators.end(); ++iterators_it ) { packetqueue_iterator *iterator_it = *iterators_it; - if ( *iterator_it == pktQueue.end() ) { + if (*iterator_it == pktQueue.end()) { continue; } Debug(4, "Checking iterator %p == packet ? %d", std::addressof(*iterator_it), ( *(*iterator_it) == zm_packet )); // Have to check each iterator and make sure it doesn't point to the packet we are about to delete - if ( *(*iterator_it) == zm_packet ) { + if (*(*iterator_it) == zm_packet) { return true; } } // end foreach iterator @@ -786,13 +591,13 @@ bool PacketQueue::is_there_an_iterator_pointing_to_packet(ZMPacket *zm_packet) { void PacketQueue::setMaxVideoPackets(int p) { max_video_packet_count = p; Debug(1, "Setting max_video_packet_count to %d", p); - if ( max_video_packet_count < 0 ) + if (max_video_packet_count < 0) max_video_packet_count = 0 ; } void PacketQueue::setPreEventVideoPackets(int p) { pre_event_video_packet_count = p; Debug(1, "Setting pre_event_video_packet_count to %d", p); - if ( pre_event_video_packet_count < 1 ) + if (pre_event_video_packet_count < 1) pre_event_video_packet_count = 1; // We can simplify a lot of logic in queuePacket if we can assume at least 1 packet in queue } diff --git a/src/zm_packetqueue.h b/src/zm_packetqueue.h index bc9932f24..cc163d2f1 100644 --- a/src/zm_packetqueue.h +++ b/src/zm_packetqueue.h @@ -26,12 +26,12 @@ class ZMPacket; class ZMLockedPacket; -typedef std::list::iterator packetqueue_iterator; +typedef std::list>::iterator packetqueue_iterator; class PacketQueue { public: // For now just to ease development - std::list pktQueue; - std::list::iterator analysis_it; + std::list> pktQueue; + std::list>::iterator analysis_it; int video_stream_id; int max_video_packet_count; // allow a negative value to someday mean unlimited @@ -49,27 +49,21 @@ class PacketQueue { public: PacketQueue(); virtual ~PacketQueue(); - std::list::const_iterator end() const { return pktQueue.end(); } - std::list::const_iterator begin() const { return pktQueue.begin(); } + std::list>::const_iterator end() const { return pktQueue.end(); } + std::list>::const_iterator begin() const { return pktQueue.begin(); } int addStream(); void setMaxVideoPackets(int p); void setPreEventVideoPackets(int p); void setKeepKeyframes(bool k) { keep_keyframes = k; }; - bool queuePacket(ZMPacket* packet); - ZMLockedPacket * popPacket(); - bool popVideoPacket(ZMPacket* packet); - bool popAudioPacket(ZMPacket* packet); - unsigned int clear(unsigned int video_frames_to_keep, int stream_id); - unsigned int clear(struct timeval *duration, int streamid); + bool queuePacket(std::shared_ptr packet); void clear(); void dumpQueue(); unsigned int size(); unsigned int get_packet_count(int stream_id) const { return packet_counts[stream_id]; }; - void clear_unwanted_packets(timeval *recording, int pre_event_count, int mVideoStreamId); - void clearPackets(ZMPacket *); + void clearPackets(const std::shared_ptr &packet); int packet_count(int stream_id); bool increment_it(packetqueue_iterator *it); @@ -83,7 +77,7 @@ class PacketQueue { packetqueue_iterator snapshot_it, unsigned int pre_event_count ); - bool is_there_an_iterator_pointing_to_packet(ZMPacket *zm_packet); + bool is_there_an_iterator_pointing_to_packet(const std::shared_ptr &zm_packet); void unlock(ZMLockedPacket *lp); }; diff --git a/src/zm_remote_camera.h b/src/zm_remote_camera.h index b4d9af3bc..e08975af2 100644 --- a/src/zm_remote_camera.h +++ b/src/zm_remote_camera.h @@ -83,7 +83,7 @@ public: virtual int Disconnect() = 0; virtual int PreCapture() override { return 0; }; virtual int PrimeCapture() override { return 0; }; - virtual int Capture(ZMPacket &p) override = 0; + virtual int Capture(std::shared_ptr &p) override = 0; virtual int PostCapture() override = 0; int Read(int fd, char*buf, int size); }; diff --git a/src/zm_remote_camera_http.cpp b/src/zm_remote_camera_http.cpp index 6eab03fb8..f09db425e 100644 --- a/src/zm_remote_camera_http.cpp +++ b/src/zm_remote_camera_http.cpp @@ -1069,7 +1069,7 @@ int RemoteCameraHttp::PreCapture() { return 1; } // end int RemoteCameraHttp::PreCapture() -int RemoteCameraHttp::Capture(ZMPacket &packet) { +int RemoteCameraHttp::Capture(std::shared_ptr &packet) { int content_length = GetResponse(); if (content_length == 0) { Warning("Unable to capture image, retrying"); @@ -1080,15 +1080,15 @@ int RemoteCameraHttp::Capture(ZMPacket &packet) { return -1; } - if (!packet.image) { + if (!packet->image) { Debug(4, "Allocating image"); - packet.image = new Image(width, height, colours, subpixelorder); + packet->image = new Image(width, height, colours, subpixelorder); } - Image *image = packet.image; - packet.keyframe = 1; - packet.codec_type = AVMEDIA_TYPE_VIDEO; - packet.packet.stream_index = mVideoStreamId; - packet.stream = mVideoStream; + Image *image = packet->image; + packet->keyframe = 1; + packet->codec_type = AVMEDIA_TYPE_VIDEO; + packet->packet.stream_index = mVideoStreamId; + packet->stream = mVideoStream; switch (format) { case JPEG : diff --git a/src/zm_remote_camera_http.h b/src/zm_remote_camera_http.h index dc793459b..794ccba78 100644 --- a/src/zm_remote_camera_http.h +++ b/src/zm_remote_camera_http.h @@ -69,7 +69,7 @@ public: int GetResponse(); int PrimeCapture() override; int PreCapture() override; - int Capture( ZMPacket &p ) override; + int Capture(std::shared_ptr &p) override; int PostCapture() override; int Close() override { Disconnect(); return 0; }; }; diff --git a/src/zm_remote_camera_nvsocket.cpp b/src/zm_remote_camera_nvsocket.cpp index f66d31fcb..92f806eed 100644 --- a/src/zm_remote_camera_nvsocket.cpp +++ b/src/zm_remote_camera_nvsocket.cpp @@ -184,9 +184,9 @@ int RemoteCameraNVSocket::PrimeCapture() { return 0; } -int RemoteCameraNVSocket::Capture( ZMPacket &zm_packet ) { - if ( SendRequest("GetNextImage\n") < 0 ) { - Warning( "Unable to capture image, retrying" ); +int RemoteCameraNVSocket::Capture(std::shared_ptr &zm_packet) { + if (SendRequest("GetNextImage\n") < 0) { + Warning("Unable to capture image, retrying"); return 0; } int bytes_read = Read(sd, buffer, imagesize); @@ -195,17 +195,17 @@ int RemoteCameraNVSocket::Capture( ZMPacket &zm_packet ) { return 0; } uint32_t end; - if ( Read(sd, (char *) &end , sizeof(end)) < 0 ) { + if (Read(sd, (char *) &end , sizeof(end)) < 0) { Warning("Unable to capture image, retrying"); return 0; } - if ( end != 0xFFFFFFFF) { + if (end != 0xFFFFFFFF) { Warning("End Bytes Failed\n"); return 0; } - zm_packet.image->Assign(width, height, colours, subpixelorder, buffer, imagesize); - zm_packet.keyframe = 1; + zm_packet->image->Assign(width, height, colours, subpixelorder, buffer, imagesize); + zm_packet->keyframe = 1; return 1; } diff --git a/src/zm_remote_camera_nvsocket.h b/src/zm_remote_camera_nvsocket.h index 1cd740af2..d3b5ce8e9 100644 --- a/src/zm_remote_camera_nvsocket.h +++ b/src/zm_remote_camera_nvsocket.h @@ -54,7 +54,7 @@ public: int SendRequest(std::string); int GetResponse(); int PrimeCapture() override; - int Capture(ZMPacket &p) override; + int Capture(std::shared_ptr &p) override; int PostCapture() override; int Close() override { return 0; }; }; diff --git a/src/zm_remote_camera_rtsp.cpp b/src/zm_remote_camera_rtsp.cpp index 78c947faa..e35217cc8 100644 --- a/src/zm_remote_camera_rtsp.cpp +++ b/src/zm_remote_camera_rtsp.cpp @@ -218,16 +218,16 @@ int RemoteCameraRtsp::PreCapture() { return 1; } -int RemoteCameraRtsp::Capture(ZMPacket &zm_packet) { +int RemoteCameraRtsp::Capture(std::shared_ptr &zm_packet) { int frameComplete = false; - AVPacket *packet = &zm_packet.packet; - if ( !zm_packet.image ) { + 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); + zm_packet->image = new Image(width, height, colours, subpixelorder); } - while ( !frameComplete ) { + while (!frameComplete) { buffer.clear(); if (!rtspThread || rtspThread->IsStopped()) return -1; @@ -254,7 +254,7 @@ int RemoteCameraRtsp::Capture(ZMPacket &zm_packet) { continue; } else if ( nalType == 5 ) { packet->flags |= AV_PKT_FLAG_KEY; - zm_packet.keyframe = 1; + zm_packet->keyframe = 1; // IDR buffer += lastSps; buffer += lastPps; @@ -275,14 +275,14 @@ int RemoteCameraRtsp::Capture(ZMPacket &zm_packet) { gettimeofday(&now, NULL); packet->pts = packet->dts = now.tv_sec*1000000+now.tv_usec; - int bytes_consumed = zm_packet.decode(mVideoCodecContext); + 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"); + zm_dump_video_frame(zm_packet->in_frame, "remote_rtsp_decode"); if ( ! mVideoStream-> #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) codecpar @@ -293,18 +293,18 @@ int RemoteCameraRtsp::Capture(ZMPacket &zm_packet) { zm_dump_codec(mVideoCodecContext); #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) zm_dump_codecpar(mVideoStream->codecpar); - mVideoStream->codecpar->width = zm_packet.in_frame->width; - mVideoStream->codecpar->height = zm_packet.in_frame->height; + mVideoStream->codecpar->width = zm_packet->in_frame->width; + mVideoStream->codecpar->height = zm_packet->in_frame->height; #else - mVideoStream->codec->width = zm_packet.in_frame->width; - mVideoStream->codec->height = zm_packet.in_frame->height; + mVideoStream->codec->width = zm_packet->in_frame->width; + mVideoStream->codec->height = zm_packet->in_frame->height; #endif #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) zm_dump_codecpar(mVideoStream->codecpar); #endif } - zm_packet.codec_type = mVideoCodecContext->codec_type; - zm_packet.stream = mVideoStream; + 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; diff --git a/src/zm_remote_camera_rtsp.h b/src/zm_remote_camera_rtsp.h index c4734ebee..a815b96b1 100644 --- a/src/zm_remote_camera_rtsp.h +++ b/src/zm_remote_camera_rtsp.h @@ -79,7 +79,7 @@ public: int PrimeCapture() override; int PreCapture() override; - int Capture(ZMPacket &p) override; + int Capture(std::shared_ptr &p) override; int PostCapture() override; int Close() override { return 0; }; diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index 843558de3..1c6855eac 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -1002,17 +1002,17 @@ bool VideoStore::setup_resampler() { #endif } // end bool VideoStore::setup_resampler() -int VideoStore::writePacket(ZMPacket *ipkt) { - if ( ipkt->codec_type == AVMEDIA_TYPE_VIDEO ) { +int VideoStore::writePacket(const std::shared_ptr &ipkt) { + if (ipkt->codec_type == AVMEDIA_TYPE_VIDEO) { return writeVideoFramePacket(ipkt); - } else if ( ipkt->codec_type == AVMEDIA_TYPE_AUDIO ) { + } else if (ipkt->codec_type == AVMEDIA_TYPE_AUDIO) { return writeAudioFramePacket(ipkt); } Error("Unknown stream type in packet (%d)", ipkt->codec_type); return 0; } -int VideoStore::writeVideoFramePacket(ZMPacket *zm_packet) { +int VideoStore::writeVideoFramePacket(const std::shared_ptr &zm_packet) { int ret; frame_count += 1; @@ -1056,8 +1056,8 @@ int VideoStore::writeVideoFramePacket(ZMPacket *zm_packet) { swscale.Convert(zm_packet->in_frame, out_frame); } else { - Error("Have neither in_frame or image in packet %p %d!", - zm_packet, zm_packet->image_index); + Error("Have neither in_frame or image in packet %d!", + zm_packet->image_index); return 0; } // end if has packet or image } else { @@ -1104,13 +1104,13 @@ int VideoStore::writeVideoFramePacket(ZMPacket *zm_packet) { frame->pkt_duration = 0; #endif - int64_t in_pts = zm_packet->timestamp->tv_sec * (uint64_t)1000000 + zm_packet->timestamp->tv_usec; + int64_t in_pts = zm_packet->timestamp.tv_sec * (uint64_t)1000000 + zm_packet->timestamp.tv_usec; if ( !video_first_pts ) { video_first_pts = in_pts; Debug(2, "No video_first_pts, set to (%" PRId64 ") secs(%" PRIi64 ") usecs(%" PRIi64 ")", video_first_pts, - static_cast(zm_packet->timestamp->tv_sec), - static_cast(zm_packet->timestamp->tv_usec)); + static_cast(zm_packet->timestamp.tv_sec), + static_cast(zm_packet->timestamp.tv_usec)); frame->pts = 0; } else { uint64_t useconds = in_pts - video_first_pts; @@ -1121,8 +1121,8 @@ int VideoStore::writeVideoFramePacket(ZMPacket *zm_packet) { frame->pts, video_first_pts, useconds, - static_cast(zm_packet->timestamp->tv_sec), - static_cast(zm_packet->timestamp->tv_usec), + static_cast(zm_packet->timestamp.tv_sec), + static_cast(zm_packet->timestamp.tv_usec), video_out_ctx->time_base.num, video_out_ctx->time_base.den); } @@ -1228,7 +1228,7 @@ int VideoStore::writeVideoFramePacket(ZMPacket *zm_packet) { return 1; } // end int VideoStore::writeVideoFramePacket( AVPacket *ipkt ) -int VideoStore::writeAudioFramePacket(ZMPacket *zm_packet) { +int VideoStore::writeAudioFramePacket(const std::shared_ptr &zm_packet) { AVPacket *ipkt = &zm_packet->packet; int ret; diff --git a/src/zm_videostore.h b/src/zm_videostore.h index 47872db2f..185424dcb 100644 --- a/src/zm_videostore.h +++ b/src/zm_videostore.h @@ -6,6 +6,8 @@ #include "zm_ffmpeg.h" #include "zm_swscale.h" +#include + extern "C" { #ifdef HAVE_LIBSWRESAMPLE #include "libswresample/swresample.h" @@ -119,9 +121,9 @@ class VideoStore { void write_video_packet(AVPacket &pkt); void write_audio_packet(AVPacket &pkt); - int writeVideoFramePacket(ZMPacket *pkt); - int writeAudioFramePacket(ZMPacket *pkt); - int writePacket(ZMPacket *pkt); + int writeVideoFramePacket(const std::shared_ptr &pkt); + int writeAudioFramePacket(const std::shared_ptr &pkt); + int writePacket(const std::shared_ptr &pkt); int write_packets(PacketQueue &queue); void flush_codecs(); }; diff --git a/src/zm_zone.cpp b/src/zm_zone.cpp index 106ab2ce0..7cf2252a8 100644 --- a/src/zm_zone.cpp +++ b/src/zm_zone.cpp @@ -109,7 +109,7 @@ void Zone::Setup( } // end Zone::Setup Zone::~Zone() { - if ( image ) + if (image) delete image; delete pg_image; delete[] ranges; diff --git a/src/zmc.cpp b/src/zmc.cpp index c2ee0a071..0ae934f75 100644 --- a/src/zmc.cpp +++ b/src/zmc.cpp @@ -301,6 +301,7 @@ int main(int argc, char *argv[]) { result = -1; break; } + Debug(1, "Capture:"); if (monitors[i]->Capture() < 0) { Error("Failed to capture image from monitor %d %s (%zu/%zu)", monitors[i]->Id(), monitors[i]->Name(), i + 1, monitors.size()); diff --git a/web/api/app/Plugin/Crud b/web/api/app/Plugin/Crud index 14292374c..0bd63fb46 160000 --- a/web/api/app/Plugin/Crud +++ b/web/api/app/Plugin/Crud @@ -1 +1 @@ -Subproject commit 14292374ccf1328f2d5db20897bd06f99ba4d938 +Subproject commit 0bd63fb464957080ead342db58ca9e01532cf1ef