媒体会话与高级渲染技术解析
1. 自定义媒体会话基础
1.1 源流事件处理
当 HandleSourceStreamEvent()
函数接收到源流的 MEMediaSample
事件时,它会先从事件对象中提取样本,并将其缓存到会话对象中。接着,该函数调用 SetEvent()
设置一个Win32事件,用于通知正在等待的同步MFT线程有新样本可用。同步MFT线程会从内部变量中提取样本并返回。
1.2 会话时钟机制
在拓扑结构中,所有样本流的触发都源于接收器发出的样本请求事件。接收器会主动通过拓扑结构拉取单个样本。以MP3会话为例,使用标准渲染接收器时,每个样本会依次被渲染。接收器通过查看样本中的演示时间戳,并将其与演示时钟对象进行比较,来确定每个样本的渲染时间。
演示时钟实现了 IMFPresentationClock
接口,它提供了相对于媒体项开始的时钟访问。在会话开始时,演示时钟会初始化为零。只有当样本的演示时间戳与演示时钟的时间匹配时,该样本才会被渲染。例如,若在5秒时暂停演示时钟,然后将其重置为零,音频会停止播放,直到时钟再次达到5秒。
媒体会话负责在每次搜索时调整时钟。若将源搜索到媒体开始后的35秒,就需要将演示时钟也调整到35秒。当拓扑结构包含多个数据流和多个接收器时,需要确保各个流之间同步,以保证视频帧和音频匹配。演示时钟对象提供了这种功能,使每个接收器都能使用相同的参考时间。
IMFPresentationClock
对象只是一个接