MediaMuxer 封装器
MediaMuxer 最多仅支持一个视频 track 和一个音频 track,所以如果有多个音频 track 可以先
把它们混合成为一个音频 track 然后再使用 MediaMuxer 封装到 mp4 容器中。
MediaMuxer 支持输出格式为 MP4,webm 和 3gp. 默认我们就用 mp4. MUXER_OUTPUT_3GPP:对应 3gp 文件,
MUXER_OUTPUT_HEIF:定影 HEIF 文件,
MUXER_OUTPUT_MPEG_4:对应 mp4 文件,
MUXER_OUTPUT_WEBM:对应 webm 文件。
主要函数说明:
addTrack(MediaFormat format):利用 MediaFormat 添加音频或视频轨道。
release():释放 MediaMuxer 的资源。
setLocation(float latitude,float longitude):设置并存储地理位置信息到生成文件中。
setOrientationHint(int degrees):设置输出视频回放的方向提示。
start() :开始 muxer,等待数据的输入。
Stop():停止 muxer,调用这个函数后将生成合成的文件。
writeSampleData(int trackIndex, ByteBuffer byteBuf, MediaCodec.BufferInfo bufferInfo):往 muxer 中写入编码的数据。
参数说明:
trackIndex:sample(样本)的 track index,可以利用 MediaExtractor 获取。
byteBuf:写入的数据,不可为 null;
bufferInfo:当前 sample(样本)相关的 buffer 的信息,不可为 null。
MediaCodec.BufferInfo:
主要包括四个数据:
flags:输入 buffer 相关的 buffer flags。
offset:buffer 开始的偏移量,通常设为 0。
presentationTimeUs:buffer 的时间戳。
size:buffer 的数据大小。
我们看下例子:
MediaMuxer muxer = new MediaMuxer(“temp.mp4”, OutputFormat.MUXER_OUTPUT_MPEG_4);
// More often, the MediaFormat will be retrieved from MediaCodec.getOutputFormat()
// or MediaExtractor.getTrackFormat(). MediaFormat audioFormat = new MediaFormat(…);
MediaFormat videoFormat = new MediaFormat(…);
int audioTrackIndex = muxer.addTrack(audioFormat);
int videoTrackIndex = muxer.addTrack(videoFormat);
ByteBuffer inputBuffer = ByteBuffer.allocate(bufferSize);
boolean finished = false;
BufferInfo bufferInfo = new BufferInfo();
muxer.start();
while(!finished) {
// getInputBuffer() will fill the inputBuffer with one frame of encoded
// sample from either MediaCodec or MediaExtractor, set isAudioSample to
// true when the sample is audio data, set up all the fields of bufferInfo, // and return true if there are no more samples. finished = getInputBuffer(inputBuffer, isAudioSample, bufferInfo);
if (!finished) {
int currentTrackIndex = isAudioSample ? audioTrackIndex : videoTrackIndex;
muxer.writeSampleData(currentTrackIndex, inputBuffer, bufferInfo);
}};
muxer.stop();
muxer.release();
主要流程,创建混合 MediaMuxer
addTrack 加入从 MediaExtractor 解出来的轨道信息
调用开始,启动
MediaMuxer.writeSampleData() 写入数据,每次只有一个视频或者音频信息
完成了这块知识,下来我们进入核心领域,编码 MediaCodec。MediaCodec 介绍
MediaCodec 类可以用于使用一些基本的多媒体编解码器(音视频编解码组件),它是 Android
基本的多媒体支持基础架构的一部分通常和 MediaExtractor , MediaSync , MediaMuxer , MediaCrypto , MediaDrm , Image , Surface , and AudioTrack 一起使用。
一个编解码器可以处理输入的数据来产生输出的数据,编解码器使用一组输入和输出缓冲器
来异步处理数据。你可以创建一个空的输入缓冲区,填充数据后发送到编解码器进行处理。
编解码器使用输入的数据进行转换,然后输出到一个空的输出缓冲区。最后你获取到输出缓
冲区的数据,消耗掉里面的数据, 释放回编解码器。如果后续还有数据需要继续处理,编
解码器就会重复这些操作。输出流程如下:
编解码器能处理的数据类型为:**压缩数据、原始音频数据和原始视频数据。**你可以通过
ByteBuffers 能够处理这三种数据,但是需要你提供一个 Surface,用于对原始的视频数据进
行展示,这样也能提高编解码的性能。
Surface 使用的是本地的视频缓冲区,这个缓冲区不映射或拷贝到 ByteBuffers。这样的机制
让编解码器的效率更高。通常在使用 Surface 的时候,无法访问原始的视频数据,但是你可
以使用 ImageReader 访问解码后的原始视频帧。在使用 ByteBuffer 的模式下,您可以使用
Image 类和 getInput/OutputImage(int)访问原始视频帧。编解码器的生命周期:
主要的生命周期为:Stopped、Executing、Released。
Stopped 的状态下也分为三种子状态:Uninitialized、Configured、Error。
Executing 的状态下也分为三种子状态:Flushed, Running、End-of-Stream。