2012-03-06 157 views
1

好吧,我正在嘗試開發一款應用程序,用前置攝像頭拍攝電影。 和我有一個奇怪的錯誤。預覽看起來不錯,但輸出的視頻出來,在低分辨率下一條綠線,並與高分辨率android前置攝像頭問題

這個綠線斷是代碼:

package feipeng.yacamcorder; 

import java.io.File; 
import java.io.IOException; 
import java.lang.reflect.Field; 
import java.lang.reflect.InvocationTargetException; 
import java.lang.reflect.Method; 

import android.app.Activity; 
import android.content.Context; 
import android.content.Intent; 
import android.hardware.Camera; 
import android.media.CamcorderProfile; 
import android.media.MediaRecorder; 
import android.media.MediaRecorder.AudioEncoder; 
import android.media.MediaRecorder.VideoEncoder; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 
import android.view.View; 
import android.view.Window; 
import android.widget.Button; 
import android.widget.Toast; 

/*** 
* TODO: 1. sound on/off 2. resolution change 
* 
* @author roman10 
* 
*/ 

public class Main extends Activity implements SurfaceHolder.Callback { 
    private SurfaceView prSurfaceView; 
    private Button prStartBtn; 
    private Button prSettingsBtn; 
    private boolean prRecordInProcess; 
    private SurfaceHolder prSurfaceHolder; 
    private Camera prCamera; 
    private final String cVideoFilePath = "/sdcard/r10videocam/"; 

    private Context prContext; 
    private MediaRecorder prMediaRecorder; 
    private CamcorderProfile mProfile; 
    private final int cMaxRecordDurationInMs = 30000; 

    private final long cMaxFileSizeInBytes = 5000000; 

    private final int cFrameRate = 20; 

    private File prRecordedFile; 
    private static final int REQUEST_DECODING_OPTIONS = 0; 
    private static final String TAG = "aaa"; 

