之前在博客中提到视频的裁剪和合并功能,用的是FFmpeg这块的东西,由于是从网上直接拔过来的东西,虽然功能算是实现了,但是心里总是感觉怪怪的,毕竟没有自己动手!自己也讨厌“伸手主义”,加之最近项目不是特别紧张,就自己动手编译了一遍,并在各种各样异常的情况下,总算在Android studio下跑成功了!本来打算把一些知识点再挖深一点,但是最近项目可能要迭代新版本,所以怕是要小忙一阵!为了避免把之前的忘了,所以还是需要草草的记录一下!下面开始。
准备环境:
VMware workstation 12 player
最新版下载地址:
https://my.vmware.com/cn/web/vmware/free#desktop_end_user_computing/vmware_workstation_player/12_0
Ubuntu 64(我存一份到我的云盘中了,大家可以到那下载)
下载地址:
http://pan.baidu.com/s/1bp8JG2j
安装完后打开界面如下:
OK,到这,就可以开始准备工作了!
由于之前家里的电脑也没下载NDK和FFmpeg,所以,我就打算在这个工作区间直接下载了(说到底是不会VMware的共享文件(大家可以自行谷歌或者百度,有解))
最新版的NDK下载地址:
https://dl.google.com/android/repository/android-ndk-r15b-linux-x86_64.zip
最新版的FFmpeg下载地址:
http://ffmpeg.org/releases/ffmpeg-3.3.2.tar.bz2
下载完之后,就可以开始编译了!
这里,我把两个压缩包全都放在home路径下了!
点击左键Extract File,进行解压文件夹(或者用命令行进行解压,都OK)
Ctrl+Alt+F2可打开命令行
Ctrl+Alt+F7可关闭命令行
接着打开FFmpeg的文件夹,打开configure文件,修改该属性为:
SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'
在接着创建文件build_android.sh文件,内容为:
#!/bin/bash
cd ffmpeg
export TMPDIR=/home/tianchuangxin/ffmpeg-3.3.2
NDK=/home/tianchuangxin/android-ndk-r15b
SYSROOT=$NDK/platforms/android-16/arch-arm/
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
CPU=arm
PREFIX=/home/tianchuangxin/ffmpeg-3.3.2/$CPU
ADDI_CFLAGS="-marm"
function build_one
{
./configure \
--prefix=$PREFIX \
--enable-shared \
--disable-static \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--disable-doc \
--disable-symver \
--enable-small \
--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" \
$ADDITIONAL_CONFIGURE_FLAG
make clean
make
make install
}
build_one
cd ../
创建的这个文件需要注意的是,你自己需要修改一些东西:
圈出的这三处需要改成你自己的路径。
小提示:你最好先打开自己的命令行cd一下,看看能不能到这些文件路径下面,不然会一直报文件找不到的警告
接着给build_android.sh添加执行权限命令行如下:
$chmod+x build_android.sh
接着执行.sh文件:
$./build_android.sh
ok ,到这里,如果的你的配置都没有问题的话,已经开始生成.so文件了!
当你再打开ffmpeg的文件夹的时候多了一个文件夹 arm!
接着把arm文件夹copy出来之后开始在Android studio中测试一下咯!
在创建新的Android项目的的时候在,首页面需勾选:
接着一路next知道创建完成新的项目!
创建好新的项目,将之前的生成的arm包中的东西复制到工程下的libs文件夹下:
注意:现在是arm架构类型的CPU
接着开始配置native_lib.cpp文件,它在main目录下
#include <jni.h>
#include <string>
extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavfilter/avfilter.h>
JNIEXPORT jstring JNICALL
Java_com_example_ffmpegtest_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
JNIEXPORT jstring JNICALL
Java_com_example_ffmpegtest_MainActivity_urlprotocolinfo(
JNIEnv *env, jobject) {
char info[40000] = {0};
av_register_all();
struct URLProtocol *pup = NULL;
struct URLProtocol **p_temp = &pup;
avio_enum_protocols((void **) p_temp, 0);
while ((*p_temp) != NULL) {
sprintf(info, "%sInput: %s\n", info, avio_enum_protocols((void **) p_temp, 0));
}
pup = NULL;
avio_enum_protocols((void **) p_temp, 1);
while ((*p_temp) != NULL) {
sprintf(info, "%sInput: %s\n", info, avio_enum_protocols((void **) p_temp, 1));
}
return env->NewStringUTF(info);
}
JNIEXPORT jstring JNICALL
Java_com_example_ffmpegtest_MainActivity_avformatinfo(
JNIEnv *env, jobject) {
char info[40000] = {0};
av_register_all();
AVInputFormat *if_temp = av_iformat_next(NULL);
AVOutputFormat *of_temp = av_oformat_next(NULL);
while (if_temp != NULL) {
sprintf(info, "%sInput: %s\n", info, if_temp->name);
if_temp = if_temp->next;
}
while (of_temp != NULL) {
sprintf(info, "%sOutput: %s\n", info, of_temp->name);
of_temp = of_temp->next;
}
return env->NewStringUTF(info);
}
JNIEXPORT jstring JNICALL
Java_com_example_ffmpegtest_MainActivity_avcodecinfo(
JNIEnv *env, jobject) {
char info[40000] = {0};
av_register_all();
AVCodec *c_temp = av_codec_next(NULL);
while (c_temp != NULL) {
if (c_temp->decode != NULL) {
sprintf(info, "%sdecode:", info);
} else {
sprintf(info, "%sencode:", info);
}
switch (c_temp->type) {
case AVMEDIA_TYPE_VIDEO:
sprintf(info, "%s(video):", info);
break;
case AVMEDIA_TYPE_AUDIO:
sprintf(info, "%s(audio):", info);
break;
default:
sprintf(info, "%s(other):", info);
break;
}
sprintf(info, "%s[%10s]\n", info, c_temp->name);
c_temp = c_temp->next;
}
return env->NewStringUTF(info);
}
JNIEXPORT jstring JNICALL
Java_com_example_ffmpegtest_MainActivity_avfilterinfo(
JNIEnv *env, jobject) {
char info[40000] = {0};
avfilter_register_all();
AVFilter *f_temp = (AVFilter *)avfilter_next(NULL);
while(f_temp != NULL) {
sprintf(info, "%s%s\n", info, f_temp->name);
f_temp = f_temp->next;
}
return env->NewStringUTF(info);
}
}
注意的是native的写法,你的函数名称可能跟我的不太一样哦!
接着配置CMakeLists.txt文件:
# Sets the minimum version of CMake required to build the native
# library. You should either keep the default value or only pass a
# value of 3.4.0 or lower.
cmake_minimum_required(VERSION 3.4.1)
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 )
set(distribution_DIR ${CMAKE_SOURCE_DIR}/../../../../libs)
add_library( avutil-55
SHARED
IMPORTED )
set_target_properties( avutil-55
PROPERTIES IMPORTED_LOCATION
../../../../libs/armeabi-v7a/libavutil-55.so )
add_library( swresample-2
SHARED
IMPORTED )
set_target_properties( swresample-2
PROPERTIES IMPORTED_LOCATION
../../../../libs/armeabi-v7a/libswresample-2.so )
add_library( avcodec-57
SHARED
IMPORTED )
set_target_properties( avcodec-57
PROPERTIES IMPORTED_LOCATION
../../../../libs/armeabi-v7a/libavcodec-57.so )
add_library( avfilter-6
SHARED
IMPORTED)
set_target_properties( avfilter-6
PROPERTIES IMPORTED_LOCATION
../../../../libs/armeabi-v7a/libavfilter-6.so )
add_library( swscale-4
SHARED
IMPORTED)
set_target_properties( swscale-4
PROPERTIES IMPORTED_LOCATION
../../../../libs/armeabi-v7a/libswscale-4.so )
add_library( avdevice-57
SHARED
IMPORTED)
set_target_properties( avdevice-57
PROPERTIES IMPORTED_LOCATION
../../../../libs/armeabi-v7a/libavdevice-57.so )
add_library( avformat-57
SHARED
IMPORTED)
set_target_properties( avformat-57
PROPERTIES IMPORTED_LOCATION
../../../../libs/armeabi-v7a/libavformat-57.so )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
add_library( native-lib
SHARED
src/main/cpp/native-lib.cpp )
include_directories(libs/include)
#target_include_directories(native-lib PRIVATE libs/include)
target_link_libraries( native-lib swresample-2 avcodec-57 avfilter-6 swscale-4 avdevice-57 avformat-57
${log-lib} )
接着是build.gradle的文件配置:
这两个千万别忘了,不然就跑不起来了!
哈哈,到这基本就完了!
这是跑出来的结果图:
文章参考:
http://blog.csdn.net/gobitan/article/details/22750719
http://blog.csdn.net/eastmoon502136/article/details/52806640
感谢作者的无私技术分享!
如有问题请指正,共同进步,谢谢!
每天进步一点点,时间会让你成为巨人!加油!