前言:前面几节都是介绍Camera2相关,对于Camera2预览把图像显示在SurfaceView上,还有录像时,时时刷新当前图像区域。追溯到最早介绍的MediaPlayer播放视频,这些都离不开重要角色MediaCodec,今天介绍MediaCodec,看下Agenda:

  • MediaCodec是什么?

  • codec操作的数据类型

    • 压缩buffer

    • 原始音频buffer

    • 原始视频buffer

  • MediaCodec状态周期图

  • Codec-specific数据

  • Codec数据处理过程

  • MediaCodec案例

MediaCodec是什么?

MediaCodec类可以访问底层媒体编解码器框架(StageFright或openMAX),即编码器/解码器组件。这是Android low-level多媒体支持基础设施的一部分(通常与MediaExtractor, MediaSync, MediaMuxer, MediaCrypto, MediaDrm, Image, Surface, and AudioTrack.一起使用))。

从广义上讲,codec处理输入数据产生输出数据。异步处理数据,并使用一组输入和输出buffer。在简单的层面,请求(或接收)空输入缓冲区,加满数据并将其发送到codec进行处理。codec使用的数据转换成一个空的输出缓冲区。最后,请求(或接收)输出buffer,消耗其内容并释放它回codec。

codec操作的数据类型

codec操作三种数据:压缩数据,原始音频数据和原始的视频数据。所有这三种数据可以使用ByteBuffers处理,应该对原始视频数据使用一个Surface来提高编码性能。Surface使用native视频的buffers没有映射或复制他们ByteBuffers;因此,它更高效。通常不能访问原始视频数据使用一个Surface时,可以使用ImageReader类访问未固定的解码视频帧(原生)。比起使用ByteBuffers的话,这可能会更有效的,一些native 的buffers可能直接映射到ByteBuffers。当使用ByteBuffer模式中,您可以使用Image类及getInput / OutputImage(int)访问原始视频帧。

压缩buffer

输入缓冲区(解码器)和输出缓冲区(编码器)包含压缩数据格式的类型。对于视频类型,这是一个压缩的视频帧。对于音频数据,这通常是一个单一的访问单元(一个音频段通常包含几毫秒的音频编码格式决定的类型),但这个需求略有放松,缓冲区可能包含多个接入单位的音频编码。在这两种情况下,在任意字byte边界上,buffer不会start和end,直到在(帧/访问)unit边界上。

原始音频buffer

原始音频缓冲区包含整个PCM音频帧数据,下面是一个示例为每个通道的通道顺序。每一个样例都是16位带符号整数在native byte通道中。

原始视频buffer

ByteBuffer模式视频缓冲区根据他们的颜色格式布局。你可以从getCodecInfo().getCapabilitiesForType .colorFormats(…)得到支持的颜色格式数组。视频编解码器支持三种颜色格式:

  • native raw video format: 带有COLOR_FormatSurface标记,并用于输入/输出到Surface.

  • flexible YUV buffers (带有COLOR_FormatYUV420Flexible): 当在 ByteBuffer 模式下,通过getInput/OutputImage(int)方法,也用于输入/输出到Surface.

  • specific formats: 这些都是通常只支持ByteBuffer模式,一些特定于供应商的颜色格式,其他人则MediaCodecInfo.CodecCapabilities中定义,对于color formats ,相当于一个灵活的格式,你依旧可以使用getInput/OutputImage(int)

自LOLLIPOP_MR1开始,所有视频编解码器支持灵活的YUV 4:2:0的buffer

本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/53183718

MediaCodec状态

在codec的生命周期的概念上存在三种状态之一:Stopped, Executing or Released. 。停止所有状态实际上是聚集的三种状态:Uninitialized, Configured and Error,而执行状态概念上的进展通过三个子状态:Flushed, Running and End-of-Stream。

当您使用一个工厂方法创建一个codec时,codec处于未初始化的状态。首先,您需要配置它通过configue(…),这让它处于配置的状态,然后调用start()方法将它移动到Executing状态。在这种状态下你可以通过上述缓冲队列操作过程数据。 
执行状态有三个子状态:Flushed, Running and End-of-Stream。在start()方法调用后,codec会立刻刷新子状态,它拥有所有的buffer。一旦第一个输入buffer从列中移除,codec将花费比较长的时间移动到正在运行的子状态上。当你队列的输入buffer带有end-of-stream标记,codec将转换到end-of-stream子状态。在这种状态下的codec不再接受进一步输入buffer,但仍然生成输出缓冲区,直到达到end-of-stream输出。你可以移回到Flushed子状态在任何时候当在Executing 状态时使用flush()方法。

