首頁  >  問答  >  主體

Android Camera.startPreview()启动未报错,但SurfaceView无画面输出

问题如标题所示,不知道问题出在那里,能正常出数据,但是画面就是没有,请各位大神指点迷津
代码如下

package com.jiechu.wnd.sl;

import android.content.Context;
import android.graphics.ImageFormat;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;

import java.io.IOException;
import java.util.List;

/**
 * Created by zhuyt on 2016/10/20.
 */

public class LiveStreamDisplay extends SurfaceView implements SurfaceHolder.Callback,View.OnTouchListener{
    private static String TAG = LiveStreamDisplay.class.getSimpleName();
    Camera mCamInance=null;
    Camera.Parameters mCamPmr = null;
    PreviewAction mAction;
    SurfaceHolder mHolder;

    int displayWidth = 360;
    int displayHeight = 480;

    int current_width;
    int current_height;
    double iAspectRatio = 3.0/3.0;//设备宽高比
    int iDelta = 0x7FFFFF;
    int current_fps = 25;
    int current_rate;
    int current_camera = Camera.CameraInfo.CAMERA_FACING_BACK;
    String current_video_encode = "H264";

    boolean isPreview=false;

    long mTimestampBegin=0;
    long mTimestampRec=0;

    int current_picture_format = ImageFormat.NV21;

    List<Camera.Size> mSupportPreviewSizes;
    List<int[]> mSupportPreviewFPSRanges;


    private byte[] mYuvDataBuff;
    int iYuvBuffSize = 0;

    public LiveStreamDisplay(Context context,int pCamNum,int iWidth,int iHeight) {
        super(context);
        current_camera = pCamNum>=0?pCamNum: Camera.CameraInfo.CAMERA_FACING_BACK;
        displayWidth = iWidth>0?iWidth:displayWidth;
        displayHeight = iHeight>0?iHeight:displayHeight;
        mHolder = getHolder();
        initTouchView();
    }

    public void initCamera(int pCamNum,PreviewAction pPA){
        if(mCamInance==null){
            if (pPA!=null && pPA instanceof PreviewAction){
                mAction = pPA;
            }
            current_camera = pCamNum>=0?pCamNum: Camera.CameraInfo.CAMERA_FACING_BACK;
            mCamInance = Camera.open(current_camera);

            mCamPmr = mCamInance.getParameters();

            List<Integer> tpFormat = mCamPmr.getSupportedPreviewFormats();
            if(tpFormat.contains(ImageFormat.NV21)){
                mCamPmr.setPreviewFormat(ImageFormat.NV21);
            }else{
                Log.e(TAG, "initCamera: Camera not support NV21 format data!");
                try {
                    throw new Throwable("Camera not support NV21 format data");
                } catch (Throwable throwable) {
                    throwable.printStackTrace();
                }
            }

            if (tpFormat.contains(ImageFormat.JPEG)){
                mCamPmr.setPictureFormat(ImageFormat.JPEG);
            }

            //找到手机支持的最大的分辨率,并赋值
            mSupportPreviewSizes = mCamPmr.getSupportedPreviewSizes();
            Camera.Size temp=null;
            for (Camera.Size s:mSupportPreviewSizes){
                //寻找投备支持最大宽高
                /*if(temp==null){
                    temp = s;
                }else{
                    if(s.width>temp.width){
                        temp = s;
                    }
                }*/
                //寻找设备最合适宽高
                Log.e(TAG, "initCamera: current element:[W]:"+s.width+" [H]:"+s.height);
                if (Math.abs(current_width-displayWidth)<iDelta){
                    iDelta = Math.abs(current_width-displayHeight);
                    temp = s;
                }

            }


            current_width = temp.width;
            current_height = temp.height;
            mCamPmr.setPreviewSize(current_width,current_height);
            //mCamPmr.setPictureSize(current_width,current_height);
            temp=null;

            //寻找最合适设备的帧率
            int[] tempFPS;
            mSupportPreviewFPSRanges = mCamPmr.getSupportedPreviewFpsRange();
            for(int[] mi:mSupportPreviewFPSRanges){
                Log.e(TAG, "initCamera: FPSRange:min["+mi[0]+"] max["+mi[1]+"]");
                //还没有赋值到实际的相机参数中去.需要注意
                //mCamPmr.setPreviewFpsRange((int)(mi[0]/1000),(int)(mi[1]/1000));
            }





            mCamInance.setParameters(mCamPmr);
            iAspectRatio = current_width/current_height;
            iYuvBuffSize = current_width*current_height*3/2;
            mYuvDataBuff = new byte[iYuvBuffSize];

            Log.e(TAG, "initCamera: Test Debug 1");
            mCamInance.addCallbackBuffer(mYuvDataBuff);
            Log.e(TAG, "initCamera: Test Debug 2");
            mCamInance.setPreviewCallback(new LivePreivewCallback());
            Log.e(TAG, "initCamera: Test Debug 3");
            mCamInance.setDisplayOrientation(90);
            try {
                mCamInance.setPreviewDisplay(mHolder);
            } catch (IOException e) {
                e.printStackTrace();
            }

            setOnTouchListener(this);
            //requestLayout();
            mCamInance.startPreview();

            isPreview=true;
            mTimestampBegin = System.currentTimeMillis();

        }else{
            Log.e(TAG, "initCamera: Camera Instance had exists!");
        }
    }

