Render directly on a SurfaceTexture, nothing happens
Posted: 18 Mar 2016 12:48
Hi All.
In our project we are using android MediaPlayer to decode mp4 to a Open GL texture (handled in JNI part) to render dynamic sky domes. We want to replace it with libvlc and extend support to -+.avi mpeg-dash,....
We clone class to change Android MediaPlayer to VLC, code compile and libVLC is initialised OK. But nothing happen in screen, not events are received, not traces in logcat ... Seems as internally not there are any thread working.
Summarizing our code
1 - Setup libVLC
2 - Load movie
3 - Set native texture id to SurfaceTexture
4- Update texture in render loop
Anybody has any idea to found and fix this issue?
In our project we are using android MediaPlayer to decode mp4 to a Open GL texture (handled in JNI part) to render dynamic sky domes. We want to replace it with libvlc and extend support to -+.avi mpeg-dash,....
We clone class to change Android MediaPlayer to VLC, code compile and libVLC is initialised OK. But nothing happen in screen, not events are received, not traces in logcat ... Seems as internally not there are any thread working.
Summarizing our code
1 - Setup libVLC
Code: Select all
ArrayList<String> options = new ArrayList<String>();
libVLC = new LibVLC(options);
options.add("-vvv"); // verbosity
libVLC.setOnNativeCrashListener(this);
mediaPlayer = new MediaPlayer(libVLC);
mediaPlayer.setEventListener(this);
Code: Select all
if (mediaPath.startsWith("http")) {
media = new Media(libVLC, mediaUri);
this.isLoaded = (media.parse(Media.Parse.FetchNetwork) && getMediaInformation()) || (media.parse(Media.Parse.ParseNetwork) && getMediaInformation());
} else if (mediaPath.startsWith("android.resource://")) {
media = new Media(libVLC, mediaUri);
} else {
media = new Media(libVLC, mediaPath);
this.isLoaded = (media.parse(Media.Parse.FetchLocal) && getMediaInformation()) || (media.parse(Media.Parse.ParseLocal) && getMediaInformation());
}
3 - Set native texture id to SurfaceTexture
Code: Select all
surfaceTextureID = textureID;
surfaceTexture = new SurfaceTexture(surfaceTextureID);
surfaceTexture.setOnFrameAvailableListener(this);
surface = new Surface(surfaceTexture);
surfaceHolder = new SurfaceHolder() {
@Override
public void addCallback(Callback callback) {
Log.d("[VLCVideoPlayer]","[SurfaceHolder::addCallback] Entering method");
synchronized (surfaceholder_callbacks) {
if (surfaceholder_callbacks.contains(callback) == false) {
surfaceholder_callbacks.add(callback);
}
}
}
@Override
public void removeCallback(Callback callback) {
Log.d("[VLCVideoPlayer]","[SurfaceHolder::removeCallback] Entering method");
synchronized (surfaceholder_callbacks) {
surfaceholder_callbacks.remove(callback);
}
}
@Override
public Surface getSurface() {
Log.d("[VLCVideoPlayer]","[SurfaceHolder::getSurface] Entering method");
return surface;
}
@Override
public Rect getSurfaceFrame() {
Log.d("[VLCVideoPlayer]","[SurfaceHolder::getSurfaceFrame] Entering method");
surfaceholder_frame.top = 0;
surfaceholder_frame.bottom = 0;
surfaceholder_frame.right = width;
surfaceholder_frame.bottom = height;
return surfaceholder_frame;
}
@Override
public boolean isCreating() {
Log.d("[VLCVideoPlayer]","[SurfaceHolder::isCreating] Entering method");
return surfaceholder_isCreating;
}
@Override
public void setFixedSize(int width, int height) {
Log.d("[VLCVideoPlayer]","[SurfaceHolder::setFixedSize] Entering method");
surfaceholder_width = width;
surfaceholder_height = height;
}
@Override
public void setFormat(int format) {
Log.d("[VLCVideoPlayer]","[SurfaceHolder::setFormat] Entering method");
surfaceholder_format = (format == PixelFormat.OPAQUE)? PixelFormat.RGB_565: format;
}
@Override
public void setKeepScreenOn(boolean screenOn) {
Log.d("[VLCVideoPlayer]","[SurfaceHolder::setKeepScreenOn] Entering method");
}
@Override
public void setSizeFromLayout() {
Log.d("[VLCVideoPlayer]","[SurfaceHolder::setSizeFromLayout] Entering method");
surfaceholder_width = 0;
surfaceholder_height = 0;
}
@Override
public void setType(int type) {
Log.d("[VLCVideoPlayer]","[SurfaceHolder::setType] Entering method");
}
@Override
public Canvas lockCanvas() {
Log.d("[VLCVideoPlayer]","[SurfaceHolder::lockCanvas] Entering method");
return lockCanvas(null);
}
@Override
public Canvas lockCanvas(Rect dirty) {
Log.d("[VLCVideoPlayer]","[SurfaceHolder::lockCanvas] Entering method");
surfaceholder_lock.lock();
{
Canvas canvas = null;
try {
canvas = surface.lockCanvas(dirty);
} catch(Exception ex) {
Log.e("[VLCVideoPlayer]","[SurfaceHolder::lockCanvas] Exception locking canvas-surface", ex);
}
if (null != canvas) {
surfaceholder_lastLockTime = SystemClock.uptimeMillis();
return canvas;
}
long surfaceholder_now = SystemClock.uptimeMillis();
long surfaceholder_next= surfaceholder_lastLockTime + 100;
if (surfaceholder_next > surfaceholder_now) {
try {
Thread.sleep(surfaceholder_next - surfaceholder_now);
} catch (InterruptedException ex) {
Log.e("[VLCVideoPlayer]","[SurfaceHolder::lockCanvas] Exception setting thread sleep delay", ex);
}
surfaceholder_now = SystemClock.uptimeMillis();
}
surfaceholder_lastLockTime = surfaceholder_now;
}
surfaceholder_lock.unlock();
return null;
}
@Override
public void unlockCanvasAndPost(Canvas canvas) {
Log.d("[VLCVideoPlayer]","[SurfaceHolder::unlockCanvasAndPost] Entering method");
surface.unlockCanvasAndPost(canvas);
surfaceholder_lock.unlock();
}
};
final IVLCVout outVLC = mediaPlayer.getVLCVout();
outVLC.addCallback(this);
outVLC.setVideoSurface(surface, surfaceHolder);
outVLC.attachViews();
Code: Select all
synchronized(this) {
if(isFrameNew) {
if(surfaceTexture != null) surfaceTexture.updateTexImage();
isFrameNew = false;
isMoviedone = false;
return true;
}
return false;
}