Android:MediaCodec基本原理

article/2025/10/6 18:30:54

最近需要使用MediaCodec做一些工作,因此对MediaCodec做了些研究和代码编写,在此先对MediaCodec的一些基础原理、工作流程、常用API等做个初步总结,方便后续开发过程中查阅。


1.MediaCodec简介

1.1 MediaCodec来历

Android从最初的API 1.0版本开始,集成了一种使用起来比较简单,用于播放音视频文件,但是只支持MP4、3GPP两种媒体格式的MediaPlayer,为了播放不支持的格式,许多开发人员不得不在开发过程中集成FFmpeg软件解码器

Android 4.1(API16),MediaCodec首个版本推出,开发者在应用层就能直接调用底层编解码器,实现丰富的音视频功能

Android 4.3(API18),MediaCodec引入Surface和OpenGLES,可以用OpenGLES对数据进行渲染,使用摄像头的预览数据作为输入

Android 5.0,API21,引入了异步模式,MediaCodec可以对输入数据和输出数据进行异步处理

1.2 MediaCodec是什么?

MediaCodec对应用端提供Java Api,其内部则通过调用各native方法实现对Android底层多媒体编解码器的调用,完成上层应用对音视频文件的编码和解码

开发者用到的是MediaCodec.java,它是android.media框架中的一个类

MediaCodec.java 位于Android源码:/frameworks/base/media/java/android/media/

谷歌developer网站上关于MediaCodec的详细注解:

MediaCodec  |  Android Developers

1.3 android.media

android.media框架是Framework中的多媒体管理模块,它并不是紧密耦合的单个模块,而是多个media相关功能组件的联合

AndroidN之前,framework中android.media的所有模块(包括播放、录制、camera、audio等)都在mediaserver进程中

AndroidN开始,出于安全性考虑(“stagefright安全漏洞“),mediaserver拆分为以下几个进程:
1)mediaserver:包括播放功能Mediaplayer和录制功能Mediarecoder;
2)mediacodec:音视频编解码功能;
3)mediaextractor:视频文件解封装;
4)cameraserver:相机服务;
5)audioserver:音频输出模块;
6)mediadrm:数字版权加解密;

也就是说MediaCodec是Android Media框架下,从MediaServer拆分出来的一个专门用于音视频编解码的进程 


2.MediaCodec工作机制

2.1 关联功能类

MediaCodec.java只是Framework中android.media里的一个类,在使用MediaCodec Java API对音视频文件进行编解码时,需要联合其他media功能文件一起使用,这一点在谷歌的官方注解网站里也有说明

常用的联合使用的功能类主要有如下:

 android.media.MediaExtractor;
 android.media.MediaSync;
 android.media.MediaMuxer;
 android.media.MediaFormat;
 android.media.MediaCrypto;
 android.media.MediaDrm;
 android.media.MediaCodec.BufferInfo;
 android.media.Image;
 android.media.AudioTrack;
 android.view.Surface;
 ......

2.2 MediaCodec工作流程

官网注解图:

MediaCodec的工作流程就是:处理输入数据产生输出数据

MediaCodec运行过程中的数据传输,可以看成两路数据流:Input流、Output流
  ● Input流:客户端输入的待编码或解码的数据
  Output流:客户端输出的已编码或解码的数据

MediaCodec使用两组Buffer队列,通过同步异步方式处理两路数据流:
  包含一组InputBuffer(格式ByteBuffer)的InputBufferQueue
  包含一组OutputBuffer(格式ByteBuffer)的OutputBufferQueue

1)Client也就是调用者从MediaCodec的InputBufferQueue中获取空的InputBuffer,写入要编码或解码的数据,提交给MediaCodec

2)MediaCodec收到数据进行处理,处理完毕后,将其转存到OutputBufferQueue中空的OutputBuffer(拷贝过程由mediacodec内部完成,调用者只需要关注OutputBufferQueue中空闲Buffer索引的变化),同时释放InputBuffer,将它重新放回到InputBufferQueue

