2012-07-11 131 views
13

我記錄使用下面的代碼的視頻和它完美的記錄,但是當它播放視頻,它起着倒置。Android相機錄製視頻,但播放倒掛

我試過設置mrec.setOrientationHint(180)mrec.prepare();之前,但它是無用的。任何提示?

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

import android.app.Activity; 
import android.hardware.Camera; 
import android.media.MediaRecorder; 
import android.os.Bundle; 
import android.os.Environment; 
import android.util.Log; 
import android.view.Menu; 
import android.view.MenuItem; 
import android.view.Surface; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 
import android.view.Window; 

/** 
* @author SANA HASSAN 
*/ 
public class CameraSurfaceView extends Activity { 

    private Preview mPreview; 
    private MediaRecorder mrec = new MediaRecorder(); 
    private int cameraId = 0; 
    private Camera mCamera; 


    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     requestWindowFeature(Window.FEATURE_NO_TITLE); 

     mPreview = new Preview(this); 
     setContentView(mPreview); 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     menu.add(0, 0, 0, "Start"); 
     menu.add(0, 1, 0, "Stop"); 
     return super.onCreateOptionsMenu(menu); 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     switch (item.getItemId()) { 
      case 0: 
       try { 
        startRecording(); 
       } 
       catch (Exception e) { 
        e.printStackTrace(); 
        mrec.release(); 
       } 
       break; 

      case 1: 
       mrec.stop(); 
       mrec.release(); 
       mrec = null; 
       break; 

      default: 
       break; 
     } 
     return super.onOptionsItemSelected(item); 
    } 

    protected void startRecording() throws IOException { 

     mrec = new MediaRecorder(); 
     mrec.setCamera(mCamera); 
     mCamera.unlock(); 
     File directory = new File(Environment.getExternalStorageDirectory()+"/NICUVideos"); 
     directory.mkdirs(); 
     mrec.setAudioSource(MediaRecorder.AudioSource.MIC); 
     mrec.setVideoSource(MediaRecorder.VideoSource.CAMERA); 
     mrec.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); 
     mrec.setOutputFile(Environment.getExternalStorageDirectory()+"/NICUVideos/"+System.currentTimeMillis()+".mp4"); 
     mrec.setPreviewDisplay(mPreview.getHolder().getSurface()); 
     mrec.setVideoSize(640, 480); 

     Method[] methods = mrec.getClass().getMethods(); 
     for (Method method: methods){ 
      try{ 
       if(method.getName().equals("setAudioEncodingBitRate")){ 
        method.invoke(mrec, 12200); 
       } 
       else if(method.getName().equals("setVideoEncodingBitRate")){ 
        method.invoke(mrec, 800000); 
       } 
       else if(method.getName().equals("setAudioSamplingRate")){ 
        method.invoke(mrec, 8000); 
       } 
       else if(method.getName().equals("setVideoFrameRate")){ 
        method.invoke(mrec, 20); 
       } 
      } 
      catch (IllegalArgumentException e) { 
       e.printStackTrace(); 
      } 
      catch (IllegalAccessException e) { 
       e.printStackTrace(); 
      } 
      catch (InvocationTargetException e) { 
       e.printStackTrace(); 
      } 
     } 
     mrec.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); 
     mrec.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP); 
     mrec.setMaxDuration(60000); // 60 seconds 
     mrec.setMaxFileSize(10000000); // Approximately 10 megabytes 
     mrec.prepare(); 
     mrec.start(); 
    } 

    protected void stopRecording() { 
     mrec.stop(); 
     mrec.release(); 
     mCamera.release(); 
    } 

    class Preview extends SurfaceView implements SurfaceHolder.Callback { 
     SurfaceHolder mHolder; 
     Activity activity; 

     Preview(Activity activity) { 
      super(activity); 
      mHolder = getHolder(); 
      mHolder.addCallback(this); 
      mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
     } 

     public void surfaceCreated(SurfaceHolder holder) { 

      Camera.CameraInfo info=new Camera.CameraInfo(); 
      for (int i=0; i < Camera.getNumberOfCameras(); i++) { 
       Camera.getCameraInfo(i, info); 
       if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { 
        mCamera=Camera.open(i); 
        cameraId = i; 
       } 
      } 

      try { 
       mCamera.setPreviewDisplay(holder); 
      } catch (IOException exception) { 
       mCamera.release(); 
       mCamera = null; 
      } 
     } 

     public void surfaceDestroyed(SurfaceHolder holder) { 
      mCamera.stopPreview(); 
      mCamera.release(); 
      mCamera = null; 
     } 

     public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 
      setCameraDisplayOrientation(mCamera); 
      mCamera.startPreview(); 
     } 

     public void setCameraDisplayOrientation(Camera camera) { 
      Camera.CameraInfo info = new Camera.CameraInfo(); 
      Camera.getCameraInfo(cameraId, info); 

      int rotation = CameraSurfaceView.this.getWindowManager().getDefaultDisplay().getRotation(); 
      int degrees = 0; 
      switch (rotation) { 
       case Surface.ROTATION_0: degrees = 0; break; 
       case Surface.ROTATION_90: degrees = 90; break; 
       case Surface.ROTATION_180: degrees = 180; break; 
       case Surface.ROTATION_270: degrees = 270; break; 
      } 

      int result; 
      if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { 
       result = (info.orientation + degrees) % 360; 
       result = (360 - result) % 360; // compensate the mirror 
      } else { // back-facing 
       result = (info.orientation - degrees + 360) % 360; 
      } 
      Log.d(Vars.TAG, "Result = "+result); 
      camera.setDisplayOrientation(result); 
     } 
    } 

} 
+0

這是否在設​​備上只發生?你試過不同的嗎? – Ronnie 2012-07-25 14:58:41

+0

你確定它不是媒體播放器設置嗎?其他視頻以正確的方向播放? – Ronnie 2012-07-25 15:00:04

+0

是的,我100%確定它不是媒體播放器設置。我的手機是Atrix2,我現在不打擾其他手機。 – Sana 2012-07-26 02:28:38

回答

5

這應該在mrec.prepare();方法之前被稱爲

setOrientationHint(degrees); 

Link

編輯: 嘗試mCamera.setDisplayOrientation(degrees);

0 for landscape 
90 for portrait 
180 & 270 don't work very well and give weird results. 

一些老玩家和編碼器不解釋這FL這就是爲什麼視頻播放顛倒。

+0

我做過了,但那不起作用,我已經在我的問題中說過了。 – Sana 2012-07-11 05:50:48

+0

您是否嘗試過'mrec.setDisplayOrientation(0);'?你不應該在那裏指定180,因爲這與許多視頻播放器混淆。另外,請嘗試使用不同的視頻播放器播放視頻,這可以解釋合成矩陣。 – 2012-07-11 05:52:59

+0

而不是180我該如何嘗試?並沒有什麼mrec.setDisplayOrientation的'(0);'類型,我想你指的是相機調整角度,如果你看到我的代碼,我已經照顧那!我瞄準2.3設備 – Sana 2012-07-11 05:54:51

15

此問題是由於Android的通過只是設置一些元數據,而不是實際旋轉視頻,然後是一些播放軟件忽略了設置處理旋轉。

正如the docs指出:

注意某些視頻播放器可以播放選擇過程中忽略的視頻compostion矩陣。

你的選擇是要麼使用能理解被設置或重新編碼,它已經記錄到正確的方向後,視頻元數據不同的播放軟件。從您的描述中不清楚哪些是您的案例中更好的解決方案。

0

最後我發現,摩托羅拉手機在玩這是在人像模式中的視頻問題。

爲了克服視頻的旋轉,我都採用了最好的解決辦法是把視頻上傳到服務器上使用命令ffmpeg -i input.mp4 -c:v mpeg4 -c:a copy -c:s copy -vf "transpose=2" output.mp4

如果你覺得有另一種方式運行ffmpeg,請不要讓我知道。

0

多一個解決方案是旋轉你的活動,以便它的方向是相同的傳感器方向。也就是說,背景照相機的風景和前置攝像頭的顛倒肖像。這btw不會修復前置攝像頭的鏡像效果。還有一個難題是你必須在這些旋轉的活動中實現你的用戶界面,以遵循活動方向。

1

我知道您的問題,

視頻使用Media RecorderCamera,所以你需要rotate Media Recorder。使用下面的代碼應該解決你的問題。

/** 
* 
* @param mMediaRecorder 
* @return 
*/ 
public static MediaRecorder rotateBackVideo(MediaRecorder mMediaRecorder) { 
    /** 
    * Define Orientation of video in here, 
    * if in portrait mode, use value = 90, 
    * if in landscape mode, use value = 0 
    */ 
    switch (CustomCamera.current_orientation) { 
     case 0: 
      mMediaRecorder.setOrientationHint(90); 
      break; 
     case 90: 
      mMediaRecorder.setOrientationHint(180); 
      break; 
     case 180: 
      mMediaRecorder.setOrientationHint(270); 
      break; 
     case 270: 
      mMediaRecorder.setOrientationHint(0); 
      break; 
    } 

    return mMediaRecorder; 
} 

前應prepare()添加方法:

// Step 5: Set the preview output 
    /** 
    * Define Orientation of image in here, 
    * if in portrait mode, use value = 90, 
    * if in landscape mode, use value = 0 
    */ 
    CustomCamera.mMediaRecorder = Utils.rotateBackVideo(CustomCamera.mMediaRecorder); 
    CustomCamera.mMediaRecorder.setPreviewDisplay(mCameraPreview.getHolder().getSurface()); 

謝謝

1

使用OrientationEventListener和軌道旋轉值當設備旋轉code here。這個代碼應用旋轉攝像頭,但用來記錄你需要申請旋轉MediaRecorder。當你開始mMediaRecorder.prepare()之前只是mMediaRecorder.setOrientationHint(rotation)記錄。這解決了我的問題。

0

旋轉你的MediaRecorder像下面對應你在前置攝像頭的顯示方向置攝像頭視頻錄製

Display display = ((WindowManager)getContext().getSystemService(WINDOW_SERVICE)).getDefaultDisplay(); 
     parameters.setPreviewSize(height, width); 
     if(display.getRotation() == Surface.ROTATION_0) 
     { 

      mCamera.setDisplayOrientation(90); 
      mMediaRecorder.setOrientationHint(270); 
     } 

     if(display.getRotation() == Surface.ROTATION_90) 
     { 
      mMediaRecorder.setOrientationHint(180); 
     } 

     if(display.getRotation() == Surface.ROTATION_180) 
     { 
      mMediaRecorder.setOrientationHint(270); 
     } 

     if(display.getRotation() == Surface.ROTATION_270) 
     { 
      mCamera.setDisplayOrientation(180); 
      mMediaRecorder.setOrientationHint(0); 
     } 
0

這裏使用的程度是自畫像相機的代碼,將設置圖像和視頻的正確的旋轉:


private OrientationEventListener orientationEventListener; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    //... 
    orientationEventListener = new OrientationEventListener(this) { 
     @Override 
     public void onOrientationChanged(int orientation) { 
      if (orientation == ORIENTATION_UNKNOWN) return; 

      flashButton.setRotation(-(orientation)); 
      cameraButton.setRotation(-(orientation)); 

      if (camera != null) { 
       Parameters parameters = camera.getParameters(); 
       CameraInfo info = new CameraInfo(); 
       Camera.getCameraInfo(selectedCamera, info); 
       orientation = (orientation + 45)/90 * 90; 
       int rotation = 0; 
       if (info.facing == CameraInfo.CAMERA_FACING_FRONT) { 
        rotation = (info.orientation - orientation + 360) % 360; 
       } else { // back-facing camera 
        rotation = (info.orientation + orientation) % 360; 
       } 
       parameters.setRotation(rotation); 
       if (!isRecording) { 
        mediaRecorder.setOrientationHint(rotation); 
       } 

       camera.setParameters(parameters); 
      } 
     } 
    }; 
} 


@Override 
protected void onResume() { 
    super.onResume(); 
    //... 
    orientationEventListener.enable(); 
} 

@Override 
protected void onPause() { 
    super.onPause(); 
    orientationEventListener.disable(); 
    //... 
} 

泰斯特與縱向。記住把它放在你的清單中以測試代碼。我不知道如果在景觀工作。

<activity android:name=".activities.CameraActivity" 
      android:screenOrientation="portrait"> 
+0

這個手柄後面和前面的攝像頭圖片,但只有後面的攝像頭視頻。前攝像頭視頻在我的代碼中粉碎。如果我發現問題,我會發布該案例的代碼。 – IgniteCoders 2016-11-18 13:53:26

+0

我不知道代碼是否在橫向活動中工作,如果沒有,所有你需要的是+90或-90度到最終旋轉來修復它。 – IgniteCoders 2016-11-18 13:55:24

2

我有同樣的問題,我注意到相機預覽方位角和錄製視頻角度不一樣。 所以我使用的變化方向這種方法在視頻錄製:

public static int getVideoOrientationAngle(Activity activity, int cameraId) { //The param cameraId is the number of the camera. 
    int angle; 
    Display display = activity.getWindowManager().getDefaultDisplay(); 
    int degrees = display.getRotation(); 
    android.hardware.Camera.CameraInfo info = 
      new android.hardware.Camera.CameraInfo(); 
    android.hardware.Camera.getCameraInfo(cameraId, info); 
    switch (degrees) { 
     case Surface.ROTATION_0: 
      angle = 90; 
      break; 
     case Surface.ROTATION_90: 
      angle = 0; 
      break; 
     case Surface.ROTATION_180: 
      angle = 270; 
      break; 
     case Surface.ROTATION_270: 
      angle = 180; 
      break; 
     default: 
      angle = 90; 
      break; 
    } 
    if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) 
     angle = (angle + 180) % 360; 

    return angle; 
} 

這變革的方向上攝像頭預覽:

public static int setCameraDisplayOrientation(Activity activity, 
               int cameraId, android.hardware.Camera camera) { 
    android.hardware.Camera.CameraInfo info = 
      new android.hardware.Camera.CameraInfo(); 
    android.hardware.Camera.getCameraInfo(cameraId, info); 
    int rotation = activity.getWindowManager().getDefaultDisplay() 
      .getRotation(); 
    int degrees = 0; 
    switch (rotation) { 
     case Surface.ROTATION_0: 
      degrees = 0; 
      break; 
     case Surface.ROTATION_90: 
      degrees = 90; 
      break; 
     case Surface.ROTATION_180: 
      degrees = 180; 
      break; 
     case Surface.ROTATION_270: 
      degrees = 270; 
      break; 
    } 

    int result; 
    if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { 
     result = (info.orientation + degrees) % 360; 
     result = (360 - result) % 360; // compensate the mirror 
    } else { // back-facing 
     result = (info.orientation - degrees + 360) % 360; 
    } 
    camera.setDisplayOrientation(result); 
    return result; 
} 

注意,重要的是要知道,如果相機前面或後面。

0

爲肖像模式設置您的mediaRecorder.setOrientationHint(90);度數與您的相機方向相同myCamera.setDisplayOrientation(90);