From 0022dbfb765a5b862253bbc92dab008b0e5a72c9 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Tue, 5 Mar 2019 14:31:39 -0500
Subject: [PATCH 01/40] add a newline to improve readability
---
web/includes/csrf/csrf-magic.php | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/web/includes/csrf/csrf-magic.php b/web/includes/csrf/csrf-magic.php
index 584432ef7..01122fed7 100644
--- a/web/includes/csrf/csrf-magic.php
+++ b/web/includes/csrf/csrf-magic.php
@@ -157,7 +157,8 @@ function csrf_ob_handler($buffer, $flags) {
$input = "";
$buffer = preg_replace('#(
- AutoMove() ) { ?> checked="checked" onclick="updateButtons(this);if(this.checked){$j(this.form.elements['filter[AutoMoveTo]']).css('display','inline');}else{this.form.elements['filter[AutoMoveTo]'].hide();};"/>
- AutoMoveTo(), $filter->AutoMove() ? null : array('style'=>'display:none;' )); ?>
+ AutoMove() ) { ?> checked="checked" data-on-click-this="click_automove"/>
+ AutoMoveTo(), $filter->AutoMove() ? null : array('style'=>'display:none;')); ?>
@@ -406,7 +406,8 @@ if ( ZM_OPT_MESSAGE ) {
-
+
+
Date: Tue, 5 Mar 2019 14:35:02 -0500
Subject: [PATCH 04/40] implement click_automove and submitToMontrageReview for
onclick handlers
---
web/skins/classic/views/js/filter.js | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/web/skins/classic/views/js/filter.js b/web/skins/classic/views/js/filter.js
index 3c2b561d6..bd9095763 100644
--- a/web/skins/classic/views/js/filter.js
+++ b/web/skins/classic/views/js/filter.js
@@ -63,6 +63,15 @@ function updateButtons(element) {
}
}
+function click_automove(element) {
+ updateButtons(this);
+ if ( this.checked ) {
+ $j(this.form.elements['filter[AutoMoveTo]']).css('display','inline');
+ } else {
+ this.form.elements['filter[AutoMoveTo]'].hide();
+ }
+}
+
function checkValue( element ) {
var rows = $j(element).closest('tbody').children();
parseRows(rows);
@@ -83,6 +92,11 @@ function submitToEvents( element ) {
form.action = thisUrl + '?view=events';
history.replaceState(null, null, '?view=filter&' + $j(form).serialize());
}
+function submitToMontageReview( element ) {
+ var form = element.form;
+ form.action = thisUrl + '?view=montagereview';
+ history.replaceState(null, null, '?view=filter&' + $j(form).serialize());
+}
function executeFilter( element ) {
var form = element.form;
From c9985107ee45fac584a4be0e1414396a50e4c75e Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Mon, 1 Apr 2019 13:38:13 -0400
Subject: [PATCH 05/40] Add a deinit function to handle avformat_network_deinit
---
src/zm_ffmpeg.cpp | 8 +++++++-
src/zm_ffmpeg.h | 1 +
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/src/zm_ffmpeg.cpp b/src/zm_ffmpeg.cpp
index b22ca6df5..5efbdb07a 100644
--- a/src/zm_ffmpeg.cpp
+++ b/src/zm_ffmpeg.cpp
@@ -65,8 +65,9 @@ void log_libav_callback( void *ptr, int level, const char *fmt, va_list vargs )
}
}
+static bool bInit = false;
+
void FFMPEGInit() {
- static bool bInit = false;
if ( !bInit ) {
if ( logDebugging() )
@@ -86,6 +87,11 @@ void FFMPEGInit() {
}
}
+void FFMPEGDeInit() {
+ avformat_network_deinit();
+ bInit = false;
+}
+
#if HAVE_LIBAVUTIL
enum _AVPIXELFORMAT GetFFMPEGPixelFormat(unsigned int p_colours, unsigned p_subpixelorder) {
enum _AVPIXELFORMAT pf;
diff --git a/src/zm_ffmpeg.h b/src/zm_ffmpeg.h
index 383de6af3..a4d984dec 100644
--- a/src/zm_ffmpeg.h
+++ b/src/zm_ffmpeg.h
@@ -199,6 +199,7 @@ extern "C" {
/* A single function to initialize ffmpeg, to avoid multiple initializations */
void FFMPEGInit();
+void FFMPEGDeInit();
#if HAVE_LIBAVUTIL
enum _AVPIXELFORMAT GetFFMPEGPixelFormat(unsigned int p_colours, unsigned p_subpixelorder);
From a6998cbc9ebe4fff07484c0b60033446a708d8b4 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Mon, 1 Apr 2019 13:39:11 -0400
Subject: [PATCH 06/40] Use FFMPEGDeInit instead of avformat_network_deinit
---
src/zm_ffmpeg_camera.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/zm_ffmpeg_camera.cpp b/src/zm_ffmpeg_camera.cpp
index 5da4c0dc4..18ef7da12 100644
--- a/src/zm_ffmpeg_camera.cpp
+++ b/src/zm_ffmpeg_camera.cpp
@@ -168,7 +168,7 @@ FfmpegCamera::~FfmpegCamera() {
if ( capture ) {
Terminate();
}
- avformat_network_deinit();
+ FFMPEGDeInit();
}
void FfmpegCamera::Initialise() {
@@ -1034,7 +1034,7 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event
int FfmpegCamera::FfmpegInterruptCallback(void *ctx) {
//FfmpegCamera* camera = reinterpret_cast(ctx);
- Debug(4, "FfmpegInterruptCallback");
+ //Debug(4, "FfmpegInterruptCallback");
return zm_terminate;
}
From cb33318c4ac53ee472a07d2847731da640cab64d Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Mon, 1 Apr 2019 14:02:39 -0400
Subject: [PATCH 07/40] fix invalid memory access due to incorrect
opening/closing/copying of contexts
---
src/zm_videostore.cpp | 59 +++++++++++++++++++++++++++----------------
src/zm_videostore.h | 17 ++++++++-----
2 files changed, 47 insertions(+), 29 deletions(-)
diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp
index 5ae3404b7..4e0ee2eee 100644
--- a/src/zm_videostore.cpp
+++ b/src/zm_videostore.cpp
@@ -81,7 +81,7 @@ VideoStore::VideoStore(
filename, format);
return;
} else {
- Debug(4, "Success alocateing out ctx");
+ Debug(4, "Success allocating out ctx");
}
} // end if ! oc
@@ -94,7 +94,7 @@ VideoStore::VideoStore(
out_format = oc->oformat;
- AVCodec *video_out_codec = avcodec_find_encoder(video_in_ctx->codec_id);
+ video_out_codec = avcodec_find_encoder(video_in_ctx->codec_id);
if ( !video_out_codec ) {
#if (LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 11, 0) && (LIBAVFORMAT_VERSION_MICRO >= 100))
Fatal("Could not find encoder for '%s'", avcodec_get_name(video_out_ctx->codec_id));
@@ -112,9 +112,8 @@ VideoStore::VideoStore(
}
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
- //video_out_stream->codec = avcodec_alloc_context3(video_out_codec);
- // Since we are not re-encoding, all we have to do is copy the parameters
video_out_ctx = avcodec_alloc_context3(video_out_codec);
+ // Since we are not re-encoding, all we have to do is copy the parameters
// Copy params from instream to ctx
ret = avcodec_parameters_to_context(video_out_ctx, video_in_stream->codecpar);
if ( ret < 0 ) {
@@ -230,7 +229,6 @@ VideoStore::VideoStore(
#endif
}
-
AVDictionary *opts = 0;
if ( (ret = avcodec_open2(video_out_ctx, video_out_codec, &opts)) < 0 ) {
Warning("Can't open video codec (%s) %s",
@@ -278,16 +276,14 @@ VideoStore::VideoStore(
if ( audio_in_stream ) {
Debug(3, "Have audio stream");
-#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
- audio_in_ctx = avcodec_alloc_context3(NULL);
- ret = avcodec_parameters_to_context(audio_in_ctx,
- audio_in_stream->codecpar);
- audio_in_ctx->time_base = audio_in_stream->time_base;
-#else
- audio_in_ctx = audio_in_stream->codec;
-#endif
- if ( audio_in_ctx->codec_id != AV_CODEC_ID_AAC ) {
+ if (
+#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
+ audio_in_stream->codecpar->codec_id
+#else
+ audio_in_stream->codec->codec_id
+#endif
+ != AV_CODEC_ID_AAC ) {
static char error_buffer[256];
avcodec_string(error_buffer, sizeof(error_buffer), audio_in_ctx, 0);
Debug(2, "Got something other than AAC (%s)", error_buffer);
@@ -298,6 +294,15 @@ VideoStore::VideoStore(
} else {
Debug(2, "Got AAC");
+#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
+ audio_in_ctx = avcodec_alloc_context3(NULL);
+ ret = avcodec_parameters_to_context(audio_in_ctx,
+ audio_in_stream->codecpar);
+ audio_in_ctx->time_base = audio_in_stream->time_base;
+#else
+ audio_in_ctx = audio_in_stream->codec;
+#endif
+
audio_out_stream =
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
avformat_new_stream(oc, (const AVCodec *)(audio_in_ctx->codec));
@@ -506,30 +511,39 @@ VideoStore::~VideoStore() {
#endif
video_in_ctx = NULL;
+ if ( video_out_codec ) {
+ avcodec_close(video_out_ctx);
+ Debug(4, "Success closing video_out_ctx");
+ video_out_codec = NULL;
+ } // end if video_out_codec
avcodec_close(video_out_ctx);
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
- //avcodec_free_context(&video_out_ctx);
+ avcodec_free_context(&video_out_ctx);
#endif
video_out_ctx = NULL;
- Debug(4, "Success freeing video_out_ctx");
} // end if video_out_stream
if ( audio_out_stream ) {
if ( audio_in_codec ) {
avcodec_close(audio_in_ctx);
+ Debug(4, "Success closing audio_in_ctx");
audio_in_codec = NULL;
} // end if audio_in_codec
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
// We allocate and copy in newer ffmpeg, so need to free it
avcodec_free_context(&audio_in_ctx);
+ Debug(4, "Success freeing audio_in_ctx");
#endif
audio_in_ctx = NULL;
- avcodec_close(audio_out_ctx);
+ if ( audio_out_ctx ) {
+ avcodec_close(audio_out_ctx);
+ Debug(4, "Success closing audio_out_ctx");
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
- avcodec_free_context(&audio_out_ctx);
+ avcodec_free_context(&audio_out_ctx);
#endif
+ }
audio_out_ctx = NULL;
#if defined(HAVE_LIBAVRESAMPLE) || defined(HAVE_LIBSWRESAMPLE)
if ( resample_ctx ) {
@@ -579,8 +593,11 @@ bool VideoStore::setup_resampler() {
audio_in_codec =
avcodec_find_decoder(audio_in_stream->codecpar->codec_id);
#else
- audio_in_codec = avcodec_find_decoder(audio_in_ctx->codec_id);
+// codec is already open in ffmpeg_camera
+ audio_in_codec = avcodec_find_decoder(audio_in_stream->codec->codec_id);
#endif
+ audio_in_ctx = avcodec_alloc_context3(audio_in_codec);
+
if ( (ret = avcodec_open2(audio_in_ctx, audio_in_codec, NULL)) < 0 ) {
Error("Can't open in codec!");
return false;
@@ -592,6 +609,7 @@ bool VideoStore::setup_resampler() {
return false;
}
+ audio_out_stream = avformat_new_stream(oc, audio_out_codec);
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
// audio_out_ctx = audio_out_stream->codec;
audio_out_ctx = avcodec_alloc_context3(audio_out_codec);
@@ -600,10 +618,7 @@ bool VideoStore::setup_resampler() {
audio_out_stream = NULL;
return false;
}
-
- audio_out_stream = avformat_new_stream(oc, audio_out_codec);
#else
- audio_out_stream = avformat_new_stream(oc, NULL);
audio_out_ctx = audio_out_stream->codec;
#endif
// Some formats (i.e. WAV) do not produce the proper channel layout
diff --git a/src/zm_videostore.h b/src/zm_videostore.h
index 08cf01a42..1fe3fe81b 100644
--- a/src/zm_videostore.h
+++ b/src/zm_videostore.h
@@ -20,14 +20,16 @@ extern "C" {
class VideoStore {
private:
- AVOutputFormat *out_format;
- AVFormatContext *oc;
- AVStream *video_out_stream;
- AVStream *audio_out_stream;
- AVCodecContext *video_out_ctx;
+ AVOutputFormat *out_format;
+ AVFormatContext *oc;
- AVStream *video_in_stream;
- AVStream *audio_in_stream;
+ AVCodec *video_out_codec;
+ AVCodecContext *video_out_ctx;
+ AVStream *video_out_stream;
+
+ AVStream *video_in_stream;
+
+ AVStream *audio_in_stream;
// Move this into the object so that we aren't constantly allocating/deallocating it on the stack
AVPacket opkt;
@@ -41,6 +43,7 @@ private:
int ret;
// The following are used when encoding the audio stream to AAC
+ AVStream *audio_out_stream;
AVCodec *audio_out_codec;
AVCodecContext *audio_out_ctx;
#ifdef HAVE_LIBSWRESAMPLE
From f78e95f5d4dde01fa0fb1c83400fcde8e08b07ba Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Wed, 3 Apr 2019 13:21:52 -0400
Subject: [PATCH 08/40] add is_video_context and is_audio_context and use them
in zm_revceive_frame to add audio decoding support
---
src/zm_ffmpeg.cpp | 36 ++++++++++++++++++++++++++++++------
src/zm_ffmpeg.h | 7 +++++--
2 files changed, 35 insertions(+), 8 deletions(-)
diff --git a/src/zm_ffmpeg.cpp b/src/zm_ffmpeg.cpp
index 5efbdb07a..011def0ee 100644
--- a/src/zm_ffmpeg.cpp
+++ b/src/zm_ffmpeg.cpp
@@ -285,7 +285,8 @@ static void zm_log_fps(double d, const char *postfix) {
}
void zm_dump_frame(const AVFrame *frame,const char *text) {
- Debug(1, "%s: format %d %s sample_rate %" PRIu32 " nb_samples %d channels %d layout %d pts %" PRId64,
+ Debug(1, "%s: format %d %s sample_rate %" PRIu32 " nb_samples %d channels %d layout %d pts %" PRId64
+ " duration %" PRId64,
text,
frame->format,
av_get_sample_fmt_name((AVSampleFormat)frame->format),
@@ -297,7 +298,8 @@ void zm_dump_frame(const AVFrame *frame,const char *text) {
0,
#endif
frame->channel_layout,
- frame->pts
+ frame->pts,
+ frame->pkt_duration
);
}
@@ -450,6 +452,14 @@ bool is_video_stream( AVStream * stream ) {
return false;
}
+bool is_video_context( AVCodecContext *codec_context ) {
+ return
+ #if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0))
+ ( codec_context->codec_type == AVMEDIA_TYPE_VIDEO );
+ #else
+ ( codec_context->codec_type == CODEC_TYPE_VIDEO );
+ #endif
+}
bool is_audio_stream( AVStream * stream ) {
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
@@ -466,6 +476,15 @@ bool is_audio_stream( AVStream * stream ) {
return false;
}
+bool is_audio_context( AVCodecContext *codec_context ) {
+ return
+ #if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0))
+ ( codec_context->codec_type == AVMEDIA_TYPE_AUDIO );
+ #else
+ ( codec_context->codec_type == CODEC_TYPE_AUDIO );
+ #endif
+}
+
int zm_receive_frame( AVCodecContext *context, AVFrame *frame, AVPacket &packet ) {
int ret;
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
@@ -500,15 +519,20 @@ int zm_receive_frame( AVCodecContext *context, AVFrame *frame, AVPacket &packet
# else
int frameComplete = 0;
while ( !frameComplete ) {
- if ( (ret = zm_avcodec_decode_video( context, frame, &frameComplete, &packet )) < 0 ) {
- Error( "Unable to decode frame at frame: %s, continuing",
- av_make_error_string(ret).c_str() );
+ if ( is_video_context(context) ) {
+ ret = zm_avcodec_decode_video(context, frame, &frameComplete, &packet);
+ } else {
+ ret = avcodec_decode_audio4(context, frame, &frameComplete, &packet);
+ }
+ if ( ret < 0 ) {
+ Error("Unable to decode frame: %s", av_make_error_string(ret).c_str());
return 0;
}
- }
+ } // end while !frameComplete
#endif
return 1;
} // end int zm_receive_frame( AVCodecContext *context, AVFrame *frame, AVPacket &packet )
+
void dumpPacket(AVStream *stream, AVPacket *pkt, const char *text) {
char b[10240];
diff --git a/src/zm_ffmpeg.h b/src/zm_ffmpeg.h
index a4d984dec..37a239509 100644
--- a/src/zm_ffmpeg.h
+++ b/src/zm_ffmpeg.h
@@ -326,8 +326,11 @@ void zm_dump_frame(const AVFrame *frame, const char *text="Frame");
int check_sample_fmt(AVCodec *codec, enum AVSampleFormat sample_fmt);
-bool is_video_stream( AVStream * stream );
-bool is_audio_stream( AVStream * stream );
+bool is_video_stream(AVStream *);
+bool is_audio_stream(AVStream *);
+bool is_video_context(AVCodec *);
+bool is_audio_context(AVCodec *);
+
int zm_receive_frame( AVCodecContext *context, AVFrame *frame, AVPacket &packet );
void dumpPacket(AVStream *, AVPacket *,const char *text="");
#endif // ZM_FFMPEG_H
From aece64049f7f91038f4a647fd849c630a82c2138 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Wed, 3 Apr 2019 13:23:00 -0400
Subject: [PATCH 09/40] We cannot avcodec_open2 a context that has been duped.
This code currently works without crashes and leaks on ffmpeg 2.8
---
src/zm_videostore.cpp | 457 ++++++++++++++++++++++--------------------
src/zm_videostore.h | 1 +
2 files changed, 237 insertions(+), 221 deletions(-)
diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp
index 7d3c4b256..0d0c88765 100644
--- a/src/zm_videostore.cpp
+++ b/src/zm_videostore.cpp
@@ -103,6 +103,7 @@ VideoStore::VideoStore(
#endif
}
+#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
video_out_stream = avformat_new_stream(oc, video_out_codec);
if ( !video_out_stream ) {
Error("Unable to create video out stream");
@@ -111,7 +112,7 @@ VideoStore::VideoStore(
Debug(2, "Success creating video out stream");
}
-#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
+ // by allocating our own copy, we don't run into the problems when we free the streams
video_out_ctx = avcodec_alloc_context3(video_out_codec);
// Since we are not re-encoding, all we have to do is copy the parameters
// Copy params from instream to ctx
@@ -123,8 +124,21 @@ VideoStore::VideoStore(
zm_dump_codec(video_out_ctx);
}
#else
+ video_out_stream = avformat_new_stream(oc, NULL);
+ if ( !video_out_stream ) {
+ Error("Unable to create video out stream");
+ return;
+ } else {
+ Debug(2, "Success creating video out stream");
+ }
video_out_ctx = video_out_stream->codec;
+ // This will wipe out the codec defaults
ret = avcodec_copy_context(video_out_ctx, video_in_ctx);
+ //video_out_ctx->width = video_in_ctx->width;
+ //video_out_ctx->height = video_in_ctx->height;
+ //video_out_ctx->pix_fmt = video_in_ctx->pix_fmt;
+ //video_out_ctx->max_b_frames = video_in_ctx->max_b_frames;
+ //video_out_ctx->has_b_frames = video_in_ctx->has_b_frames;
if ( ret < 0 ) {
Fatal("Unable to copy in video ctx to out video ctx %s",
av_make_error_string(ret).c_str());
@@ -142,8 +156,7 @@ VideoStore::VideoStore(
zm_dump_codec(video_out_ctx);
- //video_out_ctx->bit_rate = 400*1024;
- //video_out_ctx->thread_count = 0;
+#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
//// Fix deprecated formats
switch ( video_out_ctx->pix_fmt ) {
case AV_PIX_FMT_YUVJ422P :
@@ -162,15 +175,6 @@ VideoStore::VideoStore(
break;
}
- if ( video_out_ctx->codec_id == AV_CODEC_ID_H264 ) {
- video_out_ctx->max_b_frames = 1;
- if ( video_out_ctx->priv_data ) {
- av_opt_set(video_out_ctx->priv_data, "crf", "1", AV_OPT_SEARCH_CHILDREN);
- //av_opt_set(video_out_ctx->priv_data, "preset", "ultrafast", 0);
- } else {
- Debug(2, "Not setting priv_data");
- }
- }
if ( !video_out_ctx->codec_tag ) {
Debug(2, "No codec_tag");
@@ -185,6 +189,7 @@ VideoStore::VideoStore(
video_out_ctx->codec_tag = video_in_ctx->codec_tag;
}
}
+#endif
video_out_stream->time_base = video_in_stream->time_base;
if ( video_in_stream->avg_frame_rate.num ) {
@@ -195,13 +200,26 @@ VideoStore::VideoStore(
video_out_stream->avg_frame_rate = video_in_stream->avg_frame_rate;
}
if ( video_in_stream->r_frame_rate.num ) {
- Debug(3,"Copying r_frame_rate (%d/%d)",
+ Debug(3,"Copying r_frame_rate (%d/%d) to out (%d/%d)",
video_in_stream->r_frame_rate.num,
- video_in_stream->r_frame_rate.den
+ video_in_stream->r_frame_rate.den ,
+ video_out_stream->r_frame_rate.num,
+ video_out_stream->r_frame_rate.den
);
video_out_stream->r_frame_rate = video_in_stream->r_frame_rate;
}
#if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0)
+ if ( video_out_ctx->codec_id == AV_CODEC_ID_H264 ) {
+ //video_out_ctx->level = 32;I//
+ video_out_ctx->bit_rate = 400*1024;
+ video_out_ctx->max_b_frames = 1;
+ if ( video_out_ctx->priv_data ) {
+ av_opt_set(video_out_ctx->priv_data, "crf", "1", AV_OPT_SEARCH_CHILDREN);
+ av_opt_set(video_out_ctx->priv_data, "preset", "ultrafast", 0);
+ } else {
+ Debug(2, "Not setting priv_data");
+ }
+ }
ret = avcodec_parameters_from_context(video_out_stream->codecpar, video_out_ctx);
if ( ret < 0 ) {
Error("Could not initialize video_out_ctx parameters");
@@ -229,6 +247,7 @@ VideoStore::VideoStore(
#endif
}
+#if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0)
AVDictionary *opts = 0;
if ( (ret = avcodec_open2(video_out_ctx, video_out_codec, &opts)) < 0 ) {
Warning("Can't open video codec (%s) %s",
@@ -242,6 +261,7 @@ VideoStore::VideoStore(
while ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
Warning("Encoder Option %s not recognized by ffmpeg codec", e->key);
}
+#endif
Monitor::Orientation orientation = monitor->getOrientation();
if ( orientation ) {
@@ -273,6 +293,15 @@ VideoStore::VideoStore(
fifo = NULL;
#endif
#endif
+ video_first_pts = 0;
+ video_first_dts = 0;
+ video_last_pts = 0;
+ video_last_dts = 0;
+
+ audio_first_pts = 0;
+ audio_first_dts = 0;
+ audio_next_pts = 0;
+ audio_next_dts = 0;
if ( audio_in_stream ) {
Debug(3, "Have audio stream");
@@ -284,9 +313,27 @@ VideoStore::VideoStore(
audio_in_stream->codec->codec_id
#endif
!= AV_CODEC_ID_AAC ) {
- static char error_buffer[256];
- avcodec_string(error_buffer, sizeof(error_buffer), audio_in_ctx, 0);
- Debug(2, "Got something other than AAC (%s)", error_buffer);
+
+ audio_out_codec = avcodec_find_encoder(AV_CODEC_ID_AAC);
+ if ( !audio_out_codec ) {
+ Error("Could not find codec for AAC");
+ return;
+ }
+
+#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
+ audio_out_stream = avformat_new_stream(oc, NULL);
+ audio_out_stream->time_base = audio_in_stream->time_base;
+ audio_out_ctx = avcodec_alloc_context3(audio_out_codec);
+ if ( !audio_out_ctx ) {
+ Error("could not allocate codec ctx for AAC");
+ audio_out_stream = NULL;
+ return;
+ }
+#else
+ audio_out_stream = avformat_new_stream(oc, audio_out_codec);
+ audio_out_ctx = audio_out_stream->codec;
+#endif
+ audio_out_stream->time_base = audio_in_stream->time_base;
if ( !setup_resampler() ) {
return;
@@ -294,90 +341,66 @@ VideoStore::VideoStore(
} else {
Debug(2, "Got AAC");
-#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
- audio_in_ctx = avcodec_alloc_context3(NULL);
- ret = avcodec_parameters_to_context(audio_in_ctx,
- audio_in_stream->codecpar);
- audio_in_ctx->time_base = audio_in_stream->time_base;
-#else
- audio_in_ctx = audio_in_stream->codec;
-#endif
-
- audio_out_stream =
-#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
- avformat_new_stream(oc, (const AVCodec *)(audio_in_ctx->codec));
-#else
- avformat_new_stream(oc, (AVCodec *)audio_in_ctx->codec);
-#endif
+ audio_out_stream = avformat_new_stream(oc, NULL);
if ( !audio_out_stream ) {
- Error("Unable to create audio out stream");
- audio_out_stream = NULL;
- } else {
-#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
- audio_out_ctx = avcodec_alloc_context3(audio_out_codec);
- // Copy params from instream to ctx
- ret = avcodec_parameters_to_context(
- audio_out_ctx, audio_in_stream->codecpar);
- if ( ret < 0 ) {
- Error("Unable to copy audio params to ctx %s",
- av_make_error_string(ret).c_str());
- }
- ret = avcodec_parameters_from_context(
- audio_out_stream->codecpar, audio_out_ctx);
- if ( ret < 0 ) {
- Error("Unable to copy audio params to stream %s",
- av_make_error_string(ret).c_str());
- }
+ Error("Could not allocate new stream");
+ return;
+ }
+ audio_out_stream->time_base = audio_in_stream->time_base;
- if ( !audio_out_ctx->codec_tag ) {
- audio_out_ctx->codec_tag = av_codec_get_tag(
- oc->oformat->codec_tag, audio_in_ctx->codec_id);
- Debug(2, "Setting audio codec tag to %d",
- audio_out_ctx->codec_tag);
- }
+#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
+ // Just use the ctx to copy the parameters over
+ audio_out_ctx = avcodec_alloc_context3(NULL);
+ if ( !audio_out_ctx ) {
+ Error("Could not allocate new output_context");
+ return;
+ }
+
+ // We don't actually care what the time_base is..
+ audio_out_ctx->time_base = audio_in_stream->time_base;
+
+ // Copy params from instream to ctx
+ ret = avcodec_parameters_to_context(
+ audio_out_ctx, audio_in_stream->codecpar);
+ if ( ret < 0 ) {
+ Error("Unable to copy audio params to ctx %s",
+ av_make_error_string(ret).c_str());
+ }
+ ret = avcodec_parameters_from_context(
+ audio_out_stream->codecpar, audio_out_ctx);
+ if ( ret < 0 ) {
+ Error("Unable to copy audio params to stream %s",
+ av_make_error_string(ret).c_str());
+ }
+ avcodec_free_context(&audio_out_ctx);
#else
- audio_out_ctx = audio_out_stream->codec;
- ret = avcodec_copy_context(audio_out_ctx, audio_in_ctx);
- audio_out_ctx->codec_tag = 0;
+ audio_out_ctx = audio_out_stream->codec;
+ ret = avcodec_copy_context(audio_out_ctx, audio_in_stream->codec);
+ if ( ret < 0 ) {
+ Error("Unable to copy audio ctx %s",
+ av_make_error_string(ret).c_str());
+ audio_out_stream = NULL;
+ return;
+ } // end if
+ audio_out_ctx->codec_tag = 0;
#endif
- if ( ret < 0 ) {
- Error("Unable to copy audio ctx %s",
- av_make_error_string(ret).c_str());
- audio_out_stream = NULL;
- } else {
- if ( audio_out_ctx->channels > 1 ) {
- Warning("Audio isn't mono, changing it.");
- audio_out_ctx->channels = 1;
- } else {
- Debug(3, "Audio is mono");
- }
- }
- } // end if audio_out_stream
+
+ if ( audio_out_ctx->channels > 1 ) {
+ Warning("Audio isn't mono, changing it.");
+ audio_out_ctx->channels = 1;
+ } else {
+ Debug(3, "Audio is mono");
+ }
} // end if is AAC
- if ( audio_out_stream ) {
- if ( oc->oformat->flags & AVFMT_GLOBALHEADER ) {
+ if ( oc->oformat->flags & AVFMT_GLOBALHEADER ) {
#if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0)
- audio_out_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
+ audio_out_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
#else
- audio_out_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;
+ audio_out_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;
#endif
- }
}
} // end if audio_in_stream
-
- video_first_pts = 0;
- video_first_dts = 0;
- video_last_pts = 0;
- video_last_dts = 0;
-
- audio_first_pts = 0;
- audio_first_dts = 0;
- audio_last_pts = 0;
- audio_last_dts = 0;
- audio_next_pts = 0;
- audio_next_dts = 0;
-
} // VideoStore::VideoStore
bool VideoStore::open() {
@@ -500,6 +523,7 @@ VideoStore::~VideoStore() {
}
} // end if ( oc->pb )
+#if 0
// I wonder if we should be closing the file first.
// I also wonder if we really need to be doing all the ctx
// allocation/de-allocation constantly, or whether we can just re-use it.
@@ -508,7 +532,7 @@ VideoStore::~VideoStore() {
if ( video_out_stream ) {
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
// We allocate and copy in newer ffmpeg, so need to free it
- //avcodec_free_context(&video_in_ctx);
+ avcodec_free_context(&video_in_ctx);
#endif
video_in_ctx = NULL;
@@ -517,14 +541,15 @@ VideoStore::~VideoStore() {
Debug(4, "Success closing video_out_ctx");
video_out_codec = NULL;
} // end if video_out_codec
- avcodec_close(video_out_ctx);
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
- avcodec_free_context(&video_out_ctx);
#endif
+ avcodec_free_context(&video_out_ctx);
video_out_ctx = NULL;
} // end if video_out_stream
+#endif
if ( audio_out_stream ) {
+#if 0
if ( audio_in_codec ) {
avcodec_close(audio_in_ctx);
Debug(4, "Success closing audio_in_ctx");
@@ -533,33 +558,35 @@ VideoStore::~VideoStore() {
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
// We allocate and copy in newer ffmpeg, so need to free it
+#endif
avcodec_free_context(&audio_in_ctx);
Debug(4, "Success freeing audio_in_ctx");
-#endif
audio_in_ctx = NULL;
if ( audio_out_ctx ) {
avcodec_close(audio_out_ctx);
Debug(4, "Success closing audio_out_ctx");
-#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
avcodec_free_context(&audio_out_ctx);
+#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
#endif
}
audio_out_ctx = NULL;
+#endif
+
#if defined(HAVE_LIBAVRESAMPLE) || defined(HAVE_LIBSWRESAMPLE)
if ( resample_ctx ) {
-#if defined(HAVE_LIBSWRESAMPLE)
+ #if defined(HAVE_LIBSWRESAMPLE)
if ( fifo ) {
av_audio_fifo_free(fifo);
fifo = NULL;
}
swr_free(&resample_ctx);
-#else
-#if defined(HAVE_LIBAVRESAMPLE)
+ #else
+ #if defined(HAVE_LIBAVRESAMPLE)
avresample_close(resample_ctx);
avresample_free(&resample_ctx);
-#endif
-#endif
+ #endif
+ #endif
}
if ( in_frame ) {
av_frame_free(&in_frame);
@@ -576,7 +603,7 @@ VideoStore::~VideoStore() {
#endif
} // end if audio_out_stream
- /* free the stream */
+ /* free the streams */
avformat_free_context(oc);
} // VideoStore::~VideoStore()
@@ -593,35 +620,35 @@ bool VideoStore::setup_resampler() {
// decoder, can't reuse the one from the camera.
audio_in_codec =
avcodec_find_decoder(audio_in_stream->codecpar->codec_id);
+ audio_in_ctx = avcodec_alloc_context3(audio_in_codec);
#else
// codec is already open in ffmpeg_camera
- audio_in_codec = avcodec_find_decoder(audio_in_stream->codec->codec_id);
+ audio_in_ctx = audio_in_stream->codec;
+ audio_in_codec = (AVCodec *)audio_in_ctx->codec;
+ //audio_in_codec = avcodec_find_decoder(audio_in_stream->codec->codec_id);
#endif
- audio_in_ctx = avcodec_alloc_context3(audio_in_codec);
+#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
+#else
+#if 0
+ ret = avcodec_copy_context(audio_in_ctx, audio_in_stream->codec);
+ if ( ret < 0 ) {
+ Fatal("Unable to copy in video ctx to out video ctx %s",
+ av_make_error_string(ret).c_str());
+ } else {
+ Debug(3, "Success copying ctx");
+ }
+#endif
+#endif
+
+ // if the codec is already open, nothing is done.
if ( (ret = avcodec_open2(audio_in_ctx, audio_in_codec, NULL)) < 0 ) {
Error("Can't open in codec!");
return false;
}
- audio_out_codec = avcodec_find_encoder(AV_CODEC_ID_AAC);
- if ( !audio_out_codec ) {
- Error("Could not find codec for AAC");
- return false;
- }
+ Debug(2, "Got something other than AAC (%s)", audio_in_codec->name);
- audio_out_stream = avformat_new_stream(oc, audio_out_codec);
-#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
- // audio_out_ctx = audio_out_stream->codec;
- audio_out_ctx = avcodec_alloc_context3(audio_out_codec);
- if ( !audio_out_ctx ) {
- Error("could not allocate codec ctx for AAC");
- audio_out_stream = NULL;
- return false;
- }
-#else
- audio_out_ctx = audio_out_stream->codec;
-#endif
// Some formats (i.e. WAV) do not produce the proper channel layout
if ( audio_in_ctx->channel_layout == 0 ) {
Debug(2, "Setting input channel layout to mono");
@@ -930,7 +957,6 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt) {
opkt.dts = 0;
}
-
opkt.flags = ipkt->flags;
opkt.pos = -1;
opkt.data = ipkt->data;
@@ -969,46 +995,21 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
return 0; // FIXME -ve return codes do not free packet in ffmpeg_camera at
// the moment
}
+ dumpPacket(audio_in_stream, ipkt, "input packet");
if ( audio_out_codec ) {
-#if defined(HAVE_LIBSWRESAMPLE) || defined(HAVE_LIBAVRESAMPLE)
-
- #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
- if ( (ret = avcodec_send_packet(audio_in_ctx, ipkt)) < 0 ) {
- Error("avcodec_send_packet fail %s", av_make_error_string(ret).c_str());
+ Debug(2, "Have output codec");
+ if ( ! zm_receive_frame(audio_in_ctx, in_frame, *ipkt) ) {
return 0;
}
- if ( (ret = avcodec_receive_frame(audio_in_ctx, in_frame)) < 0 ) {
- Error("avcodec_receive_frame fail %s", av_make_error_string(ret).c_str());
- return 0;
- }
-
- #else
- int data_present;
- if ( (ret = avcodec_decode_audio4(
- audio_in_ctx, in_frame, &data_present, ipkt)) < 0 ) {
- Error("Could not decode frame (error '%s')",
- av_make_error_string(ret).c_str());
- dumpPacket(video_in_stream, ipkt);
- // I'm not sure if we should be freeing the frame.
- av_frame_free(&in_frame);
- return 0;
- }
- if ( !data_present ) {
- Debug(2, "Not ready to transcode a frame yet.");
- return 0;
- }
- #endif
zm_dump_frame(in_frame, "In frame from decode");
- int frame_size = in_frame->nb_samples;
- // Resample the in into the audioSampleBuffer until we proceed the whole
- // decoded data. Note: pts does not survive resampling or converting
- #if defined(HAVE_LIBSWRESAMPLE)
- Debug(2, "Converting %d to %d samples using swresample", in_frame->nb_samples, out_frame->nb_samples);
- ret = swr_convert_frame(resample_ctx, out_frame, in_frame);
- zm_dump_frame(out_frame, "Out frame after convert");
+ if ( ! resample_audio() ) {
+ av_frame_unref(in_frame);
+ return 0;
+ }
+ zm_dump_frame(out_frame, "Out frame after resample");
out_frame->pts = in_frame->pts;
// out_frame pts is in the input pkt pts... needs to be adjusted before sending to the encoder
@@ -1020,64 +1021,12 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
} else {
out_frame->pts = out_frame->pts - audio_first_pts;
}
+ //
+ } else {
+ // sending AV_NOPTS_VALUE doesn't really work but we seem to get it in ffmpeg 2.8
+ out_frame->pts = audio_next_pts;
}
- av_frame_unref(in_frame);
- if ( ret < 0 ) {
- Error("Could not resample frame (error '%s')",
- av_make_error_string(ret).c_str());
- return 0;
- }
- if ((ret = av_audio_fifo_realloc(fifo, av_audio_fifo_size(fifo) + out_frame->nb_samples)) < 0) {
- Error("Could not reallocate FIFO");
- return 0;
- }
- /** Store the new samples in the FIFO buffer. */
- ret = av_audio_fifo_write(fifo, (void **)out_frame->data, out_frame->nb_samples);
- if ( ret < frame_size ) {
- Error("Could not write data to FIFO on %d written", ret);
- return 0;
- }
-
- // Reset frame_size to output_frame_size
- frame_size = audio_out_ctx->frame_size;
-
- // AAC requires 1024 samples per encode. Our input tends to be 160, so need to buffer them.
- if ( frame_size > av_audio_fifo_size(fifo) ) {
- return 0;
- }
-
- if ( av_audio_fifo_read(fifo, (void **)out_frame->data, frame_size) < frame_size ) {
- Error("Could not read data from FIFO");
- return 0;
- }
- out_frame->nb_samples = frame_size;
- /// FIXME this is not the correct pts
- #else
- #if defined(HAVE_LIBAVRESAMPLE)
- (ret = avresample_convert(resample_ctx, NULL, 0, 0, in_frame->data,
- 0, in_frame->nb_samples))
- av_frame_unref(in_frame);
- if ( ret < 0 ) {
- Error("Could not resample frame (error '%s')",
- av_make_error_string(ret).c_str());
- return 0;
- }
-
- int samples_available = avresample_available(resample_ctx);
- if ( samples_available < frame_size ) {
- Debug(1, "Not enough samples yet (%d)", samples_available);
- return 0;
- }
-
- // Read a frame audio data from the resample fifo
- if ( avresample_read(resample_ctx, out_frame->data, frame_size) !=
- frame_size) {
- Warning("Error reading resampled audio.");
- return 0;
- }
- #endif
- #endif
- zm_dump_frame(out_frame, "Out frame after resample");
+ audio_next_pts = out_frame->pts + out_frame->nb_samples;
av_init_packet(&opkt);
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
@@ -1102,6 +1051,7 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
return 0;
}
#else
+ int data_present;
if ( (ret = avcodec_encode_audio2(
audio_out_ctx, &opkt, out_frame, &data_present)) < 0 ) {
Error("Could not encode frame (error '%s')",
@@ -1115,11 +1065,6 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
return 0;
}
#endif
-#else
- Error("Have audio codec but no resampler?!");
-#endif
- //if ( out_frame ) {
- //opkt.duration = out_frame->nb_samples;
opkt.duration = av_rescale_q(opkt.duration,
audio_in_stream->time_base,
audio_out_stream->time_base);
@@ -1129,12 +1074,15 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
opkt.dts = av_rescale_q(opkt.dts,
audio_in_stream->time_base,
audio_out_stream->time_base);
+ dumpPacket(audio_out_stream, &opkt, "raw opkt");
+
} else {
+ Debug(2,"copying");
av_init_packet(&opkt);
opkt.data = ipkt->data;
opkt.size = ipkt->size;
- if ( ipkt->duration != AV_NOPTS_VALUE ) {
+ if ( ipkt->duration && (ipkt->duration != AV_NOPTS_VALUE) ) {
opkt.duration = av_rescale_q(
ipkt->duration,
audio_in_stream->time_base,
@@ -1154,7 +1102,6 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
Debug(2, "audio opkt.pts = %" PRId64 " from ipkt->pts(%" PRId64 ") - first_pts(%" PRId64 ")",
opkt.pts, ipkt->pts, audio_first_pts);
}
- audio_last_pts = ipkt->pts;
} else {
Debug(2, "opkt.pts = undef");
opkt.pts = AV_NOPTS_VALUE;
@@ -1186,13 +1133,11 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
} else {
opkt.dts = AV_NOPTS_VALUE;
}
- }
+ } // end if encoding or copying
opkt.pos = -1;
opkt.stream_index = audio_out_stream->index;
- dumpPacket(audio_out_stream, &opkt, "raw opkt");
-
if ( opkt.dts > opkt.pts ) {
Debug(1,
"opkt.dts(%" PRId64 ") must be <= opkt.pts(%" PRId64 ")."
@@ -1213,3 +1158,73 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
zm_av_packet_unref(&opkt);
return 0;
} // end int VideoStore::writeAudioFramePacket(AVPacket *ipkt)
+
+int VideoStore::resample_audio() {
+ // Resample the in into the audioSampleBuffer until we process the whole
+ // decoded data. Note: pts does not survive resampling or converting
+#if defined(HAVE_LIBSWRESAMPLE) || defined(HAVE_LIBAVRESAMPLE)
+#if defined(HAVE_LIBSWRESAMPLE)
+ Debug(2, "Converting %d to %d samples using swresample",
+ in_frame->nb_samples, out_frame->nb_samples);
+ ret = swr_convert_frame(resample_ctx, out_frame, in_frame);
+ zm_dump_frame(out_frame, "Out frame after convert");
+
+ if ( ret < 0 ) {
+ Error("Could not resample frame (error '%s')",
+ av_make_error_string(ret).c_str());
+ return 0;
+ }
+ if ((ret = av_audio_fifo_realloc(fifo, av_audio_fifo_size(fifo) + out_frame->nb_samples)) < 0) {
+ Error("Could not reallocate FIFO");
+ return 0;
+ }
+ /** Store the new samples in the FIFO buffer. */
+ ret = av_audio_fifo_write(fifo, (void **)out_frame->data, out_frame->nb_samples);
+ if ( ret < in_frame->nb_samples ) {
+ Error("Could not write data to FIFO on %d written", ret);
+ return 0;
+ }
+
+ // Reset frame_size to output_frame_size
+ int frame_size = audio_out_ctx->frame_size;
+
+ // AAC requires 1024 samples per encode. Our input tends to be 160, so need to buffer them.
+ if ( frame_size > av_audio_fifo_size(fifo) ) {
+ return 0;
+ }
+
+ if ( av_audio_fifo_read(fifo, (void **)out_frame->data, frame_size) < frame_size ) {
+ Error("Could not read data from FIFO");
+ return 0;
+ }
+ out_frame->nb_samples = frame_size;
+#else
+#if defined(HAVE_LIBAVRESAMPLE)
+ (ret = avresample_convert(resample_ctx, NULL, 0, 0, in_frame->data,
+ 0, in_frame->nb_samples))
+ if ( ret < 0 ) {
+ Error("Could not resample frame (error '%s')",
+ av_make_error_string(ret).c_str());
+ return 0;
+ }
+
+ int samples_available = avresample_available(resample_ctx);
+ if ( samples_available < frame_size ) {
+ Debug(1, "Not enough samples yet (%d)", samples_available);
+ return 0;
+ }
+
+ // Read a frame audio data from the resample fifo
+ if ( avresample_read(resample_ctx, out_frame->data, frame_size) !=
+ frame_size) {
+ Warning("Error reading resampled audio.");
+ return 0;
+ }
+#endif
+#endif
+#else
+ Error("Have audio codec but no resampler?!");
+ return 0;
+#endif
+ return 1;
+} // end int VideoStore::resample_audio
diff --git a/src/zm_videostore.h b/src/zm_videostore.h
index 1fe3fe81b..8e7308e69 100644
--- a/src/zm_videostore.h
+++ b/src/zm_videostore.h
@@ -77,6 +77,7 @@ private:
int64_t audio_next_dts;
bool setup_resampler();
+ int resample_audio();
public:
VideoStore(
From b6f35db4defaa0c2a934bc15787567d6d8c254db Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Wed, 3 Apr 2019 14:25:18 -0400
Subject: [PATCH 10/40] put back codec closing in destructure, testing with
bionic
---
src/zm_videostore.cpp | 24 ++++++++++++++----------
1 file changed, 14 insertions(+), 10 deletions(-)
diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp
index 0d0c88765..d2804de90 100644
--- a/src/zm_videostore.cpp
+++ b/src/zm_videostore.cpp
@@ -104,7 +104,7 @@ VideoStore::VideoStore(
}
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
- video_out_stream = avformat_new_stream(oc, video_out_codec);
+ video_out_stream = avformat_new_stream(oc, NULL);
if ( !video_out_stream ) {
Error("Unable to create video out stream");
return;
@@ -523,7 +523,6 @@ VideoStore::~VideoStore() {
}
} // end if ( oc->pb )
-#if 0
// I wonder if we should be closing the file first.
// I also wonder if we really need to be doing all the ctx
// allocation/de-allocation constantly, or whether we can just re-use it.
@@ -532,7 +531,7 @@ VideoStore::~VideoStore() {
if ( video_out_stream ) {
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
// We allocate and copy in newer ffmpeg, so need to free it
- avcodec_free_context(&video_in_ctx);
+ //avcodec_free_context(&video_in_ctx);
#endif
video_in_ctx = NULL;
@@ -542,14 +541,12 @@ VideoStore::~VideoStore() {
video_out_codec = NULL;
} // end if video_out_codec
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
-#endif
avcodec_free_context(&video_out_ctx);
+#endif
video_out_ctx = NULL;
} // end if video_out_stream
-#endif
if ( audio_out_stream ) {
-#if 0
if ( audio_in_codec ) {
avcodec_close(audio_in_ctx);
Debug(4, "Success closing audio_in_ctx");
@@ -558,20 +555,19 @@ VideoStore::~VideoStore() {
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
// We allocate and copy in newer ffmpeg, so need to free it
-#endif
avcodec_free_context(&audio_in_ctx);
+#endif
Debug(4, "Success freeing audio_in_ctx");
audio_in_ctx = NULL;
if ( audio_out_ctx ) {
avcodec_close(audio_out_ctx);
Debug(4, "Success closing audio_out_ctx");
- avcodec_free_context(&audio_out_ctx);
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
+ avcodec_free_context(&audio_out_ctx);
#endif
}
audio_out_ctx = NULL;
-#endif
#if defined(HAVE_LIBAVRESAMPLE) || defined(HAVE_LIBSWRESAMPLE)
if ( resample_ctx ) {
@@ -621,6 +617,14 @@ bool VideoStore::setup_resampler() {
audio_in_codec =
avcodec_find_decoder(audio_in_stream->codecpar->codec_id);
audio_in_ctx = avcodec_alloc_context3(audio_in_codec);
+ // Copy params from instream to ctx
+ ret = avcodec_parameters_to_context(
+ audio_in_ctx, audio_in_stream->codecpar);
+ if ( ret < 0 ) {
+ Error("Unable to copy audio params to ctx %s",
+ av_make_error_string(ret).c_str());
+ }
+
#else
// codec is already open in ffmpeg_camera
audio_in_ctx = audio_in_stream->codec;
@@ -643,7 +647,7 @@ bool VideoStore::setup_resampler() {
// if the codec is already open, nothing is done.
if ( (ret = avcodec_open2(audio_in_ctx, audio_in_codec, NULL)) < 0 ) {
- Error("Can't open in codec!");
+ Error("Can't open audio in codec!");
return false;
}
From b53e4aa803f45c1f33af5d9045d09c4770e711de Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Wed, 3 Apr 2019 14:51:10 -0400
Subject: [PATCH 11/40] fix segfault
---
src/zm_videostore.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp
index d2804de90..993136e27 100644
--- a/src/zm_videostore.cpp
+++ b/src/zm_videostore.cpp
@@ -350,7 +350,7 @@ VideoStore::VideoStore(
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
// Just use the ctx to copy the parameters over
- audio_out_ctx = avcodec_alloc_context3(NULL);
+ audio_out_ctx = avcodec_alloc_context3(audio_out_codec);
if ( !audio_out_ctx ) {
Error("Could not allocate new output_context");
return;
@@ -372,7 +372,6 @@ VideoStore::VideoStore(
Error("Unable to copy audio params to stream %s",
av_make_error_string(ret).c_str());
}
- avcodec_free_context(&audio_out_ctx);
#else
audio_out_ctx = audio_out_stream->codec;
ret = avcodec_copy_context(audio_out_ctx, audio_in_stream->codec);
From 2e7fd7c9a24907a0b7f0ef8fb63969176f63ca75 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Wed, 3 Apr 2019 14:55:29 -0400
Subject: [PATCH 12/40] handle really old ffmpeg not having pkt_duration
---
src/zm_ffmpeg.cpp | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/src/zm_ffmpeg.cpp b/src/zm_ffmpeg.cpp
index 011def0ee..22d680260 100644
--- a/src/zm_ffmpeg.cpp
+++ b/src/zm_ffmpeg.cpp
@@ -285,8 +285,9 @@ static void zm_log_fps(double d, const char *postfix) {
}
void zm_dump_frame(const AVFrame *frame,const char *text) {
- Debug(1, "%s: format %d %s sample_rate %" PRIu32 " nb_samples %d channels %d layout %d pts %" PRId64
- " duration %" PRId64,
+ Debug(1, "%s: format %d %s sample_rate %" PRIu32 " nb_samples %d channels %d"
+ " duration %" PRId64
+ " layout %d pts %" PRId64,
text,
frame->format,
av_get_sample_fmt_name((AVSampleFormat)frame->format),
@@ -294,12 +295,12 @@ void zm_dump_frame(const AVFrame *frame,const char *text) {
frame->nb_samples,
#if LIBAVCODEC_VERSION_CHECK(56, 8, 0, 60, 100)
frame->channels,
+ frame->pkt_duration,
#else
-0,
+0, 0,
#endif
frame->channel_layout,
- frame->pts,
- frame->pkt_duration
+ frame->pts
);
}
From bd9b5afe46db7e9f9c590891bfb0417a21f446b1 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Wed, 3 Apr 2019 14:56:14 -0400
Subject: [PATCH 13/40] old ffmpeg doesn't have av_frame_unref and it doesn't
seem to be needed
---
src/zm_videostore.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp
index 0d0c88765..0586532fa 100644
--- a/src/zm_videostore.cpp
+++ b/src/zm_videostore.cpp
@@ -1006,7 +1006,7 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
zm_dump_frame(in_frame, "In frame from decode");
if ( ! resample_audio() ) {
- av_frame_unref(in_frame);
+ //av_frame_unref(in_frame);
return 0;
}
zm_dump_frame(out_frame, "Out frame after resample");
From 94479fc850afe605e0c5e8b7a9f040914932f875 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Wed, 3 Apr 2019 16:03:21 -0400
Subject: [PATCH 14/40] copy pkt flags as well. When pts is NOPTS_VALUE set it
to zero
---
src/zm_videostore.cpp | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp
index f6e38ee2c..0f51358f1 100644
--- a/src/zm_videostore.cpp
+++ b/src/zm_videostore.cpp
@@ -871,7 +871,7 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt) {
dumpPacket(video_in_stream, ipkt, "input packet");
int64_t duration;
- if ( ipkt->duration ) {
+ if ( ipkt->duration && ( ipkt->duration != AV_NOPTS_VALUE ) ) {
duration = av_rescale_q(
ipkt->duration,
video_in_stream->time_base,
@@ -925,7 +925,8 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt) {
video_last_pts = ipkt->pts;
} else {
Debug(3, "opkt.pts = undef");
- opkt.pts = AV_NOPTS_VALUE;
+ opkt.pts = 0;
+ //AV_NOPTS_VALUE;
}
// Just because the in stream wraps, doesn't mean the out needs to. Really, if we are limiting ourselves to 10min segments I can't imagine every wrapping in the out. So need to handle in wrap, without causing out wrap.
if ( ipkt->dts != AV_NOPTS_VALUE ) {
@@ -1140,6 +1141,7 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
opkt.pos = -1;
opkt.stream_index = audio_out_stream->index;
+ opkt.flags = ipkt->flags;
if ( opkt.dts > opkt.pts ) {
Debug(1,
From 12631abd46d664e9cf4389ec001cb34bf2de06a9 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Wed, 3 Apr 2019 16:51:27 -0400
Subject: [PATCH 15/40] when copying a packet (for old ffmpeg) copy pts, dts
and duration too
---
src/zm_ffmpeg.cpp | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/zm_ffmpeg.cpp b/src/zm_ffmpeg.cpp
index 22d680260..578e12e6b 100644
--- a/src/zm_ffmpeg.cpp
+++ b/src/zm_ffmpeg.cpp
@@ -434,6 +434,9 @@ unsigned int zm_av_packet_ref( AVPacket *dst, AVPacket *src ) {
av_new_packet(dst,src->size);
memcpy(dst->data, src->data, src->size);
dst->flags = src->flags;
+ dst->pts = src->pts;
+ dst->dts = src->dts;
+ dst->duration = src->duration;
return 0;
}
#endif
From 8d3fa807e2ad2ee2abdd9dabf5795eeb912d1278 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Wed, 3 Apr 2019 16:51:41 -0400
Subject: [PATCH 16/40] compilation fixes for old ffmpeg
---
src/zm_videostore.cpp | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp
index 0f51358f1..8b307ed7e 100644
--- a/src/zm_videostore.cpp
+++ b/src/zm_videostore.cpp
@@ -665,10 +665,7 @@ bool VideoStore::setup_resampler() {
audio_out_ctx->channels = audio_in_ctx->channels;
audio_out_ctx->channel_layout = audio_in_ctx->channel_layout;
audio_out_ctx->sample_fmt = audio_in_ctx->sample_fmt;
-#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
-#else
- audio_out_ctx->refcounted_frames = 1;
-#endif
+#if LIBAVCODEC_VERSION_CHECK(56, 8, 0, 60, 100)
if ( !audio_out_ctx->channel_layout ) {
Debug(3, "Correcting channel layout from (%d) to (%d)",
audio_out_ctx->channel_layout,
@@ -676,7 +673,7 @@ bool VideoStore::setup_resampler() {
);
audio_out_ctx->channel_layout = av_get_default_channel_layout(audio_out_ctx->channels);
}
-
+#endif
if ( audio_out_codec->supported_samplerates ) {
int found = 0;
for ( unsigned int i = 0; audio_out_codec->supported_samplerates[i]; i++ ) {
@@ -832,7 +829,9 @@ bool VideoStore::setup_resampler() {
out_frame->nb_samples = audio_out_ctx->frame_size;
out_frame->format = audio_out_ctx->sample_fmt;
+#if LIBAVCODEC_VERSION_CHECK(56, 8, 0, 60, 100)
out_frame->channels = audio_out_ctx->channels;
+#endif
out_frame->channel_layout = audio_out_ctx->channel_layout;
out_frame->sample_rate = audio_out_ctx->sample_rate;
@@ -1205,14 +1204,16 @@ int VideoStore::resample_audio() {
out_frame->nb_samples = frame_size;
#else
#if defined(HAVE_LIBAVRESAMPLE)
- (ret = avresample_convert(resample_ctx, NULL, 0, 0, in_frame->data,
- 0, in_frame->nb_samples))
+ ret = avresample_convert(resample_ctx, NULL, 0, 0, in_frame->data,
+ 0, in_frame->nb_samples);
if ( ret < 0 ) {
Error("Could not resample frame (error '%s')",
av_make_error_string(ret).c_str());
return 0;
}
+ int frame_size = audio_out_ctx->frame_size;
+
int samples_available = avresample_available(resample_ctx);
if ( samples_available < frame_size ) {
Debug(1, "Not enough samples yet (%d)", samples_available);
From 8de7d576a590556f9272e3477f537c30543d315b Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Thu, 4 Apr 2019 09:35:37 -0400
Subject: [PATCH 17/40] spacing and use Error instead of fprintf(stderr) so
that things get logged.
---
src/zmu.cpp | 202 +++++++++++++++++++++++++---------------------------
1 file changed, 99 insertions(+), 103 deletions(-)
diff --git a/src/zmu.cpp b/src/zmu.cpp
index a8ee61273..479bbd973 100644
--- a/src/zmu.cpp
+++ b/src/zmu.cpp
@@ -426,11 +426,11 @@ int main(int argc, char *argv[]) {
if ( config.opt_use_auth ) {
if ( strcmp(config.auth_relay, "none") == 0 ) {
if ( !checkUser(username)) {
- fprintf(stderr, "Error, username greater than allowed 32 characters\n");
+ Error("Username greater than allowed 32 characters");
exit_zmu(-1);
}
if ( !username ) {
- fprintf(stderr, "Error, username must be supplied\n");
+ Error("Username must be supplied");
exit_zmu(-1);
}
@@ -439,36 +439,32 @@ int main(int argc, char *argv[]) {
}
} else {
if ( !(username && password) && !auth ) {
- fprintf(stderr, "Error, username and password or auth string must be supplied\n");
+ Error("Username and password or auth string must be supplied");
exit_zmu(-1);
}
if ( !checkUser(username)) {
- fprintf(stderr, "Error, username greater than allowed 32 characters\n");
+ Error("Username greater than allowed 32 characters");
exit_zmu(-1);
}
if ( !checkPass(password)) {
- fprintf(stderr, "Error, password greater than allowed 64 characters\n");
+ Error("Password greater than allowed 64 characters");
exit_zmu(-1);
}
- //if ( strcmp( config.auth_relay, "hashed" ) == 0 )
- {
- if ( auth ) {
- user = zmLoadAuthUser(auth, false);
- }
+
+ if ( auth ) {
+ user = zmLoadAuthUser(auth, false);
}
- //else if ( strcmp( config.auth_relay, "plain" ) == 0 )
- {
- if ( username && password ) {
- user = zmLoadUser(username, password);
- }
+ if ( username && password ) {
+ user = zmLoadUser(username, password);
}
- }
+ } // auth relay == none or not
+
if ( !user ) {
- fprintf(stderr, "Error, unable to authenticate user\n");
- return exit_zmu(-1);
+ Error("Unable to authenticate user");
+ exit_zmu(-1);
}
if ( !ValidateAccess(user, mon_id, function) ) {
- fprintf(stderr, "Error, insufficient privileges for requested action\n");
+ Error("Insufficient privileges for requested action");
exit_zmu(-1);
}
} // end if auth
@@ -503,201 +499,201 @@ int main(int argc, char *argv[]) {
if ( verbose ) {
char timestamp_str[64] = "None";
if ( timestamp.tv_sec )
- strftime( timestamp_str, sizeof(timestamp_str), "%Y-%m-%d %H:%M:%S", localtime( ×tamp.tv_sec ) );
+ strftime(timestamp_str, sizeof(timestamp_str), "%Y-%m-%d %H:%M:%S", localtime(×tamp.tv_sec));
if ( image_idx == -1 )
- printf( "Time of last image capture: %s.%02ld\n", timestamp_str, timestamp.tv_usec/10000 );
+ printf("Time of last image capture: %s.%02ld\n", timestamp_str, timestamp.tv_usec/10000);
else
- printf( "Time of image %d capture: %s.%02ld\n", image_idx, timestamp_str, timestamp.tv_usec/10000 );
+ printf("Time of image %d capture: %s.%02ld\n", image_idx, timestamp_str, timestamp.tv_usec/10000);
} else {
- if ( have_output ) printf( "%c", separator );
- printf( "%ld.%02ld", timestamp.tv_sec, timestamp.tv_usec/10000 );
+ if ( have_output ) printf("%c", separator);
+ printf("%ld.%02ld", timestamp.tv_sec, timestamp.tv_usec/10000);
have_output = true;
}
}
if ( function & ZMU_READ_IDX ) {
if ( verbose )
- printf( "Last read index: %d\n", monitor->GetLastReadIndex() );
+ printf("Last read index: %d\n", monitor->GetLastReadIndex());
else {
- if ( have_output ) printf( "%c", separator );
- printf( "%d", monitor->GetLastReadIndex() );
+ if ( have_output ) printf("%c", separator);
+ printf("%d", monitor->GetLastReadIndex());
have_output = true;
}
}
if ( function & ZMU_WRITE_IDX ) {
- if ( verbose )
- printf( "Last write index: %d\n", monitor->GetLastWriteIndex() );
- else {
- if ( have_output ) printf( "%c", separator );
- printf( "%d", monitor->GetLastWriteIndex() );
+ if ( verbose ) {
+ printf("Last write index: %d\n", monitor->GetLastWriteIndex());
+ } else {
+ if ( have_output ) printf("%c", separator);
+ printf("%d", monitor->GetLastWriteIndex());
have_output = true;
}
}
if ( function & ZMU_EVENT ) {
- if ( verbose )
- printf( "Last event id: %" PRIu64 "\n", monitor->GetLastEventId() );
- else {
- if ( have_output ) printf( "%c", separator );
- printf( "%" PRIu64, monitor->GetLastEventId() );
+ if ( verbose ) {
+ printf("Last event id: %" PRIu64 "\n", monitor->GetLastEventId());
+ } else {
+ if ( have_output ) printf("%c", separator);
+ printf("%" PRIu64, monitor->GetLastEventId());
have_output = true;
}
}
if ( function & ZMU_FPS ) {
if ( verbose )
- printf( "Current capture rate: %.2f frames per second\n", monitor->GetFPS() );
+ printf("Current capture rate: %.2f frames per second\n", monitor->GetFPS());
else {
- if ( have_output ) printf( "%c", separator );
- printf( "%.2f", monitor->GetFPS() );
+ if ( have_output ) printf("%c", separator);
+ printf("%.2f", monitor->GetFPS());
have_output = true;
}
}
if ( function & ZMU_IMAGE ) {
if ( verbose ) {
if ( image_idx == -1 )
- printf( "Dumping last image captured to Monitor%d.jpg", monitor->Id() );
+ printf("Dumping last image captured to Monitor%d.jpg", monitor->Id());
else
- printf( "Dumping buffer image %d to Monitor%d.jpg", image_idx, monitor->Id() );
+ printf("Dumping buffer image %d to Monitor%d.jpg", image_idx, monitor->Id());
if ( scale != -1 )
- printf( ", scaling by %d%%", scale );
- printf( "\n" );
+ printf(", scaling by %d%%", scale);
+ printf("\n");
}
- monitor->GetImage( image_idx, scale>0?scale:100 );
+ monitor->GetImage(image_idx, scale>0?scale:100);
}
if ( function & ZMU_ZONES ) {
if ( verbose )
- printf( "Dumping zone image to Zones%d.jpg\n", monitor->Id() );
- monitor->DumpZoneImage( zoneString );
+ printf("Dumping zone image to Zones%d.jpg\n", monitor->Id());
+ monitor->DumpZoneImage(zoneString);
}
if ( function & ZMU_ALARM ) {
if ( verbose )
- printf( "Forcing alarm on\n" );
- monitor->ForceAlarmOn( config.forced_alarm_score, "Forced Web" );
+ printf("Forcing alarm on\n");
+ monitor->ForceAlarmOn(config.forced_alarm_score, "Forced Web");
while ( monitor->GetState() != Monitor::ALARM ) {
// Wait for monitor to notice.
usleep(1000);
}
- printf( "Alarmed event id: %" PRIu64 "\n", monitor->GetLastEventId() );
+ printf("Alarmed event id: %" PRIu64 "\n", monitor->GetLastEventId());
}
if ( function & ZMU_NOALARM ) {
if ( verbose )
- printf( "Forcing alarm off\n" );
+ printf("Forcing alarm off\n");
monitor->ForceAlarmOff();
}
if ( function & ZMU_CANCEL ) {
if ( verbose )
- printf( "Cancelling forced alarm on/off\n" );
+ printf("Cancelling forced alarm on/off\n");
monitor->CancelForced();
}
if ( function & ZMU_RELOAD ) {
if ( verbose )
- printf( "Reloading monitor settings\n" );
+ printf("Reloading monitor settings\n");
monitor->actionReload();
}
if ( function & ZMU_ENABLE ) {
if ( verbose )
- printf( "Enabling event generation\n" );
+ printf("Enabling event generation\n");
monitor->actionEnable();
}
if ( function & ZMU_DISABLE ) {
if ( verbose )
- printf( "Disabling event generation\n" );
+ printf("Disabling event generation\n");
monitor->actionDisable();
}
if ( function & ZMU_SUSPEND ) {
if ( verbose )
- printf( "Suspending event generation\n" );
+ printf("Suspending event generation\n");
monitor->actionSuspend();
}
if ( function & ZMU_RESUME ) {
if ( verbose )
- printf( "Resuming event generation\n" );
+ printf("Resuming event generation\n");
monitor->actionResume();
}
if ( function & ZMU_QUERY ) {
char monString[16382] = "";
- monitor->DumpSettings( monString, verbose );
- printf( "%s\n", monString );
+ monitor->DumpSettings(monString, verbose);
+ printf("%s\n", monString);
}
if ( function & ZMU_BRIGHTNESS ) {
if ( verbose ) {
if ( brightness >= 0 )
- printf( "New brightness: %d\n", monitor->actionBrightness( brightness ) );
+ printf("New brightness: %d\n", monitor->actionBrightness(brightness));
else
- printf( "Current brightness: %d\n", monitor->actionBrightness() );
+ printf("Current brightness: %d\n", monitor->actionBrightness());
} else {
- if ( have_output ) printf( "%c", separator );
+ if ( have_output ) printf("%c", separator);
if ( brightness >= 0 )
- printf( "%d", monitor->actionBrightness( brightness ) );
+ printf("%d", monitor->actionBrightness(brightness));
else
- printf( "%d", monitor->actionBrightness() );
+ printf("%d", monitor->actionBrightness());
have_output = true;
}
}
if ( function & ZMU_CONTRAST ) {
if ( verbose ) {
if ( contrast >= 0 )
- printf( "New brightness: %d\n", monitor->actionContrast( contrast ) );
+ printf("New brightness: %d\n", monitor->actionContrast(contrast));
else
- printf( "Current contrast: %d\n", monitor->actionContrast() );
+ printf("Current contrast: %d\n", monitor->actionContrast());
} else {
- if ( have_output ) printf( "%c", separator );
+ if ( have_output ) printf("%c", separator);
if ( contrast >= 0 )
- printf( "%d", monitor->actionContrast( contrast ) );
+ printf("%d", monitor->actionContrast(contrast));
else
- printf( "%d", monitor->actionContrast() );
+ printf("%d", monitor->actionContrast());
have_output = true;
}
}
if ( function & ZMU_HUE ) {
if ( verbose ) {
if ( hue >= 0 )
- printf( "New hue: %d\n", monitor->actionHue( hue ) );
+ printf("New hue: %d\n", monitor->actionHue(hue));
else
- printf( "Current hue: %d\n", monitor->actionHue() );
+ printf("Current hue: %d\n", monitor->actionHue());
} else {
- if ( have_output ) printf( "%c", separator );
+ if ( have_output ) printf("%c", separator);
if ( hue >= 0 )
- printf( "%d", monitor->actionHue( hue ) );
+ printf("%d", monitor->actionHue(hue));
else
- printf( "%d", monitor->actionHue() );
+ printf("%d", monitor->actionHue());
have_output = true;
}
}
if ( function & ZMU_COLOUR ) {
if ( verbose ) {
if ( colour >= 0 )
- printf( "New colour: %d\n", monitor->actionColour( colour ) );
+ printf("New colour: %d\n", monitor->actionColour(colour));
else
- printf( "Current colour: %d\n", monitor->actionColour() );
+ printf("Current colour: %d\n", monitor->actionColour());
} else {
- if ( have_output ) printf( "%c", separator );
+ if ( have_output ) printf("%c", separator);
if ( colour >= 0 )
- printf( "%d", monitor->actionColour( colour ) );
+ printf("%d", monitor->actionColour(colour));
else
- printf( "%d", monitor->actionColour() );
+ printf("%d", monitor->actionColour());
have_output = true;
}
}
if ( have_output ) {
- printf( "\n" );
+ printf("\n");
}
if ( !function ) {
Usage();
}
delete monitor;
} else {
- fprintf(stderr, "Error, invalid monitor id %d\n", mon_id);
+ Error("Invalid monitor id %d", mon_id);
exit_zmu(-1);
}
} else {
if ( function & ZMU_QUERY ) {
#if ZM_HAS_V4L
char vidString[0x10000] = "";
- bool ok = LocalCamera::GetCurrentSettings( device, vidString, v4lVersion, verbose );
- printf( "%s", vidString );
- exit_zmu( ok?0:-1 );
+ bool ok = LocalCamera::GetCurrentSettings(device, vidString, v4lVersion, verbose);
+ printf("%s", vidString);
+ exit_zmu(ok ? 0 : -1);
#else // ZM_HAS_V4L
- fprintf( stderr, "Error, video4linux is required for device querying\n" );
- exit_zmu( -1 );
+ Error("Video4linux is required for device querying");
+ exit_zmu(-1);
#endif // ZM_HAS_V4L
}
@@ -708,25 +704,25 @@ int main(int argc, char *argv[]) {
}
sql += " order by Id asc";
- if ( mysql_query( &dbconn, sql.c_str() ) ) {
- Error( "Can't run query: %s", mysql_error( &dbconn ) );
- exit_zmu( mysql_errno( &dbconn ) );
+ if ( mysql_query(&dbconn, sql.c_str()) ) {
+ Error("Can't run query: %s", mysql_error(&dbconn));
+ exit_zmu(mysql_errno(&dbconn));
}
- MYSQL_RES *result = mysql_store_result( &dbconn );
+ MYSQL_RES *result = mysql_store_result(&dbconn);
if ( !result ) {
- Error( "Can't use query result: %s", mysql_error( &dbconn ) );
- exit_zmu( mysql_errno( &dbconn ) );
+ Error("Can't use query result: %s", mysql_error(&dbconn));
+ exit_zmu(mysql_errno(&dbconn));
}
- Debug( 1, "Got %d monitors", mysql_num_rows( result ) );
+ Debug(1, "Got %d monitors", mysql_num_rows(result));
- printf( "%4s%5s%6s%9s%14s%6s%6s%8s%8s\n", "Id", "Func", "State", "TrgState", "LastImgTim", "RdIdx", "WrIdx", "LastEvt", "FrmRate" );
- for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) {
+ printf("%4s%5s%6s%9s%14s%6s%6s%8s%8s\n", "Id", "Func", "State", "TrgState", "LastImgTim", "RdIdx", "WrIdx", "LastEvt", "FrmRate");
+ for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row(result); i++ ) {
int mon_id = atoi(dbrow[0]);
int function = atoi(dbrow[1]);
- if ( !user || user->canAccess( mon_id ) ) {
+ if ( !user || user->canAccess(mon_id) ) {
if ( function > 1 ) {
- Monitor *monitor = Monitor::Load( mon_id, false, Monitor::QUERY );
+ Monitor *monitor = Monitor::Load(mon_id, false, Monitor::QUERY);
if ( monitor && monitor->connect() ) {
struct timeval tv = monitor->GetTimestamp();
printf( "%4d%5d%6d%9d%11ld.%02ld%6d%6d%8" PRIu64 "%8.2f\n",
@@ -744,7 +740,7 @@ int main(int argc, char *argv[]) {
}
} else {
struct timeval tv = { 0, 0 };
- printf( "%4d%5d%6d%9d%11ld.%02ld%6d%6d%8d%8.2f\n",
+ printf("%4d%5d%6d%9d%11ld.%02ld%6d%6d%8d%8.2f\n",
mon_id,
function,
0,
@@ -755,11 +751,11 @@ int main(int argc, char *argv[]) {
0,
0.0
);
- }
- }
- }
- mysql_free_result( result );
- }
+ } // end if function filter
+ } // endif !user || canAccess(mon_id)
+ } // end foreach row
+ mysql_free_result(result);
+ } // end if function && ZMU_LIST
}
delete user;
From 79de2b65cde72927932f5c4152ec7fae0acb3bb5 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Thu, 4 Apr 2019 12:18:46 -0400
Subject: [PATCH 18/40] If we are saving jpegs we don't save a snapshot image,
and since we may delay writing frame info to the db, we have to default to
frame 0 instead of snapshot
---
web/views/image.php | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/web/views/image.php b/web/views/image.php
index 672baf3f5..5959982d8 100644
--- a/web/views/image.php
+++ b/web/views/image.php
@@ -87,8 +87,9 @@ if ( empty($_REQUEST['path']) ) {
$Frame->Id('objdetect');
} else if ( $_REQUEST['fid'] == 'alarm' ) {
# look for first alarmed frame
- $Frame = ZM\Frame::find_one(array('EventId'=>$_REQUEST['eid'], 'Type'=>'Alarm'),
- array('order'=>'FrameId ASC'));
+ $Frame = ZM\Frame::find_one(
+ array('EventId'=>$_REQUEST['eid'], 'Type'=>'Alarm'),
+ array('order'=>'FrameId ASC'));
if ( !$Frame ) { # no alarms, get first one I find
$Frame = ZM\Frame::find_one(array('EventId'=>$_REQUEST['eid']));
if ( !$Frame ) {
@@ -101,7 +102,7 @@ if ( empty($_REQUEST['path']) ) {
$Monitor = $Event->Monitor();
if ( $Monitor->SaveJPEGs() & 1 ) {
# If we store Frames as jpgs, then we don't store an alarmed snapshot
- $path = $Event->Path().'/'.sprintf('%0'.ZM_EVENT_IMAGE_DIGITS.'d',$Frame->FrameId()).'-'.$show.'.jpg';
+ $path = $Event->Path().'/'.sprintf('%0'.ZM_EVENT_IMAGE_DIGITS.'d', $Frame->FrameId()).'-'.$show.'.jpg';
} else {
$path = $Event->Path().'/alarm.jpg';
}
@@ -113,12 +114,16 @@ if ( empty($_REQUEST['path']) ) {
ZM\Warning('No frame found for event ' . $_REQUEST['eid']);
$Frame = new ZM\Frame();
$Frame->Delta(1);
- $Frame->FrameId('snapshot');
+ if ( $Monitor->SaveJPEGs() & 1 ) {
+ $Frame->FrameId(0);
+ } else {
+ $Frame->FrameId('snapshot');
+ }
}
$Monitor = $Event->Monitor();
if ( $Monitor->SaveJPEGs() & 1 ) {
# If we store Frames as jpgs, then we don't store a snapshot
- $path = $Event->Path().'/'.sprintf('%0'.ZM_EVENT_IMAGE_DIGITS.'d',$Frame->FrameId()).'-'.$show.'.jpg';
+ $path = $Event->Path().'/'.sprintf('%0'.ZM_EVENT_IMAGE_DIGITS.'d', $Frame->FrameId()).'-'.$show.'.jpg';
} else {
$path = $Event->Path().'/snapshot.jpg';
}
From 271937f005e3dc84662a5668d7b946972d285cd3 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Thu, 4 Apr 2019 12:28:08 -0400
Subject: [PATCH 19/40] store the snapshot_file and alarm_file strings in the
boject during construction so that we don't have to do it everytime we write
out an image
---
src/zm_event.cpp | 9 +++------
src/zm_event.h | 2 ++
2 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/src/zm_event.cpp b/src/zm_event.cpp
index 876a031d4..c44f8ee93 100644
--- a/src/zm_event.cpp
+++ b/src/zm_event.cpp
@@ -193,6 +193,9 @@ Event::Event(
video_name[0] = 0;
+ snprintf(snapshot_file, sizeof(snapshot_file), "%s/snapshot.jpg", path);
+ snprintf(alarm_file, sizeof(alarm_file), "%s/alarm.jpg", path);
+
/* Save as video */
if ( monitor->GetOptVideoWriter() != 0 ) {
@@ -464,8 +467,6 @@ void Event::AddFramesInternal( int n_frames, int start_frame, Image **images, st
// neccessarily be of the motion. But some events are less than 10 frames,
// so I am changing this to 1, but we should overwrite it later with a better snapshot.
if ( frames == 1 ) {
- char snapshot_file[PATH_MAX];
- snprintf(snapshot_file, sizeof(snapshot_file), "%s/snapshot.jpg", path);
WriteFrameImage(images[i], *(timestamps[i]), snapshot_file);
}
}
@@ -549,15 +550,11 @@ void Event::AddFrame(Image *image, struct timeval timestamp, int score, Image *a
} else {
//If this is the first frame, we should add a thumbnail to the event directory
if ( frames == 1 || score > (int)max_score ) {
- char snapshot_file[PATH_MAX];
- snprintf(snapshot_file, sizeof(snapshot_file), "%s/snapshot.jpg", path);
WriteFrameImage(image, timestamp, snapshot_file);
}
// The first frame with a score will be the frame that alarmed the event
if (!alarm_frame_written && score > 0) {
alarm_frame_written = true;
- char alarm_file[PATH_MAX];
- snprintf(alarm_file, sizeof(alarm_file), "%s/alarm.jpg", path);
WriteFrameImage(image, timestamp, alarm_file);
}
}
diff --git a/src/zm_event.h b/src/zm_event.h
index 1d31addcc..2035b6af6 100644
--- a/src/zm_event.h
+++ b/src/zm_event.h
@@ -90,6 +90,8 @@ class Event {
unsigned int tot_score;
unsigned int max_score;
char path[PATH_MAX];
+ char snapshot_file[PATH_MAX];
+ char alarm_file[PATH_MAX];
VideoWriter* videowriter;
FILE* timecodes_fd;
char video_name[PATH_MAX];
From f6d5038586f524bb3331f5e2ebb4b2ca69084692 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Thu, 4 Apr 2019 12:37:25 -0400
Subject: [PATCH 20/40] we only use event_file if we are writing out a jpg, so
only generate the event_file string if we are writing out jpgs
---
src/zm_event.cpp | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/src/zm_event.cpp b/src/zm_event.cpp
index c44f8ee93..3fda77e11 100644
--- a/src/zm_event.cpp
+++ b/src/zm_event.cpp
@@ -456,9 +456,9 @@ void Event::AddFramesInternal( int n_frames, int start_frame, Image **images, st
frames++;
- static char event_file[PATH_MAX];
- snprintf(event_file, sizeof(event_file), staticConfig.capture_file_format, path, frames);
if ( monitor->GetOptSaveJPEGs() & 1 ) {
+ static char event_file[PATH_MAX];
+ snprintf(event_file, sizeof(event_file), staticConfig.capture_file_format, path, frames);
Debug(1, "Writing pre-capture frame %d", frames);
WriteFrameImage(images[i], *(timestamps[i]), event_file);
} else {
@@ -539,27 +539,25 @@ void Event::AddFrame(Image *image, struct timeval timestamp, int score, Image *a
frames++;
- static char event_file[PATH_MAX];
- snprintf(event_file, sizeof(event_file), staticConfig.capture_file_format, path, frames);
-
if ( monitor->GetOptSaveJPEGs() & 1 ) {
+ static char event_file[PATH_MAX];
+ snprintf(event_file, sizeof(event_file), staticConfig.capture_file_format, path, frames);
Debug(1, "Writing capture frame %d to %s", frames, event_file);
if ( ! WriteFrameImage(image, timestamp, event_file) ) {
Error("Failed to write frame image");
}
} else {
//If this is the first frame, we should add a thumbnail to the event directory
- if ( frames == 1 || score > (int)max_score ) {
+ if ( (frames == 1) || (score > (int)max_score) ) {
WriteFrameImage(image, timestamp, snapshot_file);
}
// The first frame with a score will be the frame that alarmed the event
- if (!alarm_frame_written && score > 0) {
+ if ( (!alarm_frame_written) && (score > 0) ) {
alarm_frame_written = true;
WriteFrameImage(image, timestamp, alarm_file);
}
}
if ( videowriter != NULL ) {
-Debug(3, "Writing video");
WriteFrameVideo(image, timestamp, videowriter);
}
@@ -625,7 +623,7 @@ Debug(3, "Writing video");
}
}
}
- }
+ } // end if frame_type == ALARM
/* This makes viewing the diagnostic images impossible because it keeps deleting them
if ( config.record_diag_images ) {
From bc6249309699fb865f191e16acd9beb68be748a5 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Thu, 4 Apr 2019 12:55:35 -0400
Subject: [PATCH 21/40] Increase sql buffer space because we are using path
strings that are PATH_MAX size.
---
src/zm_event.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/zm_event.cpp b/src/zm_event.cpp
index 3fda77e11..7b8b446d4 100644
--- a/src/zm_event.cpp
+++ b/src/zm_event.cpp
@@ -254,7 +254,7 @@ Event::~Event() {
WriteDbFrames();
// Should not be static because we might be multi-threaded
- char sql[ZM_SQL_MED_BUFSIZ];
+ char sql[ZM_SQL_LGE_BUFSIZ];
snprintf(sql, sizeof(sql),
"UPDATE Events SET Name='%s %" PRIu64 "', EndTime = from_unixtime( %ld ), Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d, DefaultVideo = '%s' WHERE Id = %" PRIu64,
monitor->EventPrefix(), id, end_time.tv_sec,
@@ -616,6 +616,7 @@ void Event::AddFrame(Image *image, struct timeval timestamp, int score, Image *a
if ( alarm_image ) {
if ( monitor->GetOptSaveJPEGs() & 2 ) {
+ static char event_file[PATH_MAX];
snprintf(event_file, sizeof(event_file), staticConfig.analyse_file_format, path, frames);
Debug(1, "Writing analysis frame %d", frames);
if ( ! WriteFrameImage(alarm_image, timestamp, event_file, true) ) {
From 7955a1c9b2d85c39e8ca831f009d9a3978e89fc1 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Thu, 4 Apr 2019 12:56:00 -0400
Subject: [PATCH 22/40] fix version check to get rid of deprecated
av_register_all
---
src/zm_ffmpeg.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/zm_ffmpeg.cpp b/src/zm_ffmpeg.cpp
index 578e12e6b..c5bc1b471 100644
--- a/src/zm_ffmpeg.cpp
+++ b/src/zm_ffmpeg.cpp
@@ -78,7 +78,7 @@ void FFMPEGInit() {
av_log_set_callback(log_libav_callback);
else
Info("Not enabling ffmpeg logs, as LOG_FFMPEG is disabled in options");
-#if LIBAVCODEC_VERSION_CHECK(58, 18, 0, 64, 0)
+#if LIBAVFORMAT_VERSION_CHECK(58, 9, 0, 64, 0)
#else
av_register_all();
#endif
From d97dd6cdd97438de87c97cbfd69599ef99ad3dde Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Thu, 4 Apr 2019 14:11:56 -0400
Subject: [PATCH 23/40] Should close videostore before closing input
codecs/streams.
---
src/zm_ffmpeg_camera.cpp | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/src/zm_ffmpeg_camera.cpp b/src/zm_ffmpeg_camera.cpp
index 04b4588d9..c07c9312e 100644
--- a/src/zm_ffmpeg_camera.cpp
+++ b/src/zm_ffmpeg_camera.cpp
@@ -675,6 +675,11 @@ int FfmpegCamera::Close() {
}
#endif
+ if ( videoStore ) {
+ delete videoStore;
+ videoStore = NULL;
+ }
+
if ( mVideoCodecContext ) {
avcodec_close(mVideoCodecContext);
Debug(1,"After codec close");
@@ -700,10 +705,6 @@ int FfmpegCamera::Close() {
mFormatContext = NULL;
}
- if ( videoStore ) {
- delete videoStore;
- videoStore = NULL;
- }
if ( packetqueue ) {
delete packetqueue;
packetqueue = NULL;
From 9ae6acf532f4bc471adc61a4ed417a15ddd34fde Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Thu, 4 Apr 2019 17:20:21 -0400
Subject: [PATCH 24/40] Fix for opening audio_in_codec
---
src/zm_ffmpeg.cpp | 1 +
src/zm_ffmpeg_camera.cpp | 18 +++++++++++++-----
2 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/src/zm_ffmpeg.cpp b/src/zm_ffmpeg.cpp
index c5bc1b471..63c0c9aa3 100644
--- a/src/zm_ffmpeg.cpp
+++ b/src/zm_ffmpeg.cpp
@@ -437,6 +437,7 @@ unsigned int zm_av_packet_ref( AVPacket *dst, AVPacket *src ) {
dst->pts = src->pts;
dst->dts = src->dts;
dst->duration = src->duration;
+ dst->stream_index = src->stream_index;
return 0;
}
#endif
diff --git a/src/zm_ffmpeg_camera.cpp b/src/zm_ffmpeg_camera.cpp
index 04b4588d9..ae04e0bc9 100644
--- a/src/zm_ffmpeg_camera.cpp
+++ b/src/zm_ffmpeg_camera.cpp
@@ -565,15 +565,23 @@ int FfmpegCamera::OpenFfmpeg() {
Debug(1, "HWACCEL not in use");
}
if ( mAudioStreamId >= 0 ) {
+ if ( (mAudioCodec = avcodec_find_decoder(
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
- mAudioCodecContext = avcodec_alloc_context3( NULL );
- avcodec_parameters_to_context( mAudioCodecContext, mFormatContext->streams[mAudioStreamId]->codecpar );
+ mFormatContext->streams[mAudioStreamId]->codecpar->codec_id
#else
- mAudioCodecContext = mFormatContext->streams[mAudioStreamId]->codec;
+ mFormatContext->streams[mAudioStreamId]->codec->codec_id
#endif
- if ( (mAudioCodec = avcodec_find_decoder(mAudioCodecContext->codec_id)) == NULL ) {
+ )) == NULL ) {
Debug(1, "Can't find codec for audio stream from %s", mPath.c_str());
} else {
+#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
+ mAudioCodecContext = avcodec_alloc_context3(mAudioCodec);
+ avcodec_parameters_to_context( mAudioCodecContext, mFormatContext->streams[mAudioStreamId]->codecpar );
+#else
+ mAudioCodecContext = mFormatContext->streams[mAudioStreamId]->codec;
+ // = avcodec_alloc_context3(mAudioCodec);
+#endif
+
Debug(1, "Audio Found decoder");
zm_dump_stream_format(mFormatContext, mAudioStreamId, 0, 0);
// Open the codec
@@ -584,7 +592,7 @@ int FfmpegCamera::OpenFfmpeg() {
Debug ( 1, "Calling avcodec_open2" );
if ( avcodec_open2(mAudioCodecContext, mAudioCodec, 0) < 0 ) {
#endif
- Error( "Unable to open codec for video stream from %s", mPath.c_str() );
+ Error( "Unable to open codec for audio stream from %s", mPath.c_str() );
return -1;
}
Debug(2, "Opened audio codec");
From aaef151815a1909dfba7153aaf7fa7cbf0a72193 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Fri, 5 Apr 2019 13:18:06 -0400
Subject: [PATCH 25/40] ZM_VERSION is a constant not a scalar variable
---
scripts/ZoneMinder/lib/ZoneMinder/Control/Dahua.pm | 2 +-
scripts/ZoneMinder/lib/ZoneMinder/Control/PSIA.pm | 2 +-
scripts/ZoneMinder/lib/ZoneMinder/Control/Trendnet.pm | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/Dahua.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/Dahua.pm
index e274aaaf7..e55a6da1c 100644
--- a/scripts/ZoneMinder/lib/ZoneMinder/Control/Dahua.pm
+++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/Dahua.pm
@@ -84,7 +84,7 @@ sub open
use LWP::UserAgent;
$self->{ua} = LWP::UserAgent->new(keep_alive => 1);
- $self->{ua}->agent("ZoneMinder Control Agent/".$ZoneMinder::Base::ZM_VERSION);
+ $self->{ua}->agent("ZoneMinder Control Agent/".ZoneMinder::Base::ZM_VERSION);
$self->{state} = 'closed';
# credentials: ("ip:port" (no prefix!), realm (string), username (string), password (string)
$self->{ua}->credentials($ADDRESS, $REALM, $USERNAME, $PASSWORD);
diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/PSIA.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/PSIA.pm
index fe067fe1f..438c5cff5 100644
--- a/scripts/ZoneMinder/lib/ZoneMinder/Control/PSIA.pm
+++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/PSIA.pm
@@ -40,7 +40,7 @@ sub open
use LWP::UserAgent;
$self->{ua} = LWP::UserAgent->new;
- $self->{ua}->agent( "ZoneMinder Control Agent/".$ZoneMinder::Base::ZM_VERSION );
+ $self->{ua}->agent( "ZoneMinder Control Agent/".ZoneMinder::Base::ZM_VERSION );
$self->{state} = 'closed';
Debug( "sendCmd credentials control address:'".$ADDRESS
."' realm:'" . $REALM
diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/Trendnet.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/Trendnet.pm
index 4ee710297..c57fc5c62 100644
--- a/scripts/ZoneMinder/lib/ZoneMinder/Control/Trendnet.pm
+++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/Trendnet.pm
@@ -45,7 +45,7 @@ sub open {
use LWP::UserAgent;
$self->{ua} = LWP::UserAgent->new;
- $self->{ua}->agent('ZoneMinder Control Agent/'.$ZoneMinder::Base::ZM_VERSION);
+ $self->{ua}->agent('ZoneMinder Control Agent/'.ZoneMinder::Base::ZM_VERSION);
$self->{state} = 'closed';
# credentials: ("ip:port" (no prefix!), realm (string), username (string), password (string)
Debug ( "sendCmd credentials control address:'".$ADDRESS
From e1873b1693b4b15b6df184f729538c69515f6975 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Fri, 5 Apr 2019 15:17:13 -0400
Subject: [PATCH 26/40] debug response content
---
scripts/ZoneMinder/lib/ZoneMinder/Control/Trendnet.pm | 2 ++
1 file changed, 2 insertions(+)
diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/Trendnet.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/Trendnet.pm
index c57fc5c62..4afba372c 100644
--- a/scripts/ZoneMinder/lib/ZoneMinder/Control/Trendnet.pm
+++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/Trendnet.pm
@@ -120,6 +120,7 @@ sub sendCmd {
Debug('sendCmd command: ' . $url);
if ( $res->is_success ) {
+ Debug($res->content);
return !undef;
}
Error("Error check failed: '".$res->status_line()."' cmd:'".$cmd."'");
@@ -155,6 +156,7 @@ sub sendCmdPost {
Debug("sendCmdPost credentials control to: $PROTOCOL$ADDRESS$url realm:'" . $REALM . "' username:'" . $USERNAME . "' password:'".$PASSWORD."'");
if ( $res->is_success ) {
+ Debug($res->content);
return !undef;
}
Error("sendCmdPost Error check failed: '".$res->status_line()."' cmd:");
From aa83239069431ad387c43fa659a4204709832dd8 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Fri, 5 Apr 2019 15:18:03 -0400
Subject: [PATCH 27/40] rework zmcontrol.pl. If command is given and server is
not up, use zmdc.pl to start it. Give up after 10 seconds.
---
scripts/zmcontrol.pl.in | 185 ++++++++++++++++++++--------------------
1 file changed, 91 insertions(+), 94 deletions(-)
diff --git a/scripts/zmcontrol.pl.in b/scripts/zmcontrol.pl.in
index b0388bcf3..f83bc82d4 100644
--- a/scripts/zmcontrol.pl.in
+++ b/scripts/zmcontrol.pl.in
@@ -30,7 +30,7 @@ use autouse 'Pod::Usage'=>qw(pod2usage);
use POSIX qw/strftime EPIPE/;
use Socket;
#use Data::Dumper;
-use Module::Load::Conditional qw{can_load};;
+use Module::Load::Conditional qw{can_load};
use constant MAX_CONNECT_DELAY => 15;
use constant MAX_COMMAND_WAIT => 1800;
@@ -43,7 +43,7 @@ delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
logInit();
-my $arg_string = join( " ", @ARGV );
+my $arg_string = join(' ', @ARGV);
my $id;
my %options;
@@ -64,22 +64,46 @@ GetOptions(
) or pod2usage(-exitstatus => -1);
if ( !$id ) {
- print( STDERR "Please give a valid monitor id\n" );
+ print(STDERR "Please give a valid monitor id\n");
pod2usage(-exitstatus => -1);
}
( $id ) = $id =~ /^(\w+)$/;
-Debug("zmcontrol: arg string: $arg_string");
my $sock_file = $Config{ZM_PATH_SOCKS}.'/zmcontrol-'.$id.'.sock';
+Debug("zmcontrol: arg string: $arg_string sock file $sock_file");
-socket(CLIENT, PF_UNIX, SOCK_STREAM, 0)
- or Fatal("Can't open socket: $!");
+socket(CLIENT, PF_UNIX, SOCK_STREAM, 0) or Fatal("Can't open socket: $!");
my $saddr = sockaddr_un($sock_file);
-my $server_up = connect(CLIENT, $saddr);
-if ( !$server_up ) {
+
+if ( $options{command} ) {
+ # Have a command, so we are the client, connect to the server and send it.
+
+ my $tries = 10;
+ my $server_up;
+ while ( $tries and ! ( $server_up = connect(CLIENT, $saddr) ) ) {
+ Debug("Failed to connect to $server_up at $sock_file");
+ runCommand("zmdc.pl start zmcontrol.pl --id=$id");
+ sleep 1;
+ $tries -= 1;
+ }
+ if ( $server_up ) {
+ # The server is there, connect to it
+ #print( "Writing commands\n" );
+ CLIENT->autoflush();
+
+ if ( $options{command} ) {
+ my $message = jsonEncode(\%options);
+ print(CLIENT $message);
+ }
+ shutdown(CLIENT, 1);
+ } else {
+ Error("Unable to connect to zmcontrol server at $sock_file");
+ }
+} else {
+
# The server isn't there
my $monitor = zmDbGetMonitorAndControl($id);
if ( !$monitor ) {
@@ -113,99 +137,72 @@ if ( !$server_up ) {
Fatal("Can't load ZoneMinder::Control::$protocol\n$Module::Load::Conditional::ERROR");
}
- if ( my $cpid = fork() ) {
- logReinit();
+ Info("Control server $id/$protocol starting at "
+ .strftime('%y/%m/%d %H:%M:%S', localtime())
+ );
- # Parent process just sleep and fall through
- socket(CLIENT, PF_UNIX, SOCK_STREAM, 0)
- or die("Can't open socket: $!");
- my $attempts = 0;
- while ( !connect(CLIENT, $saddr) ) {
- $attempts++;
- Fatal("Can't connect: $! after $attempts attempts to $sock_file") if $attempts > MAX_CONNECT_DELAY;
- sleep(1);
- }
- } elsif ( defined($cpid) ) {
- close(STDOUT);
- close(STDERR);
+ $0 = $0." --id=$id";
- setpgrp();
+ my $control = "ZoneMinder::Control::$protocol"->new($id);
+ my $control_key = $control->getKey();
+ $control->loadMonitor();
- logReinit();
+ $control->open();
- Info("Control server $id/$protocol starting at "
- .strftime('%y/%m/%d %H:%M:%S', localtime())
- );
-
- $0 = $0." --id $id";
-
- my $control = "ZoneMinder::Control::$protocol"->new($id);
- my $control_key = $control->getKey();
- $control->loadMonitor();
-
- $control->open();
-
- socket(SERVER, PF_UNIX, SOCK_STREAM, 0)
- or Fatal("Can't open socket: $!");
- unlink($sock_file);
- bind(SERVER, $saddr) or Fatal("Can't bind: $!");
- listen(SERVER, SOMAXCONN) or Fatal("Can't listen: $!");
-
- my $rin = '';
- vec( $rin, fileno(SERVER), 1 ) = 1;
- my $win = $rin;
- my $ein = $win;
- my $timeout = MAX_COMMAND_WAIT;
- while( 1 ) {
- my $nfound = select(my $rout = $rin, undef, undef, $timeout);
- if ( $nfound > 0 ) {
- if ( vec( $rout, fileno(SERVER), 1 ) ) {
- my $paddr = accept(CLIENT, SERVER);
- my $message = ;
-
- next if !$message;
-
- my $params = jsonDecode($message);
- #Debug( Dumper( $params ) );
-
- my $command = $params->{command};
- close( CLIENT );
- if ( $command eq 'quit' ) {
- last;
- }
- $control->$command($params);
- } else {
- Fatal('Bogus descriptor');
- }
- } elsif ( $nfound < 0 ) {
- if ( $! == EPIPE ) {
- Error("Can't select: $!");
- } else {
- Fatal("Can't select: $!");
- }
- } else {
- #print( "Select timed out\n" );
- last;
- }
- } # end while forever
- Info("Control server $id/$protocol exiting");
- unlink($sock_file);
- $control->close();
- exit(0);
- } else {
- Fatal("Can't fork: $!");
+ # If we have a command when starting up, then do it.
+ if ( $options{command} ) {
+ my $command = $options{command};
+ $control->$command(\%options);
}
+
+ socket(SERVER, PF_UNIX, SOCK_STREAM, 0) or Fatal("Can't open socket: $!");
+ unlink($sock_file);
+ bind(SERVER, $saddr) or Fatal("Can't bind: $!");
+ listen(SERVER, SOMAXCONN) or Fatal("Can't listen: $!");
+
+ my $rin = '';
+ vec( $rin, fileno(SERVER), 1 ) = 1;
+ my $win = $rin;
+ my $ein = $win;
+ my $timeout = MAX_COMMAND_WAIT;
+ while( 1 ) {
+ my $nfound = select(my $rout = $rin, undef, undef, $timeout);
+ if ( $nfound > 0 ) {
+ if ( vec( $rout, fileno(SERVER), 1 ) ) {
+ my $paddr = accept(CLIENT, SERVER);
+ my $message = ;
+
+ next if !$message;
+
+ my $params = jsonDecode($message);
+ #Debug( Dumper( $params ) );
+
+ my $command = $params->{command};
+ close( CLIENT );
+ if ( $command eq 'quit' ) {
+ last;
+ }
+ $control->$command($params);
+ } else {
+ Fatal('Bogus descriptor');
+ }
+ } elsif ( $nfound < 0 ) {
+ if ( $! == EPIPE ) {
+ Error("Can't select: $!");
+ } else {
+ Fatal("Can't select: $!");
+ }
+ } else {
+ #print( "Select timed out\n" );
+ last;
+ }
+ } # end while forever
+ Info("Control server $id/$protocol exiting");
+ unlink($sock_file);
+ $control->close();
+ exit(0);
} # end if !server up
-# The server is there, connect to it
-#print( "Writing commands\n" );
-CLIENT->autoflush();
-
-if ( $options{command} ) {
- my $message = jsonEncode(\%options);
- print(CLIENT $message);
-}
-shutdown(CLIENT, 1);
exit(0);
From 381f526d66874703b877a315e108a6d4c82cb4a8 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Fri, 5 Apr 2019 15:18:20 -0400
Subject: [PATCH 28/40] spacing
---
web/includes/control_functions.php | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/web/includes/control_functions.php b/web/includes/control_functions.php
index bea235668..77240df49 100644
--- a/web/includes/control_functions.php
+++ b/web/includes/control_functions.php
@@ -735,29 +735,29 @@ function buildControlCommand( $monitor ) {
return( $ctrlCommand );
}
-function sendControlCommand($mid,$command) {
+function sendControlCommand($mid, $command) {
// Either connects to running zmcontrol.pl or runs zmcontrol.pl to send the command.
- $socket = socket_create( AF_UNIX, SOCK_STREAM, 0 );
+ $socket = socket_create(AF_UNIX, SOCK_STREAM, 0);
if ( $socket < 0 ) {
- Fatal( 'socket_create() failed: '.socket_strerror($socket) );
+ Fatal('socket_create() failed: '.socket_strerror($socket));
}
$sockFile = ZM_PATH_SOCKS.'/zmcontrol-'.$mid.'.sock';
- if ( @socket_connect( $socket, $sockFile ) ) {
+ if ( @socket_connect($socket, $sockFile) ) {
$options = array();
- foreach ( explode( ' ', $command ) as $option ) {
- if ( preg_match( '/--([^=]+)(?:=(.+))?/', $option, $matches ) ) {
+ foreach ( explode(' ', $command) as $option ) {
+ if ( preg_match('/--([^=]+)(?:=(.+))?/', $option, $matches) ) {
$options[$matches[1]] = $matches[2]?$matches[2]:1;
}
}
- $optionString = jsonEncode( $options );
- if ( !socket_write( $socket, $optionString ) ) {
- Fatal( "Can't write to control socket: ".socket_strerror(socket_last_error($socket)) );
+ $optionString = jsonEncode($options);
+ if ( !socket_write($socket, $optionString) ) {
+ Fatal("Can't write to control socket: ".socket_strerror(socket_last_error($socket)));
}
- socket_close( $socket );
+ socket_close($socket);
} else if ( $command != 'quit' ) {
$command .= ' --id='.$mid;
// Can't connect so use script
- $ctrlOutput = exec( escapeshellcmd( $command ) );
+ $ctrlOutput = exec(escapeshellcmd($command));
}
-} // end function sendControlCommand( $mid, $command )
+} // end function sendControlCommand($mid, $command)
From f719dd9acc4b042be9b56999be179fabbe166b83 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Sun, 7 Apr 2019 10:29:02 -0400
Subject: [PATCH 29/40] always commit buffered db_frames when we have a new max
score image or alarm cause image
---
src/zm_event.cpp | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/zm_event.cpp b/src/zm_event.cpp
index 7b8b446d4..330f421eb 100644
--- a/src/zm_event.cpp
+++ b/src/zm_event.cpp
@@ -538,6 +538,7 @@ void Event::AddFrame(Image *image, struct timeval timestamp, int score, Image *a
}
frames++;
+ bool write_to_db = false;
if ( monitor->GetOptSaveJPEGs() & 1 ) {
static char event_file[PATH_MAX];
@@ -549,10 +550,12 @@ void Event::AddFrame(Image *image, struct timeval timestamp, int score, Image *a
} else {
//If this is the first frame, we should add a thumbnail to the event directory
if ( (frames == 1) || (score > (int)max_score) ) {
+ write_to_db = true; // web ui might show this as thumbnail, so db needs to know about it.
WriteFrameImage(image, timestamp, snapshot_file);
}
// The first frame with a score will be the frame that alarmed the event
if ( (!alarm_frame_written) && (score > 0) ) {
+ write_to_db = true; // OD processing will need it, so the db needs to know about it
alarm_frame_written = true;
WriteFrameImage(image, timestamp, alarm_file);
}
@@ -574,7 +577,7 @@ void Event::AddFrame(Image *image, struct timeval timestamp, int score, Image *a
static char sql[ZM_SQL_MED_BUFSIZ];
frame_data.push(new Frame(id, frames, frame_type, timestamp, delta_time, score));
- if ( frame_data.size() > 20 ) {
+ if ( write_to_db || ( frame_data.size() > 20 ) ) {
WriteDbFrames();
Debug(1, "Adding 20 frames to DB");
last_db_frame = frames;
From d776f63bd85bc8a56f29115dcaafb2815072d260 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Sun, 7 Apr 2019 17:23:39 -0400
Subject: [PATCH 30/40] Change MonitorIds from TinyText to TEXT. Fixes #2569
---
db/zm_create.sql.in | 2 +-
db/zm_update-1.33.6.sql | 1 +
version | 2 +-
3 files changed, 3 insertions(+), 2 deletions(-)
create mode 100644 db/zm_update-1.33.6.sql
diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in
index 1eaca832b..c197d09ab 100644
--- a/db/zm_create.sql.in
+++ b/db/zm_create.sql.in
@@ -639,7 +639,7 @@ CREATE TABLE `Users` (
`Devices` enum('None','View','Edit') NOT NULL default 'None',
`System` enum('None','View','Edit') NOT NULL default 'None',
`MaxBandwidth` varchar(16),
- `MonitorIds` tinytext,
+ `MonitorIds` text,
PRIMARY KEY (`Id`),
UNIQUE KEY `UC_Username` (`Username`)
) ENGINE=@ZM_MYSQL_ENGINE@;
diff --git a/db/zm_update-1.33.6.sql b/db/zm_update-1.33.6.sql
new file mode 100644
index 000000000..159f80ac6
--- /dev/null
+++ b/db/zm_update-1.33.6.sql
@@ -0,0 +1 @@
+ALTER TABLE Users MODIFY MonitorIds text;
diff --git a/version b/version
index ad5831d4d..170749774 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-1.33.5
+1.33.6
From 4b2fe5c3c7fb50d590e354afe7642e301d024c5e Mon Sep 17 00:00:00 2001
From: Andrew Bauer
Date: Sun, 7 Apr 2019 18:21:52 -0500
Subject: [PATCH 31/40] Update zoneminder.spec
---
distros/redhat/zoneminder.spec | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec
index 1f0352fc4..440b05acc 100644
--- a/distros/redhat/zoneminder.spec
+++ b/distros/redhat/zoneminder.spec
@@ -23,7 +23,7 @@
%global _hardened_build 1
Name: zoneminder
-Version: 1.33.4
+Version: 1.33.6
Release: 1%{?dist}
Summary: A camera monitoring and analysis tool
Group: System Environment/Daemons
@@ -410,11 +410,14 @@ EOF
%dir %attr(755,nginx,nginx) %{_localstatedir}/spool/zoneminder-upload
%changelog
+* Sun Apr 07 2019 Andrew Bauer - 1.33.6-1
+- Bump to 1.33.6 Development
+
* Sat Mar 30 2019 Andrew Bauer - 1.33.4-1
-- Bump tp 1.33.4 Development
+- Bump to 1.33.4 Development
* Tue Dec 11 2018 Andrew Bauer - 1.33.0-1
-- Bump tp 1.33.0 Development
+- Bump to 1.33.0 Development
* Sat Dec 08 2018 Andrew Bauer - 1.32.3-1
- 1.32.3 Release
From 3c57d79669ecd33086c0c886f5381488e0cd47fc Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Mon, 8 Apr 2019 10:04:26 -0400
Subject: [PATCH 32/40] Go back to using video_first_dts
---
src/zm_videostore.cpp | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp
index 8b307ed7e..51e4805ef 100644
--- a/src/zm_videostore.cpp
+++ b/src/zm_videostore.cpp
@@ -93,7 +93,6 @@ VideoStore::VideoStore(
oc->metadata = pmetadata;
out_format = oc->oformat;
-
video_out_codec = avcodec_find_encoder(video_in_ctx->codec_id);
if ( !video_out_codec ) {
#if (LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 11, 0) && (LIBAVFORMAT_VERSION_MICRO >= 100))
@@ -870,7 +869,7 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt) {
dumpPacket(video_in_stream, ipkt, "input packet");
int64_t duration;
- if ( ipkt->duration && ( ipkt->duration != AV_NOPTS_VALUE ) ) {
+ if ( ipkt->duration != AV_NOPTS_VALUE ) {
duration = av_rescale_q(
ipkt->duration,
video_in_stream->time_base,
@@ -929,8 +928,9 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt) {
}
// Just because the in stream wraps, doesn't mean the out needs to. Really, if we are limiting ourselves to 10min segments I can't imagine every wrapping in the out. So need to handle in wrap, without causing out wrap.
if ( ipkt->dts != AV_NOPTS_VALUE ) {
-#if 0
- if ( (!video_first_dts) && ( ipkt->dts >= 0 ) ) {
+#if 1
+ if ( (!video_first_dts) ) {
+ // && ( ipkt->dts >= 0 ) ) {
// This is the first packet.
opkt.dts = 0;
Debug(1, "Starting video first_dts will become (%" PRId64 ")", ipkt->dts);
@@ -938,14 +938,14 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt) {
} else {
#endif
opkt.dts = av_rescale_q(
- ipkt->dts - video_first_pts,
+ ipkt->dts - video_first_dts,
video_in_stream->time_base,
video_out_stream->time_base
);
Debug(3, "opkt.dts = %" PRId64 " from ipkt->dts(%" PRId64 ") - first_pts(%" PRId64 ")",
- opkt.dts, ipkt->dts, video_first_pts);
+ opkt.dts, ipkt->dts, video_first_dts);
video_last_dts = ipkt->dts;
-#if 0
+#if 1
}
#endif
if ( opkt.dts > opkt.pts ) {
From e81c216b4a8d64670f68affc9d6bd12689e23fac Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Mon, 8 Apr 2019 13:51:13 -0400
Subject: [PATCH 33/40] add more fields in dump_codec.
---
src/zm_ffmpeg.cpp | 26 +++++++++++++++-----------
1 file changed, 15 insertions(+), 11 deletions(-)
diff --git a/src/zm_ffmpeg.cpp b/src/zm_ffmpeg.cpp
index 63c0c9aa3..d49210cbf 100644
--- a/src/zm_ffmpeg.cpp
+++ b/src/zm_ffmpeg.cpp
@@ -320,7 +320,8 @@ void zm_dump_codecpar ( const AVCodecParameters *par ) {
#endif
void zm_dump_codec(const AVCodecContext *codec) {
- Debug(1, "Dumping codec_context codec_type(%d) codec_id(%d) width(%d) height(%d) timebase(%d/%d) format(%s)",
+ Debug(1, "Dumping codec_context codec_type(%d) codec_id(%d) width(%d) height(%d) timebase(%d/%d) format(%s)\n"
+ "gop_size %d max_b_frames %d me_cmp %d me_range %d qmin %d qmax %d",
codec->codec_type,
codec->codec_id,
codec->width,
@@ -328,11 +329,17 @@ void zm_dump_codec(const AVCodecContext *codec) {
codec->time_base.num,
codec->time_base.den,
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
- (codec->pix_fmt == AV_PIX_FMT_NONE ? "none" : av_get_pix_fmt_name(codec->pix_fmt))
+ (codec->pix_fmt == AV_PIX_FMT_NONE ? "none" : av_get_pix_fmt_name(codec->pix_fmt)),
#else
- "unsupported on avconv"
+ "unsupported on avconv",
#endif
-);
+ codec->gop_size,
+ codec->max_b_frames,
+ codec->me_cmp,
+ codec->me_range,
+ codec->qmin,
+ codec->qmax
+ );
}
/* "user interface" functions */
@@ -356,9 +363,9 @@ 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 codec timebase: %d/%d",
- st->codec_info_nb_frames, codec->frame_size, st->time_base.num, st->time_base.den,
- st->codec->time_base.num, st->codec->time_base.den
+ Debug(1, "frames:%d, frame_size:%d stream timebase: %d/%d",
+ st->codec_info_nb_frames, codec->frame_size,
+ st->time_base.num, st->time_base.den
);
avcodec_string(buf, sizeof(buf), st->codec, is_output);
Debug(1, "codec: %s", buf);
@@ -377,17 +384,14 @@ void zm_dump_stream_format(AVFormatContext *ic, int i, int index, int is_output)
display_aspect_ratio.num, display_aspect_ratio.den);
}
- if ( st->codec->codec_type == AVMEDIA_TYPE_VIDEO ) {
+ if ( codec->codec_type == AVMEDIA_TYPE_VIDEO ) {
int fps = st->avg_frame_rate.den && st->avg_frame_rate.num;
int tbn = st->time_base.den && st->time_base.num;
- int tbc = st->codec->time_base.den && st->codec->time_base.num;
if (fps)
zm_log_fps(av_q2d(st->avg_frame_rate), "fps");
if (tbn)
zm_log_fps(1 / av_q2d(st->time_base), "stream tb numerator");
- if (tbc)
- zm_log_fps(1 / av_q2d(st->codec->time_base), "codec time base:");
}
if (st->disposition & AV_DISPOSITION_DEFAULT)
From accaeadb188aaabd9ea07ea4bf2c705f33a59ae8 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Mon, 8 Apr 2019 13:51:41 -0400
Subject: [PATCH 34/40] code cleanup. dump_codecs
---
src/zm_ffmpeg_camera.cpp | 30 +++++++++++-------------------
1 file changed, 11 insertions(+), 19 deletions(-)
diff --git a/src/zm_ffmpeg_camera.cpp b/src/zm_ffmpeg_camera.cpp
index da25b5f62..152f426f2 100644
--- a/src/zm_ffmpeg_camera.cpp
+++ b/src/zm_ffmpeg_camera.cpp
@@ -535,31 +535,23 @@ int FfmpegCamera::OpenFfmpeg() {
zm_dump_stream_format(mFormatContext, mVideoStreamId, 0, 0);
// Open the codec
#if !LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 8, 0)
- Debug(1, "Calling avcodec_open");
- if ( avcodec_open(mVideoCodecContext, mVideoCodec) < 0 )
+ ret = avcodec_open(mVideoCodecContext, mVideoCodec);
#else
- Debug(1, "Calling avcodec_open2");
- if ( avcodec_open2(mVideoCodecContext, mVideoCodec, &opts) < 0 )
+ ret = avcodec_open2(mVideoCodecContext, mVideoCodec, &opts);
#endif
- {
- AVDictionaryEntry *e = NULL;
- while ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
- Warning( "Option %s not recognized by ffmpeg", e->key);
- }
- Error( "Unable to open codec for video stream from %s", mPath.c_str() );
+ AVDictionaryEntry *e = NULL;
+ while ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
+ Warning( "Option %s not recognized by ffmpeg", e->key);
+ }
+ if ( ret < 0 ) {
+ Error("Unable to open codec for video stream from %s", mPath.c_str());
av_dict_free(&opts);
return -1;
- } else {
-
- AVDictionaryEntry *e = NULL;
- if ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
- Warning( "Option %s not recognized by ffmpeg", e->key);
- }
- av_dict_free(&opts);
}
+ zm_dump_codec(mVideoCodecContext);
}
- if (mVideoCodecContext->hwaccel != NULL) {
+ if ( mVideoCodecContext->hwaccel != NULL ) {
Debug(1, "HWACCEL in use");
} else {
Debug(1, "HWACCEL not in use");
@@ -595,7 +587,7 @@ int FfmpegCamera::OpenFfmpeg() {
Error( "Unable to open codec for audio stream from %s", mPath.c_str() );
return -1;
}
- Debug(2, "Opened audio codec");
+ zm_dump_codec(mAudioCodecContext);
} // end if find decoder
} // end if have audio_context
From 7f2440177b2f9f5752809a140e4dc3b91c6228ba Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Mon, 8 Apr 2019 13:51:55 -0400
Subject: [PATCH 35/40] remove duplicate dump_codec
---
src/zm_videostore.cpp | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp
index 51e4805ef..997b27cd2 100644
--- a/src/zm_videostore.cpp
+++ b/src/zm_videostore.cpp
@@ -119,8 +119,6 @@ VideoStore::VideoStore(
if ( ret < 0 ) {
Error("Could not initialize video_out_ctx parameters");
return;
- } else {
- zm_dump_codec(video_out_ctx);
}
#else
video_out_stream = avformat_new_stream(oc, NULL);
From 1b98f3529f7b60dd55e5e6860ac21bf503a9edf3 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Mon, 8 Apr 2019 14:18:59 -0400
Subject: [PATCH 36/40] allow non-increasing dts in muxer
---
src/zm_videostore.cpp | 24 +++++++++++++++++-------
1 file changed, 17 insertions(+), 7 deletions(-)
diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp
index 51e4805ef..da245b14c 100644
--- a/src/zm_videostore.cpp
+++ b/src/zm_videostore.cpp
@@ -92,6 +92,7 @@ VideoStore::VideoStore(
oc->metadata = pmetadata;
out_format = oc->oformat;
+ out_format->flags |= AVFMT_TS_NONSTRICT; // allow non increasing dts
video_out_codec = avcodec_find_encoder(video_in_ctx->codec_id);
if ( !video_out_codec ) {
@@ -926,17 +927,18 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt) {
opkt.pts = 0;
//AV_NOPTS_VALUE;
}
- // Just because the in stream wraps, doesn't mean the out needs to. Really, if we are limiting ourselves to 10min segments I can't imagine every wrapping in the out. So need to handle in wrap, without causing out wrap.
+ // Just because the in stream wraps, doesn't mean the out needs to.
+ // Really, if we are limiting ourselves to 10min segments I can't imagine every wrapping in the out.
+ // So need to handle in wrap, without causing out wrap.
+
if ( ipkt->dts != AV_NOPTS_VALUE ) {
-#if 1
- if ( (!video_first_dts) ) {
+ if ( !video_first_dts ) {
// && ( ipkt->dts >= 0 ) ) {
// This is the first packet.
opkt.dts = 0;
Debug(1, "Starting video first_dts will become (%" PRId64 ")", ipkt->dts);
video_first_dts = ipkt->dts;
} else {
-#endif
opkt.dts = av_rescale_q(
ipkt->dts - video_first_dts,
video_in_stream->time_base,
@@ -944,10 +946,7 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt) {
);
Debug(3, "opkt.dts = %" PRId64 " from ipkt->dts(%" PRId64 ") - first_pts(%" PRId64 ")",
opkt.dts, ipkt->dts, video_first_dts);
- video_last_dts = ipkt->dts;
-#if 1
}
-#endif
if ( opkt.dts > opkt.pts ) {
Debug(1,
"opkt.dts(%" PRId64 ") must be <= opkt.pts(%" PRId64 "). Decompression must happen "
@@ -960,6 +959,17 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt) {
opkt.dts = 0;
}
+# if 0
+ if ( opkt.dts <= video_out_stream->cur_dts ) {
+ Warning("Fixing non-monotonic dts/pts dts %" PRId64 " pts %" PRId64 " stream %" PRId64,
+ opkt.dts, opkt.pts, video_out_stream->cur_dts);
+ opkt.dts = video_out_stream->cur_dts + 1;
+ if ( opkt.dts > opkt.pts ) {
+ opkt.pts = opkt.dts;
+ }
+ }
+#endif
+
opkt.flags = ipkt->flags;
opkt.pos = -1;
opkt.data = ipkt->data;
From 3abf263e7a9bf206644d3576afbdcb73c416139f Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Mon, 8 Apr 2019 16:57:41 -0400
Subject: [PATCH 37/40] fixup half-merged changes to filter to view in
montagereview
---
scripts/ZoneMinder/lib/ZoneMinder/Control.pm | 2 +-
web/api/app/Plugin/Crud | 2 +-
web/lang/en_gb.php | 1 +
web/skins/classic/views/filter.php | 4 ++--
4 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control.pm
index efd17abcd..bbc06a884 100644
--- a/scripts/ZoneMinder/lib/ZoneMinder/Control.pm
+++ b/scripts/ZoneMinder/lib/ZoneMinder/Control.pm
@@ -67,7 +67,7 @@ sub AUTOLOAD {
if ( exists($self->{$name}) ) {
return $self->{$name};
}
- Error("Can't access $name member of object of class $class");
+ Error("Can't access $name $AUTOLOAD member of object of class $class");
}
sub getKey {
diff --git a/web/api/app/Plugin/Crud b/web/api/app/Plugin/Crud
index c3976f147..0bd63fb46 160000
--- a/web/api/app/Plugin/Crud
+++ b/web/api/app/Plugin/Crud
@@ -1 +1 @@
-Subproject commit c3976f1478c681b0bbc132ec3a3e82c3984eeed5
+Subproject commit 0bd63fb464957080ead342db58ca9e01532cf1ef
diff --git a/web/lang/en_gb.php b/web/lang/en_gb.php
index bb5e59a88..4eb493630 100644
--- a/web/lang/en_gb.php
+++ b/web/lang/en_gb.php
@@ -782,6 +782,7 @@ $SLANG = array(
'VersionRemindNever' => 'Don\'t remind about new versions',
'VersionRemindWeek' => 'Remind again in 1 week',
'Version' => 'Version',
+ 'ViewMatches' => 'View Matches',
'VideoFormat' => 'Video Format',
'VideoGenFailed' => 'Video Generation Failed!',
'VideoGenFiles' => 'Existing Video Files',
diff --git a/web/skins/classic/views/filter.php b/web/skins/classic/views/filter.php
index 20218cb07..da965b4e9 100644
--- a/web/skins/classic/views/filter.php
+++ b/web/skins/classic/views/filter.php
@@ -406,8 +406,8 @@ if ( ZM_OPT_MESSAGE ) {
-
-
+
+
Date: Mon, 8 Apr 2019 18:40:52 -0500
Subject: [PATCH 38/40] fix eslint errors
---
web/api/app/Plugin/Crud | 2 +-
web/skins/classic/views/js/filter.js | 12 ++++++------
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/web/api/app/Plugin/Crud b/web/api/app/Plugin/Crud
index c3976f147..0bd63fb46 160000
--- a/web/api/app/Plugin/Crud
+++ b/web/api/app/Plugin/Crud
@@ -1 +1 @@
-Subproject commit c3976f1478c681b0bbc132ec3a3e82c3984eeed5
+Subproject commit 0bd63fb464957080ead342db58ca9e01532cf1ef
diff --git a/web/skins/classic/views/js/filter.js b/web/skins/classic/views/js/filter.js
index 7de029ff6..29e4dfe82 100644
--- a/web/skins/classic/views/js/filter.js
+++ b/web/skins/classic/views/js/filter.js
@@ -64,12 +64,12 @@ function updateButtons(element) {
}
function click_automove(element) {
- updateButtons(this);
- if ( this.checked ) {
- $j(this.form.elements['filter[AutoMoveTo]']).css('display','inline');
- } else {
- this.form.elements['filter[AutoMoveTo]'].hide();
- }
+ updateButtons(this);
+ if ( this.checked ) {
+ $j(this.form.elements['filter[AutoMoveTo]']).css('display', 'inline');
+ } else {
+ this.form.elements['filter[AutoMoveTo]'].hide();
+ }
}
function checkValue( element ) {
From 50dd63c21dfbc05f347784ce2d8728a928632234 Mon Sep 17 00:00:00 2001
From: Andrew Bauer
Date: Mon, 8 Apr 2019 19:58:18 -0500
Subject: [PATCH 39/40] fix eslint
---
web/skins/classic/views/js/filter.js | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/web/skins/classic/views/js/filter.js b/web/skins/classic/views/js/filter.js
index 29e4dfe82..8b6968668 100644
--- a/web/skins/classic/views/js/filter.js
+++ b/web/skins/classic/views/js/filter.js
@@ -67,9 +67,9 @@ function click_automove(element) {
updateButtons(this);
if ( this.checked ) {
$j(this.form.elements['filter[AutoMoveTo]']).css('display', 'inline');
- } else {
- this.form.elements['filter[AutoMoveTo]'].hide();
- }
+ } else {
+ this.form.elements['filter[AutoMoveTo]'].hide();
+ }
}
function checkValue( element ) {
From 37b7c32465ea85a1005d3eb120edf6fc7cfdaa80 Mon Sep 17 00:00:00 2001
From: Isaac Connor
Date: Tue, 9 Apr 2019 09:45:28 -0400
Subject: [PATCH 40/40] fix errors when no filter specified
---
web/skins/classic/views/montagereview.php | 49 ++++++++++++-----------
1 file changed, 25 insertions(+), 24 deletions(-)
diff --git a/web/skins/classic/views/montagereview.php b/web/skins/classic/views/montagereview.php
index 61cf95b21..1d05d597e 100644
--- a/web/skins/classic/views/montagereview.php
+++ b/web/skins/classic/views/montagereview.php
@@ -59,34 +59,35 @@ include('_monitor_filters.php');
$filter_bar = ob_get_contents();
ob_end_clean();
+$filter = array();
if ( isset($_REQUEST['filter']) ) {
$filter = $_REQUEST['filter'];
} else {
- if (isset($_REQUEST['minTime']) && isset($_REQUEST['maxTime']) && count($displayMonitors) != 0) {
- $filter = array(
- 'Query' => array(
- 'terms' => array(
- array('attr' => 'StartDateTime', 'op' => '>=', 'val' => $_REQUEST['minTime'], 'obr' => '1'),
- array('attr' => 'StartDateTime', 'op' => '<=', 'val' => $_REQUEST['maxTime'], 'cnj' => 'and', 'cbr' => '1'),
- )
- ),
- );
- if ( count($selected_monitor_ids) ) {
- $filter['Query']['terms'][] = (array('attr' => 'MonitorId', 'op' => 'IN', 'val' => implode(',',$selected_monitor_ids), 'cnj' => 'and'));
- } else if ( ( $group_id != 0 || isset($_SESSION['ServerFilter']) || isset($_SESSION['StorageFilter']) || isset($_SESSION['StatusFilter']) ) ) {
- # this should be redundant
- for ($i=0; $i < count($displayMonitors); $i++) {
- if ($i == '0') {
- $filter['Query']['terms'][] = array('attr' => 'MonitorId', 'op' => '=', 'val' => $displayMonitors[$i]['Id'], 'cnj' => 'and', 'obr' => '1');
- } else if ($i == (count($displayMonitors)-1)) {
- $filter['Query']['terms'][] = array('attr' => 'MonitorId', 'op' => '=', 'val' => $displayMonitors[$i]['Id'], 'cnj' => 'or', 'cbr' => '1');
- } else {
- $filter['Query']['terms'][] = array('attr' => 'MonitorId', 'op' => '=', 'val' => $displayMonitors[$i]['Id'], 'cnj' => 'or');
- }
- }
- }
-} # end if REQUEST[Filter]
+ if (isset($_REQUEST['minTime']) && isset($_REQUEST['maxTime']) && count($displayMonitors) != 0) {
+ $filter = array(
+ 'Query' => array(
+ 'terms' => array(
+ array('attr' => 'StartDateTime', 'op' => '>=', 'val' => $_REQUEST['minTime'], 'obr' => '1'),
+ array('attr' => 'StartDateTime', 'op' => '<=', 'val' => $_REQUEST['maxTime'], 'cnj' => 'and', 'cbr' => '1'),
+ )
+ ),
+ );
+ if ( count($selected_monitor_ids) ) {
+ $filter['Query']['terms'][] = (array('attr' => 'MonitorId', 'op' => 'IN', 'val' => implode(',',$selected_monitor_ids), 'cnj' => 'and'));
+ } else if ( ( $group_id != 0 || isset($_SESSION['ServerFilter']) || isset($_SESSION['StorageFilter']) || isset($_SESSION['StatusFilter']) ) ) {
+ # this should be redundant
+ for ($i=0; $i < count($displayMonitors); $i++) {
+ if ($i == '0') {
+ $filter['Query']['terms'][] = array('attr' => 'MonitorId', 'op' => '=', 'val' => $displayMonitors[$i]['Id'], 'cnj' => 'and', 'obr' => '1');
+ } else if ($i == (count($displayMonitors)-1)) {
+ $filter['Query']['terms'][] = array('attr' => 'MonitorId', 'op' => '=', 'val' => $displayMonitors[$i]['Id'], 'cnj' => 'or', 'cbr' => '1');
+ } else {
+ $filter['Query']['terms'][] = array('attr' => 'MonitorId', 'op' => '=', 'val' => $displayMonitors[$i]['Id'], 'cnj' => 'or');
+ }
+ }
+ }
+ } # end if REQUEST[Filter]
parseFilter($filter);
# This is to enable the download button
session_start();