Android平台下编译FFmpeg用于视频压缩处理
2017-11-17 18:24
746 查看
最近因为项目需求需要用到视频压缩处理,其实这个功能要实现出来很简单,到Github上拉几个知名的库分分钟搞定,但是那些比较知名的库功能很齐全所以包也比较大,arm、arm-v7a、arm64-v8a、x86、x86_64等基本全部做到了支持。为了解决这个问题顺便学习学习NDK入门方面的知识,本文仅仅分析arm-v7a架构的编译,其他的几种处理方式原理是一样的,有兴趣自己可以编译下。
Android studio 2.3.3 (需要配置ndk环境)
如果你是linux或者Mac环境那是最方便了,本人偷懒懒得装个Ubuntu所以还是在Windows上编译了,Android环境下的jni开发有两种方式,一种是传统的配置Android.mk,另一种就是AS2.2及以后主推的配置cmakelist方法,这里使用新方法进行编译因为更加简单。
x264文件放libx264的源码,fad-aac-0.1.5文件夹放libfdk-aac源码,ffmpeg-3.2.5文件夹放FFmpeg-3.2.5源码,buildoutput里面放我们编译上述源码的so文件及头文件。我们所做的工作就是把号称最好的视频编码器libx264和音频编码器libfdk-aac替换ffmpeg自带的音视频编码器,然后把ffmpeg编译出来丢到buildoutput文件里面去。
编译请特别注意如果直接按照未修改的配置进行编译,结果编译出来的so文件类似libavcodec.so.55.39.101,版本号位于so之后,Android上似乎无法加载。因此需要按如下修改:
将x264/configure文件的
修改成
然后我们运行MinGW\msys\1.0目录下的msys.bat,cd到该目录执行x264_arm_build.sh脚本
chmod +x 命令是设置执行权限,出现上面的图说明编译成功了,现在去buildoutput/lib目录可以看到编译后生成的文件了。
同样,我们cd到这个目录执行脚本命令./fdkacc_arm_build.sh,这个等的时间有点长。。。
编译完成后去buildoutput/lib目录就能看到fdk_aac目录了。
disable-encoders 禁用全部的编码器,然后视频使用libx264,音频使用libfdk_aac,以及图片mjpeg png等
disable-decoders 禁用全部的解码器,然后使用几个常用的
disable-demuxers 禁用全部的视音频分离器,然后使用几个常用的
disable-parsers 禁止全部的解析器,然后使用几个常用的
主要是这四个方面,其他一些应该也是通用作用的,具体没研究过。执行脚本命令./ffmpeg_arm_build.sh
编译完成后去buildoutput/lib目录就能看到ffmpeg目录了。
1.创建默认支持jni的项目,找到编译后ffmpeg-3.2.5文件目录找到如下8个文件,然后复制到项目的cpp目录(最新的ffmpeg源码目录没有cmdutils_common_opts.h编译方式未知)
2.把编译后产生的目录buildoutput/lib/ffmpeg/armv7-a中的产生头文件的include目录拷贝到cpp目录下
3.ffmpeg.c文件中有个main方法,这个就是ffmpeg命令执行的入口,我们把它改成我们自定义的函数名称run_command,并且在ffmpeg.h里面加上函数声明int run_command(int argc,char **argv);。
4.找到cmdutils.c中的exit_program函数,把exit_program函数修改成:
cmdutils.h中exit_program的申明,也把返回类型修改为int类型
5.修改ffmpeg.c之前我们自定义的run_command方法,在末尾加上如下代码:
6.实现我们定义的jni函数,在之前我们创建的ffmpeg_cmd_run.c中:
7.配置cmakelist用来编译jni,然后把之前编译ffmpeg生成的目录/buildoutput/lib/ffmpeg/armv7-a/lib
里面的七个so文件放到我们项目的/app/src/main/jniLibs/armeabi-v7a里面,还需要把ffmpeg源码放在项目根目录,目的是为了给我们上面引入的几个c文件设置头文件。
8.两个注意点:
1.本文只编译了armeabi-v7a架构的so文件,所以需要在build.gradle中过滤下:
2.千万不要忘了加上文件读写权限,不然会报Fatal signal 11 (SIGSEGV), code 1, fault addr 0x18 in tid 9051 (Thread-26083)错误,因为c代码在控制台上只报这一行错误,所以很难找到问题所在,本人也被这个问题坑了很久,最近有时间加上了日志系统才找到问题所在。
最后附上源码: Github
编译环境
Windows下编译(需要配置MinGW)Android studio 2.3.3 (需要配置ndk环境)
如果你是linux或者Mac环境那是最方便了,本人偷懒懒得装个Ubuntu所以还是在Windows上编译了,Android环境下的jni开发有两种方式,一种是传统的配置Android.mk,另一种就是AS2.2及以后主推的配置cmakelist方法,这里使用新方法进行编译因为更加简单。
下载相关源码
我在桌面创建一个目录FFmpegInAndroid,里面创建如下几个目录:x264文件放libx264的源码,fad-aac-0.1.5文件夹放libfdk-aac源码,ffmpeg-3.2.5文件夹放FFmpeg-3.2.5源码,buildoutput里面放我们编译上述源码的so文件及头文件。我们所做的工作就是把号称最好的视频编码器libx264和音频编码器libfdk-aac替换ffmpeg自带的音视频编码器,然后把ffmpeg编译出来丢到buildoutput文件里面去。
编译 x264 视频编码器
在buildoutput目录创建写一个编译x264的脚本x264_arm_build.sh#!/bin/bash # ndk 环境(改成自己的相应的环境) NDK=E:/Android/sdk/ndk-bundle SYSROOT=$NDK/platforms/android-14/arch-arm/ TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64 # cpu 架构平台,若要编译 x86 则指定 x86 CPU=armv7-a # 输出文件的前缀,也就是指定最后静态库输出到那里 PREFIX=$(pwd)/lib/x264/$CPU # 优化参数 OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU " ADDI_CFLAGS="" ADDI_LDFLAGS="" # 因为当前目录在 build 目录,需要切换到 x264找到源码去执行 config cd ../x264 function build_x264 { ./configure \ --prefix=$PREFIX \ --disable-shared \ --disable-asm \ --enable-static \ --enable-pic \ --enable-strip \ --host=arm-linux-androideabi \ --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \ --sysroot=$SYSROOT --extra-cflags="-Os -fpic $ADDI_CFLAGS $OPTIMIZE_CFLAGS" \ --extra-ldflags="$ADDI_LDFLAGS" \ $ADDITIONAL_CONFIGURE_FLAG make clean make -j4 make install } # 执行编译指令 build_x264
编译请特别注意如果直接按照未修改的配置进行编译,结果编译出来的so文件类似libavcodec.so.55.39.101,版本号位于so之后,Android上似乎无法加载。因此需要按如下修改:
将x264/configure文件的
echo "SOSUFFIX=so" >> config.mak echo "SONAME=libx264.so.$API" >> config.mak echo "SOFLAGS=-shared -Wl,-soname,\$(SONAME) $SOFLAGS" >> config.mak
修改成
echo "SOSUFFIX=so" >> config.mak echo "SONAME=libx264-$API.so" >> config.mak echo "SOFLAGS=-shared -Wl,-soname,\$(SONAME) $SOFLAGS" >> config.mak
然后我们运行MinGW\msys\1.0目录下的msys.bat,cd到该目录执行x264_arm_build.sh脚本
chmod +x 命令是设置执行权限,出现上面的图说明编译成功了,现在去buildoutput/lib目录可以看到编译后生成的文件了。
编译 fad-aac 音频编码器
先在buildoutput目录创建一个配置脚本文件fdkacc_arm_build.sh# 这个路径要根据自己环境修改 NDK=E:/Android/sdk/ndk-bundle ANDROID_API=android-14 SYSROOT=$NDK/platforms/android-14/arch-arm/ ANDROID_BIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin CROSS_COMPILE=${ANDROID_BIN}/arm-linux-androideabi- CPU=armv7-a # 输出文件的前缀,也就是指定最后静态库输出到那里 PREFIX=$(pwd)/lib/fdk_aac/$CPU CFLAGS="" FLAGS="--enable-static --host=arm-linux-androideabi --target=android --disable-asm " export CXX="${CROSS_COMPILE}g++ --sysroot=${SYSROOT}" export LDFLAGS=" -L$SYSROOT/usr/lib $CFLAGS " export CXXFLAGS=$CFLAGS export CFLAGS=$CFLAGS export CC="${CROSS_COMPILE}gcc --sysroot=${SYSROOT}" export AR="${CROSS_COMPILE}ar" export LD="${CROSS_COMPILE}ld" export AS="${CROSS_COMPILE}gcc" # 因为当前目录在 build 目录,需要切换到fdk-aac-0.1.3找到源码去执行 cd ../fdk-aac-0.1.5 function build_fdkacc { ./configure $FLAGS \ --enable-pic \ --enable-strip \ --prefix=$PREFIX\ $ADDITIONAL_CONFIGURE_FLAG make clean make -j12 make install } # 执行编译指令 build_fdkacc
同样,我们cd到这个目录执行脚本命令./fdkacc_arm_build.sh,这个等的时间有点长。。。
编译完成后去buildoutput/lib目录就能看到fdk_aac目录了。
交叉编译FFmpeg
所以的准备工作做好了后,我们开始编译ffmpeg,同样的我们还是在buildoutput目录创建一个配置脚本文件ffmpeg_arm_build.sh,由于完全编译的话可能so文件会很大,所以我们编译一个精简版的ffmpeg,我们从如何几个方面入手:disable-encoders 禁用全部的编码器,然后视频使用libx264,音频使用libfdk_aac,以及图片mjpeg png等
disable-decoders 禁用全部的解码器,然后使用几个常用的
disable-demuxers 禁用全部的视音频分离器,然后使用几个常用的
disable-parsers 禁止全部的解析器,然后使用几个常用的
主要是这四个方面,其他一些应该也是通用作用的,具体没研究过。执行脚本命令./ffmpeg_arm_build.sh
编译完成后去buildoutput/lib目录就能看到ffmpeg目录了。
编译Android环境的FFmpeg
上面我们已经把我们定制的ffmpeg编译出来了,接下来我们需要修改ffmpeg源码的某些c类来满足Android环境下的使用,然后通过JNI给Java调用执行ffmpeg的命令,我们用cMake方式来写jni。1.创建默认支持jni的项目,找到编译后ffmpeg-3.2.5文件目录找到如下8个文件,然后复制到项目的cpp目录(最新的ffmpeg源码目录没有cmdutils_common_opts.h编译方式未知)
ffmpeg_filter.c ffmpeg_opt.c ffmpeg.c ffmpeg.h cmdutils_common_opts.h cmdutils.c cmdutils.h config.h (编译后才会有生成config.h)
2.把编译后产生的目录buildoutput/lib/ffmpeg/armv7-a中的产生头文件的include目录拷贝到cpp目录下
3.ffmpeg.c文件中有个main方法,这个就是ffmpeg命令执行的入口,我们把它改成我们自定义的函数名称run_command,并且在ffmpeg.h里面加上函数声明int run_command(int argc,char **argv);。
4.找到cmdutils.c中的exit_program函数,把exit_program函数修改成:
int exit_program(int ret) { av_log(NULL, AV_LOG_FATAL,"Quit at %d",ret); if (program_exit) program_exit(ret); // exit(ret); return ret; }
cmdutils.h中exit_program的申明,也把返回类型修改为int类型
int exit_program(int ret);
5.修改ffmpeg.c之前我们自定义的run_command方法,在末尾加上如下代码:
nb_filtergraphs = 0; progress_avio = NULL; input_streams = NULL; nb_input_streams = 0; input_files = NULL; nb_input_files = 0; output_streams = NULL; nb_output_streams = 0; output_files = NULL; nb_output_files = 0;
6.实现我们定义的jni函数,在之前我们创建的ffmpeg_cmd_run.c中:
#include "ffmpeg.h" #include <jni.h> JNIEXPORT jint JNICALL com_example_ffmpeginandroid_MainActivity_ffmpegCommand(JNIEnv *env, jobject instance, jobjectArray cmd) { int argc = (*env)->GetArrayLength(env,cmd); char *argv[argc]; int i; for (i = 0; i < argc; i++) { jstring js = (jstring) (*env)->GetObjectArrayElement(env,cmd, i); argv[i] = (char *) (*env)->GetStringUTFChars(env,js, 0); } return run_command(argc,argv); }
7.配置cmakelist用来编译jni,然后把之前编译ffmpeg生成的目录/buildoutput/lib/ffmpeg/armv7-a/lib
里面的七个so文件放到我们项目的/app/src/main/jniLibs/armeabi-v7a里面,还需要把ffmpeg源码放在项目根目录,目的是为了给我们上面引入的几个c文件设置头文件。
# For more information about using CMake with Android Studio, read the # documentation: https://d.android.com/studio/projects/add-native-code.html # Sets the minimum version of CMake required to build the native library. cmake_minimum_required(VERSION 3.4.1) # Creates and names a library, sets it as either STATIC # or SHARED, and provides the relative paths to its source code. # You can define multiple libraries, and CMake builds them for you. # Gradle automatically packages shared libraries with your APK. add_library( # Sets the name of the library. ffmpeg-lib # Sets the library as a shared library. SHARED # Provides a relative path to your source file(s). src/main/cpp/cmdutils.c src/main/cpp/ffmpeg.c src/main/cpp/ffmpeg_filter.c src/main/cpp/ffmpeg_opt.c src/main/cpp/ffmpeg_cmd_run.c ) add_library( avcodec SHARED IMPORTED ) add_library( avfilter SHARED IMPORTED ) add_library( avformat SHARED IMPORTED ) add_library( avutil SHARED IMPORTED ) add_library( swresample SHARED IMPORTED ) add_library( swscale SHARED IMPORTED ) add_library( fdk-aac SHARED IMPORTED ) if(${ANDROID_ABI} STREQUAL "armeabi") set_target_properties( avcodec PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi/libavcodec.so ) set_target_properties( avfilter PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi/libavfilter.so ) set_target_properties( avformat PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi/libavformat.so ) set_target_properties( avutil PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi/libavutil.so ) set_target_properties( swresample PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi/libswresample.so ) set_target_properties( swscale PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi/libswscale.so ) set_target_properties( fdk-aac PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi/libfdk-aac.so ) endif(${ANDROID_ABI} STREQUAL "armeabi") if(${ANDROID_ABI} STREQUAL "armeabi-v7a") set_target_properties( avcodec PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libavcodec.so ) set_target_properties( avfilter PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libavfilter.so ) set_target_properties( avformat PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libavformat.so ) set_target_properties( avutil PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libavutil.so ) set_target_properties( swresample PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libswresample.so ) set_target_properties( swscale PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libswscale.so ) set_target_properties( fdk-aac PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libfdk-aac.so ) endif(${ANDROID_ABI} STREQUAL "armeabi-v7a") if(${ANDROID_ABI} STREQUAL "arm64-v8a") set_target_properties( avcodec PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/arm64-v8a/libavcodec.so ) set_target_properties( avfilter PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/arm64-v8a/libavfilter.so ) set_target_properties( avformat PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/arm64-v8a/libavformat.so ) set_target_properties( avutil PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/arm64-v8a/libavutil.so ) set_target_properties( swresample PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/arm64-v8a/libswresample.so ) set_target_properties( swscale PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/arm64-v8a/libswscale.so ) set_target_properties( fdk-aac PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/arm64-v8a/libfdk-aac.so ) endif(${ANDROID_ABI} STREQUAL "arm64-v8a") if(${ANDROID_ABI} STREQUAL "x86") set_target_properties( avcodec PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86/libavcodec.so ) set_target_properties( avfilter PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86/libavfilter.so ) set_target_properties( avformat PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86/libavformat.so ) set_target_properties( avutil PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86/libavutil.so ) set_target_properties( swresample PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86/libswresample.so ) set_target_properties( swscale PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86/libswscale.so ) set_target_properties( fdk-aac PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86/libfdk-aac.so ) endif(${ANDROID_ABI} STREQUAL "x86") if(${ANDROID_ABI} STREQUAL "x86_64") set_target_properties( avcodec PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86_64/libavcodec.so ) set_target_properties( avfilter PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86_64/libavfilter.so ) set_target_properties( avformat PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86_64/libavformat.so ) set_target_properties( avutil PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86_64/libavutil.so ) set_target_properties( swresample PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86_64/libswresample.so ) set_target_properties( swscale PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86_64/libswscale.so ) set_target_properties( fdk-aac PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/x86_64/libfdk-aac.so ) endif(${ANDROID_ABI} STREQUAL "x86_64") # 我们拷贝进来的几个c文件中需要头文件 为了方便使用这里我们直接指向ffmpeg源代码 include_directories( ../ffmpeg-3.2.5 ) # Searches for a specified prebuilt library and stores the path as a # variable. Because CMake includes system libraries in the search path by # default, you only need to specify the name of the public NDK library # you want to add. CMake verifies that the library exists before # completing its build. find_library( # Sets the name of the path variable. log-lib # Specifies the name of the NDK library that # you want CMake to locate. log ) # Specifies libraries CMake should link to your target library. You # can link multiple libraries, such as libraries you define in this # build script, prebuilt third-party libraries, or system libraries. target_link_libraries( # Specifies the target library. ffmpeg-lib fdk-aac avcodec avfilter avformat avutil swresample swscale # Links the target library to the log library # included in the NDK. ${log-lib} )
8.两个注意点:
1.本文只编译了armeabi-v7a架构的so文件,所以需要在build.gradle中过滤下:
externalNativeBuild { cmake { cppFlags "" } ndk{ abiFilters "armeabi-v7a" } }
2.千万不要忘了加上文件读写权限,不然会报Fatal signal 11 (SIGSEGV), code 1, fault addr 0x18 in tid 9051 (Thread-26083)错误,因为c代码在控制台上只报这一行错误,所以很难找到问题所在,本人也被这个问题坑了很久,最近有时间加上了日志系统才找到问题所在。
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
使用FFmpeg命令
public class MainActivity extends AppCompatActivity { private String mFileBeforeName = "out.mp4"; private String mFileAfterName = "my_girl.mp4"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); FfmpegNativeBridge.setDebug(true);//开启日志系统 Button bt = (Button) findViewById(R.id.bt_text); final ProgressBar pb = (ProgressBar) findViewById(R.id.pb); bt.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { pb.setVisibility(View.VISIBLE); new Thread(new Runnable() { @Override public void run() { String basePath = Environment.getExternalStorageDirectory().getPath(); if (new File(basePath + "/" + mFileBeforeName).exists() && !new File(basePath + "/" + mFileAfterName).exists()) { String cmd_transcoding = String.format( "ffmpeg -i %s -c:v libx264 %s -c:a libfdk_aac %s", basePath + "/" + mFileBeforeName, "-crf 40", basePath + "/" + mFileAfterName); Log.e("命令", cmd_transcoding); int i = FFmpegCMDRun(cmd_transcoding); new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { pb.setVisibility(View.GONE); Toast.makeText(MainActivity.this, "压缩成功了", Toast.LENGTH_SHORT).show(); } }); } else if (new File(basePath + "/" + mFileBeforeName).exists() && new File(basePath + "/" + mFileAfterName).exists()) { pb.post(new Runnable() { @Override public void run() { pb.setVisibility(View.GONE); Toast.makeText(MainActivity.this, "已经压缩成功了", Toast.LENGTH_SHORT).show(); } }); } else { runOnUiThread(new Runnable() { @Override public void run() { pb.setVisibility(View.GONE); Toast.makeText(MainActivity.this, "没找过该视频文件", Toast.LENGTH_SHORT).show(); } }); } } }).start(); } }); } /** * 以空格分割字符串 */ public int FFmpegCMDRun(String cmd) { String regulation = "[ \\t]+"; String[] split = cmd.split(regulation); //执行命令 return FfmpegNativeBridge.RunCommand(split); } }
最后附上源码: Github
相关文章推荐
- 利用FFmpeg玩转Android视频录制与压缩(二)
- android平台通过ndk给ijkplayer的ffmpeg编译libx264
- mac下 ffmpeg 编译到android平台(支持 frei0r)
- win 7下ffmpeg平台和Android联合编译ndk rc7和ffmpeg harmony(最后还是改为r5)
- android ndk编译x264开源(用于android的ffmpeg中进行软编码)
- 深入了解android平台的jni---编译ffmpeg源码
- FFmpeg Android端编译与集成(视频时长剪辑)
- 视频编解码之windows平台下编译ffmpeg的方法和使用教程
- 利用FFmpeg玩转Android视频录制与压缩(三)
- android基于ffmpeg的简单视频播发器 编译ffmpeg
- 用 NDK 编译 ffmpeg 到 Android 平台
- Android平台上使用SDL官方demo播放视频(使用ffmpeg最新版解码)
- FFmpeg Android平台编译与使用
- android平台,视频转码加速思路(FFMPEG)
- Mac环境下编译Android平台的ffmpeg
- FFmpeg视频录制压缩处理走过的坑
- Android 音视频编解码系列(1)--ubuntu下ndk编译ffmpeg0.8.1
- 用NDKr9编译最新ffmpeg2.0.1(ffmpeg2.0.2)到android平台
- 使用FFmpeg4android 实现视频 水印 剪切 压缩 旋转
- android平台源码编译,播放yuv的视频