ff_compute_frame_duration() 代码注释

/**
 * 输入参数: 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;
    }
}

你可能感兴趣的:(#,ffmpeg,ffmpeg,frame_duration,计算frame时长)