2011-03-17 14 views
10

Tengo un problema con referencias no resueltas a funciones libavcodec de ffmpeg, hasta ahora no he podido encontrar la respuesta en otros lugares (incluida mi mente) :)FFMpeg en Android, referencias indefinidas a funciones libavcodec, aunque aparece en la línea de comandos

Vamos a describir mi configuración - se necesita espacio, pero es muy básico, podría ser que estoy fallando a ver algunos errores ...

I construyó un conjunto de herramientas con fFmpeg NDK R5, puerto ffmpeg llegué desde http://bambuser.com/opensource (como se recomienda en otras preguntas aquí). Se construye muy bien, por lo que poner varias librerías estáticas en mi proyecto como este:

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

A continuación, he creado una carpeta en Android.mk bambuser_ffmpeg enumerar estas bibliotecas como los prediseñados:

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) 

a continuación, tengo otro módulo que hace referencia a estas bibliotecas en su Android.mk, configura incluir caminos, etc:

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) 

Y finalmente tengo mi ffmpeg_test.cpp que es muy básico, así:

#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; 
} 

Cuando corro NDK-construir, que compila bien, pero cuando la vinculación se imprime una referencia sin resolver a casi todas las funciones en libavcodec. Parece que solo las funciones de esta lib no están ubicadas:

/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...

No entiendo por qué sucede esto. Traté de ejecutar ndk-build V = 1 para comprobar el comando de enlace real, y libavcodec está sentado allí perfectamente, como debería. Todas las otras libs ffmpeg están allí también.

¿Alguna pista?

+0

¿Hay alguna posibilidad de que su código va a ser liberado de código abierto? ¿O podría ayudarme proporcionando una estructura muy básica (es decir, dónde colocar los archivos .so o .a, cómo llamarlo en la aplicación de Android)? Probé tanto su procedimiento original como la respuesta a continuación, pero ninguno funcionó. Gracias por cualquier pista! – slhck

+0

@slhck Tal vez podría enviarte un correo electrónico con mi Android.mk y el directorio comprimido, aunque no es muy complejo allí, escríbeme a dimsuz en gmail com. Como alternativa, supongo que puedes hacer una pregunta específica aquí, describir tu problema, tal vez alguien encuentre una solución :) – dimsuz

Respuesta

2

He estado usando ffmpeg para algunos trabajos Android también. Aunque hago mi compilación un poco diferente. Tomo los archivos lib * .a y la incluyo dir de la acumulación bambuser.com y justo directamente los incluyo en mi directorio JNI, mi Android.mk se ve así:

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) 

Puede haber alguna costra allí , pero tal vez te ayude a orientarte en la dirección correcta. Intenté seguir algunos de los formularios establecidos en los proyectos de ejemplo de NDK como los que tiene. Agrupar las librerías en un módulo y luego hacer referencia a eso. Pero terminaron recurriendo a la simple inclusión directa solo para que las cosas funcionen, y hasta ahora no han tenido motivos para volver a visitarla.

+0

Eso funcionó bien, ¡muchas gracias! :) – dimsuz

+0

Lo que también encontré es la misteriosa frase "NDK no admite la combinación de bibliotecas estáticas", pero no estoy seguro de lo que significa: al final, las bibliotecas estáticas son solo colecciones de archivos de objetos, por lo que si las especifico al comando línea, deben estar vinculados todos juntos en el orden especificado. Ese fue el caso, pero no funcionó por alguna razón. Tal vez no conozco algunos detalles :) – dimsuz

+0

Eh, ahora otra cosa. av_open_input_file devuelve -2 (sin dicho archivo o directorio) cuando intento abrir un archivo desde /sdcard/myfile.mp4 (seguramente existe, tengo permisos en androidmanifest.xml, etc.). ¿Tuviste tal problema quizás, conoces la solución? :) – dimsuz

5

El siguiente Android.mk funciona para mí, incluido el manejo del arco de destino. El resultado de ejecutar bambuser build.sh se copia de .../build/ffmpeg a/jni/lib/ffmpeg. Estoy usando PREBUILD_SHARED_LIBRARY en lugar de PREBUILT_STATIC_LIBRARY como lo hizo 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) 

También tuve que cambiar el build.sh Bambuser para modificar el argumento --soname-prefijo para incluir mi nombre de paquete en lugar de 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" 
+0

¡Gracias! ¿Lograste tocar algo? :) Porque después de compilarlo, no puedo jugar nada (ver mi último comentario a la respuesta anterior) – dimsuz

+2

Sí. Tuve que habilitar el protocolo de archivo y el códec/demuxer que estaba usando mi archivo. La configuración de Bambuser desactiva todos los códecs excepto los que usan. – Fasaxc

+0

Aha. Sospecho que este podría ser mi problema. Intenté habilitar el códec mp4 y abrir el archivo mp4, pero no se abrirá. Empecé a pensar que tal vez tenía que habilitar algunos códecs más, tal vez incluso tratar de habilitarlos a todos :) ¿Habilita solo algunos específicos o todos? – dimsuz

0

cuando se genera ffmpeg debe usar android-14 o inferior, de esta manera:

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 
Cuestiones relacionadas