mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-04 17:52:29 +00:00
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
This commit is contained in:
parent
6beda8aae0
commit
a5f22f03aa
2 changed files with 59 additions and 7 deletions
|
@ -1028,13 +1028,19 @@ atom_trak_new (AtomsContext * context)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
atom_trak_free (AtomTRAK * trak)
|
atom_trak_clear (AtomTRAK * trak)
|
||||||
{
|
{
|
||||||
atom_clear (&trak->header);
|
atom_clear (&trak->header);
|
||||||
atom_tkhd_clear (&trak->tkhd);
|
atom_tkhd_clear (&trak->tkhd);
|
||||||
if (trak->edts)
|
if (trak->edts)
|
||||||
atom_edts_free (trak->edts);
|
atom_edts_free (trak->edts);
|
||||||
atom_mdia_clear (&trak->mdia);
|
atom_mdia_clear (&trak->mdia);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
atom_trak_free (AtomTRAK * trak)
|
||||||
|
{
|
||||||
|
atom_trak_clear (trak);
|
||||||
g_free (trak);
|
g_free (trak);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1702,6 +1702,26 @@ gst_qt_mux_collected (GstCollectPads * pads, gpointer user_data)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
static gboolean
|
||||||
gst_qt_mux_audio_sink_set_caps (GstPad * pad, GstCaps * caps)
|
gst_qt_mux_audio_sink_set_caps (GstPad * pad, GstCaps * caps)
|
||||||
{
|
{
|
||||||
|
@ -1718,6 +1738,7 @@ gst_qt_mux_audio_sink_set_caps (GstPad * pad, GstCaps * caps)
|
||||||
AtomInfo *ext_atom = NULL;
|
AtomInfo *ext_atom = NULL;
|
||||||
gint constant_size = 0;
|
gint constant_size = 0;
|
||||||
const gchar *stream_format;
|
const gchar *stream_format;
|
||||||
|
GstCaps *current_caps = NULL;
|
||||||
|
|
||||||
/* find stream data */
|
/* find stream data */
|
||||||
qtpad = (GstQTPad *) gst_pad_get_element_private (pad);
|
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;
|
qtpad->prepare_buf_func = NULL;
|
||||||
|
|
||||||
/* does not go well to renegotiate stream mid-way */
|
/* does not go well to renegotiate stream mid-way, unless
|
||||||
if (qtpad->fourcc)
|
* the old caps are a subset of the new one (this means upstream
|
||||||
goto refuse_renegotiation;
|
* 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_OBJECT (qtmux, "%s:%s, caps=%" GST_PTR_FORMAT,
|
||||||
GST_DEBUG_PAD_NAME (pad), caps);
|
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;
|
GList *ext_atom_list = NULL;
|
||||||
gboolean sync = FALSE;
|
gboolean sync = FALSE;
|
||||||
int par_num, par_den;
|
int par_num, par_den;
|
||||||
|
GstCaps *current_caps = NULL;
|
||||||
|
|
||||||
/* find stream data */
|
/* find stream data */
|
||||||
qtpad = (GstQTPad *) gst_pad_get_element_private (pad);
|
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;
|
qtpad->prepare_buf_func = NULL;
|
||||||
|
|
||||||
/* does not go well to renegotiate stream mid-way */
|
/* does not go well to renegotiate stream mid-way, unless
|
||||||
if (qtpad->fourcc)
|
* the old caps are a subset of the new one (this means upstream
|
||||||
goto refuse_renegotiation;
|
* 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_OBJECT (qtmux, "%s:%s, caps=%" GST_PTR_FORMAT,
|
||||||
GST_DEBUG_PAD_NAME (pad), caps);
|
GST_DEBUG_PAD_NAME (pad), caps);
|
||||||
|
|
Loading…
Reference in a new issue