如果不存在B幀认烁,當然dts等于pts。
如果存在B幀呢督勺,flv文件中dts和pts是如何體現(xiàn)的呢?
FLV的官方文檔中對tag的定義蔬墩,前半部分如下:
tag的前半部分
可以看到有兩個字段涉及時間戳:
Timestamp(3字節(jié))
時間戳,單位毫秒佑淀。
該時間戳是相對于首個Tag時間戳的相對時間戳留美。
首個Tag的時間戳一般為0。TimestampExtended(1字節(jié))
擴展時間戳伸刃。
和Timestamp合在一起拼成一個32bit的時間戳谎砾。
該時間戳占高8位。
這個時間戳是什么呢? 是dts還是pts?
看一段ffmpeg中l(wèi)ibavformat/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如何體現(xiàn)呢?
答案是用VideoTagHeader中有個Composition Time的字段來實現(xiàn)景图。
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 thatCT(n) = DT(n) + CTTS(n)
where CTTS(n) is the (uncompressed) table entry for sample n.
由以上的文檔可知隘道,flv文檔中的composition time表示PTS相對于DTS的偏移值症歇。
參見一段ffmpeg中l(wèi)ibavformat/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字節(jié)激捏, 。
顯示時間(pts) = 解碼時間(tag的第5~8字節(jié)) + 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