关于MFCreateFMPEG4MediaSink的帧计数与mdat帧控制技术问询
关于MFCreateFMPEG4MediaSink的两个问题解答
1. 如何从MFCreateFMPEG4MediaSink中提取帧计数?
遗憾的是,MFCreateFMPEG4MediaSink并没有直接提供API来获取已处理的总帧计数,不过有两个可靠的方案可以实现:
- 自行维护计数器:这是最直接的方式。作为调用方,你每次调用
IMFStreamSink::ProcessSample向sink写入帧时,在自己的代码里递增一个计数器即可。这个计数器的数值就是当前已写入的总帧数,完全不需要依赖sink的内部状态。 - 结合事件监听辅助验证:如果需要确认sink是否完成所有帧的写入,可以通过
sink的IMFMediaEventGenerator接口监听MESinkCompleted事件。当收到这个事件时,你维护的计数器数值就是最终的总帧计数。
补充说明:如果是想从生成的MP4文件中提取总帧数,那需要解析文件的mvhd或stts原子,但这已经不属于从sink对象中提取的范畴了。
2. 关于多个moof+mdats的帧数控制与查询
不解析原子的情况下得知每个mdat的帧数
默认情况下,MFCreateFMPEG4MediaSink不会暴露每个mdat对应的帧数统计。如果不想解析文件原子,唯一可行的方式是在写入阶段跟踪批次:
- 这个sink会根据内部的缓存策略(比如时间长度、数据大小)分割生成
moof+mdat块。你可以控制自己的写入批次——比如每次写入固定数量的帧后,等待sink完成当前块的写入(可监听MEStreamSinkFlushCompleted事件),此时这个批次的帧数就对应一个mdat的帧数。通过这种方式,你可以在写入时记录每个批次的帧数,间接得到每个mdat的帧数。
是否存在参数强制指定每个mdat的帧数?
没有直接指定帧数的参数,但可以通过设置时间间隔间接实现。MFCreateFMPEG4MediaSink支持MF_MPEG4SINK_MOOF_INTERVAL属性,这个属性用于设置两个moof块之间的时间间隔(单位为100纳秒)。
举个例子:如果你的视频帧率是30fps,想要每个mdat包含15帧,对应的时间间隔就是15/30 = 0.5秒 = 500000000(100纳秒单位)。你只需要在创建sink前,把这个值设置到IMFAttributes对象中,再将该对象传入MFCreateFMPEG4MediaSink的第三个参数即可。
另外还有一个MF_MPEG4SINK_MIN_MOOF_SIZE属性,它按字节数设置最小的moof块大小,但无法直接对应帧数,所以更推荐用时间间隔的方式间接控制帧数。
内容的提问来源于stack exchange,提问作者Evren Bingøl
相关产品推荐
相关产品推荐

