Andriod studio3.5搭建ffmpeg helloworld(动态库文件)

环境

win7、jdk8、Andriod studio3.5、 NDK21


写在前

  1. 采用编译好的ffmpeg动态库文件(多个动态文件)
  2. Android studio3.5创建navtive c++工程已经配置好jni demo,不用考虑gradle和cmake协调配置,非常方便
  3. 不同版本的Android studio创建的C+项目的CMakeLists.txt放置路径不一样,多用message命令确认内置变量的值

简单总结

一般NDK开发时会有三方面报错

  1. 编辑C/C++代码时,找不到头文件。说明CMakeLists.txt配置有漏
  2. build构建时,链接linked报错。说明CMakeLists.txt配置有漏
  3. 运行时找不到so文件,闪退,这是外部so文件没有打包如apk中。说明build.gradle配置有漏。或者将外部so文件放入main/jniLibs/{ABI版本}中
    具体的解决方案看本文最后

使用静态文件 vs 使用动态文件

  1. 使用静态文件在build构建时会编入内部so文件中;而使用动态文件,需要把外部so文件打包如spk中
  2. 静态文件会缺少uncompress等函数定义,需要添加压缩库(Z);使用动态文件则不用

操作步骤-详细:

  1. AS添加C++工程


    image.png
  2. 拷贝ffmpeg文件到AS工程,目录结构如下


    image.png
  3. 修改app的gradle.build

apply plugin: 'com.android.application'

android {
    compileSdkVersion 30
    buildToolsVersion "30.0.3"
    defaultConfig {
        applicationId "com.example.mmffndk"
        minSdkVersion 21
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                cppFlags ""
               abiFilters 'armeabi-v7a'    //ABIs [armeabi] are not supported for platform. Supported ABIs are [arm64-v8a, armeabi-v7a, x86, x86_64].
            
            }
        }

        ndk{                //修改点2
            abiFilters 'armeabi-v7a'
        }

        sourceSets {
            main {
                jniLibs.srcDirs = ['libs']  //jniLibs打包时会查找libs/${ANDROID_ARCH_ABI}/*.so
            }
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt"
            version "3.10.2"
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.0.2'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.0'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
}

  1. 修改CMakeLists.txt
  • 需要注意:
    1) 不同版本的android studio生成项目的CMakeLists.txt路径不同,所以CMAKE_SOURCE_DIR的值不同
    2)使用ffmpeg动态库,已经包含压缩等。所以target_link_libraries不需要添加 -lz
cmake_minimum_required(VERSION 3.4.1)

# 指定引入文件头路径 , include文件夹里放置了ffmpeg的.h头文件
include_directories(${CMAKE_SOURCE_DIR}/ffmpeg/include)

# 指定 .so共享库目录 (相当于添加 CXXFLAGS=-Lpath)
link_directories(${PROJECT_SOURCE_DIR}/../../../libs/${CMAKE_ANDROID_ARCH_ABI})

# 指定 c/c++ 源文件目录
aux_source_directory(${CMAKE_SOURCE_DIR} cpp-list)
message(STATUS "cpp-list = ${cpp-list}")

add_library( # Sets the name of the library.
       native-lib11
       SHARED
       ${cpp-list})

find_library( # Sets the name of the path variable.
       log-lib
       log)

target_link_libraries( # Specifies the target library.
       native-lib11
       avcodec avdevice avfilter avformat avutil swresample swscale
       android
       ${log-lib})
  1. 点击 build->rebuild project ,项目构建完成后,打开 apk分析器(build ->apk analyze然后选择apk)
    由于我们在app:build.gradle里配置 abiFilters=armeabi-v7a,而且配置了jniLibs.srcDirs = 'libs'。所以apk打包时会在lib下创建armeabi-v7a文件夹,并且把项目中libs目录下armeabi-v7a里所有so文件拷贝过来。 同样的,如果配置 abiFilters='armeabi-v7a'和'arm64-v8a', 则会在apk的lib下创建armeabi-v7a和arm64-v8a两个文件夹,并且把项目中的libs目录下对应的文件夹拷贝过来。如果项目中没有libs/arm64-v8a目录,则build的时候会报错
    image.png

