2012-08-16 58 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