Showing posts with label Camera. Show all posts
Showing posts with label Camera. Show all posts

Monday, January 2, 2017

Android MediaRecorder Stop Failed - 1007

If you have ever used Android MediaRecorder to record video or audio in your android application, you must have faced this error. Recently I had nightmare in using MediaRecorder in my android application. I think it's most unstable class in Android SDK and there is a different behavior in each device. In this blog I am going to explain more about this and possible resolution of this.


First lets see wha's the meaning of this error : Android MediaRecorder Stop Failed - 1007

There is no documentation on Android developer site about this error code but from my experience I found out that there are three reasons behind this error

1) You called stop method too early.

According to documentation on MediaRecorder.java class it says

Stops recording. Call this after start(). Once recording is stopped, you will have to configure it again as if it has just been constructed. Note that a RuntimeException is intentionally thrown to the application, if no valid audio/video data has been received when stop() is called. This happens if stop() is called immediately after start(). The failure lets the application take action accordingly to clean up the output file (delete the output file, for instance), since the output file is not properly constructed when this happens.

That means if you start recording and in couple of seconds you call stop recording there is no significant data of recording hence stop method throws an exception. So you must wait for sometime. From my testing I found out that you should at least for minimum 10 seconds. So the solution is to have stop method called inside try catch block and handle the exception properly or do not allow user to stop recording till 10 seconds of start of recording. You can either disable stop button and make it enable after sometime. Once the exception is thrown, you should clean the the resources, release media recorder and camera and all other objects.

2) Error in Writing to Output file

We have to set output file to MediaRecorder when we start recording. When you stop all the recorded data will be appended in output file specified by you on start. This could failed due to reasons like insufficient space to write file or you don't have permissions to write to external and internal storage due in Android 6.0 on words.

3) MisMatch in preview size and video size set in MediaRecorder

I have mentioned about this in my previous blog. You can read it here.

Android MediaRecorder Start Failed - 19

Hope this helps you and save you time.

Friday, December 30, 2016

Android MediaRecorder Start Failed - 19

If you have ever used Android MediaRecorder to record video or audio in your android application, you must have faced this error. Recently I had nightmare in using MediaRecorder in my android application. I think it's most unstable class in Android SDK and there is a different behavior in each device. In this blog I am going to explain more about this and possible resolution of this.

First lets see wha's the meaning of this error : Android MediaRecorder Start Failed - 19

There is no documentation on Android developer site about this error code but from my experience I found out that it's because of mis match in size of video preview frame and MediaRecorder video size and this error comes randomly in different devices. The best approach is to use CamCorder profile as mentioned on Android developer site.

CamcorderProfile profile =CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
mMediaRecorder.setProfile(profile);

When you use this most of the following default values are set in MediaRecorder from the selected profile.


  • OutputFormat
  • AudioEncoder
  • VideoEncoder
  • VideoSize
  • VideoFrameRate

But this does not work on all the devices as some the devices don't accept these default values hence MediaRecorder does not work and specifically due to VideoSize it gives error. So to solve this you should manually set all the values. Following settings works on almost all devices

int width = mCamera.getParameters().getPreviewSize().width;
int height = mCamera.getParameters().getPreviewSize().height;

mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
mMediaRecorder.setVideoSize(width, height);
mMediaRecorder.setVideoFrameRate(30);

However there are still some problem with it. When I tested in some high resolution devices. I got following width and height from getPreviewSize()

2048
1536

But MediaRecorder failed to start and when I checked error log I got error.

Unsupported Video Dimension 1920 X 1688

That means it changed the dimension by itself and ignored the width and height I set it in setVideoSize. So that means you can not depend on it. So what's the solution for this. Well the solution is find the optimal video size based on your preferred frame dimensions and available supported size in your device. Following is the function I used for it.

private Size getOptimalPreviewSize(List sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.2;
double targetRatio = (double) w / h;
if (sizes == 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) {
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;
}


List sizes = mCamera.getParameters().getSupportedPreviewSizes();
Camera.Size optimal = getOptimalPreviewSize(sizes, 640, 480);

if(optimal != null){
           
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
mMediaRecorder.setVideoSize(optimal.width, optimal.height);
mMediaRecorder.setVideoFrameRate(30);      

}else{

int width = mCamera.getParameters().getPreviewSize().width;
int height = mCamera.getParameters().getPreviewSize().height;

mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
mMediaRecorder.setVideoSize(width, height);
mMediaRecorder.setVideoFrameRate(30);      

}    

For me above solution worked on almost all devices, first we get optimal size from available supported sizes and if there is no supported sizes then we use default preview size.