From patchwork Tue May 9 08:37:29 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Khirnov X-Patchwork-Id: 41556 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:dca6:b0:f3:34fa:f187 with SMTP id ky38csp2899666pzb; Tue, 9 May 2023 01:37:52 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ63Y9WNmy2SVdZQUQh1xNRm/UFwEMfGRsTidQGPWxBApj+Id64v/bft1BpS3zS5K6CfpL23 X-Received: by 2002:a17:907:9608:b0:969:e95e:e4f3 with SMTP id gb8-20020a170907960800b00969e95ee4f3mr1508932ejc.55.1683621472221; Tue, 09 May 2023 01:37:52 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1683621472; cv=none; d=google.com; s=arc-20160816; b=WXiV0Vo/cwUywBBHeWFuRZS5btas7+u0U80JL4tExlMfk/u46G8uzPbLEk04Bud+0t AZ8XOisExVTyJ28CDOQTLYk+Y1R6leYxHl3HJBQJT4mXK8yyPm8AJZAOPQfLNf+Rjfxb aAi4mm+wrMIqXUOv4BpAjAFfcHAnDgLPz+0DuHnE+tuAvCmM2WEYfYEvbGU1OtuuqhT3 N+WzWtIT5yCW33SeWO5yxEYD922PjpPiIWrcOWrX7yDH3TlL6cCm73nNJnfXL8SYgnXz YSLN/8y6GoaEEAi8z0Ac2v/BDC+ztf4/bpFTF5LUZLTSvIXH3ENPNF12aDkrgPesdwgb l/6w== 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:references:in-reply-to:message-id :date:to:from:delivered-to; bh=7ak39r4XD3ge5Ra5mxhyDiOOuFqJ6vL4Vtobq15K5k4=; b=SmVaIOBcn/5N2M57Sk0WAiOW2W5MykaRO85Aq0j0Q4UfjSHrN/rVHcDb2KuAL/SAIg 4NsYoXV/wtjmc51XkaVxsCwZyJh5zqzTP7faSzyaZxpO9YEoS0dXJDS1Z6pcGpxDXZ6g 3UMNhDvPjlfyyuDKmc83pvmIHHznf196OrnfBYL7aHIMSiph0feuXbqleGWrzVbqJKSg qRIHAUQ5lkITvJ6oH8PAlrfjLoM76Mn/WHIiGj/jtYwaAIsdtJUGvsSypBL1OmDHeZOm y2q0NbiPF+8ENNejI3n+qZGnYDtUQFl81lIfpPozDhkwvVClFleKI2RKVfe8WweMLzGU 0nbQ== 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 i12-20020a1709067a4c00b00965e57a3668si1728465ejo.806.2023.05.09.01.37.50; Tue, 09 May 2023 01:37:52 -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 3AC8668BFF3; Tue, 9 May 2023 11:37:46 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail0.khirnov.net (red.khirnov.net [176.97.15.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 2ADD368BFF3 for ; Tue, 9 May 2023 11:37:40 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id E3D182404EC for ; Tue, 9 May 2023 10:37:39 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id I1yCIq1hMfq8 for ; Tue, 9 May 2023 10:37:38 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:2a00:c500:561:201::7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "libav.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail0.khirnov.net (Postfix) with ESMTPS id C2D3D240177 for ; Tue, 9 May 2023 10:37:38 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:::1]) by libav.khirnov.net (Postfix) with ESMTP id 828693A031B for ; Tue, 9 May 2023 10:37:32 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Tue, 9 May 2023 10:37:29 +0200 Message-Id: <20230509083729.25362-1-anton@khirnov.net> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230508141208.GR1391451@pb2> References: <20230508141208.GR1391451@pb2> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v2 04/13] lavf: use AV_CODEC_PROP_FIELDS where appropriate X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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" X-TUID: M3bNv2JK5tvf H.264 and mpeg12 parsers need to be adjusted at the same time to stop using the value of AVCodecContext.ticks_per_frame, because it is not set correctly unless the codec has been opened. Previously this would result in both the parser and lavf seeing the same incorrect value, which would cancel out. Updating lavf and not the parsers would result in correct value in lavf, but the wrong one in parsers, which would break some tests. --- libavcodec/h264_parser.c | 4 ++-- libavcodec/mpegvideo_parser.c | 2 +- libavformat/avformat.c | 9 ++++++--- libavformat/demux.c | 35 ++++++++++++++++++++--------------- libavformat/internal.h | 3 +++ 5 files changed, 32 insertions(+), 21 deletions(-) diff --git a/libavcodec/h264_parser.c b/libavcodec/h264_parser.c index 46134a1c48..43abc45f9c 100644 --- a/libavcodec/h264_parser.c +++ b/libavcodec/h264_parser.c @@ -568,7 +568,7 @@ static inline int parse_nal_units(AVCodecParserContext *s, if (p->sei.common.unregistered.x264_build < 44U) den *= 2; av_reduce(&avctx->framerate.den, &avctx->framerate.num, - sps->num_units_in_tick * avctx->ticks_per_frame, den, 1 << 30); + sps->num_units_in_tick * 2, den, 1 << 30); } av_freep(&rbsp.rbsp_buffer); @@ -625,7 +625,7 @@ static int h264_parse(AVCodecParserContext *s, parse_nal_units(s, avctx, buf, buf_size); if (avctx->framerate.num) - time_base = av_inv_q(av_mul_q(avctx->framerate, (AVRational){avctx->ticks_per_frame, 1})); + time_base = av_inv_q(av_mul_q(avctx->framerate, (AVRational){2, 1})); if (p->sei.picture_timing.cpb_removal_delay >= 0) { s->dts_sync_point = p->sei.buffering_period.present; s->dts_ref_dts_delta = p->sei.picture_timing.cpb_removal_delay; diff --git a/libavcodec/mpegvideo_parser.c b/libavcodec/mpegvideo_parser.c index 8e7e88ff25..08e5316960 100644 --- a/libavcodec/mpegvideo_parser.c +++ b/libavcodec/mpegvideo_parser.c @@ -129,6 +129,7 @@ static void mpegvideo_extract_headers(AVCodecParserContext *s, s->pict_type = (buf[1] >> 3) & 7; if (bytes_left >= 4) vbv_delay = ((buf[1] & 0x07) << 13) | (buf[2] << 5) | (buf[3] >> 3); + s->repeat_pict = 1; } break; case SEQ_START_CODE: @@ -186,7 +187,6 @@ static void mpegvideo_extract_headers(AVCodecParserContext *s, progressive_frame = buf[4] & (1 << 7); /* check if we must repeat the frame */ - s->repeat_pict = 1; if (repeat_first_field) { if (pc->progressive_sequence) { if (top_field_first) diff --git a/libavformat/avformat.c b/libavformat/avformat.c index 708d90b38c..fea905693d 100644 --- a/libavformat/avformat.c +++ b/libavformat/avformat.c @@ -679,6 +679,7 @@ AVRational av_guess_sample_aspect_ratio(AVFormatContext *format, AVStream *strea AVRational av_guess_frame_rate(AVFormatContext *format, AVStream *st, AVFrame *frame) { AVRational fr = st->r_frame_rate; + const AVCodecDescriptor *desc = cffstream(st)->codec_desc; AVCodecContext *const avctx = ffstream(st)->avctx; AVRational codec_fr = avctx->framerate; AVRational avg_fr = st->avg_frame_rate; @@ -688,7 +689,7 @@ AVRational av_guess_frame_rate(AVFormatContext *format, AVStream *st, AVFrame *f fr = avg_fr; } - if (avctx->ticks_per_frame > 1) { + if (desc && (desc->props & AV_CODEC_PROP_FIELDS)) { if ( codec_fr.num > 0 && codec_fr.den > 0 && (fr.num == 0 || av_q2d(codec_fr) < av_q2d(fr)*0.7 && fabs(1.0 - av_q2d(av_div_q(avg_fr, fr))) > 0.1)) fr = codec_fr; @@ -701,10 +702,12 @@ int avformat_transfer_internal_stream_timing_info(const AVOutputFormat *ofmt, AVStream *ost, const AVStream *ist, enum AVTimebaseSource copy_tb) { + const AVCodecDescriptor *desc = cffstream(ist)->codec_desc; const AVCodecContext *const dec_ctx = cffstream(ist)->avctx; AVCodecContext *const enc_ctx = ffstream(ost)->avctx; - AVRational dec_ctx_tb = dec_ctx->framerate.num ? av_inv_q(av_mul_q(dec_ctx->framerate, - (AVRational){dec_ctx->ticks_per_frame, 1})) + + AVRational mul = (AVRational){ desc && (desc->props & AV_CODEC_PROP_FIELDS) ? 2 : 1, 1 }; + AVRational dec_ctx_tb = dec_ctx->framerate.num ? av_inv_q(av_mul_q(dec_ctx->framerate, mul)) : (ist->codecpar->codec_type == AVMEDIA_TYPE_AUDIO ? (AVRational){0, 1} : ist->time_base); diff --git a/libavformat/demux.c b/libavformat/demux.c index 2a32bde7f5..dec02a1a6b 100644 --- a/libavformat/demux.c +++ b/libavformat/demux.c @@ -213,6 +213,8 @@ FF_ENABLE_DEPRECATION_WARNINGS if (ret < 0) return ret; + sti->codec_desc = avcodec_descriptor_get(sti->avctx->codec_id); + sti->need_context_update = 0; } return 0; @@ -677,10 +679,11 @@ static void compute_frame_duration(AVFormatContext *s, int *pnum, int *pden, *pnum = st->time_base.num; *pden = st->time_base.den; } else if (codec_framerate.den * 1000LL > codec_framerate.num) { - av_assert0(sti->avctx->ticks_per_frame); + int ticks_per_frame = (sti->codec_desc && + (sti->codec_desc->props & AV_CODEC_PROP_FIELDS)) ? 2 : 1; av_reduce(pnum, pden, codec_framerate.den, - codec_framerate.num * (int64_t)sti->avctx->ticks_per_frame, + codec_framerate.num * (int64_t)ticks_per_frame, INT_MAX); if (pc && pc->repeat_pict) { @@ -692,7 +695,8 @@ static void compute_frame_duration(AVFormatContext *s, int *pnum, int *pden, /* If this codec can be interlaced or progressive then we need * a parser to compute duration of a packet. Thus if we have * no parser in such case leave duration undefined. */ - if (sti->avctx->ticks_per_frame > 1 && !pc) + if (sti->codec_desc && + (sti->codec_desc->props & AV_CODEC_PROP_FIELDS) && !pc) *pnum = *pden = 0; } break; @@ -1288,6 +1292,8 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) return ret; } + sti->codec_desc = avcodec_descriptor_get(sti->avctx->codec_id); + sti->need_context_update = 0; } @@ -2164,9 +2170,10 @@ static int get_std_framerate(int i) static int tb_unreliable(AVFormatContext *ic, AVStream *st) { FFStream *const sti = ffstream(st); + const AVCodecDescriptor *desc = sti->codec_desc; AVCodecContext *c = sti->avctx; - AVRational time_base = c->framerate.num ? av_inv_q(av_mul_q(c->framerate, - (AVRational){c->ticks_per_frame, 1})) + AVRational mul = (AVRational){ desc && (desc->props & AV_CODEC_PROP_FIELDS) ? 2 : 1, 1 }; + AVRational time_base = c->framerate.num ? av_inv_q(av_mul_q(c->framerate, mul)) /* NOHEADER check added to not break existing behavior */ : (((ic->ctx_flags & AVFMTCTX_NOHEADER) || st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) ? (AVRational){0, 1} @@ -2718,13 +2725,14 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) break; } if (pkt->duration > 0) { + const int fields = sti->codec_desc && (sti->codec_desc->props & AV_CODEC_PROP_FIELDS); if (avctx->codec_type == AVMEDIA_TYPE_SUBTITLE && pkt->pts != AV_NOPTS_VALUE && st->start_time != AV_NOPTS_VALUE && pkt->pts >= st->start_time && (uint64_t)pkt->pts - st->start_time < INT64_MAX ) { sti->info->codec_info_duration = FFMIN(pkt->pts - st->start_time, sti->info->codec_info_duration + pkt->duration); } else sti->info->codec_info_duration += pkt->duration; - sti->info->codec_info_duration_fields += sti->parser && sti->need_parsing && avctx->ticks_per_frame == 2 + sti->info->codec_info_duration_fields += sti->parser && sti->need_parsing && fields ? sti->parser->repeat_pict + 1 : 2; } } @@ -2864,15 +2872,12 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) best_fps, 12 * 1001, INT_MAX); } if (!st->r_frame_rate.num) { - AVRational time_base = avctx->framerate.num ? av_inv_q(av_mul_q(avctx->framerate, - (AVRational){avctx->ticks_per_frame, 1})) - /* NOHEADER check added to not break existing behavior */ - : ((ic->ctx_flags & AVFMTCTX_NOHEADER) ? (AVRational){0, 1} - : st->time_base); - if ( time_base.den * (int64_t) st->time_base.num - <= time_base.num * (uint64_t)avctx->ticks_per_frame * st->time_base.den) { - av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, - time_base.den, (int64_t)time_base.num * avctx->ticks_per_frame, INT_MAX); + const AVCodecDescriptor *desc = sti->codec_desc; + AVRational mul = (AVRational){ desc && (desc->props & AV_CODEC_PROP_FIELDS) ? 2 : 1, 1 }; + AVRational fr = av_mul_q(avctx->framerate, mul); + + if (fr.num && fr.den && av_cmp_q(st->time_base, av_inv_q(fr)) <= 0) { + st->r_frame_rate = fr; } else { st->r_frame_rate.num = st->time_base.den; st->r_frame_rate.den = st->time_base.num; diff --git a/libavformat/internal.h b/libavformat/internal.h index f575064e8f..40c46311c8 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -23,6 +23,7 @@ #include +#include "libavcodec/codec_desc.h" #include "libavcodec/packet_internal.h" #include "avformat.h" @@ -408,6 +409,8 @@ typedef struct FFStream { */ int64_t first_dts; int64_t cur_dts; + + const AVCodecDescriptor *codec_desc; } FFStream; static av_always_inline FFStream *ffstream(AVStream *st)