常见错误

  1. 头文件找不到
  • 现象:编辑c/cpp代码时报错 cannot find 'libavcodec'


    image.png
  • 原因:头文件路径错误
  • 解决方案:
    ①先在 CmakeLists.txt 里添加:include_directories(${CMAKE_SOURCE_DIR}/ffmpeg/include)
    ②点击 build->refresh linked C++ projects
  1. 链接错误:linker command failed with exit code 1 (use -v to see invocation)
  • 现象:build构建时报错:undefined reference to 'avutil_configuration'
[2/2] Linking CXX shared library G:\learn\androidlearn\workstation\Mmffndk\app\build\intermediates\cmake\debug\obj\armeabi-v7a\libnative-lib.so
  FAILED: G:/android/workstation/Mmffndk/app/build/intermediates/cmake/debug/obj/armeabi-v7a/libnative-lib.so 
  cmd.exe /C "cd . && G:\learn\androidlearn\studio\sdk\ndk\21.0.6113669\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=armv7-none-linux-androideabi21 --gcc-toolchain=G:/android/studio/sdk/ndk/21.0.6113669/toolchains/llvm/prebuilt/windows-x86_64 --sysroot=G:/android/studio/sdk/ndk/21.0.6113669/toolchains/llvm/prebuilt/windows-x86_64/sysroot -fPIC -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -march=armv7-a -mthumb -Wformat -Werror=format-security   -O0 -fno-limit-debug-info  -Wl,--exclude-libs,libgcc_real.a -Wl,--exclude-libs,libatomic.a -static-libstdc++ -Wl,--build-id -Wl,--fatal-warnings -Wl,--exclude-libs,libunwind.a -Wl,--no-undefined -Qunused-arguments -shared -Wl,-soname,libnative-lib.so -o G:\learn\androidlearn\workstation\Mmffndk\app\build\intermediates\cmake\debug\obj\armeabi-v7a\libnative-lib.so CMakeFiles/native-lib.dir/native-lib.cpp.o  -lavformat -lavcodec -lavfilter -lavutil -lswresample -lswscale -landroid -llog -latomic -lm && cd ."
  G:/android/studio/sdk/ndk/21.0.6113669/toolchains/llvm/prebuilt/windows-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin\ld: error: cannot find -lavformat
  G:/android/studio/sdk/ndk/21.0.6113669/toolchains/llvm/prebuilt/windows-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin\ld: error: cannot find -lavcodec
  G:/android/studio/sdk/ndk/21.0.6113669/toolchains/llvm/prebuilt/windows-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin\ld: error: cannot find -lavfilter
  G:/android/studio/sdk/ndk/21.0.6113669/toolchains/llvm/prebuilt/windows-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin\ld: error: cannot find -lavutil
  G:/android/studio/sdk/ndk/21.0.6113669/toolchains/llvm/prebuilt/windows-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin\ld: error: cannot find -lswresample
  G:/android/studio/sdk/ndk/21.0.6113669/toolchains/llvm/prebuilt/windows-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin\ld: error: cannot find -lswscale
  G:/android/workstation/Mmffndk/app/src/main/cpp/native-lib.cpp:27: error: undefined reference to 'avutil_configuration'
  G:/android/workstation/Mmffndk/app/src/main/cpp/native-lib.cpp:40: error: undefined reference to 'av_register_all'
  G:/android/workstation/Mmffndk/app/src/main/cpp/native-lib.cpp:42: error: undefined reference to 'avformat_alloc_context'
  G:/android/workstation/Mmffndk/app/src/main/cpp/native-lib.cpp:52: error: undefined reference to 'av_dict_set'
  G:/android/workstation/Mmffndk/app/src/main/cpp/native-lib.cpp:54: error: undefined reference to 'avformat_open_input'
  G:/android/workstation/Mmffndk/app/src/main/cpp/native-lib.cpp:62: error: undefined reference to 'avformat_find_stream_info'
  G:/android/workstation/Mmffndk/app/src/main/cpp/native-lib.cpp:87: error: undefined reference to 'avcodec_find_decoder'
  G:/android/workstation/Mmffndk/app/src/main/cpp/native-lib.cpp:94: error: undefined reference to 'avcodec_open2'
  G:/android/workstation/Mmffndk/app/src/main/cpp/native-lib.cpp:102: error: undefined reference to 'sws_getContext'
  G:/android/workstation/Mmffndk/app/src/main/cpp/native-lib.cpp:108: error: undefined reference to 'av_malloc'
  G:/android/workstation/Mmffndk/app/src/main/cpp/native-lib.cpp:110: error: undefined reference to 'av_init_packet'
  G:/android/workstation/Mmffndk/app/src/main/cpp/native-lib.cpp:116: error: undefined reference to 'av_frame_alloc'
  G:/android/workstation/Mmffndk/app/src/main/cpp/native-lib.cpp:119: error: undefined reference to 'av_frame_alloc'
  G:/android/workstation/Mmffndk/app/src/main/cpp/native-lib.cpp:122: error: undefined reference to 'avpicture_get_size'
  G:/android/workstation/Mmffndk/app/src/main/cpp/native-lib.cpp:121: error: undefined reference to 'av_malloc'
  G:/android/workstation/Mmffndk/app/src/main/cpp/native-lib.cpp:125: error: undefined reference to 'avpicture_fill'
  G:/android/workstation/Mmffndk/app/src/main/cpp/native-lib.cpp:136: error: undefined reference to 'av_read_frame'
  G:/android/workstation/Mmffndk/app/src/main/cpp/native-lib.cpp:144: error: undefined reference to 'avcodec_decode_video2'
  G:/android/workstation/Mmffndk/app/src/main/cpp/native-lib.cpp:155: error: undefined reference to 'sws_scale'
  G:/android/workstation/Mmffndk/app/src/main/cpp/native-lib.cpp:179: error: undefined reference to 'av_free_packet'
  G:/android/workstation/Mmffndk/app/src/main/cpp/native-lib.cpp:185: error: undefined reference to 'av_frame_free'
  G:/android/workstation/Mmffndk/app/src/main/cpp/native-lib.cpp:186: error: undefined reference to 'av_frame_free'
  G:/android/workstation/Mmffndk/app/src/main/cpp/native-lib.cpp:188: error: undefined reference to 'avcodec_close'
  G:/android/workstation/Mmffndk/app/src/main/cpp/native-lib.cpp:189: error: undefined reference to 'avformat_free_context'
  clang++: error: linker command failed with exit code 1 (use -v to see invocation)
  • 原因:so文件没有引入
  • 解决方法:在 CMakeLists.txt添加
