目标
了解
MediaCodecAPI的基本使用,熟悉使用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数组。