From: Anton Khirnov <anton@khirnov.net> To: ffmpeg-devel@ffmpeg.org Subject: [FFmpeg-devel] [PATCH 27/33] fftools/ffmpeg: rework initializing encoders with no frames Date: Thu, 13 Jul 2023 12:55:47 +0200 Message-ID: <20230713105553.21052-27-anton@khirnov.net> (raw) In-Reply-To: <20230713105553.21052-1-anton@khirnov.net> When no frames were passed from a filtergraph to an encoder, but the filtergraph is configured (i.e. has output parameters), encoder flush code will use those parameters to initialize the encoder in a last-ditch effort to produce some useful output. Rework this process so that it is triggered by the filtergraph, which now sends a dummy frame with parameters, but no data, to the encoder, rather than the encoder reaching backwards into the filter. This approach is more in line with the natural data flow from filters to encoders and will allow to reduce encoder-filter interactions in following commits. This code is tested by fate-adpcm-ima-cunning-trunc-t2-track1, which (as confirmed by Zane) is supposed to produce empty output. --- fftools/ffmpeg_enc.c | 22 ++--------------- fftools/ffmpeg_filter.c | 54 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 52 insertions(+), 24 deletions(-) diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c index b35dbb6290..390f1b3b57 100644 --- a/fftools/ffmpeg_enc.c +++ b/fftools/ffmpeg_enc.c @@ -1142,26 +1142,8 @@ void enc_flush(void) AVCodecContext *enc = ost->enc_ctx; OutputFile *of = output_files[ost->file_index]; - if (!enc) - continue; - - // Try to enable encoding with no input frames. - // Maybe we should just let encoding fail instead. - if (!e->opened) { - FilterGraph *fg = ost->filter->graph; - - av_log(ost, AV_LOG_WARNING, - "Finishing stream without any data written to it.\n"); - - if (!fg->graph) - continue; - - ret = enc_open(ost, NULL); - if (ret < 0) - exit_program(1); - } - - if (enc->codec_type != AVMEDIA_TYPE_VIDEO && enc->codec_type != AVMEDIA_TYPE_AUDIO) + if (!enc || !e->opened || + (enc->codec_type != AVMEDIA_TYPE_VIDEO && enc->codec_type != AVMEDIA_TYPE_AUDIO)) continue; ret = submit_encode_frame(of, ost, NULL); diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 67a5f48245..f8e64ce6cc 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -143,11 +143,17 @@ typedef struct OutputFilterPriv { int sample_rate; AVChannelLayout ch_layout; + AVRational time_base; + AVRational sample_aspect_ratio; + // those are only set if no format is specified and the encoder gives us multiple options // They point directly to the relevant lists of the encoder. const int *formats; const AVChannelLayout *ch_layouts; const int *sample_rates; + + // set to 1 after at least one frame passed through this output + int got_frame; } OutputFilterPriv; static OutputFilterPriv *ofp_from_ofilter(OutputFilter *ofilter) @@ -1576,6 +1582,9 @@ static int configure_filtergraph(FilterGraph *fg) ofp->width = av_buffersink_get_w(sink); ofp->height = av_buffersink_get_h(sink); + ofp->time_base = av_buffersink_get_time_base(sink); + ofp->sample_aspect_ratio = av_buffersink_get_sample_aspect_ratio(sink); + ofp->sample_rate = av_buffersink_get_sample_rate(sink); av_channel_layout_uninit(&ofp->ch_layout); ret = av_buffersink_get_ch_layout(sink, &ofp->ch_layout); @@ -1688,6 +1697,7 @@ int reap_filters(int flush) { /* Reap all buffers present in the buffer sinks */ for (OutputStream *ost = ost_iter(NULL); ost; ost = ost_iter(ost)) { + OutputFilterPriv *ofp; FilterGraphPriv *fgp; AVFrame *filtered_frame; AVFilterContext *filter; @@ -1697,6 +1707,7 @@ int reap_filters(int flush) continue; filter = ost->filter->filter; fgp = fgp_from_fg(ost->filter->graph); + ofp = ofp_from_ofilter(ost->filter); filtered_frame = fgp->frame; @@ -1749,6 +1760,7 @@ int reap_filters(int flush) enc_frame(ost, filtered_frame); av_frame_unref(filtered_frame); + ofp->got_frame = 1; } } @@ -1961,6 +1973,7 @@ int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference) int fg_transcode_step(FilterGraph *graph, InputStream **best_ist) { + FilterGraphPriv *fgp = fgp_from_fg(graph); int i, ret; int nb_requests, nb_requests_max = 0; InputStream *ist; @@ -1988,10 +2001,43 @@ int fg_transcode_step(FilterGraph *graph, InputStream **best_ist) return reap_filters(0); if (ret == AVERROR_EOF) { - ret = reap_filters(1); - for (i = 0; i < graph->nb_outputs; i++) - close_output_stream(graph->outputs[i]->ost); - return ret; + reap_filters(1); + for (int i = 0; i < graph->nb_outputs; i++) { + OutputFilter *ofilter = graph->outputs[i]; + OutputFilterPriv *ofp = ofp_from_ofilter(ofilter); + + // we are finished and no frames were ever seen at this output, + // at least initialize the encoder with a dummy frame + if (!ofp->got_frame) { + AVFrame *frame = fgp->frame; + + frame->time_base = ofp->time_base; + frame->format = ofp->format; + + frame->width = ofp->width; + frame->height = ofp->height; + frame->sample_aspect_ratio = ofp->sample_aspect_ratio; + + frame->sample_rate = ofp->sample_rate; + if (ofp->ch_layout.nb_channels) { + ret = av_channel_layout_copy(&frame->ch_layout, &ofp->ch_layout); + if (ret < 0) + return ret; + } + + av_assert0(!frame->buf[0]); + + av_log(ofilter->ost, AV_LOG_WARNING, + "No filtered frames for output stream, trying to " + "initialize anyway.\n"); + + enc_open(ofilter->ost, frame); + av_frame_unref(frame); + } + + close_output_stream(ofilter->ost); + } + return 0; } if (ret != AVERROR(EAGAIN)) return ret; -- 2.40.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
next prev parent reply other threads:[~2023-07-13 10:58 UTC|newest] Thread overview: 45+ messages / expand[flat|nested] mbox.gz Atom feed top 2023-07-13 10:55 [FFmpeg-devel] [PATCH 01/33] fftools/ffmpeg_mux_init: return errors from of_open() instead of aborting Anton Khirnov 2023-07-13 10:55 ` [FFmpeg-devel] [PATCH 02/33] fftools/ffmpeg_demux: return errors from ifile_open() " Anton Khirnov 2023-07-13 10:55 ` [FFmpeg-devel] [PATCH 03/33] fftools/ffmpeg_demux: drop a redundant avio_flush() Anton Khirnov 2023-07-13 10:55 ` [FFmpeg-devel] [PATCH 04/33] fftools/ffmpeg_demux: forward errors from dump_attachment() instead of aborting Anton Khirnov 2023-07-13 10:55 ` [FFmpeg-devel] [PATCH 05/33] fftools/ffmpeg_demux: add logging for -dump_attachment Anton Khirnov 2023-07-13 10:55 ` [FFmpeg-devel] [PATCH 06/33] fftools/ffmpeg: return errors from assert_file_overwrite() instead of aborting Anton Khirnov 2023-07-13 10:55 ` [FFmpeg-devel] [PATCH 07/33] fftools/ffmpeg_demux: return errors from ist_add() " Anton Khirnov 2023-07-13 10:55 ` [FFmpeg-devel] [PATCH 08/33] fftools/ffmpeg_mux_init: return errors from create_streams() " Anton Khirnov 2023-07-13 10:55 ` [FFmpeg-devel] [PATCH 09/33] fftools/ffmpeg_mux_init: improve error handling in of_add_attachments() Anton Khirnov 2023-07-13 10:55 ` [FFmpeg-devel] [PATCH 10/33] fftools/ffmpeg_mux_init: return error codes from map_*() instead of aborting Anton Khirnov 2023-07-13 10:55 ` [FFmpeg-devel] [PATCH 11/33] fftools/ffmpeg_mux_init: move allocation out of prologue Anton Khirnov 2023-07-13 10:55 ` [FFmpeg-devel] [PATCH 12/33] fftools/ffmpeg_mux_init: return error codes from ost_add() instead of aborting Anton Khirnov 2023-07-13 10:55 ` [FFmpeg-devel] [PATCH 13/33] fftools/ffmpeg_mux_init: return error codes from copy_meta() " Anton Khirnov 2023-07-13 10:55 ` [FFmpeg-devel] [PATCH 14/33] fftools/ffmpeg_mux_init: return error codes from parse_forced_key_frames() " Anton Khirnov 2023-07-13 10:55 ` [FFmpeg-devel] [PATCH 15/33] fftools/ffmpeg_mux_init: return error codes from validate_enc_avopt() " Anton Khirnov 2023-07-13 10:55 ` [FFmpeg-devel] [PATCH 16/33] fftools/ffmpeg_mux_init: improve of_add_programs() Anton Khirnov 2023-07-13 23:30 ` Michael Niedermayer 2023-07-14 9:07 ` Anton Khirnov 2023-07-14 18:12 ` Michael Niedermayer 2023-07-13 10:55 ` [FFmpeg-devel] [PATCH 17/33] fftools/ffmpeg_mux_init: return error codes from metadata processing instead of aborting Anton Khirnov 2023-07-13 10:55 ` [FFmpeg-devel] [PATCH 18/33] fftools/ffmpeg_mux_init: replace all remaining aborts with returning error codes Anton Khirnov 2023-07-13 10:55 ` [FFmpeg-devel] [PATCH 19/33] fftools/ffmpeg: return an error instead of aborting Anton Khirnov 2023-07-13 10:55 ` [FFmpeg-devel] [PATCH 20/33] fftools/ffmpeg: handle error codes from process_input_packet() Anton Khirnov 2023-07-13 10:55 ` [FFmpeg-devel] [PATCH 21/33] fftools/ffmpeg_mux: return errors from of_streamcopy() instead of aborting Anton Khirnov 2023-07-13 10:55 ` [FFmpeg-devel] [PATCH 22/33] fftools/ffmpeg_enc: return errors from enc_subtitle() " Anton Khirnov 2023-07-13 10:55 ` [FFmpeg-devel] [PATCH 23/33] fftools/ffmpeg_mux_init: drop an obsolete assignment Anton Khirnov 2023-07-13 10:55 ` [FFmpeg-devel] [PATCH 24/33] fftools/ffmpeg_mux_init: handle pixel format endianness Anton Khirnov 2023-07-13 10:55 ` [FFmpeg-devel] [PATCH 25/33] fftools/ffmpeg_filter: stop disregarding user-specified pixel format Anton Khirnov 2023-07-13 23:11 ` Michael Niedermayer 2023-07-14 9:44 ` Anton Khirnov 2023-07-14 10:20 ` Timo Rothenpieler 2023-07-14 15:47 ` Michael Niedermayer 2023-07-14 17:06 ` Anton Khirnov 2023-07-15 8:59 ` Paul B Mahol 2023-07-15 20:01 ` Michael Niedermayer 2023-07-13 10:55 ` [FFmpeg-devel] [PATCH 26/33] fftools/ffmpeg_filter: stop accessing encoder from pixfmt selection Anton Khirnov 2023-07-13 10:55 ` Anton Khirnov [this message] 2023-07-13 10:55 ` [FFmpeg-devel] [PATCH 28/33] fftools/ffmpeg_filter: only flush vsync code if encoding actually started Anton Khirnov 2023-07-13 10:55 ` [FFmpeg-devel] [PATCH 29/33] fftools/ffmpeg_enc: initialize audio/video encoders from frame parameters Anton Khirnov 2023-07-13 10:55 ` [FFmpeg-devel] [PATCH 30/33] fftools/ffmpeg_filter: make OutputFilter.filter private Anton Khirnov 2023-07-13 10:55 ` [FFmpeg-devel] [PATCH 31/33] fftools/ffmpeg: add more structure to FrameData Anton Khirnov 2023-07-13 10:55 ` [FFmpeg-devel] [PATCH 32/33] fftools/ffmpeg: rework -enc_time_base handling Anton Khirnov 2023-07-13 10:55 ` [FFmpeg-devel] [PATCH 33/33] doc/ffmpeg: fix -enc_time_base documentation Anton Khirnov 2023-07-13 12:01 ` [FFmpeg-devel] [PATCH 01/33] fftools/ffmpeg_mux_init: return errors from of_open() instead of aborting "zhilizhao(赵志立)" 2023-07-13 13:01 ` Anton Khirnov
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20230713105553.21052-27-anton@khirnov.net \ --to=anton@khirnov.net \ --cc=ffmpeg-devel@ffmpeg.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel This inbox may be cloned and mirrored by anyone: git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \ ffmpegdev@gitmailbox.com public-inbox-index ffmpegdev Example config snippet for mirrors. AGPL code for this site: git clone https://public-inbox.org/public-inbox.git