【问题标题】:Unable to integrate ffmpeg as a native dependency for an Android NDK project无法将 ffmpeg 集成为 Android NDK 项目的本机依赖项
【发布时间】:2016-08-13 19:38:06
【问题描述】:

我有一个完全由 C/C++ 代码组成的 Android NDK 项目,它基本上处理图像而不使用任何外部库。

我正在使用 Android Studio + Gradle NDK 实验插件 (0.7.0-alpha1)。

现在,我需要将 ffmpeg 集成为本机库,以便从 C/C++ 代码中使用它来解码 H.264 视频帧。

这些是我在这里找到的关于这个问题的问题:

Android - Integrating ffmpeg and android-ndk-r9c

Android NDK w/ ffmpeg library - error running project

Using FFmpeg native libraries with Android-NDK

Can not build with prebuilt static libraries using gradle-experimental

这是我的 build.gradle 文件:

apply plugin: 'com.android.model.application'

def ffmpeg_path = file(project(':ffmpeg').projectDir).absolutePath + "/ffmpeg-android"

model {

    repositories {
        libs(PrebuiltLibraries) {
            libavcodec {
                headers.srcDir "${ffmpeg_path}/include"
                binaries.withType(StaticLibraryBinary) {
                    staticLibraryFile = file("${ffmpeg_path}/${targetPlatform.getName()}/lib/libavcodec.a")
                }
            }
            libavutil {
                headers.srcDir "${ffmpeg_path}/include"
                binaries.withType(StaticLibraryBinary) {
                    staticLibraryFile = file("${ffmpeg_path}/${targetPlatform.getName()}/lib/libavutil.a")
                }
            }
            libswresample {
                headers.srcDir "${ffmpeg_path}/include"
                binaries.withType(StaticLibraryBinary) {
                    staticLibraryFile = file("${ffmpeg_path}/${targetPlatform.getName()}/lib/libswresample.a")
                }
            }
            libswscale {
                headers.srcDir "${ffmpeg_path}/include"
                binaries.withType(StaticLibraryBinary) {
                    staticLibraryFile = file("${ffmpeg_path}/${targetPlatform.getName()}/lib/libswscale.a")
                }
            }
            libavformat {
                headers.srcDir "${ffmpeg_path}/include"
                binaries.withType(StaticLibraryBinary) {
                    staticLibraryFile = file("${ffmpeg_path}/${targetPlatform.getName()}/lib/libavformat.a")
                }
            }
            libavdevice {
                headers.srcDir "${ffmpeg_path}/include"
                binaries.withType(StaticLibraryBinary) {
                    staticLibraryFile = file("${ffmpeg_path}/${targetPlatform.getName()}/lib/libavdevice.a")
                }
            }
            libavfilter {
                headers.srcDir "${ffmpeg_path}/include"
                binaries.withType(StaticLibraryBinary) {
                    staticLibraryFile = file("${ffmpeg_path}/${targetPlatform.getName()}/lib/libavfilter.a")
                }
            }
            libpostproc {
                headers.srcDir "${ffmpeg_path}/include"
                binaries.withType(StaticLibraryBinary) {
                    staticLibraryFile = file("${ffmpeg_path}/${targetPlatform.getName()}/lib/libpostproc.a")
                }
            }
        }
    }

    android {
        compileSdkVersion = 23
        buildToolsVersion = "23.0.2"

        defaultConfig.with {
            applicationId = "com.example.hellojni"
            minSdkVersion.apiLevel = 4
            targetSdkVersion.apiLevel = 23
        }
    }

    /*
     * native build settings
     */
    android.ndk {
        moduleName = "hello-jni"
        platformVersion = 9 //same as minSdkVersion.apiLevel for better compatibility
        stl    = "c++_static"
        abiFilters.addAll(["armeabi", "armeabi-v7a", "x86"]) //filtering ABIs on the ones Google Play Games library is compatible with.
    }
    android.buildTypes {
        release {
            minifyEnabled = false
            proguardFiles.add(file('proguard-rules.txt'))
        }
    }

    android.sources {
        main {
            jni {
                dependencies {
                    library "libavcodec" linkage "static"
                    library "libavutil" linkage "static"
                    library "libswresample" linkage "static"
                    library "libswscale" linkage "static"
                    library "libavformat" linkage "static"
                    library "libavdevice" linkage "static"
                    library "libavfilter" linkage "static"
                    library "libpostproc" linkage "static"
                }
            }
        }
    }

}

我基于来自 Google 的this sample,它集成了一个外部原生库。

这是我在导入之前编译的 ffmpeg 项目: https://github.com/WritingMinds/ffmpeg-android

我已经添加了所有 .a 和 .h 文件,并且能够在我的 C/C++ 代码中导入标头,但是当我尝试编译它时,我收到以下错误:

