Back to project page MediaCodecDemo.
The source code is released under:
Copyright (c) 2012, Cedric Fung <cedric@vec.io> All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following condit...
If you think the Android project MediaCodecDemo listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
package io.vec.demo.mediacodec; /*from ww w . java 2s. com*/ import java.nio.ByteBuffer; import android.app.Activity; import android.media.MediaCodec; import android.media.MediaCodec.BufferInfo; import android.media.MediaExtractor; import android.media.MediaFormat; import android.os.Bundle; import android.os.Environment; import android.util.Log; import android.view.Surface; import android.view.SurfaceHolder; import android.view.SurfaceView; public class DecodeActivity extends Activity implements SurfaceHolder.Callback { private static final String SAMPLE = Environment.getExternalStorageDirectory() + "/video.mp4"; private PlayerThread mPlayer = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); SurfaceView sv = new SurfaceView(this); sv.getHolder().addCallback(this); setContentView(sv); } protected void onDestroy() { super.onDestroy(); } @Override public void surfaceCreated(SurfaceHolder holder) { } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { if (mPlayer == null) { mPlayer = new PlayerThread(holder.getSurface()); mPlayer.start(); } } @Override public void surfaceDestroyed(SurfaceHolder holder) { if (mPlayer != null) { mPlayer.interrupt(); } } private class PlayerThread extends Thread { private MediaExtractor extractor; private MediaCodec decoder; private Surface surface; public PlayerThread(Surface surface) { this.surface = surface; } @Override public void run() { extractor = new MediaExtractor(); extractor.setDataSource(SAMPLE); for (int i = 0; i < extractor.getTrackCount(); i++) { MediaFormat format = extractor.getTrackFormat(i); String mime = format.getString(MediaFormat.KEY_MIME); if (mime.startsWith("video/")) { extractor.selectTrack(i); decoder = MediaCodec.createDecoderByType(mime); decoder.configure(format, surface, null, 0); break; } } if (decoder == null) { Log.e("DecodeActivity", "Can't find video info!"); return; } decoder.start(); ByteBuffer[] inputBuffers = decoder.getInputBuffers(); ByteBuffer[] outputBuffers = decoder.getOutputBuffers(); BufferInfo info = new BufferInfo(); boolean isEOS = false; long startMs = System.currentTimeMillis(); while (!Thread.interrupted()) { if (!isEOS) { int inIndex = decoder.dequeueInputBuffer(10000); if (inIndex >= 0) { ByteBuffer buffer = inputBuffers[inIndex]; int sampleSize = extractor.readSampleData(buffer, 0); if (sampleSize < 0) { // We shouldn't stop the playback at this point, just pass the EOS // flag to decoder, we will get it again from the // dequeueOutputBuffer Log.d("DecodeActivity", "InputBuffer BUFFER_FLAG_END_OF_STREAM"); decoder.queueInputBuffer(inIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM); isEOS = true; } else { decoder.queueInputBuffer(inIndex, 0, sampleSize, extractor.getSampleTime(), 0); extractor.advance(); } } } int outIndex = decoder.dequeueOutputBuffer(info, 10000); switch (outIndex) { case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED: Log.d("DecodeActivity", "INFO_OUTPUT_BUFFERS_CHANGED"); outputBuffers = decoder.getOutputBuffers(); break; case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED: Log.d("DecodeActivity", "New format " + decoder.getOutputFormat()); break; case MediaCodec.INFO_TRY_AGAIN_LATER: Log.d("DecodeActivity", "dequeueOutputBuffer timed out!"); break; default: ByteBuffer buffer = outputBuffers[outIndex]; Log.v("DecodeActivity", "We can't use this buffer but render it due to the API limit, " + buffer); // We use a very simple clock to keep the video FPS, or the video // playback will be too fast while (info.presentationTimeUs / 1000 > System.currentTimeMillis() - startMs) { try { sleep(10); } catch (InterruptedException e) { e.printStackTrace(); break; } } decoder.releaseOutputBuffer(outIndex, true); break; } // All decoded frames have been rendered, we can stop playing now if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { Log.d("DecodeActivity", "OutputBuffer BUFFER_FLAG_END_OF_STREAM"); break; } } decoder.stop(); decoder.release(); extractor.release(); } } }