3)Client从MediaCodec的OutputBufferQueue中获取到一个空的OutputBuffer,读取数据进行使用,待Client处理完数据后,释放OutputBuffer并将其放回OutputBufferQueue

上述过程不断重复
直至MediaCodec将数据处理完毕后,手动释放OutputBuffer

另外需要先注解一下的是:

同步模式:编解码器对Input和Output的数据处理是同步的,
                  数据输入和数据输出依次进行,
                  上一次数据输入后才能输出数据,
                  上一次数据输出后才能再次进行数据输入。

异步模式:编解码器对Input和Output的数据处理是异步的,
                  数据输入和数据输出操作相互独立,
                  底层服务判断何时可以进行输入/输出,然后进行相应回调,
                  开发者在回调中进行数据输入/输出处理。

2.3 MediaCodec Buffer与底层交互

MediaCodec Buffer与底层Acodec,以及OpenMAX标准的交互流程:


3.MediaCodec状态转换

3.1 MediaCodec的几种状态

MediaCodec有三种状态:Stopped、Executing、Released
其中StoppedExecuting状态又分别包含三个子状态

所以MediaCodec状态可以细分为如下:
1) 停止态(Stopped):
      1.1) 未初始化状态(Uninitialized
      1.2) 配置状态(Configured
      1.3) 错误状态(Error

2) 执行态(Executing):
      2.1) 刷新状态(Flushed
      2.2) 运行状态( Running
      2.3) 流结束状态(End-of-Stream

3) 释放态(Released)

MediaCodec在不同的数据处理模式下状态间的转换会有些许差别,
接下来我们分别对同步模式异步模式下的状态转换做一些分析

3.2 同步模式下的状态转换

官网示图:


 

1) createDecoderByType(...) / createEncoderByType(...) / createByCodecName(...)
调用三个方法中的任意一个创建一个MediaCodec对象实例后,
MediaCodec处于Stopped:Uninitialized子状态

2) MediaCodec.configure(...)配置,切换到StoppedConfigured子状态

3) MediaCodec.start()启动,切换到ExecutingFlushed子状态。
MediaCodec此时拥有全部InputBuffer和OutputBuffers的所有权,Client无法操作这些Buffers,
但是MediaCodec在Flush状态下并不进行任何内部数据传送和编解码处理

4) MediaCodec.dequeueInputBuffer()请求到一个有效的InputBuffer Index, 第一个InputBuffer出队列时,
MediaCodec立即进入到了Executing:Running子状态

5) Executing:Running状态下,MediaCodec进行数据处理(解码、编码)工作,完成生命周期的主要阶段

6) MediaCodec.queueInputBuffer(... , MediaCodec.BUFFER_FLAG_END_OF_STREAM)被调用,输入端带有"End-Of-Stream"标记的InputBuffer加入InputBufferQueue,MediaCodec随即进入Executing:End of Stream子状态,且不再接受新的InputBuffer数据,
但是仍然会处理完之前InputBufferQueue中未处理的InputBuffer并产生OutputBuffer,直到"End-Of-Stream"标记到达输出端,数据处理的过程也随即终止

7) Executing状态下,MediaCodec.flush(),切换到Executing:Flushed子状态

8) Executing状态下,MediaCodec.stop()MediaCodec.reset(),切换到Stopped:Uninitialized子状态

9) MediaCodec运行出错时会切换到Stopped:Error状态,可以调用MediaCodec.reset()进行重置,使其再次可用

10) MediaCodec数据处理任务完成或不再需要使用MediaCodec时,MediaCodec.release()方法释放其资源,MediaCodec切换到Released状态

3.3 异步模式下的状态转换

官网示图:

异步模式下状态转换与同步模式下大同小异,主要有两点区别

1) MediaCodec.start()启动,会直接切换到Executing:Running子状态;

2) MediaCodec.flush()切换到Executing:Flushed子状态后,必须调用MediaCodec.start()才能切换回Executing:Running子状态。

