当前位置: 首页 > 知识库问答 >
问题:

Android Camera2:最优最快的改变输出面设置的方法

曾弘扬
2023-03-14

我正在制作一个视频流应用程序,使视频比特率适应可用的上行链路带宽,我希望它能动态地改变视频分辨率,这样就不会有太多的压缩工件在较低的比特率。虽然通过释放mediaCodec调用cameracapturesession上的abortcapture()stoprepeating(),然后为新的解析配置所有内容,我已经开始工作了,但这会导致流中非常明显的中断--在我的测试中至少中断半秒钟。

我使用OpenGL来缩放图像,当相机不支持所需的分辨率时,类似于这样。我用两个曲面初始化捕获会话--一个用于向用户预览(使用textureview),另一个用于编码器,它要么是MediaCodec的直接输入曲面,要么是我的OpenGL纹理曲面。

通过使用MediaCodec.createPersistentInputSurface()可以解决这个问题,因为我将能够在分辨率变化中重用这个scaler实例,并且不必对捕获会话做任何事情,因为就相机而言,不会发生表面变化,但它只有在API23之后才可用,而且我还需要这个实现来支持API21。

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

因此,我的一般问题是:如何更改CameracaptureSession中的输出曲面集,或者重新创建CameracaptureSession,同时尽可能少地在视频流中引入滞后?

共有1个答案

慕仲渊
2023-03-14

事实证明,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,因为相机输出到的曲面集没有变化。

 类似资料:
  • 问题内容: 我在XML文件下面有这个 现在,下面显示了从XML文件读取数据的Java程序。 结果是.. 现在,我的查询是请告知是否还有其他最快的方式来读取此xml,我正在查看斋戒,请告知..! 问题答案: 如果性能对您而言很重要,则应首选SAX或StAX(http://en.wikipedia.org/wiki/StAX)而不是DOM。 使用时,第一次将文件解析为对象模型,然后您可以提出要求。因此

  • 问题内容: 我有一个,我想将每个索引的值设置为相同的值。 有一种很明显的方法(迭代): 但是我想知道是否有一种可以利用的方法或某种等效方法可以绕过迭代的需要。有没有办法做到这一点? 编辑: 从 这是完全相同的过程,这表明可能没有更好的方法可以做到这一点。 +1对所有提出建议的人-你们都是正确的,谢谢。 问题答案: 试试:数组javadoc

  • 问题内容: 我正在做这样的事情: 基本上,我计算一个整数并输出大约10K-100K次的字符串,然后将结果写入system.out,每个结果都用换行符分隔。 最快的方法是什么? 问题答案: 感谢您的建议。我创建了一个测试程序来比较它们: 结果: Environment1 System.out.println:482 StringBuilder:210 BufferedoutputStream:86

  • 我正在做这样的事情: 基本上,我计算一个整数并输出一个字符串大约10k-100k次,然后需要将结果写入System.out,每个结果用换行分隔。 最快的方法是什么?

  • 本文向大家介绍Android退出应用最优雅的方式(改进版),包括了Android退出应用最优雅的方式(改进版)的使用技巧和注意事项,需要的朋友参考一下 我们先来看看几种常见的退出方法(不优雅的方式) 一、容器式 建立一个全局容器,把所有的Activity存储起来,退出时循环遍历finish所有Activity 这种方法比较简单, 但是可以看到activityStack持有这Activity的强引用

  • 如何将值中的所有位设置为1?使用AVX或AVX2的本质? 而我似乎在AVX中找不到一个简单的按位非运算?如果这是可用的,我可以简单地使用setzero,后面跟着一个向量NOT。