我有一个自定义视频解码器。对于这个解码器,每当我提供一个H.264
文件(只有视频元素而不是音频)作为输入时,我得到一组YUV
帧作为我的输出。然后,我将此YUV
帧转换为RGB24
帧并将其呈现在OpenGL
中。这种转换和渲染同时发生,即逐帧发生,从而看起来就像我正在观看视频一样。
完成上述操作后,我的下一个任务是实现其他功能,如播放,暂停,后退,前进等。
目前我只是渲染帧以及如何解码并转换为RGB。那就是帧率约为60-70 fps。现在如果我必须实现这个播放/暂停功能,那我该怎么办呢。也就是说,如果按下暂停,解码器应该等到我按下播放按钮。
为此提供一些解决方案。
答案 0 :(得分:0)
有点奇怪的是,你设法做了这么多,并且在项目的这一点上陷入困境。如果您运行OpenGL程序,我假设您有一些无限循环,您可以捕获所有事件(鼠标,键)以及从文件中读取图像并将它们渲染到屏幕(使用OpenGL)。这种应用程序通常在多线程环境中运行,特别是读取文件。你可能想要一些缓冲区,你总是存储类似下一秒动画的东西(或更多),当你执行事件循环时你从那个缓冲区读取。同时,当你从缓冲区读取东西时,从磁盘读取数据的线程需要用新信息填充缓冲区。
这可能是使用生产者 - 消费者算法。请注意,您不需要在多线程环境中执行此操作,但如果您的系统无法以30 fps的速度运行,则可能会出现连续性问题。在事件循环中,您可以读取接下来的20帧或10或其他内容,然后从缓冲区,渲染等中读取下一个图像。
在此循环中,如果查看者已按下暂停键(比如空格),则只需将文件和渲染的读取传递给循环中的屏幕任务。或者,您可以在渲染之前将整个文件读取到内存中。
// event loop
while (1) {
char key = nextEvent(...)
if (key == 'x') quiteApp();
else if (key == 'p') { pauseApp = (pauseApp == true) ? false : true; }
if (!pauseApp) {
// adjust the number of frames your read in each loop depending
// on your frame rate. If you frame rate drops below 30 fps
// read less frames, etc.
readFrames(&buffer, videoFile, 10);
getNextFrameFromBuffer(buffer, frameBuffer);
displayFrameuBuffer(frameCount, frameBuffer);
}
frameCount++;
// do time synchronisation here so that you always play at given frame
// rate which is likely to be 30 fps.
...
}