控制VirtualDisplay的帧速率

Enc*_*ble 4 android mediacodec

我正在编写一个Android应用程序,在其中,我有一个VirtualDisplay镜像屏幕上的内容,然后我将帧从屏幕发送到一个实例MediaCodec.它有效,但是,我想添加一种指定编码视频的FPS的方法,但我不确定如何这样做.

根据我的阅读和实验,丢弃编码的帧(基于演示时间)不能很好地工作,因为它最终会产生块状/伪影的视频,而不是低帧率的平滑视频.其他阅读表明,做我想要的唯一方法(限制FPS)将限制传入的FPS到MediaCodec,但是VirtualDisplay刚收到一个SurfaceMediaCodec下面构造的

mSurface = <instance of MediaCodec>.createInputSurface();
mVirtualDisplay = mMediaProjection.createVirtualDisplay(
    "MyDisplay",
    screenWidth,
    screenHeight,
    screenDensity,
    DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
    mSurface,
    null,
    null);
Run Code Online (Sandbox Code Playgroud)

我也试过子类Surface和限制被馈送到帧MediaCodec通过unlockCanvasAndPost(Canvas canvas),但该功能似乎从来没有对我的情况下被调用,因此,有可能是我如何延长一些古怪Surface以及与互动ParcelwriteToParcel功能称为上我的实例,但这是在我的实例中调用的唯一函数(我可以告诉).

其他阅读建议我可以从编码器 - >解码器 - >编码器,并限制第二个编码器馈送帧的速率,但这是很多额外的计算,如果我可以避免它,我宁愿不做.

有没有人成功限制VirtualDisplay饲喂它的速度Surface?任何帮助将不胜感激!

fad*_*den 9

从你做不到的事情开始......

您无法从编码流中删除内容.编码流中的大多数帧基本上是来自其他帧的"差异".在不知道帧如何交互的情况下,您无法安全地丢弃内容,并最终会遇到损坏的宏块外观.

您无法为MediaCodec编码器指定帧速率.它可能会在某个地方填充元数据,但对编解码器来说真正重要的唯一事情就是你要加入它的帧,以及与每个帧相关的表示时间戳.编码器不会丢帧.

通过子类化Surface,您无法做任何有用的事情.Canvas操作仅用于软件渲染,这与从相机或虚拟显示器馈送帧无关.

可以做的是将帧发送到中间曲面,然后选择是否将它们转发到MediaCodec的输入曲面.一种方法是创建SurfaceTexture,从中构造Surface,并将其传递给虚拟显示.当SurfaceTexture的框架可用回调触发时,您要么忽略它,要么使用GLES将纹理渲染到MediaCodec输入Surface上.

Grafikabigflake中可以找到各种例子,其中没有一个是完全合适的,但所有必要的EGL和GLES类都在那里.