2012-07-11 12 views
13

Registra un video utilizzando il codice seguente e registra perfettamente, ma quando riproduce il video, viene riprodotto a testa in giù.La videocamera Android registra video ma suona sottosopra

Ho provato le impostazioni mrec.setOrientationHint(180) prima del mrec.prepare(); ma era inutile. Qualche suggerimento?

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

Si verifica solo sul dispositivo? Ne hai provato uno diverso? – Ronnie

+0

Sei sicuro che non siano le impostazioni del lettore multimediale.? La riproduzione di altri video è corretta? – Ronnie

+0

Sì, sono sicuro al 100% che non si tratta delle impostazioni del lettore multimediale. I miei telefoni sono Atrix2, non mi preoccupo di altri telefoni ora. – Sana

risposta

5

Questo dovrebbe essere chiamato prima che il metodo mrec.prepare();

setOrientationHint(degrees); 

Link

EDIT: Prova mCamera.setDisplayOrientation(degrees);

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

Alcuni giocatori più anziani e gli encoder non interpretare questo fl ag che è il motivo per cui il video suona sottosopra.

+0

L'ho fatto, ma non funziona, l'ho già detto nella mia domanda. – Sana

+0

Hai provato 'mrec.setDisplayOrientation (0);'? Non dovresti specificare 180 lì, in quanto ciò incasina molti lettori video. Inoltre, prova a riprodurre il video utilizzando un altro lettore video in grado di interpretare la matrice di composizione. –

+0

Invece di 180 cosa provo allora? e non c'è niente di 'mrec.setDisplayOrientation (0);' tipi, penso che tu ti stia riferendo all'angolo di regolazione della fotocamera, me ne occupo già io se vedi il mio codice !!! Mi occupo di 2.3 dispositivi – Sana

15

Questo problema è dovuto alla rotazione della gestione di Android semplicemente impostando alcuni metadati invece di ruotare effettivamente il video e alcuni software di riproduzione ignorando tale impostazione.

Come rilevato in the docs:

Nota che alcuni lettori video potrebbero scegliere di ignorare la matrice compostion in un video durante la riproduzione.

Le opzioni disponibili sono per utilizzare un software di riproduzione diverso che comprenda i metadati impostati o per ricodificare il video dopo che è stato registrato con l'orientamento corretto. Non è chiaro dalla tua descrizione quale di questi sarebbe la soluzione migliore nel tuo caso.

0

Finalmente ho scoperto che i telefoni Motorola hanno problemi nel riprodurre il video che è registrato in modalità verticale.

Al fine di superare la rotazione del video, la soluzione migliore che ho adottato è stato quello di caricare il video al server ed eseguire ffmpeg sull'utilizzo del comando ffmpeg -i input.mp4 -c:v mpeg4 -c:a copy -c:s copy -vf "transpose=2" output.mp4

Se pensate che ci fosse un altro modo, si prega di fare fammi sapere.

0

un'altra soluzione è quella di ruotare l'attività in modo che il suo orientamento sia lo stesso dell'orientamento del sensore. Cioè, paesaggio per fotocamera posteriore e ritratto capovolto per fotocamera frontale. Questo btw non risolverà l'effetto specchio per la fotocamera frontale. Un'altra difficoltà è che dovrai implementare l'interfaccia utente in quelle attività ruotate in modo da seguire l'orientamento dell'attività.

1

So che il vostro problema,

video utilizzano Media Recorder da Camera, quindi è necessario rotate Media Recorder. utilizzare sotto i codici dovrebbe essere risolto il 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; 
} 

dovrebbe aggiungere prima prepare() metodo:

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

Grazie

1

Usa OrientationEventListener e la pista valore di rotazione quando il dispositivo viene ruotato code here codice .Questo applicano rotazione macchina fotografica, ma per la registrazione è necessario applicare rotazione su MediaRecorder. Quando si inizia a registrare solo mMediaRecorder.setOrientationHint(rotation) prima di mMediaRecorder.prepare(). Questo risolve il mio problema.

0

ruotare le MediaRecorder come qui di seguito corrispondente al grado che hai utilizzato in orientamento del display Fotocamera per la parte anteriore rivolta verso la registrazione videocamera

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

Ecco il codice per la macchina fotografica ritratto personalizzato, imposterà la corretta rotazione di foto e video:


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 orientamento verticale. Ricordati di inserirlo nel tuo manifest per testare il codice. Non so se lavoro nel paesaggio.

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

Questo consente di gestire le immagini della fotocamera posteriore e anteriore, ma solo i video della fotocamera posteriore. I video della fotocamera frontale si sono schiantati ora nel mio codice. Pubblicherò il codice per quel caso se ho trovato il problema. – IgniteCoders

+0

Non so se il codice funziona in attività orizzontale, se no, tutto ciò che serve è a +90 o -90 gradi alla rotazione finale per risolverlo. – IgniteCoders

2

Ho lo stesso problema, noto che l'angolo di orientamento dell'anteprima della videocamera e l'angolo di registrazione del video non sono gli stessi. Così ho utilizzare questo metodo per l'orientamento cambiamento sulla registrazione video:

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

E questo per il cambiamento di orientamento sul anteprima fotocamera:

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

Nota che è importante sapere se la fotocamera è anteriore o posteriore.

0

per la modalità verticale impostare mediaRecorder.setOrientationHint (90); il grado è uguale all'orientamento della fotocamera myCamera.setDisplayOrientation (90);

Problemi correlati