时间编码
一、概念
这里我们要说明一下媒体流处理中的一个重要概念-时间编码。
时间编码是一个为了视频和音频流的一种辅助的数据。它包含在视频和音频文件中,我们可以理解为时间戳。
SMPTE timecode 是一个SMPTE 时间和控制码的总和,它是一视频和音频流中的连续数字地址桢,标志和附加数据。它被定义在ANSI/SMPTE12-1986。它的目的就是提供一个可用计算机处理的视频和音频地址。
最多SMPTE时间码的数据结构是一个80bit的一桢,它包含下面的内容:
a、 一个hh::mm::ss::ff(小时::分钟::秒::桢)格式的时间戳。
b、 8个4位的二进制数据通常叫做“用户位”。
c、 不同的标志位
d、 同步序列
e、 效验和
这个格式在DirectShow中被定义为TIMECODE_SAMPLE。
时间码分为两种形式,一种是线性的时间格式LTC(纵向编码),在连续时间中每一个时间码就代表一桢。另外一种时间码是VITC(横向编码),它在垂直消隐间隔中储存视频信号的两条线,有些地方在10到20之间。
LTC时间码要加到比如录像带中会非常容易,因为它是分离的音频信号编码。但它不能在磁带机暂停、慢进、快进的时候被读取。另外在非专业的录像机中它有可能会丢失一路音频信号。
VITC时间码和LTC不同,它可以在0-15倍速度的时候读取。它还可以从视频捕获卡中读取。但是它要是想被录制到磁带上可能就需要一些别的设备了,通常那些设备比较昂贵。
SMPTE时间码同时支持有两种模式,一种是非丢桢模式,一种是丢桢模式。在非丢桢模式中,时间码是被连续增长的记录下来。它可以完成时实的播放工作达到30桢,或更高。
NTSC制式的视频播放标准为29.97桢/ 每秒,这是考虑到单色电视系统的兼容性所致。这就导致一个问提,在非掉桢模式下会导致一个小时会有108桢的不同步,就是真实时间中一个小时的时候,时间码只读了00:59:56:12,当你计算流媒体的播放时间的时候会有一些问题。为了解决这种问题,我们可以在可以容忍的情况下跳桢实现。这种方式的实现是通过在每分钟开始计数的时候跳过两桢但00,20,30,40,50分钟时不跳桢。采用这样的方案我们的网络测试结果每小时误差少于一桢,每24小时误差大概在3桢左右。
在现在的实际工作中,虽然两种模式都被同时提供,但丢桢模式通常被我们采纳。
二、 时间码的典型应用
控制外围设备来进行视频捕获和编辑是一种典型的应用程序。这种应用程序就需要标识视频和音频桢的每一桢,它们使用的方法就是使用SMPTE时间码。线性编辑系统通常会控制三个或者更多的磁带机器,而且还要尽可能的切换视频于光盘刻录机之间。计算机必须精确的执行命令,因此必须要在特定的时间得到录像带指定位置的地址。应用程序使用时间码的方法有很多中,主要有下面这些种:
a、 在整个编辑处理过程中跟踪视频和音频源
b、 同步视频和音频。
c、 同步多个设备
d、 在时间码中使用未定义的字节,叫做:userbits。这里面通常包含日期,ascii码或者电影的工业信息等待。
三、 捕获时间码
通常,时间码是通过一些有产生时间码能力的捕获卡设备来产生的。比如一个rs-422就需要时间码来控制外围设备和主机通信。
在时间吗产生以后,我们需要从流格式的视频和音频中获得时间码,这是可以在以后进行访问的。然后我们处理时间码通过下面两步:
a、 建立一个每一桢位置的非连续的索引,将时间码和每一桢一一对应。这个列表是在捕获完成后的文件末尾被写入的。列表可以是一个象下面的这个结构的矩阵数组,为了简明起见,这里提供的只是DirectShowTIMECODE_SAMPLE结构的一个简化。
struct {
DWORD dwOffset; // 在桢中的偏移位
char[11] szTC; // 在偏移值中的时间码的值
// hh:mm:ss:ff是非掉桢的格式 hh:mm:ss;ff 是掉桢的格式
} TIMECODE;
例如,这里可以给出一个视频捕获流中的时间码:
{0, 02:00:00:02},
{16305, 15:21:13:29} // 位于16305桢的时间格式
使用了这张表,任何桢的时间码都会很好计算。
B、还有一种做法就是将时间码作为视频和音频数据写入。这种我们不推荐使用因此不作介绍了。
被写入时间码的文件就可以编辑,复合,同步等操作了。这里就写到这里,对于我们理解时间码已经足够了。其它的很多是关于标准的介绍,大家感兴趣可以参阅一下。