2

Я пытаюсь записать видео в правильной ориентации на Android. Я создал свою работу, она работает правильно, единственное, что сохраненное видео после записи повернуто. Предварительный просмотр камеры работает правильно, поэтому я не могу понять, почему. Для того, чтобы зафиксировать поворот я использую этот код (метод я нашел на Google Developers):GetCameraDisplayOrientation всегда возвращается 0

mMediaRecorder.setOrientationHint(getCameraDisplayOrientation());  

private int getCameraDisplayOrientation() 
    { 
     android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo(); 
     android.hardware.Camera.getCameraInfo(CameraInfo.CAMERA_FACING_BACK, 
       info); 
     int rotation = 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; 

     } 

     return result; 

Деятельность определяется в манифесте так:

<activity android:name="pages.CameraPage" 
     android:label="@string/app_name" 
     android:theme="@android:style/Theme.NoTitleBar.Fullscreen" 
     android:screenOrientation="landscape" 
     > 
    </activity> 

Проблема заключается в том, что getCameraDisplayOrientation всегда возвращает 0 градусов, независимо от того, как я ориентирую экран.

Я вызываю метод непосредственно перед началом записи, поэтому, если бы я смог получить поворот экрана относительно ландшафта по умолчанию, я был бы в порядке.

Благодарим за помощь!

+0

Ваша деятельность связана с пейзажем, не так ли? –

+0

Да, я указал его в манифесте, потому что разработчики ANdroid advisec так легко справляются с камерой –

+0

Вот почему getCameraDisplayOrientation() не изменяется. Но даже когда ориентация активности фиксирована, вы можете проверить акселерометр, чтобы получить ориентацию устройства. –

ответ

0

Если ваша проблема связана с вашей переменной поворота, вы можете рассмотреть возможность использования this link. Основное отличие от этой ссылки - создать объект WindowManager, а затем использовать его для поворота. Эта, казалось бы, небольшая разница заключалась в том, что создатель различий между частью моего кода работает и не работает.

Вы можете просто сказать Camera.CameraInfo info = new Camera.CameraInfo(); и Camera.getCameraInfo(...);.

Мне любопытно, почему вы задаете CameraInfo.CAMERA_FACING_BACK в android.hardware.Camera.getCameraInfo(CameraInfo.CAMERA_FACING_BACK, info); Я чувствую, что вы могли бы просто назвать info.facing, чтобы получить int вместо этого.

Я надеюсь, что между ссылкой и моими предложениями/запросами, что что-то искроет правильный ответ!

+0

Благодарим вас за предложение, но оно все еще не работает. Проблема заключается в активности, зафиксированной в ландшафтном режиме в манифесте. Если я удалю его, я смогу получить правильную ориентацию даже с помощью моего метода, но мне нужно что-то, что работает в ландшафте –

2

Наконец-то я смог успешно создать собственное приложение для камеры без какой-либо проблемы с ориентацией. Ключ смотрел на surfaceView для вращения. Я думаю, что это может помочь кому-то получить весь код, размещенный здесь, просто скопируйте его и запустите Activity!

CameraPage.java

package pages; 

import java.io.BufferedInputStream; 
import java.io.ByteArrayOutputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.net.InetAddress; 
import java.net.NetworkInterface; 
import java.net.SocketException; 
import java.net.URI; 
import java.text.DateFormat; 
import java.text.SimpleDateFormat; 
import java.util.Date; 
import java.util.Enumeration; 
import java.util.HashMap; 

import model.CameraView; 

import com.controller.R; 

import android.annotation.SuppressLint; 
import android.app.Activity; 
import android.content.Intent; 
import android.hardware.Camera; 
import android.media.CamcorderProfile; 
import android.media.MediaRecorder; 
import android.net.Uri; 
import android.os.AsyncTask; 
import android.os.Bundle; 
import android.os.Environment; 
import android.util.Base64; 
import android.util.Log; 
import android.view.MotionEvent; 
import android.view.Surface; 
import android.view.View; 
import android.view.View.OnTouchListener; 
import android.view.WindowManager; 
import android.view.animation.AlphaAnimation; 
import android.widget.FrameLayout; 
import android.widget.ImageButton; 
import android.widget.Toast; 




