2017-01-27 3 views
1

Я создаю приложение видеокамеры, которое всегда находится в ландшафтном режиме и всегда записывается с передней камеры. Но когда я записываю видео, он выглядит растянутым. Как его решить? Где я ошибаюсь ??Почему видео растягивается в Camera2 API?

public class MainActivity extends AppCompatActivity { 

public static final int REQUEST_CAMERA_PERMISSION_RESULT = 0; 
public static final int REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION_RESULT = 1; 
private TextureView mTextureView; 
//public ImageView mImageView; 
private TextureView.SurfaceTextureListener mSurfaceTextureListener = new TextureView.SurfaceTextureListener() { 

    @Override 
    public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) { 
     //Toast.makeText(getApplicationContext(),"TextureView is Available",Toast.LENGTH_SHORT).show(); 
     setupCamera(width, height); 
     connectCamera(); 
    } 

    @Override 
    public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width, int height) { 

    } 

    @Override 
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) { 
     return false; 
    } 

    @Override 
    public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) { 

    } 
}; 
private CameraDevice mCameraDevice; 
private CameraDevice.StateCallback mCameraDeviceStateCallback; 

{ 
    mCameraDeviceStateCallback = new CameraDevice.StateCallback() { 

     @Override 
     public void onOpened(CameraDevice camera) { 
      mCameraDevice = camera; 
      mMediaRecorder = new MediaRecorder(); 

      if (mIsRecording) { 
       try { 
        createVideoFileName(); 
       } catch (IOException e) { 
        Log.e("Error", e.getMessage()); 
        e.printStackTrace(); 
       } 
       startRecord(); 
       mMediaRecorder.start(); 
       runOnUiThread(new Runnable() { 
        @Override 
        public void run() { 
         mChronometer.setBase(SystemClock.elapsedRealtime()); 
         mChronometer.setVisibility(View.VISIBLE); 
         mChronometer.start(); 
        } 
       }); 


      } else { 

       startPreview(); 

      } 


      //Toast.makeText(getApplicationContext(),"Camera connected",Toast.LENGTH_SHORT).show(); 
     } 

     @Override 
     public void onDisconnected(CameraDevice camera) { 
      camera.close(); 
      mCameraDevice = null; 


     } 


     @Override 
     public void onError(CameraDevice camera, int i) { 

     } 
    }; 
} 

private HandlerThread mBackgroundHandlerThread; 
private Handler mBackgroundHandler; 
private String mCameraId; 
private Size mPreviewSize; 
private Size mVideoSize; 
private MediaRecorder mMediaRecorder; 
private Chronometer mChronometer; 
private ImageView thumb; 
//private String V1, V2, V3, V4, V5; 
// private Map<String, String> mapA = new HashMap<>(); 
// private ImageView[] IMGS = {mImageView1, mImageView2, mImageView3, mImageView4, mImageView5}; 
private int mTotalRotation; 
private CaptureRequest.Builder mCaptureRequestBuilder; 
public static int count; 
public static int max = 5; 
private ImageButton mRecordImageButton; 
private boolean mIsRecording = false; 
public static File mVideoFolder; 
private static File mRawVideoFolder; 
public static String mVideoFileName; 

//Test 
private List<Bitmap> bitMapsAvailable = new ArrayList<>(); 
private List<String> bitMapsFilePath = new ArrayList<>(); 
private int bitMapIndex; 
CameraCaptureSession storedSession; 
private ArrayAdapter bitMapAdapter; 
private ArrayAdapter bitMapFileAdapter; 
private static SparseIntArray ORIENTATIONS = new SparseIntArray(); 
public int index; 
static { 
    ORIENTATIONS.append(Surface.ROTATION_0, 0); 
    ORIENTATIONS.append(Surface.ROTATION_90, 90); 
    ORIENTATIONS.append(Surface.ROTATION_180, 180); 
    ORIENTATIONS.append(Surface.ROTATION_270, 270); 

} 

private static class CompareSizeByArea implements Comparator<Size> { 

    @Override 
    public int compare(Size lhs, Size rhs) { 
     return Long.signum((long) lhs.getWidth() * lhs.getHeight()/(long) rhs.getWidth() * rhs.getHeight()); 
    } 
} 


