package org.gstreamer.android; import org.gstreamer.Element; import org.gstreamer.interfaces.XOverlayBase; import org.gstreamer.lowlevel.AndroidAPI; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import com.sun.jna.Pointer; // A simple SurfaceView whose width and height can be set from the outside public abstract class GstAndroidSurfaceAttach { private Pointer nativeWindow; private XOverlayBase xoverlay; private native long nativeSurfaceWindow(Object surface); public GstAndroidSurfaceAttach(Element sinkElement, SurfaceView view) { xoverlay = XOverlayBase.wrap(sinkElement); view.getHolder().addCallback(new SurfaceHolder.Callback() { boolean surfaceReady; public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Log.d("GStreamer", "Surface changed to format " + format + " width " + width + " height " + height); Pointer _nativeWindow = new Pointer(nativeSurfaceWindow(holder.getSurface())); if (nativeWindow != null) { AndroidAPI.api.ANativeWindow_release(nativeWindow); } if (_nativeWindow.equals(nativeWindow)) { if (xoverlay != null) { xoverlay.expose(); xoverlay.expose(); } } else { nativeWindow = _nativeWindow; updateXoverlay(); } if (nativeWindow != null && !surfaceReady) { surfaceReady = true; onCreated(); } } public void surfaceCreated(SurfaceHolder holder) { Log.d("GStreamer", "Surface created: " + holder.getSurface()); } public void surfaceDestroyed(SurfaceHolder holder) { Log.d("GStreamer", "Surface destroyed"); if (nativeWindow != null) { AndroidAPI.api.ANativeWindow_release(nativeWindow); } nativeWindow = null; updateXoverlay(); surfaceReady = false; onDestroyed(); } }); } protected abstract void onCreated(); protected abstract void onDestroyed(); private void updateXoverlay() { if (xoverlay != null) { xoverlay.setWindowHandle(nativeWindow == null ? 0L : Pointer.nativeValue(nativeWindow)); } } }