转载请注明出处:http://blog.youkuaiyun.com/a512337862/article/details/72629779
最近开始接触Android MediaCodec,经过学习之后总算是有点简单的收获,所以在这里总结一下,希望能帮到一些有需要的人。今天主要是关于利用MediaCodec解码H264文件之后利用SurfaceView进行显示:
封装解码器
这部分代码主要功能是对MediaCodec进行封装,实现MediaCodec初始化以及一些配置,并提供解码的h264视频帧的方法:
/**
* Created by ZhangHao on 2016/8/5.
* 用于硬件解码(MediaCodec)H264的工具类
*/
public class MediaCodecUtil {
//自定义的log打印,可以无视
Logger logger = Logger.getLogger();
private String TAG = "MediaCodecUtil";
//解码后显示的surface及其宽高
private SurfaceHolder holder;
private int width, height;
//解码器
private MediaCodec mCodec;
private boolean isFirst = true;
// 需要解码的类型
private final static String MIME_TYPE = "video/avc"; // H.264 Advanced Video
private final static int TIME_INTERNAL = 5;
/**
* 初始化解码器
*
* @param holder 用于显示视频的surface
* @param width surface宽
* @param height surface高
*/
public MediaCodecUtil(SurfaceHolder holder, int width, int height) {
// logger.d("MediaCodecUtil() called with: " + "holder = [" + holder + "], " +
// "width = [" + width + "], height = [" + height + "]");
this.holder = holder;
this.width = width;
this.height = height;
}
public MediaCodecUtil(SurfaceHolder holder) {
this(holder, holder.getSurfaceFrame().width(), holder.getSurfaceFrame().height());
}
public void startCodec() {
if (isFirst) {
//第一次打开则初始化解码器
initDecoder();
}
}
private void initDecoder() {
try {
//根据需要解码的类型创建解码器
mCodec = MediaCodec.createDecoderByType(MIME_TYPE);
} catch (IOException e) {
e.printStackTrace();
}
//初始化MediaFormat
MediaFormat mediaFormat = MediaFormat.createVideoFormat(MIME_TYPE,
width, height);
//配置MediaFormat以及需要显示的surface
mCodec.configure(mediaFormat, holder.getSurface(), null, 0);
//开始解码
mCodec.start();
isFirst = false;
}
int mCount = 0;
public boolean onFrame(byte[] buf, int offset, int length) {
// 获取输入buffer index
ByteBuffer[] inputBuffers = mCodec.getInputBuffers();
//-1表示一直等待;0表示不等待;其他大于0的参数表示等待毫秒数
int inputBufferIndex = mCodec.dequeueInputBuffer(-1);
if (inputBufferIndex >= 0) {
ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
//清空buffer
inputBuffer.clear();
//put需要解码的数据
inputBuffer.put(buf, offset, length);
//解码
mCodec.queueInputBuffer(inputBufferIndex, 0, length, mCount * TIME_INTERNAL, 0);
mCount++;
} else {
return