I'm trying to implement pause/resume feature for my app that records display capture using MediaCodec. I've tried doing mEncoder.stop() and then mEncoder.start() without calling mEncoder.release() but that didn't work. I get IllegalStateException when calling mEncoder.start() again. Right now I implemented a workaround, I'm merging peaces of video after the capture is complete, but it takes a really long time to merge. Can anyone help me with that? Maybe someone has already implemented this thing?
Initialazation:
MediaCodec mEncoder;
mEncoder = MediaCodec.createEncoderByType(Preferences.MIME_TYPE);
mEncoder.configure(mFormat, null, null,
MediaCodec.CONFIGURE_FLAG_ENCODE);
mInputSurface = new InputSurface(mEncoder.createInputSurface(),
mSavedEglContext);
mEncoder.start();
try {
String fileId = String.valueOf(System.currentTimeMillis());
mMuxer = new MediaMuxer(dir.getPath() + "/Video"
+ fileId + ".mp4",
MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
videoParts.add(fileId);
} catch (IOException ioe) {
throw new RuntimeException("MediaMuxer creation failed", ioe);
}
isRecording = true;
Pause:
public void pauseRecordPressed() {
if (isRecording){
isRecording = false;
drainEncoder(false);
if (mEncoder != null) {
mEncoder.stop();
}
}
}
Unpause:
public void resumeRecordPressed() {
mEncoder.start();
isRecording = true;
}
Exception:
01-09 15:34:27.980: E/AndroidRuntime(21467): FATAL EXCEPTION: main
01-09 15:34:27.980: E/AndroidRuntime(21467): Process: com.example.poc, PID: 21467
01-09 15:34:27.980: E/AndroidRuntime(21467): java.lang.IllegalStateException: start failed
01-09 15:34:27.980: E/AndroidRuntime(21467): at android.media.MediaCodec.start(Native Method)
01-09 15:34:27.980: E/AndroidRuntime(21467): at com.example.poc.MyRenderer.resumeRecordPressed(MyRenderer.java:501)
01-09 15:34:27.980: E/AndroidRuntime(21467): at com.example.poc.MyGLSurfaceView.resumeRecordPressed(MyGLSurfaceView.java:243)
01-09 15:34:27.980: E/AndroidRuntime(21467): at com.example.poc.MainActivity.onClick(MainActivity.java:775)
01-09 15:34:27.980: E/AndroidRuntime(21467): at android.view.View.performClick(View.java:4438)
01-09 15:34:27.980: E/AndroidRuntime(21467): at android.view.View$PerformClick.run(View.java:18422)
01-09 15:34:27.980: E/AndroidRuntime(21467): at android.os.Handler.handleCallback(Handler.java:733)
01-09 15:34:27.980: E/AndroidRuntime(21467): at android.os.Handler.dispatchMessage(Handler.java:95)
01-09 15:34:27.980: E/AndroidRuntime(21467): at android.os.Looper.loop(Looper.java:136)
01-09 15:34:27.980: E/AndroidRuntime(21467): at android.app.ActivityThread.main(ActivityThread.java:5017)
01-09 15:34:27.980: E/AndroidRuntime(21467): at java.lang.reflect.Method.invokeNative(Native Method)
01-09 15:34:27.980: E/AndroidRuntime(21467): at java.lang.reflect.Method.invoke(Method.java:515)
01-09 15:34:27.980: E/AndroidRuntime(21467): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
01-09 15:34:27.980: E/AndroidRuntime(21467): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
01-09 15:34:27.980: E/AndroidRuntime(21467): at dalvik.system.NativeStart.main(Native Method)
MediaFormat:
mFormat = createMediaFormat();
private static MediaFormat createMediaFormat() {
MediaFormat format = MediaFormat.createVideoFormat(
Preferences.MIME_TYPE, mScreenWidth, mScreenHeight);
format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
format.setInteger(MediaFormat.KEY_BIT_RATE, Preferences.BIT_RATE);
format.setInteger(MediaFormat.KEY_FRAME_RATE, Preferences.FRAME_RATE);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL,
Preferences.IFRAME_INTERVAL);
return format;
}
The MediaCodec
discards its configuration when stopped, so you will need to call configure()
again. I'm not sure why you're trying to do restart it though -- you can just leave it active, without feeding it data.
For example, see the CameraCaptureActivity
in Grafika, which leaves the encoder alive across activity restarts. If you don't want to have a pause in the video during the restart, you'll need to keep track of how long encoding was paused, and then adjust the timestamps being fed into the muxer.
private void suspendMediaCodec(boolean suspend)
{
if(mediaCodec != null)
{
Bundle params = new Bundle();
params.putInt(MediaCodec.PARAMETER_KEY_SUSPEND, suspend ? 1 : 0);
mediaCodec.setParameters(params);
}
}
You can suspend/resume mediacodec to drop frames by setting parameter MediaCodec.PARAMETER_KEY_SUSPEND. Above one is example to do it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With