FFMPEG 时间戳PTS校正

本文介绍FFMPEG时间戳PTS校正,其通过DTS在compute_pkt_fields中实现。文中给出相关代码,涉及对视频、音频等不同情况的处理,如判断PTS、DTS有效性,处理B帧,校正时间戳等,还包含计算时长、更新初始时长等操作。

FFMPEG 时间戳PTS校正

前言

    FFMPEG时间戳校正是通过DTS来进行的,在compute_pkt_fields中实现。这篇文章也写了很久了,没有空整理,先发出来供需要的人参考。

代码

static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
                               AVCodecParserContext *pc, AVPacket *pkt,
                               int64_t next_dts, int64_t next_pts)
{
    int num, den, presentation_delayed, delay, i;
    int64_t offset;
    AVRational duration;
    int onein_oneout = st->codecpar->codec_id != AV_CODEC_ID_H264 &&
                       st->codecpar->codec_id != AV_CODEC_ID_HEVC;
    /* AVFMT_FLAG_NOFILLIN定义于AVFormatContext中,表示不需要进行pts处理,直接使用当前的pts */
    if (s->flags & AVFMT_FLAG_NOFILLIN)
        return;
    /* 视频,且当前pkt的dts存在 */
    if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && pkt->dts != AV_NOPTS_VALUE) {
        /* 解码时间等于显示时间,并且之前已经记录到了正常的dts */
        if (pkt->dts == pkt->pts && st->last_dts_for_order_check != AV_NOPTS_VALUE) {
            /* 前述记录的正常dts小于等于当前的dts,用dts_ordered表示正常顺序的pkt数目。 */
            if (st->last_dts_for_order_check <= pkt->dts) {
                st->dts_ordered++;
            } else {
                /* 当前的dts比之前记录的dts小,用dts_misordered表示dts顺序异常的Pkt数目 */
                st->dts_misordered++;
            }
            /* 总包数大于250时,包数都减半,这是为了避免变量溢出 */
            if (st->dts_ordered + st->dts_misordered > 250) {
                st->dts_ordered    >>= 1;
                st->dts_misordered >>= 1;
            }
        }
        /* 将当前有效的PTS设置为检查点的pts */
        st->last_dts_for_order_check = pkt->dts;
        /* dts正常的包少,并且当前包的pts和dts相等,则认为当前pkt的pts无效 */
        if (st->dts_ordered < 8*st->dts_misordered && pkt->dts == pkt->pts)
            pkt->dts = AV_NOPTS_VALUE;
    }
    /* 忽略DTS */
    if ((s->flags & AVFMT_FLAG_IGNDTS) && pkt->pts != AV_NOPTS_VALUE)
        pkt->dts = AV_NOPTS_VALUE;
    /* 遇到B帧,将B帧存在标记置上 */
    if (pc && pc->pict_type == AV_PICTURE_TYPE_B
        && !st->internal->avctx->has_b_frames)
        //FIXME Set low_delay = 0 when has_b_frames = 1
        st->internal->avctx->has_b_frames = 1;

    /* do we have a video B-frame ? */
    delay = st->internal->avctx->has_b_frames;
    presentation_delayed = 0;

    /* 存在B帧并且当前包不是B帧数据,显示delay置1 */
    if (delay &&
        pc && pc->pict_type != AV_PICTURE_TYPE_B)
        presentation_delayed = 1;
    /* pts_wrap_bits表示码流中某条流的PTS对应的bit数,
     * 比如TS的码流,PTS是33位,pts_wrap_bits就是33,
     * wrap在ffmpeg中是超过最大值后重新回到开始这种情况。中文翻译成换行。     
     */
     /* pts,dts都有值,但是dts远远大于pts,限制pts_wrap_bits小于63是为了防止移位溢出 */
    if (pkt->pts != AV_NOPTS_VALUE && pkt->dts != AV_NOPTS_VALUE &&
        st->pts_wrap_bits < 63 &&
        pkt->dts - (1LL << (st->pts_wrap_bits - 1)) > pkt->pts) {
        /* 大于RELATIVE_TS_BASE的值认为是相对值,cur_dts是相对值或者pkt的dts远大于cur_dts */
        if (is_relative(st->cur_dts) || pkt->dts - (1LL<<(st->pts_wrap_bits - 1)) > st->cur_dts) {
            pkt->dts -= 1LL << st->pts_wrap_bits;
        } else
            pkt->pts += 1LL << st->pts_wrap_bits;
    }

    /* Some MPEG-2 in MPEG-PS lack dts (issue #171 / input_file.mpg).
     * We take the conservative approach and discard both.
     * Note: If this is misbehaving for an H.264 file, then possibly
     * presentation_delayed is not set correctly. */
    if (delay == 1 && pkt->dts == pkt->pts &&
        pkt->dts != AV_NOPTS_VALUE && presentation_delayed) {
        av_log(s, AV_LOG_DEBUG, "invalid dts/pts combination %"PRIi64"\n", pkt->dts);
      &n

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值