Android的视频相干的开辟,大年夜概一向是全部Android生态,以及Android API中,最为决裂以及兼容性问题最为凸起的一部分。摄像头,以及视频编码相干的API,Google一向对这方面的┞菲握力异常差,导致不合厂商对这两个API的实现有不少差别,并且大年夜API的设计来看,一向以来竽暌古化也相当有限,甚至有人认为这是“Android上最难用的API之一”
以微信为例,我们录制一个540p的mp4文件,对于Android来说,大年夜体上是遵守这么一个流程:
膳绫擎只是针对视频流的编码,别的还须要对音频流零丁录制,最后再将视频流和音频流进行合成出最终视频。
视频编码器的选择
对于录制视频的需求,不少app都须要对每一帧数据进行零丁处理,是以很少会直接用到 MediaRecorder 来直接登科视频,一般来说,会有这么两个选择
- MediaCodec
- FFMpeg+x264/openh264
我们来逐个解析一下
MediaCodec
MediaCodec是API 16之后Google推出的用于音视频编解码的一套偏底层的API,可以直接应用硬件加快进行视频的编解码。调用的时刻须要先初始化MediaCodec作为视频的编码器,然后只须要一向传入原始的YUV数据进入编码器就可以直接输出编码好的h264流,全部API设计模型来看,就是同时包含了输入端和输出端的两条队列:
是以,作为编码器,输入端队列存放的就是原始YUV数据,输出端队列输出的就是编码好的h264流,作为解码器则对应相反。在调用的时刻,MediaCodec供给了同步和异仓站种调用方法,然则异步应用Callback的方法是在API 21之后才参加的,以同步调用为例,一般来说调用方法大年夜概是如许(摘自官方例子):
- MediaCodec codec = MediaCodec.createByCodecName(name);
- codec.configure(format, …);
- MediaFormat outputFormat = codec.getOutputFormat(); // option B
- codec.start();
- for (;;) {
- int inputBufferId = codec.dequeueInputBuffer(timeoutUs);
- if (inputBufferId >= 0) {
- ByteBuffer inputBuffer = codec.getInputBuffer(…);
- // fill inputBuffer with valid data
- …
- codec.queueInputBuffer(inputBufferId, …);
- }
- int outputBufferId = codec.dequeueOutputBuffer(…);
- if (outputBufferId >= 0) {
- ByteBuffer outputBuffer = codec.getOutputBuffer(outputBufferId);
- MediaFormat bufferFormat = codec.getOutputFormat(outputBufferId); // option A
- // bufferFormat is identical to outputFormat
- // outputBuffer is ready to be processed or rendered.
- …
- codec.relea搜刮引擎优化utputBuffer(outputBufferId, …);
- } else if (outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
- // Subsequent data will conform to new format.
推荐阅读
我们计算编写这些函数异常简单的版本,但真正的调试器有 thread plan 的概念,它封装了所有的单步信息。例如,调试器可能有一些复杂的逻辑去决定断点的地位,然后有一些回调函数用于断定>>>详细阅读
本文标题:谈谈关于Android视频编码的那些坑
地址:http://www.17bianji.com/lsqh/36974.html
1/2 1