概述

直播系统的架构总体上分为采集模块、预览模块、处理模块、编码模块、推流模块。
把这五个模块串联起来就构成了整个直播系统的数据流。如下图所示:

音频采集:采集原始的PCM数据。
音频处理:对音频进行混音消除、降噪、自动增益等处理。
音频编码:把PCM格式的数据编码为AAC格式。
视频采集:相机/屏幕流的采集;YUV格式或者纹理格式。
视频处理:对视频进行美颜/滤镜等处理。
预 览: 把视频处理后的视频流在屏幕上进行渲染显示。
视频编码:把纹理或者YUV格式的原始视频流压缩成H264格式。
推 流:把AAC格式的音频流与H264格式的视频流,通过flv格式包装、推流。

模块设计

为了充分利用CPU的多核、提升推流系统的效率、低延时等,模块的设计采用多线程模型。线程之间的交互通过Blocking队列实现,由于队列是在多线程都需要操作的,需要保证队列的安全性。为了保证队列的安全性,在放入队列之前先上锁,然后操作队列。在操作队列结束之后,发出一个signal指令来告诉block住的线程继续操作队列。添加队列之后的模块图如下图所示:

音频采集

Android 端音频采集常用的有三种方案:AudioRecord、OpenSL、AAudio。
AudioRecord是Android 上层的一个API,通过它可以采集PCM格式的音频数据。
OpenSL是Native层提供的API,它可以采集或播放PCM。
详情链接: https://developer.android.google.cn/ndk/guides/audio/opensl/getting-started
AAudio 是Native层提供的API,Android O 引入的全新的音频API。
详情链接: https://developer.android.google.cn/ndk/guides/audio/aaudio/aaudio

音频的采集放到一个独立线程中执行。把采集之后的音频放到pcm队列中。这里以AudioRecord为例介绍下AudioRecord采集音频的过程:

配置参数(采样率、声道数、采样格式)并获取AudioRecord采集音频缓冲的大小

public static int SAMPLE_RATE_IN_HZ = 44100;
private final static int CHANNEL_CONFIGURATION = AudioFormat.CHANNEL_IN_MONO;
private final static int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT;int bufferSizeInBytes = AudioRecord.getMinBufferSize(SAMPLE_RATE_IN_HZ, CHANNEL_CONFIGURATION, AUDIO_FORMAT)

创建AudioRecord

AudioRecord audioRecord = new AudioRecord(AUDIO_SOURCE, SAMPLE_RATE_IN_HZ, CHANNEL_CONFIGURATION, AUDIO_FORMAT, bufferSizeInBytes);

配置好AudioRecord之后需要检查一下AudioRecord的状态,可能因为权限问题或者其他的原因造成AudioRecord创建失败或者状态不对;

if (audioRecord == null || audioRecord.getState() != AudioRecord.STATE_INITIALIZED) {throw new AudioConfigurationException();
}

开始采集

AudioRecord创建成功之后,可以根据 startRecording() api 开始采集视频。

获取音频数据

获取音频数据需要一个线程,将AudioRecord缓冲区中的音频数据不断的读出来。
int size = audioRecord.read(audioSamplesBuffer, 0, audioSamplesBufferMaxSize);

把音频数据放入PCM队列中

pcm队列的设计后面会模块介绍

停止采集,释放资源

停止音频采集的线程,并调用stop停止采集,调用release释放AudioRecord创建的资源。

音频编码

音频的编码格式有许多像 mp3、aac、wma、ogg、pous、amr等。 aac在低码率场景下,其音频品质非常好,并且在移动平台上无论是单独的音频编码,还是视频中的音频流部分,使用最广泛的都是aac编码。
音频编码器:fdk_aac、MediaCodec
音频编码线程从pcm队列中获取数据编码,编码完成后,把AAC数据放入AAC队列。

这里介绍下软编libfdk_aac编码pcm为aac码流。这里介绍的libfdk_aac是以ffmpeg为基础的,如果后期想用其他编码库,都可以通过ffmpeg的配置实现。
基于ffmpeg的API编码aac,这样做的好处是,只需要编写一份音频编码的代码即可,对于不同的编码器,后期只需要调整相应的编码器ID或者编码器name就可以编码出不同格式的音频文件。既然要使用第三方库libfdk_aac编码aac文件,那么必须首先在ffmpeg交叉编译的时候把libfdk_aac库编译进去。通过调用ffmpeg的API进行音频编码。

