From cb33318c4ac53ee472a07d2847731da640cab64d Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Mon, 1 Apr 2019 14:02:39 -0400 Subject: [PATCH] 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