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

6
我需要在我的应用中有两个摄像头预览。然而,安卓相机一次只能提供一个预览。是否有任何方法将该预览流水线/复制到另一个视图中?我遇到了这个问题如何在Android中使用一个相机创建多个镜头或预览,他说:

在Android 3.0或更高版本上,您可以使用setPreviewTexture方法将预览数据导入OpenGL纹理,然后在GLSurfaceView或等效物中呈现到多个四边形中。

但我不知道如何在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) {

    }


}

输出: 在此输入图片描述

1
只是为了明确:您想要在两个相邻的窗口中显示来自单个相机的预览帧,还是想要并排显示来自两个不同相机的预览帧? - fadden
@fadden 我需要将单个摄像头的预览显示在两个相邻的窗口中。 - Abhishek V
@fadden 但是正如我所说,我不想使用onPreviewFrame来获取单个帧,因为它会引入一些延迟。 - Abhishek V
1
@AbhishekV 你完成这个任务了吗?能否分享一下你是如何完成的?我也卡在同样的地方,能帮帮我吗? - Erum
@ErumHannan 我无法解决那个问题。那只是我们项目中的一个小模块,我不能花太多时间在上面,因为我忙于其他项目。最终我使用了来自 onPreviewFrame() 方法的预览帧。这也不是很糟糕,如果您可以根据需要正确设置相机预览大小,就完全没有延迟了。 - Abhishek V
请分享您的工作代码。我对所有这些都很新,并且遇到了相同的问题。 - Hitesh Danidhariya
1个回答

11

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

然后,不再使用两个TextureViews,而是使用GLES渲染两个带有纹理的矩形,每个矩形占据单个视图的一半。这比渲染到两个不同的表面更容易(只需要关注一个EGL上下文)。如果您以前没有使用过OpenGL ES,则可能会有点学习曲线。

所需的组件可以在Grafika中找到。例如,考虑“持续捕获”和“显示+捕获摄像头”活动。两者都将相机输出直接传输到SurfaceTexture并进行两次渲染。对于它们来说,一次是在屏幕上,一次是在视频编码器的输入上,但是这是相同的思路。如果查看“硬件缩放器练习程序”,则可以看到它正在拍摄照片,并将其设置为在屏幕上移动的纹理矩形;您可以将其用作如何设置矩形大小和位置的示例。

还有“双重解码”,它使用一对TextureViews并排显示两个已解码电影。您不想执行它所做的操作-它正在接收来自两个不同来源的内容,而不是将单个来源显示两次。

各种活动都使用带有TextureViewSurfaceViewGLSurfaceView的GLES。每种视图类型都具有独特的优点和限制。

更新:新(比此答案更新)的“texture from camera”活动可能是最接近您想要的内容。它将相机预览发送到SurfaceTexture,并演示了如何通过使用GLES移动、调整大小、旋转和缩放图像。


谢谢。我会研究您提供的示例并告诉您结果。 - Abhishek V
@AbhishekV,你能告诉我这个解决方案是否适用于您吗?你能帮我吗?我需要将cameraInstance.startPreview()发送到SurfaceTexture吗? - user3233280
@user3233280 我没有继续研究那个问题。看看 Grafika 项目吧,我相信你会在那里找到一些有用的代码。 - Abhishek V
更新了答案--几个月后我添加了一个“来自相机的纹理”活动,使用GLES渲染相机预览。 - fadden

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接