flv # 存在B帧情况下的dts和pts

如果不存在B帧,当然dts等于pts。
如果存在B帧呢,flv文件中dts和pts是如何体现的呢?

FLV的官方文档中对tag的定义,前半部分如下:

tag的前半部分

可以看到有两个字段涉及时间戳:


flv timestamp
  • Timestamp(3字节)
    时间戳,单位毫秒
    该时间戳是相对于首个Tag时间戳的相对时间戳
    首个Tag的时间戳一般为0。

  • TimestampExtended(1字节)
    扩展时间戳
    和Timestamp合在一起拼成一个32bit的时间戳
    该时间戳占高8位。

这个时间戳是什么呢? 是dts还是pts?
看一段ffmpeg中libavformat/flvdec.c的代码:

static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
{
...
        pos  = avio_tell(s->pb);
        type = (avio_r8(s->pb) & 0x1F);
        orig_size =
        size = avio_rb24(s->pb);
        flv->sum_flv_tag_size += size + 11;
        dts  = avio_rb24(s->pb);
        dts |= (unsigned)avio_r8(s->pb) << 24;
        av_log(s, AV_LOG_TRACE, "type:%d, size:%d, last:%d, dts:%"PRId64" pos:%"PRId64"\n", type, size, last, dts, avio_tell(s->pb));
        if (avio_feof(s->pb))
            return AVERROR_EOF;
        avio_skip(s->pb, 3); /* stream id, always 0 */
        flags = 0;
...
}

可以看到里边非常重要的两句:

dts  = avio_rb24(s->pb);
dts |= (unsigned)avio_r8(s->pb) << 24;

可见Timestamp和TimestampExtended拼出来的是dts
那么pts如何体现呢?
答案是用VideoTagHeader中有个Composition Time的字段来实现

VideoTagHeader

Composition Time in VideoTagHeader

关于composition time的详细定义,文档说:
See ISO 14496-12, 8.15.3 for an explanation of composition times.
The offset in an FLV file is always in milliseconds.
(单位也是毫秒)

Then look into the ISO 14496-12,8.15.3 , Page 24 and 26

8.15.3 Composition Time to Sample Box
8.15.3.1 Definition
Box Type: ‘ctts’
Container: Sample Table Box (‘stbl’)
Mandatory: No
Quantity: Zero or one
This box provides the offset between decoding time and composition time.
Since decoding time must be less than the composition time,
the offsets are expressed as unsigned numbers such that CT(n) = DT(n) + CTTS(n) where CTTS(n) is the (uncompressed) table entry for sample n.

由以上的文档可知,flv文档中的composition time表示PTS相对于DTS的偏移值
参见一段ffmpeg中libavformat/flvdec.c的代码:

static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
{
...
if (st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_MPEG4) {
            // sign extension
            int32_t cts = (avio_rb24(s->pb) + 0xff800000) ^ 0xff800000;
            pts = dts + cts;
            if (cts < 0) { // dts might be wrong
                if (!flv->wrong_dts)
                    av_log(s, AV_LOG_WARNING,
                        "Negative cts, previous timestamps might be wrong.\n");
                flv->wrong_dts = 1;
            } else if (FFABS(dts - pts) > 1000*60*15) {
                av_log(s, AV_LOG_WARNING,
                       "invalid timestamps %"PRId64" %"PRId64"\n", dts, pts);
                dts = pts = AV_NOPTS_VALUE;
            }
        }
...
}

其中最重要的两句:

            int32_t cts = (avio_rb24(s->pb) + 0xff800000) ^ 0xff800000;
            pts = dts + cts;

总结一下:
1. flv文件中Timestamp和TimestampExtended拼出来的是dts。也就是解码时间。
Timestamp和TimestampExtended拼出来dts单位为ms。

2. CompositionTime 表示PTS相对于DTS的偏移值, 在每个视频tag的第14~16字节, 。
显示时间(pts) = 解码时间(tag的第5~8字节) + CompositionTime
CompositionTime的单位也是ms

注: 上文涉及到的ffmpeg的版本是4.0

ffmpeg version N-91445-g6cc6b61 Copyright (c) 2000-2018 the FFmpeg developers
  built with gcc 4.8.5 (GCC) 20150623 (Red Hat 4.8.5-11)
  configuration: --enable-gpl --enable-debug=3 --enable-libmfx --disable-optimizations --disable-stripping
  libavutil      56. 18.102 / 56. 18.102
  libavcodec     58. 21.104 / 58. 21.104
  libavformat    58. 17.101 / 58. 17.101
  libavdevice    58.  4.101 / 58.  4.101
  libavfilter     7. 25.100 /  7. 25.100
  libswscale      5.  2.100 /  5.  2.100
  libswresample   3.  2.100 /  3.  2.100
  libpostproc    55.  2.100 / 55.  2.100

References:

http://download.macromedia.com/f4v/video_file_format_spec_v10_1.pdf
ISO 14496-12,8.15.3
https://stackoverflow.com/questions/7054954/the-composition-timects-when-wrapping-h-264-nalus
https://blog.csdn.net/cabbage2008/article/details/50402580
https://blog.csdn.net/leixiaohua1020/article/details/12678577

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容