[gst-cvs] gst-plugins-bad: qtmux: Do caps renegotiation when it only adds fields

Thiago Sousa Santos thiagoss at kemper.freedesktop.org
Thu Jan 14 14:13:17 PST 2010


Module: gst-plugins-bad
Branch: master
Commit: 0b4c0890a5e8ab31b469697ee0f82320851a5891
URL:    http://cgit.freedesktop.org/gstreamer/gst-plugins-bad/commit/?id=0b4c0890a5e8ab31b469697ee0f82320851a5891

Author: Thiago Santos <thiago.sousa.santos at collabora.co.uk>
Date:   Wed Jan 13 23:33:51 2010 -0300

qtmux: Do caps renegotiation when it only adds fields

Qtmux can accept caps renegotiation if the new caps is a
superset of the old one, meaning upstream added new info to
the caps. This patch still doesn't make qtmux update any
atoms info from the new info, but at least it doesn't
reject the new caps anymore.

A pipeline that reproduces this use case is:

videotestsrc num-buffers=200 ! x264enc byte-stream=true ! \
h264parse output-format=0 ! qtmux ! \
filesink location=test.mov

---

 gst/qtmux/atoms.c    |    8 ++++++-
 gst/qtmux/gstqtmux.c |   58 ++++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 59 insertions(+), 7 deletions(-)

diff --git a/gst/qtmux/atoms.c b/gst/qtmux/atoms.c
index 84c3068..3d7c10f 100644
--- a/gst/qtmux/atoms.c
+++ b/gst/qtmux/atoms.c
@@ -1028,13 +1028,19 @@ atom_trak_new (AtomsContext * context)
 }
 
 static void
-atom_trak_free (AtomTRAK * trak)
+atom_trak_clear (AtomTRAK * trak)
 {
   atom_clear (&trak->header);
   atom_tkhd_clear (&trak->tkhd);
   if (trak->edts)
     atom_edts_free (trak->edts);
   atom_mdia_clear (&trak->mdia);
+}
+
+static void
+atom_trak_free (AtomTRAK * trak)
+{
+  atom_trak_clear (trak);
   g_free (trak);
 }
 
diff --git a/gst/qtmux/gstqtmux.c b/gst/qtmux/gstqtmux.c
index a6ec2c3..aaba67b 100644
--- a/gst/qtmux/gstqtmux.c
+++ b/gst/qtmux/gstqtmux.c
@@ -1703,6 +1703,26 @@ gst_qt_mux_collected (GstCollectPads * pads, gpointer user_data)
 }
 
 static gboolean
+check_field (GQuark field_id, const GValue * value, gpointer user_data)
+{
+  GstStructure *structure = (GstStructure *) user_data;
+  const GValue *other = gst_structure_id_get_value (structure, field_id);
+  if (other == NULL)
+    return FALSE;
+  return gst_value_compare (value, other) == GST_VALUE_EQUAL;
+}
+
+static gboolean
+gst_qtmux_caps_is_subset_full (GstQTMux * qtmux, GstCaps * subset,
+    GstCaps * superset)
+{
+  GstStructure *sub_s = gst_caps_get_structure (subset, 0);
+  GstStructure *sup_s = gst_caps_get_structure (superset, 0);
+
+  return gst_structure_foreach (sub_s, check_field, sup_s);
+}
+
+static gboolean
 gst_qt_mux_audio_sink_set_caps (GstPad * pad, GstCaps * caps)
 {
   GstQTMux *qtmux = GST_QT_MUX_CAST (gst_pad_get_parent (pad));
@@ -1718,6 +1738,7 @@ gst_qt_mux_audio_sink_set_caps (GstPad * pad, GstCaps * caps)
   AtomInfo *ext_atom = NULL;
   gint constant_size = 0;
   const gchar *stream_format;
+  GstCaps *current_caps = NULL;
 
   /* find stream data */
   qtpad = (GstQTPad *) gst_pad_get_element_private (pad);
@@ -1725,9 +1746,21 @@ gst_qt_mux_audio_sink_set_caps (GstPad * pad, GstCaps * caps)
 
   qtpad->prepare_buf_func = NULL;
 
-  /* does not go well to renegotiate stream mid-way */
-  if (qtpad->fourcc)
-    goto refuse_renegotiation;
+  /* does not go well to renegotiate stream mid-way, unless
+   * the old caps are a subset of the new one (this means upstream
+   * added more info to the caps, as both should be 'fixed' caps) */
+  if (qtpad->fourcc) {
+    g_object_get (pad, "caps", &current_caps, NULL);
+    g_assert (caps != NULL);
+
+    if (!gst_qtmux_caps_is_subset_full (qtmux, current_caps, caps)) {
+      goto refuse_renegotiation;
+    }
+    GST_DEBUG_OBJECT (qtmux,
+        "pad %s accepted renegotiation to %" GST_PTR_FORMAT " from %"
+        GST_PTR_FORMAT, GST_PAD_NAME (pad), caps, GST_PAD_CAPS (pad));
+    return TRUE;
+  }
 
   GST_DEBUG_OBJECT (qtmux, "%s:%s, caps=%" GST_PTR_FORMAT,
       GST_DEBUG_PAD_NAME (pad), caps);
@@ -1984,6 +2017,7 @@ gst_qt_mux_video_sink_set_caps (GstPad * pad, GstCaps * caps)
   GList *ext_atom_list = NULL;
   gboolean sync = FALSE;
   int par_num, par_den;
+  GstCaps *current_caps = NULL;
 
   /* find stream data */
   qtpad = (GstQTPad *) gst_pad_get_element_private (pad);
@@ -1991,9 +2025,21 @@ gst_qt_mux_video_sink_set_caps (GstPad * pad, GstCaps * caps)
 
   qtpad->prepare_buf_func = NULL;
 
-  /* does not go well to renegotiate stream mid-way */
-  if (qtpad->fourcc)
-    goto refuse_renegotiation;
+  /* does not go well to renegotiate stream mid-way, unless
+   * the old caps are a subset of the new one (this means upstream
+   * added more info to the caps, as both should be 'fixed' caps) */
+  if (qtpad->fourcc) {
+    g_object_get (pad, "caps", &current_caps, NULL);
+    g_assert (caps != NULL);
+
+    if (!gst_qtmux_caps_is_subset_full (qtmux, current_caps, caps)) {
+      goto refuse_renegotiation;
+    }
+    GST_DEBUG_OBJECT (qtmux,
+        "pad %s accepted renegotiation to %" GST_PTR_FORMAT " from %"
+        GST_PTR_FORMAT, GST_PAD_NAME (pad), caps, GST_PAD_CAPS (pad));
+    return TRUE;
+  }
 
   GST_DEBUG_OBJECT (qtmux, "%s:%s, caps=%" GST_PTR_FORMAT,
       GST_DEBUG_PAD_NAME (pad), caps);





More information about the Gstreamer-commits mailing list