From patchwork Tue Sep 13 08:44:02 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: 559 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.140.134 with SMTP id o128csp2030320vsd; Tue, 13 Sep 2016 01:43:44 -0700 (PDT) X-Received: by 10.28.126.69 with SMTP id z66mr4077692wmc.74.1473756224153; Tue, 13 Sep 2016 01:43:44 -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 n184si7901142wme.83.2016.09.13.01.43.43; Tue, 13 Sep 2016 01:43:44 -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 27305689E4E; Tue, 13 Sep 2016 11:43:29 +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 EE693689BC0 for ; Tue, 13 Sep 2016 11:43:22 +0300 (EEST) Received: from localhost (kimiko.pkh.me [local]) by kimiko.pkh.me (OpenSMTPD) with ESMTPA id 35c5299f; Tue, 13 Sep 2016 08:44:05 +0000 (UTC) From: =?UTF-8?q?Cl=C3=A9ment=20B=C5=93sch?= To: ffmpeg-devel@ffmpeg.org Date: Tue, 13 Sep 2016 10:44:02 +0200 Message-Id: <20160913084402.10841-1-u@pkh.me> X-Mailer: git-send-email 2.9.3 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH] lavf: add avformat_transfer_internal_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. --- doc/APIchanges | 4 ++++ ffmpeg.c | 52 ++++-------------------------------------- libavformat/avformat.h | 21 +++++++++++++++++ libavformat/utils.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++ libavformat/version.h | 4 ++-- 5 files changed, 92 insertions(+), 50 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 7ac809c..158a0b2 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,10 @@ libavutil: 2015-08-28 API changes, most recent first: +2016-09-xx - xxxxxxx - lavf 57.49.100 - avformat.h + Add avformat_transfer_internal_stream_timing_info helper to help with stream + copy. + 2016-08-29 - 4493390 - lavfi 6.58.100 - avfilter.h Add AVFilterContext.nb_threads. diff --git a/ffmpeg.c b/ffmpeg.c index d858407..b16b4ad 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -2909,57 +2909,13 @@ 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; - } - 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); + ost->st->avg_frame_rate = 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); + ret = avformat_transfer_internal_stream_timing_info(oc->oformat, ost->st, ist->st, copy_tb); + if (ret < 0) + return ret; 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 74915a1..389d985 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -2894,6 +2894,27 @@ 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, +}; + +/** + * Transfer internal timing information from one stream to another. + * + * This function is useful when doing stream copy. + * + * @param ofmt target output format for ost + * @param ost output stream which needs timings copy and adjustments + * @param ist reference input stream to copy timings from + * @param copy_tb define from where the stream codec timebase needs to be imported + */ +int avformat_transfer_internal_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..92a29ae 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -5281,3 +5281,64 @@ int ff_bprint_to_codecpar_extradata(AVCodecParameters *par, struct AVBPrint *buf par->extradata_size = buf->len; return 0; } + +int avformat_transfer_internal_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; + } + + if (ost->avg_frame_rate.num) + enc_ctx->time_base = av_inv_q(ost->avg_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); + + return 0; +} diff --git a/libavformat/version.h b/libavformat/version.h index 90ac534..34226ca 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,8 +32,8 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 57 -#define LIBAVFORMAT_VERSION_MINOR 48 -#define LIBAVFORMAT_VERSION_MICRO 103 +#define LIBAVFORMAT_VERSION_MINOR 49 +#define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \