【问题标题】:How do you get an accurate duration of a given h264 stream(Silverlight)?您如何获得给定 h264 流(Silverlight)的准确持续时间?
【发布时间】:2012-02-21 22:18:38
【问题描述】:
背景:
我已经使用 ffmpeg 编码了一个原始的 h264 文件。我正在尝试创建自己的容器,例如 Smooth Streaming 如何与碎片化的 mp4 容器一起工作。我对流畅流的安全性不满意,因为任何人都可以通过适当的身份验证从 IIS 完全翻录文件。
问题
无论如何,我的原始 h264 流播放“有点”在 Silverlight 中使用 MediaStreamSource 并启用了 ssl,但我无法为我从服务器端发送到 silverlight 客户端中的 MediaStreamSource 的卡盘获得正确的时间戳。我已由 sps Nals 解析的 h264 数据块之间存在延迟。我看到this question 获得持续时间。想知道是否有一种简单的方法可以计算 h264 流中的帧并获得持续时间,以便我可以将准确的时间戳传递给 MediaSampleSource。如果有人可以回答:指出开源帧计数器的方向或给我一些解析帧的伪代码(也许是一些十六进制解析技巧)。或者,也许有人对这个确切的问题有一些经验,那会很棒。任何帮助将不胜感激。提前致谢。
【问题讨论】:
标签:
c#-4.0
silverlight-4.0
h.264
【解决方案1】:
我翻阅了 ISO 14496-10 文档,发现了一些用于在原始 h264 流中查找帧的十六进制字符串:
0x00000141,
0x00000101,
0x00000165
如果您浏览您的流并计算这些十六进制字符串以及您使用 ffmpeg 和 libx264 进行的编码,这应该可以让您获得相当可靠的帧数。 (如果我错了,请有人纠正我)。因此,如果您拥有 h264 视频的总持续时间并且您拥有应该能够从 ffmpeg 轻松获得的 FPS,那么您可以使用在传递给 MediaStreamSource 的任何给定数据块中计算的帧数来获得为您的 MediaSampleSource 提供非常准确的时间戳。希望这对某人有所帮助,因为几天前我的播放一直断断续续,这让我非常沮丧。
编辑
当我在 directshow 中测试我的播放功能时,我注意到这并不完美,仅适用于使用 ffmpeg 进行简单编码的 h264 流。 h264 具有可变的帧速率和比特率。尽管视频运行得相当流畅,但明眼人可以看出,在视频中更复杂的序列中,时间安排有点尴尬。我认为对于粗制滥造的视频流播放器来说,这是一种很好的方法,尤其是在经常使用关键帧的情况下。我认为在我点击回答之前添加它是公平的。
【解决方案2】:
这实际上有点像兔子洞。从 ISO 14496 第 10 部分开始,然后转到第 7.3 节了解语法。
第一个近似值是使用 vui_parameters ( num_units_in_tick/time_scale ) 中的场速率和 slice_header() 的数量。
如果您正在处理高清内容并且您的编码器在每张图片中使用多个 slice_header()(那么您必须检查 first_mb_in_slice ==0),则会出现这种情况。
您必须注意 frame_mbs_only_flag 和 field_pic_flag。
另一个毛球是表 D-1,它解释了 pic_timing SEI 消息的 pic_struct 字段。这包括场重复(TBT 或 BTB)、帧倍增和帧倍增等内容。
如果您有传输流,则可以通过检查第一个和最后一个访问单元的 PES 标头(ISO 13818 第 1 部分)上的 DTS 值来解决此问题。