【Android RTMP】音频数据采集编码 ( FAAC 音频编码参数设置 | FAAC 编码器创建 | 获取编码器参数 | 设置 AAC 编码规格 | 设置编码器输入输出参数 )

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 【Android RTMP】音频数据采集编码 ( FAAC 音频编码参数设置 | FAAC 编码器创建 | 获取编码器参数 | 设置 AAC 编码规格 | 设置编码器输入输出参数 )

文章目录

一、 头文件、成员变量准备

二、 创建 FAAC 编码器

三、 获取并设置 FAAC 编码器参数

四、 设置 FAAC 编码器编码标准

五、 设置 FAAC 编码器 AAC 编码规格

六、 设置 FAAC 编码器输入、输出格式

七、 FAAC 设置音频编码参数代码



Android 直播推流流程 : 手机采集视频 / 音频数据 , 视频数据使用 H.264 编码 , 音频数据使用 AAC 编码 , 最后将音视频数据都打包到 RTMP 数据包中 , 使用 RTMP 协议上传到 RTMP 服务器中 ;



视频推流 : 之前的一系列博客中完成手机端采集视频数据操作 , 并将视频数据传递给 JNI , 在 NDK 中使用 x264 将图像转为 H.264 格式的视频 , 最后将 H.264 格式的视频打包到 RTMP 数据包中 , 上传到 RTMP 服务器中 ;



音频推流 : 开始进行音频直播推流操作 , 先采集音频 , 将音频编码为 AAC 格式 , 将编码后的音频打包成 RTMP 包 , 然后推流到服务器中 ;



NV21 格式图像编码为 H.264 视频 , 需要设置 x264 编码器参数 , 对应 【Android RTMP】x264 编码器初始化及设置 ( 获取 x264 编码参数 | 编码规格 | 码率 | 帧率 | B帧个数 | 关键帧间隔 | 关键帧解码数据 SPS PPS ) 博客 ;



本博客中讲解的是 , PCM 音频采样编码为 AAC 音频 , 如何设置 FACC 编码器参数 ;






一、 头文件、成员变量准备


1 . 导入包 : 使用 FACC 编码器前 , 必须导入 facc.h 头文件 ;


#include <faac.h>




2 . 成员变量定义 : 在初始化 FACC 编码器时 , 需要预先定义一些成员变量 , 这些变量在后续设置编码器参数 , 音频编码时都需要使用到 ;



① 输入样本个数 : 输入到 FAAC 编码器中的需要进行编码的 PCM 样本个数 , 表示FAAC 编码器最多一次可以接收的样本个数 ,


unsigned long mInputSamples;


注意 : 是样本个数 , 不是字节数 , 如果采样位数是 8 88 位 , 那么 字 节 数 = 样 本 个 数 字节数 = 样本个数字节数=样本个数 , 如果采样位数是 16 1616 位 , 字 节 数 = 样 本 个 数 × 2 字节数 = 样本个数 \times 2字节数=样本个数×2 ;



② FAAC 编码器最大输出字节数 : 该参数 mMaxOutputBytes 与上面的 mInputSamples 都要传入 FAAC 编码器创建函数中 , 用于接收创建 FAAC 编码器后的返回值 , 创建之前这些值是不知道的 ;


unsigned long mMaxOutputBytes;


③ FAAC 编码器 : 用于将 PCM 音频采样编码成 AAC 格式 ;


faacEncHandle mFaacEncHandle;


④ FAAC 编码输出缓冲区 : FAAC 编码后的 AAC 裸数据, 存储到该缓冲区中 , 该缓冲区在初始化 FAAC 编码器时创建 ; 初始化完成后 , 知道 FAAC 最大输出缓冲区大小后 , 创建该输出缓冲区 , 其大小是 mMaxOutputBytes 字节 ;


unsigned char* mFaacEncodeOutputBuffer;





二、 创建 FAAC 编码器


1 . 调用 faacEncOpen 函数 , 创建 FAAC 编码器 ;



2 . 函数原型解析 :


faacEncHandle FAACAPI faacEncOpen(unsigned long sampleRate,
      unsigned int numChannels,
      unsigned long *inputSamples,
                                  unsigned long *maxOutputBytes
                                 );


① unsigned long sampleRate 参数 : 音频采样率 ;


② unsigned int numChannels 参数 : 音频通道参数 ;


③ unsigned long *mInputSamples 参数 : 输入样本个数, 需要进行编码的 PCM 音频样本个数 , FAAC 编码器最多一次可以接收的样本个数 ;


④ unsigned long *mMaxOutputBytes 参数 : 输出数据最大字节数 ;


⑤ faacEncHandle 返回值 : FAAC 音频编码器 ;



3 . 创建 FAAC 编码器 代码示例 :


