一、autoplug_factories_cb
- /* Called when we must provide a list of factories to plug to @pad with @caps.
- * We first check if we have a sink that can handle the format and if we do, we
- * return NULL, to expose the pad. If we have no sink (or the sink does not
- * work), we return the list of elements that can connect. */
- static GValueArray *
- autoplug_factories_cb (GstElement * decodebin, GstPad * pad,
- GstCaps * caps, GstSourceGroup * group)
- {
- GstPlayBin *playbin;
- GList *factory_list, *tmp;
- GValueArray *result;
- gboolean unref_caps = FALSE;
- gboolean isaudiodeclist = FALSE;
- gboolean isvideodeclist = FALSE;
- if (!caps) {
- caps = gst_caps_new_any ();
- unref_caps = TRUE;
- }
- playbin = group->playbin;
- GST_DEBUG_OBJECT (playbin, "factories group %p for %s:%s, %" GST_PTR_FORMAT,
- group, GST_DEBUG_PAD_NAME (pad), caps);
- /* filter out the elements based on the caps. */
- g_mutex_lock (&playbin->elements_lock);
- gst_play_bin_update_elements_list (playbin);
- //caps匹配的factory_list
- factory_list =
- gst_element_factory_list_filter (playbin->elements, caps, GST_PAD_SINK,
- gst_caps_is_fixed (caps));
- g_mutex_unlock (&playbin->elements_lock);
- GST_DEBUG_OBJECT (playbin, "found factories %p", factory_list);
- GST_PLUGIN_FEATURE_LIST_DEBUG (factory_list);
- /* check whether the caps are asking for a list of audio/video decoders */
- tmp = factory_list;
- if (!gst_caps_is_any (caps)) {
- for (; tmp; tmp = tmp->next) {
- GstElementFactory *factory = (GstElementFactory *) tmp->data;
- isvideodeclist = gst_element_factory_list_is_type (factory,
- GST_ELEMENT_FACTORY_TYPE_DECODER |
- GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO |
- GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE);
- isaudiodeclist = gst_element_factory_list_is_type (factory,
- GST_ELEMENT_FACTORY_TYPE_DECODER |
- GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO);
- if (isaudiodeclist || isvideodeclist)
- break;
- }
- }
- if (isaudiodeclist || isvideodeclist) {
- GSequence **ave_list;
- GstPlayFlags flags;
- if (isaudiodeclist)
- ave_list = &playbin->aelements;
- else
- ave_list = &playbin->velements;
- flags = gst_play_bin_get_flags (playbin);
- g_mutex_lock (&playbin->elements_lock);
- /* sort factory_list based on the GstAVElement list priority */
- factory_list = create_decoders_list (factory_list, *ave_list, flags);
- g_mutex_unlock (&playbin->elements_lock);
- }
- /* 2 additional elements for the already set audio/video sinks */
- result = g_value_array_new (g_list_length (factory_list) + 2);
- /* Check if we already have an audio/video sink and if this is the case
- * put it as the first element of the array */
- if (group->audio_sink) {
- GstElementFactory *factory = gst_element_get_factory (group->audio_sink);
- if (factory && _factory_can_sink_caps (factory, caps)) {
- GValue val = { 0, };
- g_value_init (&val, G_TYPE_OBJECT);
- g_value_set_object (&val, factory);
- result = g_value_array_append (result, &val);
- g_value_unset (&val);
- }
- }
- if (group->video_sink) {
- GstElementFactory *factory = gst_element_get_factory (group->video_sink);
- if (factory && _factory_can_sink_caps (factory, caps)) {
- GValue val = { 0, };
- g_value_init (&val, G_TYPE_OBJECT);
- g_value_set_object (&val, factory);
- result = g_value_array_append (result, &val);
- g_value_unset (&val);
- }
- }
- for (tmp = factory_list; tmp; tmp = tmp->next) {
- GstElementFactory *factory = GST_ELEMENT_FACTORY_CAST (tmp->data);
- GValue val = { 0, };
- if (group->audio_sink && gst_element_factory_list_is_type (factory,
- GST_ELEMENT_FACTORY_TYPE_SINK |
- GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO)) {
- continue;
- }
- if (group->video_sink && gst_element_factory_list_is_type (factory,
- GST_ELEMENT_FACTORY_TYPE_SINK | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO
- | GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE)) {
- continue;
- }
- g_value_init (&val, G_TYPE_OBJECT);
- g_value_set_object (&val, factory);
- g_value_array_append (result, &val);
- g_value_unset (&val);
- }
- gst_plugin_feature_list_free (factory_list);
- if (unref_caps)
- gst_caps_unref (caps);
- return result;
- }
复制代码 1.gst_play_bin_update_elements_list函数,创建可用的factories列表playbin->elements( GList *elements; /* factories we can use for selecting elements */)
- /* Must be called with elements lock! */
- static void
- gst_play_bin_update_elements_list (GstPlayBin * playbin)
- {
- GList *res, *tmp;
- guint cookie;
- cookie = gst_registry_get_feature_list_cookie (gst_registry_get ());
- if (!playbin->elements || playbin->elements_cookie != cookie) {
- if (playbin->elements)
- gst_plugin_feature_list_free (playbin->elements);
- res =
- gst_element_factory_list_get_elements
- (GST_ELEMENT_FACTORY_TYPE_DECODABLE, GST_RANK_MARGINAL);
- tmp =
- gst_element_factory_list_get_elements
- (GST_ELEMENT_FACTORY_TYPE_AUDIOVIDEO_SINKS, GST_RANK_MARGINAL);
- playbin->elements = g_list_concat (res, tmp);
- playbin->elements = g_list_sort (playbin->elements, compare_factories_func);
- }
- if (!playbin->aelements || playbin->elements_cookie != cookie) {
- if (playbin->aelements)
- g_sequence_free (playbin->aelements);
- playbin->aelements = avelements_create (playbin, TRUE);
- }
- if (!playbin->velements || playbin->elements_cookie != cookie) {
- if (playbin->velements)
- g_sequence_free (playbin->velements);
- playbin->velements = avelements_create (playbin, FALSE);
- }
- playbin->elements_cookie = cookie;
- }
复制代码 也就是同过gst_element_factory_list_get_elements从registry中获取type是GST_ELEMENT_FACTORY_TYPE_DECODABLE,GST_ELEMENT_FACTORY_TYPE_AUDIOVIDEO_SINKS,优先级高于GST_RANK_MARGINAL的factory。
- #define GST_ELEMENT_FACTORY_TYPE_DECODABLE \
- ((GstElementFactoryListType)(GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_DEMUXER | GST_ELEMENT_FACTORY_TYPE_DEPAYLOADER | GST_ELEMENT_FACTORY_TYPE_PARSER | GST_ELEMENT_FACTORY_TYPE_DECRYPTOR))
- #define GST_ELEMENT_FACTORY_TYPE_AUDIOVIDEO_SINKS ((GstElementFactoryListType)(GST_ELEMENT_FACTORY_TYPE_SINK | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO | GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE))
复制代码 尚有(GSequence *)playbin->aelements和playbin->velements用来保存audioelement和videoelement。
(1)先看下gst_element_factory_list_get_elements
- GList *
- gst_element_factory_list_get_elements (GstElementFactoryListType type,
- GstRank minrank)
- {
- GList *result;
- FilterData data;
- /* prepare type */
- data.type = type;
- data.minrank = minrank;
- /* get the feature list using the filter */
- result = gst_registry_feature_filter (gst_registry_get (),
- (GstPluginFeatureFilter) element_filter, FALSE, &data);
- /* sort on rank and name */
- result = g_list_sort (result, gst_plugin_feature_rank_compare_func);
- return result;
- }
- //根据rank和type选择
- static gboolean
- element_filter (GstPluginFeature * feature, FilterData * data)
- {
- gboolean res;
- /* we only care about element factories */
- if (G_UNLIKELY (!GST_IS_ELEMENT_FACTORY (feature)))
- return FALSE;
- res = (gst_plugin_feature_get_rank (feature) >= data->minrank) &&
- gst_element_factory_list_is_type (GST_ELEMENT_FACTORY_CAST (feature),
- data->type);
- return res;
- }
- //factory_type的判断逻辑
- gboolean
- gst_element_factory_list_is_type (GstElementFactory * factory,
- GstElementFactoryListType type)
- {
- gboolean res = FALSE;
- const gchar *klass;
- klass =
- gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_KLASS);
- if (klass == NULL) {
- GST_ERROR_OBJECT (factory, "element factory is missing klass identifiers");
- return res;
- }
- /* Filter by element type first, as soon as it matches
- * one type, we skip all other tests */
- if (!res && (type & GST_ELEMENT_FACTORY_TYPE_SINK))
- res = (strstr (klass, "Sink") != NULL);
- if (!res && (type & GST_ELEMENT_FACTORY_TYPE_SRC))
- res = (strstr (klass, "Source") != NULL);
- if (!res && (type & GST_ELEMENT_FACTORY_TYPE_DECODER))
- res = (strstr (klass, "Decoder") != NULL);
- if (!res && (type & GST_ELEMENT_FACTORY_TYPE_ENCODER))
- res = (strstr (klass, "Encoder") != NULL);
- if (!res && (type & GST_ELEMENT_FACTORY_TYPE_MUXER))
- res = (strstr (klass, "Muxer") != NULL);
- if (!res && (type & GST_ELEMENT_FACTORY_TYPE_DEMUXER))
- res = (strstr (klass, "Demux") != NULL);
- /* FIXME : We're actually parsing two Classes here... */
- if (!res && (type & GST_ELEMENT_FACTORY_TYPE_PARSER))
- res = ((strstr (klass, "Parser") != NULL)
- && (strstr (klass, "Codec") != NULL));
- if (!res && (type & GST_ELEMENT_FACTORY_TYPE_DEPAYLOADER))
- res = (strstr (klass, "Depayloader") != NULL);
- if (!res && (type & GST_ELEMENT_FACTORY_TYPE_PAYLOADER))
- res = (strstr (klass, "Payloader") != NULL);
- if (!res && (type & GST_ELEMENT_FACTORY_TYPE_FORMATTER))
- res = (strstr (klass, "Formatter") != NULL);
- if (!res && (type & GST_ELEMENT_FACTORY_TYPE_DECRYPTOR))
- res = (strstr (klass, "Decryptor") != NULL);
- if (!res && (type & GST_ELEMENT_FACTORY_TYPE_ENCRYPTOR))
- res = (strstr (klass, "Encryptor") != NULL);
- if (!res && (type & GST_ELEMENT_FACTORY_TYPE_HARDWARE))
- res = (strstr (klass, "Hardware") != NULL);
- /* Filter by media type now, we only test if it
- * matched any of the types above or only checking the media
- * type was requested. */
- if ((res || !(type & (GST_ELEMENT_FACTORY_TYPE_MAX_ELEMENTS - 1)))
- && (type & (GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO |
- GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO |
- GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE |
- GST_ELEMENT_FACTORY_TYPE_MEDIA_SUBTITLE |
- GST_ELEMENT_FACTORY_TYPE_MEDIA_METADATA)))
- res = ((type & GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO)
- && (strstr (klass, "Audio") != NULL))
- || ((type & GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO)
- && (strstr (klass, "Video") != NULL))
- || ((type & GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE)
- && (strstr (klass, "Image") != NULL)) ||
- ((type & GST_ELEMENT_FACTORY_TYPE_MEDIA_SUBTITLE)
- && (strstr (klass, "Subtitle") != NULL)) ||
- ((type & GST_ELEMENT_FACTORY_TYPE_MEDIA_METADATA)
- && (strstr (klass, "Metadata") != NULL));
- return res;
- }
- //根据rank排序
- gint
- gst_plugin_feature_rank_compare_func (gconstpointer p1, gconstpointer p2)
- {
- GstPluginFeature *f1, *f2;
- gint diff;
- f1 = (GstPluginFeature *) p1;
- f2 = (GstPluginFeature *) p2;
- diff = f2->rank - f1->rank;
- if (diff != 0)
- return diff;
- diff = strcmp (GST_OBJECT_NAME (f1), GST_OBJECT_NAME (f2));
- return diff;
- }
复制代码 (2)avelements_create,创建一个保存GstAudioVideoElement的GSequence
/* The GstAudioVideoElement structure holding the audio/video decoder
* and the audio/video sink factories together with field indicating
* the number of common caps features */
- static GSequence *
- avelements_create (GstPlayBin * playbin, gboolean isaudioelement)
- {
- GstElementFactory *d_factory, *s_factory;
- GList *dec_list, *sink_list, *dl, *sl;
- GSequence *ave_seq = NULL;
- GstAVElement *ave;
- guint n_common_cf = 0;
- //选择符合要求的音视频添加到对应的sink_list和dec_list
- if (isaudioelement) {
- sink_list = gst_element_factory_list_get_elements
- (GST_ELEMENT_FACTORY_TYPE_SINK |
- GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO, GST_RANK_MARGINAL);
- dec_list =
- gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_DECODER
- | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO, GST_RANK_MARGINAL);
- } else {
- sink_list = gst_element_factory_list_get_elements
- (GST_ELEMENT_FACTORY_TYPE_SINK |
- GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO |
- GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE, GST_RANK_MARGINAL);
- dec_list =
- gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_DECODER
- | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO |
- GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE, GST_RANK_MARGINAL);
- }
- /* create a list of audio/video elements. Each element in the list
- * is holding an audio/video decoder and an audio/video sink in which
- * the decoders srcpad template caps and sink element's sinkpad template
- * caps are compatible */
- dl = dec_list;
- sl = sink_list;
-
- ave_seq = g_sequence_new ((GDestroyNotify) avelements_free);
- //查找可以匹配的dec和sink,组合形式的ave,并保存到ave_seq,函数最后会返回
- /****
- * typedef struct
- *{
- * GstElementFactory *dec; /* audio:video decoder */
- * GstElementFactory *sink; /* audio:video sink */
- * guint n_comm_cf; /* number of common caps features */
- *} GstAVElement;
- *****/
-
- for (; dl; dl = dl->next) {
- d_factory = (GstElementFactory *) dl->data;
- for (; sl; sl = sl->next) {
- s_factory = (GstElementFactory *) sl->data;
- n_common_cf =
- gst_playback_utils_get_n_common_capsfeatures (d_factory, s_factory,
- gst_play_bin_get_flags (playbin), isaudioelement);
- if (n_common_cf < 1)
- continue;
- ave = g_slice_new (GstAVElement);
- ave->dec = gst_object_ref (d_factory);
- ave->sink = gst_object_ref (s_factory);
- ave->n_comm_cf = n_common_cf;
- g_sequence_append (ave_seq, ave);
- }
- sl = sink_list;
- }
- g_sequence_sort (ave_seq, (GCompareDataFunc) avelement_compare_decoder, NULL);
- gst_plugin_feature_list_free (dec_list);
- gst_plugin_feature_list_free (sink_list);
- return ave_seq;
- }
复制代码 主要看下gst_playback_utils_get_n_common_capsfeatures怎样计算common caps features
- for (i = 0; i < fact1_caps_size; i++) {
- fact1_features =
- gst_caps_get_features ((const GstCaps *) fact1_tmpl_caps, i);
- if (gst_caps_features_is_any (fact1_features))
- continue;
- fact1_struct =
- gst_caps_get_structure ((const GstCaps *) fact1_tmpl_caps, i);
- for (j = 0; j < fact2_caps_size; j++) {
- fact2_features =
- gst_caps_get_features ((const GstCaps *) fact2_tmpl_caps, j);
- if (gst_caps_features_is_any (fact2_features))
- continue;
- fact2_struct =
- gst_caps_get_structure ((const GstCaps *) fact2_tmpl_caps, j);
- /* A common caps feature is given if the caps features are equal
- * and the structures can intersect. If the NATIVE_AUDIO/NATIVE_VIDEO
- * flags are not set we also allow if both structures are raw caps with
- * system memory caps features, because in that case we have converters in
- * place.
- */
- if (gst_caps_features_is_equal (fact1_features, fact2_features) &&
- (gst_structure_can_intersect (fact1_struct, fact2_struct) ||
- (!native_raw
- && gst_caps_features_is_equal (fact1_features,
- GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY)
- && gst_structure_can_intersect (raw_struct, fact1_struct)
- && gst_structure_can_intersect (raw_struct, fact2_struct)))
- && !is_included (cf_list, fact2_features)) {
- cf_list = g_list_prepend (cf_list, fact2_features);
- n_common_cf++;
- }
- }
- }
复制代码 2 .获取factory_list :查找包含sink_pad类型是caps匹配的elements
factory_list =
gst_element_factory_list_filter (playbin->elements, caps, GST_PAD_SINK,
gst_caps_is_fixed (caps));
- GList *
- gst_element_factory_list_filter (GList * list,
- const GstCaps * caps, GstPadDirection direction, gboolean subsetonly)
- {
- GQueue results = G_QUEUE_INIT;
- GST_DEBUG ("finding factories");
- /* loop over all the factories */
- for (; list; list = list->next) {
- GstElementFactory *factory;
- const GList *templates;
- GList *walk;
- factory = (GstElementFactory *) list->data;
- GST_DEBUG ("Trying %s",
- gst_plugin_feature_get_name ((GstPluginFeature *) factory));
- /* get the templates from the element factory */
- templates = gst_element_factory_get_static_pad_templates (factory);
- for (walk = (GList *) templates; walk; walk = g_list_next (walk)) {
- GstStaticPadTemplate *templ = walk->data;
- /* we only care about the sink templates */
- if (templ->direction == direction) {
- GstCaps *tmpl_caps;
- /* try to intersect the caps with the caps of the template */
- tmpl_caps = gst_static_caps_get (&templ->static_caps);
- /* FIXME, intersect is not the right method, we ideally want to check
- * for a subset here */
- /* check if the intersection is empty */
- if ((subsetonly && gst_caps_is_subset (caps, tmpl_caps)) ||
- (!subsetonly && gst_caps_can_intersect (caps, tmpl_caps))) {
- /* non empty intersection, we can use this element */
- g_queue_push_tail (&results, gst_object_ref (factory));
- gst_caps_unref (tmpl_caps);
- break;
- }
- gst_caps_unref (tmpl_caps);
- }
- }
- }
- return results.head;
- }
复制代码 3.然后继续后续处理,判定找到factory_list中第一个audio/video decoder的位置
- /* check whether the caps are asking for a list of audio/video decoders */
- tmp = factory_list;
- if (!gst_caps_is_any (caps)) {
- for (; tmp; tmp = tmp->next) {
- GstElementFactory *factory = (GstElementFactory *) tmp->data;
- isvideodeclist = gst_element_factory_list_is_type (factory,
- GST_ELEMENT_FACTORY_TYPE_DECODER |
- GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO |
- GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE);
- isaudiodeclist = gst_element_factory_list_is_type (factory,
- GST_ELEMENT_FACTORY_TYPE_DECODER |
- GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO);
- if (isaudiodeclist || isvideodeclist)
- break;
- }
- }
- if (isaudiodeclist || isvideodeclist) {
- GSequence **ave_list;
- GstPlayFlags flags;
-
- if (isaudiodeclist)
- ave_list = &playbin->aelements;
- else
- ave_list = &playbin->velements;
- flags = gst_play_bin_get_flags (playbin);
- //创建decoder_list
- g_mutex_lock (&playbin->elements_lock);
- /* sort factory_list based on the GstAVElement list priority */
- factory_list = create_decoders_list (factory_list, *ave_list, flags);
- g_mutex_unlock (&playbin->elements_lock);
- }
复制代码- static GList *
- create_decoders_list (GList * factory_list, GSequence * avelements,
- GstPlayFlags flags)
- {
- GList *dec_list = NULL, *tmp;
- GList *ave_list = NULL;
- GList *ave_free_list = NULL;
- GstAVElement *ave, *best_ave;
- g_return_val_if_fail (factory_list != NULL, NULL);
- g_return_val_if_fail (avelements != NULL, NULL);
- for (tmp = factory_list; tmp; tmp = tmp->next) {
- GstElementFactory *factory = (GstElementFactory *) tmp->data;
- /* if there are parsers or sink elements, add them first */ //parsers or sink elements直接dec_list,如果不是走下面流程添加到ave_list
- if (gst_element_factory_list_is_type (factory,
- GST_ELEMENT_FACTORY_TYPE_PARSER) ||
- gst_element_factory_list_is_type (factory,
- GST_ELEMENT_FACTORY_TYPE_SINK)) {
- dec_list = g_list_prepend (dec_list, gst_object_ref (factory));
- } else if (!(((flags & GST_PLAY_FLAG_FORCE_SW_DECODERS) != 0) //如果没有同时满足以下两个条件则为TRUE:强制软件解码且factory 是硬件解码器类型
- && gst_element_factory_list_is_type (factory,
- GST_ELEMENT_FACTORY_TYPE_HARDWARE))) {
- GSequenceIter *seq_iter;
- seq_iter =
- g_sequence_lookup (avelementszh, factory,
- (GCompareDataFunc) avelement_lookup_decoder, NULL);//avelements中查找,匹配条件avelement_lookup_decoder
- if (!seq_iter) {
- GstAVElement *ave = g_slice_new0 (GstAVElement);
- ave->dec = factory;
- ave->sink = NULL;
- /* There's at least raw */
- ave->n_comm_cf = 1;
- ave_list = g_list_prepend (ave_list, ave);
- /* We need to free these later */
- ave_free_list = g_list_prepend (ave_free_list, ave);
- 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 (!g_sequence_iter_is_begin (seq_iter));
- /* 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) //最佳匹配,匹配条件avelement_compare
- best_ave = ave;
- seq_iter = g_sequence_iter_next (seq_iter);
- }
- ave_list = g_list_prepend (ave_list, best_ave);
- }
- }
- /* 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, gst_object_ref (ave->dec));//prepend是添加到list的头部,所以需要后面的翻转
- }
- g_list_free (ave_list);
- gst_plugin_feature_list_free (factory_list);
- for (tmp = ave_free_list; tmp; tmp = tmp->next)
- g_slice_free (GstAVElement, tmp->data);
- g_list_free (ave_free_list);
- //所以parse和sink都被添加到了前面,其他的根据rank等排序
- dec_list = g_list_reverse (dec_list);
- return dec_list;
- }
- static gint
- avelement_compare (gconstpointer p1, gconstpointer p2)
- {
- GstAVElement *v1, *v2;
- GstPluginFeature *fd1, *fd2, *fs1, *fs2;
- gint64 diff, v1_rank, v2_rank;
- v1 = (GstAVElement *) p1;
- v2 = (GstAVElement *) p2;
- fd1 = (GstPluginFeature *) v1->dec;
- fd2 = (GstPluginFeature *) v2->dec;
- //优先比较sink的rank,没有在比较dec的rank
- /* If both have a sink, we also compare their ranks */
- if (v1->sink && v2->sink) {
- fs1 = (GstPluginFeature *) v1->sink;
- fs2 = (GstPluginFeature *) v2->sink;
- v1_rank = (gint64) gst_plugin_feature_get_rank (fd1) *
- gst_plugin_feature_get_rank (fs1);
- v2_rank = (gint64) gst_plugin_feature_get_rank (fd2) *
- gst_plugin_feature_get_rank (fs2);
- } else {
- v1_rank = gst_plugin_feature_get_rank (fd1);
- v2_rank = gst_plugin_feature_get_rank (fd2);
- fs1 = fs2 = NULL;
- }
- /* comparison based on the rank */
- diff = v2_rank - v1_rank;
- if (diff < 0)
- return -1;
- else if (diff > 0)
- return 1;
- //比较number of common caps feature,多的优先
- /* comparison based on number of common caps features */
- diff = v2->n_comm_cf - v1->n_comm_cf;
- if (diff != 0)
- return diff;
- if (fs1 && fs2) {
- /* comparison based on the name of sink elements */
- diff = strcmp (GST_OBJECT_NAME (fs1), GST_OBJECT_NAME (fs2));
- if (diff != 0)
- return diff;
- }
- /* comparison based on the name of decoder elements */
- return strcmp (GST_OBJECT_NAME (fd1), GST_OBJECT_NAME (fd2));
- }
复制代码 这里留意下list中的排序吧:parse和sink最前,其他会按照优先级(rank)、共有 caps 特性数量、吸收器名称息争码器名称的顺序分列 。
后续如果应有sink则将sink插入到list中,基本也就完成了autoplug_factories_cb流程了。
二、autoplug_select_cb
- GstPlayBin *playbin;
- GstElement *element;
- const gchar *klass;
- GstPlaySinkType type;
- GstElement **sinkp;
- GList *ave_list = NULL, *l;
- GstAVElement *ave = NULL;
- GSequence *ave_seq = NULL;
- GSequenceIter *seq_iter;
- gboolean created_sink = FALSE;
- {省略}
- if (isaudiodec) {
- ave_seq = playbin->aelements;
- sinkp = &group->audio_sink;
- } else {
- ave_seq = playbin->velements;
- 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 (!g_sequence_iter_is_begin (seq_iter));
- 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);
- }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |