AMediaCodec_start()返回-10000的原因及解决思路求助
首先,错误码-10000在NDK MediaCodec的错误映射里属于底层未明确分类的未知错误,但结合你只在第8次重建Codec时触发的现象,几乎可以肯定是资源泄漏或状态机混乱导致的底层资源耗尽。我来帮你拆解问题并给出针对性的排查方向:
1. 先修正代码里的两个致命错误
错误1:用C++ delete销毁AMediaCodec实例
你的destroyCodec函数里,在AMediaCodec_stop成功后直接调用delete codec;,这是完全错误的!NDK的AMediaCodec是通过C API创建的,必须使用AMediaCodec_delete(codec)来销毁,而不是C++的delete操作符。这种错误会导致底层的MediaCodec实例没有被系统正确回收,每次重建都会残留一个无效实例,次数多了(比如第8次)就会触发系统的资源限制,导致start失败。
修正后的destroyCodec销毁部分:
status = AMediaCodec_stop(codec); if (status != AMEDIA_OK) { LOG_E("MediaCodec stop failed with status = %d", status); ASSERT(false, "Stop failed!"); } else { if (codec) { AMediaCodec_delete(codec); // 替换delete为AMediaCodec_delete codec= nullptr; } }
错误2:reCreateCodec里重复调用AMediaCodec_configure
看你的reCreateCodec代码,居然连续调用了两次AMediaCodec_configure!第一次configure之后没有处理错误分支的清理逻辑,第二次又重复配置,这会让MediaCodec的状态机彻底混乱。虽然前7次可能侥幸通过,但多次重复操作会积累底层状态错误,最终在第8次触发失败。
你需要删掉重复的那行configure代码,确保只调用一次,并且在configure失败时正确销毁已创建的Codec:
// 保留这一次configure即可 media_status_t status = AMediaCodec_configure(mCodec, androidMediaFormat, mOutputTexture.nativeWindow, NULL, 0); if (status != AMEDIA_OK){ LOG_E("Could not configure video decoder, status = %d", status); AMediaFormat_delete(androidMediaFormat); AMediaCodec_delete(mCodec); // 配置失败时要销毁已创建的codec mCodec = nullptr; mState = DecoderHWState::ERROR_STATE; return; // 提前返回,避免后续执行start } mState = DecoderHWState::CONFIGURED; AMediaFormat_delete(androidMediaFormat); status = AMediaCodec_start(mCodec); if (status != AMEDIA_OK){ LOG_E("MediaCodec start failed, status = %d", status); }
2. 额外排查方向
检查SurfaceTexture/ANativeWindow的资源泄漏
你的Codec绑定了mOutputTexture.nativeWindow,如果每次重建Codec时都创建了新的SurfaceTexture,但旧的SurfaceTexture没有被正确释放或解绑,底层的窗口资源会被耗尽。你需要确保在destroyCodec时,正确释放关联的SurfaceTexture资源(比如调用ANativeWindow_release,如果是从SurfaceTexture获取的nativeWindow)。
查看系统层MediaCodec日志
只看自己的日志只能得到-10000这个模糊的错误,你可以通过adb命令抓取系统层的MediaCodec日志,获取更详细的错误原因:
adb logcat -s MediaCodec MediaCodecInfo
日志里可能会出现类似“Too many instances of codec type”或者“Failed to allocate output buffer”的具体信息,直接指向问题根源。
验证MediaCodec实例的回收情况
使用adb命令查看当前系统中活跃的MediaCodec实例:
adb shell dumpsys media.codec
在每次调用destroyCodec后,检查对应的decoder实例是否已经从列表中消失。如果第8次重建时,活跃实例数超过了设备的限制(通常同类型Codec实例有数量上限),就会导致start失败。
检查mLastDecodedFrameIndex的有效性
在destroyCodec里调用AMediaCodec_releaseOutputBuffer之前,要先判断mLastDecodedFrameIndex是否为有效值(比如不等于-1),否则可能触发不必要的错误,虽然这不一定是第8次失败的直接原因,但会干扰资源回收流程。
内容的提问来源于stack exchange,提问作者Kai Fang

