2012-08-16 20 views
7

Intento hacer una aplicación de video personalizada. Trabajo usando la configuración en el manifiesto solo 2.2 (API 8).Captura de video MediaRecorder en modo retrato

Todo va bien, pero no entiendo por qué el modo de retrato de video no difiere de lanscape one.

Para hacer la detección del dispositivo cambie la orientación de uso este código dentro de 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); 
    } 
} 

funciona como un encanto. Si giro la orientación de cambio de superficie del dispositivo, llamo a surfaceChanged, donde la cámara está configurada para la rotación de pantalla correspondiente.

La pregunta es cómo determinar más adelante si el video se capturó en el modo paisaje o en el retrato uno. Como obtuve todos los videos son capturados en orientación horizontal. No depende de setDisplayOrientation, que solo afecta al proceso de vista previa.

También explorando el problema Me di cuenta de que si se usa la aplicación estándar de la cámara, se escribe una etiqueta especial en un archivo de video (visto en MediaInfo): Rotación: 90 para los videos capturados en retrato.

Pero la clase MediaRecorder no.

Parece que es el problema. ¿Alguien tiene que resolver esto?

Respuesta

28

¡Lo encontró! De hecho, puede cambiar la vista previa, puede etiquetar el vídeo, pero no hay manera de cambiar realmente el video ... (tal vez un tema de la velocidad o algo así)

camera.setDisplayOrientation(90); 

Para girar la vista previa, a continuación,

recorder.setOrientationHint(90); 

Para etiquetar el video como que tiene una rotación de 90 °, entonces el teléfono lo rotará automáticamente al leer.

Así que todo lo que tiene que hacer es

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

espero que ayude ;-)

+0

setOrientationHint sólo está disponible para API 9. Tengo el mismo problema, pero necesito una solución de API 8. – AndroidDev

+3

Pasé horas tratando de descubrir este estúpido problema de orientación preliminar. Muchas gracias @ Taiko! Esto es lo que funcionó para mí: en el método 'onCreate' de la clase que implementa' SurfaceHolder.Callback', incluí este código: 'mCamera = Camera.open(); mCamera.setDisplayOrientation (90); mCamera.unlock(); 'seguido de' mediaRecorder = new MediaRecorder(); mediaRecorder.setCamera (mCamera); '. ¡Trabajado como un encanto! – Cat

8

camera.setDisplayOrientation (90) no funciona en todos los dispositivos. La siguiente solución funciona perfectamente en diferentes dispositivos y también maneja el permiso de tiempo de ejecución de marshmallow.

método Ver 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) { 

     } 
    } 



} 

Ahora prepara grabadora multimedia con la rotación correcta para que la reproducción de vídeo grabada en la orientación correcta.

mediaRecorder.setOrientationHint (CameraPreview.girar);

prepareMediaRecorder private boolean() {

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; 

} 

Puede descargar la muestra completa https://github.com/umesh-kushwaha/Android_Video_Recording_portrait

+0

setOrientationHint no ayuda - de vídeo se gira ( – Alex

+0

funcionaba perfecto para mí :) Gracias – SimpleCoder

+0

favor editar esta parte // crear la superficie y empezar vista previa de cámara si (mCamera == null) { mCamera.setPreviewDisplay (titular.); mCamera.startPreview(); } debe ser mCamera! = Null – EdgarK

Cuestiones relacionadas