音频编码需要在一个线程中实现,它会从pcm队列中获取pcm数据。当队列为空时,wait当前线程。当队列有数据进入signal唤醒当前线程。获取到pcm音频数据后就开始编码,编码完成后把编码后的aac数据入aac 队列。

OpenGL上下文环境搭建

背景

OpenGL不负责窗口管理及上下文环境管理,OpenGL窗口管理及上下文环境管理将由各个平台或者设备自行完成。为了在openGL的输出与设备的屏幕之间架起一个桥梁,需要EGL。EGL是双缓冲的工作模式,即有一个Back Frame Buffer 和一个 Front Frame Buffer,正常绘制操作的目标都是Back Frame Buffer,操作完毕之后,调用eglSwapBuffer这个api,将绘制完毕的Back Frame Buffer 交换到 Front Frame Buffer 并显示出来。在Android平台,使用的是EGL这一套机制,EGL承担了为OpenGL提供上下文环境以及窗口管理的职责。

Android上下文环境

要在Android平台使用opengl es, 第一种方式是直接使用GLSurfaceView,通过这种方式使用OpenGL ES比较简单,因为不需要开发者搭建OpenGL ES的上下文环境,以及创建OpenGL ES的显示设备。但凡事都有两面性,有好处也有坏处,使用GLSurfaceView不够灵活,很多OpenGL ES的核心用法,比如共享上上下文实现多个线程共同操作一个纹理不能使用。所以这里需要通过EGL的api搭建OpenGL的上下文环境,并且基于C++的环境搭建。因为如果用Java层搭建,那么对于普通的应用也许可行,但对于视频应用,出于效率和性能的考虑,这里需要通过C++语言EGL api搭建一个OpenGL的上下文环境。

任何一条opengl指令都必须在自己的OpenGL上下文环境中运行,所以EGL构建出opengl上下文环境之后,就可以执行OpenGL ES了。
OpenGL处理模块需要在一个线程中实现,该线程功能:

  1. EGL环境的管理
  2. 渲染窗口的管理
  3. 纹理的创建
  4. 对视频流的处理

视频采集与预览

Camera的参数配置这里不再进行介绍,这里只介绍 Camera 是如何与 OpenGL结合实现预览的。

SurfaceView的转化

首先UI层构造一个SurfaceView通过SurfaceView获取Surface,然后在NDK把Surface转化为ANativeWindow,在EGL中通过ANativeWindow创建EGLSurface。

外部纹理的创建

通过OpenGL创建一个外部纹理

把外部纹理设置给Camera

通过2创建的外部纹理ID,创建一个SurfaceTexture,并设置一个监听器SurfaceTexture.setOnFrameAvailableListener();每次视频流渲染到SurfaceTexture上时,都会回调该方法。把SurfaceTexture通过setPreviewTexture api设置给Camera。

OpenGL操作外部纹理实现预览

Camera/Camera2采集相机流把采集的相机流渲染到一个外部纹理中,然后通过OpenGL 把外部纹理渲染到窗口,实现预览。

视频采集与预览的流程图如下:

视频编码

MediaCodec的配置及使用不再介绍,这里只介绍OpenGL ES如何与MediaCodec交互的。
MediaCodec的输入视频流是通过OpenGL模块处理的,通过createInputSurface() api获取一个Surface,最终该Surface创建一个EGL Surface。

OpenGL通过把外部纹理渲染到MediaCodec inputsurface上,通知MediaCodec获取编码之后的数据,获取编码之后的数据后通过处理入h264队列。

MediaCodec与OpenGL操作图:

推流:

推流模块根据具体的顺序分别从aac队列/h264队列获取数据,处理,然后封装成flv 格式,推流。
推流模块通过FFmpeg中集成的rtmp协议实现推流。这样我们就可以通过ffmpeg的写文件的API实现推流。
这样做的好处是,只需要编写一份推流模块的代码即可,当我们想把音视频流写到本地时,推流模块的代码不需要修改,只需要修改我们的传给推流模块的path就可以。比如:mnt/sdcard/0/test.mp4,就可以把视频流以mp4格式保存到本地。

