Android音频开发(六)音频编解码之初识MediaCodec上

前五篇我们介绍了关于音频的基础知识,今天来讲述一下音频的重点和难点部分,这一节依然是分上下俩个节点,深入讲述Android音频开发的编解码技术。

1.MediaCodec 介绍

MediaCodeC是Android 4.1(API16 ) 版本加入的一个新的音视频处理API,旨在提高Android平台的音视频编码能力,Mediacodec类可用于访问底层的媒体编解码器,即编码器/解码器组件。这是Android底层的多媒体支持基础设施的一部分(通常与 MediaExtractor, MediaSync, MediaMuxer,MediaCrypto, MediaDrm, Image, Surface, AudioTrack)。Android 应用层统一由 MediaCodec API 提供音视频编解码的功能,由参数配置来决定采用何种编解码算法、是否采用硬件编解码加速等。由于使用硬件编解码,兼容性有不少问题,据说 MediaCodec 坑比较多。

MediaCodec 采用了基于环形缓冲区的「生产者-消费者」模型,异步处理数据。在 input 端,Client 是这个环形缓冲区「生产者」,MediaCodec 是「消费者」。在 output 端,MediaCodec 是这个环形缓冲区「生产者」,而 Client 则变成了「消费者」。

2.MediaCodec 的工作流程

mediacodec的工作流程图如下:
在这里插入图片描述MediaCodeC 状态机:
在这里插入图片描述
简化一下工作流程如下:

  1. Client 从 input 缓冲区队列申请 empty buffer [dequeueInputBuffer]

  2. Client 把需要编解码的数据拷贝到 empty buffer,然后放入 input 缓冲区队列 [queueInputBuffer]

  3. MediaCodec 从 input 缓冲区队列取一帧数据进行编解码处理

  4. 处理结束后,MediaCodec 将原始数据 buffer 置为 empty 后放回 input 缓冲区队列,将编解码后 的数据放入到 output 缓冲区队列

  5. Client 从 output 缓冲区队列申请编解码后的 buffer [dequeueOutputBuffer]

  6. Client 对编解码后的 buffer 进行渲染/播放

  7. 渲染/播放完成后,Client 再将该 buffer 放回 output 缓冲区队列 [releaseOutputBuffer]

所根据mediacodec的工作流程可以大概归纳出MediaCodec 基本使用流程:

- createEncoderByType/createDecoderByType
- configure
- start
- while(true) {
    
    
    - dequeueInputBuffer
    - queueInputBuffer
    - dequeueOutputBuffer
    - releaseOutputBuffer
}
- stop
- release

3.使用MediaCodeC注意事项

  1. MediaCodeC是4.1(API16)才开始引入的,后续的几个版本中API都有不断更改,(大部分核心API会发现标记为过时,需要更换新的版本) ,比如,在 5.0后加入了异步模式,5.0以下是同步获取的,5.0以下需要准备一个缓冲区不断的刷新请求MediaCodeC获取解码后的数据.

  2. 众所周知,Google并没有预制很多解码器,相反,解码器都是后期手机厂商自己register进去的,MediaCodeC只提供抽象的接口,具体实现在各个手机上,当然,Android源码里面引入了一套AAC编码器(因为AAC是开放标准的 ),而大家常用的MP3是有版权的,所以原生MediaCodeC无法编码MP3,除非厂商提供MP3编码器)

  3. MediaCodeC适用于音视频编/解码,其底层最后调用的是 OpenGL ES,最终调用手机 GPU 进行工作,是 Android 提供给我们的一种音视频编解码高级 API,所以编/解码效率跟手机CPU 有很大的关系,经多台测试机调查得知,高通的 CPU 明显有优势,同时,手机性能有限,编/解码需要耗费大量的内存及 cpu 时间。

介于上面这三点原因,如果我们想使用mediacodec,那么我们就要知道我们的手机厂商使用了那些解码器,只有如此,才能对症下药。

那么如何查看自己的手机自带那些解码器了,方法如下:

在我们手机system/etc/目录下,有一个media_codecs.xml文件,里面记录了手机厂商在出厂时配置的音视频软、硬件解码库及其支持的媒体编码格式。我们可以使用MediaCodecList相关的api来查看是否支持

如果你的手机是Android 5.0(API16)以上,你可以这样获取:

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private fun checkMediaDecoder() {
    
    
        val mediaCodecList = MediaCodecList(MediaCodecList.ALL_CODECS)
        val codecInfos: Array<MediaCodecInfo> = mediaCodecList.getCodecInfos()
        for (codecInfo in codecInfos) {
    
    
            Log.i("TAG", "codecInfo =" + codecInfo.getName())
        }
    }

