Search code examples
androidh.264android-mediacodec

MediaCodec Async mode with NDK not triggering callback functions


I'm working on a demo to decode AVC stream using Android NDK MediaCodec. The following jni function is called from Kotlin, the MediaCodec callback functions, "notifyCallback", are not triggered. They don't work as expected.

extern "C"
JNIEXPORT void JNICALL
Java_com_initiald_avcdemo_MainActivityKt_configCodec(JNIEnv *env, jclass clazz,
                                                     jobject surface, jobject frames) {
    __android_log_print(ANDROID_LOG_INFO, "Native_Gate", "configCodec>>>>");

    AMediaCodec* decoder = AMediaCodec_createCodecByName("OMX.google.h264.decoder");
    AMediaFormat* format = AMediaFormat_new();
    AMediaFormat_setString(format, "mime", "video/avc");
    AMediaFormat_setInt32(format, "width", 832);
    AMediaFormat_setInt32(format, "height", 480);

    ANativeWindow* window = ANativeWindow_fromSurface(env, surface);
    if(NULL == window){
        __android_log_print(ANDROID_LOG_ERROR, "Native_Gate", "native window is null");
        return;
    }

    AMediaCodecOnAsyncNotifyCallback* notifyCallback = new  AMediaCodecOnAsyncNotifyCallback{
            []( 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");
            }
    };


    media_status_t status = AMediaCodec_configure(decoder, format, window, NULL, 0);
    if(status != 0){
        __android_log_print(ANDROID_LOG_ERROR, "Native_Gate", "config codec failed [%d]", status);
        return;
    }

    status = AMediaCodec_setAsyncNotifyCallback(decoder, *notifyCallback, nullptr);
    if(status != 0){
        __android_log_print(ANDROID_LOG_ERROR, "Native_Gate", "set callback failed [%d]", status);
        return;
    }


    status = AMediaCodec_start(decoder);
    if(status != 0){
        __android_log_print(ANDROID_LOG_ERROR, "Native_Gate", "start codec failed");
        return;
    }

 
    // ANativeWindow_release(window);
    __android_log_print(ANDROID_LOG_INFO, "Native_Gate", "configCodec<<<<<");
}

Can anyone help me identify the root cause of this issue? or share me relvant documents. Thank you!


Solution

  • According to the documentation:

    If the client intends to use the component in asynchronous mode, a valid callback should be provided before configure(MediaFormat, Surface, MediaCrypto, int) is called.

    In your case, AMediaCodec_setAsyncNotifyCallback should be called before calling AMediaCodec_configure.