|
1 引 言 传统的视频处理都是在空间域中进行的,但是实际传输的码流都是压缩形式的,所以对压缩码流的处理必须先将其解压到空间域,在空间域中处理完成后,再将其重新进行压缩,其中压缩/解压缩所带来的运算量是非常大的,对于计算机来说要耗费大量的内存和CUP资源,很难实现实时的接收处理,因此实时视频拼接技术成为其中的关键技术之一。 由于数字电视技术的迅速发展,多节目流的实时无缝拼接技术成为多媒体领域的关键技术之一,其主要是针对传输流(TS)的研究。但在一些以PS流为主的交互式多媒体领域,如视频监控、多媒体教室、视频点播、视频会议等,实时无缝拼接技术同样有着重要的应用。 2解码器的解码原理 PS流在P-STD(Program-System Target Decoder)中解码的过程如图1所示。从多路复合流中取出的数据放入系统目标解码器中,通过分流得到各路基本流数据,分别放入各自对应的任意解码缓冲区内。其中出现在复合流中的单元、系统或包头标中的字节内容不发送到任意缓冲区中,但可以用于控制系统,例如:缓冲区的大小,在序列头标中得到确定。 图1中在解码时间tdn(j),访问单元的所有数据以某一次序立即被删除,即删除放人缓冲区时问最长的数据An(j)。在视频基本流中,图像组和放在图像前的序列头数据在同一时刻被删除。对于视频序列的第一个编码图像,所有0位或放在序列头的最前面的那一字节在同一时刻被删除。注意,这仅适合视频序列的第一个图像,而不适合视频序列的序列头中的其他部分。当存取单元(访问单元)从缓冲区中删除时,他被立即放入解码器D1~Dn中进行立即解码,在送到系统目标解码器的输出观察程序之前,有可能在重定序缓冲区O1~On中延迟,以保证图像帧按正确的顺序进行显示。
3视频校验缓冲器(VBV) VBV是一个假象的解码器,他在概念上与编码器的输出相联结。他等同于P-SFD中的视频缓冲区部分。图2给出了恒速率编码的视频位流VBV缓冲区占有量说明图。其中,vbv_delay(n)为第n帧的vbv_delay值,表示帧图像起始码的最后一个字节到达解码缓冲器后,在对该帧解码前还需要等待的90 kHz系统时钟周期数,vbvdelay用来在播放开始时设置解码缓冲器的的初始分配,即分配一块多大的内存来接收图像数据,通过调整编码器参数vbv_delay可以保证缓冲器不发生溢出。其中:
Bn是位于图像n即将被解码之前,除去图像n数据元素之前的任何GOP头数据、序列头数据和picture startcode后的VBV的占有情况;R为编码比特率;f是系统时钟频率为90 kHz。 我们可以设VBV在第一帧编码前的初始状态为init_bit,帧率为picture_rate,Dn为从vbv_delay(n)参数最后一个字节到下一帧此位置时等待的数据长度。根据定义可得:
4实时流的拼接过程 为了拼接前后的帧正确显示,而不出现马赛克、花屏,我们必须先进行帧选择。设一组头序列(切出)的编码顺序为: I2,B0,B1,P5,B3,B4,P8,B6,B7,P11,B9,B10 则其对应的显示帧顺序即为: B0,B1,I2,B3,B4,P5,B6,B7,P8,B9,B10,P11 可以看出,头序列的出点必须在I或P帧前面(左边)即第二个B帧后面(右边),如果我们从B帧前面(左边)断开,则从显示顺序上看两个P帧或I与P帧之间显示时间上就不连续,这一显示时间段内的图像内容就不完整,出现一个个不规则的黑洞。 对于尾序列(切入)就必须从I帧前面(左边)断开,这是由于对于I贞后面(右边)的所有帧都直接或是间接的用到了I帧作为参考帧,如果没有I帧,则其后面(右边)所有帧均无法正确显示,而出现马赛克现象。为了避免解码缓冲区下溢,本文采用向前查找的方法选取适合帧,如图3所示。 在未进行切换时,在程序中为每路PS流开辟一块内存,这块内存可以保存每路流中当前这一组的所有数据帧,在未接收到拼接命令时,读取内存中最近时间的一帧放入解码缓冲区中进行解码。 当尾序列接收到拼接命令后,如图4所示,读取帧立刻跳转到这一组的第一帧(I帧),放人解码缓冲区中,同时对此I帧解码时间和显示时间做出相应的调整。已知头序列最后一帧B10的解码时间戳为DTS1,显示时间戳为PTS1,则为达到前后帧在解码时间上的连续,设置下一帧即尾序列第一帧I2的DTS2为 ,其后所有帧均以此类推。从显示次序上看,头序列最后显示的一帧为P11帧,则其显示时间为 。对于尾序列第一个显示帧为B帧,则其显示时间为 ,其后以此类推,这样从显示时间上也就构成了连续。值得注意的是,对于组头标中closed_gop=0的组中,I帧后面的两个B帧也无法显示,他们要用到上一组的帧为参考,所以也应该将其去掉,否则有马赛克出现,我们将组头标中参数broken_link=1即可,对于闭组无需考虑。 为了避免多次切换中vbv_delay前后波动过大而造成的缓冲区溢出,还必须对每一帧的vbv_delay进行调整。由式(3)可得vbv_delay(n-1)的值:  这样我们可以看出vbv_delay(n)的变化只跟vbv_delay(n-1)和Dn-1有关,所以可以根据头序列最后一帧计算出尾序列中每一帧新的vbv_delay值。 5实验分析 如表1所示已知头序列拼接帧的PTS值,且其类型为B,所以其DTS=PTS=42 063 600,进而可计算尾序列拼接帧的 ,从而取代原来的47 618 400,依此类推可以在此基础上计算出以后每一帧的DTS值,再通过DTS得到每一帧的PTS值,若为I或P帧,则其PTS=DTS+3 600×3,若为B帧则PTS=DTS,这样使头尾序列在解码时间和显示时间上达到连续。 然后利用上面的公式,对vbv_delay进行调整。如图5所示,黑线代表头序列中拼接帧的附近的vbv_delay值,红线代表未调整的尾序列中拼接帧的vbv_delay值,蓝线代表调整后的拼接帧的vbv_delay值。从图中可以看出,在拼接点附近,红线vbv_delay值有一个突增,变化率△vbv_delay相对于上一帧明显增大,调整后的蓝线的△vbv_delay与上一帧趋于一致。 ,
即每切换一次缓冲区中就会增加6 098 b/s的数据,通过图中可以看出,这一增量会叠加到以后的每一帧中,所以进行vbv_delay调整很有必要。 6结 语 本文主要在缓冲区充盈度方面做出了改善,通过在程序中对已到来的数据帧前向即时查找,避免了传统方法通过等待适合帧到来后再拼接可能造成的缓冲区下溢问题,并使拼接操作变得简便、效果更好,但却使尾序列拼接帧的播放向前延迟了一组,且播放时间延迟了480 ms,一般是我们的视觉很难察觉的,还有就是对拼接帧的解码延时间做了新的调整,使前后一致,避免了缓冲区的溢出,实验表明可以达到很好的视听效果。
|