两个视图上的Android Camera预览(多镜头相机预览)

时间:2014-03-20 10:25:57

标签: android android-camera

我的应用中需要两个相机预览。但是,Android相机一次只能提供一个预览。有没有办法将该预览管道/复制到另一个视图?我遇到了这个问题How to create multi lenses or preview using one camera in Android,他说那个

On Android 3.0 or later, you can use the setPreviewTexture method to pipe the preview data into an OpenGL texture, which you can then render to multiple quads in a GLSurfaceView or equivalent.

但是我不知道如何将它呈现给GLSurfaceView中的多个四边形。我需要支持android 4.0+。但我不想使用预览回调中的预览帧。它会导致严重的延误。任何帮助,将不胜感激。谢谢!

这是我的单预览代码

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/black"
    tools:context=".MainActivity" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        android:weightSum="10" >

        <TextureView
            android:id="@+id/textureView1"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="5" />

        <TextureView
            android:id="@+id/textureView2"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="5" />
    </LinearLayout>

</RelativeLayout>

MainActivity.java

public class MainActivity extends Activity implements SurfaceTextureListener{

    private Camera mCamera;
    private TextureView mTextureView1;
    private TextureView mTextureView2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mTextureView1 = (TextureView) findViewById(R.id.textureView1);
        mTextureView2 = (TextureView) findViewById(R.id.textureView2);

        mTextureView1.setSurfaceTextureListener(this);
    }



    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width,
            int height) {


        try {
            mCamera = Camera.open(getCameraId());
            mCamera.setPreviewTexture(surface);
            CameraInfo cameraInfo = new CameraInfo();
            Camera.getCameraInfo(getCameraId(), cameraInfo);
            setCameraDisplayOrientation(this, getCameraId(), mCamera);
            mCamera.startPreview();

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        try {
            mCamera.stopPreview();
            mCamera.release();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width,
            int height) {


    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {

    }


}

输出: enter image description here

1 个答案:

答案 0 :(得分:10)

首先将相机预览发送到SurfaceTexture,而不是与视图关联的Surface。这需要相机的输出并使其可用作GLES纹理。

然后,不要使用两个TextureViews,而是使用GLES渲染两个带纹理的四边形,每个四边形占据一个视图的一半。这比渲染到两个不同的表面(只需要担心一个EGL上下文)更容易。如果您还没有使用过OpenGL ES,那么可能会有一些学习曲线。

您需要的部分可以在Grafika中找到。例如,考虑&#34;连续捕获&#34;和&#34;显示+捕捉相机&#34;活动。两者都将摄像机输出定向到SurfaceTexture并渲染两次。对于这些,它一次到屏幕,一次到视频编码器的输入,但它是相同的想法。如果你看一下&#34;硬件缩放器训练器&#34;你可以看到它在屏幕上反弹的纹理四边形;您可以将此作为如何设置四边形的大小和位置的示例。

还有&#34; Double decode&#34;,它使用一对TextureViews来并排显示两个解码的电影。你不想做它做的事情 - 它从两个不同的来源接收内容,而不是两次显示一个来源。

各种活动将GLES与TextureViewSurfaceViewGLSurfaceView结合使用。每种视图类型都有其独特的优点和局限性。

更新:新的(比此答案更早)&#34; texture from camera&#34;活动可能是最接近你想要的。它将相机预览发送到SurfaceTexture,并演示如何通过使用GLES渲染图像来移动,调整大小,旋转和缩放图像。