前言

本文重点关注如何对一帧音频数据进行编码和解码。

Android 官方的 MediaCodec API

首先,我们了解一下 Android 官方提供的音频编解码的 API,即 MediaCodec 类,该 API 是在 Andorid 4.1 (API 16) 版本引入的,因此只能工作于 Android 4.1 以上的手机上。

1. MediaCodec 基本介绍

  • 提供了一套访问 Android 底层多媒体模块的接口,主要是音视频的编解码接口;
  • Android 底层多媒体模块采用的是 OpenMax 框架,任何 Android 底层编解码模块的实现,都必须遵循 OpenMax 标准。Google 官方默认提供了一系列的软件编×××:包括:OMX.google.h264.encoder,OMX.google.h264.encoder, OMX.google.aac.encoder, OMX.google.aac.decoder 等等,而硬件编解码功能,则需要由芯片厂商依照 OpenMax 框架标准来完成,所以,一般采用不同芯片型号的手机,硬件编解码的实现和性能是不同的;
  • Android 应用层统一由 MediaCodec API 来提供各种音视频编解码功能,由参数配置来决定采用何种编解码算法、是否采用硬件编解码加速等

2. MediaCodec 核心原理
MediaCodec 使用的基本流程是:

- createEncoderByType/createDecoderByType
- configure
- start
- while(1) {
    - dequeueInputBuffer
    - queueInputBuffer
    - dequeueOutputBuffer
    - releaseOutputBuffer
}
- stop
- release

由此可以看到,Buffer 队列的操作是其最核心的部分之一,关于 MediaCodec 的 Buffer 队列 ,示意图如下:

Android音频码率 android 音频编码_Android音频码率


MediaCodec 架构上采用了2个缓冲区队列,异步处理数据,下面描述的 Client 和 MediaCodec 模块是并行工作的(注:这里的 Client 就是指 “开发者,API 的使用者”):

(1)Client 从 input 缓冲区队列申请 empty buffer [dequeueInputBuffer]

(2)Client 把需要编解码的数据拷贝到 empty buffer,然后放入 input 缓冲区队列 [queueInputBuffer]

(3)MediaCodec 模块从 input 缓冲区队列取一帧数据进行编解码处理

(4)编解码处理结束后,MediaCodec 将原始数据 buffer 置为 empty 后放回 input 缓冲区队列,将编解码后的数据放入到 output 缓冲区队列

(5)Client 从 output 缓冲区队列申请编解码后的 buffer [dequeueOutputBuffer]

(6)Client 对编解码后的 buffer 进行渲染/播放

(7)渲染/播放完成后,Client 再将该 buffer 放回 output 缓冲区队列 [releaseOutputBuffer]

MediaCodec 在架构上,其实是采用了一种基于“环形缓冲区”的“生产者-消费者”模式,它设计了 2 个基于 idx 序号的“环形缓冲区” ,注意,是 2 个,一个在 input 端, 一个在 output 端。

基于 idx 的环形缓冲区的总体示意图如下,图中,wp 代表 “写指针”,指向的是 “empty buffer”, 而 rp 代表 “读指针”,指向的是 “filled buffer”:

Android音频码率 android 音频编码_Android音频码率_02


“生产者”和“消费者”其实是共用这一个缓冲区队列,“生产者”负责从队列中取出未使用的 Buffer,填入数据,然后放回队列,“消费者”则负责取出填入数据后的 Buffer,进行处理,处理结束后,再把 Buffer 标记为“空”,退回到队列中去以供“生产者”继续填充数据。

在 input 端,“Client”是这个环形缓冲区“生产者”,“MediaoCodec 模块”是“消费者”。

在 output 端,“MediaoCodec 模块”是这个环形缓冲区“生产者”,而“Client”则变成了“消费者”。

第三方音频编解码库

  • opus 编解码库
    官网地址: https://www.opus-codec.org
  • Speex 编解码库
    官网地址: http://www.speex.org
  • ffmpeg
    官网地址: https://www.ffmpeg.org
  • Android AAC Encoder
    官网地址: https://github.com/timsu/android-aac-enc
  • opencore-amr-android
    Git 地址: https://github.com/kevinho/opencore-amr-android
  • iLBC-Android
    Git 地址:  https://github.com/lukeweber/iLBC-Android