setOutputFormat called in an invalid state: 4 (where and why)

风流意气都作罢 提交于 2019-12-09 10:08:50

问题


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?


回答1:


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.




回答2:


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.




回答3:


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);


来源:https://stackoverflow.com/questions/21632769/setoutputformat-called-in-an-invalid-state-4-where-and-why

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!