Merge branch 'master' into 0.11
[platform/upstream/gstreamer.git] / gst / rtsp / gstrtspsrc.c
index 8442646..dec7c25 100644 (file)
@@ -285,39 +285,9 @@ G_STMT_START {                                          \
 } G_STMT_END
 
 /*static guint gst_rtspsrc_signals[LAST_SIGNAL] = { 0 }; */
-
-static void
-_do_init (GType rtspsrc_type)
-{
-  static const GInterfaceInfo urihandler_info = {
-    gst_rtspsrc_uri_handler_init,
-    NULL,
-    NULL
-  };
-
-  GST_DEBUG_CATEGORY_INIT (rtspsrc_debug, "rtspsrc", 0, "RTSP src");
-
-  g_type_add_interface_static (rtspsrc_type, GST_TYPE_URI_HANDLER,
-      &urihandler_info);
-}
-
-GST_BOILERPLATE_FULL (GstRTSPSrc, gst_rtspsrc, GstBin, GST_TYPE_BIN, _do_init);
-
-static void
-gst_rtspsrc_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&rtptemplate));
-
-  gst_element_class_set_details_simple (element_class, "RTSP packet receiver",
-      "Source/Network",
-      "Receive data over the network via RTSP (RFC 2326)",
-      "Wim Taymans <wim@fluendo.com>, "
-      "Thijs Vermeir <thijs.vermeir@barco.com>, "
-      "Lutz Mueller <lutz@topfrose.de>");
-}
+#define gst_rtspsrc_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstRTSPSrc, gst_rtspsrc, GST_TYPE_BIN,
+    G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER, gst_rtspsrc_uri_handler_init));
 
 static void
 gst_rtspsrc_class_init (GstRTSPSrcClass * klass)
@@ -330,6 +300,8 @@ gst_rtspsrc_class_init (GstRTSPSrcClass * klass)
   gstelement_class = (GstElementClass *) klass;
   gstbin_class = (GstBinClass *) klass;
 
+  GST_DEBUG_CATEGORY_INIT (rtspsrc_debug, "rtspsrc", 0, "RTSP src");
+
   gobject_class->set_property = gst_rtspsrc_set_property;
   gobject_class->get_property = gst_rtspsrc_get_property;
 
@@ -489,6 +461,16 @@ gst_rtspsrc_class_init (GstRTSPSrcClass * klass)
   gstelement_class->send_event = gst_rtspsrc_send_event;
   gstelement_class->change_state = gst_rtspsrc_change_state;
 
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&rtptemplate));
+
+  gst_element_class_set_details_simple (gstelement_class,
+      "RTSP packet receiver", "Source/Network",
+      "Receive data over the network via RTSP (RFC 2326)",
+      "Wim Taymans <wim@fluendo.com>, "
+      "Thijs Vermeir <thijs.vermeir@barco.com>, "
+      "Lutz Mueller <lutz@topfrose.de>");
+
   gstbin_class->handle_message = gst_rtspsrc_handle_message;
 
   gst_rtsp_ext_list_init ();
@@ -496,7 +478,7 @@ gst_rtspsrc_class_init (GstRTSPSrcClass * klass)
 
 
 static void
