From patchwork Fri Sep 9 15:01:14 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?Q2zDqW1lbnQgQsWTc2No?= X-Patchwork-Id: 494 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.140.134 with SMTP id o128csp367132vsd; Fri, 9 Sep 2016 08:01:03 -0700 (PDT) X-Received: by 10.28.157.139 with SMTP id g133mr3323112wme.82.1473433263205; Fri, 09 Sep 2016 08:01:03 -0700 (PDT) Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id gn7si3336758wjc.89.2016.09.09.08.01.00; Fri, 09 Sep 2016 08:01:03 -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 57ACB68A076; Fri, 9 Sep 2016 18:00:48 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from kimiko.pkh.me (ns3001740.ip-5-196-73.eu [5.196.73.185]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 0F71E689FAE for ; Fri, 9 Sep 2016 18:00:42 +0300 (EEST) Received: from localhost (kimiko.pkh.me [local]) by kimiko.pkh.me (OpenSMTPD) with ESMTPA id 80ea9c1d; Fri, 9 Sep 2016 15:01:16 +0000 (UTC) From: =?UTF-8?q?Cl=C3=A9ment=20B=C5=93sch?= To: ffmpeg-devel@ffmpeg.org Date: Fri, 9 Sep 2016 17:01:14 +0200 Message-Id: <20160909150114.4019-1-u@pkh.me> X-Mailer: git-send-email 2.9.3 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH] lavf: add avformat_transfer_stream_timing_info() and use it in ffmpeg 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 Cc: =?UTF-8?q?Cl=C3=A9ment=20B=C5=93sch?= Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" From: Clément Bœsch In lavf we have access to st->internal->avctx so it's a better place than in ffmpeg*.c and will allow moving to codecpar. TODO: avformat.h doxy TODO: version.h minor bump TODO: doc/APIchanges update --- ffmpeg.c | 51 +++----------------------------------------- libavformat/avformat.h | 12 +++++++++++ libavformat/utils.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 48 deletions(-) diff --git a/ffmpeg.c b/ffmpeg.c index d858407..5c487c3 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -2909,57 +2909,12 @@ static int transcode_init(void) enc_ctx->bits_per_coded_sample = dec_ctx->bits_per_coded_sample; enc_ctx->bits_per_raw_sample = dec_ctx->bits_per_raw_sample; - enc_ctx->time_base = ist->st->time_base; - /* - * Avi is a special case here because it supports variable fps but - * having the fps and timebase differe significantly adds quite some - * overhead - */ - if(!strcmp(oc->oformat->name, "avi")) { - if ( copy_tb<0 && ist->st->r_frame_rate.num - && av_q2d(ist->st->r_frame_rate) >= av_q2d(ist->st->avg_frame_rate) - && 0.5/av_q2d(ist->st->r_frame_rate) > av_q2d(ist->st->time_base) - && 0.5/av_q2d(ist->st->r_frame_rate) > av_q2d(dec_ctx->time_base) - && av_q2d(ist->st->time_base) < 1.0/500 && av_q2d(dec_ctx->time_base) < 1.0/500 - || copy_tb==2){ - enc_ctx->time_base.num = ist->st->r_frame_rate.den; - enc_ctx->time_base.den = 2*ist->st->r_frame_rate.num; - enc_ctx->ticks_per_frame = 2; - } else if ( copy_tb<0 && av_q2d(dec_ctx->time_base)*dec_ctx->ticks_per_frame > 2*av_q2d(ist->st->time_base) - && av_q2d(ist->st->time_base) < 1.0/500 - || copy_tb==0){ - enc_ctx->time_base = dec_ctx->time_base; - enc_ctx->time_base.num *= dec_ctx->ticks_per_frame; - enc_ctx->time_base.den *= 2; - enc_ctx->ticks_per_frame = 2; - } - } else if(!(oc->oformat->flags & AVFMT_VARIABLE_FPS) - && strcmp(oc->oformat->name, "mov") && strcmp(oc->oformat->name, "mp4") && strcmp(oc->oformat->name, "3gp") - && strcmp(oc->oformat->name, "3g2") && strcmp(oc->oformat->name, "psp") && strcmp(oc->oformat->name, "ipod") - && strcmp(oc->oformat->name, "f4v") - ) { - if( copy_tb<0 && dec_ctx->time_base.den - && av_q2d(dec_ctx->time_base)*dec_ctx->ticks_per_frame > av_q2d(ist->st->time_base) - && av_q2d(ist->st->time_base) < 1.0/500 - || copy_tb==0){ - enc_ctx->time_base = dec_ctx->time_base; - enc_ctx->time_base.num *= dec_ctx->ticks_per_frame; - } - } - if ( enc_ctx->codec_tag == AV_RL32("tmcd") - && dec_ctx->time_base.num < dec_ctx->time_base.den - && dec_ctx->time_base.num > 0 - && 121LL*dec_ctx->time_base.num > dec_ctx->time_base.den) { - enc_ctx->time_base = dec_ctx->time_base; - } + ret = avformat_transfer_stream_timing_info(oc->oformat, ost->st, ist->st, copy_tb); + if (ret < 0) + return ret; if (!ost->frame_rate.num) ost->frame_rate = ist->framerate; - if(ost->frame_rate.num) - enc_ctx->time_base = av_inv_q(ost->frame_rate); - - av_reduce(&enc_ctx->time_base.num, &enc_ctx->time_base.den, - enc_ctx->time_base.num, enc_ctx->time_base.den, INT_MAX); if (ist->st->nb_side_data) { ost->st->side_data = av_realloc_array(NULL, ist->st->nb_side_data, diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 3ee7051..766e9b3 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -2893,6 +2893,18 @@ int av_apply_bitstream_filters(AVCodecContext *codec, AVPacket *pkt, AVBitStreamFilterContext *bsfc); #endif +enum AVTimebaseCopyFrom { + AVFMT_TBCF_AUTO = -1, + AVFMT_TBCF_DECODER, + AVFMT_TBCF_DEMUXER, + AVFMT_TBCF_R_FRAMERATE, +}; + +// TODO: doc +int avformat_transfer_stream_timing_info(const AVOutputFormat *ofmt, + AVStream *ost, const AVStream *ist, + enum AVTimebaseCopyFrom copy_tb); + /** * @} */ diff --git a/libavformat/utils.c b/libavformat/utils.c index 76cbff4..e0c307f 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -5281,3 +5281,61 @@ int ff_bprint_to_codecpar_extradata(AVCodecParameters *par, struct AVBPrint *buf par->extradata_size = buf->len; return 0; } + +int avformat_transfer_stream_timing_info(const AVOutputFormat *ofmt, + AVStream *ost, const AVStream *ist, + enum AVTimebaseCopyFrom copy_tb) +{ + //TODO: use [io]st->internal->avctx + const AVCodecContext *dec_ctx = ist->codec; + AVCodecContext *enc_ctx = ost->codec; + + enc_ctx->time_base = ist->time_base; + /* + * Avi is a special case here because it supports variable fps but + * having the fps and timebase differe significantly adds quite some + * overhead + */ + if (!strcmp(ofmt->name, "avi")) { + if (copy_tb == AVFMT_TBCF_AUTO && ist->r_frame_rate.num + && av_q2d(ist->r_frame_rate) >= av_q2d(ist->avg_frame_rate) + && 0.5/av_q2d(ist->r_frame_rate) > av_q2d(ist->time_base) + && 0.5/av_q2d(ist->r_frame_rate) > av_q2d(dec_ctx->time_base) + && av_q2d(ist->time_base) < 1.0/500 && av_q2d(dec_ctx->time_base) < 1.0/500 + || copy_tb == AVFMT_TBCF_R_FRAMERATE) { + enc_ctx->time_base.num = ist->r_frame_rate.den; + enc_ctx->time_base.den = 2*ist->r_frame_rate.num; + enc_ctx->ticks_per_frame = 2; + } else if (copy_tb == AVFMT_TBCF_AUTO && av_q2d(dec_ctx->time_base)*dec_ctx->ticks_per_frame > 2*av_q2d(ist->time_base) + && av_q2d(ist->time_base) < 1.0/500 + || copy_tb == AVFMT_TBCF_DECODER) { + enc_ctx->time_base = dec_ctx->time_base; + enc_ctx->time_base.num *= dec_ctx->ticks_per_frame; + enc_ctx->time_base.den *= 2; + enc_ctx->ticks_per_frame = 2; + } + } else if (!(ofmt->flags & AVFMT_VARIABLE_FPS) + && strcmp(ofmt->name, "mov") && strcmp(ofmt->name, "mp4") && strcmp(ofmt->name, "3gp") + && strcmp(ofmt->name, "3g2") && strcmp(ofmt->name, "psp") && strcmp(ofmt->name, "ipod") + && strcmp(ofmt->name, "f4v")) { + if (copy_tb == AVFMT_TBCF_AUTO && dec_ctx->time_base.den + && av_q2d(dec_ctx->time_base)*dec_ctx->ticks_per_frame > av_q2d(ist->time_base) + && av_q2d(ist->time_base) < 1.0/500 + || copy_tb == AVFMT_TBCF_DECODER) { + enc_ctx->time_base = dec_ctx->time_base; + enc_ctx->time_base.num *= dec_ctx->ticks_per_frame; + } + } + + if (enc_ctx->codec_tag == AV_RL32("tmcd") + && dec_ctx->time_base.num < dec_ctx->time_base.den + && dec_ctx->time_base.num > 0 + && 121LL*dec_ctx->time_base.num > dec_ctx->time_base.den) { + enc_ctx->time_base = dec_ctx->time_base; + } + + av_reduce(&enc_ctx->time_base.num, &enc_ctx->time_base.den, + enc_ctx->time_base.num, enc_ctx->time_base.den, INT_MAX); + + return 0; +}