2

我一直在对机器之间的编码/解码和流式视频进行一些研究,我觉得我已经很好地掌握了从文件到流的管道。我可以打开容器,解码和抓取单个帧和音频块,我想在网络上移动这些帧就像简单地发送字节数据一样简单(尽管原始且低效)。我不明白的是它的实际播放方式。简单地将帧写入某个图像框并将音频数据放到声卡缓冲区中并不能很好地工作。谁能向我解释一下 vlc 播放器或 windows 媒体播放器等程序中发生的情况,这些程序允许他们将所有这些帧数据发送到屏幕而不破坏 cpu 和内存?只是一般的想法或一些高级文档会很棒。

谢谢!

4

2 回答 2

1

如果您使用 OpenGL,您可以创建纹理并不断用新的帧数据替换它。这不是一个非常昂贵的操作。然后,您在窗口上绘制一个带纹理的矩形。 glOrtho是这里有用的投影。

在 Windows 中,如果您使用 DirectX 或 Direct3D,同样的事情也适用。您甚至可以获得良好的性能 blitting DIB Sections (GDI): Fastest method for blitting from a pixel buffer into a device context

无论您如何绘制像素,您都可以设置更新计时器,就这么简单。

为了获得流畅的操作,您需要在绘图之前进行缓冲,以便磁盘(或网络)和解码延迟不会影响实时绘图。即使是视频中最轻微的抖动也能被人类感知到。当您的计时器触发时,您需要在图像缓冲区中解码像素并准备好绘制。

于 2013-01-18T02:43:55.597 回答
1

我编写了许多播放器应用程序(适用于 Windows),它们结合了视频和音频,并且需要在两者之间进行精确同步。在 Windows 音频中,您基本上准备缓冲区(只是音频样本值的数组)并将它们排队到音频子系统进行播放;当每个缓冲区完成播放时,子系统会对您的应用程序进行回调,并且您的应用程序使用每个回调来 1) 将下一帧渲染到屏幕,以及 2) 准备要排队到音频子系统的下一个音频块。

例如,假设您在内存中有一些视频帧,您希望以每秒 50 帧的速度播放,与单声道、每个样本 2 个字节和每秒 44,100 个样本的音频同步。这意味着您的音频缓冲区需要每个大小为 882 个样本 (44,100 / 50 = 882),因此每个缓冲区只是一个包含 882 个元素的短(2 字节)整数数组。您至少需要两个缓冲区,但实际上更多更好(缓冲区的权衡是更多的缓冲区意味着更流畅的播放,但代价是启动延迟更长和内存占用更大)。

视频的帧需要以相同的方式“缓冲”,以便始终准备好渲染至少一帧;将单个图像传输到 PC 屏幕是如此之快,以至于它实际上是即时的,而不是您需要担心的事情。唯一关心的是提取或组成帧的任何方法。这些方法至少需要足够快以跟上播放速率,或者它们需要在播放之前充分缓冲,这也会导致更长的启动延迟和更大的内存占用(这些问题对于视频来说比它们用于音频,具有任何合理的分辨率)。

当应用程序开始播放时,它会预先加载所有带有音频的缓冲区并将它们排队等待播放;然后,它同时开始播放并将第一帧渲染到屏幕上。用户看到第一帧并听到前 20 毫秒的音频(20 毫秒 = 1/50 秒)。此时,音频子系统将播放从第一个缓冲区切换到第二个缓冲区,并对应用程序进行回调。然后应用程序将第二帧渲染到屏幕上,并用下一个可用的音频块填充第一个缓冲区,然后将这个第一个缓冲区再次排队到音频子系统。

只要应用程序有可用的音频和视频数据来不断填充缓冲区和帧,这个过程就会继续,你会看到/听到视频。

于 2013-01-18T03:11:47.070 回答