2012-08-16 17 views
7

Próbuję utworzyć niestandardową aplikację wideo. Iwork za pomocą ustawień tylko w manifeście 2.2 (API 8).Przechwytywanie wideo MediaRecorder w trybie portretowym

Wszystko idzie dobrze, ale nie rozumiem, dlaczego wideo w trybie pionowym nie różni się od obrazu z lanscape.

Aby wykrywanie urządzenia zmienił orientację Używam tego kodu w ramach 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); 
    } 
} 

działa jak czar. Jeśli obrócę orientację zmiany powierzchni urządzenia, wywołam surfaceChanged, gdzie kamera jest ustawiona na odpowiednią DisplayRotation.

Pytanie, jak określić później, czy wideo zostało zrobione w trybie lanscape, czy w trybie portretu. Jak już dostałem wszystkie filmy są przechwytywane w orientacji poziomej. Nie zależy to od metody setDisplayOrientation, która wpływa tylko na proces podglądu.

Eksplorowanie problemu Zauważyłem, że jeśli użyć standardowej aplikacji Camera, zapisuje specjalny znacznik do pliku wideo (widoczny w MediaInfo): Obrót: 90 dla przechwyconych portretów wideo.

Ale klasa MediaRecorder nie.

Wydaje się, że to jest problem. Ktoś musi to rozwiązać?

Odpowiedz

28

Znaleziono! Rzeczywiście, można zmienić podgląd, można oznaczyć wideo, ale nie ma sposobu, aby rzeczywiście zmienić wideo ... (może to kwestia prędkości lub coś)

camera.setDisplayOrientation(90); 

Aby obrócić podgląd, a następnie

recorder.setOrientationHint(90); 

Aby oznaczyć wideo jako obrót o 90 °, telefon automatycznie obróci go podczas czytania.

Więc wszystko co musisz zrobić, to

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

Nadzieja pomaga ;-)

+0

setOrientationHint jest dostępna tylko dla API 9. Mam ten sam problem, ale potrzebne jest rozwiązanie dla API 8. – AndroidDev

+3

Spędziłem wiele godzin próbując rozgryźć ten głupi problem z orientacją na podglądzie. Wielkie dzięki @Taiko! Oto, co działało dla mnie: w metodzie 'onCreate' klasy implementującej' SurfaceHolder.Callback' zawarłem ten kod: 'mCamera = Camera.open(); mCamera.setDisplayOrientation (90); mCamera.unlock(); 'a następnie' mediaRecorder = new MediaRecorder(); mediaRecorder.setCamera (mCamera); '. Pracował jak urok! – Cat

8

camera.setDisplayOrientation (90) nie działa na wszystkich urządzeniach. Rozwiązanie działa doskonale w różnych urządzeniach, a także obsługuje zezwolenie na działanie praw ptasich.

metoda See 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) { 

     } 
    } 



} 

Teraz przygotować nagrywarkę z właściwej rotacji, dzięki czemu odtwarzanie nagrań wideo w orientacji prawej.

mediaRecorder.setOrientationHint (CameraPreview.obracać się);

private boolean 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; 

} 

Możesz pobrać pełną próbkę https://github.com/umesh-kushwaha/Android_Video_Recording_portrait

+0

setOrientationHint nie pomaga - film jest obracany ( – Alex

+0

pracował dla mnie idealny Dzięki :) – SimpleCoder

+0

proszę edytować tę część // utworzenie powierzchni i rozpocząć podgląd kamery if (mCamera == null) { mCamera.setPreviewDisplay (posiadacz.); mCamera.startPreview(); } powinno być mCamera! = Null – EdgarK

Powiązane problemy