/Users/marcos/Documents/Android/fdecoder/ffmpeg/ffmpeg-android/armeabi-v7a/lib/libavformat.a(utils.o):utils.c:function try_decode_frame: error: undefined reference to 'avpriv_h264_has_num_reorder_frames'
/Users/marcos/Documents/Android/fdecoder/ffmpeg/ffmpeg-android/armeabi-v7a/lib/libavformat.a(utils.o):utils.c:function compute_pkt_fields: error: undefined reference to 'avpriv_h264_has_num_reorder_frames'
/Users/marcos/Documents/Android/fdecoder/ffmpeg/ffmpeg-android/armeabi-v7a/lib/libavformat.a(utils.o):utils.c:function parse_packet: error: undefined reference to 'av_parser_parse2'
/Users/marcos/Documents/Android/fdecoder/ffmpeg/ffmpeg-android/armeabi-v7a/lib/libavformat.a(utils.o):utils.c:function parse_packet: error: undefined reference to 'av_parser_close'
/Users/marcos/Documents/Android/fdecoder/ffmpeg/ffmpeg-android/armeabi-v7a/lib/libavformat.a(utils.o):utils.c:function read_frame_internal: error: undefined reference to 'av_parser_init'
/Users/marcos/Documents/Android/fdecoder/ffmpeg/ffmpeg-android/armeabi-v7a/lib/libavformat.a(utils.o):utils.c:function avformat_find_stream_info: error: undefined reference to 'av_parser_init'
/Users/marcos/Documents/Android/fdecoder/ffmpeg/ffmpeg-android/armeabi-v7a/lib/libavformat.a(utils.o):utils.c:function avformat_find_stream_info: error: undefined reference to 'avcodec_pix_fmt_to_codec_tag'
/Users/marcos/Documents/Android/fdecoder/ffmpeg/ffmpeg-android/armeabi-v7a/lib/libavformat.a(utils.o):utils.c:function avformat_find_stream_info: error: undefined reference to 'avpriv_get_raw_pix_fmt_tags'
/Users/marcos/Documents/Android/fdecoder/ffmpeg/ffmpeg-android/armeabi-v7a/lib/libavformat.a(utils.o):utils.c:function ff_stream_add_bitstream_filter: error: undefined reference to 'av_bitstream_filter_init'
/Users/marcos/Documents/Android/fdecoder/ffmpeg/ffmpeg-android/armeabi-v7a/lib/libavformat.a(utils.o):utils.c:function ff_stream_add_bitstream_filter: error: undefined reference to 'av_bitstream_filter_close'
/Users/marcos/Documents/Android/fdecoder/ffmpeg/ffmpeg-android/armeabi-v7a/lib/libavformat.a(utils.o):utils.c:function av_apply_bitstream_filters: error: undefined reference to 'av_bitstream_filter_filter'
/Users/marcos/Documents/Android/fdecoder/ffmpeg/ffmpeg-android/armeabi-v7a/lib/libavformat.a(aadec.o):aadec.c:function aa_read_packet: error: undefined reference to 'av_tea_init'
/Users/marcos/Documents/Android/fdecoder/ffmpeg/ffmpeg-android/armeabi-v7a/lib/libavformat.a(aadec.o):aadec.c:function aa_read_packet: error: undefined reference to 'av_tea_crypt'
/Users/marcos/Documents/Android/fdecoder/ffmpeg/ffmpeg-android/armeabi-v7a/lib/libavformat.a(aadec.o):aadec.c:function aa_read_header: error: undefined reference to 'av_tea_alloc'
/Users/marcos/Documents/Android/fdecoder/ffmpeg/ffmpeg-android/armeabi-v7a/lib/libavformat.a(aadec.o):aadec.c:function aa_read_header: error: undefined reference to 'av_tea_init'
/Users/marcos/Documents/Android/fdecoder/ffmpeg/ffmpeg-android/armeabi-v7a/lib/libavformat.a(aadec.o):aadec.c:function aa_read_header: error: undefined reference to 'av_tea_crypt'
/Users/marcos/Documents/Android/fdecoder/ffmpeg/ffmpeg-android/armeabi-v7a/lib/libavformat.a(ac3dec.o):ac3dec.c:function ac3_eac3_probe.isra.0: error: undefined reference to 'avpriv_ac3_parse_header'
/Users/marcos/Documents/Android/fdecoder/ffmpeg/ffmpeg-android/armeabi-v7a/lib/libavformat.a(adtsenc.o):adtsenc.c:function adts_write_header: error: undefined reference to 'avpriv_mpeg4audio_get_config'
/Users/marcos/Documents/Android/fdecoder/ffmpeg/ffmpeg-android/armeabi-v7a/lib/libavformat.a(adtsenc.o):adtsenc.c:function adts_write_header: error: undefined reference to 'avpriv_copy_pce_data'
/Users/marcos/Documents/Android/fdecoder/ffmpeg/ffmpeg-android/armeabi-v7a/lib/libavformat.a(asfcrypt.o):asfcrypt.c:function ff_asfcrypt_dec: error: undefined reference to 'av_rc4_alloc'
/Users/marcos/Documents/Android/fdecoder/ffmpeg/ffmpeg-android/armeabi-v7a/lib/libavformat.a(asfcrypt.o):asfcrypt.c:function ff_asfcrypt_dec: error: undefined reference to 'av_rc4_init'
/Users/marcos/Documents/Android/fdecoder/ffmpeg/ffmpeg-android/armeabi-v7a/lib/libavformat.a(asfcrypt.o):asfcrypt.c:function ff_asfcrypt_dec: error: undefined reference to 'av_rc4_crypt'
/Users/marcos/Documents/Android/fdecoder/ffmpeg/ffmpeg-android/armeabi-v7a/lib/libavformat.a(asfcrypt.o):asfcrypt.c:function ff_asfcrypt_dec: error: undefined reference to 'av_rc4_init'
/Users/marcos/Documents/Android/fdecoder/ffmpeg/ffmpeg-android/armeabi-v7a/lib/libavformat.a(asfcrypt.o):asfcrypt.c:function ff_asfcrypt_dec: error: undefined reference to 'av_rc4_crypt'
/Users/marcos/Documents/Android/fdecoder/ffmpeg/ffmpeg-android/armeabi-v7a/lib/libavformat.a(matroska.o):matroska.c:function ff_mkv_stereo3d_conv: error: undefined reference to 'av_stereo3d_alloc'
/Users/marcos/Documents/Android/fdecoder/ffmpeg/ffmpeg-android/armeabi-v7a/lib/libavformat.a(nut.o):nut.c:function ff_nut_add_sp: error: undefined reference to 'av_tree_node_alloc'
/Users/marcos/Documents/Android/fdecoder/ffmpeg/ffmpeg-android/armeabi-v7a/lib/libavformat.a(nut.o):nut.c:function ff_nut_add_sp: error: undefined reference to 'av_tree_insert'
/Users/marcos/Documents/Android/fdecoder/ffmpeg/ffmpeg-android/armeabi-v7a/lib/libavformat.a(nut.o):nut.c:function ff_nut_free_sp: error: undefined reference to 'av_tree_enumerate'
/Users/marcos/Documents/Android/fdecoder/ffmpeg/ffmpeg-android/armeabi-v7a/lib/libavformat.a(nut.o):nut.c:function ff_nut_free_sp: error: undefined reference to 'av_tree_destroy'
Error:error: ld returned 1 exit status
Error:Execution failed for task ':app:linkHello-jniArmeabi-v7aDebugSharedLibrary'.
> A build operation failed.
      Linker failed while linking libhello-jni.so.
  See the complete log at: file:///Users/marcos/Documents/Android/fdecoder/app/build/tmp/linkHello-jniArmeabi-v7aDebugSharedLibrary/output.txt
