【Android RTMP】音频数据采集编码 ( FAAC 编码器编码 AAC 音频解码信息 | 封装 RTMP 音频数据头 | 设置 AAC 音频数据类型 | 封装 RTMP 数据包 )

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 【Android RTMP】音频数据采集编码 ( FAAC 编码器编码 AAC 音频解码信息 | 封装 RTMP 音频数据头 | 设置 AAC 音频数据类型 | 封装 RTMP 数据包 )

文章目录

安卓直播推流专栏博客总结

一、 FAAC 编码器编码 AAC 音频解码信息

二、 封装 RTMP 音频数据头

三、 封装 RTMP 音频数据类型

四、 拷贝 AAC 音频数据到 RTMPPacket 数据包中

五、 设置数据包大小

六、 设置绝对时间、数据类型、RTMP 通道、头类型

七、 FAAC 编码器编码代码示例





安卓直播推流专栏博客总结


Android RTMP 直播推流技术专栏 :



0 . 资源和源码地址 :


资源下载地址 : 资源下载地址 , 服务器搭建 , x264 , faac , RTMPDump , 源码及交叉编译库 , 本专栏 Android 直播推流源码 ;

GitHub 源码地址 : han1202012 / RTMP_Pusher


1. 搭建 RTMP 服务器 : 下面的博客中讲解了如何在 VMWare 虚拟机中搭建 RTMP 直播推流服务器 ;


【Android RTMP】RTMP 直播推流服务器搭建 ( Ubuntu 18.04.4 虚拟机 )

2. 准备视频编码的 x264 编码器开源库 , 和 RTMP 数据包封装开源库 :


【Android RTMP】RTMPDumb 源码导入 Android Studio ( 交叉编译 | 配置 CMakeList.txt 构建脚本 )


【Android RTMP】Android Studio 集成 x264 开源库 ( Ubuntu 交叉编译 | Android Studio 导入函数库 )


3. 讲解 RTMP 数据包封装格式 :


【Android RTMP】RTMP 数据格式 ( FLV 视频格式分析 | 文件头 Header 分析 | 标签 Tag 分析 | 视频标签 Tag 数据分析 )


【Android RTMP】RTMP 数据格式 ( FLV 视频格式分析 | AVC 序列头格式解析 )


4. 图像数据采集 : 从 Camera 摄像头中采集 NV21 格式的图像数据 , 并预览该数据 ;


【Android RTMP】Android Camera 视频数据采集预览 ( 视频采集相关概念 | 摄像头预览参数设置 | 摄像头预览数据回调接口 )


【Android RTMP】Android Camera 视频数据采集预览 ( NV21 图像格式 | I420 图像格式 | NV21 与 I420 格式对比 | NV21 转 I420 算法 )


【Android RTMP】Android Camera 视频数据采集预览 ( 图像传感器方向设置 | Camera 使用流程 | 动态权限申请 )


5. NV21 格式的图像数据编码成 H.264 格式的视频数据 :


【Android RTMP】x264 编码器初始化及设置 ( 获取 x264 编码参数 | 编码规格 | 码率 | 帧率 | B帧个数 | 关键帧间隔 | 关键帧解码数据 SPS PPS )


【Android RTMP】x264 图像数据编码 ( Camera 图像数据采集 | NV21 图像数据传到 Native 处理 | JNI 传输字节数组 | 局部引用变量处理 | 线程互斥 )


【Android RTMP】x264 图像数据编码 ( NV21 格式中的 YUV 数据排列 | Y 灰度数据拷贝 | U 色彩值数据拷贝 | V 饱和度数据拷贝 | 图像编码操作 )


6. 将 H.264 格式的视频数据封装到 RTMP 数据包中 :


【Android RTMP】RTMPDump 封装 RTMPPacket 数据包 ( 封装 SPS / PPS 数据包 )


【Android RTMP】RTMPDump 封装 RTMPPacket 数据包 ( 关键帧数据格式 | 非关键帧数据格式 | x264 编码后的数据处理 | 封装 H.264 视频数据帧 )


【Android RTMP】RTMPDump 推流过程 ( 独立线程推流 | 创建推流器 | 初始化操作 | 设置推流地址 | 启用写出 | 连接 RTMP 服务器 | 发送 RTMP 数据包 )


7. 阶段总结 : 阿里云服务器中搭建 RTMP 服务器 , 并使用电脑软件推流和观看直播内容 ;


