Android的MediaCodec详解

简介

应用程序对音频和视频数据进行编码(压缩)和解码(解压缩)。通过MediaCodec,开发者可以直接访问底层的编解码器,实现更高效的音视频处理,并支持硬件加速,从而提高编解码的性能。

工作原理

MediaCodec采用异步的方式处理两路数据流:输入流(input)和输出流(output)。输入流用于接收待解码或待编码的数据,而输出流则用于输出已解码或已编码的数据。

  • 在编码过程中,MediaCodec不断从输入缓冲区中读取原始数据(如YUV格式的视频帧),经过编码后,从输出缓冲区获取压缩后的数据(如H.264格式的视频流)。
  • 解码过程则相反,MediaCodec从输入缓冲区读取压缩后的数据,解码后输出原始数据到输出缓冲区。

在这里插入图片描述

生命周期

MediaCodec在不同的数据处理模式下,其状态会有所不同。MediaCodec的三种主要状态包括:停止态(Stopped)、执行态(Executing)和释放态(Released)。其中,停止态和执行态又分别包含多个子状态:
在这里插入图片描述

  • 未初始化状态(Uninitialized):MediaCodec对象刚被创建,尚未进行配置。
  • 配置状态(Configured):MediaCodec已经通过configure()方法进行了配置,但尚未启动。
  • 错误状态(Error):MediaCodec在编解码过程中遇到错误,需要重置或释放。
  • 刷新状态(Flushed):MediaCodec已经启动,但尚未处理任何数据,或者已经通过flush()方法被清空。
  • 运行状态(Running):MediaCodec正在处理数据,可以从输入缓冲区读取数据,并向输出缓冲区写入数据。
  • 流结束状态(End-of-Stream):MediaCodec已经处理完所有输入数据,不再有新的数据输入。

使用

//创建MediaCodec
MediaCodec codec = MediaCodec.createEncoderByType("video/avc");
MediaFormat format = MediaFormat.createVideoFormat("video/avc", width, height);
//码率
format.setInteger(MediaFormat.KEY_BIT_RATE, 5000000);
//帧率
format.setInteger(MediaFormat.KEY_FRAME_RATE, 20);
//关键帧
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 2);
//颜色空间
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedPlanar);

codec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
codec.start();

//把待解码或待编码的数据放入MediaCodec的缓冲区中
int index = mediaCodec.dequeueInputBuffer(timeoutUs);
if (index >= 0) {
   ByteBuffer inputBuffer = mediaCodec.getInputBuffer(index);
   inputBuffer.clear();
   inputBuffer.put(buffer);
   //填充的数据加入队列
   mediaCodec.queueInputBuffer(index, 0,
                            buffer.length, System.nanoTime() / 1000, 0);
}

//获取已解码或已编码的数据
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
int encode = mediaCodec.dequeueOutputBuffer(bufferInfo, timeoutEn);
if (encode >= 0) {
   ByteBuffer outputBuffer = mediaCodec.getOutputBuffer(encode);
   MediaFormat bufferFormat = mediaCodec.getOutputFormat(encode);
                    mediaCodec.releaseOutputBuffer(encode,false);
}

常用的API

//获取解码器对象。
public static MediaCodec createDecoderByType(String type) 
//获取编码器对象。
public static MediaCodec createEncoderByType(String type)
//开始
public void start()
//结束
public void stop()
//创建输入缓冲Surface(用于视频编码)。
public native Surface createInputSurface()
//设置输出缓冲Surface(用于视频解码)。
public void setOutputSurface(@NonNull Surface surface)
// 获取可用的输入缓冲区的索引
public int dequeueInputBuffer (long timeoutUs)
// 获取输入缓冲区
public ByteBuffer getInputBuffer(int index)
// 将填满数据的inputBuffer提交到编码队列
public final void queueInputBuffer(int index,int offset, int size, long presentationTimeUs, int flags)
// 获取已成功编解码的输出缓冲区的索引
public final int dequeueOutputBuffer(BufferInfo info, long timeoutUs)
// 获取输出缓冲区
public ByteBuffer getOutputBuffer(int index)
// 释放输出缓冲区
public final void releaseOutputBuffer(int index, boolean render) 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值