Referencias no definidas durante el uso de ffmpeg 2.1.1 para Android
android-ndk (1)
Estoy construyendo ffmpeg siguiendo el mismo patrón que la construcción de halfninja : hacer que la main
de ffmpeg esté disponible desde Java a través de JNI. Construí ffmpeg con las siguientes opciones:
./configure /
--prefix=$PREFIX /
--disable-shared /
--enable-static /
--disable-doc /
--disable-ffmpeg /
--disable-ffplay /
--disable-ffprobe /
--disable-ffserver /
--disable-doc /
--disable-symver /
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- /
--target-os=linux /
--arch=arm /
--enable-cross-compile /
--sysroot=$SYSROOT /
--extra-cflags="-Os -fpic $ADDI_CFLAGS" /
--extra-ldflags="$ADDI_LDFLAGS"
$PREFIX
, TOOLCHAIN
, ... en las carpetas correspondientes de mi NDK. $ADDI_CFLAGS
está configurado en -marm
y $ADDI_LDFLAGS
y $ADDITIONAL_CONFIGURE_FLAGS
están ambos desarmados. Las bibliotecas estáticas resultantes se crean:
$ ls -1 android/arm/lib/ libavcodec.a libavdevice.a libavfilter.a libavformat.a libavutil.a libswresample.a libswscale.a pkgconfig
Los Android.mk
con un archivo Android.mk
, ffmpeg está siendo Android.mk
en $NDK/sources/ffmpeg-2.1.1
:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:= libavdevice
LOCAL_SRC_FILES:= lib/libavdevice.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= libavcodec
LOCAL_SRC_FILES:= lib/libavcodec.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= libavformat
LOCAL_SRC_FILES:= lib/libavformat.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= libswscale
LOCAL_SRC_FILES:= lib/libswscale.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= libavutil
LOCAL_SRC_FILES:= lib/libavutil.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= libavfilter
LOCAL_SRC_FILES:= lib/libavfilter.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= libwsresample
LOCAL_SRC_FILES:= lib/libswresample.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)
Entonces, hasta allí, todo se ve bien. Ahora, intento construir el equivalente binario de ffmpeg
como una biblioteca estática. Copié (y no ffmpeg.c
un solo carácter por el momento) ffmpeg.c
, ffmpeg.h
, cmdutils.c
, cmdutils.h
, ffmpeg_opt.c
y ffmpeg_filter.c
en mi carpeta jni
. También tengo dos archivos directamente relacionados con JNI en esta carpeta (copiados de la compilación de halfninja, acabo de cambiar el nombre del paquete). Aquí está el Android.mk
relevante:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := /Applications/android-ndk-r9b/sources/ffmpeg-2.1.1
LOCAL_CFLAGS := -Wdeprecated-declarations
LOCAL_MODULE := videokit
ANDROID_LIB := -landroid
LOCAL_LDLIBS += -llog -ljnigraphics -lz
LOCAL_SRC_FILES := videokit/com_rfc_video_ffmpeg_Videokit.c videokit/ffmpeg.c videokit/cmdutils.c videokit/ffmpeg_opt.c videokit/ffmpeg_filter.c
LOCAL_SHARED_LIBRARIES := libavdevice libavformat libavfilter libavcodec libwscale libavutil libswresample libswscale libpostproc
include $(BUILD_SHARED_LIBRARY)
$(call import-module,ffmpeg-2.1.1/android/arm)
Todo compila bien, pero no enlaza. Aquí están los primeros errores:
[armeabi] SharedLibrary : libvideokit.so /Applications/android-ndk-r9b/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/objs/videokit/videokit/cmdutils.o: in function print_all_libs_info.constprop.5:jni/videokit/cmdutils.c:1063: error: undefined reference to ''swresample_version'' /Applications/android-ndk-r9b/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/objs/videokit/videokit/cmdutils.o: in function print_all_libs_info.constprop.5:jni/videokit/cmdutils.c:1063: error: undefined reference to ''swresample_configuration'' /Applications/android-ndk-r9b/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/objs/videokit/videokit/cmdutils.o: in function opt_default:jni/videokit/cmdutils.c:558: error: undefined reference to ''swr_get_class'' /Applications/android-ndk-r9b/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/objs/videokit/videokit/cmdutils.o: in function opt_default:jni/videokit/cmdutils.c:561: error: undefined reference to ''swr_alloc'' /Applications/android-ndk-r9b/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/objs/videokit/videokit/cmdutils.o: in function opt_default:jni/videokit/cmdutils.c:563: error: undefined reference to ''swr_free'' /Applications/android-ndk-r9b/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/objs/videokit/videokit/ffmpeg_opt.o: in function show_help_default:jni/videokit/ffmpeg_opt.c:2464: error: undefined reference to ''swr_get_class''
Lo que no entiendo es que estas funciones están definidas y disponibles en libswresample.a
, a las que estoy vinculando:
arm-linux-androideabi-nm /Applications/android-ndk-r9b/sources/ffmpeg-2.1.1/android/arm/lib/libswresample.a | grep -i -e swr_get_class -e swresample_version 000001d4 T swr_get_class 00000178 T swresample_version
¿Qué estoy haciendo mal? ¿Hay alguna otra manera, quizás más simple, de exponer ffmpeg como una biblioteca estática disponible a través de JNI? (No uso halfninja porque necesito al menos ffmpeg 1.1, mientras que el suyo está en 0.9).
Sus nombres están un poco revueltos: en un lugar, lo llamaron libwsresample
, en otro lugar libswresample
.
Verifique todos los nombres por consistencia.