目标
- 了解 - 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数组。