Enc*_*ble 4 android mediacodec
我正在编写一个Android应用程序,在其中,我有一个VirtualDisplay镜像屏幕上的内容,然后我将帧从屏幕发送到一个实例MediaCodec.它有效,但是,我想添加一种指定编码视频的FPS的方法,但我不确定如何这样做.
根据我的阅读和实验,丢弃编码的帧(基于演示时间)不能很好地工作,因为它最终会产生块状/伪影的视频,而不是低帧率的平滑视频.其他阅读表明,做我想要的唯一方法(限制FPS)将限制传入的FPS到MediaCodec,但是VirtualDisplay刚收到一个Surface由MediaCodec下面构造的
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以及与互动Parcel的writeToParcel功能被称为上我的实例,但这是在我的实例中调用的唯一函数(我可以告诉).
其他阅读建议我可以从编码器 - >解码器 - >编码器,并限制第二个编码器馈送帧的速率,但这是很多额外的计算,如果我可以避免它,我宁愿不做.
有没有人成功限制VirtualDisplay饲喂它的速度Surface?任何帮助将不胜感激!
从你做不到的事情开始......
您无法从编码流中删除内容.编码流中的大多数帧基本上是来自其他帧的"差异".在不知道帧如何交互的情况下,您无法安全地丢弃内容,并最终会遇到损坏的宏块外观.
您无法为MediaCodec编码器指定帧速率.它可能会在某个地方填充元数据,但对编解码器来说真正重要的唯一事情就是你要加入它的帧,以及与每个帧相关的表示时间戳.编码器不会丢帧.
通过子类化Surface,您无法做任何有用的事情.Canvas操作仅用于软件渲染,这与从相机或虚拟显示器馈送帧无关.
您可以做的是将帧发送到中间曲面,然后选择是否将它们转发到MediaCodec的输入曲面.一种方法是创建SurfaceTexture,从中构造Surface,并将其传递给虚拟显示.当SurfaceTexture的框架可用回调触发时,您要么忽略它,要么使用GLES将纹理渲染到MediaCodec输入Surface上.
在Grafika和bigflake中可以找到各种例子,其中没有一个是完全合适的,但所有必要的EGL和GLES类都在那里.