【Android RTMP】音频数据采集编码 ( FAAC 头文件与静态库拷贝到 AS | CMakeList.txt 配置 FAAC | AudioRecord 音频采样 PCM 格式 )
文章目录
- 一、 FAAC 头文件与静态库拷贝到 Android Studio
- 二、 CMakeList.txt 构建脚本配置
- 三、 Java 层 AudioRecord 音频采样 PCM 格式
- 四、 Java 层 AudioRecord 音频采样 PCM 格式代码示例
一、 FAAC 头文件与静态库拷贝到 Android Studio
将 PCM 音频采样编码成 AAC 格式 , 需要使用 FAAC编码器 , 在上一篇博客 【Android RTMP】音频数据采集编码 ( 音频数据采集编码 | AAC 高级音频编码 | FAAC 编码器 | Ubuntu 交叉编译 FAAC 编码器 ) 中完成了对 FAAC 音频编码器的交叉编译 , 交叉编译结果如下 :
root@octopus:~/rtmp/faac-1.29.9.2/android# tree
.
└── armeabi-v7a
├── bin
│ └── faac
├── include
│ ├── faaccfg.h
│ └── faac.h
├── lib
│ ├── libfaac.a
│ └── libfaac.la
└── share
└── man
└── man1
└── faac.1
将
个头文件 faaccfg.h , faac.h 拷贝到 Android Studio 项目中的 src/main/cpp/include 目录中 , 将 libfaac.a 静态库拷贝到 src/main/cpp/libs/armeabi-v7a 目录中 ;
二、 CMakeList.txt 构建脚本配置
将头文件与函数库拷贝到 Android Studio 项目中后 , 配置 CMakeList.txt 构建脚本 , 主要配置头文件与函数库的搜索路径 , 让编译工具可以找到对应的 FAAC 库的头文件与静态库 ;
1 . 设置头文件搜索路径 :
# 设置头文件搜索路径
include_directories(include)
2 . 设置函数库搜索路径 :
# 通过设置编译选项, 设置函数库的搜索路径
# 此处的 ANDROID_ABI 是在
# build.gradle android->defaultConfig->externalNativeBuild->cmake
# 下的 abiFilters 中设置
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}")
3 . 完整的 CMakeList.txt 文件 :
cmake_minimum_required(VERSION 3.4.1)
# 链接 src/main/cpp/librtmp 目录下的构建脚本
add_subdirectory(librtmp)
add_library( # 函数库名称
native-lib
# 动态库类型
SHARED
# 源文件
native-lib.cpp
VedioChannel.cpp)
find_library( # 日志库
log-lib
log )
# 设置头文件搜索路径
include_directories(include)
# 通过设置编译选项, 设置函数库的搜索路径
# 此处的 ANDROID_ABI 是在
# build.gradle android->defaultConfig->externalNativeBuild->cmake
# 下的 abiFilters 中设置
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}")
target_link_libraries( # 链接动态库
native-lib
# 编译的 rtmp 静态库
rtmp
# 查找到的 x264 静态库
x264
# 查找到的 faac 静态库
faac
${log-lib} )
三、 Java 层 AudioRecord 音频采样 PCM 格式
1 . 初始化 AudioRecord :
① 计算最小缓冲区大小 : 获取 44100 立体声 / 单声道 16 位采样率的最小缓冲区大小 , 使用最小缓冲区大小, 不能保证声音流畅平滑, 这里将缓冲区大小翻倍, 保证采集数据的流畅 , 否则会有电流产生
int minBufferSize = AudioRecord.getMinBufferSize(44100,
AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT) * 2;
② 创建 AudioRecord 对象 : AudioRecord 构造函数需要传入 音频来源 , 采样率 , 声道配置 , 采样位数 , 采样缓冲区大小 信息 ;
AudioRecord mAudioRecord = new AudioRecord(
MediaRecorder.AudioSource.MIC, // 声音来源 麦克风
44100, // PCM 音频采样率 44100 Hz
AudioFormat.CHANNEL_IN_STEREO, // 立体声
AudioFormat.ENCODING_PCM_16BIT, // 采样位数 16 位
minBufferSize); // 最小采样缓冲区个数
③ AudioRecord 构造函数原型 :
public AudioRecord(int audioSource, int sampleRateInHz, int channelConfig, int audioFormat,
int bufferSizeInBytes)
① int audioSource 参数 : 声音来源, 麦克风 ;
② int sampleRateInHz 参数 : 音频采样率, 一般是 44100 Hz, 该采样率在所有设备支持比较好 ;
③ int channelConfig 参数 : 单声道 AudioFormat.CHANNEL_IN_MONO / 立体声 AudioFormat.CHANNEL_IN_STEREO ;
④ int audioFormat 参数 : 采样位数, 8 位 AudioFormat.ENCODING_PCM_8BIT / 16 , AudioFormat.ENCODING_PCM_16BIT ;
⑤ int bufferSizeInBytes 参数 : 每次采集数据的最大缓冲区大小 ;
2 . PCM 音频采样线程 :
① 独立线程封装 : 音频采样需要持续进行操作 , 并且该操作非常耗时 , 肯定要封装在一个独立线程中完成 ;
② 开始采样 : 调用 AudioRecord 对象的 startRecording 方法 , 开始进行音频采样 ;
mAudioRecord.startRecording();
③ 读取数据 : 循环读取麦克风采样数据 , 调用 AudioRecord 对象的 read 方法 , 可以获取麦克风采样的数据 ;
④ 停止采样 : 调用 AudioRecord 对象的 stop 方法 , 可以停止采样 ;
mAudioRecord.stop();
⑤ 代码示例 :
/**
* 音频采样线程
*/
class AudioSampling implements Runnable{
@Override
public void run() {
// 开始录音采样
mAudioRecord.startRecording();
while (isStartPush){
// 循环读取录音, 需要传入一系列参数
//mAudioRecord.read( ... );
}
// 停止录音采样
mAudioRecord.stop();
}
}
四、 Java 层 AudioRecord 音频采样 PCM 格式代码示例
package kim.hsl.rtmp;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 音频处理类
* 音频采样, 编码, 推流控制
*/
public class AudioChannel {
/**
* 直播推流器
*/
private LivePusher mLivePusher;
/**
* 音频录制对象
*/
private AudioRecord mAudioRecord;
/**
* 是否已经开始推流
*/
private boolean isStartPush;
/**
* 单线程线程池, 在该线程中进行音频采样
*/
private ExecutorService mExecutorService;
public AudioChannel(LivePusher mLivePusher) {
this.mLivePusher = mLivePusher;
// 初始化线程池, 单线程线程池
mExecutorService = Executors.newSingleThreadExecutor();
/*
获取 44100 立体声 / 单声道 16 位采样率的最小缓冲区大小
使用最小缓冲区大小, 不能保证声音流畅平滑, 这里将缓冲区大小翻倍, 保证采集数据的流畅
否则会有电流产生
*/
int minBufferSize = AudioRecord.getMinBufferSize(44100,
AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT) * 2;
/*
public AudioRecord(int audioSource, int sampleRateInHz,
int channelConfig, int audioFormat,
int bufferSizeInBytes)
int audioSource 参数 : 声音来源, 麦克风
int sampleRateInHz 参数 : 音频采样率, 一般是 44100 Hz, 该采样率在所有设备支持比较好
int channelConfig 参数 : 单声道 AudioFormat.CHANNEL_IN_MONO / 立体声 AudioFormat.CHANNEL_IN_STEREO,
int audioFormat 参数 : 采样位数, 8 位 AudioFormat.ENCODING_PCM_8BIT / 16 位 AudioFormat.ENCODING_PCM_16BIT
int bufferSizeInBytes 参数 : 每次采集数据的最大缓冲区大小
*/
mAudioRecord = new AudioRecord(
MediaRecorder.AudioSource.MIC, // 声音来源 麦克风
44100, // PCM 音频采样率 44100 Hz
AudioFormat.CHANNEL_IN_STEREO, // 立体声
AudioFormat.ENCODING_PCM_16BIT, // 采样位数 16 位
minBufferSize); // 最小采样缓冲区个数
}
/**
* 开始推流
*/
public void startLive() {
isStartPush = true;
// 执行音频采样线程
// 如果在启动一个线程, 后续线程就会排队等待
mExecutorService.submit(new AudioSampling());
}
/**
* 停止推流
*/
public void stopLive() {
isStartPush = false;
}
public void release(){
//释放音频录音对象
mAudioRecord.release();
}
/**
* 音频采样线程
*/
class AudioSampling implements Runnable{
@Override
public void run() {
// 开始录音采样
mAudioRecord.startRecording();
while (isStartPush){
// 循环读取录音
mAudioRecord.read();
}
// 停止录音采样
mAudioRecord.stop();
}
}
}
相关文章
- android 验证码短信验证码,Android短信验证码倒计时验证的2种常用方式
- android短信验证码方案,Android开发之属于你的短信验证码(一)
- Android界面布局属性layout_gravity和gravity的区别
- android telephony 原理解析与开发指南_Android逆向pdf
- Android 编译_android线程
- Android Services Library_android freeware
- android 系统浏览器 源码-Android 最最最简单的浏览器代码
- 浅谈 Android 的安全启动和完整性保护
- 【Android 应用开发】Android 图表绘制 achartengine 示例解析
- 【Android 异步操作】手写 Handler ( Message 消息 | ThreadLocal 线程本地变量 | Looper 中的消息队列 MessageQueue )
- 【Android Gradle 插件】Module 目录下 build.gradle 配置文件 ( android 闭包块配置 | AppExtension 扩展类型参考文档 )
- 【错误记录】编译 Android 版本的 ijkplayer 报错 ( You must define ANDROID_NDK before starting. | 下载指定版本 NDK )
- 【Android Gradle 插件】Gradle 依赖管理 ② ( build.gradle 中的 dependencies 依赖配置 | DependencyHandler#add 方法介绍 )
- 【Android Gradle 插件】Gradle 基础配置 ② ( Gradle 空白项目构建示例演示 )
- 【Android Gradle 插件】Gradle 基础配置 ⑤ ( gradle-wrapper.properties 配置分析 | GRADLE_USER_HOME 目录 )
- 【Android Gradle 插件】Android 依赖管理 ② ( 为工程配置依赖仓库 | 为工程构建添加依赖仓库 | classpath 引入依赖库 | 配置依赖仓库 )
- Android SlidingMenu 侧拉菜单的使用(详细配置)详解手机开发
- 史上最大设计变化:Android 12让你眼前一亮
- 安卓编年史(7):Android 1.1——第一个真正的增量更新