其他情况下均与同步模式下相同,就不在此赘述


4.MediaCodec主要API和数据格式:

4.1 主要API:

编解码器创建和配置:
createDecoderByType():根据特定mime类型(如"video/avc")创建编解码器(MediaCodec实例)
createEncoderBytype(): 同上
createByCodecName:根据组件的确切名称(如OMX.google.mp3.decoder)创建编解码器,使用MediaCodecList可以获取组件的名称
configure():对编解码器进行配置,使编解码器切换到Stopped:Configured状态

常见的mime类型多媒体格式如下:
● “video/x-vnd.on2.vp8” - VP8 video (i.e. video in .webm)
● “video/x-vnd.on2.vp9” - VP9 video (i.e. video in .webm)
● “video/avc”                  - H.264/AVC video
● “video/mp4v-es”          - MPEG4 video
● “video/3gpp”                - H.263 video
● “audio/3gpp”                - AMR narrowband audio
● “audio/amr-wb”            - AMR wideband audio
● “audio/mpeg”               - MPEG1/2 audio layer III
● “audio/mp4a-latm”       - AAC audio (note, this is raw AAC packets, not packaged in LATM!)
● “audio/vorbis”              - vorbis audio
● “audio/g711-alaw”       - G.711 alaw audio
● “audio/g711-mlaw”      - G.711 ulaw audio

编解码器状态控制:
start():编码器启动,切换到ExecutingFlushed状态
stop():编码器结束,返回到Stopped:Uninitialized状态
release():释放实例资源

Surface创建和配置:
createInputSurface():创建输入缓冲Surface
setOutputSurface():设置输出缓冲Surface

Buffer操作:
getInputBuffers():获取InputBufferQueue,返回ByteBuffer[ ]
dequeueInputBuffer():从InputBufferQueue中取InputBuffer
queueInputBuffer():Client往InputBuffer写入数据后,将InputBuffer加入到InputBufferQueue
getOutputBuffers():获取OutputBufferQueue,返回ByteBuffer[ ]
dequeueOutputBuffer():从OutputBufferQueue中取OutputBuffer
releaseOutputBuffer():释放ByteBuffer数据

4.2 数据类型和载体

1) Mediacodecde的数据流有两种载体:ByteBuffer和Surface

    ● 使用ByteBuffer作为数据载体时,可以用Image类和getInput/OutputImage(int)获取原始视频帧

    ● 使用Surface来获取/呈现原始的视频数据时,Surface使用本地的视频Buffer,不需要进行ByteBuffers拷贝,编解码器的效率更高

    ● 通常在使用Surface的时候,无法访问原始的视频数据,但是可以使用ImageReader访问解码后的原始视频帧

2) Mediacodec接受三种数据类型:

2.1)压缩数据:
压缩数据可以作为解码器的输入、编码器的输出,
但是需要指定数据格式,这样MediaCodec才知道如何处理这些压缩数据.

压缩数据支持的格式有:
   ● MediaFormat.KEY_MIME支持的所有格式类型
   ● 对于视频类型,通常是一个单独的压缩视频帧
   ● 对于音频数据,通常是一个单独的访问单元

无论是视频还是音频,buffer都不会在任意字节边界上开始或结束,而是在帧/访问单元边界上开始或结束,除非它们被BUFFER_FLAG_PARTIAL_FRAME标记

2.2)原始音频数据:PCM音频数据帧

原始音频Buffer包含PCM音频数据的整个帧,这是每个通道按通道顺序的一个样本。
每个样本都是一个 AudioFormat#ENCODING_PCM_16BIT

2.3)原始视频数据:
在ByteBuffer模式下,视频buffer根据它们的MediaFormat#KEY_COLOR_FORMAT进行布局.
可以从getCodecInfo(). MediaCodecInfo.getCapabilitiesForType.CodecCapability.colorFormats获取支持的颜色格式。

