Android TextureView: Video displaying gray frame while calling getBitmap - android

I am working on android app which can grab frame from video when user performs button click, the android app which is configured to play video using a TextureView. For capturing the frame as a bitmap, i am using:
Bitmap bit = textureView.getBitmap(width, height);
It works fine, but "getBitmap" takes quite long time (around 150-200 ms for a 640x480 frame). The issue is while getBitmap is being called the a gray frame is getting displayed on the view. This looks like some thing is flicking. Is there a way to get ride of this issue?
Thanks

You should use Handler to avoid delay time
new Handler().post(new Runnable() {
#Override
public void run() {
try {
Bitmap bit = textureView.getBitmap(width, height);
//you could save the video frames to use later
} catch (Exception ex) {
ex.printStackTrace();
}
}});

Related

Videos in RecyclerView: any way to prevent restarting when off-screen?

I have a RecyclerView with some video elements and they get restarted every time they get off-screen. I tried:
recyclerView.getRecycledViewPool().setMaxRecycledViews(RecyclerViewAdapter.TYPE_VIDEO, 0);
but no success. I also tried to do:
holder.setIsRecyclable(false)
inside my adapter, but videos still restart every time.
Is there any way to stop restarting videos, and somehow pause them and resume them once they are on screen again?
The videos are remote, not local. And I am using a class extending TextureView, not the Android's VideoView
Edit: I missunderstood the question. See original answer below.
I guess you have two possibilities:
Ugly, only possible if the list is not going to be too long™ and undermining the purpose of the recyclerview: use setItemViewCacheSize(int) to increase the number of viewholders that are cached to the number of videos you have and just pause and play during attach / detach.
much better: Store and restore the current playback timestamp of each video when the viewholder gets attached/dettached.
You can use an RecyclerView.OnChildAttachStateChangeListener that will be called whenever a view is attached / removed.
Do it like this:
mRecyclerView.addOnChildAttachStateChangeListener(new RecyclerView.OnChildAttachStateChangeListener() {
#Override
public void onChildViewAttachedToWindow(View view) {
YourTextureView yourTextureView = (YourTextureView) view.findViewById(R.id.yourvideoviewid);
if (yourTextureView != null) {
// start your video
}
}
#Override
public void onChildViewDetachedFromWindow(View view) {
YourTextureView yourTextureView = (YourTextureView) view.findViewById(R.id.yourvideoviewid);
if (yourTextureView != null) {
// stop your video
}
}
});

Want to get current video duration in logcat. using exoplayer

I want to get current duration of video. I am using ExoPlayer(Exoplayer is used to play videos it is a video player) and i want to display current video playing duration. The method getCurrentDuration() is used to get current duration of video so I want to get that duration in log. That is why i code like this but it is not providing correct duration. I want that when video is playing and the current duration which is showing on seek bar should be displayed in log also.
for (long x=0;x<10000000;x++){
long position = mPlayer.getCurrentPosition();
Log.d(">>>>AdPopUp", Long.toString(position));
There is a way:
private PlayerView videoView;
Log.i("video_duration",
((TextView)videoView.findViewById(R.id.exo_duration)).getText().toString());
Remember not to call it immediately. It will return 00:00 instead use it inside a handler with postDelayed(Runnable, long millisec) like below:
videoView.postDelayed(new Runnable() {
#Override
public void run() {
Log.i("video_duration",
((TextView)videoView.findViewById(R.id.exo_duration)).getText().toString());
}
}, 2000);
However, you may use MediaMetadataRetriever:
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
try {
retriever.setDataSource(mContext, Uri.fromFile(file));
String time = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
} catch (Exception ignored) {
} finally {
retriever.release();
}

GLSurfaceView switching issue

I am having an issue with while switching GLSurfaceView. I have a GLSurfaceView (connected with Camera) and I want to move it to another view , but when I am moving it it's losing its frames and showing blackScreen after switching. and when I am reconnecting it to Camera, it starts show my Camera but with delay.
Could any one please tell me solution to move it to another parent without losing its frames (because when I am reconnecting it its showing frames with 2-3 seconds delay).
Please find code written below :
(Here VideoPanel (extends GLSurfaceView) is Frame provided by oovooSDK to show video)
final VideoPanel movingVideoView = parent1.getChildAt(0);
movingView.onPause();
parent1.removeView(movingView);
parent2.addView(movingView);
movingView.onResume();
movingView.requestRender();
for reconnecting :
application.unbindVideoPanel(videoView.userId, videoView.videoRender);
application.unbindVideoPanel(videoView.userId, videoView.videoRender);
// this methods shows delay of 2-3 seconds for binding view again
I tried following methods also
((VideoPanel) videoView.videoRender).setPreserveEGLContextOnPause(true);
// to save context when paused
((VideoPanel)videoView.videoRender).setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); // to render frame again when requestRender is called
Camera is not proper release when your activity going to end.
If you are using a Surface view than release your camera in onSurfaceDestroy
public void surfaceDestroyed(SurfaceHolder holder) {
if(camera!=null){
camera.stopPreview();
camera.setPreviewCallback(null);
camera.release();
camera = null;
}
}
Also recommend a release your camera if it's not ever going to use.
protected void onDestroy(){
if(camera!=null){
camera.stopPreview();
camera.setPreviewCallback(null);
camera.release();
camera = null;
}
}

