【学习】从零开始的Android音视频开发(12)——MediaCodec基本认识、从创建到Start过程

Android音视频 - MediaCodec编解码音视频 前情提要 MediaCodec 阅读详情

MediaCodec相关知识

在Android中还可以通过MediaCodec播放视频

MediaCodec基本认识

MediaCodec是什么

MediaCodec类可以访问底层媒体编解码框架(StageFright或OMX),即编解码组件。这时Android low-level多媒体支持基础设施的一部分(通常与MediaExtractor、MediaSync、MediaMuxer、MediaCrypto、MediaDrm、Image、Surface和AudioTrack一起使用)。它本身不是Codec,它通过调用底层编解码组件获得了Codec的能力

创建MediaCodec的方式

创建MediaCodec(按格式创建)
1.MediaCodec createDecoderByType(String type):创建解码器
2.MediaCodec createEncoderByType(String type):创建编码器
3.type:数据解析阶段的mimeType,如video/avc

创建MediaCodec(按Codec名字创建)
1.MediaCodec createByCodecName(String name)
2.OMX.google.h264.decoder:软解码
3.OMX.MTK.VIDEO.DECODER.AVC:硬解码

MediaCodec的工作方式

在这里插入图片描述

MediaCodec处理输入数据产生输出数据。当异步处理数据时,使用一组输入和输出Buffer队列。在逻辑上,客户端请求或接受数据后填入预先设定的空输入缓冲区,输入Buffer填满数据后将其传递到MediaCodec并进行编解码处理。之后MediaCodec编解码后的数据被填充到一个输出Buffer中。最后客户端请求或接收输出Buffer,消耗输出Buffer中的内容,用完后释放,给回MediaCodec重新填充输出数据

注意必须要保证输入和输出队列同时非空,即至少持有一个输入Buffer和输出Buffer才能工作

1.MediaCodec读取输入Buffer的数据,进行解码或编码,将处理完的数据填入输出Buffer
2.MediaCodec处理完一个输入Buffer的数据,将此Buffer移入客户端队列,客户端可以继续使用
3.MediaCodec将填充的输出Buffer放入客户端队列,客户端可以取出数据进行播放

MediaCodec状态周期图

在这里插入图片描述

在MediaCodec的生命周期内存在3种状态,即Stopped、Executing和Released。Stopped状态实际上还可处于3种子状态,即Uninitialized、Configured和Error,而Executing状态概念上的进展通过3个子状态进行,即Flushed、Running、End-of-Stream。

当使用工厂方法创建一个MediaCodec时,其处于未初始化状态。首先要通过configure(...)配置它,让其处于配置状态,然后调用start函数把它转变为Executing状态

在调用start函数后,MediaCodec会立刻刷新子状态,它拥有所有的Buffer。一旦第一个输入Buffer被从列中移除,MediaCodec将花费比较长的时间移动到正在运行的子状态上。当队列的输入Buffer带有end of stream标记,它会转换到end of stream子状态。这种状态下它不再接受进一步输入Buffer,但仍然生成输出Buffer,直到达到end of stream状态输出。在executing状态的任何时候调用flush函数可以回到flushed状态

调用stop函数返回的MediaCodec处于未初始化状态,因为它可能被再次配置。当再使用一个编解码器(Codec)时必须调用release函数否则会出现资源未被释放的问题。极少数情况下会遇到一个Error状态,可调用reset函数让编解码器再次可用

特定编解码格式数据

我们可以先理解为一些重要编解码信息的载体。在MediaCodec编解码过程中,当遇到AAC音频格式及MPEG-4、H.264/5视频格式时,需要设置大量的Buffer,或者将特定信息载体作为真实数据的开头。在处理这样的压缩格式,进行编解码操作前,调用start函数后,这些载体是编解码的依据,所以要立刻传给MediaCodec。当调用MediaCodec的queueInputBuffer函数时,这些数据必须使用flag:BUFFER_FLAG_CODEC_CONFIG,表明已经配置好,可以进行真正的编解码操作

特定编解码格式数据也可以包含在ByteBuffer条目的格式中传递给配置钥匙"csd-0/1"等。这些钥匙总是包含从MediaExtractor类中获取视频源的格式。当调用start函数时,特定编解码格式数据格式自动提交给编解码器,如果不包含特定编码的数据格式,你可以按照格式要求选择以正确的顺序提交到指定的缓冲区。对于H.264还可以连接所有信息载体数据并提交作为单个编解码配置缓冲区