视频编解码器支持三种颜色格式:   
   ● native raw video format:CodecCapabilities.COLOR_FormatSurface,
                                                  可以与输入/输出的Surface一起使用

   ● flexible YUV buffers:例如CodecCapabilities.COLOR_FormatYUV420Flexible,
                                           可以使用getInput/OutputImage(int)与输入/输出Surface一起使用,
                                           也可以在ByteBuffer模式下使用

   ● other,specific formats:通常只支持ByteBuffer模式;
                                               有些颜色格式是厂商特有的,其他定义在CodecCapabilities;
                                               对于等价于flexible格式的颜色格式,可以使用getInput/OutputImage(int);


5.结语

MediaCodec的基本原理就先介绍到这里,本篇主要是理论讲解,先对MediaCodec的运用有个初步的认知,暂未涉及实践开发和Demo代码演示,后续博文会逐步跟进。

关于MediaCodec,网上优秀的资料和博文也很多,在学习MediaCodec过程中查阅了大量资料,
链接就不一一列举了,其中主要优秀博文链接有:

MediaCodec基本原理及使用_有心好书的博客-CSDN博客_mediacodecMediaCodec的使用介绍 - 简书
MediaCodec基础入门_Kayson12345的博客-CSDN博客
Android MediaExtractor + MediaCodec 实现简易播放器 - 简书
Android MediaCodec 状态(States)转换分析 - 二的次方 - 博客园


http://chatgpt.dhexx.cn/article/AJG0lxJk.shtml

相关文章

MediaCodec原理及使用

使用MediaCodec目的 MediaCodec是Android底层多媒体框架的一部分,通常与MediaExtractor、MediaMuxer、AudioTrack结合使用,可以编码H264、H265、AAC、3gp等常见的音视频格式 MediaCodec工作原理是处理输入数据以产生输出数据 MediaCodec工作流程 Medi…

Android MediaCodec

Android中可以使用MediaCodec来访问底层的媒体编解码器,可以对媒体进行编/解码。 MediaCodec可以处理的数据有以下三种类型:压缩数据、原始音频数据、原始视频数据。这三种类型的数据均可以利用ByteBuffers进行处理,但是对于原始视频数据应提…

android P MediaCodec编解码流程分析

1.MediaCodec初始化流程分析 通过上面流程分析可知,MediaCodecList初始化是通过调用它的getLocalInstance函数,然后在里面new的MediaCodecList对象。在MediaCodec的CreateByType函数中new了MediaCodec对象。 allocateNode调用流程是在ACodec.cpp中的onA…

MediaCodec_Analyze-3-start

MediaCodec Analyse – start Refrence: https://source.android.google.cn/devices/media 一 APK调用的核心API Android APK使用 MediaCodec API 播放音视频的简易流程: MediaCodec codec MediaCodec.createDecoderByType("video/avc"); MediaFormat …

mediacodec api

mediacodec api 官网: https://developer.android.com/reference/android/media/MediaCodec 中文: https://www.apiref.com/android-zh/android/media/MediaCodec.html 学习mediacodec api的使用说明,在android源码查看: andro…

MediaCodec硬解流程

一 MediaCodec概述 MediaCodec 是Android 4.1(api 16)版本引入的低层编解码接口,同时支持音视频的编码和解码。通常与MediaExtractor、MediaMuxer、AudioTrack结合使用,能够编解码诸如H.264、H.265、AAC、3gp等常见的音视频格式。MediaCodec在编解码的过…

MediaCodec_Analyze-1-create

MediaCodec Analyse – create Refrence: https://source.android.google.cn/devices/media 一 APK调用的核心API Android APK使用 MediaCodec API 播放音视频的简易流程: MediaCodec codec MediaCodec.createDecoderByType("video/avc"); MediaFormat…

mediacodec