【Android RTMP】RTMP 直播推流 ( 阿里云服务器购买 | 远程服务器控制 | 搭建 RTMP 服务器 | 服务器配置 | 推流软件配置 | 直播软件配置 | 推流直播效果展示 )


【Android RTMP】RTMP 直播推流阶段总结 ( 服务器端搭建 | Android 手机端编码推流 | 电脑端观看直播 | 服务器状态查看 )


8. 处理 Camera 图像传感器导致的 NV21 格式图像旋转问题 :


【Android RTMP】NV21 图像旋转处理 ( 问题描述 | 图像顺时针旋转 90 度方案 | YUV 图像旋转细节 | 手机屏幕旋转方向 )


【Android RTMP】NV21 图像旋转处理 ( 图像旋转算法 | 后置摄像头顺时针旋转 90 度 | 前置摄像头顺时针旋转 90 度 )


9. 下面这篇博客比较重要 , 里面有一个快速搭建 RTMP 服务器的脚本 , 强烈建议使用 ;


【Android RTMP】NV21 图像旋转处理 ( 快速搭建 RTMP 服务器 Shell 脚本 | 创建 RTMP 服务器镜像 | 浏览器观看直播 | 前置 / 后置摄像头图像旋转效果展示 )

10. 编码 AAC 音频数据的开源库 FAAC 交叉编译与 Android Studio 环境搭建 :


【Android RTMP】音频数据采集编码 ( 音频数据采集编码 | AAC 高级音频编码 | FAAC 编码器 | Ubuntu 交叉编译 FAAC 编码器 )


【Android RTMP】音频数据采集编码 ( FAAC 头文件与静态库拷贝到 AS | CMakeList.txt 配置 FAAC | AudioRecord 音频采样 PCM 格式 )


11. 解析 AAC 音频格式 :


【Android RTMP】音频数据采集编码 ( AAC 音频格式解析 | FLV 音频数据标签解析 | AAC 音频数据标签头 | 音频解码配置信息 )

12 . 将麦克风采集的 PCM 音频采样编码成 AAC 格式音频 , 并封装到 RTMP 包中 , 推流到客户端 :


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


【Android RTMP】音频数据采集编码 ( FAAC 编码器编码 AAC 音频解码信息 | 封装 RTMP 音频数据头 | 设置 AAC 音频数据类型 | 封装 RTMP 数据包 )


【Android RTMP】音频数据采集编码 ( FAAC 编码器编码 AAC 音频采样数据 | 封装 RTMP 音频数据头 | 设置 AAC 音频数据类型 | 封装 RTMP 数据包 )






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



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



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



AAC 音频解码信息 : AAC 音频数据推流前 , 需要将解码信息推流到服务器 , 否则播放器无法识别该 AAC 音频数据 , 本篇博客就是讲解 FAAC 编码器编码生成 AAC 解码信息 , 并封装 RTMPPacket 数据包 , 推流到 RTMP 服务器中 ;






一、 FAAC 编码器编码 AAC 音频解码信息


推流 AAC 音频数据之前 , 需要先将 AAC 格式音频的解码信息推流到服务器中 , AAC 音频解码信息用于指导播放器解码 AAC 音频数据 ; 其作用类似于 H.264 视频的 SPS 和 PPS 数据 , 用于指导播放器解码 H.264 视频帧数据 ;



1 . AAC 解码信息生成方法 : FAAC 编码器调用 faacEncGetDecoderSpecificInfo 方法 , 生成 AAC 音频解码信息 ;



2 . faacEncGetDecoderSpecificInfo 方法原型 :


#include <faac.h>
int FAACAPI faacEncGetDecoderSpecificInfo(faacEncHandle hEncoder, unsigned char **ppBuffer,
       unsigned long *pSizeOfDecoderSpecificInfo);


① faacEncHandle hEncoder 参数 : FAAC 编码器 ;


② unsigned char **ppBuffer 参数 : 用于接收 FFAC 编码器编码生成的 AAC 解码信息 , 这是个二维指针 , 外部传入 , 当做返回值使用 ; 该值一般需要预先在外部定义 , 定义 unsigned char * 类型一维指针变量 , 或 unsigned char ** 类型二维指针变量 ;


