android– 将相机渲染到多个表面 – 打开和关闭屏幕

android– 将相机渲染到多个表面 – 打开和关闭屏幕,第1张

概述我想将摄像机输出渲染到视图中,偶尔将摄像机输出帧保存到文件中,约束为–保存的帧应该与摄像机配置的分辨率相同,而视图小于相机输出(保持纵横比).基于ContinuousCaptureActivityexampleingrafika,我认为最好的方法是将相机发送到SurfaceTexture并通常渲染输出并将其缩小为Su

我想将摄像机输出渲染到视图中,偶尔将摄像机输出帧保存到文件中,约束为 – 保存的帧应该与摄像机配置的分辨率相同,而视图小于相机输出(保持纵横比).

基于ContinuousCaptureActivity example in grafika,我认为最好的方法是将相机发送到SurfaceTexture并通常渲染输出并将其缩小为SurfaceVIEw,并在需要时将整个帧渲染到一个没有视图的不同Surface中,按顺序从常规SurfaceVIEw渲染并行检索字节缓冲区.

该示例与我的情况非常相似 – 预览呈现为较小尺寸的视图,可以通过VIDeoEncoder以全分辨率进行记录和保存.

我用自己的替换了VIDeoEncoder逻辑,并试图提供一个Surface,就像编码器一样,用于全分辨率渲染.如何创建这样的Surface?我接近这个吗?

基于示例的一些代码构思:

在surfaceCreated(SurfaceHolder holder)方法内(第350行):

@OverrIDe   // SurfaceHolder.Callbackpublic voID surfaceCreated(SurfaceHolder holder) {    Log.d(TAG, "surfaceCreated holder=" + holder);    mEglCore = new EglCore(null, EglCore.FLAG_RECORDABLE);    mdisplaySurface = new windowsurface(mEglCore, holder.getSurface(), false);    mdisplaySurface.makeCurrent();    mFullFrameBlit = new FullFrameRect(            new Texture2dProgram(Texture2dProgram.ProgramType.TEXTURE_EXT));    mTextureID = mFullFrameBlit.createTextureObject();    mCameraTexture = new SurfaceTexture(mTextureID);    mCameraTexture.setonFrameAvailableListener(this);    Log.d(TAG, "starting camera prevIEw");    try {        mCamera.setPrevIEwTexture(mCameraTexture);    } catch (IOException ioe) {        throw new RuntimeException(ioe);    }    mCamera.startPrevIEw();    // *** MY EDIT START ***    // Encoder creation no longer needed    //  try {    //    mCircEncoder = new CircularEncoder(VIDEO_WIDTH, VIDEO_HEIGHT, 6000000,    //            mCameraPrevIEwThousandFps / 1000, 7, mHandler);    //  } catch (IOException ioe) {    //      throw new RuntimeException(ioe);    //  }    mEncoderSurface = new windowsurface(mEglCore, mCameraTexture); // <-- Crashes with EGL error 0x3003    // *** MY EDIT END ***    updateControls();}

drawFrame()方法(第420行):

private voID drawFrame() {    //Log.d(TAG, "drawFrame");    if (mEglCore == null) {        Log.d(TAG, "SkipPing drawFrame after shutdown");        return;    }    // Latch the next frame from the camera.    mdisplaySurface.makeCurrent();    mCameraTexture.updateTexImage();    mCameraTexture.gettransformMatrix(mTmpMatrix);    // Fill the SurfaceVIEw with it.    SurfaceVIEw sv = (SurfaceVIEw) findVIEwByID(R.ID.continuousCapture_surfaceVIEw);    int vIEwWIDth = sv.getWIDth();    int vIEwHeight = sv.getHeight();    GLES20.glVIEwport(0, 0, vIEwWIDth, vIEwHeight);    mFullFrameBlit.drawFrame(mTextureID, mTmpMatrix);    mdisplaySurface.swapBuffers();    // *** MY EDIT START ***    // Send it to the vIDeo encoder.    if (someCondition) {        mEncoderSurface.makeCurrent();        GLES20.glVIEwport(0, 0, VIDEO_WIDTH, VIDEO_HEIGHT);        mFullFrameBlit.drawFrame(mTextureID, mTmpMatrix);        mEncoderSurface.swapBuffers();        try {            mEncoderSurface.saveFrame(new file(getExternalfilesDir(null), String.valueOf(System.currentTimeMillis()) + ".png"));        } catch (IOException e) {            e.printstacktrace();        }    }    // *** MY EDIT END ***}

解决方法:

你走在正确的轨道上. SurfaceTexture只是快速地从相机包裹原始YUV帧,因此“外部”纹理是原始图像,没有任何变化.您无法直接从外部纹理中读取像素,因此您必须先将其渲染到某处.

最简单的方法是创建一个屏幕外的pbuffer表面. Grafika的gles / OffscreenSurface类正是这样做的(通过调用eglCreatePbufferSurface()).将EGLSurface设置为当前,将纹理渲染到FullFrameRect上,然后使用glreadPixels()读取帧缓冲区(有关代码,请参阅EglSurfaceBase#saveFrame()).不要调用eglSwapBuffers().

请注意,您不是为输出创建AndroID Surface,而是为EGLSurface创建. (They’re different.)

总结

以上是内存溢出为你收集整理的android – 将相机渲染到多个表面 – 打开和关闭屏幕全部内容,希望文章能够帮你解决android – 将相机渲染到多个表面 – 打开和关闭屏幕所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1111042.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-29
下一篇 2022-05-29

发表评论

登录后才能评论

评论列表(0条)

保存