MedaiCodec简介 MediaCodec是Android中提供的音视频编/解码工具。它主要是完成上层接口的封装,供给开发者使用,编解码功能实际是在native底层服务中完成的 MediaCodec工作流程 包括两个缓冲区队列 一个输入缓冲区队列,包含一组输入缓冲区(格…

Android MediaCodec 完全解析

MediaCodec是什么? MediaCodec类为开发者提供了能访问到Android底层媒体Codec(Encoder/Decoder)的能力,它是Android底层多媒体基础架构的一部分(通常和MediaExtractor、MediaSync、MediaMuxer、MediaCrypto、MediaDrm…

Android MediaCodec解析

Android MediaCodec解析 1 引言 MediaCodec是Android平台提供的一个底层的音视频编解码框架,它是安卓底层多媒体基础框架的重要组成部分。它经常和 MediaExtractor, MediaSync, MediaMuxer, MediaCrypto, MediaDrm, Image, Surface, AudioTrack一起使用。解码的作…

Android原生编解码接口MediaCodec详解

作者:躬行之 了解了音视频的相关知识,可以先阅读同系列文章: 音视频开发基础知识音频帧、视频帧及其同步Camera2、MediaCodec录制mp4 MediaCodec 是 Android 中的编解码器组件,用来访问底层提供的编解码器,通常与 Me…

MediaCodec视频解码流程详解及参考demo

一、MediaCodec简介 MediaCodec是Android自带的底层多媒体支持架构的一部分(通常与 MediaExtractor,MediaSync,MediaMuxer,MediaCrypto,MediaDrm,Image,Surface 和 AudioTrack 一起使用&#xf…

Android MediaCodec简单总结

#.MedaiCodec简介 MediaCodec是Android中提供的音视频编码、解码工具。它主要是完成上层接口的封装,提供给开发者使用,编解码功能实际是在native底层服务中完成的。 #.MediaCodec工作的宏观流程: ##.包换两个缓冲区队列 一个输入缓冲区队列&a…

软件测试面试指导之自我介绍

面试自我介绍虽然人人都准备,但是做到让人印象深刻可不容易啊。 本篇就具体来聊聊人人都要经历的面试,怎么做自我介绍,才能让你在面试官的眼睛里像金子一样闪闪发光? 面试是什么? 它是个机会,让面试官更…

软件测试面试要注意的细节以及处理(自我介绍篇)

面试问题第一问,95%都会是: 请简单的做个自我介绍吧~ 分以下几点说明。 一、个人的基本信息,扬长避短 1、年纪太大与太小,都不需要主动去说明。 比如我年纪只有21岁 例子:面试官您好,我叫***&#xff…

【软件测试】企业测试面试题9道,从自我介绍到项目考察+回答......

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 1、自我介绍 您好…

软件测试面试怎样介绍自己的项目?会问到什么程度?

最近收到很多粉丝的私信说找不到工作,简历投了百十来份,邀约都没几个,更别说offer了,是不是软件测试要黄了? 说句实话,现在大环境确实不好,互联网大厂裁员这是摆在明面上的原因。时代的一粒沙&…

软件测试面试怎样介绍自己的测试项目?会问到什么程度?

想知道面试时该怎样介绍测试项目?会问到什么程度?那就需要换位思考,思考HR在这个环节想知道什么。 HR在该环节普遍想获得的情报主要是下面这2个方面: 1)应聘者的具体经验和技术能力, 2)应聘者的…

【软件测试】面试中介绍项目你该这么说!

黑马程序员视频库 播妞微信号:heiniu526 传智播客旗下互联网资讯、学习资源免费分享平台 测试人员在找工作的过程中,通常有一个问题是很难绕开的。就是要如何向别人介绍自己之前做过的项目。下面我们就这个问题简单的做一些分析。 大体上可以分为如下几个…

软件测试面试自我介绍/项目介绍居然还有模板?我要是早点发现就好了

目录 1、自我介绍 2、项目介绍 2.1、最全电商项目介绍 2.2、电商项目介绍 2.3、在线教育项目介绍 2.4、互联网金融项目介绍 总结 1、自我介绍 以XXX简历来举例(参照下面的案例,编写你的自我介绍,框架就是:我是谁&#xff0…