我运行一下测试方法,看一下后台输出的日志信息,我这里用的是rk3399的开发主板,信息如下:

2021-03-09 11:49:55.598 12178-12178/com.pcl.ocr I/TAG: codecInfo =OMX.google.mp3.decoder
2021-03-09 11:49:55.598 12178-12178/com.pcl.ocr I/TAG: codecInfo =OMX.google.amrnb.decoder
2021-03-09 11:49:55.598 12178-12178/com.pcl.ocr I/TAG: codecInfo =OMX.google.amrwb.decoder
2021-03-09 11:49:55.598 12178-12178/com.pcl.ocr I/TAG: codecInfo =OMX.google.aac.decoder
2021-03-09 11:49:55.598 12178-12178/com.pcl.ocr I/TAG: codecInfo =OMX.google.g711.alaw.decoder
2021-03-09 11:49:55.598 12178-12178/com.pcl.ocr I/TAG: codecInfo =OMX.google.g711.mlaw.decoder
2021-03-09 11:49:55.598 12178-12178/com.pcl.ocr I/TAG: codecInfo =OMX.google.vorbis.decoder
2021-03-09 11:49:55.598 12178-12178/com.pcl.ocr I/TAG: codecInfo =OMX.google.opus.decoder
2021-03-09 11:49:55.598 12178-12178/com.pcl.ocr I/TAG: codecInfo =OMX.google.raw.decoder
2021-03-09 11:49:55.598 12178-12178/com.pcl.ocr I/TAG: codecInfo =OMX.google.aac.encoder
2021-03-09 11:49:55.598 12178-12178/com.pcl.ocr I/TAG: codecInfo =OMX.google.amrnb.encoder
2021-03-09 11:49:55.598 12178-12178/com.pcl.ocr I/TAG: codecInfo =OMX.google.amrwb.encoder
2021-03-09 11:49:55.598 12178-12178/com.pcl.ocr I/TAG: codecInfo =OMX.google.flac.encoder
2021-03-09 11:49:55.598 12178-12178/com.pcl.ocr I/TAG: codecInfo =OMX.rk.video_decoder.avc
2021-03-09 11:49:55.598 12178-12178/com.pcl.ocr I/TAG: codecInfo =OMX.rk.video_decoder.m2v
2021-03-09 11:49:55.598 12178-12178/com.pcl.ocr I/TAG: codecInfo =OMX.rk.video_decoder.vp8
2021-03-09 11:49:55.598 12178-12178/com.pcl.ocr I/TAG: codecInfo =OMX.rk.video_decoder.h263
2021-03-09 11:49:55.598 12178-12178/com.pcl.ocr I/TAG: codecInfo =OMX.rk.video_decoder.m4v
2021-03-09 11:49:55.598 12178-12178/com.pcl.ocr I/TAG: codecInfo =OMX.rk.video_decoder.hevc
2021-03-09 11:49:55.598 12178-12178/com.pcl.ocr I/TAG: codecInfo =OMX.rk.video_decoder.vp9
2021-03-09 11:49:55.598 12178-12178/com.pcl.ocr I/TAG: codecInfo =OMX.rk.video_encoder.avc
2021-03-09 11:49:55.599 12178-12178/com.pcl.ocr I/TAG: codecInfo =OMX.google.h264.decoder
2021-03-09 11:49:55.599 12178-12178/com.pcl.ocr I/TAG: codecInfo =OMX.google.hevc.decoder
2021-03-09 11:49:55.599 12178-12178/com.pcl.ocr I/TAG: codecInfo =OMX.google.vp8.decoder
2021-03-09 11:49:55.599 12178-12178/com.pcl.ocr I/TAG: codecInfo =OMX.google.vp9.decoder
2021-03-09 11:49:55.599 12178-12178/com.pcl.ocr I/TAG: codecInfo =OMX.google.h263.encoder
2021-03-09 11:49:55.599 12178-12178/com.pcl.ocr I/TAG: codecInfo =OMX.google.mpeg4.encoder
2021-03-09 11:49:55.599 12178-12178/com.pcl.ocr I/TAG: codecInfo =OMX.google.vp8.encoder

你会发现,厂家内置的编解码还是挺多的,具体是用哪一种,就更具自己的实际情况来定义。

4.总结

关于MediaCodec的工作流程已经介绍完毕了,在接下来我将着重讲解如何利用MediaCodec实现真正意义上的编解码。

音频开发的知识点还是很多的,学习音频开发需要大家有足够的耐心,一步一个脚印的积累,只有这样才能把音频开发学好。下面推荐几个比较好的博主,希望对大家有所帮助。

猜你喜欢

转载自blog.csdn.net/ljx1400052550/article/details/114578269