-gst_rtspsrc_init (GstRTSPSrc * src, GstRTSPSrcClass * g_class)
+gst_rtspsrc_init (GstRTSPSrc * src)
 {
 #ifdef G_OS_WIN32
   WSADATA wsa_data;
@@ -1621,18 +1603,14 @@ again:
 
   /* we keep these elements, we configure all in configure_transport when the
    * server told us to really use the UDP ports. */
-  stream->udpsrc[0] = gst_object_ref (udpsrc0);
-  stream->udpsrc[1] = gst_object_ref (udpsrc1);
+  stream->udpsrc[0] = gst_object_ref_sink (udpsrc0);
+  stream->udpsrc[1] = gst_object_ref_sink (udpsrc1);
 
   /* keep track of next available port number when we have a range
    * configured */
   if (src->next_port_num != 0)
     src->next_port_num = tmp_rtcp + 1;
 
-  /* they are ours now */
-  gst_object_sink (udpsrc0);
-  gst_object_sink (udpsrc1);
-
   return TRUE;
 
   /* ERRORS */
@@ -1688,7 +1666,7 @@ gst_rtspsrc_flush (GstRTSPSrc * src, gboolean flush)
     cmd = CMD_WAIT;
     state = GST_STATE_PAUSED;
   } else {
-    event = gst_event_new_flush_stop ();
+    event = gst_event_new_flush_stop (TRUE);
     GST_DEBUG_OBJECT (src, "stop flush");
     cmd = CMD_LOOP;
     state = GST_STATE_PLAYING;
@@ -1861,7 +1839,7 @@ gst_rtspsrc_perform_seek (GstRTSPSrc * src, GstEvent * event)
    * right values in the segment to perform the seek */
   if (event) {
     GST_DEBUG_OBJECT (src, "configuring seek");
-    gst_segment_set_seek (&seeksegment, rate, format, flags,
+    gst_segment_do_seek (&seeksegment, rate, format, flags,
         cur_type, cur, stop_type, stop, &update);
   }
 
@@ -1890,24 +1868,6 @@ gst_rtspsrc_perform_seek (GstRTSPSrc * src, GstEvent * event)
     /* if we started flush, we stop now */
     GST_DEBUG_OBJECT (src, "stopping flush");
     gst_rtspsrc_flush (src, FALSE);
-  } else if (src->running) {
-    /* re-engage loop */
-    gst_rtspsrc_loop_send_cmd (src, CMD_LOOP, FALSE);
-
-    /* we are running the current segment and doing a non-flushing seek,
-     * close the segment first based on the previous last_stop. */
-    GST_DEBUG_OBJECT (src, "closing running segment %" G_GINT64_FORMAT
-        " to %" G_GINT64_FORMAT, src->segment.accum, src->segment.last_stop);
-
-    /* queue the segment for sending in the stream thread */
-    if (src->close_segment)
-      gst_event_unref (src->close_segment);
-    src->close_segment = gst_event_new_new_segment (TRUE,
-        src->segment.rate, src->segment.format,
-        src->segment.accum, src->segment.last_stop, src->segment.accum);
-
-    /* keep track of our last_stop */
-    seeksegment.accum = src->segment.last_stop;
   }
 
   /* now we did the seek and can activate the new segment values */
@@ -1917,20 +1877,17 @@ gst_rtspsrc_perform_seek (GstRTSPSrc * src, GstEvent * event)
   if (src->segment.flags & GST_SEEK_FLAG_SEGMENT) {
     gst_element_post_message (GST_ELEMENT_CAST (src),
         gst_message_new_segment_start (GST_OBJECT_CAST (src),
-            src->segment.format, src->segment.last_stop));
+            src->segment.format, src->segment.position));
   }
 
   /* now create the newsegment */
   GST_DEBUG_OBJECT (src, "Creating newsegment from %" G_GINT64_FORMAT
-      " to %" G_GINT64_FORMAT, src->segment.last_stop, stop);
+      " to %" G_GINT64_FORMAT, src->segment.position, stop);
 
   /* store the newsegment event so it can be sent from the streaming thread. */
   if (src->start_segment)
     gst_event_unref (src->start_segment);
-  src->start_segment =
-      gst_event_new_new_segment (FALSE, src->segment.rate,
-      src->segment.format, src->segment.last_stop, stop,
-      src->segment.last_stop);
+  src->start_segment = gst_event_new_segment (&src->segment);
 
   /* mark discont */
   GST_DEBUG_OBJECT (src, "mark DISCONT, we did a seek to another position");
@@ -2149,6 +2106,7 @@ gst_rtspsrc_sink_chain (GstPad * pad, GstBuffer * buffer)
   GstFlowReturn res = GST_FLOW_OK;
   guint8 *data;
   guint size;
+  gsize bsize;
   GstRTSPResult ret;
   GstRTSPMessage message = { 0 };
   GstRTSPConnection *conn;
@@ -2156,8 +2114,8 @@ gst_rtspsrc_sink_chain (GstPad * pad, GstBuffer * buffer)
   stream = (GstRTSPStream *) gst_pad_get_element_private (pad);
   src = stream->parent;
 
-  data = GST_BUFFER_DATA (buffer);
-  size = GST_BUFFER_SIZE (buffer);
+  data = gst_buffer_map (buffer, &bsize, NULL, GST_MAP_READ);
+  size = bsize;
 
   gst_rtsp_message_init_data (&message, stream->channel[1]);
 
