【问题标题】:Pause/Resume MediaCodec暂停/恢复媒体编解码器
【发布时间】:2014-01-27 21:45:56
【问题描述】:

我正在尝试为我的应用实现暂停/恢复功能,该功能使用 MediaCodec 记录显示捕获。 我尝试在不调用 mEncoder.release() 的情况下执行 mEncoder.stop() 和 mEncoder.start() ,但这没有用。再次调用 mEncoder.start() 时出现 IllegalStateException。 现在我实施了一种解决方法,在捕获完成后我正在合并视频的和平,但合并需要很长时间。 任何人都可以帮助我吗?也许有人已经实现了这个东西?

初始化:

    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;

暂停:

    public void pauseRecordPressed() {
    if (isRecording){
        isRecording = false;
        drainEncoder(false);

        if (mEncoder != null) {
            mEncoder.stop();
        }
    }
}

取消暂停:

    public void resumeRecordPressed() {
    mEncoder.start();
    isRecording = true;
}

例外:

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)

媒体格式:

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

【问题讨论】:

  • 您的一些代码将帮助我们找出问题
  • mFormat 你能把代码放在哪里??
  • 嗨,Alex,我也面临同样的问题。如果您分享解决方案(代码),这对我很有帮助。

标签: android video-capture android-mediacodec


【解决方案1】:

MediaCodec 停止时会丢弃其配置,因此您需要再次调用 configure()。我不确定您为什么要尝试重新启动它 - 您可以让它保持活动状态,而不提供数据。

例如,请参阅 Grafika 中的 CameraCaptureActivity,这会使编码器在活动重新启动时保持活动状态。如果您不想在重启期间暂停视频,则需要跟踪编码暂停的时间,然后调整输入多路复用器的时间戳。

【讨论】:

  • 我这样做是因为信息安全:developer.android.com/reference/android/media/…。 stop() 完成解码/编码会话,注意编解码器实例保持活动状态并准备再次启动()。不过谢谢你的建议,我试试看!
  • 您能否给我一些示例,说明如何调整 MediaCodec 视频捕获的时间戳。这对我有很大帮助。提前致谢!
  • 我不认为有一个 CTS 测试可以执行此操作(通常等同于“它不起作用”),但事实证明 bigflake.com/mediacodec/#DecoderTest 可以。您只需再次致电configure() [答案已更新]。对于时间戳,在onPause()onResume() 中记录当前时间,以确定您睡了多长时间,然后从您提交的每个时间戳中减去该时间。确保你得到正确的时间尺度(微秒与毫秒或纳秒),否则可能会发生疯狂的事情。
  • fadden,非常感谢!我完全按照你的建议做了,我能够消除视频部分之间的差距。现在我只有一个黑框来代替合并。我不相信有可能摆脱它吗?
  • 是的,这就是问题所在。暂停/恢复后我忘记重置帧计数器。再次感谢!
【解决方案2】:
private void suspendMediaCodec(boolean suspend)
{
    if(mediaCodec != null)
    {
        Bundle params = new Bundle();
        params.putInt(MediaCodec.PARAMETER_KEY_SUSPEND, suspend ? 1 : 0);
        mediaCodec.setParameters(params);
    }
}

您可以通过设置参数 MediaCodec.PARAMETER_KEY_SUSPEND 暂停/恢复媒体编解码器以丢帧。以上是一个例子。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-12
    • 2023-04-05
    • 2014-02-18
    • 2016-09-21
    • 2014-05-26
    相关资源
    最近更新 更多