mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-20 07:16:55 +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
|
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;
|
GstAVElement *v1, *v2;
|
||||||
GstPluginFeature *fd1, *fd2, *fs1, *fs2;
|
GstPluginFeature *fd1, *fd2, *fs1, *fs2;
|
||||||
|
@ -3452,7 +3477,7 @@ avelements_create (GstPlayBin * playbin, gboolean isaudioelement)
|
||||||
}
|
}
|
||||||
sl = sink_list;
|
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 (dec_list);
|
||||||
gst_plugin_feature_list_free (sink_list);
|
gst_plugin_feature_list_free (sink_list);
|
||||||
|
@ -3460,45 +3485,82 @@ avelements_create (GstPlayBin * playbin, gboolean isaudioelement)
|
||||||
return ave_seq;
|
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 *
|
static GList *
|
||||||
create_decoders_list (GList * factory_list, GSequence * avelements)
|
create_decoders_list (GList * factory_list, GSequence * avelements)
|
||||||
{
|
{
|
||||||
GList *dec_list = NULL, *tmp;
|
GList *dec_list = NULL, *tmp;
|
||||||
GSequenceIter *seq_iter = NULL;
|
GList *ave_list = NULL;
|
||||||
GstElementFactory *factory;
|
GstAVElement *ave, *best_ave;
|
||||||
GstAVElement *ave;
|
|
||||||
guint dl_length, dl_count = 0;
|
|
||||||
|
|
||||||
g_return_val_if_fail (factory_list != NULL, NULL);
|
g_return_val_if_fail (factory_list != NULL, NULL);
|
||||||
g_return_val_if_fail (avelements != NULL, NULL);
|
g_return_val_if_fail (avelements != NULL, NULL);
|
||||||
|
|
||||||
dl_length = g_list_length (factory_list);
|
for (tmp = factory_list; tmp; tmp = tmp->next) {
|
||||||
tmp = factory_list;
|
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 there are parsers or sink elements, add them first */
|
||||||
if (!gst_element_factory_list_is_type (factory,
|
if (!gst_element_factory_list_is_type (factory,
|
||||||
GST_ELEMENT_FACTORY_TYPE_DECODER)) {
|
GST_ELEMENT_FACTORY_TYPE_DECODER)) {
|
||||||
dec_list = g_list_prepend (dec_list, factory);
|
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);
|
/* Sort all GstAVElements by their relative ranks and insert
|
||||||
while (!g_sequence_iter_is_end (seq_iter)) {
|
* into the decoders list */
|
||||||
ave = (GstAVElement *) g_sequence_get (seq_iter);
|
ave_list = g_list_sort (ave_list, (GCompareFunc) avelement_compare);
|
||||||
|
for (tmp = ave_list; tmp; tmp = tmp->next) {
|
||||||
if (g_list_find (factory_list, ave->dec)
|
ave = (GstAVElement *) tmp->data;
|
||||||
&& !g_list_find (dec_list, ave->dec)) {
|
dec_list = g_list_prepend (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);
|
|
||||||
}
|
}
|
||||||
|
g_list_free (ave_list);
|
||||||
|
|
||||||
dec_list = g_list_reverse (dec_list);
|
dec_list = g_list_reverse (dec_list);
|
||||||
|
|
||||||
|
@ -3775,6 +3837,7 @@ autoplug_select_cb (GstElement * decodebin, GstPad * pad,
|
||||||
const gchar *klass;
|
const gchar *klass;
|
||||||
GstPlaySinkType type;
|
GstPlaySinkType type;
|
||||||
GstElement **sinkp;
|
GstElement **sinkp;
|
||||||
|
GList *ave_list = NULL, *l;
|
||||||
GstAVElement *ave = NULL;
|
GstAVElement *ave = NULL;
|
||||||
GSequence *ave_seq = NULL;
|
GSequence *ave_seq = NULL;
|
||||||
GSequenceIter *seq_iter;
|
GSequenceIter *seq_iter;
|
||||||
|
@ -3811,23 +3874,46 @@ autoplug_select_cb (GstElement * decodebin, GstPad * pad,
|
||||||
sinkp = &group->video_sink;
|
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
|
/* if it is a decoder and we don't have a fixed sink, then find out
|
||||||
* the matching audio/video sink from GstAVElements list */
|
* the matching audio/video sink from GstAVElements list */
|
||||||
seq_iter = g_sequence_get_begin_iter (ave_seq);
|
for (l = ave_list; l; l = l->next) {
|
||||||
while (!g_sequence_iter_is_end (seq_iter)) {
|
ave = (GstAVElement *) l->data;
|
||||||
ave = (GstAVElement *) g_sequence_get (seq_iter);
|
|
||||||
if (ave->dec != factory) {
|
|
||||||
seq_iter = g_sequence_iter_next (seq_iter);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (((isaudiodec && !group->audio_sink) ||
|
if (((isaudiodec && !group->audio_sink) ||
|
||||||
(isvideodec && !group->video_sink))) {
|
(isvideodec && !group->video_sink))) {
|
||||||
|
|
||||||
GST_SOURCE_GROUP_LOCK (group);
|
GST_SOURCE_GROUP_LOCK (group);
|
||||||
if (ave && ave->sink) {
|
if (ave && ave->sink) {
|
||||||
if ((*sinkp = gst_element_factory_create (ave->sink, NULL)) == NULL)
|
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_plugin_feature_get_name (GST_PLUGIN_FEATURE (*sinkp)));
|
||||||
gst_object_ref_sink (*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_DEBUG_OBJECT (playbin, "%s not compatible with the fixed sink",
|
||||||
GST_OBJECT_NAME (factory));
|
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) ||
|
if ((isaudiodec && group->audio_sink != playbin->audio_sink) ||
|
||||||
(isvideodec && group->video_sink != playbin->video_sink)) {
|
(isvideodec && group->video_sink != playbin->video_sink)) {
|
||||||
GST_SOURCE_GROUP_LOCK (group);
|
GST_SOURCE_GROUP_LOCK (group);
|
||||||
|
@ -3898,8 +3986,8 @@ autoplug_select_cb (GstElement * decodebin, GstPad * pad,
|
||||||
return GST_AUTOPLUG_SELECT_SKIP;
|
return GST_AUTOPLUG_SELECT_SKIP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
seq_iter = g_sequence_iter_next (seq_iter);
|
|
||||||
}
|
}
|
||||||
|
g_list_free (ave_list);
|
||||||
g_mutex_unlock (&playbin->elements_lock);
|
g_mutex_unlock (&playbin->elements_lock);
|
||||||
return GST_AUTOPLUG_SELECT_TRY;
|
return GST_AUTOPLUG_SELECT_TRY;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue