2012-07-11 14 views
13

Grabo un video usando el siguiente código y graba perfectamente, pero cuando reproduce el video, lo reproduce boca abajo.Android Cámara grabación de video pero se reproduce boca abajo

Probé la configuración mrec.setOrientationHint(180) antes de mrec.prepare(); pero fue inútil. ¿Algún consejo?

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

¿Esto ocurre solo en su dispositivo? ¿Has intentado con uno diferente? – Ronnie

+0

¿Estás seguro de que no es la configuración del reproductor multimedia? ¿Otros reproductores de videos en la orientación correcta? – Ronnie

+0

Sí, estoy 100% seguro de que no es la configuración del reproductor multimedia. Mis teléfonos son Atrix2, ahora no me molestan otros teléfonos. – Sana

Respuesta

5

Esto se debe llamar antes del método mrec.prepare();

setOrientationHint(degrees); 

Link

EDIT: Trate mCamera.setDisplayOrientation(degrees);

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

Algunos jugadores de mayor edad y los codificadores no interpretan este fl ag por lo que el video se reproduce boca abajo.

+0

Lo hice, pero eso no funciona, ya lo dije en mi pregunta. – Sana

+0

¿Intentó 'mrec.setDisplayOrientation (0);'? No debe especificar 180 allí, ya que eso arruina muchos reproductores de video. Además, intente reproducir el video usando un reproductor de video diferente que pueda interpretar la matriz de composición. –

+0

En lugar de 180, ¿qué intento entonces? y no hay nada de tipos 'mrec.setDisplayOrientation (0);', creo que te refieres al ángulo de ajuste de la cámara, ¡ya me ocupo de eso si ves mi código! Me estoy dirigiendo a 2.3 dispositivos – Sana

15

Este problema se debe a que Android maneja la rotación simplemente configurando algunos metadatos en lugar de realmente girar el video, y algunos programas de reproducción luego ignoran esa configuración.

Como se señala en the docs:

cuenta que algunos reproductores de vídeo pueden optar por ignorar la matriz en un Composición de vídeo durante la reproducción.

Sus opciones son usar un software de reproducción diferente que entienda los metadatos que se configuran, o recodificar el video después de haber sido grabado con la orientación correcta. No está claro a partir de su descripción cuál de esas sería la mejor solución en su caso.

0

Finalmente descubrí que los teléfonos Motorola tienen problemas para reproducir el video que se graba en modo retrato.

Con el fin de superar la rotación del video, la mejor solución que he adoptado consistió en cargar el vídeo en el servidor y ejecutar ffmpeg sobre el uso del comando ffmpeg -i input.mp4 -c:v mpeg4 -c:a copy -c:s copy -vf "transpose=2" output.mp4

Si se siente había otra manera, por favor Házmelo saber.

0

una solución más es rotar su actividad de modo que su orientación sea la misma que la orientación del sensor. Es decir, paisaje para cámara trasera y retrato boca abajo para cámara frontal. Esto por cierto no arreglará el efecto espejo para la cámara frontal. Una dificultad más es que tendrá que implementar su UI en las actividades giradas de forma que se pueda seguir la orientación de la actividad.

1

Conozco el problema,

video uso Media Recorder de Camera, por lo que necesita rotate Media Recorder. utilice los códigos a continuación debe solucionar su problema.

/** 
* 
* @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; 
} 

debe agregar antes prepare() método:

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

Gracias

valor de rotación
1

Uso OrientationEventListener y la pista cuando el dispositivo se gira code here código .Esta aplicar la rotación de la cámara, pero para la grabación que es necesario aplicar rotación a MediaRecorder. Cuando comienza a grabar solo mMediaRecorder.setOrientationHint(rotation) antes de mMediaRecorder.prepare(). Esto resuelve mi problema

0

giran a su MediaRecorder, como a continuación corresponde al grado que utilizó en orientación de la pantalla de la cámara para la parte frontal hacia la grabación de vídeo de la cámara

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

Este es el código para la cámara retrato de encargo, fijará la correcta rotación de imagen y vídeo:


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

Teste con orientación vertical. Recuerda ponerlo en tu manifiesto para probar el código. No sé si trabajo en el paisaje.

+0

Este maneja atrás y las imágenes de la cámara frontal, pero solo los videos de la cámara trasera. Los videos de la cámara frontal se aplastan ahora en mi código. Publicaré el código para ese caso si encuentro el problema. – IgniteCoders

+0

No sé si el código funciona en la actividad de paisaje, si no lo hace, todo lo que necesita es +90 o -90 grados a la rotación final para solucionarlo. – IgniteCoders

2

Tengo el mismo problema, observo que el ángulo de orientación de la vista previa de la cámara y el ángulo de grabación de video no son los mismos. lo tanto, utilizar este método para cambiar la orientación de grabación de vídeo:

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

Y que para el cambio de orientación en la vista previa de la cámara:

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

Tenga en cuenta que es importante saber si la cámara está delante o hacia atrás.

0

para modo retrato configure su mediaRecorder.setOrientationHint (90); grado es igual a la orientación de su cámara myCamera.setDisplayOrientation (90);

Cuestiones relacionadas