6

I need two camera previews in my app. However, android camera can give only one preview at a time. Is there any way to pipeline/copy that preview to another view? I came across this question How to create multi lenses or preview using one camera in Android and he says that

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.

But I have no idea how to render that to multiple quads in GLSurfaceView.I need to support android 4.0+. But I don't want to use preview frame from preview callback. It causes significant delay. Any help would be appreciated. Thanks!!

Here is my code for single preview

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) {

    }


}

Output: enter image description here

Community
  • 1
  • 1
Abhishek V
  • 12,488
  • 6
  • 51
  • 63
  • 1
    Just to be clear: do you want to have preview frames from a *single* camera shown in two adjacent windows, or preview frames from *two different cameras* shown side-by-side? – fadden Mar 20 '14 at 14:48
  • @fadden I need preview from single camera shown in two adjacent Windows. – Abhishek V Mar 20 '14 at 14:55
  • @fadden But as I said, I don't want to use `onPreviewFrame` to get the individual frames as it introduces some delay. – Abhishek V Mar 20 '14 at 15:20
  • 1
    @AbhishekV have u achieved this task can u pls share how u have done i also stuck at the same point can u help me – Erum Oct 18 '14 at 11:24
  • @ ErumHannan I couldn't solve that problem. It was only small module in our project and I couldn't spend much time on that as I got busy on other projects. I ended up using preview frames from **onPreviewFrame()** method. It is not that bad either and if you can set the camera preview size properly according to your needs, there is absolutely no delay at all. – Abhishek V Oct 18 '14 at 12:37
  • Please share your working code.I am new to all stuff and facing same issue. – Hitesh Danidhariya May 31 '18 at 10:21

1 Answers1

11

Start by sending the camera preview to a SurfaceTexture instead of a Surface associated with a View. That takes the output of the camera and makes it available for use as a GLES texture.

Then, instead of having two TextureViews, just render two textured quads with GLES, each of which occupies half of a single View. This is easier than rendering to two different surfaces (only one EGL context to worry about). If you haven't worked with OpenGL ES before there can be a bit of a learning curve.

The pieces you need can be found in Grafika. Consider for example the "Continuous capture" and "Show + capture camera" activities. Both direct the camera output to a SurfaceTexture and render it twice. For these, it's once to the screen and once to the input of a video encoder, but it's the same idea. If you look at "Hardware scaler exerciser" you can see it blitting a textured quad that bounces around the screen; you can use this as an example of how to set the size and position of the quad.

There's also "Double decode", which is using a pair of TextureViews to show two decoded movies side-by-side. You don't want to do what it does -- it's receiving content from two different sources, not showing a single source twice.

The various activities use GLES with TextureView, SurfaceView, and GLSurfaceView. Each view type comes with unique benefits and limitations.

Update: The new(er than this answer) "texture from camera" activity is probably the closest to what you want. It sends the camera preview to a SurfaceTexture and demonstrates how to move, resize, rotate, and zoom the image by rendering it with GLES.

fadden
  • 51,356
  • 5
  • 116
  • 166
  • Thank You. I will work on the examples you provided and let you know. – Abhishek V Mar 21 '14 at 04:40
  • @AbhishekV can u pls tell me will this solution works for u ? can u pls help me may i need to send cameraInstance.startPreview() to SurfaceTexture ?? – user3233280 Oct 18 '14 at 15:32
  • @user3233280 I didn't work on that problem further.Have a look at Grafika project. I am sure you will find some useful code there. – Abhishek V Oct 18 '14 at 19:02
  • Updated the answer -- I added a "texture from camera" activity a couple months later that renders the camera preview with GLES. – fadden Oct 19 '14 at 04:16