前言
MediaCodec
是API 16
之后Google
推出的用于音视频编解码的一套可访问底层的媒体的API
,可以直接利用硬件加速进行视频的编解码。调用的时候需要先初始化MediaCodec
作为视频的编码器,然后只需要不停传入原始的YUV
数据进入编码器就可以直接输出编码好的h264
流。
通常与 MediaExtractor, MediaSync, MediaMuxer, MediaCrypto, MediaDrm, Image, Surface, and AudioTrack 一起结合使用
相关资源
一些示例代码和常见问题的答案。
https://bigflake.com/mediacodec/
MediaCodec类官网介绍
https://developer.android.com/reference/android/media/MediaCodec.html
编解码的过程
图来自官网
一、创建MediaCodec对象
编码MediaCodec.createByCodecName(name)
解码MediaCodec.createDecoderByType(type)
二、配置状态configure(…)
三、进入执行状态 start()
执行状态中进行数据处理编码
dequeueInputBuffer
获取输入队列空闲数组下标getInputBuffer
获取输入队列,queueInputBuffer
把原始YUV数据送入编码器dequeueOutputBuffer
获取输出队列空闲数组下标getOutputBuffer
获取输出的h264流releaseOutputBuffer
把输出buffer还给系统,重新放到输出队列中
四、退出进入未初始化状态 stop()
五、释放对象及相关资源 release()
用ByteBuffer
编码例子1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28MediaCodec 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.releaseOutputBuffer(outputBufferId, …);
} else if (outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
// Subsequent data will conform to new format.
// Can ignore if using getOutputFormat(outputBufferId)
outputFormat = codec.getOutputFormat(); // option B
}
}
codec.stop();
codec.release();
用Buffer数组
编码例子1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26MediaCodec codec = MediaCodec.createByCodecName(name);
codec.configure(format, …);
codec.start();
ByteBuffer[] inputBuffers = codec.getInputBuffers();
ByteBuffer[] outputBuffers = codec.getOutputBuffers();
for (;;) {
int inputBufferId = codec.dequeueInputBuffer(…);
if (inputBufferId >= 0) {
// fill inputBuffers[inputBufferId] with valid data
…
codec.queueInputBuffer(inputBufferId, …);
}
int outputBufferId = codec.dequeueOutputBuffer(…);
if (outputBufferId >= 0) {
// outputBuffers[outputBufferId] is ready to be processed or rendered.
…
codec.releaseOutputBuffer(outputBufferId, …);
} else if (outputBufferId == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
outputBuffers = codec.getOutputBuffers();
} else if (outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
// Subsequent data will conform to new format.
MediaFormat format = codec.getOutputFormat();
}
}
codec.stop();
codec.release();