首先需要使用MediaExtractor
MediaExtractor extractor = new MediaExtractor();
设置本地视频
extractor.setDataSource(videoFilePath);
遍历视频所有轨道
for (int i = 0; i < extractor.getTrackCount(); i++)
获取轨道的格式
MediaFormat tempFormat = extractor.getTrackFormat(i);
String mime = tempFormat.getString(MediaFormat.KEY_MIME);
接下来进行视频的解码,先构造出一个解码器
MediaCodec codec = MediaCodec.createDecoderByType(format.getString(MediaFormat.KEY_MIME));
codec.configure(format, null, null, 0);
codec.start();
//初始化输入和输出缓冲区数组
ByteBuffer[] inputBuffers = codec.getInputBuffers();
ByteBuffer[] outputBuffers = codec.getOutputBuffers();
解码循环
while (!isEOS) {
int inputBufferIndex = codec.dequeueInputBuffer(10000);
if (inputBufferIndex >= 0) {
ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
int sampleSize = extractor.readSampleData(inputBuffer, 0);
long presentationTimeUs = extractor.getSampleTime();
if (sampleSize < 0) {
isEOS = true;
codec.queueInputBuffer(inputBufferIndex, 0, 0, 0, 0);
} else {
codec.queueInputBuffer(inputBufferIndex, 0, sampleSize, presentationTimeUs, 0);
extractor.advance();
}
}
// 输出解码的帧
int outputBufferIndex = codec.dequeueOutputBuffer(new MediaCodec.BufferInfo(), 2000);
while (outputBufferIndex >= 0) {
//将获取到的ByteBuffer数据转为byte[]
ByteBuffer outputBuffer = outputBuffers[outputBufferIndex];
byte[] yuvBytes = new byte[outputBuffer.remaining()];
outputBuffer.get(yuvBytes);
// 释放输出缓冲区
codec.releaseOutputBuffer(outputBufferIndex, false);
outputBufferIndex = codec.dequeueOutputBuffer(new MediaCodec.BufferInfo(), 0);
}
}
最后循环完成后记得将资源释放!!!
完整代码(根据代码提示自行添加try catch)
public static void extractFrames(String videoFilePath){
MediaExtractor extractor = new MediaExtractor();
extractor.setDataSource(videoFilePath);
MediaFormat format = null;
int trackIndex = -1;
// 找到视频轨道
for (int i = 0; i < extractor.getTrackCount(); i++) {
MediaFormat tempFormat = extractor.getTrackFormat(i);
String mime = tempFormat.getString(MediaFormat.KEY_MIME);
//检查MIME类型
if (mime.startsWith("video/")) {
format = tempFormat;
trackIndex = i;
extractor.selectTrack(trackIndex);
//获取视频的宽高(根据需求看是否需要)
width = format.getInteger(MediaFormat.KEY_WIDTH);
height = format.getInteger(MediaFormat.KEY_HEIGHT);
// 获取帧率(根据需求看是否需要)
int frameRate = format.getInteger(MediaFormat.KEY_FRAME_RATE);
if (frameRate < 0) {
frameRate = 0;
}
totalFrames = format.getLong(MediaFormat.KEY_DURATION) / 1000000 * frameRate;
break;
}
}
MediaCodec codec = MediaCodec.createDecoderByType(format.getString(MediaFormat.KEY_MIME));
codec.configure(format, null, null, 0);
codec.start();
//初始化输入和输出缓冲区数组
ByteBuffer[] inputBuffers = codec.getInputBuffers();
ByteBuffer[] outputBuffers = codec.getOutputBuffers();
boolean isEOS = false;
while (!isEOS) {
int inputBufferIndex = codec.dequeueInputBuffer(10000);
if (inputBufferIndex >= 0) {
ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
int sampleSize = extractor.readSampleData(inputBuffer, 0);
long presentationTimeUs = extractor.getSampleTime();
if (sampleSize < 0) {
isEOS = true;
codec.queueInputBuffer(inputBufferIndex, 0, 0, 0, 0);
} else {
codec.queueInputBuffer(inputBufferIndex, 0, sampleSize, presentationTimeUs, 0);
extractor.advance();
}
}
// 输出解码的帧
int outputBufferIndex = codec.dequeueOutputBuffer(new MediaCodec.BufferInfo(), 2000);
while (outputBufferIndex >= 0) {
//将获取到的ByteBuffer数据转为byte[]
ByteBuffer outputBuffer = outputBuffers[outputBufferIndex];
byte[] yuvBytes = new byte[outputBuffer.remaining()];
outputBuffer.get(yuvBytes);
// 释放输出缓冲区
codec.releaseOutputBuffer(outputBufferIndex, false);
outputBufferIndex = codec.dequeueOutputBuffer(new MediaCodec.BufferInfo(), 0);
}
}
codec.stop();
codec.release();
extractor.release();
}