public class CameraPage extends Activity 
{ 
    private Camera mCamera; 
    private CameraView mPreview; 
    private MediaRecorder mMediaRecorder; 
    private FrameLayout preview; 
    private ImageButton buttonRecordStop; 
    private boolean isRecording = false; 
    private String fileName; 

    @Override 
    public void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     Log.d("CameraPage-onCreate", "Called onCreate()"); 

     setContentView(R.layout.camera_surface); 

     buttonRecordStop = (ImageButton) findViewById(R.id.camera_surface_buttonRecordStop); 

     buttonRecordStop.setOnTouchListener(new OnTouchListener() { 

      @Override 
      public boolean onTouch(View v, MotionEvent event) 
      { 
       if (event.getAction() == MotionEvent.ACTION_DOWN 
         || event.getAction() == MotionEvent.ACTION_MOVE) 
       { 
        AlphaAnimation alpha = new AlphaAnimation(1.0F, 0.3F); 
        alpha.setDuration(100); 
        alpha.setFillAfter(true); // Tell it to persist after the animation ends 
        buttonRecordStop.startAnimation(alpha); 
       } else if (event.getAction() == MotionEvent.ACTION_UP 
         || event.getAction() == MotionEvent.ACTION_CANCEL) 
       { 
        AlphaAnimation alpha = new AlphaAnimation(0.3F, 1.0F); 
        alpha.setDuration(100); 
        alpha.setFillAfter(true); // Tell it to persist after the animation ends 
        buttonRecordStop.startAnimation(alpha); 
       } 
       return false; 
      } 
     }); 

     buttonRecordStop.setOnClickListener(new View.OnClickListener() { 

      @Override 
      public void onClick(View v) 
      { 
       if (!isRecording) 
       { 
        Log.d("CameraPage-buttonRecordStop-onClick", "Start Record"); 

        getWindow().addFlags(
          WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 

        // initialize video camera 
        if (prepareVideoRecorder()) 
        { 
         v.setVisibility(View.GONE); 
         ((ImageButton) v) 
           .setImageResource(R.drawable.iconapause); 
         v.setVisibility(View.VISIBLE); 
         isRecording = true; 

         // Camera is available and unlocked, MediaRecorder is prepared, 
         // now you can start recording 
         mMediaRecorder.start(); 

        } else 
        { 
         // prepare didn't work, release the camera 
         releaseMediaRecorder(); 
         // inform user 
        } 

       } else 
       { 
        Log.d("CameraPage-buttonRecordStop-onClick", "Stop Record"); 

        getWindow().clearFlags(
          WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 

        v.setVisibility(View.GONE); 
        ((ImageButton) v).setImageResource(R.drawable.iconarecord); 
        v.setVisibility(View.VISIBLE); 
        isRecording = false; 

        stopRecording(); 

        sendBroadcast(new Intent(
          Intent.ACTION_MEDIA_MOUNTED, 
          Uri.parse("file://" 
            + Environment.getExternalStorageDirectory()))); 


       } 

      }// end onClick 
     }); 

     mCamera = getCameraInstance(); 
     preview = (FrameLayout) findViewById(R.id.camera_preview); 

    }// end onCreate 


    @Override 
    protected void onResume() 
    { 
     super.onResume(); 
     Log.d("CameraPage-onResume", 
       "Chiamato onResume ripristino le risorse se necessario"); 

     if (mCamera == null) 
     { 
      // Create an instance of Camera 
      mCamera = getCameraInstance(); 

     } 

     if (mPreview == null) 
     { 
      mPreview = new CameraView(getApplicationContext(), mCamera, this); 
      preview.addView(mPreview); 
     } 

    } 

    @Override 
    protected void onPause() 
    { 
     super.onPause(); 
     Log.d("CameraPage-onPause", "Vado in onPause e rilascio le risorse"); 

     releaseMediaRecorder(); // if you are using MediaRecorder, release it first 
     releaseCamera(); // release the camera immediately on pause event 

     preview.removeView(mPreview); 
     mPreview = null; 
    } 

    private void stopRecording() 
    { 
     mMediaRecorder.stop(); 
     releaseMediaRecorder(); 

     // Restarto la preview della camera 
     mCamera.startPreview(); 
     // mCamera.lock(); 
    } 

    private boolean prepareVideoRecorder() 
    { 

     // mCamera = getCameraInstance(); 
     mMediaRecorder = new MediaRecorder(); 

     // Stop preview because I have to start the preview for the video 
     mCamera.stopPreview(); 

     // Step 1: Unlock and set camera to MediaRecorder 
     mCamera.unlock(); 
     mMediaRecorder.setCamera(mCamera); 

     // Step 2: Set sources 
     mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); 
     mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); 

