2011-11-29 114 views
4

美好的一天!我正在學習如何使用MediaRecorder錄製視頻,但錄製的視頻在播放時已損壞。看這個截圖:http://www.4shared.com/photo/QtmJCHRi/corrupted-video.html。左上角標有紅色矩形的照片是相機可以看到的。但它很小,重複着,有很多綠色區域。請告知我做錯了什麼。硬件是三星Galaxy S2(GT-I9100,Android 2.3.5)。我試圖按照這個教程:http://developer.android.com/guide/topics/media/camera.html#saving-media使用Android MediaRecorder錄製的視頻在Samsung Galaxy S2上損壞

先謝謝您!

CameraRecorderActivity.java

package cz.ryvo.android.camerarecorder; 

import java.io.File; 
import java.io.IOException; 
import java.text.SimpleDateFormat; 
import java.util.Date; 
import android.app.Activity; 
import android.content.Context; 
import android.content.pm.PackageManager; 
import android.hardware.Camera; 
import android.hardware.Camera.CameraInfo; 
import android.media.CamcorderProfile; 
import android.media.MediaRecorder; 
import android.os.Bundle; 
import android.os.Environment; 
import android.util.Log; 
import android.view.SurfaceHolder; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.Button; 
import android.widget.FrameLayout; 

public class CameraRecorderActivity extends Activity 
implements SurfaceHolder.Callback, OnClickListener { 

private static final String TAG = "CameraRecorderActivity"; 

public static final int MEDIA_TYPE_IMAGE = 1; 
public static final int MEDIA_TYPE_VIDEO = 2; 

private Camera mCamera; 
private CameraPreview mPreview; 
private MediaRecorder mMediaRecorder; 
private Button captureButton; 
private boolean isRecording = false; 

/** Called when the activity is first created. */ 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 
    // Create an instance of Camera. 
    mCamera = getCameraInstance(); 
    // Create preview view and set it as the content of our activity. 
    mPreview = new CameraPreview(this, mCamera); 
    int i = R.id.camera_preview; 
    Object o = this.findViewById(i); 
    FrameLayout preview = (FrameLayout) o; 
    preview.addView(mPreview); 

// Add a listener to the Capture button 
    captureButton = (Button) findViewById(R.id.button_capture); 
    captureButton.setOnClickListener(
     new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       if (isRecording) { 
        // stop recording and release camera 
        mMediaRecorder.stop(); // stop the recording 
        releaseMediaRecorder(); // release the MediaRecorder object 
        mCamera.lock();   // take camera access back from MediaRecorder 

        // inform the user that recording has stopped 
        setCaptureButtonText("Capture"); 
        isRecording = false; 
       } else { 
        // initialize video camera 
        if (prepareVideoRecorder()) { 
         // Camera is available and unlocked, MediaRecorder is prepared, 
         // now you can start recording 
         mMediaRecorder.start(); 

         // inform the user that recording has started 
         setCaptureButtonText("Stop"); 
         isRecording = true; 
        } else { 
         // prepare didn't work, release the camera 
         releaseMediaRecorder(); 
         // inform user 
        } 
       } 
      } 
     } 
    ); 
} 

public void setCaptureButtonText(String s) { 
    captureButton.setText(s); 
} 

@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.startPreview(); 
    } catch (IOException e) { 
     Log.d(TAG, "Error setting camera preview: " + e.getMessage()); 
    } 
} 

@Override 
public void surfaceChanged(SurfaceHolder holder, int format, int width, 
     int height) { 
    // TODO Auto-generated method stub 
} 

@Override 
public void surfaceDestroyed(SurfaceHolder holder) { 
    // TODO Auto-generated method stub 
} 

/** 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), "MyCameraApp"); 
    // 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").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 boolean prepareVideoRecorder(){ 
    //mCamera = getCameraInstance(); 
    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); 
    mMediaRecorder.setVideoSize(720, 480); 
    // Step 3: Set a CamcorderProfile (requires API Level 8 or higher) 
    mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH)); 
    // Step 4: Set output file 
    mMediaRecorder.setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO).toString()); 
    // Step 5: Set the preview output 
    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; 
} 


@Override 
public void onClick(View v) { 
    /* 
    Log.i("onClick", "BEGIN"); 
    if(!recording) { 
     recording = startRecording(); 
    } else { 
     stopRecording(); 
     recording = false; 
    } 
    Log.i("onClick", "END"); 
    */ 
} 

@Override 
protected void onPause() { 
    super.onPause(); 
    releaseMediaRecorder();  // if you are using MediaRecorder, release it first 
    releaseCamera();    // release the camera immediately on pause event 
} 

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; 
    } 
} 

    private Camera getCameraInstance(){ 
      Camera c = null; 
      try { 
       c = Camera.open(); // attempt to get a Camera instance 
       //c = this.open(); // attempt to get a Camera instance 
      } 
      catch (Exception e){ 
       // Camera is not available (in use or does not exist) 
      } 
      return c; // returns null if camera is unavailable 
    } 

    public Camera open() { 
     int numberOfCameras = Camera.getNumberOfCameras(); 
     CameraInfo cameraInfo = new CameraInfo(); 
     for (int i = 0; i < numberOfCameras; i++) { 
      Camera.getCameraInfo(i, cameraInfo); 
      if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) { 
       return Camera.open(i); 
      } 
     } 
     return null; 
    }  
} 

CameraPreview.java

package cz.ryvo.android.camerarecorder; 

import java.io.IOException; 
import android.content.Context; 
import android.hardware.Camera; 
import android.util.Log; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { 

private static final String TAG = "CameraPreview"; 

private SurfaceHolder mHolder; 
private Camera mCamera; 

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); 
} 

public void surfaceCreated(SurfaceHolder holder) { 
    // The Surface has been created, now tell the camera where to draw the preview. 
    try { 
     mCamera.setPreviewDisplay(holder); 
     mCamera.startPreview(); 
    } catch (IOException e) { 
     Log.d(TAG, "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 
    } 

    // 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()); 
    } 
    } 
} 
+0

事實上,你可以在高清分辨率記錄的問題。檢查我的答案在這裏:http://stackoverflow.com/questions/7225571/camcorderprofile-quality-high-resolution-produces-green-flickering-video/10995975#10995975 – Tvaroh

回答

5

我讀到它的地方(我認爲這是在SO)。問題是顯然,三星Galaxy不支持以高質量錄製(CamcorderProfile.QUALITY_HIGH)。

試用CamcorderProfile.QUALITY_LOW。看看它是否有效。

編輯:我發現了同樣的問題here

+2

謝謝你的建議SeRPRo。我嘗試了QUALITY_LOW。它的工作原理,但不幸的是,最高分辨率僅720x480。不過,三星的相機應用程序可以以1920x1080的分辨率錄製視頻。我在[此線程](http://forum.xda-developers.com/showthread.php?t=1104970)中指出,SecCamera和SecMediaRecorder(位於/ system/android)中的特殊類必須用於捕獲該解決方案中的視頻還提供了Camera和MediaRecorder不提供的其他特殊功能。如果我成功地使它工作,我會在這裏發佈我的代碼。 – Vojtech

+0

@ user1071282我很高興能夠提供幫助,我希望儘快看到代碼正常工作。 – SERPRO

+0

你有沒有這個 –

相關問題