    @Override 
    protected void onActivityResult(int requestCode, int resultCode, 
      Intent intent) { 
     super.onActivityResult(requestCode, resultCode, intent); 
     switch (requestCode) { 
     case REQUEST_DECODING_OPTIONS: 
      if (resultCode == RESULT_OK) { 
       updateEncodingOptions(); 
      } 
      break; 
     } 
    } 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     this.requestWindowFeature(Window.FEATURE_NO_TITLE); 
     prContext = this.getApplicationContext(); 
     setContentView(R.layout.main); 
     Utils.createDirIfNotExist(cVideoFilePath); 
     prSurfaceView = (SurfaceView) findViewById(R.id.surface_camera); 
     prStartBtn = (Button) findViewById(R.id.main_btn1); 
     prSettingsBtn = (Button) findViewById(R.id.main_btn2); 
     prRecordInProcess = false; 
     prStartBtn.setOnClickListener(new View.OnClickListener() { 
      // @Override 
      @Override 
      public void onClick(View v) { 
       if (prRecordInProcess == false) { 
        startRecording(); 
       } else { 
        stopRecording(); 
       } 
      } 
     }); 
     prSettingsBtn.setOnClickListener(new View.OnClickListener() { 
      // @Override 
      @Override 
      public void onClick(View v) { 
       Intent lIntent = new Intent(); 
       lIntent.setClass(prContext, 
         feipeng.yacamcorder.SettingsDialog.class); 
       startActivityForResult(lIntent, REQUEST_DECODING_OPTIONS); 
      } 
     }); 
     prSurfaceHolder = prSurfaceView.getHolder(); 
     prSurfaceHolder.addCallback(this); 
     prSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
     prMediaRecorder = new MediaRecorder(); 
    } 

    private Camera openFrontFacingCamera() { 
     Camera camera = null; 

     // Look for front-facing camera, using the Gingerbread API. 
     // Java reflection is used for backwards compatibility with 
     // pre-Gingerbread APIs. 
     try { 
      Class<?> cameraClass = Class.forName("android.hardware.Camera"); 
      Object cameraInfo = null; 
      Field field = null; 
      int cameraCount = 0; 
      Method getNumberOfCamerasMethod = cameraClass 
        .getMethod("getNumberOfCameras"); 
      if (getNumberOfCamerasMethod != null) { 
       cameraCount = (Integer) getNumberOfCamerasMethod.invoke(null, 
         (Object[]) null); 
      } 
      Class<?> cameraInfoClass = Class 
        .forName("android.hardware.Camera$CameraInfo"); 
      if (cameraInfoClass != null) { 
       cameraInfo = cameraInfoClass.newInstance(); 
      } 
      if (cameraInfo != null) { 
       field = cameraInfo.getClass().getField("facing"); 
      } 
      Method getCameraInfoMethod = cameraClass.getMethod("getCameraInfo", 
        Integer.TYPE, cameraInfoClass); 
      if (getCameraInfoMethod != null && cameraInfoClass != null 
        && field != null) { 
       for (int camIdx = 0; camIdx < cameraCount; camIdx++) { 
        getCameraInfoMethod.invoke(null, camIdx, cameraInfo); 
        int facing = field.getInt(cameraInfo); 
        if (facing == 1) { // Camera.CameraInfo.CAMERA_FACING_FRONT 
         try { 
          Method cameraOpenMethod = cameraClass.getMethod(
            "open", Integer.TYPE); 
          if (cameraOpenMethod != null) { 
           camera = (Camera) cameraOpenMethod.invoke(null, 
             camIdx); 
           mProfile = CamcorderProfile 
             .get(CamcorderProfile.QUALITY_LOW); 
          } 
         } catch (RuntimeException e) { 
          Log.e(TAG, 
            "Camera failed to open: " 
              + e.getLocalizedMessage()); 
         } 
        } 
       } 
      } 
     } 
     // Ignore the bevy of checked exceptions the Java Reflection API throws 
     // - if it fails, who cares. 
     catch (ClassNotFoundException e) { 
      Log.e(TAG, "ClassNotFoundException" + e.getLocalizedMessage()); 
     } catch (NoSuchMethodException e) { 
      Log.e(TAG, "NoSuchMethodException" + e.getLocalizedMessage()); 
     } catch (NoSuchFieldException e) { 
      Log.e(TAG, "NoSuchFieldException" + e.getLocalizedMessage()); 
     } catch (IllegalAccessException e) { 
      Log.e(TAG, "IllegalAccessException" + e.getLocalizedMessage()); 
     } catch (InvocationTargetException e) { 
      Log.e(TAG, "InvocationTargetException" + e.getLocalizedMessage()); 
     } catch (InstantiationException e) { 
      Log.e(TAG, "InstantiationException" + e.getLocalizedMessage()); 
     } catch (SecurityException e) { 
      Log.e(TAG, "SecurityException" + e.getLocalizedMessage()); 
     } 

     if (camera == null) { 
      // Try using the pre-Gingerbread APIs to open the camera. 
      try { 
       camera = Camera.open(); 
      } catch (RuntimeException e) { 
       Log.e(TAG, "Camera failed to open: " + e.getLocalizedMessage()); 
      } 
     } 

     return camera; 
    } 

    private boolean startRecording() { 
     prCamera.stopPreview(); 
     try { 
      prCamera.unlock(); 
      prMediaRecorder.setCamera(prCamera); 

      // set audio source as Microphone, video source as camera 
      // state: Initial=>Initialized 
      prMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); 
      prMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); 
      // set the file output format: 3gp or mp4 
      // state: Initialized=>DataSourceConfigured 
      String lVideoFileFullPath; 
      String lDisplayMsg = "Current container format: "; 
      if (Utils.puContainerFormat == SettingsDialog.cpu3GP) { 
       lDisplayMsg += "3GP\n"; 
       lVideoFileFullPath = ".3gp"; 
       prMediaRecorder 
         .setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); 
      } else if (Utils.puContainerFormat == SettingsDialog.cpuMP4) { 
       lDisplayMsg += "MP4\n"; 
       lVideoFileFullPath = ".mp4"; 
       prMediaRecorder 
         .setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); 
      } else { 
       lDisplayMsg += "3GP\n"; 
       lVideoFileFullPath = ".3gp"; 
       prMediaRecorder 
         .setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); 
      } 
      // the encoders: 
      // audio: AMR-NB 
      prMediaRecorder.setAudioEncoder(AudioEncoder.AMR_NB); 
      // video: H.263, MP4-SP, or H.264 
      // prMediaRecorder.setVideoEncoder(VideoEncoder.H263); 
      // prMediaRecorder.setVideoEncoder(VideoEncoder.MPEG_4_SP); 
      lDisplayMsg += "Current encoding format: "; 
      if (Utils.puEncodingFormat == SettingsDialog.cpuH263) { 
       lDisplayMsg += "H263\n"; 
       prMediaRecorder.setVideoEncoder(VideoEncoder.H263); 
      } else if (Utils.puEncodingFormat == SettingsDialog.cpuMP4_SP) { 
       lDisplayMsg += "MPEG4-SP\n"; 
       prMediaRecorder.setVideoEncoder(VideoEncoder.MPEG_4_SP); 
      } else if (Utils.puEncodingFormat == SettingsDialog.cpuH264) { 
       lDisplayMsg += "H264\n"; 
       prMediaRecorder.setVideoEncoder(VideoEncoder.H264); 
      } else { 
       lDisplayMsg += "H263\n"; 
       prMediaRecorder.setVideoEncoder(VideoEncoder.H263); 
      } 
      lVideoFileFullPath = cVideoFilePath 
        + String.valueOf(System.currentTimeMillis()) 
        + lVideoFileFullPath; 
      prRecordedFile = new File(lVideoFileFullPath); 
      prMediaRecorder.setOutputFile(prRecordedFile.getPath()); 
      if (Utils.puResolutionChoice == SettingsDialog.cpuRes176) { 
       prMediaRecorder.setVideoSize(176, 144); 
      } else if (Utils.puResolutionChoice == SettingsDialog.cpuRes320) { 
       prMediaRecorder.setVideoSize(320, 240); 
      } else if (Utils.puResolutionChoice == SettingsDialog.cpuRes720) { 
       prMediaRecorder.setVideoSize(720, 480); 
      } 
      Toast.makeText(prContext, lDisplayMsg, Toast.LENGTH_LONG).show(); 
      prMediaRecorder.setVideoFrameRate(cFrameRate); 
      prMediaRecorder.setPreviewDisplay(prSurfaceHolder.getSurface()); 
      prMediaRecorder.setMaxDuration(cMaxRecordDurationInMs); 
      prMediaRecorder.setMaxFileSize(cMaxFileSizeInBytes); 
      // prepare for capturing 
      // state: DataSourceConfigured => prepared 
      prMediaRecorder.prepare(); 
      // start recording 
      // state: prepared => recording 
      prMediaRecorder.start(); 
      prStartBtn.setText("Stop"); 
      prRecordInProcess = true; 
      return true; 
     } catch (IOException _le) { 
      _le.printStackTrace(); 
      return false; 
     } 
    } 

    private void stopRecording() { 
     prMediaRecorder.stop(); 
     prMediaRecorder.reset(); 
     try { 
      prCamera.reconnect(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     prStartBtn.setText("Start"); 
     prRecordInProcess = false; 
     prCamera.startPreview(); 
    } 

    // @Override 
    @Override 
    public void surfaceChanged(SurfaceHolder _holder, int _format, int _width, 
      int _height) { 
     Camera.Parameters lParam = prCamera.getParameters(); 
     // //lParam.setPreviewSize(_width, _height); 
     // //lParam.setPreviewSize(320, 240); 
     // lParam.setPreviewFormat(PixelFormat.JPEG); 
     prCamera.setParameters(lParam); 
     try { 
      prCamera.setPreviewDisplay(_holder); 
      prCamera.startPreview(); 
      // prPreviewRunning = true; 
     } catch (IOException _le) { 
      _le.printStackTrace(); 
     } 
    } 

    // @Override 
    @Override 
    public void surfaceCreated(SurfaceHolder arg0) { 

     prCamera = openFrontFacingCamera(); 

     if (prCamera == null) { 
      Toast.makeText(this.getApplicationContext(), 
        "Camera is not available!", Toast.LENGTH_SHORT).show(); 
      finish(); 
     } 
    } 

    // @Override 
    @Override 
    public void surfaceDestroyed(SurfaceHolder arg0) { 
     if (prRecordInProcess) { 
      stopRecording(); 
     } else { 
      prCamera.stopPreview(); 
     } 
     prMediaRecorder.release(); 
     prMediaRecorder = null; 
     prCamera.release(); 
     prCamera = null; 
    } 

    private void updateEncodingOptions() { 
     if (prRecordInProcess) { 
      stopRecording(); 
      startRecording(); 
      Toast.makeText(prContext, "Recording restarted with new options!", 
        Toast.LENGTH_SHORT).show(); 
     } else { 
      Toast.makeText(prContext, "Recording options updated!", 
        Toast.LENGTH_SHORT).show(); 
     } 
    } 
} 

附:使用galaxy s1的 。

有什麼想法?

+0

這是視頻輸出:http://www.youtube.com/watch?v = BeDnwipn7QU – 2012-03-06 17:04:50

回答

0

我在4.0.4上運行的Samsung Nexus S上試過了你的代碼,它運行良好。 的MediaRecorder設定如下:

private boolean startRecording() { 
     ... 
     prMediaRecorder.setCamera(prCamera); 
     prMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); 
     prMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); 
     prMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); 
     prMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); 
     prMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); 
     prMediaRecorder.setOutputFile("/sdcard/video.mp4"); 
     prMediaRecorder.setVideoSize(320, 240);//If higher produces error -19 
     prMediaRecorder.setVideoFrameRate(15);//If higher produces error -19 
     prMediaRecorder.setPreviewDisplay(prSurfaceHolder.getSurface()); 
     prMediaRecorder.setMaxDuration(cMaxRecordDurationInMs); 
     prMediaRecorder.setMaxFileSize(cMaxFileSizeInBytes); 
     prMediaRecorder.prepare(); 
     prMediaRecorder.start(); 
     ... 
}//endOfStartRecording() 

對於10秒記錄它產生〜300 KB大小的.mp4檔案。質量不是很好,但它是我能得到的最高質量。請記住,前置攝像頭不如後置攝像頭那麼強大。

+0

是的,這似乎是一個具體的三星Galaxy s1的問題。 – 2014-04-07 19:51:11