Directshow中的Sample时间戳(Time Stamp)

22 篇文章 0 订阅
7 篇文章 0 订阅

每个Sample上可以设置两种时间戳:IMediaSample::SetTime和IMediaSample::SetMediaTime。

我们通常讲到时间戳,一般是指前者,它又叫Presentation time,Renderer正是根据这个时间戳来控制播放;而后者对于Filter来说不是必须的,Media time有没有用取决于你的实现,比如你给每个发出去的Sample依次打上递增的序号,在后面的Filter接收时就可以判断传输的过程中是否有Sample丢失。

我们再看一下IMediaSample::SetTime的参数,两个参数类型都是REFERENCE_TIME,千万不要误解这里的时间是Reference time,其实它们用的是Stream time。还有一点,就是并不是所有的Sample都要求打上时间戳。对于一些压缩数据,时间戳是很难打的,而且意义也不是很大(不过压缩数据经过Decoder出来之后到达Renderer之前,一般都会打好时间戳了)。

时间戳包括两个时间,开始时间和结束时间。当Renderer接收到一个Sample时,一般会将Sample的开始时间和当前的Stream time作比较,如果Sample来晚了或者没有时间戳,则马上播放这个Sample;如果Sample来得早了,则通过调用参考时钟的IReferenceClock::AdviseTime等待Sample的开始时间到达后再将这个Sample播放。

Sample上的时间戳一般由Source Filter或Parser Filter来设置,设置的方法有如下几种情况:

1. 文件回放(File playback):第一个Sample的时间戳从0开始打起,后面Sample的时间戳根据Sample有效数据的长度和回放速率来定。


2. 音视频捕捉(Video and audio capture):原则上,采集到的每一个Sample的开始时间都打上采集时刻的Stream time。对于视频帧,Preview pin出来的Sample是个例外,因为如果按上述方法打时间戳的话,每个Sample通过Filter链路传输,最后到达Video Renderer的时候都将是迟到的;Video Renderer通过Quality Control反馈给Source Filter,会导致Source Filter丢帧。所以,Preview pin出来的Sample都不打时间戳。对于音频采集,需要注意的是,Audio Capture Filter与声卡驱动程序两者各自使用了不同的缓存,采集的数据是定时从驱动程序缓存拷贝到Filter的缓存的,这里面有一定时间的消耗。

  3. 合成(Mux Filters):取决于Mux后输出的数据类型,可以打时间戳,也可以不打时间戳。

  大家可以看到,Sample的时间戳对于保证音视频同步是很重要的。Video Renderer和Audio Renderer作为音视频同步的最终执行者,需要做很多工作。我们或许要开发其它各种类型的Filter,但一般这两个Filter是不用再开发的。一是因为Renderer Filter本身的复杂性,二是因为微软会对这两个Filter不断升级,集成DirectX中其它模块的最新技术(如DirectSound、DirectDraw、Direct3D等)。

  最后,我们再来仔细看一下Live Source的情况。Live Source又叫Push source,包括Video /Audio Capture Filter、网络广播接收器等。Filter Graph Manager是如何知道一个Filter是Live Source的呢?通过如下任何一个条件判断:

  1. 调用Filter上的IAMFilterMiscFlags::GetMiscFlags返回有AM_FILTER_MISC_FLAGS_IS_SOURCE标记,并且至少有一个Output pin实现了IAMPushSource接口。

  2. Filter实现了IKsPropertySet接口,并且有一个Capture output pin(Pin的类型为PIN_CATEGORY_CAPTURE)。

  Live Source对于音视频同步的影响主要是以下两个方面:Latency和Rate Matching。Latency是指Filter处理一个Sample花费的时间,对于Live Source来说,主要取决于使用缓存的大小,比如采集30fps的视频一般采集完一帧后才将数据以一个Sample发送出去,则这个Filter的Latency为33ms,而Audio一般缓存500ms后才发送一个Sample,则它的Latency就为500ms。这样的话,Audio与Video到达Renderer就会偏差470ms,造成音视频的不同步。默认情况下,Filter Graph Manager是不会对这种情况进行调整的。当然,应用程序可以通过IAMPushSource接口来进行Latency的补偿,方法是调用IAMGraphStreams::SyncUsingStreamOffset函数。Filter Graph Manager的实现如下:对所有实现IAMPushSource接口的Filter调用IAMLatency::GetLatency得到各个Source的Latency值,记下所有Latency值中的最大值,然后调用IAMPushSource::SetStreamOffset对各个Source设置偏移值。

  这样,在Source Filter产生Sample时,打的时间戳就会加上这个偏移量。Rate Matching问题的引入,主要是由于Renderer Filter和Source Filter使用的是不同的参考时钟。这种情况下,Renderer对数据的播放要么太快,要么太慢。另外,一般Live Source不能控制输出数据的速率,所以必须在Renderer上进行播放速率的匹配。因为人的听觉敏感度要大于视觉敏感度,所以微软目前只在Audio Renderer上实现了Rate Matching。实现Rate Matching的算法是比较复杂的,这里就不再赘述。

  看到这里,大家应该对DirectShow是如何解决音视频同步问题的方案有一点眉目了吧。深层次的研究,还需要更多的测试、Base class源码阅读,以及DirectShow相关控制机制的理解,比如Quality Control Management等 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值