版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zxd_Android/article/details/81436090
上一篇讲了如何采集摄像头画面并且进行编码,再进行封装成MP4格式文件,如需了解可以看 安卓采集摄像头画面生成MP4文件
本篇博客,主要讲解如何对MP4文件进行解封装,再进行解H264码流,进行画面显示。
Android 使用MediaCodec进行视频编解码工作,这里解码当然还由其来完成,那从MP4文件中提取出H264码流的工作,由MediaExtractor完成
MediaExtractor的使用比较简单:
mediaExtractor = new MediaExtractor();
//设置MP4文件存放的位置
mediaExtractor.setDataSource(path);
Log.d(TAG, "getTrackCount: " + mediaExtractor.getTrackCount());
for (int i = 0; i < mediaExtractor.getTrackCount(); i++) {
MediaFormat format = mediaExtractor.getTrackFormat(i);
String mime = format.getString(MediaFormat.KEY_MIME);
//如果是video格式
if (mime.startsWith("video")) {
mediaFormat = format;
mediaExtractor.selectTrack(i);
}
}
2、解码器MediaCodec初始化如下
mediaCodec = MediaCodec.createDecoderByType("video/avc");
mediaFormat = MediaFormat.createVideoFormat("video/avc", 1280, 720);
Surface surface = MainActivity.surfaceHolder.getSurface();
//必须配置一个surface,作为其输出解码显示画面
mediaCodec.configure(mediaFormat, surface, null, 0);
mediaCodec.start();
3、开启解码线程
/**
* Play the MP4 file Thread
*/
private class DecoderMP4Thread extends Thread {
long pts = 0;
@Override
public void run() {
super.run();
while (!isDecodeFinish) {
int inputIndex = mediaCodec.dequeueInputBuffer(-1);
Log.d(TAG, "inputIndex: " + inputIndex);
if (inputIndex >= 0) {
ByteBuffer byteBuffer = mediaCodec.getInputBuffer(inputIndex);
//读取一片或者一帧数据
int sampSize = mediaExtractor.readSampleData(byteBuffer,0);
//读取时间戳
long time = mediaExtractor.getSampleTime();
Log.d(TAG, "sampSize: " + sampSize + "time: " + time);
if (sampSize > 0 && time > 0) {
mediaCodec.queueInputBuffer(inputIndex, 0, sampSize, time, 0);
//读取一帧后必须调用,提取下一帧
mediaExtractor.advance();
//控制帧率在30帧左右
try {
sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
BufferInfo bufferInfo = new BufferInfo();
int outIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0);
Log.d(TAG, "outIndex: " + outIndex);
if (outIndex >= 0) {
mediaCodec.releaseOutputBuffer(outIndex, true);
}
}
}
}
4、最后结束的时候,别忘了释放资源
public void close() {
if (mediaCodec != null) {
mediaCodec.stop();
mediaCodec.release();
isDecodeFinish=true;
}
}
怎么样,是不是整个流程比较简单啊,so easy.
代码资源下载地址:https://download.csdn.net/download/zxd_android/10584840