     // Step 3: Set a CamcorderProfile (requires API Level 8 or higher) 
     mMediaRecorder.setProfile(CamcorderProfile 
       .get(CamcorderProfile.QUALITY_HIGH)); 

     // Step 4: Set output file 
     setOutputFile(); 
     mMediaRecorder.setOutputFile(getOutputFile()); 

     // Step 5: Set the preview output 
     mMediaRecorder.setPreviewDisplay(mPreview.getHolder().getSurface()); 

     mMediaRecorder.setOrientationHint(CameraPage 
       .getCameraDisplayOrientation(this, 
         Camera.CameraInfo.CAMERA_FACING_BACK, mCamera)); 

     // Step 6: Prepare configured MediaRecorder 
     try 
     { 
      mMediaRecorder.prepare(); 
     } catch (IllegalStateException e) 
     { 
      Log.d("CameraPage-prepareVideoRecorder", 
        "IllegalStateException preparing MediaRecorder: " 
          + e.getMessage()); 
      releaseMediaRecorder(); 
      return false; 
     } catch (IOException e) 
     { 
      Log.d("CameraPage-prepareVideoRecorder", 
        "IOException preparing MediaRecorder: " + e.getMessage()); 
      releaseMediaRecorder(); 
      return false; 
     } 
     return true; 
    } 

    private void releaseMediaRecorder() 
    { 
     if (mMediaRecorder != null) 
     { 
      mMediaRecorder.reset(); // clear recorder configuration 
      mMediaRecorder.release(); // release the recorder object 
      mMediaRecorder = null; 
      mCamera.lock(); // lock camera for later use 
     } 
    } 

    private void releaseCamera() 
    { 
     if (mCamera != null) 
     { 
      mCamera.release(); // release the camera for other applications 
      mCamera = null; 
     } 

     if (mPreview != null) 
      mPreview.getHolder().removeCallback(mPreview); 
    } 

    /** A safe way to get an instance of the Camera object. */ 
    private Camera getCameraInstance() 
    { 
     Camera c = null; 
     try 
     { 
      Log.d("CameraPage-getCameraInstance", "Prendo istanza camera"); 
      c = Camera.open(); // attempt to get a Camera instance 
     } catch (Exception e) 
     { 
      // Camera is not available (in use or does not exist) 
      Log.d("CameraPage-getCameraInstance", 
        "Eccezione durante retrieve istanza camera " + e); 
     } 
     return c; // returns null if camera is unavailable 
    } 

    @SuppressLint("SimpleDateFormat") 
    private void setOutputFile() 
    { 
     String folderPath = Environment.getExternalStorageDirectory().getPath(); 
     File vims = new File(folderPath + "/ViMS"); 

     if (!vims.exists()) 
      vims.mkdir(); 

     DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd---HH-mm-ss"); 
     Date date = new Date(); 
     String timestamp = "/" + dateFormat.format(date) + ".mp4"; 

     Log.d("CameraPage-getOutputFile", Environment 
       .getExternalStorageDirectory().getPath()); 

     fileName = vims.getPath() + timestamp; 

    } 

    private String getOutputFile() 
    { 
     return fileName; 
    } 

    public static void setCameraDisplayOrientation(Activity activity, 
      int cameraId, android.hardware.Camera camera) 
    { 

     int result = CameraPage.getCameraDisplayOrientation(activity, cameraId, 
       camera); 

     if (android.os.Build.VERSION.SDK_INT <= 14) 
     { 
      camera.stopPreview(); 
      camera.setDisplayOrientation(result); 
      camera.startPreview(); 
     } else 
     { 
      camera.setDisplayOrientation(result); 
     } 

    }// end setCameraDisplayOrientation 

    public static int getCameraDisplayOrientation(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; 
     } 

     return result; 
    } 

    @Override 
    public void onDestroy() 
    { 
     super.onDestroy(); 

     Log.d("CameraPage-onDestroy", "Called onDestroy"); 

    } 

}// end CameraPage 