@@ -2178,20 +2136,18 @@ gst_rtspsrc_sink_chain (GstPad * pad, GstBuffer * buffer)
   gst_rtsp_message_steal_body (&message, &data, &size);
   gst_rtsp_message_unset (&message);
 
+  gst_buffer_unmap (buffer, data, size);
   gst_buffer_unref (buffer);
 
   return res;
 }
 
-static void
-pad_unblocked (GstPad * pad, gboolean blocked, GstRTSPSrc * src)
+static GstProbeReturn
+pad_blocked (GstPad * pad, GstProbeType type, gpointer type_data,
+    gpointer user_data)
 {
-  GST_DEBUG_OBJECT (src, "pad %s:%s unblocked", GST_DEBUG_PAD_NAME (pad));
-}
+  GstRTSPSrc *src = user_data;
 
-static void
-pad_blocked (GstPad * pad, gboolean blocked, GstRTSPSrc * src)
-{
   GST_DEBUG_OBJECT (src, "pad %s:%s blocked, activating streams",
       GST_DEBUG_PAD_NAME (pad));
 
@@ -2205,12 +2161,12 @@ pad_blocked (GstPad * pad, gboolean blocked, GstRTSPSrc * src)
 
   gst_rtspsrc_activate_streams (src);
 
-  return;
+  return GST_PROBE_OK;
 
 was_ok:
   {
     GST_OBJECT_UNLOCK (src);
-    return;
+    return GST_PROBE_OK;
   }
 }
 
