Tuesday, April 12, 2016

Capture frames in VideoView using MediaMetadataRetriever


Previous posts show how to " VideoView example to play video from Internet" and "Add MediaController to VideoView". We can capture frame in the video using MediaMetadataRetriever.

This video show how it run on Android Emulator running Marshmallow.


MainActivity.java
package com.blogspot.android_er.androidvideoview;

import android.graphics.Bitmap;
import android.media.MediaMetadataRetriever;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.MediaController;
import android.widget.Spinner;
import android.widget.Toast;
import android.widget.VideoView;

import java.util.HashMap;

public class MainActivity extends AppCompatActivity {

Button btnCapture;
Spinner spOption;
VideoView myVideoView;

String videoSource =
"https://sites.google.com/site/androidexample9/download/RunningClock.mp4";
Uri uriVideoSource;

MediaController myMediaController;
MediaMetadataRetriever myMediaMetadataRetriever;

String[] stringOpts = {
"none",
"OPTION_CLOSEST",
"OPTION_CLOSEST_SYNC",
"OPTION_NEXT_SYNC",
"OPTION_PREVIOUS_SYNC"};
int[] valOptions ={
0, //will not be used
MediaMetadataRetriever.OPTION_CLOSEST,
MediaMetadataRetriever.OPTION_CLOSEST_SYNC,
MediaMetadataRetriever.OPTION_NEXT_SYNC,
MediaMetadataRetriever.OPTION_PREVIOUS_SYNC};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myVideoView = (VideoView)findViewById(R.id.vview);

prepareVideo();

spOption = (Spinner)findViewById(R.id.option);
ArrayAdapter<String> adapter
= new ArrayAdapter<String>(MainActivity.this,
android.R.layout.simple_list_item_1, stringOpts);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spOption.setAdapter(adapter);

btnCapture = (Button)findViewById(R.id.capture);
btnCapture.setOnClickListener(btnCaptureOnClickListener);
}

View.OnClickListener btnCaptureOnClickListener = new View.OnClickListener(){
@Override
public void onClick(View v) {

int currentPosition = myVideoView.getCurrentPosition(); //in millisecond
Toast.makeText(MainActivity.this,
"Current Position: " + currentPosition + " (ms)",
Toast.LENGTH_LONG).show();

Bitmap bmFrame;
int pos = currentPosition * 1000; //unit in microsecond
int opt = spOption.getSelectedItemPosition();
if(opt == 0){
bmFrame = myMediaMetadataRetriever
.getFrameAtTime(pos);

}else{
bmFrame = myMediaMetadataRetriever
.getFrameAtTime(pos,
valOptions[opt]);

}

if(bmFrame == null){
Toast.makeText(MainActivity.this,
"bmFrame == null!",
Toast.LENGTH_LONG).show();
}else {
AlertDialog.Builder myCaptureDialog =
new AlertDialog.Builder(MainActivity.this);
ImageView capturedImageView = new ImageView(MainActivity.this);
capturedImageView.setImageBitmap(bmFrame);
LinearLayout.LayoutParams capturedImageViewLayoutParams =
new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
capturedImageView.setLayoutParams(capturedImageViewLayoutParams);

myCaptureDialog.setView(capturedImageView);
myCaptureDialog.show();
}

}
};

private void prepareVideo(){

myMediaMetadataRetriever = new MediaMetadataRetriever();
myMediaMetadataRetriever.setDataSource(
videoSource, new HashMap<String, String>());


myMediaController = new MediaController(MainActivity.this);
myVideoView.setMediaController(myMediaController);

Toast.makeText(MainActivity.this, videoSource, Toast.LENGTH_LONG).show();

uriVideoSource = Uri.parse(videoSource);

myVideoView.setVideoURI(uriVideoSource);

myVideoView.setOnCompletionListener(myVideoViewCompletionListener);
myVideoView.setOnPreparedListener(MyVideoViewPreparedListener);
myVideoView.setOnErrorListener(myVideoViewErrorListener);

myVideoView.requestFocus();
myVideoView.start();

}

MediaPlayer.OnCompletionListener myVideoViewCompletionListener =
new MediaPlayer.OnCompletionListener() {

@Override
public void onCompletion(MediaPlayer arg0) {
Toast.makeText(MainActivity.this, "End of Video",
Toast.LENGTH_LONG).show();
}
};

MediaPlayer.OnPreparedListener MyVideoViewPreparedListener =
new MediaPlayer.OnPreparedListener() {

@Override
public void onPrepared(MediaPlayer mp) {

long duration = myVideoView.getDuration(); //in millisecond
Toast.makeText(MainActivity.this,
"Duration: " + duration + " (ms)",
Toast.LENGTH_LONG).show();

}
};

MediaPlayer.OnErrorListener myVideoViewErrorListener =
new MediaPlayer.OnErrorListener() {

@Override
public boolean onError(MediaPlayer mp, int what, int extra) {

String errWhat = "";
switch (what){
case MediaPlayer.MEDIA_ERROR_UNKNOWN:
errWhat = "MEDIA_ERROR_UNKNOWN";
break;
case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
errWhat = "MEDIA_ERROR_SERVER_DIED";
break;
default: errWhat = "unknown what";
}

String errExtra = "";
switch (extra){
case MediaPlayer.MEDIA_ERROR_IO:
errExtra = "MEDIA_ERROR_IO";
break;
case MediaPlayer.MEDIA_ERROR_MALFORMED:
errExtra = "MEDIA_ERROR_MALFORMED";
break;
case MediaPlayer.MEDIA_ERROR_UNSUPPORTED:
errExtra = "MEDIA_ERROR_UNSUPPORTED";
break;
case MediaPlayer.MEDIA_ERROR_TIMED_OUT:
errExtra = "MEDIA_ERROR_TIMED_OUT";
break;
default:
errExtra = "...others";

}

Toast.makeText(MainActivity.this,
"Error!!!\n" +
"what: " + errWhat + "\n" +
"extra: " + errExtra,
Toast.LENGTH_LONG).show();
return true;
}
};
}


layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
android:orientation="vertical"
tools:context="com.blogspot.android_er.androidvideoview.MainActivity">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/capture"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="Capture"/>
<Spinner
android:id="@+id/option"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"/>
</LinearLayout>

<VideoView
android:id="@+id/vview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>


uses-permission of "android.permission.INTERNET" is needed in AndroidManifest.xml.

No comments:

Post a Comment