MediaCodec|文档翻译

  classoverView

 mediacodec类可以用来调用系统底层的编码/解码软件。

 mediacodec一般是这么用的:

  1. MediaCodec codec = MediaCodec.createDecoderByType(type);
  2. codec.configure(format, ...);
  3. codec.start();
  4. ByteBuffer[] inputBuffers = codec.getInputBuffers();
  5. ByteBuffer[] outputBuffers = codec.getOutputBuffers();
  6. for (;;) {
  7. int inputBufferIndex = codec.dequeueInputBuffer(timeoutUs);
  8. if (inputBufferIndex >= 0) {
  9. // fill inputBuffers[inputBufferIndex] with valid data
  10. ...
  11. codec.queueInputBuffer(inputBufferIndex, ...);
  12. }
  13.  
  14. int outputBufferIndex = codec.dequeueOutputBuffer(timeoutUs);
  15. if (outputBufferIndex >= 0) {
  16. // outputBuffer is ready to be processed or rendered.
  17. ...
  18. codec.releaseOutputBuffer(outputBufferIndex, ...);
  19. } else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
  20. outputBuffers = codec.getOutputBuffers();
  21. } else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
  22. // Subsequent data will conform to new format.
  23. MediaFormat format = codec.getOutputFormat();
  24. ...
  25. }
  26. }
  27. codec.stop();
  28. codec.release();
  29. 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)

Added in API level 16

配置一个组件。

Parameters
format 如果为解码器,此处表示输入数据的格式;如果为编码器,此处表示输出数据的格式。
surface 指定一个surface,可用作decode的输出渲染。
crypto 如果需要给媒体数据加密,此处指定一个crypto类.
flags 如果正在配置的对象是用作编码器,此处加上CONFIGURE_FLAG_ENCODE 标签。

public static MediaCodec createByCodecName (String name)

Added in API level 16

如果你知道你想实例化的组件确切名字, 用这个方法来初始化它,谨慎使用这个函数,最好配合从 MediaCodecList获得的信息来使用。

Parameters
name 需要实例化的组件的名字.

public static MediaCodec createDecoderByType (String type)

Added in API level 16

用给定的媒体格式来创建一个解码器.下面是部分媒体格式和他们所对应的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)

Added in API level 16

按给定的媒体类型创建一个编码器。

Parameters
type 所需要的输出媒体格式.

public final Surface createInputSurface ()

Added in API level 18

请求一个surface作为解码器的输入(替代掉inputbuffer?).这个函数需要在  configure(MediaFormat, Surface, MediaCrypto, int) 之后 start()之前被调用。

程序应该自己调用release去释放这个 surface而不是等gc 去做。

public final int dequeueInputBuffer (long timeoutUs)

Added in API level 16

返回一个可用来填充有效数据的inputbuffer的索引(Index),如果返回-1表示暂无可用的buffer. 如果 timeoutUs == 0,该方法会立刻返回值, 如果 timeoutUs < 0 则一直等待,如果 timeoutUs > 0则等待对应时间.

Parameters
timeoutUs 单位为微秒, 负数表示无穷大.

public final int dequeueOutputBuffer (MediaCodec.BufferInfo info, long timeoutUs)

Added in API level 16

排一个output buffer, 等待“timeoutUs"后若无有效值则阻塞,单位为 microseconds. 返回成功解码的outputbuffer的索引 或者 一个 INFO_* constants 常量.

Parameters
info buffer的一些信息
timeoutUs 单位为微秒, 负数表示无穷大.

public final void flush ()

Added in API level 16

flush,重洗组件的input和output接口, 之前调用 dequeueInputBuffer(long) 和dequeueOutputBuffer(MediaCodec.BufferInfo, long) 排好的buffer都变成不可用。

public MediaCodecInfo getCodecInfo ()

Added in API level 18

获得codec的信息.如果codec是 createDecoderByType 或createEncoderByType创建的, 事先并不知道用的什么组件,那么 调用这个函数不会返回CodecInfo。

public ByteBuffer[] getInputBuffers ()

Added in API level 16

在start()之后可调用这个函数获得inputbuffer

public final String getName ()

Added in API level 18

获得这个组件的名字.

public ByteBuffer[] getOutputBuffers ()

Added in API level 16

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 ()

Added in API level 16

如果 dequeueOutputBuffer 返回INFO_OUTPUT_FORMAT_CHANGED ,调用这个函数。

public final void queueInputBuffer (int index, int offset, int size, long presentationTimeUs, int flags)

Added in API level 16

再给指定索引的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_FRAMEBUFFER_FLAG_CODEC_CONFIG , BUFFER_FLAG_END_OF_STREAM选一个,或者0~

public final void queueSecureInputBuffer (int index, int offset, MediaCodec.CryptoInfo info, long presentationTimeUs, int flags)

Added in API level 16

与 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_FRAMEBUFFER_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 release ()

Added in API level 16

在你调用这个函数的时候,确保释放了所以不需要用的组件,而不是依赖gc为你做这些事

public final void releaseOutputBuffer (int index, boolean render)

Added in API level 16

如果你处理完这个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)

Added in API level 19

可以给组件加上一些附加参数(具体参数文档没写,估计是仍在测试阶段)

public final void setVideoScalingMode (int mode)

Added in API level 16

如果在 configure(MediaFormat, Surface, MediaCrypto, int)传入了surface,可以通过这个函数来设置显示模式。