③ unsigned long *pSizeOfDecoderSpecificInfo 参数 : 用于接收 FFAC 编码器编码生成的 AAC 解码信息 字节个数 , 当做返回值使用 ; 该值一般需要预先在外部定义 , 定义 unsigned long 类型变量 , 或 unsigned long* 类型变量 ;


后两个参数定义不同级别的指针类型 , 使用方法不同 , 但形式类似 , 都是用指针变量 , 传入地址作为参数 , 传入的指针当做返回值使用 ;



3 . 代码示例 :


 

// 该指针用于接收获取的 FAAC 解码特殊信息
    unsigned char *pBuffer;
    // 该指针用于接收获取的 FAAC 解码特殊信息长度
    unsigned long sizeOfDecoderSpecificInfo;
    // 生成 FAAC 解码特殊信息数据
    faacEncGetDecoderSpecificInfo(mFaacEncHandle, &pBuffer, &sizeOfDecoderSpecificInfo);





二、 封装 RTMP 音频数据头


1 . 封装第 1 11 字节数据 : 第一个字节中封装了 4 44 部分数据 , 音频格式 , 采样率 , 采样位数 , 音频通道 ; 一般情况下是 AE , 或者 AF ;



① AF 含义 : AAC 格式 , 44100 Hz 采样 , 16 位采样位数 , 立体声 ;


② AE 含义 : AAC 格式 , 44100 Hz 采样 , 16 位采样位数 , 单声道 ;



参考博客 【Android RTMP】音频数据采集编码 ( AAC 音频格式解析 | FLV 音频数据标签解析 | AAC 音频数据标签头 | 音频解码配置信息 ) 、四、 音频解码配置信息、 2. 第 11 字节 AF 数据解析 章节 , 有详细介绍这 8 88 位各代表的意义 ;



2 . 代码示例 :


 

/*
        根据声道数生成相应的 文件头 标识
        AF / AE 头中的最后一位为 1 表示立体声, 为 0 表示单声道
        AF 是立体声
        AE 是单声道
     */
    rtmpPacket->m_body[0] = 0xAF;   //默认立体声
    if (mChannelConfig == 1) {
        // 如果是单声道, 将该值修改成 AE
        rtmpPacket->m_body[0] = 0xAE;
    }






三、 封装 RTMP 音频数据类型


AAC 音频数据类型 : 如果是编码的音频采样数据 , 类型是 01 , 如果是 AAC 解码信息 , 类型是 00 ; 这里是 00 类型 , AAC 音频解码信息类型 ;


 

// 编码出的声音 都是 0x01, 头信息是 AF 01 数据
    // 如果是AAC 音频解码数据 , 那么头信息是 AF 00 数据
    rtmpPacket->m_body[1] = 0x00;






四、 拷贝 AAC 音频数据到 RTMPPacket 数据包中


之前调用 faacEncGetDecoderSpecificInfo 方法 , 生成了 AAC 音频解码信息 , 将生成的信息封装到 RTMPPacket 数据包中 , RTMP 数据包的大小是生成 AAC 解码信息大小 + 2 ; 多出的 2 字节数据是 AF 00 ;


 

// 拷贝 AAC 音频数据到 RTMPPacket 数据包中
    memcpy(&rtmpPacket->m_body[2], pBuffer, sizeOfDecoderSpecificInfo);





五、 设置数据包大小


该数据包大小是 2 字节 , 加上 faacEncGetDecoderSpecificInfo 方法生成 的 AAC 解码数据大小 ;


2 字节是 AF 00 ;


 

// 设置 RTMP 数据包大小
    rtmpPacket->m_nBodySize = rtmpPackagesize;




六、 设置绝对时间、数据类型、RTMP 通道、头类型


这些数据设置基本都是格式化的 , 按照如下设置即可 ;


// 设置绝对时间, 一般设置 0 即可
    rtmpPacket->m_hasAbsTimestamp = 0;
    // 设置 RTMP 数据包大小
    rtmpPacket->m_nBodySize = rtmpPackagesize;
    // 设置 RTMP 包类型, 视频类型数据
    rtmpPacket->m_packetType = RTMP_PACKET_TYPE_AUDIO;
    // 分配 RTMP 通道, 该值随意设置, 建议在视频 H.264 通道基础上加 1
    rtmpPacket->m_nChannel = 0x11;
    // // 设置头类型, 随意设置一个
    rtmpPacket->m_headerType = RTMP_PACKET_SIZE_LARGE;





