OpenGLopengl

Android基于Shader的图像处理(13)-相机分屏预览

2018-12-26  本文已影响40人  andev009

完整代码查看# AndroidShaderDemo下的SplitScreenOneActivity
想要的效果如下,上下两个屏幕显示相机预览图像:

split_sreen1.jpg

这里给出分屏预览的一种方式,在布局里使用GLSurfaceView和SurfaceView两个View分别展示相机预览,缺点是录制视频时不能保持画面的分屏特效,如果要想录制时也要分屏,那么分屏后的画面应该在一张图片纹理上,这个以后再说,这里先看两个View展示的效果。

在看这篇之前,最好先看之前的Camera开发Android java层封装EGL

分屏显示原理是,GLSurfaceView通过SurfaceTexture接收相机传来的数据显示预览图像,这时预览图像是个纹理,把纹理传给SurfaceView,这样就达到分屏显示的效果。当然因为SurfaceView没有OpenGL的运行环境,还要封装个离屏Render。
GLSurfaceView怎么显示相机预览图像就不重复了,重点看第二步,把纹理传给SurfaceView显示。
首先要为SurfaceView建立渲染线程,HandlerThread可以帮忙,简化不少工作。

handlerThread = new HandlerThread("preview");
handlerThread.start();
previewHandler = new Handler(handlerThread.getLooper());

之后就可以通过previewHandler来post渲染线程的指令了。
在GLSurfaceView的render回调里,初始化SurfaceView的Callback:

surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
        @Override
        public void surfaceCreated(SurfaceHolder surfaceHolder) {
            previewHandler.post(new Runnable() {
                @Override
                public void run() {
                    offScreenRender = new OffScreenRender(eglContext, surfaceView.getHolder().getSurface());
                    }
                });
        }
         ......
}

这里在preview线程里生成一个offScreenRender离屏render,render有了,下面在相机每帧回调时取得纹理,用offScreenRender画出来:

@Override
public void onFrameAvailableCallback(final VideoFrameData frameData) {
    previewHandler.post(new Runnable() {
        @Override
        public void run() {
            if(offScreenRender != null){
                offScreenRender.draw(frameData.getFilter(), frameData.getMatrix(), frameData.getTextureId()
                    ,frameData.getTimestamp());
                }
        }
    });
}

可见offScreenRender做了主要工作,GLSurfaceView和SurfaceView共享一个EGLContext:
1.建立OpenGL环境
2.发送OpenGL渲染指令
建立OpenGL环境的工作用到了之前的Android java层封装EGL,这里不再累述,重点是把SurfaceView的Surface传递给EglCore,这样EglCore才知道往哪里绘制。

发送OpenGL渲染指令封装成了:

public void draw(CameraInputFilter cameraInputFilter, float[] matrix, int textureId, long time) {
    cameraInputFilter.onDrawFrame(textureId);
    offSreenSurface.swapBuffers();
}

这里主要关注其中两个参数cameraInputFilter和textureId,textureId就是传来的纹理,cameraInputFilter这里直接显示,当然这里也可以做些特效,这样分屏后,上下两个画面显示就不一样了。

上一篇下一篇

猜你喜欢

热点阅读