camera2 opengl实现滤镜效果录制视频 二 双SurfaceView渲染

上一篇用到了EGLUtils这个类,initEGL函数有个EGLContext参数,这篇将用到

public void initEGL(EGLContext eglContext, Surface surface) 

双SurfaceView渲染其实很简单,只要两个线程,个跑个的的就OK了

不过有时候会有特殊需求比如

这里就用到纹理共享了,同一个纹理给两个surfaceview

关键点就是EGLContext参数,把第一个egl的EGLContext传给第二个egl就可以实现共享纹理了

EGLUtils eglUtils = new EGLUtils();
eglUtils.initEGL(mEglUtils.getContext(),mSurfaceView2.getHolder().getSurface());

贴代码

public class DoubleSurfaceView extends LinearLayout {

    private SurfaceView mSurfaceView1;
    private SurfaceView mSurfaceView2;

    private EGLUtils mEglUtils;
    private GLFramebuffer mFramebuffer;
    private SurfaceTexture mSurfaceTexture;
    private Surface mSurface;

    private final Object mObject1 = new Object();
    private final Object mObject2 = new Object();

    private String mCameraId;
    private CameraManager mCameraManager;
    private CameraCaptureSession mCameraCaptureSession;
    private CameraDevice mCameraDevice;
    private Handler mHandler;

    private int screenWidth1, screenHeight1,screenWidth2, screenHeight2;

    public DoubleSurfaceView(Context context) {
        super(context);
        init(context);
    }

