我想乱序显示MediaCodec的解码视频帧,或者省略帧,或多次显示帧.
我考虑过配置MediaCodec以使用Surface,反复调用MediaCodec.dequeueOutputBuffer(),保存生成的缓冲区索引,然后再调用MediaCodec.releaseOutputBuffer(desired_index,true),但是似乎没有办法增加数量输出缓冲区,因此如果我要处理许多要重新排列的帧,我可能会用完输出缓冲区.
我正在考虑的一个想法是使用glReadPixels()将像素数据读取到帧缓冲区中,适当地转换颜色格式,然后在需要显示帧时将其复制到SurfaceView.但这似乎是很多复制(和颜色格式转换)的开销,尤其是当我本来不需要修改像素数据时.
所以我想知道是否有更好,更高效的方法.也许有一种方法可以为每个解码帧配置不同的“表面/纹理/缓冲区”,然后通过一种方法告诉SurfaceView显示特定的“表面/纹理/缓冲区”(而不必执行内存复制).似乎必须有一种使用OpenGL完成此操作的方法,但是我对OpenGL还是很陌生,可以使用有关领域的建议进行调查.如果需要,我什至会去NDK.
到目前为止,我一直在审查Android文档以及fadden的bigflake和Grafika.谢谢.
解决方法:
当使用高分辨率视频和更多帧数时,保存大量帧的副本可能会带来问题.保存为RGBA的1280×720帧将为1280x720x4 = 3.5MB.如果您要保存100帧,则这是1GB设备上的内存的1/3.
如果您确实想采用这种方法,我想您要做的就是将一系列纹理附加到FBO上并对其进行渲染以存储像素.然后可以在需要绘制时从纹理进行渲染.用于FBO渲染的示例代码存在于Grafika中(这是屏幕录制活动中使用的方法之一).
另一种方法是在解码流中四处寻找.您需要在感兴趣的帧之前寻找最接近的同步帧(通过要求MediaExtractor进行操作,或者通过使用BufferInfo标志保存编码的数据)并进行解码,直到到达目标帧为止.这有多快取决于您需要遍历多少帧,帧的分辨率以及设备上解码器的速度. (如您所料,前进比后退容易.您可能已经在使用的其他视频播放器中注意到类似的现象.)
不要打扰glReadPixels().一般来说,如果可以从您的应用程序直接访问解码后的数据,那么您将受到极大的打击(某些设备比其他设备更多).另外,MediaCodec解码器使用的缓冲区数量在某种程度上取决于设备,因此我不会指望拥有4或5个以上的缓冲区.