Android 音视频开发入门(一)
作为资深失业用户,怀念一句话“裸辞一时爽,一直裸辞一直爽”,然后,笔者快要爽死了。好了言归正传,笔者开始带领大家一起学习很多人比较头痛的一个地方,音视频处理。马上 5g 要来了,虽然美国佬和中国闹得很凶,但是肯定不能阻挡科技的进程,所以,大家可以想一想5g到来了,什么东西会火起来呢?想来想去,移动端 音视频肯定会火,你想想,你坐着高铁开着用不完的流量看着 4k 甚至是清晰度更高的视频,什么感觉。所以不用多说,音视频很重要。
万事开头难,音视频处理可能会涉及大量的笔者从没接触的东西,或者读者也从未接触的,但是只要努力肯定没问题的哈。下面我们言归正传哈
一、创建项目
1、外表直观的东西
说到音视频开发,我们肯定要创建一个 c++ 的 Android 项目,不要头大,我们还要撰写 c++ 相关代码哈,各位看官 需要准备 带有 ndk 的 AS。创建工程各位应该都没有问题,然后,我们需要为 这个项目做一些特殊处理,如下:
特殊处理
我们需要为项目添加这两个工具,这样我们的项目就可以顺利运行了。
CMake:项目需要 CMake 进行编译
LLDB: 动态调试C++ 的库
这里比普通的 Android 项目多了 一个 cpp 文件夹里面包含“CMakeLists.txt”和“native-lib.cpp”两个文件这两个文件的作用分别是“引入外部动态库”和“撰写c++”代码
2、深入代码表层的东西
CMakeLists.txt 内生成代码含义
#CMakeLists 的版本
cmake_minimum_required(VERSION 3.4.1)
# 添加动态库的名属性
add_library(
# 添加的动态库名字
native-lib
# 动态库的类型
SHARED
# 指定 cpp 文件所在位置
native-lib.cpp)
# 表示使用系统自带的动态库
target_link_libraries(
native-lib
# 需要系统 log 日志的动态库
log)
native-lib.cpp 文件内的代码含义 : 一个c++ 撰写的方法
#include <jni.h>
#include <string>
extern "C" JNIEXPORT jstring JNICALL
Java_com_hxd_music_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
在项目的module 下 build.gradle 内也增加一些东西分别是:
//添加的一些动态库
externalNativeBuild {
cmake {
cppFlags ""
}
}
// CMakeList 的编译路径
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
version "3.10.2"
}
}
项目的 MainActivity 内也存在差别
public class MainActivity extends AppCompatActivity {
//加载到系统 使用的动态库
static {
System.loadLibrary("native-lib");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = findViewById(R.id.sample_text);
tv.setText(stringFromJNI());
}
//调用 c++ 方法
public native String stringFromJNI();
}
该介绍的都介绍完了,我们来运行一些我们的项目
运行一下项目二、创建新的 library 进行 分包管理
创建一个 library 并将 视频处理相关文件 转移到 library 内 ,类似于组件化开发,文件迁移完成之后 ,library 的 结构如下
文件
library内的 build.gradle 的结构为
android {
compileSdkVersion 28
defaultConfig {
minSdkVersion 21
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ""
}
}
}
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"
}
}
}
三、项目内导入动态库
将我使用的 .so 文件上传到 csdn,连接为:自用 FFmpeg 动态库
1、导入 so 库
在 library 内的 main 文件夹下 建立 jniLibs 文件夹 将 “armeabi” 和 “X86” 的文件加入其中,如图
导入 so 文件
2、导入头文件
在 cpp 文件夹内 导入 “include”文件夹 :自用头文件
3、library 内的 build.gradle 内添加 abi 过滤
externalNativeBuild {
cmake {
cppFlags ""
abiFilters'armeabi','x86'
}
}
4、在 android 的大括号内 添加 sourceSets 配置
sourceSets {
main{
jniLibs.srcDirs("src/main/jniLibs")
}
}
5、在 CMakeLists 内关联头文件路径
#关联 头文件路径
include_directories(src/main/cpp/include)
括号内表示 include 文件夹所在位置
6、设置动态库路径
在 CMakeLists.txt 内配置动态库的路径如下
#CMakeLists 的版本
cmake_minimum_required(VERSION 3.4.1)
#关联 头文件路径
include_directories(src/main/cpp/include)
# 引入自己需的动态库
add_library( avcodec-57 SHARED IMPORTED)
set_target_properties( avcodec-57
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libavcodec-57.so)
add_library( avdevice-57 SHARED IMPORTED)
set_target_properties( avdevice-57
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libavdevice-57.so)
add_library( avfilter-6 SHARED IMPORTED)
set_target_properties( avfilter-6
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libavfilter-6.so)
add_library( avformat-57 SHARED IMPORTED)
set_target_properties( avformat-57
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libavformat-57.so)
add_library( avutil-55 SHARED IMPORTED)
set_target_properties( avutil-55
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libavutil-55.so)
add_library( postproc-54 SHARED IMPORTED)
set_target_properties( postproc-54
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libpostproc-54.so)
add_library( swresample-2 SHARED IMPORTED)
set_target_properties( swresample-2
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libswresample-2.so)
add_library( swscale-4 SHARED IMPORTED)
set_target_properties( swscale-4
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libswscale-4.so)
# 添加动态库的名属性
add_library(
# 添加的动态库名字
native-lib
# 动态库的类型
SHARED
# 指定 cpp 文件所在位置
native-lib.cpp)
# 表示使用系统自带的动态库
target_link_libraries(
native-lib
avcodec-57
avdevice-57
avfilter-6
avformat-57
avutil-55
postproc-54
swresample-2
swscale-4
# 需要系统 log 日志的动态库
log)
//上面表示项目内添加 该动态库
add_library( swscale-4 SHARED IMPORTED)
//下面表示该动态库路径
set_target_properties( swscale-4
PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libswscale-4.so)
7、Java项目内引入动态库
package com.hxd.player;
public class Test {
static {
System.loadLibrary("native-lib");
System.loadLibrary("avcodec-57");
System.loadLibrary("avdevice-57");
System.loadLibrary("avfilter-6");
System.loadLibrary("avformat-57");
System.loadLibrary("avutil-55");
System.loadLibrary("postproc-54");
System.loadLibrary("swresample-2");
System.loadLibrary("swscale-4");
}
public native String stringFromJNI();
}
8、在撰写相关方法 测试动态库是否导入成功
Test.java 文件内撰写
public native void TestFFmpeg ();
native-lib.cpp 内撰写
#include <android/log.h>
extern "C"{
#include "include/libavformat/avformat.h"
#include "include/libavutil/avutil.h"
#include "include/libavcodec/avcodec.h"
}
extern "C"
JNIEXPORT void JNICALL
Java_com_hxd_player_Test_TestFFmpeg(JNIEnv *env, jobject instance) {
//导入头文件
av_register_all();
AVCodec *c_temp = av_codec_next(NULL);
while (c_temp != NULL)
{
switch (c_temp->type)
{
case AVMEDIA_TYPE_VIDEO:
LOGI("[Video]:%s", c_temp->name);
break;
case AVMEDIA_TYPE_AUDIO:
LOGI("[Audio]:%s", c_temp->name);
break;
default:
LOGI("[Other]:%s", c_temp->name);
break;
}
c_temp = c_temp->next;
}
}
9、在library 内和项目的 build.gradle 内进行配置
library 内
defaultConfig {
minSdkVersion 21
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ""
abiFilters"armeabi","x86"
}
}
ndk {
abiFilters"armeabi","x86"
}
}
项目内
defaultConfig {
applicationId "com.hxd.music"
minSdkVersion 21
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
ndk {
abiFilters"armeabi","x86"
}
}
最后 运行项目打印如下日志则表示 引入成功
项目运行成功