diff options
author | Anton Khirnov <anton@khirnov.net> | 2023-04-30 12:17:16 +0200 |
---|---|---|
committer | Anton Khirnov <anton@khirnov.net> | 2023-05-08 10:38:59 +0200 |
commit | c7c73a3250542dde9bb882867f1b2d9af61cc5a0 (patch) | |
tree | 628e23515214716bafd4688e6be52031f0ac47ba /fftools/ffmpeg_filter.c | |
parent | 48d8d3549a1b97d6f811b7d0bed8b0fdb6a0dc6d (diff) | |
download | ffmpeg-c7c73a3250542dde9bb882867f1b2d9af61cc5a0.tar.gz |
fftools/ffmpeg_filter: take fallback parameters from decoder, not demuxer
When an input stream terminates and no frames were successfully decoded,
filtering code will currently configure the filtergraph using demuxer
stream parameters. Use decoder parameters instead, which should be more
reliable. Also, initialize them immediately when an input stream is
bound to a filtergraph input, so that these parameters are always
available (if at all) and filtering code does not need to reach into the
decoder at some arbitrary later point.
Diffstat (limited to 'fftools/ffmpeg_filter.c')
-rw-r--r-- | fftools/ffmpeg_filter.c | 59 |
1 files changed, 53 insertions, 6 deletions
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 8c408eb7c4..3fad38f782 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -58,6 +58,19 @@ typedef struct InputFilterPriv { AVRational time_base; AVFifo *frame_queue; + + // fallback parameters to use when no input is ever sent + struct { + int format; + + int width; + int height; + AVRational sample_aspect_ratio; + + int sample_rate; + AVChannelLayout ch_layout; + } fallback; + } InputFilterPriv; static InputFilterPriv *ifp_from_ifilter(InputFilter *ifilter) @@ -225,6 +238,8 @@ static InputFilter *ifilter_alloc(FilterGraph *fg) ifilter->graph = fg; ifilter->format = -1; + ifp->fallback.format = -1; + ifp->frame_queue = av_fifo_alloc2(8, sizeof(AVFrame*), AV_FIFO_FLAG_AUTO_GROW); if (!ifp->frame_queue) report_and_exit(AVERROR(ENOMEM)); @@ -260,6 +275,9 @@ void fg_free(FilterGraph **pfg) avsubtitle_free(&sub); av_fifo_freep2(&ist->sub2video.sub_queue); } + + av_channel_layout_uninit(&ifp->fallback.ch_layout); + av_buffer_unref(&ifilter->hw_frames_ctx); av_freep(&ifilter->name); av_freep(&fg->inputs[j]); @@ -1361,6 +1379,29 @@ fail: return ret; } +int ifilter_parameters_from_dec(InputFilter *ifilter, const AVCodecContext *dec) +{ + InputFilterPriv *ifp = ifp_from_ifilter(ifilter); + + if (dec->codec_type == AVMEDIA_TYPE_VIDEO) { + ifp->fallback.format = dec->pix_fmt; + ifp->fallback.width = dec->width; + ifp->fallback.height = dec->height; + ifp->fallback.sample_aspect_ratio = dec->sample_aspect_ratio; + } else { + int ret; + + ifp->fallback.format = dec->sample_fmt; + ifp->fallback.sample_rate = dec->sample_rate; + + ret = av_channel_layout_copy(&ifp->fallback.ch_layout, &dec->ch_layout); + if (ret < 0) + return ret; + } + + return 0; +} + static int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame) { AVFrameSideData *sd; @@ -1469,12 +1510,18 @@ int ifilter_send_eof(InputFilter *ifilter, int64_t pts, AVRational tb) if (ret < 0) return ret; } else { - // the filtergraph was never configured - if (ifilter->format < 0) { - ret = ifilter_parameters_from_codecpar(ifilter, ifilter->ist->par); - if (ret < 0) - return ret; - } + // the filtergraph was never configured, use the fallback parameters + ifilter->format = ifp->fallback.format; + ifilter->sample_rate = ifp->fallback.sample_rate; + ifilter->width = ifp->fallback.width; + ifilter->height = ifp->fallback.height; + ifilter->sample_aspect_ratio = ifp->fallback.sample_aspect_ratio; + + ret = av_channel_layout_copy(&ifilter->ch_layout, + &ifp->fallback.ch_layout); + if (ret < 0) + return ret; + if (ifilter->format < 0 && (ifilter->type == AVMEDIA_TYPE_AUDIO || ifilter->type == AVMEDIA_TYPE_VIDEO)) { av_log(NULL, AV_LOG_ERROR, "Cannot determine format of input stream %d:%d after EOF\n", ifilter->ist->file_index, ifilter->ist->st->index); return AVERROR_INVALIDDATA; |