MediaPlayer setDisplay when returning to an activity not working

I want to play video with MediaPlayer in the background so when the user leave my app he will still hear the audio and when he is returning to the app he will see the video. I managed to do the first part with Service that plays the MediaPlayer, but I have a problem in the second part. When I leave the app and return the video does not show in the SurfaceView.
When the user return I created new Surface, so I tried this:
public void surfaceCreated(SurfaceHolder holder) {
if(mService!=null && mService.player.isPlaying()){
try {
mService.player.setDisplay(holder);
mService.player.prepare();
mService.player.start();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
While mService is my Service and he holds the MediaPlayer player.
In my research I saw this post:
Black screen when returning to video playback activity in Android
But this was posted a year ago so maybe anyone has any different and new answer.
EDIT:
I forgot to say that the video is streaming, so reset is not good option (i tried :)).
is it possible to save the SurfaceView in the Service and when the user return to take the view and add it dynamically to the current layout?
When you first launch Activity: onResume()->onSurfaceCreated()->onSurfaceChanged().
When you leave Activity: onPause()->onSurfaceDestroyed()
So i you leave your app, surface will be automatically destroy, you also can not save surfaceview in service.
Remember, if you want to show video again, surfaceview and holder callback must created again in onStart in case your home or lockscreen pressed
surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
holder = surfaceView.getHolder();
holder.setFixedSize(800, 480);
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

Android VideoView, need to switch between videos quickly

I'm developing a new app and am using VideoView to display mpeg clips.
I need to switch between videos very quickly, however, loading a new clip to a VideoView seems to take about half a second of black screen.
The transition must be seamless, how would you go about solving this kind of problem?
I had a similar issue and resolved with a still-image (ImageView) transition:
build a FrameLayout with an ImageView over the VideoView
the ImageView shows the first frame of the video
initially the ImageView is visible
start the video, wait for an arbitrary time (e.g. 2-300ms)
hide the ImageView
to switch two videos:
- show the image
- switch the video
- hide the image
a bit hackish but worked for me
I faced the same problem, but I used mediaplayer, my code is:
Here I use a button to trigger the switch action, before switching, I have already loaded the video and prepare for switching. When you need to do so, you just need to stop and release the old mediaplayer and starting the new one.The key point for seamless switching is the sleep(), when the process is sleeping, actually the video is still going on, but give the system some time to prepare for the next one.
switch_button = (Button) findViewById(R.id.button_switch);
switch_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Button switch_button = (Button) v;
VideoPlayer2 = new MediaPlayer();
try {
VideoPlayer2.setDataSource("rtsp://" + hostIP + ":1935/vod/Timer.mp4");
VideoPlayer2.prepare();
VideoPlayer2.setAudioStreamType(AudioManager.STREAM_MUSIC);
} catch (IOException e) {
e.printStackTrace();
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
VideoPlayer.release();
VideoPlayer2.setDisplay(vidHolder);
VideoPlayer2.start();
}
});

Categories

Resources