调用stop()方法返回的codec未初始化(Uninitialized)状态,因为它可能是再次被配置了。当你再使用一个编解码器(codec),你必须释放它通过调用release()方法。 
在极少数情况下的codec可能会遇到一个错误,Error状态。这是沟通使用无效的返回值从一个队列操作,或者通过一个例外。调用reset()方法让编解码器(codec)能再次可用。你可以调用它 把当前的任何状态转移到Uninitialized状态,否则,调用release()方法,回到终端Released状态。

Codec-specific数据

一些格式,特别是AAC音频和MPEG4,H.264和H.265视频格式需要通过大量的buffer包含设置数据,或codec特定数据来作为真实数据的开头。在处理这样的压缩格式时,在任意帧数据开始前,调用start方法后,这个数据必须提交给codec。当在调用queueInputBuffer时,这些数据必须使用flag:BUFFER_FLAG_CODEC_CONFIG。

Codec-specific数据也可以包含在ByteBuffer条目的格式传递给配置钥匙“csd-0”、“csd-1”,等等。这些钥匙总是包含在跟踪MediaFormat从MediaExtractor获得。Codec-specific数据格式自动提交给codec在start调用;你不能明确地提交这些数据。如果不包含编码特定的数据格式,你可以选择提交使用指定的缓冲区以正确的顺序,按照格式要求。对于H.264 AVC,您还可以连接所有codec-specific数据并提交它作为单个codec-config缓冲区。 
Android使用以下codec-specific数据缓冲区。这些也需要跟踪格式中设置适当的MediaMuxer track 配置。每个参数设置和codec-specific-data部分标注(*)必须从以”\x00\x00\x00\x01”开始。

注意:必须注意codec在start之后马上刷新,在任何output buffer或输出格式被改变被返回之前, codec specific data也许会丢失在刷新过程中。在这种刷新时,要确保合适的codec操作不出问题,必须要重提交data,使用带BUFFER_FLAG_CODEC_CONFIG标志的buffers。

在任意有效的output buffers输出的buffer带有codec-config 标志前,编码器(或codec生成压缩数据)将创建并返回编码特定的数据。buffer包含codec-specific-data没有意义的时间戳。

Codec数据处理过程

每个codec维护的一组输入和输出buffer被指向在API调用的buffer-ID。成功调用start()方法后,client“拥有”输入和输出buffer。在同步模式下,调用dequeueInput / OutputBuffer(…)来获得(所有权)codec的输入或输出buffer。在异步模式下,您通过MediaCodec.Callback.onInput / OutputBufferAvailable(…)回调方法将自动接收buffer。 
在获得一个输入缓冲区,填入数据并提交它的codec使用queueInputBuffer——或者queueSecureInputBuffer如果使用解密。不要使用相同的时间戳提交多个输入buffer(除非codec-specific数据被标记为)。

codec在异步模式下通过onOutputBufferAvailable回调方法将返回一个只读输出buffer,或在同步模式下响应dequeuOutputBuffer调用。在输出buffer被处理后,调用一个releaseOutputBuffer方法返回codec的buffer。

当你不需要重新提交/立即释放codec的buffer,抓住输入和/或输出buffer可能在codec中延后,这种情况和设备相关。具体地说,codec可能暂缓生成输出buffer,直到所有buffer的未发布/重新提交。因此,试图得到可用buffer尽可能少。 
根据API版本,您可以在三个方面:处理数据

异步处理使用缓冲区 
自LOLLIPOP开始,首选的方法处理异步过程数据是通过设置一个回调在调用配置之前。异步模式改变了状态转换,因为刷新后必须调用start()方法的codec过渡到正在运行的子状态,开始接收输入buffer。同样,在一个初始直接调用开始后,codec将正在运行的子状态,开始通过回调传递可用的输入buffer。

案例

此前我们曾用MediaPlayer播放网络视频及本地视频,今天不用MediaPlayer,转而用MediaCodec来Codec一个视频到SurfaceView上,下面看代码:




 效果图

案例工程已上传到github:https://github.com/hejunlin2013/MultiMediaSample,之前其他多媒体框架相关案例也在此仓库中

第一时间获得博客更新提醒,以及更多android干货,源码分析,欢迎关注我的微信公众号,扫一扫下方二维码或者长按识别二维码,即可关注。

