lavf: use AV_CODEC_PROP_FIELDS where appropriate

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.
This commit is contained in:
Anton Khirnov
2023-05-05 15:45:42 +02:00
parent 70433abf7f
commit e930b834a9
5 changed files with 32 additions and 21 deletions

View File

@@ -568,7 +568,7 @@ static inline int parse_nal_units(AVCodecParserContext *s,
if (p->sei.common.unregistered.x264_build < 44U) if (p->sei.common.unregistered.x264_build < 44U)
den *= 2; den *= 2;
av_reduce(&avctx->framerate.den, &avctx->framerate.num, 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); av_freep(&rbsp.rbsp_buffer);
@@ -625,7 +625,7 @@ static int h264_parse(AVCodecParserContext *s,
parse_nal_units(s, avctx, buf, buf_size); parse_nal_units(s, avctx, buf, buf_size);
if (avctx->framerate.num) 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) { if (p->sei.picture_timing.cpb_removal_delay >= 0) {
s->dts_sync_point = p->sei.buffering_period.present; s->dts_sync_point = p->sei.buffering_period.present;
s->dts_ref_dts_delta = p->sei.picture_timing.cpb_removal_delay; s->dts_ref_dts_delta = p->sei.picture_timing.cpb_removal_delay;

View File

@@ -129,6 +129,7 @@ static void mpegvideo_extract_headers(AVCodecParserContext *s,
s->pict_type = (buf[1] >> 3) & 7; s->pict_type = (buf[1] >> 3) & 7;
if (bytes_left >= 4) if (bytes_left >= 4)
vbv_delay = ((buf[1] & 0x07) << 13) | (buf[2] << 5) | (buf[3] >> 3); vbv_delay = ((buf[1] & 0x07) << 13) | (buf[2] << 5) | (buf[3] >> 3);
s->repeat_pict = 1;
} }
break; break;
case SEQ_START_CODE: case SEQ_START_CODE:
@@ -186,7 +187,6 @@ static void mpegvideo_extract_headers(AVCodecParserContext *s,
progressive_frame = buf[4] & (1 << 7); progressive_frame = buf[4] & (1 << 7);
/* check if we must repeat the frame */ /* check if we must repeat the frame */
s->repeat_pict = 1;
if (repeat_first_field) { if (repeat_first_field) {
if (pc->progressive_sequence) { if (pc->progressive_sequence) {
if (top_field_first) if (top_field_first)

View File

@@ -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 av_guess_frame_rate(AVFormatContext *format, AVStream *st, AVFrame *frame)
{ {
AVRational fr = st->r_frame_rate; AVRational fr = st->r_frame_rate;
const AVCodecDescriptor *desc = cffstream(st)->codec_desc;
AVCodecContext *const avctx = ffstream(st)->avctx; AVCodecContext *const avctx = ffstream(st)->avctx;
AVRational codec_fr = avctx->framerate; AVRational codec_fr = avctx->framerate;
AVRational avg_fr = st->avg_frame_rate; 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; 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 && 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.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; fr = codec_fr;
@@ -701,10 +702,12 @@ int avformat_transfer_internal_stream_timing_info(const AVOutputFormat *ofmt,
AVStream *ost, const AVStream *ist, AVStream *ost, const AVStream *ist,
enum AVTimebaseSource copy_tb) enum AVTimebaseSource copy_tb)
{ {
const AVCodecDescriptor *desc = cffstream(ist)->codec_desc;
const AVCodecContext *const dec_ctx = cffstream(ist)->avctx; const AVCodecContext *const dec_ctx = cffstream(ist)->avctx;
AVCodecContext *const enc_ctx = ffstream(ost)->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->codecpar->codec_type == AVMEDIA_TYPE_AUDIO ? (AVRational){0, 1}
: ist->time_base); : ist->time_base);

View File

@@ -213,6 +213,8 @@ FF_ENABLE_DEPRECATION_WARNINGS
if (ret < 0) if (ret < 0)
return ret; return ret;
sti->codec_desc = avcodec_descriptor_get(sti->avctx->codec_id);
sti->need_context_update = 0; sti->need_context_update = 0;
} }
return 0; return 0;
@@ -677,10 +679,11 @@ static void compute_frame_duration(AVFormatContext *s, int *pnum, int *pden,
*pnum = st->time_base.num; *pnum = st->time_base.num;
*pden = st->time_base.den; *pden = st->time_base.den;
} else if (codec_framerate.den * 1000LL > codec_framerate.num) { } 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, av_reduce(pnum, pden,
codec_framerate.den, codec_framerate.den,
codec_framerate.num * (int64_t)sti->avctx->ticks_per_frame, codec_framerate.num * (int64_t)ticks_per_frame,
INT_MAX); INT_MAX);
if (pc && pc->repeat_pict) { 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 /* If this codec can be interlaced or progressive then we need
* a parser to compute duration of a packet. Thus if we have * a parser to compute duration of a packet. Thus if we have
* no parser in such case leave duration undefined. */ * 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; *pnum = *pden = 0;
} }
break; break;
@@ -1288,6 +1292,8 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt)
return ret; return ret;
} }
sti->codec_desc = avcodec_descriptor_get(sti->avctx->codec_id);
sti->need_context_update = 0; sti->need_context_update = 0;
} }
@@ -2164,9 +2170,10 @@ static int get_std_framerate(int i)
static int tb_unreliable(AVFormatContext *ic, AVStream *st) static int tb_unreliable(AVFormatContext *ic, AVStream *st)
{ {
FFStream *const sti = ffstream(st); FFStream *const sti = ffstream(st);
const AVCodecDescriptor *desc = sti->codec_desc;
AVCodecContext *c = sti->avctx; AVCodecContext *c = sti->avctx;
AVRational time_base = c->framerate.num ? av_inv_q(av_mul_q(c->framerate, AVRational mul = (AVRational){ desc && (desc->props & AV_CODEC_PROP_FIELDS) ? 2 : 1, 1 };
(AVRational){c->ticks_per_frame, 1})) AVRational time_base = c->framerate.num ? av_inv_q(av_mul_q(c->framerate, mul))
/* NOHEADER check added to not break existing behavior */ /* NOHEADER check added to not break existing behavior */
: (((ic->ctx_flags & AVFMTCTX_NOHEADER) || : (((ic->ctx_flags & AVFMTCTX_NOHEADER) ||
st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) ? (AVRational){0, 1} st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) ? (AVRational){0, 1}
@@ -2718,13 +2725,14 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
break; break;
} }
if (pkt->duration > 0) { 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 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 && (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); sti->info->codec_info_duration = FFMIN(pkt->pts - st->start_time, sti->info->codec_info_duration + pkt->duration);
} else } else
sti->info->codec_info_duration += pkt->duration; 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; ? 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); best_fps, 12 * 1001, INT_MAX);
} }
if (!st->r_frame_rate.num) { if (!st->r_frame_rate.num) {
AVRational time_base = avctx->framerate.num ? av_inv_q(av_mul_q(avctx->framerate, const AVCodecDescriptor *desc = sti->codec_desc;
(AVRational){avctx->ticks_per_frame, 1})) AVRational mul = (AVRational){ desc && (desc->props & AV_CODEC_PROP_FIELDS) ? 2 : 1, 1 };
/* NOHEADER check added to not break existing behavior */ AVRational fr = av_mul_q(avctx->framerate, mul);
: ((ic->ctx_flags & AVFMTCTX_NOHEADER) ? (AVRational){0, 1}
: st->time_base); if (fr.num && fr.den && av_cmp_q(st->time_base, av_inv_q(fr)) <= 0) {
if ( time_base.den * (int64_t) st->time_base.num st->r_frame_rate = fr;
<= 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);
} else { } else {
st->r_frame_rate.num = st->time_base.den; st->r_frame_rate.num = st->time_base.den;
st->r_frame_rate.den = st->time_base.num; st->r_frame_rate.den = st->time_base.num;

View File

@@ -23,6 +23,7 @@
#include <stdint.h> #include <stdint.h>
#include "libavcodec/codec_desc.h"
#include "libavcodec/packet_internal.h" #include "libavcodec/packet_internal.h"
#include "avformat.h" #include "avformat.h"
@@ -408,6 +409,8 @@ typedef struct FFStream {
*/ */
int64_t first_dts; int64_t first_dts;
int64_t cur_dts; int64_t cur_dts;
const AVCodecDescriptor *codec_desc;
} FFStream; } FFStream;
static av_always_inline FFStream *ffstream(AVStream *st) static av_always_inline FFStream *ffstream(AVStream *st)