Android MediaRecorder錄製視頻報錯start failed:-19原因

在設置MediaRecorder參數時有設置setVideoFrameRate(int rate)或者setVideoSize(int width, int height),這兩個方法代表設置錄製視頻的幀率和分辨率,關鍵在於需要手機硬件支持的,如果測試機的硬件不支持設置的參數就會無法start。

解決思路:查找手機支持的參數,選擇最合適的設置進去。
針對setVideoSize(int width, int height)來舉例:
通常在代碼中預覽佈局是SurfaceView,它的大小是可控的,我們可以在其getHolder.addCallback()裏獲取到寬度和高度:

@Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
    {
        //根據width和height去選取Camera最優預覽尺寸
    }

獲取到SurfaceView寬高後,我們應該去選擇一個合適的預覽尺寸分辨率,選擇預覽尺寸的標準是(1)攝像頭支持的預覽尺寸的寬高比與SurfaceView的寬高比的絕對差值小於0.1;(2)在(1)獲得的尺寸中,選取與SurfaceView的高的差值最小的。這裏貼一下官方的代碼:

public Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
    final double ASPECT_TOLERANCE = 0.1;
    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) {
      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;
  }

在加載預覽畫面時,需要考慮Camera支持的尺寸(getSupportedPreviewSizes)和加載預覽畫面的SurfaceView的尺寸(layout_width/layout_height),在預覽階段,兩者之間的關係直接影響清晰度及圖像拉伸。對於Camera的尺寸,由於設備的硬件差異,不同設備支持的尺寸存在差異,但在默認情況(orientation=landscape)下,其width>height。以HTC609d爲例,Camera支持的分辨率爲1280*720(16:9)……640*480(4:3)……480*320(3:2)等十多種,而其屏幕的分辨率爲960*540(16:9)。因此,很容易得到以下結論:(1)當Camera預覽尺寸小於SurfaceView尺寸較多時,預覽畫面就不清晰;(2)Camera預覽尺寸寬高比與SurfaceView寬高比相差較大時,預覽畫面就會拉伸。
上述代碼在手機設置爲橫屏時並沒有問題,在設置爲豎屏時,爲獲得最優的預覽尺寸,需要在調用此方法前比較SurfaceView的寬高:

if (mSupportedPreviewSizes != null) {
  mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, 
            Math.max(width, height), Math.min(width, height));
}

獲得與當前SurfaceView匹配的預覽尺寸後,即可通過Camera.Parameters進行設置:

Camera.Parameters mParams = mCamera.getParameters();
mParams.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
mCamera.setParameters(mParams);

就醬~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章