mFaacEncHandle = faacEncOpen(sampleRateInHz, channelConfig, &mInputSamples, &mMaxOutputBytes);






三、 获取并设置 FAAC 编码器参数


1 . 获取编码器参数 : 先获取参数, 然后设置参数, 最后再设置回去


faacEncConfigurationPtr configurationPtr = faacEncGetCurrentConfiguration(mFaacEncHandle);



2 . 设置编码器参数 : 为 mFaacEncHandle 音频编码器设置 configurationPtr 编码器参数


faacEncSetConfiguration(mFaacEncHandle, configurationPtr);


先获取 FAAC 编码器参数 faacEncConfigurationPtr 结构体 , 然后设置编码器参数 , 最后再将编码器参数 设置回 FAAC 编码器 FaacEncHandle ;






四、 设置 FAAC 编码器编码标准


设置 FAAC 编码器编码标准 : 可以设置 MPEG2 , 或 MPEG4 , 目前一般设置 MPEG4 标准 ;


// 设置编码格式标准, 使用 MPEG4 新标准
configurationPtr->mpegVersion = MPEG4;






五、 设置 FAAC 编码器 AAC 编码规格


1 . AAC 编码规格 : 9 99 种 ;


MPEG-2 AAC LC低复杂度规格(Low Complexity)

MPEG-2 AAC Main主规格

MPEG-2 AAC SSR可变采样率规格(Scaleable Sample Rate)

MPEG-4 AAC LC低复杂度规格(Low Complexity)

MPEG-4 AAC Main主规格, MPEG-4 AAC SSR可变采样率规格(Scaleable Sample Rate)

MPEG-4 AAC LTP长时期预测规格(Long Term Predicition)

MPEG-4 AAC LD低延迟规格(Low Delay)

MPEG-4 AAC HE高效率规格(High Efficiency)


2 . 这里选择低复杂度规格 : MPEG-4 AAC LC低复杂度规格(Low Complexity) 是最常用的 AAC 编码规格, 即兼顾了编码效率, 有保证了音质;


( 使用更高音质, 极大降低编码效率, 音质提升效果有限 ; 再提升编码效率, 会使音质降低很多 )


configurationPtr->aacObjectType = LOW;





六、 设置 FAAC 编码器输入、输出格式


1 . 设置编码器的输入格式 : 这里设置输入的 PCM 的采样位数是 16 1616 位 ;


configurationPtr->inputFormat = FAAC_INPUT_16BIT;


2 . 设置编码器的输出格式 : 这里设置输出格式 0, 就是 FAAC 将 PCM 采样进行编码, 编码出的格式是 AAC 原始数据 , 即没有解码信息的 ADIF 和 ADTS 的 AAC 纯样本裸数据 ;


configurationPtr->outputFormat = 0;


参考 【Android RTMP】音频数据采集编码 ( AAC 音频格式解析 | FLV 音频数据标签解析 | AAC 音频数据标签头 | 音频解码配置信息 ) 博客的 AAC 格式音频解析 , AAC 有两种格式 :


音频数据交换格式 ( Audio Data Interchange Format )

音频数据传输流格式 ( Audio Data Transport Stream )

此处使用的不是上述两种格式的任意一种 , 而是 AAC 的纯样本裸数据 ;






七、 FAAC 设置音频编码参数代码


1 . 成员变量定义代码 :


/**
     * 输入样本个数, 需要进行编码的 PCM 音频样本个数
     * FAAC 编码器最多一次可以接收的样本个数
     * 传递下面两个数值的地址到 faacEncOpen 函数中, 用于当做返回值使用
     *
     * 该数据需要返回给 Java 层
     * Java 层每次从 AudioRecord 中读取 mInputSamples 个数据
     */
    unsigned long mInputSamples;
    /**
     * FAAC 编码器最多一次可以接收的样本个数
     * 传递下面两个数值的地址到 faacEncOpen 函数中, 用于当做返回值使用
     */
    unsigned long mMaxOutputBytes;
    /**
     * PCM 音频 FAAC 编码器
     * 将 PCM 采样数据编码成 FAAC 编码器
     */
    faacEncHandle mFaacEncHandle;
    /**
     * FAAC 编码输出缓冲区
     * FAAC 编码后的 AAC 裸数据, 存储到该缓冲区中
     * 该缓冲区在初始化 FAAC 编码器时创建
     */
    unsigned char* mFaacEncodeOutputBuffer;



2 . FACC 编码器参数初始化代码 :


/**
 * 设置音频编码参数
 * @param sampleRateInHz    音频采样率
 * @param channelConfig     音频采样通道, 单声道 / 立体声
 */