    public void release(){
        mCamInance.stopPreview();
        mCamInance.setPreviewCallback(null);
        try {
            mCamInance.setPreviewDisplay(null);
        } catch (IOException e) {
            e.printStackTrace();
        }
        mYuvDataBuff = null;

        mCamInance.release();
        isPreview=false;
    }

    public void setAction(PreviewAction pPa){
        if(null==pPa)return;
        mAction = pPa;
    }


    //设置点击屏幕进行对焦
    void initTouchView(){
        this.setFocusable(true);
        this.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                mCamInance.autoFocus(null);
                return false;
            }
        });
    }




    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        //initCamera(current_camera,mAction);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        release();
        initCamera(current_camera,mAction);
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        //release();
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Log.e(TAG, "onTouch: Camera AutoFoucs!");
        mCamInance.autoFocus(null);
        return false;
    }

    class LivePreivewCallback implements Camera.PreviewCallback{
        @Override
        public void onPreviewFrame(byte[] data, Camera camera) {
            mTimestampRec = System.currentTimeMillis();
            if (data==null){
                Log.e(TAG, "onPreviewFrame: undefined video data!");
            }else{
                if (mAction!=null && data.length==iYuvBuffSize && mAction instanceof PreviewAction){
                    Log.e(TAG, "onPreviewFrame: find video data & call doTakeVideo[length:"+data.length+"]!");
                    mAction.doTakeVideo(mYuvDataBuff,mYuvDataBuff.length);
                }else{
                    Log.e(TAG, "onPreviewFrame: find video data but else error!");
                }

            }
            mCamInance.addCallbackBuffer(mYuvDataBuff);
        }
    }
    //根据传入的宽高值,重新计算VIEW的宽高并应用
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int tpWidth = MeasureSpec.getSize(widthMeasureSpec);
        int tpHeight = MeasureSpec.getSize(heightMeasureSpec);

        if (tpWidth>tpHeight*iAspectRatio){
            tpWidth = (int)(tpHeight*iAspectRatio+.5);
        }else{
            tpHeight = (int)(tpWidth/iAspectRatio+.5);
        }
        Log.e(TAG, "onMeasure: reconstructed!");
        super.onMeasure(MeasureSpec.makeMeasureSpec(tpWidth,MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(tpHeight,MeasureSpec.EXACTLY));
    }

    public interface PreviewAction{
        void doTakePicture();
        void doTakeVideo(byte[] data,int length);
    }
}

调用如下

Display mDisplay = getWindowManager().getDefaultDisplay();
        DisplayMetrics mDet=new DisplayMetrics();
        mDisplay.getMetrics(mDet);

        mLSD = new LiveStreamDisplay(getApplicationContext(), Camera.CameraInfo.CAMERA_FACING_BACK,mDet.widthPixels,mDet.heightPixels);
...

addContentView(mLSD,new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        mLSD.initCamera(0,new LiveStreamDisplay.PreviewAction() {
            @Override
            public void doTakePicture() {

            }

            @Override
            public void doTakeVideo(byte[] data, int length) {
                Log.e(TAG, "doTakeVideo: get video data!");
            }
        });

这是输出

10-20 13:30:11.336 5970-5970/com.jiechu.wnd.lv E/LiveStreamDisplay: onPreviewFrame: find video data & call doTakeVideo[length:1382400]!
10-20 13:30:11.336 5970-5970/com.jiechu.wnd.lv E/MainActivity: doTakeVideo: get video data!
10-20 13:30:11.337 5970-5970/com.jiechu.wnd.lv D/Camera-JNI: Adding callback buffer to queue, 1 total
10-20 13:30:11.448 5970-6053/com.jiechu.wnd.lv D/Camera-JNI: Allocating callback buffer
10-20 13:30:11.484 5970-6053/com.jiechu.wnd.lv D/dalvikvm: GC_FOR_ALLOC freed 1350K (10), 17% free 14810K/17632K, paused 36ms, total 36ms
10-20 13:30:11.489 5970-5970/com.jiechu.wnd.lv I/CameraFramework: handleMessage: 16
10-20 13:30:11.489 5970-5970/com.jiechu.wnd.lv D/Camera-JNI: setHasPreviewCallback: installed:1, manualBuffer:0
10-20 13:30:11.491 5970-5970/com.jiechu.wnd.lv E/LiveStreamDisplay: onPreviewFrame: find video data & call doTakeVideo[length:1382400]!
10-20 13:30:11.491 5970-5970/com.jiechu.wnd.lv E/MainActivity: doTakeVideo: get video data!
10-20 13:30:11.491 5970-5970/com.jiechu.wnd.lv D/Camera-JNI: Adding callback buffer to queue, 1 total
10-20 13:30:11.609 5970-5983/com.jiechu.wnd.lv D/Camera-JNI: Allocating callback buffer
怪我咯怪我咯2763 天前735

全部回覆(0)我來回復

無回覆
  • 取消回覆