Android 音视频基础——Android MediaCodec API学习

目标

简介

两张图,一张是MediaCodec处理的流程图,一张是MediaCodec生命周期图,如下:

处理流程图

MidiaCodec处理流程图

简单来说,就是客户端从MediaCodec请求一段内存空间,用来填充数据,填充好后,交给MediaCodec处理,处理完毕后,MediaCodec讲处理结果填充到自己分配一段空内存中,然后由客户端自己去拉取。

  • 用来进行数据填充的内存空间,在MediaCodec中由ByteBuffer来实现;
  • 提交给MediaCodec处理由一个BufferMapHashMap的简单封装实现)来实现,代码对应于mDequeuedInputBuffers,相应的操作方法是queueInputBufferdequeueInputBuffer
  • 从MediaCodec拉取处理结果由一个BufferMapHashMap的简单封装实现)来实现,代码对应于mDequeuedOutputBuffers, 相应的操作方法是dequeueOutputBuffer

生命周期图

MediaCodec生命周期图

从上图可以看出,MediaCodec共三种大状态:

  • Stopped,分三种子状态:
    • ConfiguredMediaCodec实例创建后,调用configure方法后就进入了Configured状态
    • UninitializedMediaCodec实例被创建后,在调用configure方法前都处于该状态;
    • ErrorMediaCodec遇到错误时进入该状态,通常可能是队列操作返回错误或异常导致的;
  • 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,中断EncodeDecode处理,但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数组。

MediaCodec使用

硬解与软解

硬解

软解

硬解与软解的优劣

硬解密AAC

硬解码H.264

参考文章:https://www.jianshu.com/p/f5a1c9318524