Android MediaCodec实现多段音视频的截取与拼接

很早以前收藏的一篇文章,本想再访问原作者的blog,好像涉嫌违规被关了,只得遗憾了,不过还好是收藏了,此前在总结多媒体框架时,MediaCodeC作为编解码的重要角色,一起看下今天Android MediaCodec实现多段音视频的截取与拼接。

视音频编辑中,对多段媒体素材进行截取和拼接是非常常见的操作。截取和拼接实际上是对媒体文件数据重新进行组合的过程。

要实现这些功能,就需要对媒体文件进行编解码操作,即先解码要处理的媒体文件数据,然后再按照某种规则对这些数据进行编码,以生成我们所需的目标。

Android提供的MediaCodec及其相关类为我们提供了所需的方法,这些类主要包括:MediaCodec、MediaExtractor、MediaMuxer、MediaFormat。

MediaCodec用于创建视音频编解码器,通过它可以对视音频数据进行编解码操作,它是编解码功能的核心类。

MediaExtractor相当于一个reader,它用于读取媒体文件,并提取出其中的视音频数据。

MediaMuxer相当于一个writer,它用于将内存中的视音频数据写到文件中。

MediaFormat即媒体格式类,它用于描述媒体的格式参数,如视频帧率、音频采样率等。

对视音频文件进行截取与拼接的主要过程是:先创建视音频编解码器,再分别启动视频线程和音频线程,以分别对视音频数据进行解码、编码,最后将编码好的数据写入文件。

主要逻辑如下,关键是三处线程同步的地方,具体原因稍后解释。

再来了解一下这几个类的“脾气”。

一般用MediaCodec创建编解码器时,使用的都是createDecoderByType方法,但在用三星PAD(API LEVEL 18, Android version 4.3)调试时发现,调用该方法创建音频编码器时会出错。故改为使用createByCodecName("OMX.SEC.aac.enc")创建音频编码器。估计这是一个API bug。

configure decoder时,第一个格式参数要与源的格式相同,这里可以先通过extractor将源的格式读出来,再直接传给configure方法。configure encoder时,需设定几个必要的参数,具体请参考官方说明。

当把全部要处理的数据灌给编解码器后,使用queueInputBuffer(inputBufIndex,0, 0, 0L, MediaCodec.BUFFER_FLAG_END_OF_STREAM)方法来通知编解码器结束工作。之后,在OutputBuffer的bufferInfo中,将携带这个标志,通过判断是否有这个标志,我们就可以断定数据是否都已处理完成,以进行后续操作。再之后,dequeueOutputBuffer的返回都将是INFO_TRY_AGAIN_LATER。当然,如果你自己有办法在OutputBuffer中判断数据是否灌完,也可以不使用此标志。

当数据灌完后,要使用releaseOutputBuffer,把缓冲区释放掉。否则,你会发现queueInputBuffer总是返回-1,因为没有空闲的缓冲区了。

MediaExtractor用来读取源文件,给定文件路径后,便可将其中的视音频数据拿出来。关键是它的seekTo方法,它用于对读取数据的游标进行定位,可以定位到指定点前的最后一个sync点、指定点后的第一个sync点,或者与指定点最近的sync点。对于H.264数据,sync点可以认为是视频关键帧的时码位置。

MediaMuxer的使用非常简单,先创建,再添加视音频轨,然后start,再writeSampleData,最后stop。需要注意的是,必需先添加完所有的视音频轨后,再去start,而不能先start,再试图去addTrack,否则会出错。这也是为什么在本文的逻辑中,视频线程需要去wait音频线程添加完音频轨后再继续的原因。

需要注意的是,不能在启动完编解码器后,立即调用getOutputFormat企图addTrack,而应该在dequeueOutputBuffer后的INFO_OUTPUT_FORMAT_CHANGED中调用,否则会出错。

当要向文件中同时写入视频和音频数据时,必需先writeSampleData所有视频数据,再写音频数据,或者反之,即二者必需连续调用writeSampleData,不能交叉调用,否则写出的文件会有问题。这也是本文中为何muxer启动后,音频线程需等待视频线程先写完数据,自己才能继续干活的原因。

当所有的writeSampleData完成后,不要忘记调用stop和release,否则写出的文件也会有问题。

最后还要注意,这几个类中,时间单位都是微秒。

下面我来补充mediaCodec的支持的格式,MediaCodec更多详情,会在Camera相关框架分析中,会隆重介绍的:

MediaCodec支持的格式:

  • "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

原文发布于微信公众号 - 何俊林(DriodDeveloper)

原文发表时间:2016-11-11

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏freesan44

python 携程爬虫开发笔记

最近购买了《Python3 爬虫、数据清洗与可视化实战》,刚好适逢暑假,就尝试从携程页面对广州的周边游产品进行爬虫数据捕捉。 因为才学Python不够一个星期...

5801
来自专栏飞总聊IT

Log:被BigData遗忘的奠基者

Log是关系数据库对计算机行业的伟大贡献。在大数据时代,Log更是基础技术之一。然而在大家热烈讨论GFS, NoSQL,乃至Paxos, LSM tree等词语...

3777
来自专栏Crossin的编程教室

用程序帮你炒股

最近在知乎上看到一个问题:如何使用 Python 抓取雪球网页? 雪球是国内一个人气很高的股票财经类网站,上面有个投资组合功能,很多民间股神在上面设定自己的投资...

3637
来自专栏JackieZheng

解决Myeclipse下Debug出现Source not found以及sql server中导入数据报错

前言:在空间里回顾了我的2014,从生活、技术、家庭等各方面对自己进行总结剖析,也是给自己一个交代。也想在博客上专门写一篇2014年度菜鸟的技术路回忆录,但是...

3185
来自专栏人工智能头条

Python热门文章推荐Top10

1704
来自专栏hbbliyong

设计模式学习--面向对象的5条设计原则之开放封闭原则--OCP

一、OCP简介(OCP--Open-Closed Principle): Software entities(classes,modules,functions...

2988
来自专栏斑斓

当DDD遇上微服务

DDD与微服务是可以相通的,其关键在于Bounded Context。 分布式系统的定义 在谈论这个之前,我们需要就什么是分布式系统达成一致。在我看来,判断一个...

4225
来自专栏数据派THU

手把手教你用Pandas透视表处理数据(附学习资料)

来源:伯乐在线 - PyPer 本文共2203字,建议阅读5分钟。 本文重点解释pandas中的函数pivot_table,并教大家如何使用它来进行数据分析...

2435
来自专栏编程一生

ORM规约变更经典案例---mysql军规

1314
来自专栏带你撸出一手好代码

使用测试用例来约束自己的代码

写测试代码这种事情 ,以前只在网上和书上看到过, 自己从来没有写过。 每当看到那些世界顶级程序员编写的技术书籍中出现“测试用例”“测试代码”的字样或者一些行业的...

3776

扫码关注云+社区

领取腾讯云代金券