<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
</head>
<body bgcolor="#FFFFFF" text="#000000">
I've got two pipelines:<br>
<br>
data->video_pipeline = gst_parse_launch("udpsrc port=5000
caps=application/x-rtp buffer-size=100000 ! rtph264depay !
ffdec_h264 ! clockoverlay time-format=\"%D\n%H:%M:%S\" !
autovideosink sync=false", &error);<br>
<br>
and another<br>
<br>
"udpsrc port=5000 caps=application/x-rtp buffer-size=100000 !
rtph264depay ! tee name=splitter ! ffdec_h264 ! clockoverlay
time-format=\"%D\n%H:%M:%S\" ! autovideosink sync=false splitter. !
queue ! mpegpsmux name=mux ! filesink location=" ( the string
appends by file location and parses by gst_parse_launch also)<br>
<br>
And now i want to combine this two pipelines in one application. <br>
What would i do with GStreamerSurfaceView when desire to switch to
another pipeline?<br>
<br>
How sould i reinitialize Surface to prepare it to work with another
pipe after setting the first one to Null- or Pause-state.<br>
<br>
<u>The native part of work with Surface:</u><br>
<br>
<font color="#3366ff"><i>static void gst_native_surface_init (JNIEnv
*env, jobject thiz, jobject surface) {</i><i><br>
</i><i> CustomData *data = GET_CUSTOM_DATA (env, thiz,
custom_data_field_id);</i><i><br>
</i><i> Surface = surface;</i><i><br>
</i><i> if (!data) return;</i><i><br>
</i><i> ANativeWindow *new_native_window =
ANativeWindow_fromSurface(env, surface);</i><i><br>
</i><i> GST_DEBUG ("Received surface %p (native window %p)",
surface, new_native_window);</i><i><br>
</i><i><br>
</i><i> if (data->native_window) {</i><i><br>
</i><i> ANativeWindow_release (data->native_window);</i><i><br>
</i><i> </i><i><br>
</i><i> if (data->native_window == new_native_window) {</i><i><br>
</i><i> GST_DEBUG ("New native window is the same as the
previous one", data->native_window);</i><i><br>
</i><i> if (data->video_sink) {</i><i><br>
</i><i> gst_x_overlay_expose(GST_X_OVERLAY
(data->video_sink));</i><i><br>
</i><i> gst_x_overlay_expose(GST_X_OVERLAY
(data->video_sink));</i><i><br>
</i><i> }</i><i><br>
</i><i> return;</i><i><br>
</i><i> } else {</i><i><br>
</i><i> GST_DEBUG ("Released previous native window %p",
data->native_window);</i><i><br>
</i><i> data->initialized = FALSE;</i><i><br>
</i><i> }</i><i><br>
</i><i> </i><i><br>
</i><i> }</i><i><br>
</i><i> else data->native_window = new_native_window;</i><i><br>
</i><i><br>
</i><i> check_initialization_complete (data);</i><i><br>
</i><i>}</i><i><br>
</i><i><br>
</i><i>static void gst_native_surface_finalize (JNIEnv *env,
jobject thiz) {</i><i><br>
</i><i> CustomData *data = GET_CUSTOM_DATA (env, thiz,
custom_data_field_id);</i><i><br>
</i><i> if (!data) return;</i><i><br>
</i><i> GST_DEBUG ("Releasing Native Window %p",
data->native_window);</i><i><br>
</i><i><br>
</i><i> if (data->video_sink) {</i><i><br>
</i><i> gst_x_overlay_set_window_handle (GST_X_OVERLAY
(data->video_sink), (guintptr)NULL);</i><i><br>
</i><i> gst_element_set_state (data->video_pipeline,
GST_STATE_READY);</i><i><br>
</i><i> }</i><i><br>
</i><i><br>
</i><i> ANativeWindow_release (data->native_window);</i><i><br>
</i><i> data->native_window = NULL;</i><i><br>
</i><i> data->initialized = FALSE;</i><i><br>
</i><i>}</i></font><i><br>
</i><br>
<u>The GstreamerSurfaceView class:</u><u><br>
</u><br>
<font color="#3366ff"><i>import android.content.Context;</i><i><br>
</i><i>import android.util.AttributeSet;</i><i><br>
</i><i>import android.util.Log;</i><i><br>
</i><i>import android.view.SurfaceView;</i><i><br>
</i><i>import android.view.View;</i><i><br>
</i><i><br>
</i><i>// A simple SurfaceView whose width and height can be set
from the outside</i><i><br>
</i><i>public class GStreamerSurfaceView extends SurfaceView {</i><i><br>
</i><i> public int media_width = 320;</i><i><br>
</i><i> public int media_height = 240;</i><i><br>
</i><i><br>
</i><i> // Mandatory constructors, they do not do much</i><i><br>
</i><i> public GStreamerSurfaceView(Context context,
AttributeSet attrs,</i><i><br>
</i><i> int defStyle) {</i><i><br>
</i><i> super(context, attrs, defStyle);</i><i><br>
</i><i> }</i><i><br>
</i><i><br>
</i><i> public GStreamerSurfaceView(Context context,
AttributeSet attrs) {</i><i><br>
</i><i> super(context, attrs);</i><i><br>
</i><i> }</i><i><br>
</i><i><br>
</i><i> public GStreamerSurfaceView (Context context) {</i><i><br>
</i><i> super(context);</i><i><br>
</i><i> }</i><i><br>
</i><i><br>
</i><i> // Called by the layout manager to find out our size
and give us some rules.</i><i><br>
</i><i> // We will try to maximize our size, and preserve the
media's aspect ratio if</i><i><br>
</i><i> // we are given the freedom to do so.</i><i><br>
</i><i> @Override</i><i><br>
</i><i> protected void onMeasure(int widthMeasureSpec, int
heightMeasureSpec) {</i><i><br>
</i><i> int width = 0, height = 0;</i><i><br>
</i><i> int wmode =
View.MeasureSpec.getMode(widthMeasureSpec);</i><i><br>
</i><i> int hmode =
View.MeasureSpec.getMode(heightMeasureSpec);</i><i><br>
</i><i> int wsize =
View.MeasureSpec.getSize(widthMeasureSpec);</i><i><br>
</i><i> int hsize =
View.MeasureSpec.getSize(heightMeasureSpec);</i><i><br>
</i><i><br>
</i><i> Log.i ("GStreamer", "onMeasure called with " +
media_width + "x" + media_height);</i><i><br>
</i><i> // Obey width rules</i><i><br>
</i><i> switch (wmode) {</i><i><br>
</i><i> case View.MeasureSpec.AT_MOST:</i><i><br>
</i><i> if (hmode == View.MeasureSpec.EXACTLY) {</i><i><br>
</i><i> width = Math.min(hsize * media_width /
media_height, wsize);</i><i><br>
</i><i> break;</i><i><br>
</i><i> }</i><i><br>
</i><i> case View.MeasureSpec.EXACTLY:</i><i><br>
</i><i> width = wsize;</i><i><br>
</i><i> break;</i><i><br>
</i><i> case View.MeasureSpec.UNSPECIFIED:</i><i><br>
</i><i> width = media_width;</i><i><br>
</i><i> }</i><i><br>
</i><i><br>
</i><i> // Obey height rules</i><i><br>
</i><i> switch (hmode) {</i><i><br>
</i><i> case View.MeasureSpec.AT_MOST:</i><i><br>
</i><i> if (wmode == View.MeasureSpec.EXACTLY) {</i><i><br>
</i><i> height = Math.min(wsize * media_height /
media_width, hsize);</i><i><br>
</i><i> break;</i><i><br>
</i><i> }</i><i><br>
</i><i> case View.MeasureSpec.EXACTLY:</i><i><br>
</i><i> height = hsize;</i><i><br>
</i><i> break;</i><i><br>
</i><i> case View.MeasureSpec.UNSPECIFIED:</i><i><br>
</i><i> height = media_height;</i><i><br>
</i><i> }</i><i><br>
</i><i><br>
</i><i> // Finally, calculate best size when both axis are
free</i><i><br>
</i><i> if (hmode == View.MeasureSpec.AT_MOST &&
wmode == View.MeasureSpec.AT_MOST) {</i><i><br>
</i><i> int correct_height = width * media_height /
media_width;</i><i><br>
</i><i> int correct_width = height * media_width /
media_height;</i><i><br>
</i><i><br>
</i><i> if (correct_height < height)</i><i><br>
</i><i> height = correct_height;</i><i><br>
</i><i> else</i><i><br>
</i><i> width = correct_width;</i><i><br>
</i><i> }</i><i><br>
</i><i><br>
</i><i> // Obey minimum size</i><i><br>
</i><i> width = Math.max (getSuggestedMinimumWidth(),
width);</i><i><br>
</i><i> height = Math.max (getSuggestedMinimumHeight(),
height);</i><i><br>
</i><i> setMeasuredDimension(width, height);</i><i><br>
</i><i> }</i><i><br>
</i><i><br>
</i><i>}</i></font><br>
<br>
The MainActivity implements SurfaceHolder.Callback:<br>
<br>
<font color="#3333ff"><i> public void surfaceChanged(SurfaceHolder
holder, int format, int width,</i><i><br>
</i><i> int height) {</i><i><br>
</i><i> Log.d("GStreamer", "Surface changed to format "
+ format + " width "</i><i><br>
</i><i> + width + " height " + height);</i><i><br>
</i><i> /</i><i></i><i><br>
</i><i> </i><i><br>
</i><i> nativeSurfaceInit (holder.getSurface());</i><i><br>
</i><i> nativePlay(); </i><i><br>
</i><i> </i><i> </i><i><br>
</i><i> }</i><i><br>
</i><i><br>
</i><i> public void surfaceCreated(SurfaceHolder holder) {</i><i><br>
</i><i> Log.d("GStreamer", "Surface created: " +
holder.getSurface());</i><i><br>
</i><i> }</i><i><br>
</i><i><br>
</i><i> public void surfaceDestroyed(SurfaceHolder holder)
{</i><i><br>
</i><i> Log.d("GStreamer", "Surface destroyed");</i><i><br>
</i><i> // nativePause();</i><i><br>
</i><i> nativeSurfaceFinalize ();</i><i><br>
</i><i> }</i><i><br>
</i><i><br>
</i></font><br>
</body>
</html>