2011-06-17 41 views
7

我正在使用Android開發(SDK 2.2),我想用mediaRecorder進行視頻錄製,同時在每個預覽幀上執行一些操作。與MediaRecorder在項目視頻錄製時的Android預覽處理

我錄製視頻,在其他的我用的是onPreviewFrame(byte[] dataCamera camera)(從PreviewCallback),用於處理圖片預覽。

我試圖創建一個攝像頭並使用它與mediaRecordersetCamera功能),但它不起作用。

是否有可能在同一時間執行兩個操作?

其實我不明白如何鏈接兩件事?

我的代碼:

package ch.fraise; 

import java.io.IOException; 
import android.app.Activity; 
import android.hardware.Camera; 
import android.hardware.Camera.PreviewCallback; 
import android.media.MediaRecorder; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.Menu; 
import android.view.MenuInflater; 
import android.view.MenuItem; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 

public class CameraActivity extends Activity implements SurfaceHolder.Callback, 
    Camera.AutoFocusCallback { 

private SurfaceView preview; 
private SurfaceHolder previewHolder; 

private MediaRecorder mRecorder; 
private Camera mCamera; 
private boolean mPreviewRunning = false; 
private boolean mCaptureFrame = false; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    Log.e("", "Begin onCreate"); 
    setContentView(R.layout.main); 

    preview = (SurfaceView) findViewById(R.id.surfaceView1); 
    previewHolder = preview.getHolder(); 
    previewHolder.addCallback(this); 
    previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 

    mRecorder = new MediaRecorder(); 
} 

@Override 
public void onResume() { 
    super.onResume(); 
} 

@Override 
public void onPause() { 
    super.onPause(); 
} 

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    MenuInflater inflater = getMenuInflater(); 
    inflater.inflate(R.menu.capture_menu, menu); 
    return true; 
} 

public void startRecording() { 
    Log.e("", "Begin StartRecording"); 
    mCaptureFrame = true; 
    mRecorder.start(); 
} 

public void stopRecording() { 
    Log.e("", "Begin StopChange"); 
    mRecorder.stop(); 
} 

@Override 
public boolean onOptionsItemSelected(MenuItem item) { 
    // Handle item selection 
    switch (item.getItemId()) { 
    case R.id.startRecording: 
     startRecording(); 
     return true; 
    case R.id.stopRecording: 
     stopRecording(); 
     return true; 
    default: 
     return super.onOptionsItemSelected(item); 
    } 
} 

@Override 
public void surfaceCreated(SurfaceHolder holder) { 
    Log.e("", "Begin surfaceDestroy"); 
    mCamera = Camera.open(); 
} 

@Override 
public void surfaceDestroyed(SurfaceHolder holder) { 
    mCamera.stopPreview(); 
    mPreviewRunning = false; 
    mCamera.release(); 

    mRecorder.reset(); 
    mRecorder.release(); 
} 

@Override 
public void onAutoFocus(boolean success, Camera camera) { 
    // TODO Auto-generated method stub 

} 

/* 
* PreviewCallback() 
* 
* this callback captures the preview at every frame and puts it in a byte 
* buffer. we will evaluate if this is a frame that we want to process, and 
* if so, we will send it to an asynchronous thread that will process it to 
* an ARGB Bitmap and POST it to the server 
*/ 
PreviewCallback previewCallback = new PreviewCallback() { 
    public void onPreviewFrame(byte[] data, Camera camera) { 
     Log.e("", "onPreviewFrame pass"); 
     if (mCaptureFrame) { 
      mCaptureFrame = false; 
      // new FrameHandler().execute(data); 
     } 
    } 
}; 

@Override 
public void surfaceChanged(SurfaceHolder holder, int format, int width, 
     int height) { 
    Log.e("", "Begin SurfaceChange"); 

    mRecorder.reset(); 
    mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); 
    mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); 
    mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP); 
    mRecorder.setOutputFile("/sdcard/videotest2.mp4"); 
    mRecorder.setVideoFrameRate(30); 

    mRecorder.setPreviewDisplay(previewHolder.getSurface()); 
    try { 
     mRecorder.prepare(); 
    } catch (IllegalStateException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

    if (mPreviewRunning) 
     mCamera.stopPreview(); 

    Camera.Parameters p = mCamera.getParameters(); 
    // p.setPreviewSize(width, height); 
    mCamera.setParameters(p); 

    try { 
     mCamera.setPreviewDisplay(holder); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

    mCamera.setPreviewCallback(previewCallback); 

    mCamera.startPreview(); 
    mPreviewRunning = true; 

} 

} 