CameraView.java

package model; 

import java.io.IOException; 

import pages.CameraPage; 

import android.app.Activity; 
import android.content.Context; 
import android.hardware.Camera; 
import android.util.AttributeSet; 
import android.util.Log; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 




/** A basic Camera preview class */ 
public class CameraView extends SurfaceView implements SurfaceHolder.Callback 
{ 
    private SurfaceHolder mHolder; 
    private Camera mCamera; 
    private Activity activity; 

    public CameraView(Context context) 
    { 
     super(context); 
     Log.d("CameraView-default constructor", 
       "Chiamato uno dei due default constructors"); 
    } 

    public CameraView(Context context, AttributeSet attrs) 
    { 
     super(context, attrs); 
     Log.d("CameraView-default constructor", 
       "Chiamato uno dei due default constructors"); 
    } 

    public CameraView(Context context, Camera camera, Activity activity) 
    { 
     super(context); 
     Log.d("CameraView-constructor", 
       "Inizializzo la classe con la camera e il context"); 

     this.activity = activity; 

     mCamera = camera; 

     // Install a SurfaceHolder.Callback so we get notified when the 
     // underlying surface is created and destroyed. 
     mHolder = getHolder(); 
     mHolder.addCallback(this); 
     // deprecated setting, but required on Android versions prior to 3.0 
     mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
    } 

    public void surfaceCreated(SurfaceHolder holder) 
    { 
     Log.d("CameraView-surfaceCreated", 
       "La superfice è stata creata, setto la preview della camera sulla superficie"); 

     // The Surface has been created, now tell the camera where to draw the preview. 
     try 
     { 
      mCamera.setPreviewDisplay(holder); 
      mCamera.startPreview(); 
     } catch (IOException e) 
     { 
      Log.d("CameraView-surfaceCreated", "Error setting camera preview: " 
        + e.getMessage()); 
     } 
    } 

    public void surfaceDestroyed(SurfaceHolder holder) 
    { 
     Log.d("CameraView-surfaceDestroyed", 
       "Distrutta superficie della preview"); 
     // Take care of releasing the Camera preview in your activity. 
    } 

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) 
    { 
     Log.d("CameraView-surfaceChanged", 
       "Gestisco i cambiamenti nella superficie che ospita la camera"); 
     // If your preview can change or rotate, take care of those events here. 
     // Make sure to stop the preview before resizing or reformatting it. 

     if (mHolder.getSurface() == null) 
     { 
      // preview surface does not exist 
      Log.d("CameraView-surfaceChanged", "Preview surface doesn't exist"); 
      return; 
     } 

     try 
     { 
      CameraPage.setCameraDisplayOrientation(activity, 
        Camera.CameraInfo.CAMERA_FACING_BACK, mCamera); 
     } catch (Exception e) 
     { 
      Log.d("CameraView-surfaceChanged", 
        "Exception reorienting the camera " + e); 
     } 

    }// end surfaceChanged 
}// end CameraView 

camera_surface.xml

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="horizontal" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    > 

    <FrameLayout 
     android:id="@+id/camera_preview" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" > 

    </FrameLayout> 

    <ImageButton 
     android:id="@+id/camera_surface_buttonRecordStop" 
     android:layout_width="60dp" 
     android:layout_height="60dp" 
     android:layout_alignParentBottom="true" 
     android:layout_centerHorizontal="true" 
     android:layout_marginBottom="10dp" 
     android:adjustViewBounds="true" 
     android:background="@null" 
     android:contentDescription="@string/action" 
     android:scaleType="fitCenter" 
     android:src="@drawable/iconarecord" /> 

</RelativeLayout> 

Деятельность была протестирована с Android 2.3.6 до 4.3. Если вы обнаружите какую-либо проблему или имеете какое-либо предложение, пожалуйста, дайте мне знать!

Смежные вопросы