Search code examples
androidvideo-capture

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


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?


Solution

  • 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.