My application displays an action that allows the user to click up to five points on the graph, each of which displays a different animation of the graph. Animations are provided by displaying a .mp4 file using MediaPlayer.
My freeze comes when the animation plays. Before .mp4 playback starts, a brief white screen appears. I tried several ways to show videos, all of which are based on MediaPlayer: VideoView, SurfaceView and TextureView.
The most typically proposed answer to this problem is to show the View behind what kind of View is used by MediaPlayer to display its video, which contains the background taken from the first frame of the video. Before starting to play the video, it is suggested to make the video image View visible and hide the background image View. However, these methods are not relevant because they are based on MediaPlayer; a brief white screen remains.
Here is my basic setup:
AnimationLauncherFragment contains a RelativeLayout, whose background is set to the first frame of the animation with 5 transparent buttons. Each button has an OnClickListener that replaces AnimationLauncherFragment AnimationFragment.
An AnimationFragment contains a TextureView and implements a TextureView.OnSurfaceListener and MediaPlayer.OnCompletionListener. When a surface is available, the onSurfaceTextureAvailable () callback is launched. Here is my implementation:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_animationlauncher, container, false);
textureView = (TextureView) rootView.findViewById(R.id.animation);
textureView.setSurfaceTextureListener(this);
return rootView;
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i2) {
MediaPlayer player = MediaPlayer.create(getActivity(), R.raw.bdleft);
player.setOnCompletionListener(this);
player.setSurface(new Surface(surfaceTexture));
player.start();
}
@Override
public void onCompletion(MediaPlayer mediaPlayer) {
mediaPlayer.stop();
mediaPlayer.release();
}
I did some research on what causes the white screen, starting with LogCat output:
01-09 11:02:27.378 8086-8086/com.turbogunhawk.android.app V/MediaPlayer﹕ setVideoSurfaceTexture
01-09 11:02:27.658 8086-8086/com.turbogunhawk.android.app V/MediaPlayer﹕ setVideoSurfaceTexture
When a MediaPlayer is created, it calls setVideoSurfaceTexture twices before starting the video, once for the .setDataSource () method and once for .setSurface (). Googling around leads me to this useful blog post, where I find an explanation for creating MediaPlayers:
After setVideoSource and setAudioSource, now MediaPlayerService will highlight SurfaceTexture for future video rendering (connect to SurfaceFlinger)
Media Framework: android_src\framework\basemedia\libmediaplayerservice\MediaPlayerService.cpp
status_t MediaPlayerService::Client::setVideoSurfaceTexture(const sp& surfaceTexture) {
LOGV("[%d] setVideoSurfaceTexture(%p)", mConnId, surfaceTexture.get());
sp p = getPlayer();
sp anw;
if (surfaceTexture != NULL) {
anw = new SurfaceTextureClient(surfaceTexture);
status_t err = native_window_api_connect(anw.get(), NATIVE_WINDOW_API_MEDIA);
}
status_t err = p->setVideoSurfaceTexture(surfaceTexture);
return err;
}
, SurfaceTexture, MediaPlayer, SurfaceTexture, , .
, , . MediaPlayer/MediaPlayerService ?