FFMpeg на Android, неопределенные ссылки на функции libavcodec, хотя они указаны в командной строке

У меня проблема с неразрешенными ссылками на функции libavcodec ffmpeg, пока не удалось найти ответ в других местах (включая мой разум) :)

Позвольте мне описать мою настройку - она ​​занимает много места, но на самом деле она проста, возможно, я не вижу какой-то ошибки...

Я создал FFMPeg с набором инструментов ndk r5, порт ffmpeg я получил с http://bambuser.com/opensource ( как рекомендовано в других вопросах здесь). Он отлично собран, поэтому я добавил в свой проект несколько статических библиотек, например:

<project>/jni/bambuser_ffmpeg/libavcodec.a
<project>/jni/bambuser_ffmpeg/libavformat.a
<project>/jni/bambuser_ffmpeg/libavcore.a
<project>/jni/bambuser_ffmpeg/libavutil.a

Затем я создал Android.mk в папке bambuser_ffmpeg, чтобы перечислить эти библиотеки как готовые:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := bambuser-libavcore
LOCAL_SRC_FILES := libavcore.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := bambuser-libavformat
LOCAL_SRC_FILES := libavformat.a
include $(PREBUILT_STATIC_LIBRARY)

(same for other two libs)

Затем у меня есть еще один модуль, который ссылается на эти библиотеки в своем Android.mk, устанавливает пути включения и т. д.:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := ffmpegtest
LOCAL_STATIC_LIBRARIES := bambuser-libavcodec bambuser-libavcore bambuser-libavformat bambuser-libavutil
LOCAL_SRC_FILES := ffmpeg_test.cpp
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../bambuser_ffmpeg/include
LOCAL_LDLIBS    := -llog -lz

include $(BUILD_SHARED_LIBRARY)

И, наконец, у меня есть мой ffmpeg_test.cpp, который действительно прост, например:

#include <jni.h>

extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
}

extern "C" {
    JNIEXPORT jint JNICALL Java_com_the7art_ffmpegtest_PaintThread_testFFMpeg(JNIEnv* env, jobject obj, jstring fileName);
}

JNIEXPORT jint JNICALL Java_com_the7art_ffmpegtest_PaintThread_testFFMpeg(JNIEnv* env, jobject obj, jstring fileName)
{
    av_register_all();
    return 0;
}

Когда я запускаю ndk-build, он компилируется нормально, но при компоновке выводит неразрешенную ссылку почти на каждую функцию в libavcodec. Похоже, только функции этой библиотеки не могут быть найдены:

