您的位置:首页 > 移动开发 > Android开发

把一个音视频文件的视频部分抽取出来播放

2016-10-10 22:43 411 查看

知识结构

MediaCodec: Android中直播视频技术探究之—基础知识大纲介绍MediaCodec文档翻译

详细介绍了MediaCodec的用法;在这里我们只使用MediaCodec的解码的功能;

mMediaCodec.configure(mMediaFormat, mSurface, null, 0);我们把SurfaceView.getSurface()传给它,就能把视频在SurfaceView上播放;

MediaExtractor: 实现把一个音频文件的视频抽取出来这里已经详细介绍了MediaExtractor的用处,这里不再累述;

步骤

1、创建一个SurfaceView

mSurfaceView = (SurfaceView) this.findViewById(R.id.mSurfaceView);
mSurfaceView.getHolder().addCallback(this);


2、在SurfaceView的Surface创建成功后开启一个线程执行MediaExtractor抽取视频,在MediaCodec进行解码;

public void surfaceCreated(SurfaceHolder holder) {

}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
mSurfaceHolder = holder;
if(null == mPlayerThread){
mPlayerThread = new Thread(new PlayerRunnable(mSurfaceHolder.getSurface()));
mPlayerThread.start();
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if(null != mPlayerThread){
mPlayerThread.interrupt();
}
}


3、最重要的:MediaExtractor与MediaCodec的组合

private class PlayerRunnable implements Runnable{
private MediaExtractor mMediaExtractor;
private MediaCodec mMediaCodec;
private Surface mSurface ;

public PlayerRunnable(Surface surface) {
this.mSurface = surface;
}

@Override
public void run() {
try {
mMediaExtractor = new MediaExtractor();

String filePath = new File(Environment.getExternalStorageDirectory(), "/input.mp4").getPath();
mMediaExtractor.setDataSource(filePath);

int trackCount = mMediaExtractor.getTrackCount();
for(int i=0; i<trackCount; i++){
MediaFormat mMediaFormat = mMediaExtractor.getTrackFormat(i);
String mime = mMediaFormat.getString(MediaFormat.KEY_MIME);
if(mime.startsWith("video/")){
mMediaExtractor.selectTrack(i);
mMediaCodec = MediaCodec.createDecoderByType(mime);
mMediaCodec.configure(mMediaFormat, mSurface, null, 0);
break;
}
}

if(null == mMediaCodec){
Log.d("MainActivity","dont't find mediaformat info;");
return ;
}
mMediaCodec.start();

ByteBuffer[] inputBuffers = mMediaCodec.getInputBuffers();
ByteBuffer[] outputBuffers = mMediaCodec.getOutputBuffers();
boolean isEOS = false;
BufferInfo info = new BufferInfo();
long startMs = System.currentTimeMillis();

while(!Thread.interrupted()){
if(!isEOS){
int inputBufferIndex = mMediaCodec.dequeueInputBuffer(10000);
if(inputBufferIndex >= 0){
ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
int readSampleSize = mMediaExtractor.readSampleData(inputBuffer, 0);
if(readSampleSize < 0){
//此时表明Video数据我们已经抽取完毕
mMediaCodec.queueInputBuffer(inputBufferIndex, 0, 0, 0,         MediaCodec.BUFFER_FLAG_END_OF_STREAM);
isEOS = true;
} else {
mMediaCodec.queueInputBuffer(inputBufferIndex, 0, readSampleSize, mMediaExtractor.getSampleTime(), 0);
mMediaExtractor.advance();
}
}
}

int outputBufferIndex = mMediaCodec.dequeueOutputBuffer(info, 10000);
switch (outputBufferIndex) {
case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
outputBuffers = mMediaCodec.getOutputBuffers();
break;
case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
Log.d("MainActivity", "New format " + mMediaCodec.getOutputFormat());
break;
case MediaCodec.INFO_TRY_AGAIN_LATER:
Log.d("MainActivity", "dequeueOutputBuffer timed out!");
break;

default:
ByteBuffer outputBuffer = outputBuffers[outputBufferIndex];
while (info.presentationTimeUs / 1000 > System.currentTimeMillis() - startMs) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
mMediaCodec.releaseOutputBuffer(outputBufferIndex, true);
break;
}

}
mMediaCodec.stop();
mMediaCodec.release();
mMediaExtractor.release();

} catch (Exception e) {
e.printStackTrace();
}
}
}


总结

上面的代码主要是练习这几天学习的MediaCodec、MediaExtractor;只有多次练习,我们才能熟练使用;

Demo实例下载:DecodeVideoFileDemo
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