@@ -2735,8 +2691,7 @@ gst_rtspsrc_stream_configure_mcast (GstRTSPSrc * src, GstRTSPStream * stream,
       goto no_element;
 
     /* take ownership */
-    gst_object_ref (stream->udpsrc[0]);
-    gst_object_sink (stream->udpsrc[0]);
+    gst_object_ref_sink (stream->udpsrc[0]);
 
     /* change state */
     gst_element_set_state (stream->udpsrc[0], GST_STATE_PAUSED);
@@ -2751,8 +2706,7 @@ gst_rtspsrc_stream_configure_mcast (GstRTSPSrc * src, GstRTSPStream * stream,
       goto no_element;
 
     /* take ownership */
-    gst_object_ref (stream->udpsrc[1]);
-    gst_object_sink (stream->udpsrc[1]);
+    gst_object_ref_sink (stream->udpsrc[1]);
 
     gst_element_set_state (stream->udpsrc[1], GST_STATE_PAUSED);
   }
@@ -2803,8 +2757,9 @@ gst_rtspsrc_stream_configure_udp (GstRTSPSrc * src, GstRTSPStream * stream,
     /* configure pad block on the pad. As soon as there is dataflow on the
      * UDP source, we know that UDP is not blocked by a firewall and we can
      * configure all the streams to let the application autoplug decoders. */
-    gst_pad_set_blocked_async (stream->blockedpad, TRUE,
-        (GstPadBlockCallback) pad_blocked, src);
+    stream->blockid =
+        gst_pad_add_probe (stream->blockedpad, GST_PROBE_TYPE_BLOCK,
+        pad_blocked, src, NULL);
 
     if (stream->channelpad[0]) {
       GST_DEBUG_OBJECT (src, "connecting UDP source 0 to manager");
@@ -3157,11 +3112,10 @@ gst_rtspsrc_activate_streams (GstRTSPSrc * src)
   for (walk = src->streams; walk; walk = g_list_next (walk)) {
     GstRTSPStream *stream = (GstRTSPStream *) walk->data;
 
-    if (stream->blockedpad) {
+    if (stream->blockid) {
       GST_DEBUG_OBJECT (src, "unblocking stream pad %p", stream);
-      gst_pad_set_blocked_async (stream->blockedpad, FALSE,
-          (GstPadBlockCallback) pad_unblocked, src);
-      stream->blockedpad = NULL;
+      gst_pad_remove_probe (stream->blockedpad, stream->blockid);
+      stream->blockid = 0;
     }
   }
 
@@ -3177,7 +3131,7 @@ gst_rtspsrc_configure_caps (GstRTSPSrc * src, GstSegment * segment)
 
   GST_DEBUG_OBJECT (src, "configuring stream caps");
 
-  start = segment->last_stop;
+  start = segment->position;
   stop = segment->duration;
   play_speed = segment->rate;
   play_scale = segment->applied_rate;
@@ -3658,9 +3612,8 @@ gst_rtspsrc_loop_interleaved (GstRTSPSrc * src)
   size -= 1;
 
   buf = gst_buffer_new ();
-  GST_BUFFER_DATA (buf) = data;
-  GST_BUFFER_MALLOCDATA (buf) = data;
-  GST_BUFFER_SIZE (buf) = size;
+  gst_buffer_take_memory (buf, -1,
+      gst_memory_new_wrapped (0, data, g_free, size, 0, size));
 
   /* don't need message anymore */
   gst_rtsp_message_unset (&message);
@@ -3673,12 +3626,6 @@ gst_rtspsrc_loop_interleaved (GstRTSPSrc * src)
     src->need_activate = FALSE;
   }
 
-  if (!src->manager) {
-    /* set stream caps on buffer when we don't have a session manager to do it
-     * for us */
-    gst_buffer_set_caps (buf, stream->caps);
-  }
-
   if (src->base_time == -1) {
     /* Take current running_time. This timestamp will be put on
      * the first buffer of each stream because we are a live source and so we
@@ -4161,7 +4108,7 @@ pause:
       if (src->segment.flags & GST_SEEK_FLAG_SEGMENT) {
         gst_element_post_message (GST_ELEMENT_CAST (src),
             gst_message_new_segment_done (GST_OBJECT_CAST (src),
-                src->segment.format, src->segment.last_stop));
+                src->segment.format, src->segment.position));
       } else {
         gst_rtspsrc_push_event (src, gst_event_new_eos (), FALSE);
       }
@@ -5421,7 +5368,7 @@ gst_rtspsrc_parse_range (GstRTSPSrc * src, const gchar * range,
   /* we need to start playback without clipping from the position reported by
    * the server */
   segment->start = seconds;
-  segment->last_stop = seconds;
+  segment->position = seconds;
 
   if (therange->max.type == GST_RTSP_TIME_NOW)
     seconds = -1;
@@ -5447,7 +5394,7 @@ gst_rtspsrc_parse_range (GstRTSPSrc * src, const gchar * range,
   /* don't change duration with unknown value, we might have a valid value
    * there that we want to keep. */
   if (seconds != -1)
-    gst_segment_set_duration (segment, GST_FORMAT_TIME, seconds);
+    segment->duration = seconds;
 
   return TRUE;
 }
@@ -5973,11 +5920,11 @@ gen_range_header (GstRTSPSrc * src, GstSegment * segment)
   if (src->range && src->range->min.type == GST_RTSP_TIME_NOW) {
     g_strlcpy (val_str, "now", sizeof (val_str));
   } else {
-    if (segment->last_stop == 0) {
+    if (segment->position == 0) {
       g_strlcpy (val_str, "0", sizeof (val_str));
     } else {
       g_ascii_dtostr (val_str, sizeof (val_str),
-          ((gdouble) segment->last_stop) / GST_SECOND);
+          ((gdouble) segment->position) / GST_SECOND);
     }
   }
   return g_strdup_printf ("npt=%s-", val_str);
@@ -6129,7 +6076,7 @@ gst_rtspsrc_play (GstRTSPSrc * src, GstSegment * segment, gboolean async)
       /* NOTE the above also disables npt based eos detection */
       /* and below forces position to 0,
        * which is visible feedback we lost the plot */
-      segment->start = segment->last_stop = src->last_pos;
+      segment->start = segment->position = src->last_pos;
     }
 
     gst_rtsp_message_unset (&request);
@@ -6647,13 +6594,13 @@ gst_rtspsrc_send_event (GstElement * element, GstEvent * event)
 /*** GSTURIHANDLER INTERFACE *************************************************/
 
 static GstURIType
-gst_rtspsrc_uri_get_type (void)
+gst_rtspsrc_uri_get_type (GType type)
 {
   return GST_URI_SRC;
 }
 
 static gchar **
-gst_rtspsrc_uri_get_protocols (void)
+gst_rtspsrc_uri_get_protocols (GType type)
 {
   static const gchar *protocols[] =
       { "rtsp", "rtspu", "rtspt", "rtsph", "rtsp-sdp", NULL };