void AudioChannel::setAudioEncoderParameters(int sampleRateInHz, int channelConfig) {
    // 设置音频通道参数, 单声道 / 立体声
    mChannelConfig = channelConfig;
    /*
        打开编码器
        faacEncHandle FAACAPI faacEncOpen(unsigned long sampleRate,
      unsigned int numChannels,
      unsigned long *mInputSamples,
                  unsigned long *mMaxOutputBytes);
        unsigned long sampleRate 参数 : 音频采样率
        unsigned int numChannels 参数 : 音频通道参数
        unsigned long *mInputSamples 参数 : 输入样本个数, 需要进行编码的 PCM 音频样本个数
            FAAC 编码器最多一次可以接收的样本个数
        unsigned long *mMaxOutputBytes 参数 : 输出数据最大字节数
        faacEncHandle 返回值 : FAAC 音频编码器
        注意上述 样本个数, 字节个数 区别 : 16 位采样位数, 一个样本有 2 字节
     */
    mFaacEncHandle = faacEncOpen(sampleRateInHz, channelConfig, &mInputSamples, &mMaxOutputBytes);
    // 获取编码器当前参数
    // 先获取参数, 然后设置参数, 最后再设置回去
    faacEncConfigurationPtr configurationPtr = faacEncGetCurrentConfiguration(mFaacEncHandle);
    // 设置编码格式标准, 使用 MPEG4 新标准
    configurationPtr->mpegVersion = MPEG4;
    /*
        设置 AAC 编码规格, 有 9 种
        MPEG-2 AAC LC低复杂度规格(Low Complexity), MPEG-2 AAC Main主规格, MPEG-2 AAC SSR可变采样率规格(Scaleable Sample Rate)
        MPEG-4 AAC LC低复杂度规格(Low Complexity), MPEG-4 AAC Main主规格, MPEG-4 AAC SSR可变采样率规格(Scaleable Sample Rate)
        MPEG-4 AAC LTP长时期预测规格(Long Term Predicition), MPEG-4 AAC LD低延迟规格(Low Delay), MPEG-4 AAC HE高效率规格(High Efficiency)
        这里选择低复杂度规格, 可选参数有 4 种
        MPEG-4 AAC LC低复杂度规格(Low Complexity) 是最常用的 AAC 编码规格, 即兼顾了编码效率, 有保证了音质;
        使用更高音质, 极大降低编码效率, 音质提升效果有限
        再提升编码效率, 会使音质降低很多
     */
    configurationPtr->aacObjectType = LOW;
    // 采样位数 16 位
    configurationPtr->inputFormat = FAAC_INPUT_16BIT;
    /*
        AAC 音频文件有两种格式 ADIF 和 ADTS
        AAC 文件解码时 : 音频解码信息定义在头部, 后续音频数据解码按照音频数据长度
        音频数据交换格式 ( Audio Data Interchange Format ) , 只有一份音频解码信息 , 存储在文件开头
        这种格式适合存储音频文件 , 节省空间 , 但是必须从开始播放才可以 , 从中间位置无法播放 ;
        音频数据传输流格式 ( Audio Data Transport Stream ) , 每隔一段音频数据
        就会有一份音频解码信息 , 这种格式适合音频流传输 , 可以在任何位置开始解码播放 ;
        RTMP 推流时, 不使用上述两种格式
        推流视频时, 先将 SPS, PPS 解码数据包的信息推流到服务器上
        推流音频时, 也是将解码相关的数据先推流到服务器中
        AAC 编码时, 会编码成 ADTS 数据
        但是推流音频时, 推流的是 AAC 裸数据, 需要将 ADTS 音频格式中的头信息去掉
        博客中截图 FLV 第一帧 AAC 音频数据标签 和 后续 AAC 音频数据标签
        这里设置输出格式 0, 就是 FAAC 将 PCM 采样进行编码, 编码出的格式是 AAC 原始数据
        即没有解码信息的 ADIF 和 ADTS 的 AAC 纯样本裸数据
     */
    configurationPtr->outputFormat = 0;
    // 为 mFaacEncHandle 音频编码器设置 configurationPtr 编码器参数
    faacEncSetConfiguration(mFaacEncHandle, configurationPtr);
    // 初始化输出缓冲区, 保存 FAAC 编码输出数据
    mFaacEncodeOutputBuffer = new unsigned char[mMaxOutputBytes];
}



