ext/dv/gstdvdemux.c: Add srcpads only when needed and remove them again when going...
authorSebastian Dröge <slomo@circular-chaos.org>
Tue, 9 Dec 2008 09:39:53 +0000 (09:39 +0000)
committerSebastian Dröge <slomo@circular-chaos.org>
Tue, 9 Dec 2008 09:39:53 +0000 (09:39 +0000)
Original commit message from CVS:
* ext/dv/gstdvdemux.c: (gst_dvdemux_add_video_pad),
(gst_dvdemux_add_audio_pad), (gst_dvdemux_remove_pads),
(gst_dvdemux_demux_audio), (gst_dvdemux_demux_video),
(gst_dvdemux_chain), (gst_dvdemux_loop),
(gst_dvdemux_change_state):
Add srcpads only when needed and remove them again when going
back to READY. This prevents stalled pipelines if there's no
audio inside the DV stream, which happens for many MXF files.

ChangeLog
ext/dv/gstdvdemux.c

index 9e30851..fc93ecd 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
 2008-12-09  Sebastian Dröge  <sebastian.droege@collabora.co.uk>
 
+       * ext/dv/gstdvdemux.c: (gst_dvdemux_add_video_pad),
+       (gst_dvdemux_add_audio_pad), (gst_dvdemux_remove_pads),
+       (gst_dvdemux_demux_audio), (gst_dvdemux_demux_video),
+       (gst_dvdemux_chain), (gst_dvdemux_loop),
+       (gst_dvdemux_change_state):
+       Add srcpads only when needed and remove them again when going
+       back to READY. This prevents stalled pipelines if there's no
+       audio inside the DV stream, which happens for many MXF files.
+
+2008-12-09  Sebastian Dröge  <sebastian.droege@collabora.co.uk>
+
        * tests/check/elements/souphttpsrc.c: (GST_START_TEST),
        (run_server):
        The ports in libsoup are unsigned integers and not signed
index 916a34d..a12b2d6 100644 (file)
@@ -292,8 +292,11 @@ gst_dvdemux_reset (GstDVDemux * dvdemux)
 }
 
 static void