和XML文件中的權限:

<uses-permission android:name="android.permission.CAMERA" /> 
<uses-permission android:name="android.permission.RECORD_AUDIO" /> 
<uses-permission android:name="android.permission.RECORD_VIDEO" /> 
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 
+0

什麼是你的問題? – YXD

+0

我已經添加了我的代碼,但我有以下錯誤W/System.err(5476):java.io.IOException:準備失敗。應用程序在第一個錯誤之後運行,直到我開始錄製視頻。然後我有一個java.lang.IllegalStateException E/AndroidRuntime(5476):在android.media.MediaRecorder.start(本地方法) –

回答

0

您只需添加標籤來您的清單文件。因此它會work.Sample如下所示的代碼。

如: -

</application> 
    <uses-permission android:name="android.permission.CAMERA" /> 
<uses-permission android:name="android.permission.RECORD_AUDIO" /> 
<uses-permission android:name="android.permission.RECORD_VIDEO" /> 
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 
    ***<uses-feature android:name="android.hardware.camera" />*** 
</manifest> 
+0

您好nikhilkilivayil!謝謝你的幫助!不幸的是,我已經添加了這一行,但它似乎也不起作用。我已經看到錄製開始時,onFramePreview停止被調用!也許他們可以一起跑!! –

+0

我有同樣的問題。如果你有答案請通知我.. – nikhilkilivayil

+0

我也有這個問題。也許我們可以嘗試解碼視頻,同時獲得原始圖像實時? –

4

錄音時,onPreviewFrame不會被調用,一旦你開始錄製時,您不能訪問視頻流。奇怪的是,onPreviewFrame似乎並沒有得到所謂錄製要麼...之後

+1

這是錯誤的。您只需在錄製後再次開始收聽。 –

0

,如果使用的是OS 2.2或更高版本,然後用這個方法您準備失敗等異常將刪除

public boolean startRecording() { 
    try { 
     camera.unlock(); 

     mediaRecorder = new MediaRecorder(); 
     mediaRecorder.setCamera(camera); 
     mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); 
     mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); 
     mediaRecorder.setProfile(CamcorderProfile 
       .get(CamcorderProfile.QUALITY_HIGH)); 

     File tempFile = new File(getOutputMediaFile(MEDIA_TYPE_VIDEO) 
       .toString()); 

     mediaRecorder.setOutputFile(tempFile.getPath()); 
     mediaRecorder.setVideoFrameRate(videoFramesPerSecond); 
     mediaRecorder.setVideoSize(surfaceView.getWidth(), 
       surfaceView.getHeight()); 
     mediaRecorder.setPreviewDisplay(surfaceHolder.getSurface()); 
     mediaRecorder.setMaxFileSize(maxFileSizeInBytes); 
     mediaRecorder.prepare(); 
     mediaRecorder.start(); 

     return true; 
    } catch (IllegalStateException e) { 
     Log.e(TAG, e.getMessage()); 
     e.printStackTrace(); 
     return false; 
    } catch (IOException e) { 
     Log.e(TAG, e.getMessage()); 
     e.printStackTrace(); 
     return false; 
    } 
} 
6

尤里卡!訣竅在於將PreviewCallback附加在surfaceChanged(...)SurfaceHolder.Callback!完成此操作後,MediaRecorder運行後您將繼續獲取預覽幀數據!

例如:

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 
    mCamera.setPreviewCallback(new PreviewCallback() { 
      public void onPreviewFrame(byte[] _data, Camera _camera) { 
       Log.d("onPreviewFrame-surfaceChanged",String.format("Got %d bytes of camera data", _data.length)); 
      } 
     }); 

} 
+1

我這樣做,但仍然不能在MediaRecorder運行後獲得預覽幀數據!它真的適合你嗎? – whutdyp

+0

是的,那時我正在使用Android 4.2。確保你連接SufaceHolder。開始MediaRecorder之前的回調。張貼您的來源,我會看看。 – dbro

+0

@dbro,no。你的把戲不起作用。如果我調用'mMediaRecorder.setCamera(mCamera)'方法,那麼我必須在不允許獲取預覽幀之前調用mCamera.unlock()。如果我沒有調用'mMediaRecorder.setCamera(mCamera)'方法,'mMediaRecorder.start()'會因'IllegalStateException'崩潰,因爲相機已經在使用。你能發佈更多(或全部)代碼嗎?你如何做你的尤里卡技巧? –