I am developping an App that use libVLC to display MP4 videos. I created a customView (VlcView) that inherits from SurfaceView in order to manage libVLC and be able to reuse it easily.
The App looks like Youtube : I have an Activity, let says "ActivityOne", that displays a video in the first half of the screen (the VlcView), and a list of video suggestions in the second half. When I clicked on a suggestion, it starts a second Activity, "ActivityTwo", and kill the ActivityOne asking the VlcView to release libVLC. The ActivityTwo displays the selected video using another instance of VlcView.
To initialize and release libVLC, VlcView exposes these two methods :
Code: Select all
private void initLibVLC() throws LibVlcException {
libVLC = new LibVLC();
libVLC.setHardwareAcceleration(LibVLC.HW_ACCELERATION_DISABLED);
libVLC.setSubtitlesEncoding("");
libVLC.setTimeStretching(false);
libVLC.setFrameSkip(false);
libVLC.setAout(LibVLC.AOUT_OPENSLES);
libVLC.setVout(LibVLC.VOUT_ANDROID_SURFACE);
libVLC.setChroma("RV32");
libVLC.setDevHardwareDecoder(LibVLC.DEV_HW_DECODER_AUTOMATIC);
libVLC.setVerboseMode(true);
EventHandler.getInstance().addHandler(videoPlayerHandler);
libVLC.init(getContext());
}
Code: Select all
private void releaseLibVLC() {
if (libVLC != null) {
if (libVLC.isPlaying()) {
stopVideo();
}
EventHandler.getInstance().removeHandler(videoPlayerHandler);
videoPlayerHandler.removeCallbacksAndMessages(null);
libVLC.detachSurface();
libVLC.destroy();
videoPlayerHandler = null;
libVLC = null;
videoHeight = 0;
videoWidth = 0;
}
}
My first reaction was to call these two methods in the OnCreate() / OnDestroy() lifecycle methods of my two activities "ActivityOne" and "ActivityTwo". Doing that, when I launched "ActivityOne", a first instance of libVLC is created and the video is well displayed. However, when "ActivityTwo" is launched by clicking on a suggestion, a second instance of libVLC is created and the video is played but only the sound is available, not the video itself.
In VLC log, I found this when ActivityTwo try to launch the video :
Code: Select all
05-05 17:42:58.178 25251-27669/com.atos.stadium D/VLC﹕ [9e9e34b4] core video output: Deinterlacing available
05-05 17:42:58.178 25251-27669/com.atos.stadium D/VLC﹕ [9e9e34b4] core video output: deinterlace 0, mode blend, is_needed 0
05-05 17:42:58.178 25251-27669/com.atos.stadium D/VLC﹕ [9e980a34] core window: looking for vout window module matching "any": 1 candidates
05-05 17:42:58.178 25251-27669/com.atos.stadium D/VLC﹕ [9e980a34] core window: no vout window modules matched
05-05 17:42:58.183 25251-27679/com.atos.stadium D/VLC﹕ [9e9e34b4] core video output: Opening vout display wrapper
05-05 17:42:58.183 25251-27679/com.atos.stadium D/VLC﹕ [9e85a0f4] core vout display: looking for vout display module matching "androidwindow": 4 candidates
05-05 17:42:58.185 25251-27679/com.atos.stadium D/VLC﹕ [9e85a0f4] core vout display: no vout display modules matched
05-05 17:42:58.185 25251-27669/com.atos.stadium E/VLC﹕ [9e9e34b4] core video output: video output creation failed
05-05 17:42:58.185 25251-27669/com.atos.stadium D/VLC﹕ [9e9add34] core spu text: removing module "freetype"
05-05 17:42:58.185 25251-27669/com.atos.stadium D/VLC﹕ [9e9ae634] core scale: removing module "yuvp"
05-05 17:42:58.185 25251-27669/com.atos.stadium D/VLC﹕ [9e9ae334] core scale: removing module "swscale"
05-05 17:42:58.185 25251-27669/com.atos.stadium E/VLC﹕ [9ebc4f34] core decoder: failed to create video output
05-05 17:42:58.185 25251-27669/com.atos.stadium W/VLC﹕ [9ebc4f34] mediacodec decoder: NewPicture failed
05-05 17:42:58.187 25251-27650/com.atos.stadium W/VLC﹕ [9ebc4f34] core decoder: can't wait without data to decode
05-05 17:42:58.187 25251-27650/com.atos.stadium D/VLC﹕ [9e94a734] core input: Decoder wait done in 76 ms
05-05 17:43:02.120 25251-27650/com.atos.stadium D/VLC﹕ [9e94a734] core input: control type=1
Code: Select all
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if(libVLC != null) {
final Surface newSurface = holder.getSurface();
if (currentSurface != newSurface) {
Log.d(LOG_TAG, "Surface changed " + holder.hashCode());
currentSurface = newSurface;
libVLC.attachSurface(currentSurface, this);
surfaceReady = true;
if(waitingSurface) {
playVideo(currentMedia);
}
}
} else {
notifyVlcNullInstance();
}
}
This error disappears if I initialize / release libVLC (and VlcView) in the onResume() / onPause() lifecycle methods of both Activities.
I noticed that when changing from ActivityOne to ActivityTwo, ActivityOne.onPause() is called before ActivityTwo.onCreate(), whereas, ActivityOne.onDestroy() is called after ActivityTwo.onCreate().
So using onCreate() / onDestroy(), the first instance of libVLC (from ActivityOne) is destroyed after the second instance (from ActivityTwo) is initialized. Because they are two distinct instances, I supposed that they didn't have anything in common, but maybe they shared someting and the deallocation of the first instance release that thing that the second instance needs to work well. Or maybe detaching the surface from the first libVLC instance detach the surface of the second instance two (a bug? ).
An other possibility is that creating 2 instances of libVLC in the same time is completely illegal and I am doing some very bad things
If you have any answer to that issue, I will be pleased to hear about it. (release libVLC in onPause() is a little bit dirty and causes issues when locking / unlocking the phone...).