Android Multimedia框架总结(二十)MediaCodec状态图及Codec与输入/输出Buffer过程(附实例)...相关推荐

  1. Android MVVM框架搭建(十)Hilt、ViewBinding、Activity Result API

    Android MVVM框架搭建(十)Hilt.ViewBinding.Activity Result API 前言 正文 一.依赖 二.Hilt使用 1. Hilt 应用类 2. ViewModel ...

  2. (转载)Android项目实战(二十八):使用Zxing实现二维码及优化实例

    Android项目实战(二十八):使用Zxing实现二维码及优化实例 作者:听着music睡 字体:[增加 减小] 类型:转载 时间:2016-11-21 我要评论 这篇文章主要介绍了Android项 ...

  3. Android项目实战(二十二):启动另一个APP or 重启本APP

    Android项目实战(二十二):启动另一个APP or 重启本APP 原文:Android项目实战(二十二):启动另一个APP or 重启本APP 一.启动另一个APP 目前公司项目需求,一个主AP ...

  4. PyTorch框架学习二十——模型微调(Finetune)

    PyTorch框架学习二十--模型微调(Finetune) 一.Transfer Learning:迁移学习 二.Model Finetune:模型的迁移学习 三.看个例子:用ResNet18预训练模 ...

  5. Android开发笔记(二十四)res目录的结构与配置

    res目录结构 res是Android项目工程中存放各类的目录,主要包括布局.图形与配置等等.res的子目录主要有: anim : 存放动画的描述文件 drawable : 存放各类图形的描述文件,包 ...

  6. Android项目实战(二十):浅谈ListView悬浮头部展现效果

    Android项目实战(二十):浅谈ListView悬浮头部展现效果 原文:Android项目实战(二十):浅谈ListView悬浮头部展现效果 先看下效果:需求是 滑动列表 ,其中一部分视图(粉丝数 ...

  7. Android基础知识(二十):Notification、提醒式通知(横幅)踩坑与通知界面设置跳转

    Android基础知识(二十):Notification.提醒式通知(横幅)踩坑与通知界面设置跳转 一.Notification通知与基本用法 通知Notification是Android系统中比较有 ...

  8. Android进阶知识(二十五):Bitmap简介及其高效加载

    Android进阶知识(二十五):Bitmap简介及其高效加载 一.Bitmap   Bitmap代表一个位图,在Android中指的是一张图片,可以是png.jpg等格式的图片.BitmapDraw ...

  9. Android 天气APP(二十九)壁纸设置、图片查看、图片保存

    上一篇:Android 天气APP(二十八)地图搜索定位 效果图 开发流程 一.前情提要 二.正式开发 1. 列表数据填充 2. 浮动按钮的交互 3. 其他优化 4. 运行效果图 三.文末 一.前情提 ...

  10. Android 天气APP(二十六)增加自动更新(检查版本、通知栏下载、自动安装)

    上一篇:Android 天气APP(二十五)地图天气(下)嵌套滑动布局渲染天气数据 效果图 开发流程 1.开发前言 2.上传应用到分发平台 3.版本数据请求与存储 4.检查版本更新.自定义更新提示弹窗 ...

最新文章

  1. 知识产权创业的比赛结果
  2. Keras学习笔记:函数式模型
  3. 在WinForm程序中嵌入ASP.NET
  4. “3D几何与视觉技术”全球在线研讨会第四期~几何深度学习
  5. IPsec   在企业网中的应用
  6. QT.pro工程文件中判断宏定义是否存在
  7. kafka windows单机安装测试
  8. 培训linux好吗,参加linux专业培训好还是自学linux好
  9. 腾讯信鸽Java服务端推送IOS静默消息的IOS客户端走两个回调的问题
  10. Android有那些好的进阶书籍呢
  11. 截图快捷键ctrl加什么
  12. 微信小程序InnerAudioContext IOS真机无法播放声音
  13. 【毕业设计】基于stm32的智能扫地机器人设计与实现 - 单片机 物联网
  14. SaaS、PaaS、LaaS以及之间的区别
  15. 第11.3节 Python正则表达式搜索支持函数search、match、fullmatch、findall、finditer
  16. 网贷公司是什么意思? 网贷公司如何挑选更安心?【理财帮手】
  17. java实现简单的LUR算法
  18. Oracle GoldenGate 文章集合
  19. 你“剁手”的时候,支付宝在干嘛?
  20. 广州.Net+Android训练营 课程体系4.1版

热门文章

  1. Guava学习笔记(六):Immutable(不可变)集合
  2. Ubuntu开机慢_开机计时1分30秒_A start job is running for dev-disk-by...
  3. 随手记_C++常考面试题
  4. C++调用C#编写的com组件方法
  5. ICCV 2021 | 超越MobileNetV3!SkipNet:面向轻量级CNN的Bias Loss
  6. 介绍一篇路端传感器的cooperative perception(3D目标检测)论文
  7. java线程从没入门就放弃
  8. C#基础精华05(正则表达式,)
  9. 怎样在安卓中实现在锁屏状态下弹出对话框,并可以震动和铃声,就像闹钟似的?...
  10. 排序算法专题-冒泡排序