七、 FAAC 编码器编码代码示例


/**
 * 获取音频解码信息
 * 推流音频数据时, 先发送解码信息包, 再推流 AAC 音频采样包
 * @return 音频解码数据包
 */
RTMPPacket *AudioChannel::getAudioDecodeInfo() {
    /*
        下面的数据信息用于指导 AAC 数据如何进行解码
        类似于 H.264 视频信息中的 SPS 与  PPS 数据
        int FAACAPI faacEncGetDecoderSpecificInfo(
                        faacEncHandle hEncoder,
                        unsigned char **ppBuffer,
         unsigned long *pSizeOfDecoderSpecificInfo);
     */
    // 该指针用于接收获取的 FAAC 解码特殊信息
    unsigned char *pBuffer;
    // 该指针用于接收获取的 FAAC 解码特殊信息长度
    unsigned long sizeOfDecoderSpecificInfo;
    // 生成 FAAC 解码特殊信息数据
    faacEncGetDecoderSpecificInfo(mFaacEncHandle, &pBuffer, &sizeOfDecoderSpecificInfo);
    // 组装 RTMP 数据包
    /*
        数据的大小 :
        前面有 2 字节头信息
        音频解码配置信息 : 前两位是 AF 00 , 指导 AAC 数据如何解码 ( 是这个 )
        音频采样信息 : 前两位是 AF 01 , 实际的 AAC 音频采样数据
     */
    int rtmpPackagesize = 2 + sizeOfDecoderSpecificInfo;
    // 创建 RTMP 数据包对象
    RTMPPacket *rtmpPacket = new RTMPPacket;
    // 为 RTMP 数据包分配内存
    RTMPPacket_Alloc(rtmpPacket, rtmpPackagesize);
    /*
        根据声道数生成相应的 文件头 标识
        AF / AE 头中的最后一位为 1 表示立体声, 为 0 表示单声道
        AF 是立体声
        AE 是单声道
     */
    rtmpPacket->m_body[0] = 0xAF;   //默认立体声
    if (mChannelConfig == 1) {
        // 如果是单声道, 将该值修改成 AE
        rtmpPacket->m_body[0] = 0xAE;
    }
    // 编码出的声音 都是 0x01, 本方法是对音频数据进行编码的方法, 头信息肯定是 AF 01 数据
    // 数据肯定是 AAC 格式的采样数据
    rtmpPacket->m_body[1] = 0x00;
    // 拷贝 AAC 音频数据到 RTMPPacket 数据包中
    memcpy(&rtmpPacket->m_body[2], pBuffer, sizeOfDecoderSpecificInfo);
    // 设置绝对时间, 一般设置 0 即可
    rtmpPacket->m_hasAbsTimestamp = 0;
    // 设置 RTMP 数据包大小
    rtmpPacket->m_nBodySize = rtmpPackagesize;
    // 设置 RTMP 包类型, 视频类型数据
    rtmpPacket->m_packetType = RTMP_PACKET_TYPE_AUDIO;
    // 分配 RTMP 通道, 该值随意设置, 建议在视频 H.264 通道基础上加 1
    rtmpPacket->m_nChannel = 0x11;
    // // 设置头类型, 随意设置一个
    rtmpPacket->m_headerType = RTMP_PACKET_SIZE_LARGE;
    // 调用回调接口, 将该封装好的 RTMPPacket 数据包放入 native-lib 类中的 线程安全队列中
    // 这是个 RTMPPacketPackUpCallBack 类型的函数指针
    // 这里不回调, 直接返回 rtmpPacket
    //mRtmpPacketPackUpCallBack(rtmpPacket);
    return rtmpPacket;
}



