Как записать видео определенной ширины и высоты на Android-устройстве Samsung?

Здравствуйте, я делаю приложение для Android, в котором я использую пользовательскую камеру для записи камеры. У меня проблема с устройством Samsung. Я не могу установить профиль устройства записи мультимедиа на CamcorderProfile.get(cameraid, CamcorderProfile.QUALITY_HIGH)

также, когда попробуйте использовать

profile = CamcorderProfile.get(cameraid, CamcorderProfile.QUALITY_LOW);
                       profile.videoFrameHeight=360;
                       profile.videoFrameWidth=640;

тогда мое приложение работает на некоторых устройствах, но вылетает на многих устройствах. Любая помощь будет заметна. Заранее спасибо, пожалуйста, проверьте код

Camera.Parameters param = mCamera.getParameters();
            param.set( "cam_mode", 1 );  
         // Enable video stabilization. Convenience methods not available in API
            // level <= 14
            String vstabSupported = param.get("video-stabilization-supported");
            if ("true".equals(vstabSupported)) {
                param.set("video-stabilization", "true");
            }
            List<Size> sizes = mCamera.getParameters() .getSupportedVideoSizes();
            mCamera.setParameters( param );
            mMediaRecorder = new MediaRecorder();
            // Step 1: Unlock and set camera to MediaRecorder
            mCamera.unlock();
            mMediaRecorder.setCamera(mCamera);
            mMediaRecorder.setPreviewDisplay(mPreview.getHolder().getSurface());
            // Step 2: Set sources
            mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
            mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
            String deviceMan = android.os.Build.MANUFACTURER;
            Toast.makeText(getApplicationContext(), deviceMan, Toast.LENGTH_SHORT).show();
            // Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
            CamcorderProfile profile = CamcorderProfile.get(cameraid, CamcorderProfile.QUALITY_LOW);
//          if(!CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_HIGH)){Log.d("", "the camcorder profile instance is null");
            int currentapiVersion = android.os.Build.VERSION.SDK_INT;
            if (currentapiVersion >= android.os.Build.VERSION_CODES.FROYO){
                // Do something for froyo and above versions
                 boolean tellbol=CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_HIGH);
                 if(deviceMan.equals("samsung")){
                       profile = CamcorderProfile.get(cameraid, CamcorderProfile.QUALITY_LOW);
                       profile.videoFrameHeight=360;
                       profile.videoFrameWidth=640;
                 }
                 else{
                        profile = CamcorderProfile.get(cameraid, CamcorderProfile.QUALITY_HIGH);
                 }
                 mMediaRecorder.setProfile(profile);
            } else{
                // do something for phones running an SDK before froyo
                mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
                mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
//              mMediaRecorder.setVideoSize(720, 480);
                mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
            }

            // Step 4: Set output file
            mMediaRecorder.setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO).toString());
            // Step 5: Set the preview output
            // Step 6: Prepare configured MediaRecorder
            try {
                mMediaRecorder.prepare();
            } catch (IllegalStateException e) {
                Log.d("Video", "IllegalStateException preparing MediaRecorder: " + e.getMessage());
                releaseMediaRecorder();
                return false;
            } catch (IOException e) {
                Log.d("Video", "IOException preparing MediaRecorder: " + e.getMessage());
                releaseMediaRecorder();
                return false;
            }
            return true;

2 ответа

Решение

Это происходит потому, что вы запрашиваете измерения, которые хотите, но не каждая камера способна на каждое измерение.

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

Что делать?

Шаг 1.

Вы должны проверить поддерживаемые размеры. Вы можете сделать это с

Camera.Parameters p = myCamera.getParameters(); 
List<Size> previewsizes = p.getSupportedPreviewSizes();
List<Size> videosizes = p.getSupportedVideoSizes();

и тогда вы можете выбрать один. Если вы хотите автоматизировать это, вы можете пойти дальше и следовать

Шаг 2

напишите функцию для выбора наилучшего доступного размера, который получит поддерживаемые размеры и желаемый размер, например:

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

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

        int targetHeight = h;

        // Try to find an size match aspect ratio and size
        for (Size size : sizes) {
            Log.d("Camera", "Checking size " + size.width + "w " + size.height
                    + "h");
            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);
            }
        }

        // Cannot find the one match the aspect ratio, ignore the
        // requirement
        if (optimalSize == null) {
            minDiff = Double.MAX_VALUE;
            for (Size size : sizes) {
                if (Math.abs(size.height - targetHeight) < minDiff) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }
            }
        }
        return optimalSize;
    }

И последний шаг, установите параметры

Шаг 3

private int desiredwidth=640, desiredheight=360; 

Size optimalPreviewSize = getOptimalPreviewSize(previewsizes, desiredwidth, desiredheight);         

Size optimalVideoSize = getOptimalPreviewSize(videosizes, desiredwidth, desiredheight);      

p.setPreviewSize(optimalPreviewSize.width, optimalPreviewSize.height);

 mCamera.unlock();
 mMediaRecorder = new MediaRecorder();
 mMediaRecorder.setCamera(mCamera);

 mMediaRecorder.setVideoSize(optimalVideoSize.width, optimalVideoSize.height);
 myCamera.setParameters(p);

При этом ваше приложение камеры будет работать на каждом устройстве с камерой!

ОБНОВИТЬ

С помощью getOptimalPreviewSize, который я написал, вы получите размер, отношение которого ближе к желаемому, и, если ни один из них не достаточно хорош, вы получите тот, высота которого близка к желаемому. если вы хотите придать больше значения размеру, вы можете легко изменить что-то вроде

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

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

    int targetHeight = h;

   if (  you want ratio as closed to what i asked for)
   {  for (Size size : sizes) {
        Log.d("Camera", "Checking size " + size.width + "w " + size.height
                + "h");
        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 (you want height as closed to what i asked for) { //you can do other for width
        minDiff = Double.MAX_VALUE;
        for (Size size : sizes) {
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }
    }

   if (you want the bigest one) { 
       minDiff = 0;
       for (Size size : sizes) {
           if (  size.height * size.width > minDiff ) {
               optimalSize = size;
               minDiff = size.height * size.width ;
           }
       }
   }
  return optimalSize;
}

С помощью параметров вы можете установить ширину и высоту просмотра видео.

        Camera.Parameters param = camera.getParameters();

        param.setPreviewSize("your width"
                "your height");
        camera.setParameters(param);
Другие вопросы по тегам