@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    //setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 
    createVideoFolder(); 

    mMediaRecorder = new MediaRecorder(); 
    mChronometer = (Chronometer) findViewById(R.id.chronometer); 
    mTextureView = (TextureView) findViewById(R.id.textureView); 

    mRecordImageButton = (ImageButton) findViewById(R.id.videoButton); 
    mRecordImageButton.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      if (mIsRecording) { 
       mChronometer.stop(); 
       mChronometer.setVisibility(View.INVISIBLE); 
       mIsRecording = false; 
       mRecordImageButton.setImageResource(R.mipmap.start_recording); 
       //Toast.makeText(getApplicationContext(),"Started",Toast.LENGTH_SHORT).show(); 

       if(storedSession != null){ 
        try { 
         storedSession.stopRepeating(); 
         storedSession.abortCaptures(); 
        }catch (CameraAccessException e){ 
         throw new RuntimeException(e.getMessage()); 
        } 
       } 
       mMediaRecorder.stop(); 
       mMediaRecorder.reset(); 
       startPreview(); 
       //Create bitmap with current video file path 
       Bitmap bitMap = ThumbnailUtils.createVideoThumbnail(mVideoFileName, MediaStore.Video.Thumbnails.MICRO_KIND); 
       //Add bitmap to array list 
       bitMapsAvailable.add(bitMap); 
       bitMapsFilePath.add(mVideoFileName); 
       // Shows thumbnails 
       showThumbnails(); 
      } else { 
       checkWriteStoragePermission(); 
      } 
     } 

    }); 
} 

private void showThumbnails() { 

    LinearLayout layout = (LinearLayout) findViewById(R.id.thumbnails); 

    bitMapAdapter = new ArrayAdapter(this, R.layout.activity_main, bitMapsAvailable); 
    bitMapFileAdapter = new ArrayAdapter(this, R.layout.activity_main, bitMapsFilePath); 


    bitMapIndex = 0; 
    if (layout.getChildCount() > 0) { 
     layout.removeAllViews(); 
    } 
    for (Bitmap eachBitMap : bitMapsAvailable) { 

     bitMapIndex++; 
     ImageView thumb = new ImageView(this); 
     thumb.setId(new Integer(bitMapIndex+ 17)); 
     thumb.setLayoutParams(new android.view.ViewGroup.LayoutParams(100, 80)); 
     thumb.setImageBitmap(eachBitMap); 
     // Adds the view to the layout 
     thumb.setOnClickListener(previewThumb(thumb)); 


     layout.addView(thumb); 
    } 
} 
View.OnClickListener previewThumb(final ImageView imageview) { 

    return new View.OnClickListener() { 
     public void onClick(View arg0) { 

      index = imageview.getId()-18; 
      imageview.setBackgroundColor(0xff999999); 
      // Start NewActivity.class 
      Intent myIntent = new Intent(MainActivity.this, 
        VideoViewActivity.class); 

      Bundle bundle = new Bundle(); 

      bundle.putStringArrayList("bitMapsAvailable", new ArrayList(bitMapsAvailable)); 
      bundle.putStringArrayList("bitMapsFilePath", new ArrayList(bitMapsFilePath)); 
      //Add your data to bundle 
      bundle.putInt("urlIndex", index); 
      myIntent.putExtras(bundle); 
      bitMapAdapter.notifyDataSetChanged(); 
      bitMapFileAdapter.notifyDataSetChanged(); 

      // startActivity(myIntent); 
      startActivityForResult(myIntent, 111); 

     } 
    }; 
} 
@Override 
protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
    super.onActivityResult(requestCode, resultCode, data); 
    if (resultCode == RESULT_OK) { 
     if (requestCode == 111) { 
      int indexToBeDeleted = data.getIntExtra("indexToBeDeleted",index); 
      //bitMapsFilePath.remove(indexToBeDeleted); 
      bitMapsAvailable.remove(indexToBeDeleted); 
     } 
    } 
} 
@Override 
protected void onResume() { 
    super.onResume(); 
    startBackgroundThread(); 
    if (mTextureView.isAvailable()) { 
     setupCamera(mTextureView.getWidth(), mTextureView.getHeight()); 
     connectCamera(); 
    } else { 
     mTextureView.setSurfaceTextureListener(mSurfaceTextureListener); 
    } 
} 

@Override 
public void onRequestPermissionsResult(int requestCode, String[] permission, int[] grantResults) { 
    super.onRequestPermissionsResult(requestCode, permission, grantResults); 
    if (requestCode == REQUEST_CAMERA_PERMISSION_RESULT) { 
     if (grantResults[0] != PackageManager.PERMISSION_GRANTED) { 
      Toast.makeText(getApplicationContext(), "Application will not run without camera service", Toast.LENGTH_SHORT).show(); 
     } 
     if (grantResults[0] != PackageManager.PERMISSION_GRANTED) { 
      Toast.makeText(getApplicationContext(), "Application will not have audio on record ", Toast.LENGTH_SHORT).show(); 
     } 
    } 
    if (requestCode == REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION_RESULT) { 
     if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { 
      mIsRecording = true; 
      mRecordImageButton.setImageResource(R.mipmap.ic_launcher); 
      try { 
       createVideoFileName(); 
      } catch (IOException e) { 
       Log.e("Error", e.getMessage()); 
       e.printStackTrace(); 
      } 
      Toast.makeText(this, "Permission Successfully Granted", Toast.LENGTH_SHORT).show(); 
     } else { 
      Toast.makeText(this, "App needs to save video to run", Toast.LENGTH_SHORT).show(); 
     } 
    } 
} 


@Override 
protected void onPause() { 
    closeCamera(); 
    stopBackgroundThread(); 
    super.onPause(); 

} 

@Override 
public void onWindowFocusChanged(boolean hasFocus) { 
    super.onWindowFocusChanged(hasFocus); 
    View decorView = getWindow().getDecorView(); 
    if (hasFocus) { 
     decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE 
       | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY 
       | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 
       | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 
       | View.SYSTEM_UI_FLAG_FULLSCREEN 
       | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); 
    } 
} 

private void setupCamera(int width, int height) { 
    CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); 
    try { 
     for (String cameraId : cameraManager.getCameraIdList()) { 
      CameraCharacteristics cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId); 
      if (cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_BACK) { 
       continue; 
      } 
      StreamConfigurationMap map = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); 
      //int deviceOrientation = getWindowManager().getDefaultDisplay().getRotation(); 
      mTotalRotation = sensorToDeviceRotation(cameraCharacteristics); 
      boolean swapRotation = mTotalRotation == 90 || mTotalRotation == 270; 
      int rotateWidth = width; 
      int rotateHeight = height; 
      if (swapRotation) { 
       rotateWidth = height; 
       rotateHeight = width; 
      } 
      mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class), rotateWidth, rotateHeight); 
      mVideoSize = chooseOptimalSize(map.getOutputSizes(MediaRecorder.class), rotateWidth, rotateHeight); 
      mCameraId = cameraId; 

      return; 
     } 
    } catch (CameraAccessException e) { 
     Log.e("Error", e.getMessage()); 
     e.printStackTrace(); 
    } 
} 

private void connectCamera() { 
    CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); 
    try { 
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 
      if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) { 
       cameraManager.openCamera(mCameraId, mCameraDeviceStateCallback, mBackgroundHandler); 
      } else { 
       if (shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) { 
        Toast.makeText(this, "Video app required access to camera", Toast.LENGTH_SHORT).show(); 
       } 
       requestPermissions(new String[]{android.Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO}, REQUEST_CAMERA_PERMISSION_RESULT); 
      } 
     } else { 
      cameraManager.openCamera(mCameraId, mCameraDeviceStateCallback, mBackgroundHandler); 
     } 
    } catch (CameraAccessException e) { 
     Log.e("Error", e.getMessage()); 
     e.printStackTrace(); 
    } 
} 

private void startRecord() { 
    if (this.bitMapsAvailable.size() < max) { 

     try { 
      setupMediaRecorder(); 
      SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture(); 
      surfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight()); 
      Surface previewSurface = new Surface(surfaceTexture); 
      Surface recordSurface = mMediaRecorder.getSurface(); 
      mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD); 
      mCaptureRequestBuilder.addTarget(previewSurface); 
      mCaptureRequestBuilder.addTarget(recordSurface); 

      mCameraDevice.createCaptureSession(Arrays.asList(previewSurface, recordSurface), new CameraCaptureSession.StateCallback() { 

       @Override 
       public void onConfigured(CameraCaptureSession session) { 
        try { 
         session.setRepeatingRequest(mCaptureRequestBuilder.build(), null, null); 
         storedSession = session; 
        } catch (CameraAccessException e) { 
         Log.e("Error", e.getMessage()); 
         e.printStackTrace(); 
        } 
       } 

       @Override 
       public void onConfigureFailed(CameraCaptureSession session) { 

       } 
      }, null); 
     } catch (Exception e) { 
      Log.e("Error", e.getMessage()); 
      e.printStackTrace(); 
     } 
    } else { 

    } 

} 

private void startPreview() { 
    SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture(); 
    surfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight()); 
    Surface previewSurface = new Surface(surfaceTexture); 
    try { 
     mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 
     mCaptureRequestBuilder.addTarget(previewSurface); 
     mCameraDevice.createCaptureSession(Arrays.asList(previewSurface), new CameraCaptureSession.StateCallback() { 

      @Override 
      public void onConfigured(CameraCaptureSession session) { 
       try { 
        session.stopRepeating(); 
        session.abortCaptures(); 
        session.setRepeatingRequest(mCaptureRequestBuilder.build(), null, mBackgroundHandler); 

       } catch (CameraAccessException e) { 
        Log.e("Error", e.getMessage()); 
        e.printStackTrace(); 
       } 
      } 

      @Override 
      public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) { 
       Toast.makeText(getApplicationContext(), "Unable to setup Camera Preview", Toast.LENGTH_SHORT).show(); 
      } 
     }, null); 
    } catch (CameraAccessException e) { 
     Log.e("Error", e.getMessage()); 
     e.printStackTrace(); 
    } 
} 

private void closeCamera() { 
    if (mCameraDevice != null) { 
     mCameraDevice.close(); 
     mCameraDevice = null; 

    } 
} 

private void startBackgroundThread() { 
    mBackgroundHandlerThread = new HandlerThread("AuthorTV"); 
    mBackgroundHandlerThread.start(); 
    mBackgroundHandler = new Handler(mBackgroundHandlerThread.getLooper()); 
} 

private void stopBackgroundThread() { 
    mBackgroundHandlerThread.quitSafely(); 
    try { 
     mBackgroundHandlerThread.join(); 
     mBackgroundHandlerThread = null; 
     mBackgroundHandler = null; 
    } catch (InterruptedException e) { 
     Log.e("Error", e.getMessage()); 
     e.printStackTrace(); 
    } 
} 

private static int sensorToDeviceRotation(CameraCharacteristics cameraCharacteristics) { 
    int sensorOrientation = cameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION); 
    // deviceOrientation = ORIENTATIONS.get(deviceOrientation); 
    return (sensorOrientation + 180 + 360) % 360; 
} 

private static Size chooseOptimalSize(Size[] choices, int width, int height) { 
    List<Size> bigEnough = new ArrayList<Size>(); 
    for (Size option : choices) { 
     if (option.getHeight() == option.getWidth() * height/width && option.getWidth() >= width && option.getHeight() >= height) { 
      bigEnough.add(option); 
     } 
    } 
    if (bigEnough.size() > 0) { 
     return Collections.min(bigEnough, new CompareSizeByArea()); 
    } else { 
     return choices[0]; 
    } 
} 


private void setupMediaRecorder() throws IOException { 
    mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE); 
    mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); 
    mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); 
    mMediaRecorder.setOutputFile(mVideoFileName); 
    mMediaRecorder.setVideoEncodingBitRate(1000000); 
    mMediaRecorder.setVideoFrameRate(30); 
    mMediaRecorder.setVideoSize(mVideoSize.getWidth(), mVideoSize.getHeight()); 
    mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); 
    mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); 
    mMediaRecorder.setOrientationHint(mTotalRotation); 
    mMediaRecorder.prepare(); 
} 

ответ

0

chooseOptimalSize должен быть отрегулирован и различен для mPreviewSize и mVideoSize. Проверьте эту ссылку Camera2VideoFragment.java

+0

на сколько plcaes мне нужно изменить мой ocde ?? – user7328722

+0

Только одно место в setupCamera. Кроме того, openCamera в Camera2VideoFragment.java более оптимизирован с точки зрения обработки ошибок. –

+0

m не правильно u – user7328722