Android使用下图所示的特定编解码格式数据缓冲区。这些也需要跟踪格式中设置适当的MediaMuxer Track配置。每个参数设置和特定编解码格式数据部分标注(*)必须以"\x00\x00\x00\x01"开始。必须注意在执行start函数之后需要马上刷新编解码器,在任何输出Buffer或输出格式被改变并返回之前,特定编解码格式数据也许会丢失在刷新过程中。在这种刷新中,要确保合适的编解码器做编解码操作不出问题,必须重新提交使用带BUFFER_FLAG_CODEC_CONFIG标志的Buffer数据

在这里插入图片描述

在任意有效的输出Buffer带有codec-config标志前,如果是编码过程,编码器将创建并返回特定编码的数据,如果是解码过程,解码器将解出对应的YUV数据

Codec数据处理过程

每个Codec维护的一组输入和输出Buffer都指向API调用的bufferid。成功调用start函数后,客户端拥有输入和输出Buffer。在同步模式下,调用dequeueInput/OutputBuffer(...)来获得Codec的输入或输出Buffer。在异步模式下,通过MediaCodec.Callback.onInput/OutputBufferAvailable(...)回调函数将自动接收回调后的Buffer

Codec在异步模式下通过onOutputBufferAvailable回调函数将返回一个只读输出Buffer,或在同步模式下响应dequeueOutputBuffer调用。在输出Buffer被处理后,调用releaseOutputBuffer函数返回Codec的Buffer
在这里插入图片描述

1.异步处理使用缓冲区

从5.0开始首选异步模式处理数据,处理方法是在调用configure函数之前设置一个回调。异步模式改变了状态转换,因为刷新后必须调用start函数,MediaCodec过渡到Running子状态,这时开始接受输入Buffer。同样在初始直接调用start函数后,MediaCodec进入Running状态,通过回调传递可用的输入Buffer
在这里插入图片描述

2.同步解码和异步解码
同步方式

错误使用的原因是,开发者会主观上认为,MediaCodec的工作方式是提供一个input数据就输出一个对应的output函数。事实上MediaCodec在读入input数据之后,按照自己的逻辑编解码,可能拆分编解码数据,或者合并输出。MediaCodec的使用者应该认为input和output没有对应关系,使用者的角色是完全被动的,把Buffer的使用权交给MediaCodec

异步方式

用MediaCodec来编解码一个视频到SurfaceView显示
在这里插入图片描述

从创建到Start过程

1.MediaCodec从创建到start过程(到JNI部分)在这里插入图片描述

2.补充MediaCodec基本用法

使用MediaCodec的基本模式

(1)创建和配置MediaCodec对象
(2)进行以下循环:如果一个输入缓冲区准备好,读取部分数据,复制到缓冲区,如果一个输出缓冲区准备好,复制到缓冲区
(3)销毁MediaCodec对象

一个MediaCodec对象可以对特定类型的数据(如MP3或H.264)进行编码或解码。因为在原始数据上操作,所以任何文件头(比如ID3 tags)必须被剔除,MediaCodec不与任何更高层次的内容交互,所以无法通过扬声器播放音频或者从网络接收视频流。它只读入缓冲区数据,再输出到缓冲区。MediaCodec可以把大部分的外层数据去掉

必须将MediaCodec的输入处理成特定的格式,H.264视频编码输入的就是一帧数据,H.264解码指的是一个NAL单元。但你不可能一次只提交单个数据或数据在需要处理的时候才出现,这样看起来输入更像是一个流。实际上编解码器在输出前同时拥有多个Buffer

MediaCodec中的BufferInfo内部类
在这里插入图片描述

MediaCodec和MediaPlayer在很多地方有相似之处,当java层调用MediaCodec。createByCodeName、MediaCodec.recateDecoderByType、MediaCodec.createEncoderByType时,都会执行MediaCodec的构造函数,构造函数中都会调用native_setup
在这里插入图片描述

其中对应一段代码,相当于做了一次映射,如native_setup对应android_media_MediaCodec_native_setup等,接着进入android_media_MediaCodec_native_setup函数,主要用于构建JNI层中的MediaCodec,也就是JMediaCodec

在这里插入图片描述

创建JMediaCodec后,通过setMediaCodec设置JMediaCodec
在这里插入图片描述

上面用到了智能指针中的成员函数incStrong和decStrong来维护引用计数器的值,这两个函数就是提供给智能指针来调用的。要注意在decStrong函数中,如果当前引用计数值为1,那么减一后就会变成0,于是就会删除这个对象。接下来看看JMediaCodec的构造函数
在这里插入图片描述