-gst_dvdemux_add_pads (GstDVDemux * dvdemux)
+gst_dvdemux_add_video_pad (GstDVDemux * dvdemux)
 {
+  if (dvdemux->videosrcpad)
+    return;
+
   dvdemux->videosrcpad =
       gst_pad_new_from_static_template (&video_src_temp, "video");
   gst_pad_set_query_function (dvdemux->videosrcpad,
@@ -306,6 +309,21 @@ gst_dvdemux_add_pads (GstDVDemux * dvdemux)
   gst_pad_set_active (dvdemux->videosrcpad, TRUE);
   gst_element_add_pad (GST_ELEMENT (dvdemux), dvdemux->videosrcpad);
 
+  if (dvdemux->videosrcpad && dvdemux->audiosrcpad)
+    gst_element_no_more_pads (GST_ELEMENT (dvdemux));
+
+  gst_pad_push_event (dvdemux->videosrcpad, gst_event_new_new_segment (FALSE,
+          dvdemux->byte_segment.rate, GST_FORMAT_TIME,
+          dvdemux->time_segment.start, dvdemux->time_segment.stop,
+          dvdemux->time_segment.start));
+}
+
+static void
+gst_dvdemux_add_audio_pad (GstDVDemux * dvdemux)
+{
+  if (dvdemux->audiosrcpad)
+    return;
+
   dvdemux->audiosrcpad =
       gst_pad_new_from_static_template (&audio_src_temp, "audio");
   gst_pad_set_query_function (dvdemux->audiosrcpad,
@@ -318,7 +336,26 @@ gst_dvdemux_add_pads (GstDVDemux * dvdemux)
   gst_pad_set_active (dvdemux->audiosrcpad, TRUE);
   gst_element_add_pad (GST_ELEMENT (dvdemux), dvdemux->audiosrcpad);
 
-  gst_element_no_more_pads (GST_ELEMENT (dvdemux));
+  if (dvdemux->videosrcpad && dvdemux->audiosrcpad)
+    gst_element_no_more_pads (GST_ELEMENT (dvdemux));
+
+  gst_pad_push_event (dvdemux->audiosrcpad, gst_event_new_new_segment (FALSE,
+          dvdemux->byte_segment.rate, GST_FORMAT_TIME,
+          dvdemux->time_segment.start, dvdemux->time_segment.stop,
+          dvdemux->time_segment.start));
+}
+
+static void
+gst_dvdemux_remove_pads (GstDVDemux * dvdemux)
+{
+  if (dvdemux->videosrcpad) {
+    gst_element_remove_pad (GST_ELEMENT (dvdemux), dvdemux->videosrcpad);
+    dvdemux->videosrcpad = NULL;
+  }
+  if (dvdemux->audiosrcpad) {
+    gst_element_remove_pad (GST_ELEMENT (dvdemux), dvdemux->audiosrcpad);
+    dvdemux->audiosrcpad = NULL;
+  }
 }
 
 static gboolean
@@ -1186,40 +1223,18 @@ gst_dvdemux_demux_audio (GstDVDemux * dvdemux, GstBuffer * buffer,
     guint64 duration)
 {
   gint num_samples;
-  gint frequency, channels;
   GstFlowReturn ret;
   const guint8 *data;
 
-  frequency = dv_get_frequency (dvdemux->decoder);
-  channels = dv_get_num_channels (dvdemux->decoder);
-
   data = GST_BUFFER_DATA (buffer);
 
-  /* check if format changed */
-  if ((frequency != dvdemux->frequency) || (channels != dvdemux->channels)) {
-    GstCaps *caps;
-
-    dvdemux->frequency = frequency;
-    dvdemux->channels = channels;
-
-    /* and set new caps */
-    caps = gst_caps_new_simple ("audio/x-raw-int",
-        "rate", G_TYPE_INT, frequency,
-        "depth", G_TYPE_INT, 16,
-        "width", G_TYPE_INT, 16,
-        "signed", G_TYPE_BOOLEAN, TRUE,
-        "channels", G_TYPE_INT, channels,
-        "endianness", G_TYPE_INT, G_BYTE_ORDER, NULL);
-    gst_pad_set_caps (dvdemux->audiosrcpad, caps);
-    gst_caps_unref (caps);
-  }
-
   dv_decode_full_audio (dvdemux->decoder, data, dvdemux->audio_buffers);
 
   if ((num_samples = dv_get_num_samples (dvdemux->decoder)) > 0) {
     gint16 *a_ptr;
     gint i, j;
     GstBuffer *outbuf;
+    gint frequency, channels;
 
     outbuf = gst_buffer_new_and_alloc (num_samples *
         sizeof (gint16) * dvdemux->channels);
@@ -1241,6 +1256,31 @@ gst_dvdemux_demux_audio (GstDVDemux * dvdemux, GstBuffer * buffer,
     dvdemux->audio_offset += num_samples;
     GST_BUFFER_OFFSET_END (outbuf) = dvdemux->audio_offset;
 
+    if (!dvdemux->audiosrcpad)
+      gst_dvdemux_add_audio_pad (dvdemux);
+
+    /* check if format changed */
+    frequency = dv_get_frequency (dvdemux->decoder);
+    channels = dv_get_num_channels (dvdemux->decoder);
+
+    if ((frequency != dvdemux->frequency) || (channels != dvdemux->channels)) {
+      GstCaps *caps;
+
+      dvdemux->frequency = frequency;
+      dvdemux->channels = channels;
+
+      /* and set new caps */
+      caps = gst_caps_new_simple ("audio/x-raw-int",
+          "rate", G_TYPE_INT, frequency,
+          "depth", G_TYPE_INT, 16,
+          "width", G_TYPE_INT, 16,
+          "signed", G_TYPE_BOOLEAN, TRUE,
+          "channels", G_TYPE_INT, channels,
+          "endianness", G_TYPE_INT, G_BYTE_ORDER, NULL);
+      gst_pad_set_caps (dvdemux->audiosrcpad, caps);
+      gst_caps_unref (caps);
+    }
+
     gst_buffer_set_caps (outbuf, GST_PAD_CAPS (dvdemux->audiosrcpad));
 
     ret = gst_pad_push (dvdemux->audiosrcpad, outbuf);
@@ -1262,6 +1302,9 @@ gst_dvdemux_demux_video (GstDVDemux * dvdemux, GstBuffer * buffer,
   gboolean wide;
   GstFlowReturn ret = GST_FLOW_OK;
 
+  if (!dvdemux->videosrcpad)
+    gst_dvdemux_add_video_pad (dvdemux);
+
   /* get params */
   /* framerate is already up-to-date */
   height = (dvdemux->PAL ? PAL_HEIGHT : NTSC_HEIGHT);
@@ -1511,10 +1554,6 @@ gst_dvdemux_chain (GstPad * pad, GstBuffer * buffer)
     /* FIXME, adjust frame_offset and other counters */
   }
 
-  /* temporary hack? Can't do this from the state change */
-  if (G_UNLIKELY (!dvdemux->videosrcpad))
-    gst_dvdemux_add_pads (dvdemux);
-
   gst_adapter_push (dvdemux->adapter, buffer);
 
   /* Apparently dv_parse_header can read from the body of the frame
@@ -1551,10 +1590,6 @@ gst_dvdemux_loop (GstPad * pad)
   dvdemux = GST_DVDEMUX (gst_pad_get_parent (pad));
 
   if (G_UNLIKELY (g_atomic_int_get (&dvdemux->found_header) == 0)) {
-    /* add pads.. why is this again? */
-    if (!dvdemux->videosrcpad)
-      gst_dvdemux_add_pads (dvdemux);
-
     GST_DEBUG_OBJECT (dvdemux, "pulling first buffer");
     /* pull in NTSC sized buffer to figure out the frame
      * length */
@@ -1785,6 +1820,8 @@ gst_dvdemux_change_state (GstElement * element, GstStateChange transition)
       gst_adapter_clear (dvdemux->adapter);
       dv_decoder_free (dvdemux->decoder);
       dvdemux->decoder = NULL;
+
+      gst_dvdemux_remove_pads (dvdemux);
       break;
     case GST_STATE_CHANGE_READY_TO_NULL:
     {