Android Capture Video Frame

How to capture frame by frame images from Android video recording in real time

One can get frames by using ImageReader for camera2 API. And preview callback for camera1 API.

Here is how to do it with camera2 API.

One can also explore this library for working example with both camera2 and camera1 API.

How to capture screenshot or video frame of VideoView in Android

I have found a solution to this problem. It appears that the VideoView does not allow this because of low-level hardware GPU reasons while using a SurfaceView.

The solution is to use a TextureView and use a MediaPlayer to play a video inside of it. The Activity will need to implement TextureView.SurfaceTextureListener. When taking a screenshot with this solution, the video freezes for a short while. Also, the TextureView does not display a default UI for the playback progress bar (play, pause, FF/RW, play time, etc). That is one drawback. If you have another solution please let me know :)

Here is the solution:

public class TextureViewActivity extends Activity 
implements TextureView.SurfaceTextureListener,
OnBufferingUpdateListener,
OnCompletionListener,
OnPreparedListener,
OnVideoSizeChangedListener
{
private MediaPlayer mp;
private TextureView tv;
public static String MY_VIDEO = "https://www.blahblahblah.com/myVideo.mp4";
public static String TAG = "TextureViewActivity";

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_texture_view);

tv = (TextureView) findViewById(R.id.textureView1);
tv.setSurfaceTextureListener(this);
}

public void getBitmap(TextureView vv)
{
String mPath = Environment.getExternalStorageDirectory().toString()
+ "/Pictures/" + Utilities.getDayTimeString() + ".png";
Toast.makeText(getApplicationContext(), "Capturing Screenshot: " + mPath, Toast.LENGTH_SHORT).show();

Bitmap bm = vv.getBitmap();
if(bm == null)
Log.e(TAG,"bitmap is null");

OutputStream fout = null;
File imageFile = new File(mPath);

try {
fout = new FileOutputStream(imageFile);
bm.compress(Bitmap.CompressFormat.PNG, 90, fout);
fout.flush();
fout.close();
} catch (FileNotFoundException e) {
Log.e(TAG, "FileNotFoundException");
e.printStackTrace();
} catch (IOException e) {
Log.e(TAG, "IOException");
e.printStackTrace();
}
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.media_player_video, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}

@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height)
{
Surface s = new Surface(surface);

try
{
mp = new MediaPlayer();
mp.setDataSource(MY_VIDEO);
mp.setSurface(s);
mp.prepare();

mp.setOnBufferingUpdateListener(this);
mp.setOnCompletionListener(this);
mp.setOnPreparedListener(this);
mp.setOnVideoSizeChangedListener(this);

mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
mp.start();

Button b = (Button) findViewById(R.id.textureViewButton);
b.setOnClickListener(new OnClickListener(){

@Override
public void onClick(View v)
{
TextureViewActivity.this.getBitmap(tv);
}
});
}
catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

Capture video frames with opencv in android

Here is how to do it:

 public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
//Do your processing here, for example:
Mat image = inputFrame.rgba();
Mat ret_mat=new Mat();
Core.add(image, new Scalar(40, 40, 40, 0), ret_mat); //change brightness of video frame

return ret_mat;
}

OpenCv functions operate with Mat object, which represents matrix of pixels of your image/frame. The code above makes each frame brighter by 40 units.

android capture video frame

The following works for me:

public static Bitmap getVideoFrame(FileDescriptor FD) {
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
try {
retriever.setDataSource(FD);
return retriever.getFrameAtTime();
} catch (IllegalArgumentException ex) {
ex.printStackTrace();
} catch (RuntimeException ex) {
ex.printStackTrace();
} finally {
try {
retriever.release();
} catch (RuntimeException ex) {
}
}
return null;
}

Also works if you use a path instead of a filedescriptor.

Android - How to get a screen recording's frames in real time using MediaRecorder

You wouldn't do an ImageView for this. You'd use a SurfaceView. It's meant to be used for things like media playback. https://developer.android.com/reference/android/view/SurfaceView?hl=en

You can find a bunch of examples on how to use it on Google, such as https://gist.github.com/scottgwald/7743453



Related Topics



Leave a reply



Submit