# 指定 .so共享库目录 (如果是 .a静态文件,需要添加 CXXFLAGS)
link_directories(${PROJECT_SOURCE_DIR}/../../../libs/${CMAKE_ANDROID_ARCH_ABI})
  1. ffmpeg的so文件没有打入apk包
    现象:打包没报错,运行时闪退,报错如下
E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.mmffndk, PID: 7253
    java.lang.UnsatisfiedLinkError: dlopen failed: library "libavformat.so" not found: needed by /data/app/~~VZddftg5_hnlp3FkuHdTxg==/com.example.mmffndk-NDSt_nrh6mmjLv39fko4gQ==/lib/arm/libnative-lib.so in namespace classloader-namespace
        at java.lang.Runtime.loadLibrary0(Runtime.java:1087)
        at java.lang.Runtime.loadLibrary0(Runtime.java:1008)
        at java.lang.System.loadLibrary(System.java:1664)
        at com.example.mmffndk.MainActivity.<clinit>(MainActivity.java:25)
        at java.lang.Class.newInstance(Native Method)
        at android.app.AppComponentFactory.instantiateActivity(AppComponentFactory.java:95)
        at androidx.core.app.CoreComponentFactory.instantiateActivity(CoreComponentFactory.java:43)
        at android.app.Instrumentation.newActivity(Instrumentation.java:1253)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3353)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
D/libEGL: loaded /vendor/lib/egl/libEGL_emulation.so

解决方案:
① 打开 apk analyze,确认ffmpeg相关的外部so文件没有打入apk中


image.png

② 确认app:build.gradle有没有报错


image.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容