2012-08-16 39 views
7

我正在嘗試製作自定義視頻應用程序。 Iwork僅使用清單2.2中的設置(API 8)。縱向模式下的MediaRecorder視頻捕捉

一切順利,但我不明白爲什麼肖像模式視頻與lanscape沒有什麼不同。

爲了使裝置的檢測範圍內改變surfaceChanged取向我使用此代碼()

 if (mCamera != null) { 

     Camera.Parameters p = mCamera.getParameters(); 

     try { 
      mCamera.stopPreview(); 
     } catch (Exception e) { 
      // TODO: handle exception 
     } 

     int previewWidth = 0; 
     int previewHeight = 0; 

     if (mPreviewSize != null) { 
      Display display = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); 
      int rotation = display.getRotation(); 

      switch (rotation) { 
      case Surface.ROTATION_0: 
       previewWidth = mPreviewSize.height; 
       previewHeight = mPreviewSize.width; 
       mCamera.setDisplayOrientation(90); 
       break; 

      case Surface.ROTATION_90: 
       previewWidth = mPreviewSize.width; 
       previewHeight = mPreviewSize.height; 
       mCamera.setDisplayOrientation(0); 
       break; 

      case Surface.ROTATION_180: 
       previewWidth = mPreviewSize.height; 
       previewHeight = mPreviewSize.width; 
       mCamera.setDisplayOrientation(270); 
       break; 

      case Surface.ROTATION_270: 
       previewWidth = mPreviewSize.width; 
       previewHeight = mPreviewSize.height; 
       mCamera.setDisplayOrientation(180); 
       break; 
      } 

      p.setPreviewSize(previewWidth, previewHeight); 
      mCamera.setParameters(p); 
     } 
    try { 
     mCamera.setPreviewDisplay(mHolder); 
     mCamera.startPreview(); 
    } catch (Exception e) { 
     Log.d(TAG, "Cannot start preview.", e); 
    } 
} 

就像一個魅力。如果我旋轉設備表面更改方向,請調用surfaceChanged,其中相機設置爲適當的DisplayRotation。

問題是如何確定以後如果視頻拍攝在景觀模式或肖像之一。正如我所有的視頻都是以橫向拍攝的。它不依賴於僅影響預覽過程的setDisplayOrientation。

還在探索我注意到,如果使用標準的相機應用程序寫入特殊標籤的視頻文件(的MediaInfo看到的)問題:旋轉:90爲人像拍攝的視頻。

但MediaRecorder類沒有。

似乎是這個問題。有人需要解決這個問題嗎?

回答

28

找到了! 事實上,你可以改變預覽,您可以標記該視頻,但沒有辦法真正改變視頻...(可能是速度問題或某事)

camera.setDisplayOrientation(90); 

要旋轉的預覽,然後

recorder.setOrientationHint(90); 

要將視頻標記爲旋轉90°,那麼手機在閱讀時會自動旋轉。

因此,所有你需要做的就是

  camera = Camera.open(); 
     //Set preview with a 90° ortientation 
     camera.setDisplayOrientation(90); 
     camera.unlock(); 

     holder = getHolder(); 
     holder.addCallback(this); 
     holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 

     recorder = new MediaRecorder(); 
     recorder.setCamera(camera); 
     recorder.setAudioSource(MediaRecorder.AudioSource.MIC); 
     recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT); 
     recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); 
     recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); 
     recorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP); 
     recorder.setOutputFile(getVideoFolder()+rnd.nextString()+".mp4"); 
     recorder.setPreviewDisplay(holder.getSurface()); 
     //Tags the video with a 90° angle in order to tell the phone how to display it 
     recorder.setOrientationHint(90); 

     if (recorder != null) { 
      try { 
       recorder.prepare(); 
      } catch (IllegalStateException e) { 
       Log.e("IllegalStateException", e.toString()); 
      } catch (IOException e) { 
       Log.e("IOException", e.toString()); 
      } 
     } 

     recorder.start(); 

希望它可以幫助;-)

+0

setOrientationHint僅適用於API 9.我有同樣的問題,但需要API 8 – AndroidDev 2013-01-30 20:23:55

+3

的解決方案我花了數小時試圖找出這個愚蠢的預覽定位問題。非常感謝@Taiko!下面是對我有用的東西:在實現'SurfaceHolder.Callback'的類的'onCreate'方法中,我包含了這個代碼:'mCamera = Camera.open(); mCamera.setDisplayOrientation(90); mCamera.unlock();'後面跟着'mediaRecorder = new MediaRecorder(); mediaRecorder.setCamera(mCamera);'。像魅力一樣工作! – Cat 2014-05-10 20:16:36

8

camera.setDisplayOrientation(90)並不適用於所有設備的工作。以下解決方案完美適用於不同的設備,並且還可以處理棉花糖運行時許可。