public final void signalEndOfInputStream ()

Added in API level 18

标志输入流的结束。 作用于传递 BUFFER_FLAG_END_OF_STREAM 下标相同. 但是这个函数只用在把createInputSurface()返回的surface作为输入,且codec是编码器的情况。

public final void start ()

Added in API level 16

在成功配置组件后, 调用start()函数。相应的可以通过函数 操作inputbuffer和outputbuffer。

public final void stop ()

Added in API level 16

停止,但是可以调用start()重开。如果要完全停止,调用release() 。

MediaCodec文档翻译的更多相关文章

  1. 我是如何进行Spring MVC文档翻译项目的环境搭建、项目管理及自动化构建工作的

    感兴趣的同学可以关注这个翻译项目 . 我的博客原文 和 我的Github 前段时间翻译的Spring MVC官方文档完成了第一稿,相关的文章和仓库可以点击以下链接.这篇文章,主要是总结一下这个翻译项目 ...

  2. Hibernate 3.3.2 文档翻译 Day01

    Hibernate 3.3.2 文档翻译 翻译人:微冷的雨 第一次书写:2015年11月29日 本人呕心沥血之作,请细心阅读领悟! Day01-1.1 项目描述 微冷的雨翻译:例如,我们将要建立一个可 ...

  3. 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 ...

  4. Flume官方文档翻译——Flume 1.7.0 User Guide (unreleased version)(二)

    Flume官方文档翻译--Flume 1.7.0 User Guide (unreleased version)(一) Logging raw data(记录原始数据) Logging the raw ...

  5. Android多媒体--MediaCodec 中文API文档

    *由于工作需要,需要利用MediaCodec实现Playback及Transcode等功能,故在学习过程中翻译了Google官方的MediaCodec API文档,由于作者水平限制,文中难免有错误和不 ...

  6. 【Android】Android Camera实时数据采集及通过MediaCodec硬编码编码数据的流程

    吐槽: 其实常用流程都差不多,但是有时候还是会忘记某一步的详细用法,但是各位朋友请注意,官方已经不推荐Camera类的使用(现在是android.hardware.camera2),但无奈公司项目之前 ...

  7. Android官方多媒体API Mediacodec翻译(一)

    因近期工作调整,关于Mediacodec部分的翻译会暂停,后续有时间一定补上,非常抱歉. 本文章为根据Android Mediacodec官方英文版的原创翻译,转载请注明出处:http://www.c ...

  8. SQLAlchemy 中文文档翻译计划

    SQLAlchemy 中文文档翻译计划已启动. Python 文档协作翻译小组人手紧缺,有兴趣的朋友可以加入我们,完全公益性质.交流群:467338606. 希望大家能够勇敢地去翻译和改进翻译.虽然我 ...

  9. Laravel 5.3 中文文档翻译完成

    经过一个多月的紧张翻译和校对,翻译完成.以下是参与人员: Laravel 5.3 中文文档翻译完成 稿源:七星互联www . qixoo.com 文档地址在此:https://laravel-chin ...

随机推荐

  1. Discuz!源代码阅读笔记之common.inc.php文件【1】

    <?php /* [Discuz!] (C)2001-2007 Comsenz Inc. This is NOT a freeware, use is subject to license te ...

  2. 老oj2146 && Pku2135 Farm Tour

    Description When FJ's friends visit him on the farm, he likes to show them around. His farm comprise ...

  3. eclipse问题解决(link方式安装插件失败)

    使用 link 方式,离线安装 eclipse 插件时,经常失败. 一.常见的失败情况 link方式配好后,eclipse 启动,没有弹出任何信息. 查看当前工作空间——.metadata——.log ...

  4. c#获取带有汉字的字符串长度

    不知道大家注意没,用c#下自带的str.Length方法获得字符串str长度的时候,返回的总是字符的个数,但是如果字符串中包含汉字的话,一个汉字是占两个字符长度的,获取的长度值就有了问题. 解决方案: ...

  5. IAR FOR ARM 各版本,需要的大家可以收藏了

    原创,原帖地址是在阿莫论坛:http://www.amobbs.com/thread-5400051-1-1.html,这里也在博客贴上来供大家参考. 用过Keil和IAR,个人感觉是IAR还是很不错 ...

  6. Sumdiv(各种数学)

    http://poj.org/problem?id=1845 题意:求A^B的所有约数的和再对9901取模: 做了这个学到了N多数学知识: 一:任意一个整数都可以唯一分解成素因子的乘积:A = p1^ ...

  7. P1894セチの祈り

    描述 在 Ninian 的花园里,有许多琼花,环绕着中间的凉亭.有 N 片琼花,组成一个环.Ninian 想在凉亭中发动 [セチの祈り] , 需要划分出三个区域的琼花,为了平均,要最大化面积最小的区域 ...

  8. Android 金融项目整理

    本来是安安心心周末休假的时间,却被强征来加班.魔都今天雾霾严重,窗外都看不到360无死角都能看到的东方明珠.吃完午饭后睡一觉起来,觉得该给自己做点事情了.那就把项目里面的一些可圈可点的技术都罗列出来, ...

  9. 读取App.config自定义标签的值

    一:程序截图 二:具体代码 config配置: <?xml version="1.0" encoding="utf-8" ?> <config ...

  10. HDU2222 Keywords Search(AC自动机)

    Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others ...