做了个实时视频采集的东西,代码仿照这个写的,代码基本上一样。调了半天,发现了一个相当奇怪的问题:
一开始发现Run了之后回调函数没有跑,就是那个每次Preview新建帧时应该被回调的onPreviewFrame()。不知道具体是怎么回事,什么错也不报,总之是这个函数里的代码木有执行。
   结果想用Debug模式看一下是哪出的问题,一点一点单步运行,然后发现居然正常了,回调执行了,PC端画面也有了!
然后反复试,发现直接Run as androidXXX的话有极低的概率成功(目前就成功过一次),
如果用Debug跑,需要在surfaceCreated()里加个断点,然后单步运行几下,就基本上能成。
求问这是怎么回事啊?PS:用的MOTO ME865的机器,刚查了下有人说MOTO的机器不调用onPreviewFrame(),可我这debug以后确实成了(而且不是100%成功率)AndroidCameraVideo实时视频监控

解决方案 »

  1.   

    我不知道 我是否真正理解了你的意思 你用Camera.setPreviewCallback ()
    来接收每一帧数据然后 存储 这一帧的数据?在onPreviewFrame 中 我原来只进行 Toast操作 是OK的 可以达到一致输出楼主贴一下你的代码看看
      

  2.   

    public class MonitorFragment extends Fragment {
    public static final int MEDIA_TYPE_IMAGE = 1;
    public static final int MEDIA_TYPE_VIDEO = 2;
    private String TAG = "tag_CameraActivity";
    private Camera mCamera = null;
    private CameraPreview mPreview = null;
    private MediaRecorder mMediaRecorder = null;
    private boolean isRecording = false; @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
    Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    View ContentView;
    ContentView = inflater.inflate(R.layout.monitorview, null);
    return ContentView;
    } /**
     * This is where we perform additional setup for the fragment that's either
     * not related to the fragment's layout or must be done after the layout is
     * drawn.
     */
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    Button captureButton = (Button) getActivity().findViewById(
    R.id.button_capture);
    captureButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    if (isRecording) {
    // 停止录像并释放camera
    mMediaRecorder.stop(); // 停止录像
    releaseMediaRecorder();// 释放MediaRecorder对象
    mCamera.lock(); // 将控制权从MediaRecorder 交回camera // 通知用户录像已停止
    setCaptureButtonText("Capture");
    isRecording = false;
    } else {
    // 初始化视频camera
    if (prepareVideoRecorder()) {
    // Camera已可用并解锁,MediaRecorder已就绪,
    // 现在可以开始录像
    mMediaRecorder.start(); // 通知用户录像已开始
    Log.v(TAG,
    "capture button click, preparevideorecorder() success");
    setCaptureButtonText("Stop");
    isRecording = true;
    } else {
    // 准备未能完成,释放camera
    releaseMediaRecorder();
    // 通知用户
    Log.v(TAG,
    "capture button click, preparevideorecorder() failed");
    }
    }
    }
    });
    // 创建Camera实例
    mCamera = getCameraInstance();
    setCameraDisplayOrientation(getActivity(),
    Camera.CameraInfo.CAMERA_FACING_BACK, mCamera);// 设置预览方向
    // 创建Preview view并将其设为activity中的内容
    mPreview = new CameraPreview(getActivity(), mCamera);
    FrameLayout preview = (FrameLayout) getActivity().findViewById(
    R.id.camera_preview);
    preview.addView(mPreview);
    } /*
     * release hardware camera
     * 
     * @see android.app.Activity#onDestroy()
     */
    @Override
    public void onDestroy() {
    super.onDestroy();
    releaseCamera();
    } private boolean checkCameraHardware() {
    if (getActivity().getPackageManager().hasSystemFeature(
    PackageManager.FEATURE_CAMERA)) {
    // 摄像头存在
    Log.v(TAG, "Camera check success.");
    return true;
    } else {
    // 摄像头不存在
    Log.v(TAG, "Camera check failed.");
    return false;
    }
    } /** A safe way to get an instance of the Camera object. */
    private Camera getCameraInstance() {
    if (!checkCameraHardware())
    return null;
    Camera c = null;
    try {
    // c = Camera.open(); // attempt to get a Camera instance
    c = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
    } catch (Exception e) {
    // Camera is not available (in use or does not exist)
    }
    return c; // returns null if camera is unavailable
    } public static void setCameraDisplayOrientation(Activity activity,
    int cameraId, Camera camera) {
    Camera.CameraInfo info = new Camera.CameraInfo();
    Camera.getCameraInfo(cameraId, info);
    int rotation = activity.getWindowManager().getDefaultDisplay()
    .getRotation();
    int degrees = 0;
    switch (rotation) {
    case Surface.ROTATION_0:
    degrees = 0;
    break;
    case Surface.ROTATION_90:
    degrees = 90;
    break;
    case Surface.ROTATION_180:
    degrees = 180;
    break;
    case Surface.ROTATION_270:
    degrees = 270;
    break;
    } int result;
    if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
    result = (info.orientation + degrees) % 360;
    result = (360 - result) % 360; // compensate the mirror
    } else { // back-facing
    result = (info.orientation - degrees + 360) % 360;
    }
    camera.setDisplayOrientation(result);
    } private boolean prepareVideoRecorder() { if (mCamera == null) {
    mCamera = getCameraInstance();
    setCameraDisplayOrientation(getActivity(),
    Camera.CameraInfo.CAMERA_FACING_BACK, mCamera);
    }
    mMediaRecorder = new MediaRecorder(); // Step 1: Unlock and set camera to MediaRecorder
    mCamera.unlock();
    mMediaRecorder.setCamera(mCamera); // Step 2: Set sources
    mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
    mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); // Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
    // mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
    mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_LOW));
    // Step 4: Set output file
    mMediaRecorder.setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO)
    .toString());
    Log.v(TAG, "path = " + getOutputMediaFile(MEDIA_TYPE_VIDEO).toString()); // Step 5: Set the preview output
    if (mPreview == null) {
    mPreview = new CameraPreview(getActivity(), mCamera);
    mMediaRecorder.setPreviewDisplay(mPreview.getHolder().getSurface());
    }
    // Step 6: Prepare configured MediaRecorder
    try {
    mMediaRecorder.prepare();
    } catch (IllegalStateException e) {
    Log.d(TAG,
    "IllegalStateException preparing MediaRecorder: "
    + e.getMessage());
    releaseMediaRecorder();
    return false;
    } catch (IOException e) {
    Log.d(TAG, "IOException preparing MediaRecorder: " + e.getMessage());
    releaseMediaRecorder();
    return false;
    }
    return true;
    } /** Create a File for saving an image or video */
    private static File getOutputMediaFile(int type) {
    // To be safe, you should check that the SDCard is mounted
    // using Environment.getExternalStorageState() before doing this. File mediaStorageDir = new File(
    Environment
    .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
    "TestCamera");
    // This location works best if you want the created images to be shared
    // between applications and persist after your app has been uninstalled. // Create the storage directory if it does not exist
    if (!mediaStorageDir.exists()) {
    if (!mediaStorageDir.mkdirs()) {
    Log.d("MyCameraApp", "failed to create directory");
    return null;
    }
    } // Create a media file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",
    Locale.SIMPLIFIED_CHINESE).format(new Date());
    File mediaFile;
    if (type == MEDIA_TYPE_IMAGE) {
    mediaFile = new File(mediaStorageDir.getPath() + File.separator
    + "IMG_" + timeStamp + ".jpg");
    } else if (type == MEDIA_TYPE_VIDEO) {
    mediaFile = new File(mediaStorageDir.getPath() + File.separator
    + "VID_" + timeStamp + ".mp4");
    } else {
    return null;
    } return mediaFile;
    } private void setCaptureButtonText(String text) {
    Button button = (Button) getActivity()
    .findViewById(R.id.button_capture);
    button.setText(text);
    } private void releaseMediaRecorder() {
    if (mMediaRecorder != null) {
    mMediaRecorder.reset(); // clear recorder configuration
    mMediaRecorder.release(); // release the recorder object
    mMediaRecorder = null;
    mCamera.lock(); // lock camera for later use
    }
    } private void releaseCamera() {
    if (mCamera != null) {
    mCamera.release(); // release the camera for other applications
    mCamera = null;
    }
    }
    }
      

  3.   

    public class CameraPreview extends SurfaceView implements
    SurfaceHolder.Callback {
    public SurfaceHolder mHolder;
    private String mIpname = "192.168.137.1";
    private Camera mCamera; // hardware? graphics?
    private String TAG = "tag_CameraPreview";
    private static final int mPort=6001; 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);
    // deprecated setting, but required on Android versions prior to 3.0
    // mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    } @Override
    public void surfaceCreated(SurfaceHolder holder) {
    // The Surface has been created, now tell the camera where to draw the
    // preview.
    try {
    mCamera.setPreviewDisplay(holder); mCamera.setPreviewCallback(new StreamIt(mIpname)); // 设置回调的类 mCamera.startPreview();
    } catch (IOException e) {
    Log.d(TAG, "Error setting camera preview: " + e.getMessage());
    }
    } @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
    // empty. Take care of releasing the Camera preview in your activity.
    } @Override
    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);
    mCamera.startPreview(); } catch (Exception e) {
    Log.d(TAG, "Error starting camera preview: " + e.getMessage());
    }
    } /*
     * Test solution 1 solution 1: use callback method of Camera.PreviewCallback
     * , to send every preview frame to the pc server
     */ class StreamIt implements Camera.PreviewCallback {
    private String ipname; public StreamIt(String ipname) {
    this.ipname = ipname;
    Log.v(TAG, "StreamIt hs been newed");
    } @Override
    public void onPreviewFrame(byte[] data, Camera camera) {
    Log.v(TAG, "onPreviewFrame has been called");
    Size size = camera.getParameters().getPreviewSize();

    try {
    // 调用image.compressToJpeg()将YUV格式图像数据data转为jpg格式
    YuvImage image = new YuvImage(data, ImageFormat.NV21,
    size.width, size.height, null);
    if (image != null) {
    ByteArrayOutputStream outstream = new ByteArrayOutputStream();
    image.compressToJpeg(
    new Rect(0, 0, size.width, size.height), 80,
    outstream);
    outstream.flush();
    // 启用线程将图像数据发送出去
    Thread th = new MyThread(outstream, ipname);
    th.start();
    }
    } catch (Exception ex) {
    Log.e("Sys", "Error:" + ex.getMessage());
    Log.v(TAG, "catch exception in on PreviewFrame");
    }
    }
    } class MyThread extends Thread {
    private byte byteBuffer[] = new byte[1024];
    private OutputStream outsocket;
    private ByteArrayOutputStream myoutputstream;
    private String ipname; public MyThread(ByteArrayOutputStream myoutputstream, String ipname) {
    this.myoutputstream = myoutputstream;
    this.ipname = ipname;
    Log.v(TAG, "MyThread has been newed");
    try {
    myoutputstream.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    } public void run() {
    try {
    // 将图像数据通过Socket发送出去
    Log.v(TAG, "new thread to send socket,in run()");
    Log.v(TAG, "ipname = " + ipname+ "Port = "+mPort);
    Socket tempSocket = new Socket(ipname, mPort);
    outsocket = tempSocket.getOutputStream();
    ByteArrayInputStream inputstream = new ByteArrayInputStream(
    myoutputstream.toByteArray());
    int amount;
    while ((amount = inputstream.read(byteBuffer)) != -1) {
    outsocket.write(byteBuffer, 0, amount);
    }
    myoutputstream.flush();
    myoutputstream.close();
    tempSocket.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    } }
    }