}
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));
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);
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", ¤t_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);
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);
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", ¤t_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);