Android NDK MediaCodec异步模式回调函数未触发求助
问题根因与修复方案
1. 未向解码器输入AVC数据(核心原因)
解码器启动后处于空闲等待状态,必须主动向其输入AVC码流数据(包含SPS/PPS和编码帧),才会触发onAsyncInputAvailable/onAsyncOutputAvailable等回调。你的代码仅完成了解码器的配置与启动,没有任何输入数据的逻辑,解码器无工作任务,自然不会触发回调。
修复:在AMediaCodec_start之后添加输入数据的逻辑:
// 示例:向解码器输入单帧AVC数据(实际需根据传入的frames jobject解析批量数据) ssize_t inputBufferIdx = AMediaCodec_dequeueInputBuffer(decoder, 10000); // 超时10ms if (inputBufferIdx >= 0) { uint8_t* inputBuffer = AMediaCodec_getInputBuffer(decoder, inputBufferIdx); // 从frames中取出AVC数据,填充到inputBuffer size_t dataSize = ...; // 实际数据长度 memcpy(inputBuffer, avcFrameData, dataSize); // 提交输入buffer,时间戳需按实际帧率设置 AMediaCodec_queueInputBuffer(decoder, inputBufferIdx, 0, dataSize, 0, 0); }
2. AMediaCodecOnAsyncNotifyCallback内存管理错误
你通过new在堆上创建结构体,但AMediaCodec_setAsyncNotifyCallback接收的是结构体的值拷贝,堆上的结构体未释放会造成内存泄漏;若后续意外释放,还可能导致回调逻辑异常。
修复:直接在栈上声明结构体即可:
AMediaCodecOnAsyncNotifyCallback notifyCallback = { [](AMediaCodec *codec, void *userdata, int32_t index) { __android_log_print(ANDROID_LOG_ERROR, "Native_Gate", "onAsyncInputAvailable"); }, [](AMediaCodec *codec, void *userdata, int32_t index, AMediaCodecBufferInfo *bufferInfo) { __android_log_print(ANDROID_LOG_ERROR, "Native_Gate", "onAsyncOutputAvailable"); }, [](AMediaCodec *codec, void *userdata, AMediaFormat *format) { __android_log_print(ANDROID_LOG_ERROR, "Native_Gate", "onAsyncFormatChanged"); }, [](AMediaCodec *codec, void *userdata, media_status_t error, int32_t actionCode, const char *detail) { __android_log_print(ANDROID_LOG_ERROR, "Native_Gate", "onAsyncError"); } }; status = AMediaCodec_setAsyncNotifyCallback(decoder, notifyCallback, nullptr);
3. 未正确释放资源(潜在问题)
- 创建的
AMediaFormat未调用AMediaFormat_delete(format),会造成内存泄漏,建议在AMediaCodec_configure执行后调用。 ANativeWindow不能在函数结束前释放,需在解码器停止(AMediaCodec_stop)并销毁(AMediaCodec_delete)后,再调用ANativeWindow_release(window)。
4. API版本兼容性问题
AMediaCodec_setAsyncNotifyCallback是Android API 26(Android 8.0)才引入的接口,若测试设备系统版本低于8.0,该函数会返回错误,回调无法触发。可通过打印set callback failed的错误码确认,若错误码为-22(MEDIA_ERROR_INVALID_OPERATION),则大概率是API版本不兼容。
修复:如需兼容低版本,需改用同步模式(循环调用dequeueInputBuffer/dequeueOutputBuffer),或通过API版本判断选择异步/同步逻辑。
内容的提问来源于stack exchange,提问作者xufei
相关产品推荐
相关产品推荐

