package com.alwaysinnovating.aimediacodec;

import java.nio.ByteBuffer;

import com.lamerman.FileDialog;

import android.app.Activity;
import android.content.Intent;
import android.media.MediaCodec;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.media.MediaCodec.BufferInfo;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;

public class MainActivity extends Activity {
	static private final int PICK_FILE_CODE = 1;
	private SurfaceView mSurfaceView;
	PlayerThread mPlayer = null;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		mSurfaceView = (SurfaceView) findViewById(R.id.main);

		ImageButton select = (ImageButton) this.findViewById(R.id.button_select);
		select.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				if (mPlayer != null)
					mPlayer.play = false;
				Intent i = new Intent(getBaseContext(), FileDialog.class);
				i.putExtra(FileDialog.START_PATH, Environment.getExternalStorageDirectory().getPath());
				startActivityForResult(i, PICK_FILE_CODE);
			}
		});
	}

	@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK && requestCode == PICK_FILE_CODE) {
            mPlayer = new PlayerThread(mSurfaceView.getHolder().getSurface(), data.getStringExtra(FileDialog.RESULT_PATH));
            mPlayer.start();
        }
    }
}

class PlayerThread extends Thread {
	private MediaExtractor extractor;
	private MediaCodec decoder;
	private Surface surface;
	private String pathFile;
	public boolean play = true;

	public PlayerThread(Surface surface, String st) {
		this.surface = surface;
		this.pathFile = st;
	}

	@Override
	public void run() {
		extractor = new MediaExtractor();
		try {
			extractor.setDataSource(pathFile);
		} catch (Exception e1) {
		}

		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 (play) {
			if (!isEOS) {
				int inIndex = decoder.dequeueInputBuffer(10000);
				if (inIndex >= 0) {
					ByteBuffer buffer = inputBuffers[inIndex];
					int sampleSize = extractor.readSampleData(buffer, 0);
					if (sampleSize < 0) {
						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);
						//sampleSize++;
						extractor.advance();
					}
				}
			}

			int outIndex = decoder.dequeueOutputBuffer(info, 10000);
			if (outIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED)
				Log.d("DecodeActivity", "INFO_OUTPUT_BUFFERS_CHANGED");
			else if(outIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED)
				Log.d("DecodeActivity", "New format " + decoder.getOutputFormat());
			else if (outIndex == MediaCodec.INFO_TRY_AGAIN_LATER)
				;//Log.d("DecodeActivity", "dequeueOutputBuffer timed out!");
			else if (outIndex < 0)
				Log.d("DecodeActivity", "Error!");
			else {
				ByteBuffer buffer = outputBuffers[outIndex];
				while (extractor.getSampleTime() / 1000 > System.currentTimeMillis() - startMs) {
					try {
						sleep(20);
					} catch (Exception e) {
						play = false;
					}
				}
				decoder.releaseOutputBuffer(outIndex, true);
			}

			if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
				Log.d("DecodeActivity", "OutputBuffer BUFFER_FLAG_END_OF_STREAM");
				play = false;
			}
		}

		decoder.stop();
		decoder.release();
		extractor.release();
	}
}