作者:anddymao
背景
MediaCodec 作为Android自带的视频编解码工具,可以直接利用底层硬件编解码能力,现在已经逐渐成为主流了。API21已经支持NDK方法了,MediaCodec api设计得非常精妙,另一个方面也是很多人觉得不好懂。
内容
MediaCodec的两个Buffer和三板斧
MediaCodec内部包含InputBuffer和OutputBuffer,内部有一个自启线程,不断去查询两个Buffer,是一个生产者消费者模型。
进行数据处理时主要靠三板斧。
- 第一步:取buffer地址
AMediaCodec_dequeueInputBuffer
- 第二步:获取buffer数据
AMediaCodec_getInputBuffer
- 第三步:buffer入队
AMediaCodec_queueInputBuffer
InputBuffer和OutputBuffer基本是对称的:
- 第一步:取buffer地址
AMediaCodec_dequeueOutputBuffer
- 第二步:获取buffer数据
AMediaCodec_getOutputBuffer
- 第三步:buffer释放
AMediaCodec_releaseOutputBuffer
只有第三步不同,AMediaCodec_queueInputBuffer是数据入队等待消费,AMediaCodec_releaseOutputBuffer是释放数据。
编码和解码过程,InputBuffer和OutputBuffer就互相置换下。
解码:原始数据(视频流)-> 提取器AMediaExtractor->InputBuffer->OutputBuffer->帧数据(YUV420sp,PCM)
编码:帧数据(视频流)->InputBuffer->OutputBuffer->合成器AMediaMuxer
解码
解码配置
解码开始需要配置AMediaCodec和AMediaExtractor,MediaCodec start后就可以开始解码。
AMediaExtractor需要设置文件描述符,通过AAssetManager_open或者fopen就可以得到。起始点和长度也同样。然后设置进提取器。
AMediaExtractor_setDataSourceFd(mExtractor,
virtualFile.fd,
virtualFile.start,
virtualFile.length);
AMediaCodec创建需要设置数据格式,通过AMediaExtractor获取到的AMediaFormat可以得到mime和format。
mCodec = AMediaCodec_createDecoderByType(mime);
AMediaCodec_configure(mCodec, format, NULL, NULL, 0);
AMediaCodec_start(mCodec);
解码配置第三个参数为NativeWindow,加了后解码后可以直接吐到surface上,GPU数据直接渲软,效率高但不够灵活。不加的话解码数据就需要输出拷贝。
解码流程
解码也就是操作两个Buffer的过程,执行玩三板斧就可以,然后有一些状