本文介绍了在previewFrame previewCallback不会改变数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要做一些处理图像的图像处理的摄像头和一个SurfaceView显示,但我不知道如何修改摄像机架。我试图用一套previewCallbackWithBuffer和previewFrame但不如预期,框架不会被修改,他们不工作。

  / **基本型摄像机preVIEW类* /
公共类相机preVIEW延伸SurfaceView工具
        SurfaceHolder.Callback,摄像头。previewCallback {
    私人SurfaceHolder mHolder;
    私人相机mCamera;
    私人字节[] MDATA;
    专用长prevFrameTick = System.currentTimeMillis的();
    帆布mCanvas;

    公共摄像头preVIEW(上下文的背景下,相机摄像头){
        超(上下文);
        mCamera =摄像头;

        //安装SurfaceHolder.Callback所以我们得到通知时,该
        //下垫面创建和销毁。
        mHolder = getHolder();
        mHolder.addCallback(本);
        尺码previewSize = mCamera.getParameters()得到previewSize();
        MDATA =新的字节[(INT)(previewSize.height * previewSize.width * 1.5)];
        initBuffer();
        //德precated设置,但在Android上之前的版本3.0所需
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    私人无效initBuffer(){
        mCamera.addCallbackBuffer(MDATA);
        mCamera.addCallbackBuffer(MDATA);
        mCamera.addCallbackBuffer(MDATA);
        mCamera.set previewCallbackWithBuffer(本);
    }

    公共无效setCamera(照相机CAM){
        mCamera =凸轮;
        initBuffer();
    }

    公共无效surfaceCreated(SurfaceHolder持有者){
        //表面有被创建,现在告诉相机在哪里画的
        // preVIEW。
        尝试 {
            mCamera.set previewDisplay(保持器);
            initBuffer();
            mCamera.start preVIEW();
        }赶上(IOException异常E){
            Log.d(APP,
                    错误设置摄像头preVIEW:+ e.getMessage());
        }
    }

    公共无效surfaceDestroyed(SurfaceHolder持有者){
        //空。以释放相机preVIEW在您的活动的照顾。
    }

    公共无效surfaceChanged(SurfaceHolder持有人,INT格式,INT W,INT高){
        //如果你的preVIEW可以改变或旋转,把这些事件的关心在这里。
        //确保调整或重新格式化之前停止preVIEW。

        如果(mHolder.getSurface()== NULL){
            // preVIEW表面不存在
            返回;
        }

        在进行更改之前//停止preVIEW
        尝试 {
            mCamera.stop preVIEW();
        }赶上(例外五){
            //忽略:试图阻止一个不存在的preVIEW
        }

        //设置preVIEW大小并进行调整大小,旋转或
        //重新格式化的变化在这里

        //启动preVIEW使用新设置
        尝试 {
            mCamera.set previewDisplay(mHolder);
            initBuffer();
            mCamera.start preVIEW();
        }赶上(例外五){
            Log.d(APP,
                    错误启动摄像头preVIEW:+ e.getMessage());
        }
    }

    在previewFrame(byte []的数据,摄像头摄像头){公共无效
        // System.arraycopy(数据,0,MDATA,0,data.length);
        Log.e(关于previewFrame,data.length +
                +(System.currentTimeMillis的() -  prevFrameTick));
        prevFrameTick = System.currentTimeMillis的();
        MDATA =新的字节[data.length]
        mCamera.addCallbackBuffer(MDATA);
    }
}
 

解决方案

您不能修改发送到SurfaceView,如果您使用的是一套previewDisplay()调用preVIEW数据。在preVIEW视频流完全是管理你的应用程序之外,并不能访问它。

有几个选项,你可以:

  1. 您可以放置​​在SurfaceView,顶部的第二个观点,如ImageView的或其他SurfaceView,并绘制收到的previewFrame回调到该视图中的数据。你必须做的preVIEW回调格式(通常为NV21)显示某些颜色/像素格式转换,很明显,你必须运行在该数据的图像处理第一次为好。这是不是很有效,除非你愿意写一些JNI code。

  2. 在Android 3.0或更高版本,可以使用<一个href="http://developer.android.com/reference/android/hardware/Camera.html#set$p$pviewTexture%28android.graphics.SurfaceTexture%29">Camera.set$p$pviewTexture()方法,以及管相机preVIEW流入一个OpenGL纹理通过使用SurfaceTexture对象,你那么可以在显示之前操纵的OpenGL。然后,你就根本不需要了preVIEW回调。这是,如果GPU处理是足够的效率更高。您还可以使用OpenGL的readPixels呼吁得到处理preVIEW数据返回到您的应用程序,如果你想显示它/过程中它一些其他的方式。

I want to do some image processing with images from camera and display it on a SurfaceView but I don't know how to modify the camera frame. I tried to use setPreviewCallbackWithBuffer and onPreviewFrame but they do not work as expected, the frame is not modified.

/** A basic Camera preview class */
public class CameraPreview extends SurfaceView implements
        SurfaceHolder.Callback, Camera.PreviewCallback {
    private SurfaceHolder mHolder;
    private Camera mCamera;
    private byte[] mData;
    private long prevFrameTick = System.currentTimeMillis();
    Canvas mCanvas;

    public CameraPreview(Context context, Camera camera) {
        super(context);
        mCamera = camera;

        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = getHolder();
        mHolder.addCallback(this);
        Size previewSize = mCamera.getParameters().getPreviewSize();
        mData = new byte[(int) (previewSize.height * previewSize.width * 1.5)];
        initBuffer();
        // deprecated setting, but required on Android versions prior to 3.0
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    private void initBuffer() {
        mCamera.addCallbackBuffer(mData);
        mCamera.addCallbackBuffer(mData);
        mCamera.addCallbackBuffer(mData);
        mCamera.setPreviewCallbackWithBuffer(this);
    }

    public void setCamera(Camera cam) {
        mCamera = cam;
        initBuffer();
    }

    public void surfaceCreated(SurfaceHolder holder) {
        // The Surface has been created, now tell the camera where to draw the
        // preview.
        try {
            mCamera.setPreviewDisplay(holder);
            initBuffer();
            mCamera.startPreview();
        } catch (IOException e) {
            Log.d("APP",
                    "Error setting camera preview: " + e.getMessage());
        }
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        // empty. Take care of releasing the Camera preview in your activity.
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        // If your preview can change or rotate, take care of those events here.
        // Make sure to stop the preview before resizing or reformatting it.

        if (mHolder.getSurface() == null) {
            // preview surface does not exist
            return;
        }

        // stop preview before making changes
        try {
            mCamera.stopPreview();
        } catch (Exception e) {
            // ignore: tried to stop a non-existent preview
        }

        // set preview size and make any resize, rotate or
        // reformatting changes here

        // start preview with new settings
        try {
            mCamera.setPreviewDisplay(mHolder);
            initBuffer();
            mCamera.startPreview();
        } catch (Exception e) {
            Log.d("APP",
                    "Error starting camera preview: " + e.getMessage());
        }
    }

    public void onPreviewFrame(byte[] data, Camera camera) {
        // System.arraycopy(data, 0, mData, 0, data.length);
        Log.e("onPreviewFrame", data.length + " "
                + (System.currentTimeMillis() - prevFrameTick));
        prevFrameTick = System.currentTimeMillis();
        mData = new byte[data.length];
        mCamera.addCallbackBuffer(mData);
    }
}
解决方案

You cannot modify the preview data sent to a SurfaceView, if you're using the setPreviewDisplay() call. The preview video stream is managed entirely outside of your application and isn't accessible to it.

There are a few options you can take:

  1. You can place a second view on top of the SurfaceView, such as an ImageView or another SurfaceView, and draw the data received by the onPreviewFrame callback into this view. You'll have to do some color/pixel format conversion from the preview callback format (usually NV21) for display, and obviously you have to run your image processing on that data first as well. This isn't very efficient, unless you're willing to write some JNI code.

  2. On Android 3.0 or newer, you can use the Camera.setPreviewTexture() method, and pipe the camera preview stream into an OpenGL texture by using a SurfaceTexture object, which you can then manipulate in OpenGL before displaying. Then you don't need the preview callbacks at all. This is more efficient if GPU processing is sufficient. You can also use the OpenGL readPixels call to get the processed preview data back to your application, if you want to display it/process it some other way.

这篇关于在previewFrame previewCallback不会改变数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-26 05:47