目录
相关文章
|
3天前
|
XML API Android开发
码农之重学安卓:利用androidx.preference 快速创建一、二级设置菜单(demo)
本文介绍了如何使用androidx.preference库快速创建具有一级和二级菜单的Android设置界面的步骤和示例代码。
23 1
码农之重学安卓:利用androidx.preference 快速创建一、二级设置菜单(demo)
|
17天前
|
开发工具 Android开发 开发者
Android平台如何不推RTMP|不发布RTSP流|不实时录像|不回传GB28181数据时实时快照?
本文介绍了一种在Android平台上实现实时截图快照的方法,尤其适用于无需依赖系统接口的情况,如在RTMP推送、RTSP服务或GB28181设备接入等场景下进行截图。通过底层模块(libSmartPublisher.so)实现了截图功能,封装了`SnapShotImpl.java`类来管理截图流程。此外,提供了关键代码片段展示初始化SDK实例、执行截图、以及在Activity销毁时释放资源的过程。此方案还考虑到了快照数据的灵活处理需求,符合GB/T28181-2022的技术规范。对于寻求更灵活快照机制的开发者来说,这是一个值得参考的设计思路。
|
13天前
|
JSON Java Android开发
Android 开发者必备秘籍:轻松攻克 JSON 格式数据解析难题,让你的应用更出色!
【8月更文挑战第18天】在Android开发中,解析JSON数据至关重要。JSON以其简洁和易读成为首选的数据交换格式。开发者可通过多种途径解析JSON,如使用内置的`JSONObject`和`JSONArray`类直接操作数据,或借助Google提供的Gson库将JSON自动映射为Java对象。无论哪种方法,正确解析JSON都是实现高效应用的关键,能帮助开发者处理网络请求返回的数据,并将其展示给用户,从而提升应用的功能性和用户体验。
25 1
|
20天前
|
缓存 API Android开发
Android经典实战之Kotlin Flow中的3个数据相关的操作符:debounce、buffer和conflate
本文介绍了Kotlin中`Flow`的`debounce`、`buffer`及`conflate`三个操作符。`debounce`过滤快速连续数据,仅保留指定时间内的最后一个;`buffer`引入缓存减轻背压;`conflate`仅保留最新数据。通过示例展示了如何在搜索输入和数据流处理中应用这些操作符以提高程序效率和用户体验。
29 6
|
18天前
|
编解码 网络协议 前端开发
如何实现Android平台GB28181设备接入模块按需打开摄像头并回传数据
后台采集摄像头,如果想再进一步扩展,可以把android平台gb28181的camera2 demo,都移植过来,实现功能更强大的国标设备侧,这里主要是展示,收到国标平台侧的回传请求后,才打开摄像头,才开始编码打包,最大限度的减少资源的占用
|
18天前
|
编解码 网络协议 Android开发
Android平台GB28181设备接入模块实现后台service按需回传摄像头数据到国标平台侧
我们在做Android平台GB28181设备对接模块的时候,遇到这样的技术需求,开发者希望能以后台服务的形式运行程序,国标平台侧没有视频回传请求的时候,仅保持信令链接,有发起视频回传请求或语音广播时,打开摄像头,并实时回传音视频数据或接收处理国标平台侧发过来的语音广播数据。
|
18天前
|
Java 网络安全 开发工具
UNITY与安卓⭐一、Android Studio初始设置
UNITY与安卓⭐一、Android Studio初始设置
|
19天前
|
算法 数据处理 开发工具
Android平台RTSP|RTMP播放器如何回调YUV或RGB数据
在开发Android平台上的RTSP或RTMP播放器时,开发者不仅追求低延迟播放,还希望获取解码后的视频数据(如YUV或RGB格式),以便进行视觉算法分析。使用大牛直播SDK中的SmartPlayer,可在确保播放流畅的同时,通过设置外部渲染器(`SmartPlayerSetExternalRender`)来高效地回调原始视频数据。例如,对于RGBA数据,需实现`NTExternalRender`接口,并重写相关方法以处理数据和尺寸变化。同样地,对于I420(YUV)数据,也需要相应地实现接口以满足需求。这种方式使得开发者能在不影响常规播放功能的情况下,进行定制化的视频处理任务。
|
2月前
|
XML Android开发 数据格式
Android 中如何设置activity的启动动画,让它像dialog一样从底部往上出来
在 Android 中实现 Activity 的对话框式过渡动画:从底部滑入与从顶部滑出。需定义两个 XML 动画文件 `activity_slide_in.xml` 和 `activity_slide_out.xml`,分别控制 Activity 的进入与退出动画。使用 `overridePendingTransition` 方法在启动 (`startActivity`) 或结束 (`finish`) Activity 时应用这些动画。为了使前 Activity 保持静止,可定义 `no_animation.xml` 并在启动新 Activity 时仅设置新 Activity 的进入动画。
48 12
|
10天前
|
开发工具 Android开发
Android项目架构设计问题之外部客户方便地设置回调如何解决
Android项目架构设计问题之外部客户方便地设置回调如何解决
12 0