58

Android音视频开发之MediaCodec编解码

 4 years ago
source link: https://www.tuicool.com/articles/7bAzeyZ
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

1 背景

音视频的原始数据非常庞大,难以存储和传输。要解决音视频数据的存储和传输问题,就需要对这些数据进行压缩,音视频数据压缩技术就是音视频编码。 编码的目的就是在最小图像或音频信息丢失情况下得到最大的压缩,解码是相对编码的,其目的是最大限度的还原原始图像或声音信息。编解码的意义就是便于数据传输和存储。

我们目前正在开发的直播、小视频、互动直播、视频会议、一对一通话、视频录制、播放器等项目都大量使用了编解码技术。 音视频编解码格式非常多(h264、h265、vp8、vp9、aac、opus……),实现每种编解码都需要引入外部库,导致项目臃肿、包体积过大且运行性能差。

MediaCodec是Google为Android开发者和芯片厂商搭建的一套用于调用硬件编解码器组件的统一接口。MediaCodec与常规编解码库相比具有非常明显的优势,它速度快、效率高、CPU占用率低、内存小、节省包体积。使用MediaCodec可以解决项目臃肿、减小包体积和提升编解码性能。

2、MediaCodec使用技巧

MediaCodec 处理输入数据后生成输出数据。它异步处理数据,并使用一组输入和输出缓冲区。一个简单的使用方式,请求一个空的输入缓冲区,用数据填充它并将其发送到编解码器进行处理。编解码器处理完数据并将其转换到一个空的输出缓冲区。最后,请求一个已填满的输出缓冲区,使用它的内容并将其释放回编解码器。

AfuYFvu.png!web

MediaCodec可以 对三种数据进行操作:编码数据、原始音频数据和原始视频数据。这三种数据都可以使用ByteBuffer来处理,但是强烈建议使用Surface来处理原始视频数据,以提高编解码器的性能。Surface使用的是原生视频缓冲区,不需要映射或复制到字节缓冲区;因此,它的效率要高得多。

解码器的输入缓冲区和编码器的输出缓冲区内含有根据MIME类型编码的数据。对于视频类型,这通常是一个单独的编码视频帧。对于音频数据,这通常是一个编码的音频段,包含几毫秒的音频,一个缓冲区可能包含多个编码的音频段。

音频缓冲区包含PCM音频数据的整个帧。每个PCM音频样本要么是一个16整数(ENCODING_PCM_16BIT),要么是一个32位浮点数(ENCODING_PCM_FLOAT)。

视频缓冲区根据KEY_COLOR_FORMAT确定数据格式。视频编解码器支持三种颜色格式:

  • native raw video format

  • flexible YUV buffers

  • other, specific formats

MediaCodec存在三种状态:停止(stoped)、执行(executing)、释放(released)。

停止状态有三个子状态:配置(configured)、未初始化(uninitialized)、错误(error)

执行状态有三个子状态:刷新(flushed)、运行(running)、结束流(end-of-stream)

B3M7v2U.png!web

Meidacodec提供了三个静态方法创建实例:

createDecoderByType(Stringtype)

createEncoderByType(Stringtype)

createByCodecName(Stringname)

以下是部分支持类型列表:

"video/x-vnd.on2.vp8"- VP8 video (i.e. video in .webm)

"video/x-vnd.on2.vp9"- VP9 video (i.e. video in .webm)

"video/avc"- H.264/AVC video

"video/hevc"- H.265/HEVC video

"video/mp4v-es"- MPEG4 video

"video/3gpp"- H.263 video

"audio/3gpp"- AMR narrowband audio

"audio/amr-wb"- AMR wideband audio

"audio/mpeg"- MPEG1/2 audio layer III

"audio/mp4a-latm"- AAC audio

"audio/vorbis"- vorbis audio

"audio/g711-alaw"- G.711 alaw audio

"audio/g711-mlaw"- G.711 ulaw audio

MediaCodec处理数据有异步模式和同步模式。从LOLLIPOP开始,首选方法是在调用configure方法之前通过设置回调来异步处理数据。异步模式会更改MediaCodec的状态转换。

EFvyAnz.png!web

3、MediaCodec技术实践

1)视频编辑功能

MediaCodec通常与MediaExtractor、MediaSync、MediaMuxer、MediaCrypto、MediaDrm、Image、Surface和AudioTrack一起使用,几乎可以实现大部分音视频相关功能。基于MediaCodec、MediaExtractor、MediaMuxer就可以实现一个完整的视频编辑功能

MediaExtractor用于对音视频文件解封装,提取出已编码的媒体数据。

MediaMuxer用于封装编码后的音视频数据,目前支持MP4、Webm和3GP文件作为输出。

操作步骤:

a) 初始化

b) MediaExtractor提取音视频编码数据

c) MediaCodec解码器解码

d) 音视频处理

e) MediaCodec编码器对音视频数据编码

f) MediaMuxer合成音视频文件

g) 释放

B7BJfyV.png!web

2)直播推流功能

直播推流功能包括图像采集、音频采集、图像和音频处理、图像编码、音频编码、FLV封装、RTMP推流等模块。其中图像编码、音频编码的硬编码部分使用了MediaCodec实现。

操作步骤:

a) 音频、图像采集

b) 采集数据处理

c) H264、aac编码

d) flv封装和RTMP传输

I7ZfYjY.png!web

4、编码性能对比

场景:58视频APP直播推流功能分别使用MediaCodec与openH264编码器进行编码,分析CPU使用率及内存占用。

性能分析工具:GT

机型:三星SM-N9100

android系统版本:6.0

推流参数:分辨率544*960、码率1500kbps、帧率15、采样率44100、、采样16位、声道数2

CPU使用率:

FbYVNbb.png!web

内存:

eAv2iq2.png!web

测试结果为MediaCodec方案占用CPU平均值为61.78%,平均内存为944MB。软编码方案CPU平均值为66.71%,平均内存为1082MB。综合以上测试结果MediaCodec占用CPU资源相对较少且波动较小,MediaCodec配合Surface输入数据方案能极大的节省内存,性能优势提升非常明显。

5、总结

MediaCodec是Android重要的底层多媒体组件,合理使用MediaCodec可以实现播放器、直播、视频编辑、视频录制、视频通话、视频会议等几乎所有音视频相关的编解码功能,且与常规编解码库相比拥有绝对的性能优势。同样,MediaCodec也存在一些缺点,兼容性、稳定性都比较差,开发过程中会经常遇到机型、版本等适配问题,这些都不会造成阻碍性问题,通过适配几乎都可以合理解决。

参考文档:   

https://developer.android.com/reference/android/media/MediaCodec

https://developer.android.com/reference/android/media/MediaExtractor.html

https://developer.android.com/reference/android/media/MediaMuxer.html


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK