mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-19 23:06:49 +00:00
playbin: Use the GSequence more efficiently
This makes it possible to take advantage of the O(log n) lookups of GSequence on the ~1000 element lists and only do iterations on <10 element lists. Previously the code iterated over ~1000 element lists multiple times.
This commit is contained in:
parent
52c5115ff0
commit
7ff4f8f4d4
1 changed files with 122 additions and 34 deletions
|
@ -3285,7 +3285,32 @@ avelements_free (gpointer avelement)
|
|||
}
|
||||
|
||||
static gint
|
||||
avelement_compare (gconstpointer p1, gconstpointer p2, gpointer user_data)
|
||||
avelement_compare_decoder (gconstpointer p1, gconstpointer p2,
|
||||
gpointer user_data)
|
||||
{
|
||||
GstAVElement *v1, *v2;
|
||||
|
||||
v1 = (GstAVElement *) p1;
|
||||
v2 = (GstAVElement *) p2;
|
||||
|
||||
return strcmp (GST_OBJECT_NAME (v1->dec), GST_OBJECT_NAME (v2->dec));
|
||||
}
|
||||
|
||||
static gint
|
||||
avelement_lookup_decoder (gconstpointer p1, gconstpointer p2,
|
||||
gpointer user_data)
|
||||
{
|
||||
GstAVElement *v1;
|
||||
GstElementFactory *f2;
|
||||
|
||||
v1 = (GstAVElement *) p1;
|
||||
f2 = (GstElementFactory *) p2;
|
||||
|
||||
return strcmp (GST_OBJECT_NAME (v1->dec), GST_OBJECT_NAME (f2));
|
||||
}
|
||||
|
||||
static gint
|
||||
avelement_compare (gconstpointer p1, gconstpointer p2)
|
||||
{
|
||||
GstAVElement *v1, *v2;
|
||||
GstPluginFeature *fd1, *fd2, *fs1, *fs2;
|
||||
|
@ -3452,7 +3477,7 @@ avelements_create (GstPlayBin * playbin, gboolean isaudioelement)
|
|||
}
|
||||
sl = sink_list;
|
||||
}
|
||||
g_sequence_sort (ave_seq, (GCompareDataFunc) avelement_compare, NULL);
|
||||
g_sequence_sort (ave_seq, (GCompareDataFunc) avelement_compare_decoder, NULL);
|
||||
|
||||
gst_plugin_feature_list_free (dec_list);
|
||||
gst_plugin_feature_list_free (sink_list);
|
||||
|
@ -3460,45 +3485,82 @@ avelements_create (GstPlayBin * playbin, gboolean isaudioelement)
|
|||
return ave_seq;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
avelement_iter_is_equal (GSequenceIter * iter, GstElementFactory * factory)
|
||||
{
|
||||
GstAVElement *ave;
|
||||
|
||||
if (!iter)
|
||||
return FALSE;
|
||||
|
||||
ave = g_sequence_get (iter);
|
||||
if (!ave)
|
||||
return FALSE;
|
||||
|
||||
return strcmp (GST_OBJECT_NAME (ave->dec), GST_OBJECT_NAME (factory)) == 0;
|
||||
}
|
||||
|
||||
static GList *
|
||||
create_decoders_list (GList * factory_list, GSequence * avelements)
|
||||
{
|
||||
GList *dec_list = NULL, *tmp;
|
||||
GSequenceIter *seq_iter = NULL;
|
||||
GstElementFactory *factory;
|
||||
GstAVElement *ave;
|
||||
guint dl_length, dl_count = 0;
|
||||
GList *ave_list = NULL;
|
||||
GstAVElement *ave, *best_ave;
|
||||
|
||||
g_return_val_if_fail (factory_list != NULL, NULL);
|
||||
g_return_val_if_fail (avelements != NULL, NULL);
|
||||
|
||||
dl_length = g_list_length (factory_list);
|
||||
tmp = factory_list;
|
||||
for (tmp = factory_list; tmp; tmp = tmp->next) {
|
||||
GstElementFactory *factory = (GstElementFactory *) tmp->data;
|
||||
|
||||
for (; tmp; tmp = tmp->next) {
|
||||
factory = (GstElementFactory *) tmp->data;
|
||||
/* if there are parsers or sink elements, add them first */
|
||||
if (!gst_element_factory_list_is_type (factory,
|
||||
GST_ELEMENT_FACTORY_TYPE_DECODER)) {
|
||||
dec_list = g_list_prepend (dec_list, factory);
|
||||
dl_count++;
|
||||
} else {
|
||||
GSequenceIter *seq_iter;
|
||||
|
||||
seq_iter =
|
||||
g_sequence_lookup (avelements, factory,
|
||||
(GCompareDataFunc) avelement_lookup_decoder, NULL);
|
||||
if (!seq_iter) {
|
||||
dec_list = g_list_prepend (dec_list, factory);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Go to first iter with that decoder */
|
||||
do {
|
||||
GSequenceIter *tmp_seq_iter;
|
||||
|
||||
tmp_seq_iter = g_sequence_iter_prev (seq_iter);
|
||||
if (!avelement_iter_is_equal (tmp_seq_iter, factory))
|
||||
break;
|
||||
seq_iter = tmp_seq_iter;
|
||||
} while (TRUE);
|
||||
|
||||
/* Get the best ranked GstAVElement for that factory */
|
||||
best_ave = NULL;
|
||||
while (!g_sequence_iter_is_end (seq_iter)
|
||||
&& avelement_iter_is_equal (seq_iter, factory)) {
|
||||
ave = g_sequence_get (seq_iter);
|
||||
|
||||
if (!best_ave || avelement_compare (ave, best_ave) < 0)
|
||||
best_ave = ave;
|
||||
|
||||
seq_iter = g_sequence_iter_next (seq_iter);
|
||||
}
|
||||
ave_list = g_list_prepend (ave_list, best_ave);
|
||||
}
|
||||
}
|
||||
|
||||
seq_iter = g_sequence_get_begin_iter (avelements);
|
||||
while (!g_sequence_iter_is_end (seq_iter)) {
|
||||
ave = (GstAVElement *) g_sequence_get (seq_iter);
|
||||
|
||||
if (g_list_find (factory_list, ave->dec)
|
||||
&& !g_list_find (dec_list, ave->dec)) {
|
||||
dec_list = g_list_prepend (dec_list, ave->dec);
|
||||
|
||||
/* to avoid unnecessary comparisons since the avelements list might be big */
|
||||
if (++dl_count == dl_length)
|
||||
break;
|
||||
}
|
||||
seq_iter = g_sequence_iter_next (seq_iter);
|
||||
/* Sort all GstAVElements by their relative ranks and insert
|
||||
* into the decoders list */
|
||||
ave_list = g_list_sort (ave_list, (GCompareFunc) avelement_compare);
|
||||
for (tmp = ave_list; tmp; tmp = tmp->next) {
|
||||
ave = (GstAVElement *) tmp->data;
|
||||
dec_list = g_list_prepend (dec_list, ave->dec);
|
||||
}
|
||||
g_list_free (ave_list);
|
||||
|
||||
dec_list = g_list_reverse (dec_list);
|
||||
|
||||
|
@ -3775,6 +3837,7 @@ autoplug_select_cb (GstElement * decodebin, GstPad * pad,
|
|||
const gchar *klass;
|
||||
GstPlaySinkType type;
|
||||
GstElement **sinkp;
|
||||
GList *ave_list = NULL, *l;
|
||||
GstAVElement *ave = NULL;
|
||||
GSequence *ave_seq = NULL;
|
||||
GSequenceIter *seq_iter;
|
||||
|
@ -3811,23 +3874,46 @@ autoplug_select_cb (GstElement * decodebin, GstPad * pad,
|
|||
sinkp = &group->video_sink;
|
||||
}
|
||||
|
||||
seq_iter =
|
||||
g_sequence_lookup (ave_seq, factory,
|
||||
(GCompareDataFunc) avelement_lookup_decoder, NULL);
|
||||
if (seq_iter) {
|
||||
/* Go to first iter with that decoder */
|
||||
do {
|
||||
GSequenceIter *tmp_seq_iter;
|
||||
|
||||
tmp_seq_iter = g_sequence_iter_prev (seq_iter);
|
||||
if (!avelement_iter_is_equal (tmp_seq_iter, factory))
|
||||
break;
|
||||
seq_iter = tmp_seq_iter;
|
||||
} while (TRUE);
|
||||
|
||||
while (!g_sequence_iter_is_end (seq_iter)
|
||||
&& avelement_iter_is_equal (seq_iter, factory)) {
|
||||
ave = g_sequence_get (seq_iter);
|
||||
ave_list = g_list_prepend (ave_list, ave);
|
||||
seq_iter = g_sequence_iter_next (seq_iter);
|
||||
}
|
||||
|
||||
/* Sort all GstAVElements by their relative ranks and insert
|
||||
* into the decoders list */
|
||||
ave_list = g_list_sort (ave_list, (GCompareFunc) avelement_compare);
|
||||
} else {
|
||||
ave_list = g_list_prepend (ave_list, NULL);
|
||||
}
|
||||
|
||||
/* if it is a decoder and we don't have a fixed sink, then find out
|
||||
* the matching audio/video sink from GstAVElements list */
|
||||
seq_iter = g_sequence_get_begin_iter (ave_seq);
|
||||
while (!g_sequence_iter_is_end (seq_iter)) {
|
||||
ave = (GstAVElement *) g_sequence_get (seq_iter);
|
||||
if (ave->dec != factory) {
|
||||
seq_iter = g_sequence_iter_next (seq_iter);
|
||||
continue;
|
||||
}
|
||||
for (l = ave_list; l; l = l->next) {
|
||||
ave = (GstAVElement *) l->data;
|
||||
|
||||
if (((isaudiodec && !group->audio_sink) ||
|
||||
(isvideodec && !group->video_sink))) {
|
||||
|
||||
GST_SOURCE_GROUP_LOCK (group);
|
||||
if (ave && ave->sink) {
|
||||
if ((*sinkp = gst_element_factory_create (ave->sink, NULL)) == NULL)
|
||||
GST_WARNING_OBJECT (playbin, "Could not create an element from %s",
|
||||
GST_WARNING_OBJECT (playbin,
|
||||
"Could not create an element from %s",
|
||||
gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (*sinkp)));
|
||||
gst_object_ref_sink (*sinkp);
|
||||
}
|
||||
|
@ -3886,6 +3972,8 @@ autoplug_select_cb (GstElement * decodebin, GstPad * pad,
|
|||
GST_DEBUG_OBJECT (playbin, "%s not compatible with the fixed sink",
|
||||
GST_OBJECT_NAME (factory));
|
||||
|
||||
/* If it is not compatible, either continue with the next possible
|
||||
* sink or if we have a fixed sink, skip the decoder */
|
||||
if ((isaudiodec && group->audio_sink != playbin->audio_sink) ||
|
||||
(isvideodec && group->video_sink != playbin->video_sink)) {
|
||||
GST_SOURCE_GROUP_LOCK (group);
|
||||
|
@ -3898,8 +3986,8 @@ autoplug_select_cb (GstElement * decodebin, GstPad * pad,
|
|||
return GST_AUTOPLUG_SELECT_SKIP;
|
||||
}
|
||||
}
|
||||
seq_iter = g_sequence_iter_next (seq_iter);
|
||||
}
|
||||
g_list_free (ave_list);
|
||||
g_mutex_unlock (&playbin->elements_lock);
|
||||
return GST_AUTOPLUG_SELECT_TRY;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue