2016-07-15 1 views
0

Я создаю приложение простого диктофона. Я хочу динамически изменять SurfaceView, когда он начинает запись. Например, когда пользователь устанавливает разрешение видео в соотношении 4: 3 заранее в активности настроек и нажимает кнопку «начать запись», я хочу, чтобы SurfaceView менял его ширину и высоту в соотношении 4: 3. Таким образом, SurfaceView меняет свой размер при нажатии кнопки записи.android - Как я могу изменить размер SurfaceView динамически?

Я могу изменить размер SurfaceView, когда приложение ничего не записывает, но когда я пытаюсь изменить его прямо перед началом записи видео, оно меняет размер изображения, но запись не выполнена должным образом (он прекращает отмену ошибки при завершении записи).

Я хочу, чтобы мое приложение изменяло размер SurfaceView и начинало запись сразу после. Не раньше, чем пользователь нажимает кнопку записи!

Вот мой код.

MainActivity.java

private boolean prepRecorder() { 
     mRecorder = new MediaRecorder(); 
     CamcorderProfile profile = getCurrentProfile(); 

     Camera.Parameters parameters = mCamera.getParameters(); 
     parameters = setContinuesFocusMode(parameters); 

     Camera.Size desiredSize = null, optimalPreviewSize = null; 
     if (mVideoSizeIndex != -1) { 
      List<Camera.Size> supportedVidSizes = parameters.getSupportedVideoSizes(); 
      if (mVideoSizeIndex < supportedVidSizes.size()) { 
       desiredSize = supportedVidSizes.get(mVideoSizeIndex); 
       optimalPreviewSize = mSurface.getOptimalPreviewSize(
         parameters.getSupportedPreviewSizes(), desiredSize.width, desiredSize.height); 

       Point screenSize = getScreenSize(); 
       mSurface.resizePreview(optimalPreviewSize.width, optimalPreviewSize.height, screenSize.x, screenSize.y); 

       parameters.setPreviewSize(optimalPreviewSize.width, optimalPreviewSize.height); 
      } 
     } else { 
      parameters.setPreviewSize(profile.videoFrameWidth, profile.videoFrameHeight); 
     } 

     mCamera.setParameters(parameters); 
     mCamera.unlock(); 

     mRecorder.setCamera(mCamera); 
     mRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); 
     mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); 
     mRecorder.setProfile(profile); 
     mRecorder.setPreviewDisplay(mSurface.getHolder().getSurface()); 

     mVideoPath = getMediaPath(); 
     if (mVideoPath != null) { 
      mRecorder.setOutputFile(mVideoPath); 
     } else { 
      return false; 
     } 

     if (desiredSize != null) { 
      mRecorder.setVideoSize(desiredSize.width, desiredSize.height); 
     } else { 
      mRecorder.setVideoSize(profile.videoFrameWidth, profile.videoFrameHeight); 
     } 

     // Orientation adjustment stuff..... 


     mTrackerThread = new VideoFileTrackerThread(new Handler(), this, mVideoPath); 
     mTrackerThread.start(); 
     mTrackerThread.prepareHandler(); 
     mTrackerThread.triggerHandler(); 

     try { 
      mRecorder.prepare(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
      return false; 
     } 
     return true; 
    } 

VideoSurfaceView.java

public void resizePreview(int desiredWidth, int desiredHeight, int screenWidth, int screenHeight) { 
    float videoProportion = (float) desiredWidth/(float) desiredHeight; 
    float screenProportion = (float) screenWidth/screenHeight; 

    ViewGroup.LayoutParams lp = this.getLayoutParams(); 
    if (videoProportion > screenProportion) { 
     lp.width = screenWidth; 
     lp.height = (int) ((float) screenWidth/videoProportion); 
    } else { 
     lp.width = (int) (videoProportion * (float) screenHeight); 
     lp.height = screenHeight; 
    } 

    this.setLayoutParams(lp); 
} 


public Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) { 
    final double ASPECT_TOLERANCE = 0.2; 
    double targetRatio = (double) w/h; 
    if (sizes == null) 
     return null; 

    Camera.Size optimalSize = null; 
    double minDiff = Double.MAX_VALUE; 

    int targetHeight = h; 

    for (Camera.Size size : sizes) { 
     if (size.width == w && size.height == h) { 
      optimalSize = size; 
      return optimalSize; 
     } 
     double ratio = (double) size.width/size.height; 
     if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) 
      continue; 
     if (Math.abs(size.height - targetHeight) < minDiff) { 
      optimalSize = size; 
      minDiff = Math.abs(size.height - targetHeight); 
     } 
    } 

    if (optimalSize == null) { 
     minDiff = Double.MAX_VALUE; 
     for (Camera.Size size : sizes) { 
      if (Math.abs(size.height - targetHeight) < minDiff) { 
       optimalSize = size; 
       minDiff = Math.abs(size.height - targetHeight); 
      } 
     } 
    } 
    return optimalSize; 
} 

Когда я бегу resizePreview() метод, когда приложение не записи, он изменяет вид отлично; но когда я запускаю его при нажатии кнопки записи, это временно замораживает пользовательский интерфейс, и видеовыход не сохраняется должным образом. Возможно ли, что основной поток перегружен?

Заранее спасибо.

+0

Это должно помочь! http://stackoverflow.com/questions/20491499/resizing-surface-view-for-aspect-ratio-change-in-video-display-in-android – acac97

+0

@ acac97 Я уже видел и реализовал этот вопрос .. он отлично работает, когда приложение ничего не записывает, но я хочу изменить размер SurfaceView, когда пользователь нажимает кнопку StartRecording. –

+0

Также убедитесь, что вы прошли через эти шаги https://developer.android.com/reference/android/hardware/Camera.html – acac97

ответ

1

Я решил. Это вызвано тем, что метод onSurfaceChanged() вызывается при изменении размера представления. Я удалил mCamera.stopPreview(), mCamera.setPreviewDisplay() и mCamera.startPreview(), и теперь он отлично работает.