From patchwork Fri May 12 20:28:14 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Levinson X-Patchwork-Id: 3667 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.3.129 with SMTP id 123csp490462vsd; Fri, 12 May 2017 13:28:25 -0700 (PDT) X-Received: by 10.223.151.148 with SMTP id s20mr3803761wrb.159.1494620905059; Fri, 12 May 2017 13:28:25 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1494620905; cv=none; d=google.com; s=arc-20160816; b=M+O0i0IAGkQnnUaLM27CN910l3czB1rHy9uIuwQjUniUX8C/Td66hUmTAlzjjsWg3+ pA8jNfw6zMWtUMAQx7iTJ761QuS+SuWOsHDwFhy3YGSFh4s7sw0TwOMNHHjfGnqBR4Ax TVrvau2EUC3xRgm6A9JlyWDr5N+z7HXJIiVH4Pn14RzALzYPTWDHGBbd0bUcVdFprYtK mNOfGw9lIyifB58PuXgVQcP1yw/E8X4GsjxYESV+EjY0qOmGILDj7pzY4VhFH31S0HIp nvVT84QRfsrhEdexx15XGsfn+dV3xa2ig7WdbCS1vYz7OpymJmJa6p+lvQRek6K3RItw XykQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:mime-version:user-agent:date:message-id:from:to :delivered-to:arc-authentication-results; bh=SjF3CQl2aKocJH5ITOTm0JSqEtUw7FblWN9YblYJuLQ=; b=jLzb05CNVlHNZPqIyWpnjBBNwC+J0rutTeOgKF/wys3GThX9QXOELE86Lti2b6rvHQ wj9DkAN1v9G38mMzi7rrO7fm4yRHKE5J9N7R4y4BeTKn0i5/YS0plhxaPP2OuRSUIQdL vpuU686kxMg18QE9ywpgnXBNWwf8X+MlBuy9lSFSSrSGoDZK9YV9uAz3LKprPCnqV5PZ X9C5bMwktYPxLoNoZk0CXfNbLTviFecBeztsLJrhz6YaUaPwL+B5JggZGbiBwjX9MiSa wfes6Ewa6NWgGzxCVGLWMeYqJI0jFfnBUDiWbcLBfnstecY8ADzkrAyalauWx1fbTQpQ 04jQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id 52si4811643wrv.17.2017.05.12.13.28.24; Fri, 12 May 2017 13:28:25 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id DB8756882EB; Fri, 12 May 2017 23:28:14 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from white.spiritone.com (white.spiritone.com [216.99.193.38]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 76D9E68091A for ; Fri, 12 May 2017 23:28:08 +0300 (EEST) Received: from [192.168.3.101] (184-100-204-251.ptld.qwest.net [184.100.204.251]) by white.spiritone.com (Postfix) with ESMTPSA id 8624A734057A for ; Fri, 12 May 2017 13:28:15 -0700 (PDT) To: FFmpeg development discussions and patches From: Aaron Levinson Message-ID: <72a8bacf-861b-b349-fc77-55f63fceee86@aracnet.com> Date: Fri, 12 May 2017 13:28:14 -0700 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:45.0) Gecko/20100101 Thunderbird/45.8.0 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 2/2] ffmpeg: Made execution of reap_filters() more deterministic with respect to when headers are written X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Purpose: Made execution of reap_filters() more deterministic with respect to when headers are written in relationship with the initialization of output streams and the processing of input audio and/or video frames. This change fixes a bug in ffmpeg encountered when decoding interlaced video. In some cases, ffmpeg would treat it as progressive. Detailed description of problem: Run the following command: "ffmpeg -i test8_1080i.h264 -c:v mpeg2video test8_1080i_mp2.ts". In this case, test8_1080i.h264 is an H.264-encoded file with 1080i59.94 (interlaced). Prior to the patch, the following output is generated: Input #0, h264, from 'test8_1080i.h264': Duration: N/A, bitrate: N/A Stream #0:0: Video: h264 (High), yuv420p(top first), 1920x1080 [SAR 1:1 DAR 16:9], 29.97 fps, 29.97 tbr, 1200k tbn, 59.94 tbc Stream mapping: Stream #0:0 -> #0:0 (h264 (native) -> mpeg2video (native)) Press [q] to stop, [?] for help Output #0, mpegts, to 'test8_1080i_mp2_2.ts': Metadata: encoder : Lavf57.72.100 Stream #0:0: Video: mpeg2video (Main), yuv420p, 1920x1080 [SAR 1:1 DAR 16:9], q=2-31, 200 kb/s, 29.97 fps, 90k tbn, 29.97 tbc Metadata: encoder : Lavc57.92.100 mpeg2video which demonstrates the bug. The output stream should instead look like: Stream #0:0: Video: mpeg2video (Main), yuv420p(top coded first (swapped)), 1920x1080 [SAR 1:1 DAR 16:9], q=2-31, 200 kb/s, 29.97 fps, 90k tbn, 29.97 tbc The bug is caused by the fact that reap_filters() calls init_output_stream(), which is then immediately followed by a call to check_init_output_file(), and this is all done prior to the first call to do_video_out(). An initial call to do_video_out() is necessary to populate the interlaced video information to the output stream's codecpar (mux_par->field_order in do_video_out()). However, check_init_output_file() calls avformat_write_header() prior to the initial call to do_video_out(), so field_order is populated too late, and the header is written with the default field_order value, progressive. Signed-off-by: Aaron Levinson --- ffmpeg.c | 43 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/ffmpeg.c b/ffmpeg.c index 3cd45ba665..7b044b068c 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -1434,6 +1434,7 @@ static int reap_filters(int flush) AVFilterContext *filter; AVCodecContext *enc = ost->enc_ctx; int ret = 0; + int do_check_init_output_file = 0; if (!ost->filter || !ost->filter->graph->graph) continue; @@ -1448,9 +1449,7 @@ static int reap_filters(int flush) exit_program(1); } - ret = check_init_output_file(of, ost->file_index); - if (ret < 0) - exit_program(1); + do_check_init_output_file = 1; } if (!ost->filtered_frame && !(ost->filtered_frame = av_frame_alloc())) { @@ -1526,6 +1525,44 @@ static int reap_filters(int flush) } av_frame_unref(filtered_frame); + + /* + * It is important to call check_init_output_file() here, after + * do_video_out() was called, instead of in init_output_stream(), + * as was done previously. + * If called from init_output_stream(), it is possible that not + * everything will have been fully initialized by the time that + * check_init_output_file() is called, and if + * check_init_output_file() determines that all output streams + * have been initialized, it will write the header. An example + * of initialization that depends on do_video_out() being called + * at least once is the specification of interlaced video, which + * happens in do_video_out(). This is particularly relevant when + * decoding--without processing a video frame, the interlaced + * video setting is not propagated before the header is written, + * and that causes problems. + * TODO: should probably handle interlaced video differently + * and not depend on it being setup in do_video_out(). Another + * solution would be to set it up once by examining the input + * header. + */ + if (do_check_init_output_file) { + ret = check_init_output_file(of, ost->file_index); + if (ret < 0) + exit_program(1); + do_check_init_output_file = 0; + } + } + + /* + * Can't wait too long to call check_init_output_file(). + * Otherwise, bad things start to occur. + * If didn't do it earlier, do it by the time it gets here. + */ + if (do_check_init_output_file) { + ret = check_init_output_file(of, ost->file_index); + if (ret < 0) + exit_program(1); } }