目标
了解
MediaCodec
API的基本使用,熟悉使用MediaCodec
编解码的一般流程;使用
MediaCodec
硬解码AAC
音频文件;使用
MediaCodec
硬解码H.264
视频文件;[x] 音视频基础0——目录
[x] 音视频基础1——AudioTrack、AudioRecorder、MediaRecorder音频数据采集播放处理
[x] 音视频基础6——交叉编译动态库
简介
两张图,一张是MediaCodec
处理的流程图,一张是MediaCodec
生命周期图,如下:
处理流程图
简单来说,就是客户端从MediaCodec请求一段内存空间,用来填充数据,填充好后,交给MediaCodec处理,处理完毕后,MediaCodec讲处理结果填充到自己分配一段空内存中,然后由客户端自己去拉取。
- 用来进行数据填充的内存空间,在
MediaCodec
中由ByteBuffer
来实现; - 提交给
MediaCodec
处理由一个BufferMap
(HashMap
的简单封装实现)来实现,代码对应于mDequeuedInputBuffers
,相应的操作方法是queueInputBuffer
和dequeueInputBuffer
; - 从MediaCodec拉取处理结果由一个
BufferMap
(HashMap
的简单封装实现)来实现,代码对应于mDequeuedOutputBuffers
, 相应的操作方法是dequeueOutputBuffer
;
生命周期图
从上图可以看出,MediaCodec共三种大状态:
Stopped
,分三种子状态:Configured
,MediaCodec
实例创建后,调用configure
方法后就进入了Configured
状态Uninitialized
,MediaCodec
实例被创建后,在调用configure
方法前都处于该状态;Error
,MediaCodec
遇到错误时进入该状态,通常可能是队列操作返回错误或异常导致的;
Executing
,分三种状态Flushed
,在调用start()
方法后MediaCodec
立即进入Flushed
子状态,此时MediaCodec
会拥有所有的缓存。可以在Executing
状态的任何时候通过调用flush()
方法返回到Flushed
子状态;Running
,一旦第一个输入缓存(input buffer
)被移出队列,MediaCodec
就转入Running
子状态,这种状态占据了MediaCodec
的大部分生命周期。通过调用stop()方法转移到Uninitialized
状态;End of Stream
,将一个带有end-of-stream
标记的输入buffer
入队列时,MediaCodec
将转入End-of-Stream
子状态。在这种状态下,MediaCodec
不再接收之后的输入buffer
,但它仍然产生输出buffer
直到end-of-stream
标记输出
Released
,当使用完MediaCodec
后,必须调用release()
方法释放其资源。调用release()
方法进入最终的Released
状态;
基本API
实例创建API
createByCodecName
,知道组件的确切名称是可以采用此方法创建MediaCodec
,一般很少使用(关于支持的组件,可以通过android.media.MediaCodecList
来获取);createDecoderByType
/createEncoderByType
,根据mime type
来创建指定用于的解码和编码的MediaCodec
实例,通常采用的时这个方法来构造MediaCodec
实例;
生命周期相关API
configure
,调用之后一般进入Configured
状态start
,调用之后,进入Flushed
状态,此时MediaCodec会拥有所有的缓存,注意这个时候MediaCodec
还没有真正的工作;flush
,在Executing
的三个子状态时调用该方法,可以使MediaCodec
进入Flushed
状态;stop
,中断Encode
和Decode
处理,但MediaCodec
仍处于活跃状态,重新configure
,然后调用start
后又可以愉快的工作了。注意,不能再release
之后调用;reset
,处于Excuting
状态时,调用该方法,可以使MediaCodec
回到Uninitialized
状态,该方法一般在发生错误后需要重置时调用;release
,在需要释放掉资源的时候,调用该方法(release
,资源已被释放,不在在调用改变生命周期的API,否则会抛出IllegalStateException
)注意:上面的方法都有对应的native实现,核心实现是有C完成的
buffer处理的相关API
dequeueInputBuffer
:从输入流队列中取数据进行编码操作。queueInputBuffer
:输入流入队列。dequeueOutputBuffer
:从输出队列中取出编码操作之后的数据。releaseOutputBuffer
:处理完成,释放ByteBuffer数据。getInputBuffers
:获取需要编码数据的输入流队列,返回的是一个ByteBuffer
数组。getOutputBuffers
:获取编解码之后的数据输出流队列,返回的是一个ByteBuffer
数组。