Android MediaCodec

article/2025/10/6 19:05:52

Android中可以使用MediaCodec来访问底层的媒体编解码器,可以对媒体进行编/解码。

MediaCodec可以处理的数据有以下三种类型:压缩数据、原始音频数据、原始视频数据。这三种类型的数据均可以利用ByteBuffers进行处理,但是对于原始视频数据应提供一个Surface以提高编解码器的性能。Surface直接使用native视频数据缓存,而没有映射或复制它们到ByteBuffers,因此,这种方式会更加高效。


MediaCodec采用异步方式处理数据,并且使用了一组输入输出缓存(ByteBuffer)。通过请求一个空的输入缓存(ByteBuffer),向其中填充满数据并将它传递给编解码器处理。编解码器处理完这些数据并将处理结果输出至一个空的输出缓存(ByteBuffer)中。使用完输出缓存的数据之后,将其释放回编解码器。

MediaCodec的生命周期有三种状态:停止态-Stopped、执行态-Executing、释放态-Released,停止状态(Stopped)包括了三种子状态:未初始化(Uninitialized)、配置(Configured)、错误(Error)。执行状态(Executing)会经历三种子状态:刷新(Flushed)、运行(Running)、流结束(End-of-Stream):


     当创建了一个MediaCodec对象,此时MediaCodec处于Uninitialized状态。首先,需要使用configure(…)方法对MediaCodec进行配置,这时MediaCodec转为Configured状态。然后调用start()方法使其转入Executing状态。在Executing状态可以通过上述的缓存队列操作处理数据。


     Executing状态包含三个子状态: Flushed、 Running 以及End-of-Stream。在调用start()方法后MediaCodec立即进入Flushed子状态,此时MediaCodec会拥有所有的缓存。一旦第一个输入缓存(input buffer)被移出队列,MediaCodec就转入Running子状态,这种状态占据了MediaCodec的大部分生命周期。当你将一个带有end-of-stream marker标记的输入缓存入队列时,MediaCodec将转入End-of-Stream子状态。在这种状态下,MediaCodec不再接收之后的输入缓存,但它仍然产生输出缓存直到end-of- stream标记输出。你可以在Executing状态的任何时候通过调用flush()方法返回到Flushed子状态。
 

      通过调用stop()方法使MediaCodec返回到Uninitialized状态,因此这个MediaCodec可以再次重新配置 。当使用完MediaCodec后,必须调用release()方法释放其资源。
 

      在极少情况下MediaCodec会遇到错误并进入Error状态。这个错误可能是在队列操作时返回一个错误的值或者有时候产生了一个异常导致的。通过调用 reset()方法使MediaCodec再次可用。你可以在任何状态调用reset()方法使MediaCodec返回到Uninitialized状态。否则,调用 release()方法进入最终的Released状态。

 

1)MediaCodec的使用相对MediaExtractor和MediaMuxer来说要复杂一些,首先是创建一个新的MediaCodec对象然后调用configure(...)方法对MediaCodec进行配置:
String AUDIO_MIME = "audio/mp4a-latm";
MediaCodec mAudioEncoder = MediaCodec.createEncoderByType(AUDIO_MIME);
MediaFormat mAudioMediaFormat = new MediaFormat();
mAudioMediaFormat.setString(MediaFormat.KEY_MIME, AUDIO_MIME);
mAudioMediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 32000);
mAudioMediaFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 2);
mAudioMediaFormat.setInteger(MediaFormat.KEY_SAMPLE_RATE, 48000);
mAudioMediaFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, BUFFER_SIZE_IN_BYTES);
mAudioMediaFormat.setInteger(MediaFormat.KEY_AAC_PROFILE,
MediaCodecInfo.CodecProfileLevel.AACObjectLC);
mAudioEncoder.configure(mAudioMediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);


2)接着调用MediaCodec的start()方法,此时MediaCodec处于Executing状态,可以通过getInputBuffers()方法和getOutputBuffers()方法获取缓存队列:

mAudioEncoder.start();
mAudioInputBuffers = mAudioEncoder.getInputBuffers();
mAudioOutputBuffers = mAudioEncoder.getOutputBuffers();

 

3)当MediaCodec处于Executing状态之后就可以对数据进行处理了。首先通过dequeueInputBuffer(long timeoutUs)请求一个输入缓存,timeoutUs代表等待时间,设置为-1代表无限等待:
int inputBufIndex = mAudioEncoder.dequeueInputBuffer(1000);

 

4)返回的整型变量为请求到的输入缓存的index,通过getInputBuffers()得到的是输入缓存数组,通过index和输入缓存数组可以得到当前请求的输入缓存,在使用之前要clear一下,避免之前的缓存数据影响当前数据:
mInputBuffer = mAudioInputBuffers[inputBufIndex];
mInputBuffer.clear();

 

5)接着就是把数据添加到输入缓存中,并调用queueInputBuffer(...)把缓存数据入队:
mInputBuffer.put(bytes, 0, BUFFER_SIZE_IN_BYTES);
mAudioEncoder.queueInputBuffer(inputBufIndex, 0, BUFFER_SIZE_IN_BYTES, (1000000 * mEncodedSize / AUDIO_BYTE_PER_SAMPLE), 0);

 

6)获取输出缓存和获取输入缓存类似,首先通过dequeueOutputBuffer(BufferInfo info, long timeoutUs)来请求一个输出缓存,这里需要传入一个BufferInfo对象,用于存储ByteBuffer的信息:
int outputBufIndex = mAudioEncoder.dequeueOutputBuffer(mOutBufferInfo, 1000);

 

7)然后通过返回的index得到输出缓存,并通过BufferInfo获取ByteBuffer的信息,通过BufferInfo我们可以得到当前数据是否Codec-specific Data:
mOutBuffer = mAudioOutputBuffers[outputBufIndex];
if ((mOutBufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
    // Codec-specific Data, 这里可以从ByteBuffer中获取csd参数
    // audioFormat.setByteBuffer("csd-0", mOutBuffer);
} else {
    // 处理数据
}
mAudioEncoder.releaseOutputBuffer(outputBufIndex, false);

 

8)使用完MediaCodec后释放资源:
mAudioEncoder.stop();
mAudioEncoder.release();


作者:郑旭泽
链接:http://www.jianshu.com/p/30e596112015
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


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

相关文章

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…

软件测试面试,如何自我介绍?如何介绍项目?如何介绍个人技术?(提供面试话术)

前准备不足而导致面试失败那可就亏大了!为了提高面试成功率,帮助大家尽快拿到高薪offer,我们盘点了面试环节必问的三类问题,希望对即将参加软件测试面试的小伙伴们有所帮助。 01 如何自我介绍 面试过程中一定要放慢语速&#xf…

软件测试面试,如何自我介绍?

01 如何自我介绍 面试过程中一定要放慢语速,做到条理清晰。特别是做自我介绍时,可以适当多介绍自己会什么,有哪些重要经验。 例如: 面试官,上午/下午好。 我是XXX,今天来面试贵公司的软件测试工程师岗位&a…