Hello I am making an android application in which I am using custom camera for recording camera.I am having problem on samsung device.I can not set the profile of Media recorder to CamcorderProfile.get(cameraid, CamcorderProfile.QUALITY_HIGH)
also when try to use
profile = CamcorderProfile.get(cameraid, CamcorderProfile.QUALITY_LOW);
profile.videoFrameHeight=360;
profile.videoFrameWidth=640;
then my app is working on some devices but crashes on many devices.Any type of help will be appreciable.Thanks in advance please check the code
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;
This happens because you are requesting the dimensions that you want, but not everycamera is capable of every dimension.
Besides, some devices works with camera aspect ratios slightly diferent, so if you are requesting a rectangle with a wrong ratio, or with a dimensions diferent from the supported, it will crash in some devices.
What to do?
Step 1.
you have to check for the supported sizes. You can do it with
Camera.Parameters p = myCamera.getParameters();
List<Size> previewsizes = p.getSupportedPreviewSizes();
List<Size> videosizes = p.getSupportedVideoSizes();
and then, you can choose one. If you want to automatize this, you can go further, and follow the
Step 2
write a function to select the best available size, which will receive the supported sizes, and the desired size, something like:
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;
}
And the last step, set the parameters
Step 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);
With this, your camera app will work in every device with a camera!
UPDATE
With the getOptimalPreviewSize that i wrote, you get the size whose ratio is closer to the desired, and if none is good enough, you get the one which height is closed to the desired. if you want to give more importante to the size, you can make an easy change, something like
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;
}