NDK Неразрешенная функция: media_status_t AMediaCodec_createInputSurface (AMediaCodec * mData, ANativeWindow ** surface) - PullRequest
0 голосов
/ 19 ноября 2018

Документация NDK гласит, что эта функция доступна (https://developer.android.com/ndk/reference/group/media#group___media_1ga8eb3e60bb5c76e90d7652dff636dd17b), и действительно ее можно вызывать из кода Java, но она выдает ошибку "неразрешенная функция" [в Android Studio] из кода C ++.

Я пытаюсь передать поток MJPEG в MediaCodec и сделать так, чтобы MediaMuxer записал видео MP4 с него. Я нашел ограниченные примеры того, как делать подобные вещи в коде Java, но примеры ZERO, как делать что-то подобное в родном коде. Поэтому я попытался дублировать примеры Java в нативном коде. Этот конкретный вызов функции представляется относительно важным для достижения моей цели, и я могу успешно вызвать: MediaCodec.createInputSurface() из Java-кода. Я посмотрел на media/NdkMediaCodec.h и createInputSurface() в списке НЕ .

Я поступаю неправильно, есть что-то, чего я не понимаю? Вот родной код:

jboolean Java_com_business_rky_tht_1app_MjpegView_StartMP4Record(JNIEnv *env, jclass clazz, jobject surface, jstring filename) {

AMediaCodec *Native_codec = AMediaCodec_createEncoderByType("video/avc");
if (Native_codec != NULL)
{
    AMediaFormat *Media_Format = AMediaFormat_new();
    if (Media_Format != NULL) 
    {
        AMediaCrypto *Media_Crypto = NULL;
        uint32_t Config_Flags = AMEDIACODEC_CONFIGURE_FLAG_ENCODE;
        ANativeWindow *Native_Window  = ANativeWindow_fromSurface(env, surface);

        if(Native_Window == NULL)
            return JNI_FALSE;

        int32_t Frame_Height = ANativeWindow_getHeight(Native_Window);
        int32_t Frame_Width  = ANativeWindow_getWidth(Native_Window);

        // Make the work area of the frame a multiple of 64
        int32_t Image_Height = (Frame_Height & (0xFFFFFFC0) );
        int32_t Image_Width = (Frame_Width & (0xFFFFFFC0) );
        int32_t Color_Format = ANativeWindow_getFormat(Native_Window);

        // No limits for input size
        // AMediaFormat_setInt32(format, "max-input-size", 0);
        AMediaFormat_setInt32(Media_Format, AMEDIAFORMAT_KEY_MAX_INPUT_SIZE, 0);
        AMediaFormat_setInt32(Media_Format, AMEDIAFORMAT_KEY_MAX_HEIGHT, Frame_Height);
        AMediaFormat_setInt32(Media_Format, AMEDIAFORMAT_KEY_MAX_WIDTH, Frame_Width);
        AMediaFormat_setString(Media_Format, AMEDIAFORMAT_KEY_MIME, "video/avc");
        AMediaFormat_setInt32(Media_Format, AMEDIAFORMAT_KEY_HEIGHT, Frame_Height);
        AMediaFormat_setInt32(Media_Format, AMEDIAFORMAT_KEY_WIDTH, Frame_Width);

        // ** For simplicity we just crop from right and bottom,
        // ** to center the image 1/2 the differences should be
        // ** cropped from all four sides
        AMediaFormat_setInt32(Media_Format, "crop-left" , 0);
        AMediaFormat_setInt32(Media_Format, "crop-top" , 0);
        AMediaFormat_setInt32(Media_Format, "crop-right" , (Image_Width - 1));
        AMediaFormat_setInt32(Media_Format, "crop-bottom" , (Image_Height - 1));
        AMediaFormat_setInt32(Media_Format,AMEDIAFORMAT_KEY_STRIDE,Frame_Width);

        AMediaFormat_setInt32(Media_Format, AMEDIAFORMAT_KEY_COLOR_FORMAT, Color_Format);

        media_status_t rc = AMediaCodec_configure(Native_codec, Media_Format, NULL, NULL, Config_Flags);

        if (AMEDIA_OK == rc) {

            AMediaCodec_createInputSurface(Native_codec, &Native_Window);
                            //  ^^^ UNRESOLVED - UNRESOLVED - UNRESOLVED ^^^


            // Would start codec and create muxer
            // .
            // .
            // .
            return JNI_TRUE;
        }else{
            AMediaCodec_delete(Native_codec);
            ANativeWindow_release(Native_Window);
            return JNI_FALSE;
        }
    } // End - if (Media_Format != NULL)
} // End - if (Native_codec != NULL)

} // Конец - StartMP4Rec


Ошибка сборки:

Команда построения не выполнена. Ошибка при выполнении процесса C: \ Users \ rky \ AppData \ Local \ Android \ Sdk \ ndk-bundle \ ndk-build.cmd с аргументы {NDK_PROJECT_PATH = ноль APP_BUILD_SCRIPT = C: \ Users \ скалистый \ AndroidStudioProjects \ THT_App \ приложение \ SRC \ главная \ JNI \ Android.mk NDK_APPLICATION_MK = C: \ Users \ скалистый \ AndroidStudioProjects \ THT_App \ приложение \ SRC \ главная \ JNI \ Application.mk APP_ABI = arm64-v8a NDK_ALL_ABIS = arm64-v8a NDK_DEBUG = 1 APP_PLATFORM = андроид-18 NDK_OUT = C: / Users / скалистый / AndroidStudioProjects / THT_App / приложение / сборки / промежуточные / ndkBuild / отлаживать / объект NDK_LIBS_OUT = C: \ Users \ скалистый \ AndroidStudioProjects \ THT_App \ приложение \ сборка \ полупродуктов \ ndkBuild \ Debug \ Lib С: /Users/rky/AndroidStudioProjects/THT_App/app/build/intermediates/ndkBuild/debug/obj/local/arm64-v8a/libMjpgToMP4.so} [arm64-v8a] Компиляция ++: MjpgToMP4 <= MjpgToMP4.cpp С: /Users/rky/AndroidStudioProjects/THT_App/app/src/main/jni/MjpgToMP4/MjpgToMP4.cpp: 320: 17: ошибка: использование необъявленного идентификатора 'AMediaCodec_createInputSurface'; Вы имели в виду «AMediaCodec_setOutputSurface»? AMediaCodec_createInputSurface (Native_codec, & Native_Window); ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AMediaCodec_setOutputSurface C: / Users / rky / AppData / Local / Android / Sdk / ndk-bundle / build //../ sysroot / usr / include \ media / NdkMediaCodec.h: 266: 16: примечание: здесь объявлено «AMediaCodec_setOutputSurface» media_status_t AMediaCodec_setOutputSurface (AMediaCodec *, ANativeWindow * surface) __INTRODUCED_IN (21); ^ C: /Users/rky/AndroidStudioProjects/THT_App/app/src/main/jni/MjpgToMP4/MjpgToMP4.cpp: 320: 62: ошибка: невозможно инициализировать параметр типа «ANativeWindow <em>» с Значение типа 'ANativeWindow ' AMediaCodec_createInputSurface (Native_codec, & Native_Window); ^ ~~~~~~~~~~~~~ C: / Users / скалистый / AppData / Local / Android / Sdk / NDK-расслоение / построить //../ SYSROOT / USR / включать \ Media / NdkMediaCodec.h: 266: 74: примечание: передача аргумента параметру 'surface' здесь media_status_t AMediaCodec_setOutputSurface (AMediaCodec , ANativeWindow * surface) __INTRODUCED_IN (21); ^ 2 ошибки сгенерированы. марка: * [C: /Users/rky/AndroidStudioProjects/THT_App/app/build/intermediates/ndkBuild/debug/obj/local/arm64-v8a/objs-debug/MjpgToMP4/MjpgToMP4.o] Ошибка 1

Ответы [ 2 ]

0 голосов
/ 27 ноября 2018

[решено] Как указывает отредактированный ответ Алекса Кона.Несмотря на то, что в документации сказано, AMediaCodec_createInputSurface (...) был представлен в API 26 НЕ 21. Если я редактирую приложение gradle.build так: "minSdkVersion 26", AMediaCodec_createInputSurface (...) разрешается.Если я изменю его на: "minSdkVersion 25", AMediaCodec_createInputSurface (...) НЕ будет решен.Короче говоря, документация неверна.

0 голосов
/ 19 ноября 2018

Эти функции были введены на уровне API 21 26, но ваша сборка указывает APP_PLATFORM = android-18. Убедитесь, что вы не установили minSdkVersion слишком низко в build.gradle.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...