From 3a5d1ff3caa1b9cbcc32f1eaec97823f33bed373 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 13 Sep 2019 15:51:35 -0400 Subject: [PATCH 1/2] Hack in missing bits for ubuntu trusty/libav/avresample --- src/zm_ffmpeg.cpp | 50 ++++++++++++++++++++++++++++++++++++++++++- src/zm_ffmpeg.h | 18 +++++++++++++++- src/zm_videostore.cpp | 21 ++++++------------ src/zm_videostore.h | 2 +- 4 files changed, 73 insertions(+), 18 deletions(-) diff --git a/src/zm_ffmpeg.cpp b/src/zm_ffmpeg.cpp index 55fc52f73..f4a8d74f6 100644 --- a/src/zm_ffmpeg.cpp +++ b/src/zm_ffmpeg.cpp @@ -434,6 +434,35 @@ unsigned int zm_av_packet_ref( AVPacket *dst, AVPacket *src ) { dst->stream_index = src->stream_index; return 0; } +const char *avcodec_get_name(enum AVCodecID id) { + const AVCodecDescriptor *cd; + if ( id == AV_CODEC_ID_NONE) + return "none"; + cd = avcodec_descriptor_get(id); + if (cd) + return cd->name; + AVCodec *codec; + codec = avcodec_find_decoder(id); + if (codec) + return codec->name; + codec = avcodec_find_encoder(id); + if (codec) + return codec->name; + return "unknown codec"; +} + +void av_packet_rescale_ts( + AVPacket *pkt, + AVRational src_tb, + AVRational dst_tb + ) { + if ( pkt->pts != AV_NOPTS_VALUE) + pkt->pts = av_rescale_q(pkt->pts, src_tb, dst_tb); + if ( pkt->dts != AV_NOPTS_VALUE) + pkt->dts = av_rescale_q(pkt->dts, src_tb, dst_tb); + if ( pkt->duration != AV_NOPTS_VALUE) + pkt->duration = av_rescale_q(pkt->duration, src_tb, dst_tb); +} #endif bool is_video_stream( AVStream * stream ) { @@ -646,7 +675,7 @@ int zm_resample_audio( #if defined(HAVE_LIBSWRESAMPLE) SwrContext *resample_ctx, #else -#if defined(HAVE_LIBSWRESAMPLE) +#if defined(HAVE_LIBAVRESAMPLE) AVAudioResampleContext *resample_ctx, #endif #endif @@ -692,6 +721,24 @@ int zm_resample_audio( zm_dump_frame(out_frame, "Out frame after resample delay"); return 1; } +int zm_resample_get_delay( +#if defined(HAVE_LIBSWRESAMPLE) + SwrContext *resample_ctx, +#else +#if defined(HAVE_LIBAVRESAMPLE) + AVAudioResampleContext *resample_ctx, +#endif +#endif + int time_base + ) { +#if defined(HAVE_LIBSWRESAMPLE) + return sws_get_delay(resample_ctx, time_base); +#else +#if defined(HAVE_LIBAVRESAMPLE) + return avresample_available(resample_ctx); +#endif +#endif +} #endif int zm_add_samples_to_fifo(AVAudioFifo *fifo, AVFrame *frame) { @@ -727,3 +774,4 @@ int zm_get_samples_from_fifo(AVAudioFifo *fifo, AVFrame *frame) { zm_dump_frame(frame, "Out frame after fifo read"); return 1; } + diff --git a/src/zm_ffmpeg.h b/src/zm_ffmpeg.h index ff2da509c..c65bb38a0 100644 --- a/src/zm_ffmpeg.h +++ b/src/zm_ffmpeg.h @@ -337,6 +337,9 @@ void zm_dump_codecpar(const AVCodecParameters *par); #else unsigned int zm_av_packet_ref( AVPacket *dst, AVPacket *src ); #define zm_av_packet_unref( packet ) av_free_packet( packet ) + const char *avcodec_get_name(AVCodecID id); + + void av_packet_rescale_ts(AVPacket *pkt, AVRational src_tb, AVRational dst_tb); #endif #if LIBAVCODEC_VERSION_CHECK(52, 23, 0, 23, 0) #define zm_avcodec_decode_video( context, rawFrame, frameComplete, packet ) avcodec_decode_video2( context, rawFrame, frameComplete, packet ) @@ -375,15 +378,28 @@ int zm_resample_audio( #if defined(HAVE_LIBSWRESAMPLE) SwrContext *resample_ctx, #else -#if defined(HAVE_LIBSWRESAMPLE) +#if defined(HAVE_LIBAVRESAMPLE) AVAudioResampleContext *resample_ctx, #endif #endif AVFrame *in_frame, AVFrame *out_frame ); +int zm_resample_get_delay( +#if defined(HAVE_LIBSWRESAMPLE) + SwrContext *resample_ctx, +#else +#if defined(HAVE_LIBAVRESAMPLE) + AVAudioResampleContext *resample_ctx, #endif +#endif + int time_base + ); + +#endif + int zm_add_samples_to_fifo(AVAudioFifo *fifo, AVFrame *frame); int zm_get_samples_from_fifo(AVAudioFifo *fifo, AVFrame *frame); + #endif // ZM_FFMPEG_H diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index ec1459fae..d411ac8ae 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -445,21 +445,12 @@ VideoStore::~VideoStore() { /* * At the end of the file, we pass the remaining samples to * the encoder. */ - while ( swr_get_delay(resample_ctx, audio_out_ctx->sample_rate) ) { - swr_convert_frame(resample_ctx, out_frame, NULL); - int ret = av_audio_fifo_realloc(fifo, av_audio_fifo_size(fifo) + out_frame->nb_samples); - if ( ret < 0 ) { - Error("Could not reallocate FIFO to %d samples", - av_audio_fifo_size(fifo) + out_frame->nb_samples); - } else { - /** Store the new samples in the FIFO buffer. */ - ret = av_audio_fifo_write(fifo, (void **)out_frame->data, out_frame->nb_samples); - if ( ret < out_frame->nb_samples ) { - Error("Could not write data to FIFO. %d written, expecting %d. Reason %s", - ret, out_frame->nb_samples, av_make_error_string(ret).c_str()); - } + while ( zm_resample_get_delay(resample_ctx, audio_out_ctx->sample_rate) ) { + zm_resample_audio(resample_ctx, out_frame, NULL); + + if ( zm_add_samples_to_fifo(fifo, out_frame) ) { // Should probably set the frame size to what is reported FIXME - if ( av_audio_fifo_read(fifo, (void **)out_frame->data, frame_size) ) { + if ( zm_get_samples_from_fifo(fifo, out_frame) ) { if ( zm_send_frame_receive_packet(audio_out_ctx, out_frame, pkt) ) { pkt.stream_index = audio_out_stream->index; @@ -980,7 +971,7 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) { write_packet(&opkt, audio_out_stream); zm_av_packet_unref(&opkt); - if ( swr_get_delay(resample_ctx, out_frame->sample_rate) < out_frame->nb_samples) + if ( zm_resample_get_delay(resample_ctx, out_frame->sample_rate) < out_frame->nb_samples) break; // This will send a null frame, emptying out the resample buffer input_frame = NULL; diff --git a/src/zm_videostore.h b/src/zm_videostore.h index cd704403d..f8a2f2a97 100644 --- a/src/zm_videostore.h +++ b/src/zm_videostore.h @@ -47,12 +47,12 @@ private: AVCodecContext *audio_out_ctx; #ifdef HAVE_LIBSWRESAMPLE SwrContext *resample_ctx; - AVAudioFifo *fifo; #else #ifdef HAVE_LIBAVRESAMPLE AVAudioResampleContext* resample_ctx; #endif #endif + AVAudioFifo *fifo; uint8_t *converted_in_samples; const char *filename; From eafa0da06fa82b5b3d5893b49edd6e39c076ba75 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 13 Sep 2019 16:06:25 -0400 Subject: [PATCH 2/2] fixes, handle when audio codec isn't open in ffmpeg_camera --- src/zm_ffmpeg.cpp | 7 ++++--- src/zm_videostore.cpp | 13 ++++++++----- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/zm_ffmpeg.cpp b/src/zm_ffmpeg.cpp index f4a8d74f6..3622a5faa 100644 --- a/src/zm_ffmpeg.cpp +++ b/src/zm_ffmpeg.cpp @@ -718,18 +718,19 @@ int zm_resample_audio( } #endif #endif - zm_dump_frame(out_frame, "Out frame after resample delay"); + zm_dump_frame(out_frame, "Out frame after resample"); return 1; } + int zm_resample_get_delay( #if defined(HAVE_LIBSWRESAMPLE) SwrContext *resample_ctx, #else #if defined(HAVE_LIBAVRESAMPLE) - AVAudioResampleContext *resample_ctx, + AVAudioResampleContext *resample_ctx, #endif #endif - int time_base + int time_base ) { #if defined(HAVE_LIBSWRESAMPLE) return sws_get_delay(resample_ctx, time_base); diff --git a/src/zm_videostore.cpp b/src/zm_videostore.cpp index d411ac8ae..a3fde7f2c 100644 --- a/src/zm_videostore.cpp +++ b/src/zm_videostore.cpp @@ -273,9 +273,7 @@ VideoStore::VideoStore( out_frame = NULL; #if defined(HAVE_LIBSWRESAMPLE) || defined(HAVE_LIBAVRESAMPLE) resample_ctx = NULL; -#if defined(HAVE_LIBSWRESAMPLE) fifo = NULL; -#endif #endif video_first_pts = 0; video_first_dts = 0; @@ -577,11 +575,11 @@ VideoStore::~VideoStore() { #if defined(HAVE_LIBAVRESAMPLE) || defined(HAVE_LIBSWRESAMPLE) if ( resample_ctx ) { - #if defined(HAVE_LIBSWRESAMPLE) if ( fifo ) { av_audio_fifo_free(fifo); fifo = NULL; } + #if defined(HAVE_LIBSWRESAMPLE) swr_free(&resample_ctx); #else #if defined(HAVE_LIBAVRESAMPLE) @@ -636,7 +634,12 @@ bool VideoStore::setup_resampler() { // codec is already open in ffmpeg_camera audio_in_ctx = audio_in_stream->codec; audio_in_codec = reinterpret_cast(audio_in_ctx->codec); - //audio_in_codec = avcodec_find_decoder(audio_in_stream->codec->codec_id); + if ( !audio_in_codec ) { + audio_in_codec = avcodec_find_decoder(audio_in_stream->codec->codec_id); + } + if ( !audio_in_codec ) { + return false; + } #endif #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) @@ -770,13 +773,13 @@ bool VideoStore::setup_resampler() { return false; } -#if defined(HAVE_LIBSWRESAMPLE) if ( !(fifo = av_audio_fifo_alloc( audio_out_ctx->sample_fmt, audio_out_ctx->channels, 1)) ) { Error("Could not allocate FIFO"); return false; } +#if defined(HAVE_LIBSWRESAMPLE) resample_ctx = swr_alloc_set_opts(NULL, audio_out_ctx->channel_layout, audio_out_ctx->sample_fmt,