/home/dimka/src/mobile/android/ffmpegtest/obj/local/armeabi/libavformat.a(allformats.o): In function `av_register_all':
/home/dimka/work/suzy/tmp/ffmpeg-android/ffmpeg/libavformat/allformats.c:47: undefined reference to `avcodec_register_all'
/home/dimka/src/mobile/android/ffmpegtest/obj/local/armeabi/libavformat.a(utils.o): In function `parse_frame_rate':
/home/dimka/work/suzy/tmp/ffmpeg-android/ffmpeg/libavformat/utils.c:3240: undefined reference to `av_parse_video_rate'
/home/dimka/src/mobile/android/ffmpegtest/obj/local/armeabi/libavformat.a(utils.o): In function `parse_image_size':
/home/dimka/work/suzy/tmp/ffmpeg-android/ffmpeg/libavformat/utils.c:3234: undefined reference to `av_parse_video_size'
/home/dimka/src/mobile/android/ffmpegtest/obj/local/armeabi/libavformat.a(utils.o): In function `flush_packet_queue':
/home/dimka/work/suzy/tmp/ffmpeg-android/ffmpeg/libavformat/utils.c:1277: undefined reference to `av_free_packet'
/home/dimka/work/suzy/tmp/ffmpeg-android/ffmpeg/libavformat/utils.c:1283: undefined reference to `av_free_packet'
/home/dimka/src/mobile/android/ffmpegtest/obj/local/armeabi/libavformat.a(utils.o): In function `get_audio_frame_size':
/home/dimka/work/suzy/tmp/ffmpeg-android/ffmpeg/libavformat/utils.c:766: undefined reference to `av_get_bits_per_sample'
/home/dimka/src/mobile/android/ffmpegtest/obj/local/armeabi/libavformat.a(utils.o): In function `ff_interleave_add_packet':
/home/dimka/work/suzy/tmp/ffmpeg-android/ffmpeg/libavformat/utils.c:2909: undefined reference to `av_dup_packet'
and so on...

Я не могу понять, почему это происходит. Я попытался запустить ndk-build V=1, чтобы проверить фактическую команду компоновки, и libavcodec сидит там совершенно правильно, как и должно быть. Все остальные библиотеки ffmpeg тоже есть.

Любые подсказки?


person dimsuz    schedule 17.03.2011    source источник
comment
Есть ли шанс, что ваш код будет выпущен с открытым исходным кодом? Или вы могли бы просто помочь мне, предоставив очень простую структуру (т. е. куда поместить файлы .so или .a, как это вызвать в приложении для Android)? Я попробовал как вашу исходную процедуру, так и ответ ниже, но ни один из них не сработал. Спасибо за любые подсказки!   -  person slhck    schedule 09.05.2011
comment
@slhck Может быть, я мог бы отправить вам по электронной почте мой Android.mk и заархивированный каталог, хотя это не очень сложно, напишите мне на dimsuz на gmail com. В качестве альтернативы, я думаю, вы могли бы просто задать конкретный вопрос здесь, описать свою проблему, может быть, кто-то найдет решение :)   -  person dimsuz    schedule 12.05.2011


Ответы (3)


Я также использовал ffmpeg для работы с Android. Я делаю свою сборку немного по-другому. Я беру файлы lib*.a и включаемый каталог из сборки bambuser.com и просто напрямую включаю их в свой каталог jni, мой Android.mk выглядит так:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := ndk1
LOCAL_SRC_FILES := native.c

LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_LDLIBS := -L$(NDK_PLATFORMS_ROOT)/$(TARGET_PLATFORM)/arch-arm/usr/lib -L$(LOCAL_PATH) -lavformat -lavcodec -lavdevice -lavfilter -lavutil -lswscale -llog -ljnigraphics -lz -ldl -lgcc

include $(BUILD_SHARED_LIBRARY)

Там может быть что-то бесполезное, но, возможно, это поможет указать вам правильное направление. Я попытался следовать некоторым формам, изложенным в примерах проектов NDK, как у вас. Объединение библиотек в модуль, а затем ссылка на него. Но в итоге вернулся к простому прямому включению, просто чтобы все заработало, и до сих пор не было причин пересматривать его.

person mikerowehl    schedule 18.03.2011
comment
Еще я нашел загадочную фразу NDK не поддерживает объединение статических библиотек, но я не уверен, что это значит - в конце концов, статические библиотеки - это просто наборы объектных файлов, поэтому, если я укажу их в командной строке, они должны быть связаны все вместе в указанном порядке. Так и было, но почему-то не получилось. Может быть, я не знаю каких-то деталей :) - person dimsuz; 19.03.2011
comment
Эх, теперь другое. av_open_input_file возвращает -2 (нет такого файла или каталога), когда я пытаюсь открыть файл из /sdcard/myfile.mp4 (он наверняка существует, у меня есть разрешения в androidmanifest.xml и т. д.). У вас была такая проблема, может быть, знаете решение? :) - person dimsuz; 19.03.2011
comment
На самом деле да. Если вы используете значения по умолчанию из сборки bambuser.com, у них отключен файловый протокол. У меня это включено в версии, которую я использовал, и я ссылаюсь на файл как «file:/sdcard/myfile.mp4» в своем коде. - person mikerowehl; 20.03.2011
comment
о, большое спасибо! Думаю, я перекомпилирую с включенным файловым протоколом и попробую еще раз. Я думаю, что без вашего намека на это уйдет много времени, спасибо! :) - person dimsuz; 20.03.2011
comment
Извините, что снова вас беспокою, но я снова застрял, гугление не помогает :) Файловый протокол теперь включен, но теперь я получаю ошибку -22 (Неверные данные обнаружены при обработке ввода). Я пытаюсь открыть файл mp4 - декодер mp4 тоже включен, даже пробовал разные файлы, все равно эта ошибка. Может быть, вы видели что-то подобное? :) - person dimsuz; 23.03.2011
comment
Только что узнал, что av_find_input_format (mpeg4) и av_find_input_format (mp4) возвращают значение null. Хотя я четко указал --enable-decoder=mpeg4, и он правильно включен в config.h. Чешу голову... :) - person dimsuz; 23.03.2011

У меня работает следующий Android.mk, включая обработку целевой арки. Результат запуска bambuser build.sh копируется из .../build/ffmpeg в /jni/lib/ffmpeg. Я использую PREBUILD_SHARED_LIBRARY, а не PREBUILT_STATIC_LIBRARY, как это делал OP.

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := libavcodec
LOCAL_SRC_FILES := lib/ffmpeg/$(TARGET_ARCH_ABI)/lib/$(LOCAL_MODULE).so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/lib/ffmpeg/$(TARGET_ARCH_ABI)/include
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := libavcore
LOCAL_SRC_FILES := lib/ffmpeg/$(TARGET_ARCH_ABI)/lib/$(LOCAL_MODULE).so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/lib/ffmpeg/$(TARGET_ARCH_ABI)/include
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := libavdevice
LOCAL_SRC_FILES := lib/ffmpeg/$(TARGET_ARCH_ABI)/lib/$(LOCAL_MODULE).so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/lib/ffmpeg/$(TARGET_ARCH_ABI)/include
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := libavfilter
LOCAL_SRC_FILES := lib/ffmpeg/$(TARGET_ARCH_ABI)/lib/$(LOCAL_MODULE).so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/lib/ffmpeg/$(TARGET_ARCH_ABI)/include
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := libavformat
LOCAL_SRC_FILES := lib/ffmpeg/$(TARGET_ARCH_ABI)/lib/$(LOCAL_MODULE).so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/lib/ffmpeg/$(TARGET_ARCH_ABI)/include
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := libavutil
LOCAL_SRC_FILES := lib/ffmpeg/$(TARGET_ARCH_ABI)/lib/$(LOCAL_MODULE).so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/lib/ffmpeg/$(TARGET_ARCH_ABI)/include
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := libswscale
LOCAL_SRC_FILES := lib/ffmpeg/$(TARGET_ARCH_ABI)/lib/$(LOCAL_MODULE).so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/lib/ffmpeg/$(TARGET_ARCH_ABI)/include
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)

LOCAL_MODULE    := mynativecode
LOCAL_SRC_FILES := native.c
LOCAL_SHARED_LIBRARIES := libavcore libavdevice libavfilter libavutil libswscale libavformat
LOCAL_LDLIBS := -L$(NDK_PLATFORMS_ROOT)/$(TARGET_PLATFORM)/arch-arm/usr/lib \
                -L$(LOCAL_PATH)/lib/ffmpeg/$(TARGET_ARCH_ABI)/lib \
                -lavcore \
                -lavformat \
                -lavcodec \
                -lavdevice \
                -lavfilter \
                -lavutil \
                -lswscale \
                -llog \
                -lz \
                -ldl \
                -lgcc

include $(BUILD_SHARED_LIBRARY)

Мне также пришлось изменить bambuser build.sh, чтобы изменить аргумент --soname-prefix, чтобы включить имя моего пакета, а не bambusers.

        FLAGS="--target-os=linux --cross-prefix=arm-linux-androideabi- --arch=arm"
        FLAGS="$FLAGS --sysroot=$SYSROOT"
-       FLAGS="$FLAGS --soname-prefix=/data/data/com.bambuser.broadcaster/lib/"
+       FLAGS="$FLAGS --soname-prefix=/data/data/<my package name here>/lib/"
        FLAGS="$FLAGS --enable-shared --disable-symver"
        FLAGS="$FLAGS --enable-small --optimization-flags=-O2"
person Fasaxc    schedule 05.05.2011
comment
Спасибо! Вам удалось заставить его играть что-нибудь? :) Потому что после того, как я его скомпилировал, у меня ничего не воспроизводится (см. мой последний комментарий к ответу выше) - person dimsuz; 06.05.2011
comment
да. Мне пришлось включить файловый протокол и кодек/демультиплексор, который использовал мой файл. Конфигурация Bambuser отключает все кодеки, кроме пары, которые они используют. - person Fasaxc; 12.05.2011
comment
Ага. Подозреваю, что это может быть моя проблема. Я попытался включить кодек mp4 и открыть файл mp4, но он не открывается. Я начал думать, что, может быть, мне нужно включить еще какие-то кодеки, может быть, даже попробовать включить их все :) Вы включили только определенные или все? - person dimsuz; 12.05.2011
comment
Я просто включил те, которые мне нужны. Вам понадобится файловый протокол вместе с демультиплексором 264 и декодером 264 и, возможно, парой других вещей методом проб и ошибок. Сделайте ./configure --help, а затем попробуйте параметры --list-xyz, чтобы узнать, что доступно. - person Fasaxc; 27.05.2011
comment
Какое имя моего пакета?! У меня еще нет проекта для Android! Я просто хочу скомпилировать ffmpeg для ARM! Это нормально в Ubuntu, но в Windows я получаю эту ошибку: Unknown option --soname-prefix=/data/data/com.bambuser.broadcaster/lib/ - person Dr.jacky; 06.12.2015

при сборке ffmpeg следует использовать android-14 или ниже, например:

export NDK=/Users/luoye/Downloads/android-ndk-r11c
export PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt
export PLATFORM=$NDK/platforms/android-8/arch-arm
export PREFIX=../simplefflib
build_one(){
./configure --target-os=linux --prefix=$PREFIX \
--enable-cross-compile \
--enable-runtime-cpudetect \
--disable-asm \
--arch=arm \
--cc=$PREBUILT/darwin-x86_64/bin/arm-linux-androideabi-gcc \
--cross-prefix=$PREBUILT/darwin-x86_64/bin/arm-linux-androideabi- \
--disable-stripping \
--nm=$PREBUILT/darwin-x86_64/bin/arm-linux-androideabi-nm \
--sysroot=$PLATFORM \
--enable-gpl --enable-shared --disable-static --enable-small \
--disable-ffprobe
--disable-ffplay
--disable-ffmpeg
--disable-ffserver
--disable-debug \
--extra-cflags="-fPIC -DANDROID -D__thumb__ -mthumb -Wfatal-errors -         Wno-deprecated -mfloat-abi=softfp -marm -march=armv7-a" 
}

build_one

make
make install
person Randy    schedule 01.06.2016