之前在博客中提到視頻的裁剪和合并功能,用的是FFmpeg這塊的東西,由于是從網(wǎng)上直接拔過來的東西,雖然功能算是實現(xiàn)了,但是心里總是感覺怪怪的,畢竟沒有自己動手!自己也討厭“伸手主義”,加之最近項目不是特別緊張,就自己動手編譯了一遍,并在各種各樣異常的情況下,總算在Android studio下跑成功了!本來打算把一些知識點再挖深一點,但是最近項目可能要迭代新版本,所以怕是要小忙一陣!為了避免把之前的忘了,所以還是需要草草的記錄一下!下面開始。
準備環(huán)境:
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,所以,我就打算在這個工作區(qū)間直接下載了(說到底是不會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可關(guān)閉命令行
接著打開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)'
在接著創(chuàng)建文件build_android.sh文件,內(nèi)容為:
#!/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 ../
創(chuàng)建的這個文件需要注意的是,你自己需要修改一些東西:
圈出的這三處需要改成你自己的路徑。
小提示:你最好先打開自己的命令行cd一下,看看能不能到這些文件路徑下面,不然會一直報文件找不到的警告
接著給build_android.sh添加執(zhí)行權(quán)限命令行如下:
$chmod+x build_android.sh
接著執(zhí)行.sh文件:
$./build_android.sh
ok ,到這里,如果的你的配置都沒有問題的話,已經(jīng)開始生成.so文件了!
當你再打開ffmpeg的文件夾的時候多了一個文件夾 arm!
接著把arm文件夾copy出來之后開始在Android studio中測試一下咯!
在創(chuàng)建新的Android項目的的時候在,首頁面需勾選:
接著一路next知道創(chuàng)建完成新的項目!
創(chuàng)建好新的項目,將之前的生成的arm包中的東西復制到工程下的libs文件夾下:
注意:現(xiàn)在是arm架構(gòu)類型的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的寫法,你的函數(shù)名稱可能跟我的不太一樣哦!
接著配置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的文件配置:
這兩個千萬別忘了,不然就跑不起來了!
哈哈,到這基本就完了!
這是跑出來的結(jié)果圖:
文章參考:
http://blog.csdn.net/gobitan/article/details/22750719
http://blog.csdn.net/eastmoon502136/article/details/52806640
感謝作者的無私技術(shù)分享!
如有問題請指正,共同進步,謝謝!
每天進步一點點,時間會讓你成為巨人!加油!