Information:BUILD FAILED
Information:Total time: 14.993 secs
Information:2 errors
Information:0 warnings
Information:See complete output in console

显然我没有正确导入某些内容,但无法准确确定缺少什么。

【问题讨论】:

  • dependencies 部分中库的顺序很重要。您应该将 avcodec 和 avutils 推到列表的末尾
  • @AlexCohn 有道理,我会尝试并告诉你进展如何。谢谢!

标签: android android-studio ffmpeg android-ndk gradle-experimental


【解决方案1】:

下面的 Makefile 对我有用。 (对应这个code

target:muxing

CXX = g++ 
# default rules
# compile:  $(CXX) $(CPPFLAGS) -c
# link:     $(CC) $(LDFLAGS) <n>.o $(LOADLIBES) $(LDLIBS)
FFMPEG_PATH += ./ffmpeg-2.8.15/lib/ LDFLIBS += $(addprefix ${FFMPEG_PATH}, \
           libavdevice.a \
           libyasm.a \
           libavfilter.a \
           libpostproc.a \
           libavformat.a \
           libswresample.a \
           libswscale.a \
           libavcodec.a \
           libavutil.a \
           libmp3lame.a \
           libfdk-aac.a \
           libx264.a \
           ) 
LDFLIBS += -lpthread -lcrypto -lz -lssl -ldl INCS += $(addprefix -I, ./ffmpeg-2.8.15/include/)    
CFLAGS = ${INCS} CPPFLAGS = ${CFLAGS}

muxing: muxing.o
    ${CXX} ${CPPFLAGS} $^ -o $@ ${LDFLIBS}


.PHONY:clean clean:
    rm -f muxing.o muxing

【讨论】:

    猜你喜欢
    • 2021-02-06
    • 1970-01-01
    • 1970-01-01
    • 2021-01-04
    • 1970-01-01
    • 1970-01-01
    • 2012-11-04
    • 1970-01-01
    • 2018-11-21
    相关资源
    最近更新 更多