可以看出JMediaCodec最终执行到C++层MediaCodec的两个Create函数,通过以上几个步骤得到MediaCodec对象后,就开始执行java层调用MediaCodec.configure函数
在这里插入图片描述

获取format中的map,实际上是一个HashMap,然后遍历视频源的格式名并存放到两个数组中,再通过android_media_MediaCodec_native_configure向下传递
在这里插入图片描述

通过getMediaCodec获取对应的JMediaCodec,接着传入jsurface变量,表示JNI层中的Surface数据,这个jsurface变量不一定是真正的Surface(Surface实际上是一块Buffer),也有可能是SurfaceHolder(SurfaceHolder可以通过其中的getSurface获取Surface),最后调用JMediaCodec的configure函数
在这里插入图片描述

上面最后的mCodec->configure最终会调用MediaCodec.cpp中的configure函数,构建一些编解码器。在MediaCodec.java中调用start函数后,会执行下图代码
在这里插入图片描述

在上面的代码获取JMediaCodec后,调用JMediaCodec中的start函数,JMediaCodec中的start函数代码如下

在这里插入图片描述

这个mCodec最后执行C++的MediaCodec的start函数。最后到达ACodec.cpp的start函数中去执行解码操作

【Android 音视频开发打怪升级:音视频硬解码篇】二、音视频硬解码流程:封装基础解码框架 为了方便记录解码状态,这里使用一个枚举类表示/*开始状态START,/*解码中DECODING,/*解码暂停PAUSE,/*正在快进SEEKING,/*解码完成FINISH,/*解码器释放STOP前面说过,MediaCodec需要我们不断地喂数据给输入缓冲,那么数据从哪里来呢?肯定是音视频文件了,这里的IExtractor就是用来提取音视频文件中数据流。 阅读详情

相关推荐

Android音视频--H,带你全面解析Android框架体系架构view篇

这里附上上述的技术体系图相关的几十套腾讯、头条、阿里、美团等公司2021年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。

2301_77110865的博客 828

Android:MediaCodec基本原理

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

肖云鹤的博客 4113

寒假实训笔记day01——认识M4单片机之STM32F405RGT6

认识M4单片机之STM32F405RGT6(含义、规格、参数)

weixin_47200070的博客 8551

NDK中使用 MediaCodec 编解码视频

背景 MediaCodec 作为Android自带的视频编解码工具,可以直接利用底层硬件编解码能力,现在已经逐渐成为主流了。API21已经支持NDK方法了,MediaCodec api设...

音视频开发进阶 6828

合成生物学中试:花钱只是开始,烧钱才是常态

2026年合成生物学行业面临严峻产业化挑战:多家企业终止发酵项目或延期投产,显示从实验室到工厂的转化困境。核心问题并非基因合成成本,而是工艺放大难题——67%项目在中试阶段因工艺问题失败。AI辅助无法替代工程经验,菌株-配方-工艺的三元适配需要长期数据积累。中试成本惊人,涉及设备折旧、原料消耗和稀缺工艺人才,而行业普遍回避讨论这些工程现实,导致认知偏差。建议创业者提前布局中试,将其视为核心竞争力而非简单成本项。合成生物学的真正瓶颈在于工程化能力,这需要时间沉淀而非技术叙事。

AIexander的博客 942

奔图M6700-M6800-M7100-M7200 系列打印机拆解教程?

奔图M6700-M6800-M7100-M7200 系列打印机拆解教程?

m0_58098052的博客 1598

Android13 MediaCodec start流程分析

上面方法主要处理如下:1、调用ACodec的signalResume方法。2、调用ACodec的initiateStart方法。

liuning1985622的博客 542

LC-3 机器语言 指令集

生活本就沉闷,但跑起来就有风

笔记 1万+

【Android 10 源码】深入理解 MediaCodec 硬解码初始化

方法,实际由 MediaCodecList::getCodecInfo(…实际响应方为 MediaPlayerService::getCodecList(),这个函数内部调用了 MediaCodecList::getLocalInstance(),又绕了回去(因为调用进程和响应进程是不同的,虽然都使用了同一个类的中的函数)。RTLD_NOW: 需要在 dlopen 返回前,解析出所有未定义符号,如果解析不出来,在 dlopen 会返回 NULL,错误为:undefined symbol: xxxx…

xiaowang_lj的博客 1509

S32DS使用完整指南:S32K CAN通信模块配置步骤

深入讲解S32DS使用过程中S32K芯片的CAN通信模块配置步骤,涵盖关键设置与常见问题。掌握s32ds使用技巧,提升开发效率,实现稳定可靠的车载网络通信。

weixin_42592399的博客 981

别再纠结了!手把手教你根据项目需求选对目标检测框架(MMDetection/Detectron2/YOLOv8实战对比)

本文详细对比了三大目标检测框架MMDetection、Detectron2和YOLOv8的适用场景与实战技巧,帮助开发者根据项目需求精准选型。从毕业设计到工业落地,分析不同场景下的核心需求与框架优势,提供决策树和避坑指南,确保技术选型与项目目标高度匹配。

weixin_30342209的博客 554

Android 使用 MediaCodec API音频播放器

OpenMAX 有时缩写为“OMX”,是针对多媒体处理的免版税、跨平台的例程和接口集。它主要用于嵌入式设备,在设计时考虑了效率,因此可以以优化和受控的方式处理大量多媒体数据,包括视频/音频编解码器、图形等。 OpenMAX 提供三层接口:应用层(AL)、集成层(IL)和开发层(DL)。OpenMAX IL 是媒体框架之间的接口,例如 Android 上的 StageFright 或 MediaCodec API。更多关于这个here。 在 Android 16 中引入的 MediaCodec API 可

技术刚刚好 1014

程序化广告ADX系统架构设计与实现

摘要: 本文详细介绍了程序化广告交易平台(ADX)的系统架构设计与实现。ADX作为连接广告主与媒体的核心平台,采用基于腾讯云和阿里云的微服务架构,包含网络基础设施、负载均衡、消息处理、核心业务服务和多级数据存储等层次。重点解析了Kafka消息队列处理高并发广告请求、Redis实时统计关键指标等核心技术实现,并提供了Java代码示例展示广告请求处理、竞价流程等核心功能。该系统通过分层设计和分布式组件,实现了高性能、高可用的程序化广告交易能力。

私聊前往站内信:https://i.youkuaiyun.com/#/msg/chat/weixin_44976692 768

给Android工程师的音视频教程之一文弄懂MediaCodec

MediaCodec是Android提供的用于对音视频进行编解码的类,是Android Media基础框架的一部分,一般和 MediaExtractor, MediaMuxer, Surface和AudioTrack 一起使用。

一个码农的博客 8468

厉害了,华为推出下一代光传送网:fgOTN

2024年10月,在全球信息技术博览会(GITEX Global 2024)上,华为正式发布了其颠覆性的创新产品——端到端细粒度光传送网(fgOTN)解决方案。这一产品组合被誉为行业内首个fgOTN,旨在重塑光传送网络的格局,满足电力运输等行业日益增长的通信需求。在过去的近三十年中,同步数字体系(SDH)技术一直是电信和工业网络的支柱,因其可靠性、稳定性和低延迟而备受青睐。然而,随着数据需求的激增,SDH的最大带宽仅为10 Gbps,逐渐显露出局限性。

网络技术联盟站 636

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Android音视频 MediaCodec框架-启动编码(4)

上一节我们介绍了MediaCodec框架创建编码器流程,编解码的流程其实基本是一样的,只是底层的最终的实现组件不同,所以我们只看启动编码流程。

起司锅仔的博客 1568

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Android 音视频 - MediaCodec 编解码音视频

作者:声网Agora 我们知道 Camera 采集回传的是 YUV 数据,AudioRecord 是 PCM,我们要对这些数据进行编码(压缩编码),这里我们来说在 Android 上音视频编解码逃不过的坑-MediaCodec。 MediaCodec PSMediaCodec 可以用来编/解码 音/视频。 MediaCodec 简单介绍 MediaCodec 类可用于访问低级媒体编解码器,即编码器/解码器组件。 它是 Android 低级多媒体支持基础结构的一部分(通常与 MediaExtracto.

鸿蒙开发知识记录 1193

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

MediaCodec_Analyze-3-start

MediaCodec_Analyze-3-start

Bingin的博客 656

MediaCodec基础入门

一MediaCodec的应用背景角色 二MediaCodec的状态机代码设计架构交互机制 三 MediaCodec的同步模式及JAVA代码 四参考资料一.MediaCodec的应用背景、角色如图1所示,APP开发者可以采用两种多媒体JAVA库开发多媒体播放服务,分别为MediaPlayer,MediaCodec。MediaCodec的C++层是对ACodec的封装;ACodec完成的工作是向下调用O

仰望星空 5700

Android音视频开发全解析:从基础到面试实战

音视频开发是移动应用开发中的重要领域,涉及信号处理、编解码技术和多媒体框架等核心技术。理解PCM音频采样、YUV色彩空间等基础概念是入门关键,而Android平台提供的MediaCodec、AudioTrack等API则为开发者提供了强大的工具支持。在实际工程中,性能优化和跨平台适配是常见挑战,例如通过硬件加速降低CPU占用,或使用FFmpeg处理复杂编解码需求。随着AI增强和实时通信技术的发展,音视频开发在直播、视频会议等场景中的应用越来越广泛。掌握这些技术不仅能提升应用性能,也是应对大厂面试中关于Med

weixin_30301449的博客 455

Android Multimedia框架总结(二十二)MediaCodec中C++中创建到start过程及状态变换

上一章介绍MediaCodec中创建到start过程(到jni部分),从今天开始,将深入源码中看看其c++过程,看下Agenda如下:mediacodec.hCreateByTypeinitMediaCodec中BufferInfo内部类:configure过程startBufferInfo在MediaCodec.h中对应是一个结构体//create by 逆流的鱼yuiop on 2016/12

欢迎关注公众号:【码农突围】,公号后台回复9999,可以获取一份500页的LeetCode刷题笔记。 8334

Android音视频--H

对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长。而不成体系的学习效果低效漫长且无助。时间久了,付出巨大的时间成本和努力,没有看到应有的效果,会气馁是再正常不过的。所以学习一定要找到最适合自己的方式,有一个思路方法,不然不止浪费时间,更可能把未来发展都一起耽误了。如果你是卡在缺少学习资源的瓶颈上,那么刚刚好我能帮到你。《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!再正常不过的。

2401_83817122的博客 1029

【Android 音视频开发打怪升级:音视频硬解码篇】二、音视频硬解码流程:封装基础解码框架(1)

为了方便记录解码状态,这里使用一个枚举类表示/*开始状态START,/*解码中DECODING,/*解码暂停PAUSE,/*正在快进SEEKING,/*解码完成FINISH,/*解码器释放STOP前面说过,MediaCodec需要我们不断地喂数据给输入缓冲,那么数据从哪里来呢?肯定是音视频文件了,这里的IExtractor就是用来提取音视频文件中数据流。

2401_84538135的博客 968

【Android 音视频开发打怪升级:音视频硬解码篇

因此,我们将整个解码流程抽象为一个解码基类:BaseDecoder,为了规范代码和更好的拓展性,我们先定义一个解码器:IDecoder,继承Runnable。/**暂停解码*//**继续解码*/fun goOn()/**停止解码*/fun stop()/**是否正在解码*//**是否正在快进*//**是否停止解码*//**设置状态监听器*//**获取视频宽*//**获取视频高*//**获取视频长度*//**

m0_57502067的博客 1160

11. Android MultiMedia框架完全解析 - start流程分析

还是从mediaplayer.cpp开始分析,看start函数的实现: status_t MediaPlayer::start() { mPlayer->setLooping(mLoop); mPlayer->setVolume(mLeftVolume, mRightVolume); mPlayer->setAuxEffectSendLevel(mSendLe...

吾皇的博客 3435

2024年Android最新Android音视频——MediaCodec编码mp4踩坑记录,2024年最新华为软件开发工程师面试题

我这些话比较直接,可能会戳到一些人的玻璃心,但是我知道肯定会对一些人起到点醒的效果的。的配置上也很关键,必须配置得当,否则也还是会出现时长缩水的问题,于是我将原来项目中的代码进行修改,将帧率修改为 30f,关键帧间距改为 5s,丢帧的问题这才解决了,因为你的技术体系并不系统,是零碎的,散乱的。发现有的设备正常,个别设备录制出来的视频,时长仅仅只有一半,这也就是网上都在说的。了,但依旧无济于事。而现在随着跨平台开发,混合式开发,前端开发之类的热门,Android开发者需要学习和掌握的技术也在不断的增加。

2301_82243733的博客 929
上一篇: 【学习】从零开始的Android音视频开发(11)——OMX:Codec部分中的OMXCodec和OMX事件回调流程
下一篇: 【学习】从零开发的Android音视频开发(13)——MediaCodec到OMX框架过程及其硬解码
Panic  Lin
博客等级 码龄6年 81粉丝 64原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值