下面就是对题目《Android音视频开发之MediaCodec的使用教程》的详细讲解攻略。
一、什么是MediaCodec
MediaCodec是Android SDK提供的一个非常重要的音视频编解码API。使用MediaCodec API可以完成音视频编码、解码的功能,其中不仅包含基于软编、硬编两种方式的编码,还有对应的软解、硬解方式的解码。在Android平台上,通过MediaCodec API实现的音视频编解码过程是非常高效和稳定的,因此广泛应用于各种场景中。
二、Video MediaCodec的使用
- 初始化MediaFormat
创建一个输入格式和输出格式。输入格式指明需要编码的数据的格式,如数据类型、帧率、码率等信息。输出格式指定数据的编码类型、视频大小等信息。
MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", WIDTH, HEIGHT);
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, BITRATE);
mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible);
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);
mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
- 创建MediaCodec实例
创建MediaCodec对象,第一个参数为指明需要编码的数据类型,这里为"video/avc",第二个参数为MediaFormat。
MediaCodec mediaCodec = MediaCodec.createEncoderByType("video/avc");
mediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
- 准备MediaCodec
调用MediaCodec的start()方法开启MediaCodec。
mediaCodec.start();
- 输入数据
通过MediaCodec的inputBuffer队列获取输入buffer,并向其中写入需要编码的数据。
int inputBufferIndex = mediaCodec.dequeueInputBuffer(-1);
if (inputBufferIndex >= 0) {
ByteBuffer inputBuffer = mediaCodec.getInputBuffer(inputBufferIndex);
inputBuffer.clear();
inputBuffer.put(inputFrameData, 0, inputFrameData.length);
mediaCodec.queueInputBuffer(inputBufferIndex, 0, inputFrameData.length, 0, 0);
}
- 输出编码数据
通过MediaCodec的outputBuffer队列获取输出buffer,并将其中的编码数据提取出来。
int outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0);
if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
//TODO 处理format change
} else if (outputBufferIndex >= 0) {
ByteBuffer outputBuffer = mediaCodec.getOutputBuffer(outputBufferIndex);
handleEncodedVideoData(outputBuffer, bufferInfo);
mediaCodec.releaseOutputBuffer(outputBufferIndex, false);
}
- 停止编码
停止编码需要分两个步骤:先停止输入,再停止输出。
mediaCodec.signalEndOfInputStream(); //停止输入
while (true) {
int outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0L);
if (outputBufferIndex < 0) {
break;
}
ByteBuffer outputBuffer = mediaCodec.getOutputBuffer(outputBufferIndex);
handleEncodedVideoData(outputBuffer, bufferInfo);
mediaCodec.releaseOutputBuffer(outputBufferIndex, false); //停止输出
}
三、Audio MediaCodec的使用
- 初始化MediaFormat
和Video MediaCodec使用类似,需要初始化输入输出format,在这里列举一下音频编码所需的一些参数。
MediaFormat mediaFormat = MediaFormat.createAudioFormat("audio/mp4a-latm", SAMPLE_RATE, CHANNEL_COUNT);
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE);
mediaFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
- 创建MediaCodec实例
同上,使用createEncoderByType方法创建一个codec对象,并进行configure配置。
MediaCodec mediaCodec = MediaCodec.createEncoderByType("audio/mp4a-latm");
mediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
- 准备MediaCodec
和Video MediaCodec准备过程类似,先start开启它。
mediaCodec.start();
- 输入和输出数据
输入数据,将Buffer写入输入队列中。由于编码音频不需要关心关键帧和非关键帧等问题,所以这里和Video MediaCodec直接对应不同。
int inputBufferIndex = mediaCodec.dequeueInputBuffer(-1);
if (inputBufferIndex >= 0) {
ByteBuffer inputBuffer = mediaCodec.getInputBuffer(inputBufferIndex);
inputBuffer.clear();
inputBuffer.put(inputFrameData, 0, inputFrameData.length);
mediaCodec.queueInputBuffer(inputBufferIndex, 0, inputFrameData.length, 0, 0);
}
int outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0);
if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
//TODO 处理format change
} else if (outputBufferIndex >= 0) {
ByteBuffer outputBuffer = mediaCodec.getOutputBuffer(outputBufferIndex);
handleEncodedAudioData(outputBuffer, bufferInfo);
mediaCodec.releaseOutputBuffer(outputBufferIndex, false);
}
- 停止编码
和Video MediaCodec一样,分两步走,先停止输入,再停止输出。
mediaCodec.signalEndOfInputStream(); //停止输入
while (true) {
int outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0L);
if (outputBufferIndex < 0) {
break;
}
ByteBuffer outputBuffer = mediaCodec.getOutputBuffer(outputBufferIndex);
handleEncodedAudioData(outputBuffer, bufferInfo);
mediaCodec.releaseOutputBuffer(outputBufferIndex, false); //停止输出
}
四、参考示例
这是一个基于MediaCodec录制视频的Demo,使用MediaCodec对摄像头采集到的YUV420数据进行编码,通过编码后的数据生成mp4文件,并添加sps和pps数据。
这是一个使用MediaCodec对音频进行编码的示例,主要是封装了底层的MediaCodec API,并提供了一些常用的音频编码参数供选择。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Android音视频开发之MediaCodec的使用教程 - Python技术站