Android端直播SDK实现方案相关推荐

  1. android 视频直播SDK

    通过android移动端实时采集视频,同时在拍摄过程中支持多种实时滤镜效果,只要调用视频直播接口,通过3G.4G.WIFI等网络,推流发送给云端流媒体直播系统处理,并通过CDN视频加速分发做现场直播播 ...

  2. 搭建直播平台过程中Android端直播APP源码是如何实现连麦功能的?

    直播平台强大的变现能力是大家有目共睹的,很多开发商在搭建直播平台时为了增加用户黏性,纷纷将直播中加入连麦功能. 目前市场上通用的有两种连麦方案:本地混流和云端混流.本地混流即主播和连麦观众分别推一路流 ...

  3. Android端穿山甲SDK集成

    Android端穿山甲SDK集成 流程 创建测试状态的应用及应用下对应的测试状态的代码位ID 项目对接SDK完毕后 拿APP到应用商店审核 得到应用商店的APP的下载地址 结合文档转换成apk下载地址 ...

  4. 几个移动端直播SDK开源地址

    ios直播sdk: https://github.com/runner365/LiveVideoCoreSDK ios带滤镜的直播sdk: https://github.com/runner365/G ...

  5. android主流视频直播sdk,Android视频直播SDK集成指引

    手动安装 目前 ZegoLiveRoom SDK 仅支持通过拷贝库文件的方式,集成步骤如下. 1 准备环境 请确保开发环境满足以下技术要求: Android Studio 2.1 或以上版本 已经下载 ...

  6. Android语音直播SDK

    本文讲述如何在Android环境下集成即构语音直播SDK,实现同一房间内的成员进行语音直播,有需要时也可进行实时语音通话. 请从 ZegoAudioRoom iOS 下载 SDK.如果要实现播放本地音 ...

  7. Android端乐橙云SDK集成

    乐橙云官网链接如下:https://open.imoulife.com/ Android端接入SDK链接如下:https://open.imoulife.com/book/opensdk/sdk/an ...

  8. 58 同城 Android 端 HTTPS 实践之旅

    自 WWDC 2016 苹果传递出从 2017 年 1 月起强制启用应用程序安全传输协议(App Transport Security)的信号,各大厂均开始了 HTTPS 化的征程.虽然目前苹果将此计 ...

  9. java后台与android端集成信鸽推送和华为推送通道

    时间比较紧,并未调试. 需求:后端可以针对指定账号或者列表进行通知栏信息推送,优先使用华为通道.点击通知栏消息打开指定activity 后端版本V3,android sdk 3.2.7 一.后端部分代 ...

最新文章

  1. java基础----递归
  2. 〔译〕TypeScript 2.0 候选版发布
  3. VIO-slam 系统构建
  4. 请求对象Request
  5. 【安装教程】windows8.1 下安装ubuntu14.04 双系统
  6. z-index 绝对定位的盒子居中
  7. Web前端开发规范之图片命名规范
  8. 运用incremental backup恢复归档GAP的DG-上篇
  9. WordPress仿站实战教程
  10. Excel VBA使用总结
  11. 读书笔记:《超越需求 敏捷思维模式下的分析》
  12. html5网页设计作业代码 大学生校园网站制作 学校官网制作html
  13. 7号信令基本概念和术语
  14. jQuery+Ajax+全解析
  15. 关于Github项目DCRNN运行问题小结(1)——tables模块包
  16. Amazon Shield Advanced 更新 – 自动应用程序层 DDoS 防御
  17. PowerPoint2019删除当前ppt页上的某个动画
  18. 一份完整的单机版slurm部署
  19. Docker入门实战大全终极版
  20. xp无法ping工作组计算机,在XP下Ping不通win2003怎么解决?

热门文章

  1. 第三方软件测评公司有哪些?软件产品验收测试流程及注意事项
  2. 区分充分条件、必要条件和充分性、必要性
  3. 使用crontab出现crontab: installing new crontab时什么意思
  4. 数据分析面试之统计的基础知识(持续更新)
  5. 安卓支持RISC-V架构的技术剖析
  6. 新华三H3C急招高级网络工程师
  7. WinInet 介绍
  8. 轩辕剑五的乱码问题解决
  9. 申请CloudFlare免费DNS服务
  10. 带你理解CT的“排”与“层”