見setCameraRotation方法

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { 
    private SurfaceHolder mHolder; 
    private Camera mCamera; 
    public static int rotate; 
    private Context mContext; 

    public CameraPreview(Context context, Camera camera) { 
     super(context); 
     mCamera = camera; 
     mHolder = getHolder(); 
     mHolder.addCallback(this); 
     // deprecated setting, but required on Android versions prior to 3.0 
     mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
     mContext = context; 
    } 

    public void surfaceCreated(SurfaceHolder holder) { 
     try { 
      // create the surface and start camera preview 
      if (mCamera != null) { 
       mCamera.setPreviewDisplay(holder); 
       mCamera.startPreview(); 
      } 
     } catch (IOException e) { 
      Log.d(VIEW_LOG_TAG, "Error setting camera preview: " + e.getMessage()); 
     } 
    } 

    public void refreshCamera(Camera camera) { 
     if (mHolder.getSurface() == null) { 
      // preview surface does not exist 
      return; 
     } 
     // stop preview before making changes 
     stopPreview(); 
     // set preview size and make any resize, rotate or 
     // reformatting changes here 
     setCamera(camera); 

     // start preview with new settings 
     startPreview(); 
    } 

    public void stopPreview(){ 
     try { 
      if(mCamera != null) 
      mCamera.stopPreview(); 
     } catch (Exception e) { 
      // ignore: tried to stop a non-existent preview 
      e.printStackTrace(); 
     } 
    } 

    public void startPreview(){ 
     try { 
      if(mCamera != null) { 
       mCamera.setPreviewDisplay(mHolder); 
       mCamera.startPreview(); 
      }else{ 
       Log.d(VIEW_LOG_TAG, "Error starting camera preview: "); 
      } 
     } catch (Exception e) { 
      Log.d(VIEW_LOG_TAG, "Error starting camera preview: " + e.getMessage()); 
     } 
    } 

    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. 
     refreshCamera(mCamera); 
    } 

    public void setCamera(Camera camera) { 
     //method to set a camera instance 
     mCamera = camera; 
     /** 
     * add camera orientation and display rotation according to screen landscape or portrait 
     */ 
     setCameraRotation(); 
    } 

    @Override 
    public void surfaceDestroyed(SurfaceHolder holder) { 
     // TODO Auto-generated method stub 
     if(mCamera != null){ 
      mCamera.release(); 
     } 

    } 

    public void setCameraRotation() { 
     try { 

      Camera.CameraInfo camInfo = new Camera.CameraInfo(); 

      if (VideoCaptureActivity.cameraId == 0) 
       Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_BACK, camInfo); 
      else 
       Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_FRONT, camInfo); 
      int cameraRotationOffset = camInfo.orientation; 
      // ... 

      Camera.Parameters parameters = mCamera.getParameters(); 


      int rotation = ((Activity)mContext).getWindowManager().getDefaultDisplay().getRotation(); 
      int degrees = 0; 
      switch (rotation) { 
       case Surface.ROTATION_0: 
        degrees = 0; 
        break; // Natural orientation 
       case Surface.ROTATION_90: 
        degrees = 90; 
        break; // Landscape left 
       case Surface.ROTATION_180: 
        degrees = 180; 
        break;// Upside down 
       case Surface.ROTATION_270: 
        degrees = 270; 
        break;// Landscape right 
      } 
      int displayRotation; 
      if (camInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { 
       displayRotation = (cameraRotationOffset + degrees) % 360; 
       displayRotation = (360 - displayRotation) % 360; // compensate 
       // the 
       // mirror 
      } else { // back-facing 
       displayRotation = (cameraRotationOffset - degrees + 360) % 360; 
      } 

      mCamera.setDisplayOrientation(displayRotation); 


      if (camInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { 
       rotate = (360 + cameraRotationOffset + degrees) % 360; 
      } else { 
       rotate = (360 + cameraRotationOffset - degrees) % 360; 
      } 

      parameters.set("orientation", "portrait"); 
      parameters.setRotation(rotate); 
      mCamera.setParameters(parameters); 

     } catch (Exception e) { 

     } 
    } 



} 

現在準備的媒體記錄器,帶有正確的旋轉,這樣在正確的方向錄製的視頻播放。

mediaRecorder.setOrientationHint(CameraPreview。旋轉);

私人布爾prepareMediaRecorder(){

mediaRecorder = new MediaRecorder(); 

    mCamera.unlock(); 
    mediaRecorder.setCamera(mCamera); 

    mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); 
    mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); 
    mediaRecorder.setOrientationHint(CameraPreview.rotate); 

    mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_LOW)); 

    mediaRecorder.setOutputFile(filePath); 
    mediaRecorder.setMaxDuration(15000); // Set max duration 15 sec. 
    mediaRecorder.setMaxFileSize(10000000); // Set max file size 1M 

    try { 
     mediaRecorder.prepare(); 
    } catch (IllegalStateException e) { 
     releaseMediaRecorder(); 
     return false; 
    } catch (IOException e) { 
     releaseMediaRecorder(); 
     return false; 
    } 
    return true; 

} 

您可以下載完整的示例https://github.com/umesh-kushwaha/Android_Video_Recording_portrait

+0

setOrientationHint於事無補 - 視頻旋轉( – Alex 2016-08-02 12:21:31

+0

工作非常適合我謝謝:) – SimpleCoder 2016-08-29 16:20:30

+0

請編輯此部分 //創建面,並開始相機預覽 如果(mCamera == NULL){ mCamera.setPreviewDisplay(持有者。 ); mCamera.startPreview(); } 它應該是mCamera!= null – EdgarK 2016-09-13 14:22:31

相關問題