[FFmpeg-devel] [PATCH] libavformat: fix inputs initialization in mpegts muxer with filters
Michael Niedermayer
michael at niedermayer.cc
Tue Apr 23 02:07:56 EEST 2019
On Mon, Apr 22, 2019 at 11:42:57AM +0000, Andreas Håkon wrote:
>
> ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
> On Friday, 19 de April de 2019 17:08, Michael Niedermayer <michael at niedermayer.cc> wrote:
>
> > On Fri, Apr 19, 2019 at 08:23:35AM +0000, Andreas Håkon via ffmpeg-devel wrote:
> >
> > > From 936740731c17a9757aa093bdb35d9772df1e64a8 Mon Sep 17 00:00:00 2001
> > > From: Andreas Hakon andreas.hakon at protonmail.com
> > > Date: Fri, 19 Apr 2019 09:17:32 +0100
> > > Subject: [PATCH] libavformat: input init mpegts with filters v2
> > > This patch solves the initialization of the inputs when using filters
> > > (a graph filter) with the mpegts muxer.
> > > This bug seems to be generated by a simple forgetting to copy. The same code is
> > > repeated two times, but only in one case the variable inputs_done is initialized.
> >
> > > Testcase:
> > > $ ffmpeg -f mpegts -i mpeg.ts \
> > > -filter_complex "[i:100]fps=fps=25[out]" \
> > > -map "[out]" -c:v libx264 -f mpegts out.ts
> >
> > i see no difference in the output (same md5)
> > with what input file does this show a difference?
>
>
> Hi Michael,
>
> Let me to explain the problem inside the code. Here the relevant part of the
> file "/fftools/ffmpeg.c" (line #4606):
>
> ---------------------8<----------------------
> if (ost->filter && ost->filter->graph->graph) {
> if (!ost->initialized) {
> char error[1024] = {0};
> ret = init_output_stream(ost, error, sizeof(error));
> if (ret < 0) {
> av_log(NULL, AV_LOG_ERROR, "Error initializing output stream %d:%d -- %s\n",
> ost->file_index, ost->index, error);
> exit_program(1);
> }
> }
> if ((ret = transcode_from_filter(ost->filter->graph, &ist)) < 0)
> return ret;
> if (!ist)
> return 0;
> } else if (ost->filter) {
> int i;
> for (i = 0; i < ost->filter->graph->nb_inputs; i++) {
> InputFilter *ifilter = ost->filter->graph->inputs[i];
> if (!ifilter->ist->got_output && !input_files[ifilter->ist->file_index]->eof_reached) {
> ist = ifilter->ist;
> break;
> }
> }
> if (!ist) {
> ost->inputs_done = 1;
> return 0;
> }
> } else {
> av_assert0(ost->source_index >= 0);
> ist = input_streams[ost->source_index];
> }
> ---------------------8<----------------------
>
> Please, note the first block of the "if (ost->filter && ost->filter->graph->graph)".
> This block normally returns with "if (!ist) return 0;".
>
> But the second block (the one "else if (ost->filter)") returns with
> "if (!ist) {ost->inputs_done = 1; return 0;"
>
> What the second block likes to protect is when the input stream is completed.
> However, the first block doesn't do it!
>
> One difference is that the first block uses the transcode_from_filter() function.
> But that not makes difference, as the second block iterates over the inputs, and
> the function transcode_from_filter() does it too.
>
> Futhermore, the "ost->inputs_done" is used only in the function "choose_output()"
> (at line #3882 of /fftools/ffmpeg.c):
>
> ---------------------8<----------------------
> static OutputStream *choose_output(void)
> {
> int i;
> int64_t opts_min = INT64_MAX;
> OutputStream *ost_min = NULL;
>
> for (i = 0; i < nb_output_streams; i++) {
> OutputStream *ost = output_streams[i];
> int64_t opts = ost->st->cur_dts == AV_NOPTS_VALUE ? INT64_MIN :
> av_rescale_q(ost->st->cur_dts, ost->st->time_base,
> AV_TIME_BASE_Q);
> if (ost->st->cur_dts == AV_NOPTS_VALUE)
> av_log(NULL, AV_LOG_DEBUG,
> "cur_dts is invalid st:%d (%d) [init:%d i_done:%d finish:%d] (this is harmless if it occurs once at the start per stream)\n",
> ost->st->index, ost->st->id, ost->initialized, ost->inputs_done, ost->finished);
>
> if (!ost->initialized && !ost->inputs_done)
> return ost;
>
> if (!ost->finished && opts < opts_min) {
> opts_min = opts;
> ost_min = ost->unavailable ? NULL : ost;
> }
> }
> return ost_min;
> }
> ------------8<----------------------
>
> So, the case with troubles is when the output stream is selected because
> is not initilized and no inputs are completed. And without this patch
> it's possible that inputs can be completed but not marked as done.
>
> I assume that the error is a simple incorrect "copy&paste" of the original
> code, as the second block sets the "ost->inputs_done = 1;" but not the
> first one. And the difference between both blocks is that the first
> is when a filter graph is running.
>
> Please, revise the code! I hope you understand it when you look at my
> descriptions.
I would prefer to have some testcase that shows a problem
what you write basically sounds like
there are 2 similar pieces of code but they differ, so you change
one assuming the other is correct. Maybe the change is correct but
the explanation is insufficient
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
When you are offended at any man's fault, turn to yourself and study your
own failings. Then you will forget your anger. -- Epictetus
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20190423/0274b3dc/attachment.sig>
More information about the ffmpeg-devel
mailing list