    public DoubleSurfaceView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }



    private void init(Context context){
        LayoutInflater.from(context).inflate(R.layout.double_surface_view,this);
        mSurfaceView1 = findViewById(R.id.sv_camera1);
        mSurfaceView2 = findViewById(R.id.sv_camera2);
        initCamera2();
        mSurfaceView1.getHolder().addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder surfaceHolder) {

            }

            @Override
            public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
                screenWidth1 = i1;
                screenHeight1 = i2;
                Thread thread = new Thread(new SurfaceRunnable1());
                thread.start();
            }

            @Override
            public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
                if(mCameraCaptureSession != null){
                    mCameraCaptureSession.getDevice().close();
                    mCameraCaptureSession.close();
                    mCameraCaptureSession = null;
                }
                if(mSurface != null){
                    mSurface.release();
                    mSurface = null;
                }
                if(mSurfaceTexture != null){
                    mSurfaceTexture.release();
                    mSurfaceTexture = null;
                    synchronized (mObject1) {
                        mObject1.notifyAll();
                    }
                }
            }
        });

        mSurfaceView2.getHolder().addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder surfaceHolder) {

            }

            @Override
            public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
                screenWidth2 = i1;
                screenHeight2 = i2;
            }

            @Override
            public void surfaceDestroyed(SurfaceHolder surfaceHolder) {

            }
        });

    }

    public class SurfaceRunnable1 implements Runnable{
        @Override
        public void run() {
            mFramebuffer = new GLFramebuffer(getContext());
            GLRenderer renderer = new GLRenderer(getContext());

            mEglUtils = new EGLUtils();
            mEglUtils.initEGL(EGL14.EGL_NO_CONTEXT,mSurfaceView1.getHolder().getSurface());
            renderer.initShader();


            Size mPreviewSize =  getPreferredPreviewSize(mSizes, screenWidth1, screenHeight1);
            int previewWidth = mPreviewSize.getHeight();
            int previewHeight = mPreviewSize.getWidth();
            int left,top,viewWidth,viewHeight;
            if(previewHeight > previewWidth){
                left = 0;
                viewWidth = screenWidth1;
                viewHeight = (int)(previewHeight*1.0f/previewWidth*viewWidth);
                top = (screenHeight1 - viewHeight)/2;
            }else{
                top = 0;
                viewHeight = screenHeight1;
                viewWidth = (int)(previewWidth*1.0f/previewHeight*viewHeight);
                left = (screenWidth1 - viewWidth)/2;
            }
            Rect rect = new Rect();
            rect.left = left;
            rect.top = top;
            rect.right = left + viewWidth;
            rect.bottom = top + viewHeight;

            mFramebuffer.initFramebuffer(previewWidth,previewHeight);

            mSurfaceTexture = mFramebuffer.getSurfaceTexture();
            mSurfaceTexture.setDefaultBufferSize(previewWidth, previewHeight);
            mSurfaceTexture.setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() {
                @Override
                public void onFrameAvailable(SurfaceTexture surfaceTexture) {
                    synchronized (mObject1) {
                        mObject1.notifyAll();
                    }
                }
            });
            post(new Runnable() {
                @Override
                public void run() {
                    Thread thread = new Thread(new SurfaceRunnable2());
                    thread.start();
                }
            });

            openCamera2();
            while (true){
                synchronized (mObject1) {
                    try {
                        mObject1.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                if(mSurfaceTexture == null){
                    break;
                }
                mFramebuffer.drawFrameBuffer(previewWidth,previewHeight);
                synchronized (mObject2) {
                    mObject2.notifyAll();
                }

                GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);

                GLES20.glViewport(rect.left,rect.top,rect.width(),rect.height());

                mFramebuffer.drawFrame();

                renderer.drawFrame();
                mEglUtils.swap();

            }
            mEglUtils.release();
        }
    }
    public class SurfaceRunnable2 implements Runnable{
        @Override
        public void run() {
            EGLUtils eglUtils = new EGLUtils();
            eglUtils.initEGL(mEglUtils.getContext(),mSurfaceView2.getHolder().getSurface());
            GLRenderer renderer = new GLRenderer(getContext());
            renderer.initShader();

            Size mPreviewSize =  getPreferredPreviewSize(mSizes, screenWidth2, screenHeight2);
            int previewWidth = mPreviewSize.getHeight();
            int previewHeight = mPreviewSize.getWidth();
            int left,top,viewWidth,viewHeight;
            if(previewHeight > previewWidth){
                left = 0;
                viewWidth = screenWidth2;
                viewHeight = (int)(previewHeight*1.0f/previewWidth*viewWidth);
                top = (screenHeight2 - viewHeight)/2;
            }else{
                top = 0;
                viewHeight = screenHeight2;
                viewWidth = (int)(previewWidth*1.0f/previewHeight*viewHeight);
                left = (screenWidth2 - viewWidth)/2;
            }
            Rect rect = new Rect();
            rect.left = left;
            rect.top = top;
            rect.right = left + viewWidth;
            rect.bottom = top + viewHeight;

            while (true){
                synchronized (mObject2) {
                    try {
                        mObject2.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                if(mSurfaceTexture == null){
                    break;
                }
                GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);

                GLES20.glViewport(rect.left,rect.top,rect.width(),rect.height());

                mFramebuffer.drawFrame();
                renderer.drawFrame();
                eglUtils.swap();

            }
            eglUtils.release();
        }
    }

    private Size[] mSizes;
    private void initCamera2() {
        HandlerThread handlerThread = new HandlerThread("Camera2");
        handlerThread.start();
        mHandler = new Handler(handlerThread.getLooper());
        mCameraManager = (CameraManager) getContext().getSystemService(Context.CAMERA_SERVICE);
        try {
            String[] CameraIdList = mCameraManager.getCameraIdList();
            mCameraId = CameraIdList[0];
            CameraCharacteristics characteristics = mCameraManager.getCameraCharacteristics(mCameraId);
            characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
            StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
            if(map != null){
                mSizes = map.getOutputSizes(SurfaceTexture.class);
            }

        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }
    private void openCamera2(){
        if (PermissionChecker.checkSelfPermission(getContext(), Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
            try {
                mCameraManager.openCamera(mCameraId, stateCallback, mHandler);
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
        }
    }
    private CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
        @Override
        public void onOpened(@NonNull CameraDevice cameraDevice) {
            mCameraDevice = cameraDevice;
            takePreview();
        }

        @Override
        public void onDisconnected(@NonNull CameraDevice cameraDevice) {
            if (mCameraDevice != null) {
                mCameraDevice.close();
                mCameraDevice = null;
            }
        }

        @Override
        public void onError(@NonNull CameraDevice cameraDevice, int i) {

        }
    };

    private void takePreview() {
        try {
            mSurface = new Surface(mSurfaceTexture);
            final CaptureRequest.Builder builder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            builder.addTarget(mSurface);
            mCameraDevice.createCaptureSession(Arrays.asList(mSurface), new CameraCaptureSession.StateCallback() {
                @Override
                public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
                    if (null == mCameraDevice) return;
                    mCameraCaptureSession = cameraCaptureSession;
                    builder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
                    builder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
                    CaptureRequest previewRequest = builder.build();
                    try {
                        mCameraCaptureSession.setRepeatingRequest(previewRequest, null, mHandler);
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {

                }
            }, mHandler);

        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }
    private Size getPreferredPreviewSize(Size[] sizes, int width, int height) {
        List<Size> collectorSizes = new ArrayList<>();
        for (Size option : sizes) {
            if (width > height) {
                if (option.getWidth() > width && option.getHeight() > height) {
                    collectorSizes.add(option);
                }
            } else {
                if (option.getHeight() > width && option.getWidth() > height) {
                    collectorSizes.add(option);
                }
            }
        }
        if (collectorSizes.size() > 0) {
            return Collections.min(collectorSizes, new Comparator<Size>() {
                @Override
                public int compare(Size s1, Size s2) {
                    return Long.signum(s1.getWidth() * s1.getHeight() - s2.getWidth() * s2.getHeight());
                }
            });
        }
        return sizes[0];
    }

}

double_surface_view

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <SurfaceView
        android:id="@+id/sv_camera1"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>
    <SurfaceView
        android:id="@+id/sv_camera2"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

</LinearLayout>










  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值