gpt4 book ai didi

安卓相机2 : the most optimal and fast way to change the output surface set on-the-fly

转载 作者:太空宇宙 更新时间:2023-11-03 13:07:46 25 4
gpt4 key购买 nike

我正在制作一个视频流应用程序,它可以根据可用的上行链路带宽调整视频比特率,我希望它能够动态更改视频分辨率,以便在较低的比特率下不会出现太多的压缩伪影。虽然我通过释放 MediaCodec 并在 CameraCaptureSession 上调用 abortCaptures()stopRepeating() 来完成这项工作> 然后为新分辨率配置所有内容,这会导致流中出现非常明显的中断 - 在我的测试中至少有半秒。

当相机本身不支持所需的分辨率时,我使用 OpenGL 缩放图像,类似于 this .我使用两个表面初始化捕获 session - 一个用于向用户预览(使用 TextureView),另一个用于编码器,即 MediaCodec 的直接输入表面或我的 OpenGL 纹理表面。

这可以通过使用 MediaCodec.createPersistentInputSurface() 来解决,因为我将能够在分辨率更改时重用这个缩放器实例,而不必对捕获 session 做任何事情因为就相机而言,表面没有发生变化,但它仅在 API 23 之后可用,我也需要此实现来支持 API 21。

然后还有表面失效和重新创建的问题。例如,当用户按下后退按钮时, Activity 及其包含的 TextureView 将被销毁,从而使预览表面无效。然后,当用户再次导航到该 Activity 时,将创建一个新的 TextureView,我需要开始在其中显示预览,而不会给缩放器/编码器看到的流带来任何延迟。

所以,我的一般问题是:如何更改 CameraCaptureSession 中的输出表面集,或重新创建 CameraCaptureSession,同时尽可能少地延迟尽可能视频流?

最佳答案

事实证明,实际上保存纹理的 OpenGL 上下文(包括相机向其提供帧的纹理)与任何特定的输出目标无关。因此,我能够让我的视频缩放器在初始化后更改其输出表面,如下所示:

...
}else if(inputMessage.what==MSG_CHANGE_SURFACE){
// Detach the current thread from the context, as a precaution
EGL14.eglMakeCurrent(mEGLDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_CONTEXT);
checkEglError("eglMakeCurrent 1");

// Destroy the old EGL surface and release its Android counterpart
// the old surface belongs to the previous, now released, MediaCodec instance
EGL14.eglDestroySurface(mEGLDisplay, mEGLSurface);
checkEglError("eglDestroySurface");
surface.release(); // surface is a field that holds the current MediaCodec encoder input surface

surface=(Surface) inputMessage.obj;
dstW=inputMessage.arg1; // these are used in glViewport and the fragment shader
dstH=inputMessage.arg2;

// Create a new EGL surface for the new MediaCodec instance
int[] surfaceAttribs={
EGL14.EGL_NONE
};
mEGLSurface=EGL14.eglCreateWindowSurface(mEGLDisplay, configs[0], surface, surfaceAttribs, 0);
checkEglError("eglCreateWindowSurface");

// Make it current for the current thread
EGL14.eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext);
checkEglError("eglMakeCurrent 2");

// That's it, any subsequent draw calls will render to the new surface
}

使用这种方法,不需要重新初始化 CameraCaptureSession,因为相机输出到的表面集没有变化。

关于安卓相机2 : the most optimal and fast way to change the output surface set on-the-fly,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55043378/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com