MediaCodec文档翻译
MediaCodec|文档翻译
classoverView
mediacodec类可以用来调用系统底层的编码/解码软件。
mediacodec一般是这么用的:
MediaCodec codec = MediaCodec.createDecoderByType(type);
codec.configure(format, ...);
codec.start();
ByteBuffer[] inputBuffers = codec.getInputBuffers();
ByteBuffer[] outputBuffers = codec.getOutputBuffers();
for (;;) {
int inputBufferIndex = codec.dequeueInputBuffer(timeoutUs);
if (inputBufferIndex >= 0) {
// fill inputBuffers[inputBufferIndex] with valid data
...
codec.queueInputBuffer(inputBufferIndex, ...);
} int outputBufferIndex = codec.dequeueOutputBuffer(timeoutUs);
if (outputBufferIndex >= 0) {
// outputBuffer is ready to be processed or rendered.
...
codec.releaseOutputBuffer(outputBufferIndex, ...);
} else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
outputBuffers = codec.getOutputBuffers();
} else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
// Subsequent data will conform to new format.
MediaFormat format = codec.getOutputFormat();
...
}
}
codec.stop();
codec.release();
codec = null;
//等会再逐一介绍上述代码每一句的作用
每一个Codec类都拥有input buffer和outputbuffer,这些buffer是通过API提供的函数按索引调用(Index),这些buffer的格式是bytebuffer,实际上inputbuffer和outputbuffer都是bytebuffer的数组,用getInputBuffer和getOutputBuffer可以得到bytebuffer的调用。在成功调用Start()函数后,对象(原文是Client,在这里我理解为MediaCodec的实例化对象)并没有“拥有”input和output buffer,相应的,可以通过调用dequeueInputBuffer(long)
和dequeueOutputBuffer(MediaCodec.BufferInfo, long)把buffer的所有权从codec编解码器交换给对象。MediaCodec对象没有必要立刻把buffer传递给解码器或者释放到surface,上面的代码仅仅是一个简单的例子。
当MediaCodec对象有一个可用的input buffer时候,可以调用 queueInputBuffer(int, int, int, long, int)函数把buffer传递给解码器,当然,buffer里需要有数据。
解码器会相应的调用 dequeueOutputBuffer(MediaCodec.BufferInfo, long)返回一个output buffer,如果继续调用
releaseOutputBuffer(int, boolean)
,这个output buffer将被返回到解码器中,如果再 configure(MediaFormat, Surface, MediaCrypto, int)
的时候传入了一个videoSurface(一般是SurfaceView).那么这个这个output buffer的内容将会显示在surface上。
不管是用于解码器的input buffer还是编码器的output buffer ,其中都包含了编码好的多媒体数据.对于视频格式的文件来说,buffer里包含的是一个短暂的时间片(比如一帧),对于音频格式的文件,可能是一个多帧的声音片段。不管哪种情况,buffer里的数据并不是任意字节边界的二进制数据,buffer里存储的不是数据流,而是一个元单元(access units)流。
很多媒体格式还需要多媒体文件头数据(这些数据一般是由一些包含set up data的buffer组成),或者编码器需要的特定数据。因此,最初传递给解码器的buffer必须是带有BUFFER_FLAG_CODEC_CONFIG下标的编码特定数据,一般这个下标是由queueInputBuffer(int, int, int, long, int)生成的。编码器需要的数据,包括媒体格式信息,都通过调用 configure(MediaFormat, Surface, MediaCrypto, int)
(in ByteBuffer entries with keys "csd-0", "csd-1", 括号里这句不知道怎么翻译),自动传递给了codec类,不需要对象自己把格式信息传给codec(也就是configure会自动传递带有BUFFER_FLAG_CODEC_CONFIG的buffer和媒体格式信息给编码器)。在输入数据的末尾,对象会通过queueInputBuffer(int, int, int, long, int)函数发送一个带有BUFFER_FLAG_END_OF_STREAM
下标的信号。为了解码与之前数据无关的数据(例如执行一个seek),解码器需要调用flush()。在调用flush()后,对象里的inputbuffer或者outputbuffer都会清空,也就是说对象不再有任何buffer,但是数据的媒体格式信息不会改变,如果需要改变媒体格式信息,依次调用stop,configure,start.
Public Methods
public void configure (MediaFormat format, Surface surface, MediaCrypto crypto, int flags)
配置一个组件。
Parameters
format | 如果为解码器,此处表示输入数据的格式;如果为编码器,此处表示输出数据的格式。 |
---|---|
surface | 指定一个surface,可用作decode的输出渲染。 |
crypto | 如果需要给媒体数据加密,此处指定一个crypto类. |
flags | 如果正在配置的对象是用作编码器,此处加上CONFIGURE_FLAG_ENCODE 标签。 |
public static MediaCodec createByCodecName (String name)
如果你知道你想实例化的组件确切名字, 用这个方法来初始化它,谨慎使用这个函数,最好配合从 MediaCodecList获得的信息来使用。
Parameters
name | 需要实例化的组件的名字. |
---|
public static MediaCodec createDecoderByType (String type)
用给定的媒体格式来创建一个解码器.下面是部分媒体格式和他们所对应的key的列表:
- "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
Parameters
type | 输入数据的多媒体格式. |
---|
public static MediaCodec createEncoderByType (String type)
按给定的媒体类型创建一个编码器。
Parameters
type | 所需要的输出媒体格式. |
---|
public final Surface createInputSurface ()
请求一个surface作为解码器的输入(替代掉inputbuffer?).这个函数需要在 configure(MediaFormat, Surface, MediaCrypto, int)
之后 start()之前被调用。
程序应该自己调用release去释放这个 surface而不是等gc 去做。
public final int dequeueInputBuffer (long timeoutUs)
返回一个可用来填充有效数据的inputbuffer的索引(Index),如果返回-1表示暂无可用的buffer. 如果 timeoutUs == 0,该方法会立刻返回值, 如果 timeoutUs < 0 则一直等待,如果 timeoutUs > 0则等待对应时间.
Parameters
timeoutUs | 单位为微秒, 负数表示无穷大. |
---|
public final int dequeueOutputBuffer (MediaCodec.BufferInfo info, long timeoutUs)
排一个output buffer, 等待“timeoutUs"后若无有效值则阻塞,单位为 microseconds. 返回成功解码的outputbuffer的索引 或者 一个 INFO_* constants 常量.
Parameters
info | buffer的一些信息 |
---|---|
timeoutUs | 单位为微秒, 负数表示无穷大. |
public final void flush ()
flush,重洗组件的input和output接口, 之前调用 dequeueInputBuffer(long)
和dequeueOutputBuffer(MediaCodec.BufferInfo, long)
排好的buffer都变成不可用。
public MediaCodecInfo getCodecInfo ()
获得codec的信息.如果codec是 createDecoderByType 或createEncoderByType创建的, 事先并不知道用的什么组件,那么 调用这个函数不会返回CodecInfo。
public ByteBuffer[] getOutputBuffers ()
Call this after start() returns and whenever dequeueOutputBuffer signals an output buffer change by returning INFO_OUTPUT_BUFFERS_CHANGED
这句话不好翻译,大意是在start()调用,或者在dequeueOutputBuffer 返回 INFO_OUTPUT_BUFFERS_CHANGED信息后调用。
public final MediaFormat getOutputFormat ()
如果 dequeueOutputBuffer 返回INFO_OUTPUT_FORMAT_CHANGED ,调用这个函数。
public final void queueInputBuffer (int index, int offset, int size, long presentationTimeUs, int flags)
再给指定索引的inputbuffer填充完数据后,把它交给编码器. 很多解码器需要媒体文件的文件头,例如 vorbis audio中的编码表 ,AVC video中的PPS/SPS,. MediaExtractor
类提供了codec所需要的多媒体格式信息 ... 这些buffer应该加上 BUFFER_FLAG_CODEC_CONFIG标签
. 如果这是最后一个输入数据 (接下来没有其他的数据输入,除非马上要调用flush()) 则应该加上 BUFFER_FLAG_END_OF_STREAM标签
.
Parameters
index | 前面由 调用 dequeueInputBuffer(long)返回的index |
---|---|
offset | The byte offset into the input buffer at which the data starts. 可以理解为有效数据开始的偏差,一般为0 |
size | 输入的有效数据的大小 |
presentationTimeUs | 这个buffer被渲染的时间(一般由extractor.getsampleTime获得) |
flags | 根据需要从 BUFFER_FLAG_SYNC_FRAME , BUFFER_FLAG_CODEC_CONFIG , BUFFER_FLAG_END_OF_STREAM选一个,或者0~ |
Throws
MediaCodec.CryptoException | 如果在 configure(MediaFormat, Surface, MediaCrypto, int)被加密则抛出异常 |
---|
public final void queueSecureInputBuffer (int index, int offset, MediaCodec.CryptoInfo info, long presentationTimeUs, int flags)
与 queueInputBuffer(int, int, int, long, int)相似,但是
传入的是一个被加密的buffer。
Parameters
index | The index of a client-owned input buffer previously returned in a call to dequeueInputBuffer(long) . |
---|---|
offset | The byte offset into the input buffer at which the data starts. |
info | Metadata required to facilitate decryption, the object can be reused immediately after this call returns. |
presentationTimeUs | The time at which this buffer should be rendered. |
flags | A bitmask of flags BUFFER_FLAG_SYNC_FRAME , BUFFER_FLAG_CODEC_CONFIG or BUFFER_FLAG_END_OF_STREAM . |
Throws
MediaCodec.CryptoException | if an error occurs while attempting to decrypt the buffer. An error code associated with the exception helps identify the reason for the failure. |
---|
public final void releaseOutputBuffer (int index, boolean render)
如果你处理完这个buffer, 调用这个函数把buffer重新返回给codec. 如果你在之前configure()的时候为组件配置了一个surface,那么codec类会在那个surface上显示这个buffer
Parameters
index | 由codec对象拥有的,由 dequeueOutputBuffer(MediaCodec.BufferInfo, long)返回的索引Index. |
---|---|
render | 如果有可用的显示surface,传递为true可表示显示。 |
public final void setParameters (Bundle params)
可以给组件加上一些附加参数(具体参数文档没写,估计是仍在测试阶段)
public final void setVideoScalingMode (int mode)
如果在 configure(MediaFormat, Surface, MediaCrypto, int)传入了surface,可以通过这个函数来设置显示模式。
public final void signalEndOfInputStream ()
标志输入流的结束。 作用于传递 BUFFER_FLAG_END_OF_STREAM
下标相同. 但是这个函数只用在把createInputSurface()返回的surface作为输入,且codec是编码器的情况。
public final void start ()
在成功配置组件后, 调用start()函数。相应的可以通过函数 操作inputbuffer和outputbuffer。
MediaCodec文档翻译的更多相关文章
- 我是如何进行Spring MVC文档翻译项目的环境搭建、项目管理及自动化构建工作的
感兴趣的同学可以关注这个翻译项目 . 我的博客原文 和 我的Github 前段时间翻译的Spring MVC官方文档完成了第一稿,相关的文章和仓库可以点击以下链接.这篇文章,主要是总结一下这个翻译项目 ...
- Hibernate 3.3.2 文档翻译 Day01
Hibernate 3.3.2 文档翻译 翻译人:微冷的雨 第一次书写:2015年11月29日 本人呕心沥血之作,请细心阅读领悟! Day01-1.1 项目描述 微冷的雨翻译:例如,我们将要建立一个可 ...
- Flume官方文档翻译——Flume 1.7.0 User Guide (unreleased version)中一些知识点
Flume官方文档翻译--Flume 1.7.0 User Guide (unreleased version)(一) Flume官方文档翻译--Flume 1.7.0 User Guide (unr ...
- Flume官方文档翻译——Flume 1.7.0 User Guide (unreleased version)(二)
Flume官方文档翻译--Flume 1.7.0 User Guide (unreleased version)(一) Logging raw data(记录原始数据) Logging the raw ...
- Android多媒体--MediaCodec 中文API文档
*由于工作需要,需要利用MediaCodec实现Playback及Transcode等功能,故在学习过程中翻译了Google官方的MediaCodec API文档,由于作者水平限制,文中难免有错误和不 ...
- 【Android】Android Camera实时数据采集及通过MediaCodec硬编码编码数据的流程
吐槽: 其实常用流程都差不多,但是有时候还是会忘记某一步的详细用法,但是各位朋友请注意,官方已经不推荐Camera类的使用(现在是android.hardware.camera2),但无奈公司项目之前 ...
- Android官方多媒体API Mediacodec翻译(一)
因近期工作调整,关于Mediacodec部分的翻译会暂停,后续有时间一定补上,非常抱歉. 本文章为根据Android Mediacodec官方英文版的原创翻译,转载请注明出处:http://www.c ...
- SQLAlchemy 中文文档翻译计划
SQLAlchemy 中文文档翻译计划已启动. Python 文档协作翻译小组人手紧缺,有兴趣的朋友可以加入我们,完全公益性质.交流群:467338606. 希望大家能够勇敢地去翻译和改进翻译.虽然我 ...
- Laravel 5.3 中文文档翻译完成
经过一个多月的紧张翻译和校对,翻译完成.以下是参与人员: Laravel 5.3 中文文档翻译完成 稿源:七星互联www . qixoo.com 文档地址在此:https://laravel-chin ...
随机推荐
- phpcms栏目调用
{loop subcat(0,0,0,$siteid) $r} {php $num++} <h3><a href="{$r[url]}">{$r[catna ...
- 【转】HTML5 LocalStorage 本地存储
原文见:http://www.cnblogs.com/xiaowei0705/archive/2011/04/19/2021372.html 说到本地存储,这玩意真是历尽千辛万苦才走到HTML5这一步 ...
- MySql拾遗
1.“1130-Host is not allowed to connect to this MySQL server” 满世界的人都告诉你,到user表中把root + localhost的“loc ...
- java-web-j2e学习建议路线
JAVA学习之路(2) 首先要明白Java体系设计到得三个方面:J2SE,J2EE,J2ME(KJAVA).J2SE,Java 2 Platform Standard Edition,我们经常说 ...
- arm-none-eabi-gcc install
Zephyr除了官方的编译工具,还有第三方工具 arm-none-eabi-gcc . This PPA is an alternative to toolchain released at http ...
- Recovery和Charger模式下屏幕旋转180度[转]
如何让Recovery (系统固件升级),charger(关机充电动画)时屏幕旋转180度 解决方法: 1.在bootable\recovery\minui\Graphics.c 文件找到gr_fli ...
- Dao 处理
1. 写一个基础的接口和类来做基本的操作 /** * */ package com.wolfgang.dao; import java.util.List; /** * @author Adminis ...
- c#:for循环;穷举,迭代 练习
一)穷举 1. 第x种买法:羽毛球拍xx个,羽毛球xx个,水xx瓶 2. 单位给发了一张150元购物卡,拿着到超市买三类洗化用品. 洗发水15元,香皂2元,牙刷5元.求刚好花完150元,有多少 ...
- Android Wear计时器开发
记得在2013年12月的时候,有系列文章是介绍怎么开发一个智能手表的App,让用户可以在足球比赛中记录停表时间.随着Android Wear的问世,在可穿戴设备中开发一款这样的App确实是个很不错的想 ...
- Lesson 6: CronTrigger
CronTrigger is often more useful than SimpleTrigger, if you need a job-firing schedule that recurs b ...