目录
相关文章
|
3月前
|
存储 缓存 Android开发
安卓Jetpack Compose+Kotlin, 使用ExoPlayer播放多个【远程url】音频,搭配Okhttp库进行下载和缓存,播放完随机播放下一首
这是一个Kotlin项目,使用Jetpack Compose和ExoPlayer框架开发Android应用,功能是播放远程URL音频列表。应用会检查本地缓存,如果文件存在且大小与远程文件一致则使用缓存,否则下载文件并播放。播放完成后或遇到异常,会随机播放下一首音频,并在播放前随机设置播放速度(0.9到1.2倍速)。代码包括ViewModel,负责音频管理和播放逻辑,以及UI层,包含播放和停止按钮。
|
6天前
|
XML IDE 开发工具
🔧Android Studio高级技巧大公开!效率翻倍,编码不再枯燥无味!🛠️
【9月更文挑战第11天】在软件开发领域,Android Studio凭借其强大的功能成为Android开发者的首选IDE。本文将揭示一些提升开发效率的高级技巧,包括自定义代码模板、重构工具、高级调试技巧及多模块架构。通过对比传统方法,这些技巧不仅能简化编码流程,还能显著提高生产力。例如,自定义模板可一键插入常用代码块;重构工具能智能分析并安全执行代码更改;高级调试技巧如条件断点有助于快速定位问题;多模块架构则提升了大型项目的可维护性和团队协作效率。掌握这些技巧,将使你的开发之旅更加高效与愉悦。
19 5
|
20天前
|
Java Android开发 芯片
使用Android Studio导入Android源码:基于全志H713 AOSP,方便解决编译、编码问题
本文介绍了如何将基于全志H713芯片的AOSP Android源码导入Android Studio以解决编译和编码问题,通过操作步骤的详细说明,展示了在Android Studio中利用代码提示和补全功能快速定位并修复编译错误的方法。
31 0
使用Android Studio导入Android源码:基于全志H713 AOSP,方便解决编译、编码问题
|
2月前
|
XML IDE 开发工具
🔧Android Studio高级技巧大公开!效率翻倍,编码不再枯燥无味!🛠️
【7月更文挑战第28天】在软件开发领域, Android Studio作为首选IDE, 其高级技巧能显著提升开发效率与乐趣。掌握这些技巧, 让开发旅程更高效有趣!
35 2
|
Android开发 iOS开发 C++
Flutter中设置Android的应用名称和图标(android,ios,web)
在前面的几期给大家介绍了flutter的安装以及一些简单的配置,还运行了helloword 那么接下来就带领大家了解如何设置应用名称以及图标
272 0
|
2天前
|
Android开发 开发者 Kotlin
探索安卓开发中的新特性
【9月更文挑战第14天】本文将引导你深入理解安卓开发领域的一些最新特性,并为你提供实用的代码示例。无论你是初学者还是经验丰富的开发者,这篇文章都会给你带来新的启示和灵感。让我们一起探索吧!
|
6天前
|
IDE 开发工具 Android开发
安卓与iOS开发对比:平台选择对项目成功的影响
【9月更文挑战第10天】在移动应用开发的世界中,选择正确的平台是至关重要的。本文将深入探讨安卓和iOS这两大主要移动操作系统的开发环境,通过比较它们的市场份额、开发工具、编程语言和用户群体等方面,为开发者提供一个清晰的指南。我们将分析这两个平台的优势和劣势,并讨论如何根据项目需求和目标受众来做出最佳选择。无论你是初学者还是有经验的开发者,这篇文章都将帮助你更好地理解每个平台的特性,并指导你做出明智的决策。
|
2天前
|
XML 编解码 Android开发
安卓开发中的自定义视图控件
【9月更文挑战第14天】在安卓开发中,自定义视图控件是一种高级技巧,它可以让开发者根据项目需求创建出独特的用户界面元素。本文将通过一个简单示例,引导你了解如何在安卓项目中实现自定义视图控件,包括创建自定义控件类、处理绘制逻辑以及响应用户交互。无论你是初学者还是有经验的开发者,这篇文章都会为你提供有价值的见解和技巧。
|
4天前
|
API Android开发 iOS开发
安卓与iOS开发中的线程管理对比
【9月更文挑战第12天】在移动应用的世界中,安卓和iOS平台各自拥有庞大的用户群体。开发者们在这两个平台上构建应用时,线程管理是他们必须面对的关键挑战之一。本文将深入探讨两大平台在线程管理方面的异同,通过直观的代码示例,揭示它们各自的设计理念和实现方式,帮助读者更好地理解如何在安卓与iOS开发中高效地处理多线程任务。
|
6天前
|
开发框架 Android开发 iOS开发
探索安卓与iOS开发的差异:构建未来应用的指南
在移动应用开发的广阔天地中,安卓与iOS两大平台各占半壁江山。本文将深入浅出地对比这两大操作系统的开发环境、工具和用户体验设计,揭示它们在编程语言、开发工具以及市场定位上的根本差异。我们将从开发者的视角出发,逐步剖析如何根据项目需求和目标受众选择适合的平台,同时探讨跨平台开发框架的利与弊,为那些立志于打造下一个热门应用的开发者提供一份实用的指南。
18 5