I have the following code:
Log.i("xx","A");
media_recorder = new MediaRecorder();
Log.i("xx","B");
media_recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
Log.i("xx","C");
media_recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
Log.i("xx","D");
media_recorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
Log.i("xx","E");
media_recorder.setVideoSize(320, 240);
Log.i("xx","F");
media_recorder.setVideoFrameRate(15);
Log.i("xx","G");
CamcorderProfile profile = CamcorderProfile.get(CameraInfo.CAMERA_FACING_FRONT,CamcorderProfile.QUALITY_LOW);
Log.i("xx","H");
media_recorder.setProfile(profile);
Log.i("xx","I");
media_recorder.setOutputFile(fname);
When the code is executed, I see the following in my logs;
02-07 16:12:47.628: I/xx(15436): A
02-07 16:12:47.628: I/xx(15436): B
02-07 16:12:47.638: I/xx(15436): C
02-07 16:12:47.638: I/xx(15436): D
02-07 16:12:47.638: I/xx(15436): E
02-07 16:12:47.638: I/xx(15436): F
02-07 16:12:47.638: I/xx(15436): G
02-07 16:12:47.638: I/xx(15436): H
02-07 16:12:47.638: E/MediaRecorder(15436): setOutputFormat called in an invalid state: 4
This has confused me because the call to setOutputFormat
was made between "C" and "D", but the report of the error appears to be immediately after H (never reaching "I"). So now I don't know what is causing the error, and I'm confused about where the error is occurring.
EDIT: I just stepped through the code in the debugger - and sure enough the error occurs during the call to setProfile(profile)... so it would appear that the call made to setOutputFormat (between "C" & "D") must have worked ok, but then setProfile must itself make a second call to setOutputFormat which then fails... is that what's going on?
EDIT: And what does invalid state 4 actually mean? Is there some list somewhere which tells you the meaning of each possible invalid state number 1,2,3,4...etc?
Here is source code of setProfile
method:
public void setProfile(CamcorderProfile profile) {
setOutputFormat(profile.fileFormat);
setVideoFrameRate(profile.videoFrameRate);
setVideoSize(profile.videoFrameWidth, profile.videoFrameHeight);
setVideoEncodingBitRate(profile.videoBitRate);
setVideoEncoder(profile.videoCodec);
if (profile.quality >= CamcorderProfile.QUALITY_TIME_LAPSE_LOW &&
profile.quality <= CamcorderProfile.QUALITY_TIME_LAPSE_QVGA) {
// Nothing needs to be done. Call to setCaptureRate() enables
// time lapse video recording.
} else {
setAudioEncodingBitRate(profile.audioBitRate);
setAudioChannels(profile.audioChannels);
setAudioSamplingRate(profile.audioSampleRate);
setAudioEncoder(profile.audioCodec);
}
}
E.g. it sets outputFormat, videoSize, encoder and frameRate to values from profile. So your code:
Log.i("xx","C");
media_recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
Log.i("xx","D");
media_recorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
Log.i("xx","E");
media_recorder.setVideoSize(320, 240);
Log.i("xx","F");
media_recorder.setVideoFrameRate(15);
is at least useless, and maybe during these calls it changes state. Try without it.
In your above code media_recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
is called twice. 1st occurrence called by you in your code between Log.i("xx","C");
& Log.i("xx","D");
and the 2nd occurence called internally in MediaRecorder by your media_recorder.setProfile(profile);
method i.e., between Log.i("xx","H");
& Log.i("xx","I");
.
Because MediaRecorder object should follow the life cycle like below:
Refer setProfile() method in MediaRecoder class click here & compare your code again.
It happens because you can't change values in a MediaRecorder without calling reset(), so you have to set everything on the MediaRecorder itself (in fact you have to do this before API level 8, Android 2.2).
Alternatively, you can create a custom CamcorderProfile based on e.g. what you wanted, make the changes there and set that profile on the MediaRecorder, like this:
// establish the media recorder
MediaRecorder media_recorder = new MediaRecorder();
media_recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
media_recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
// Customise your profile based on a pre-existing profile
CamcorderProfile profile = CamcorderProfile.get(CameraInfo.CAMERA_FACING_FRONT,CamcorderProfile.QUALITY_LOW);
profile.fileFormat = MediaRecorder.OutputFormat.MPEG_4;
profile.videoCodec = MediaRecorder.VideoEncoder.MPEG_4_SP;
profile.videoFrameHeight = 240;
profile.videoFrameWidth = 320;
profile.videoBitRate = 15;
// Apply to MediaRecorder
media_recorder.setProfile(profile);