/**
* 输入参数: s(格式上下文), st(流), pc(分析器上下文), pkt(包)
* 输出参数: pnum(分子地址),pden(分母地址)
* 描述: 返回 frame 时长,秒值,用分数表达. 得不到时长时返回 0(*pnum=0,*pden=0);
*/
void ff_compute_frame_duration(AVFormatContext *s, int *pnum, int *pden, AVStream *st,
AVCodecParserContext *pc, AVPacket *pkt)
{
//取得帧率, avctx->framerate 或计算得到
//实例: st->internal->avctx->ticks_per_frame = 2, st->internal->avctx->time_base = {1,50}, st->internal->avctx->framerate={25,1}
//则不管s->iformat 是否为真,codec_framerate 都为{25,1}
AVRational codec_framerate = s->iformat ? st->internal->avctx->framerate :
av_mul_q(av_inv_q(st->internal->avctx->time_base), (AVRational){1, st->internal->avctx->ticks_per_frame});
int frame_size, sample_rate;
#if FF_API_LAVF_AVCTX
FF_DISABLE_DEPRECATION_WARNINGS
//当没有得到有效的codec_framerate 时,我们再换一种方法计算(由st->codec->time_base 及 st->codec->ticks_per_frame(此例为2) 计算
if ((!codec_framerate.den || !codec_framerate.num) && st->codec->time_base.den && st->codec->time_base.num)
codec_framerate = av_mul_q(av_inv_q(st->codec->time_base), (AVRational){1, st->codec->ticks_per_frame});
FF_ENABLE_DEPRECATION_WARNINGS
#endif
//初始化输出
*pnum = 0;
*pden = 0;
switch (st->codecpar->codec_type) {
case AVMEDIA_TYPE_VIDEO:
if (st->r_frame_rate.num && !pc && s->iformat) {
*pnum = st->r_frame_rate.den; //返回 stream 的额定帧率
*pden = st->r_frame_rate.num;
} else if (st->time_base.num * 1000LL > st->time_base.den) { //分子,分母不超过1000倍时
*pnum = st->time_base.num; //返回 stream 的时基
*pden = st->time_base.den;
} else if (codec_framerate.den * 1000LL > codec_framerate.num) {
av_assert0(st->internal->avctx->ticks_per_frame); //av_asser0()是断言条件不为0
av_reduce(pnum, pden, // 返回简化的codec_framerate
codec_framerate.den,
codec_framerate.num * (int64_t)st->internal->avctx->ticks_per_frame,
INT_MAX);
if (pc && pc->repeat_pict) { // pc 为真, pc->repeat_pict = 1
av_assert0(s->iformat); // this may be wrong for interlaced encoding but its not used for that case
av_reduce(pnum, pden, //约简 *pnum*2/ *pden, 返回 {1,25}
(*pnum) * (1LL + pc->repeat_pict),
(*pden),
INT_MAX);
}
/* 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 (st->internal->avctx->ticks_per_frame > 1 && !pc)
*pnum = *pden = 0;
}
break;
case AVMEDIA_TYPE_AUDIO: // 音频未注释, 它是从其它地方获取值
if (st->internal->avctx_inited) {
frame_size = av_get_audio_frame_duration(st->internal->avctx, pkt->size);
sample_rate = st->internal->avctx->sample_rate;
} else {
frame_size = av_get_audio_frame_duration2(st->codecpar, pkt->size);
sample_rate = st->codecpar->sample_rate;
}
if (frame_size <= 0 || sample_rate <= 0)
break;
*pnum = frame_size;
*pden = sample_rate;
break;
default:
break;
}
}