Saturday, May 25, 2013

Get the current frame in VideoView using MediaMetadataRetriever

Last exercise show a simple example to "Get image frame in video using MediaMetadataRetriever". In this exercise, we will play the video in a VideoView. Then capture the frame at the position when user click on the button.

Get the current frame in VideoView using MediaMetadataRetriever


layout file.
<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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />
    <Button
        android:id="@+id/capture"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="capture video image" />
    <VideoView
        android:id="@+id/videoview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>


MainActivity.java
package com.example.androidvideoview;

import android.graphics.Bitmap;
import android.media.MediaMetadataRetriever;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.app.AlertDialog;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.MediaController;
import android.widget.Toast;
import android.widget.VideoView;

public class MainActivity extends Activity {
 
 MediaMetadataRetriever mediaMetadataRetriever;
 MediaController myMediaController;
 VideoView myVideoView;
 String viewSource = "/storage/sdcard0/DCIM/100MEDIA/VIDEO0009.mp4";

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  mediaMetadataRetriever = new MediaMetadataRetriever();
  mediaMetadataRetriever.setDataSource(viewSource);

  myVideoView = (VideoView) findViewById(R.id.videoview);
  myVideoView.setVideoURI(Uri.parse(viewSource));  
  myMediaController = new MediaController(this);
  myVideoView.setMediaController(myMediaController);

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

  myVideoView.requestFocus();
  myVideoView.start();
  
  Button buttonCapture = (Button)findViewById(R.id.capture);
  buttonCapture.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View arg0) {
    
    int currentPosition = myVideoView.getCurrentPosition(); //in millisecond
    Toast.makeText(MainActivity.this,
      "Current Position: " + currentPosition + " (ms)", 
      Toast.LENGTH_LONG).show();
    
    Bitmap bmFrame = mediaMetadataRetriever
      .getFrameAtTime(currentPosition * 1000); //unit in microsecond
    
    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);
     LayoutParams capturedImageViewLayoutParams = 
       new LayoutParams(LayoutParams.WRAP_CONTENT, 
         LayoutParams.WRAP_CONTENT);
     capturedImageView.setLayoutParams(capturedImageViewLayoutParams);
     
     myCaptureDialog.setView(capturedImageView);
     myCaptureDialog.show();
    }
    
   }});
 }

 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) {
   
   Toast.makeText(MainActivity.this, 
     "Error!!!",
     Toast.LENGTH_LONG).show();
   return true;
  }
 };

}


Note: To use MediaMetadataRetriever, minSdkVersion="10" have to be defined in AndroidManifest.xml.

15 comments:

Anonymous said...

Very Good Blog.

Anonymous said...

Superb one.. if possible suggest me how to get all frames of the video played.. Thanks in advance.

Aditya said...

i'm getting screenshots, but screenshots are not saving in SDcard. please help me

Andr.oid Eric said...

hello Aditya,

that means you have a bitmap. Please read Save file to SD Card.

Aditya said...

i have tried that one , but i'm getting only black screen..

Rati said...

Thanks working for me on android 2.3 and above.
But what is the solution if android version is 2.2 and below.








Anonymous said...

Please give the project as a demo

Gourav Sharma said...

Hi i am using thic code but it crashes at:
mediaMetadataRetriever = new MediaMetadataRetriever();
mediaMetadataRetriever.setDataSource(viewSource);


How can i fix it??

Johnny Sears said...

Is it possible to utilize a VideoView to record a video and preview it at the same time? Meaning, the user would click a button, the VideoView would instantly display the recorder within the VideoView and the user could see what was being recorded.

Kamlesh Kumar Verma said...

Hi Its not working when set path of remote url..
Give bitmap Null..How can solve it...

karan singh said...

Superb blog......

Unknown said...

I tried to retrieve sequence of images from video using following code.

MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(videofilepath);
bitmap = retriever.getFrameAtTime(33333*i, MediaMetadataRetriever.OPTION_CLOSEST);

The above code retrieve sequence of images in lollipop but it's not working in
Marshmallow.In marsghmallow it reaped same images, Please can any one help me to retrieve images in marshmallow I'm in critical situation please help me.

Andr.oid Eric said...

hello Unknown,

I have no device running marshmallow. But I test it on emulator, work as expected. Please refer Capture frames in VideoView using MediaMetadataRetriever.

Karthi Keyan said...

hi friends, using MediaMetadataRetriever I can able to extract frams from video.But its not working in marshmallow. Can any one help me how to use MediaMetadataRetriever in marshmallow to extract frames from video.I'm in very big problem.



Andr.oid Eric said...

hello Karthi Keyan,

I tested on Marshmallow emulator:
Capture frames in VideoView using MediaMetadataRetriever.