playbin之autoplug_factories源码分析

打印 上一主题 下一主题

主题 883|帖子 883|积分 2649

 一、autoplug_factories_cb 
  1. /* Called when we must provide a list of factories to plug to @pad with @caps.
  2. * We first check if we have a sink that can handle the format and if we do, we
  3. * return NULL, to expose the pad. If we have no sink (or the sink does not
  4. * work), we return the list of elements that can connect. */
  5. static GValueArray *
  6. autoplug_factories_cb (GstElement * decodebin, GstPad * pad,
  7.     GstCaps * caps, GstSourceGroup * group)
  8. {
  9.   GstPlayBin *playbin;
  10.   GList *factory_list, *tmp;
  11.   GValueArray *result;
  12.   gboolean unref_caps = FALSE;
  13.   gboolean isaudiodeclist = FALSE;
  14.   gboolean isvideodeclist = FALSE;
  15.   if (!caps) {
  16.     caps = gst_caps_new_any ();
  17.     unref_caps = TRUE;
  18.   }
  19.   playbin = group->playbin;
  20.   GST_DEBUG_OBJECT (playbin, "factories group %p for %s:%s, %" GST_PTR_FORMAT,
  21.       group, GST_DEBUG_PAD_NAME (pad), caps);
  22.   /* filter out the elements based on the caps. */
  23.   g_mutex_lock (&playbin->elements_lock);
  24.   gst_play_bin_update_elements_list (playbin);
  25.   //caps匹配的factory_list
  26.   factory_list =
  27.       gst_element_factory_list_filter (playbin->elements, caps, GST_PAD_SINK,
  28.       gst_caps_is_fixed (caps));
  29.   g_mutex_unlock (&playbin->elements_lock);
  30.   GST_DEBUG_OBJECT (playbin, "found factories %p", factory_list);
  31.   GST_PLUGIN_FEATURE_LIST_DEBUG (factory_list);
  32.   /* check whether the caps are asking for a list of audio/video decoders */
  33.   tmp = factory_list;
  34.   if (!gst_caps_is_any (caps)) {
  35.     for (; tmp; tmp = tmp->next) {
  36.       GstElementFactory *factory = (GstElementFactory *) tmp->data;
  37.       isvideodeclist = gst_element_factory_list_is_type (factory,
  38.           GST_ELEMENT_FACTORY_TYPE_DECODER |
  39.           GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO |
  40.           GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE);
  41.       isaudiodeclist = gst_element_factory_list_is_type (factory,
  42.           GST_ELEMENT_FACTORY_TYPE_DECODER |
  43.           GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO);
  44.       if (isaudiodeclist || isvideodeclist)
  45.         break;
  46.     }
  47.   }
  48.   if (isaudiodeclist || isvideodeclist) {
  49.     GSequence **ave_list;
  50.     GstPlayFlags flags;
  51.     if (isaudiodeclist)
  52.       ave_list = &playbin->aelements;
  53.     else
  54.       ave_list = &playbin->velements;
  55.     flags = gst_play_bin_get_flags (playbin);
  56.     g_mutex_lock (&playbin->elements_lock);
  57.     /* sort factory_list based on the GstAVElement list priority */
  58.     factory_list = create_decoders_list (factory_list, *ave_list, flags);
  59.     g_mutex_unlock (&playbin->elements_lock);
  60.   }
  61.   /* 2 additional elements for the already set audio/video sinks */
  62.   result = g_value_array_new (g_list_length (factory_list) + 2);
  63.   /* Check if we already have an audio/video sink and if this is the case
  64.    * put it as the first element of the array */
  65.   if (group->audio_sink) {
  66.     GstElementFactory *factory = gst_element_get_factory (group->audio_sink);
  67.     if (factory && _factory_can_sink_caps (factory, caps)) {
  68.       GValue val = { 0, };
  69.       g_value_init (&val, G_TYPE_OBJECT);
  70.       g_value_set_object (&val, factory);
  71.       result = g_value_array_append (result, &val);
  72.       g_value_unset (&val);
  73.     }
  74.   }
  75.   if (group->video_sink) {
  76.     GstElementFactory *factory = gst_element_get_factory (group->video_sink);
  77.     if (factory && _factory_can_sink_caps (factory, caps)) {
  78.       GValue val = { 0, };
  79.       g_value_init (&val, G_TYPE_OBJECT);
  80.       g_value_set_object (&val, factory);
  81.       result = g_value_array_append (result, &val);
  82.       g_value_unset (&val);
  83.     }
  84.   }
  85.   for (tmp = factory_list; tmp; tmp = tmp->next) {
  86.     GstElementFactory *factory = GST_ELEMENT_FACTORY_CAST (tmp->data);
  87.     GValue val = { 0, };
  88.     if (group->audio_sink && gst_element_factory_list_is_type (factory,
  89.             GST_ELEMENT_FACTORY_TYPE_SINK |
  90.             GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO)) {
  91.       continue;
  92.     }
  93.     if (group->video_sink && gst_element_factory_list_is_type (factory,
  94.             GST_ELEMENT_FACTORY_TYPE_SINK | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO
  95.             | GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE)) {
  96.       continue;
  97.     }
  98.     g_value_init (&val, G_TYPE_OBJECT);
  99.     g_value_set_object (&val, factory);
  100.     g_value_array_append (result, &val);
  101.     g_value_unset (&val);
  102.   }
  103.   gst_plugin_feature_list_free (factory_list);
  104.   if (unref_caps)
  105.     gst_caps_unref (caps);
  106.   return result;
  107. }
复制代码
1.gst_play_bin_update_elements_list函数,创建可用的factories列表playbin->elements( GList *elements;    /* factories we can use for selecting elements */)
  1. /* Must be called with elements lock! */
  2. static void
  3. gst_play_bin_update_elements_list (GstPlayBin * playbin)
  4. {
  5.   GList *res, *tmp;
  6.   guint cookie;
  7.   cookie = gst_registry_get_feature_list_cookie (gst_registry_get ());
  8.   if (!playbin->elements || playbin->elements_cookie != cookie) {
  9.     if (playbin->elements)
  10.       gst_plugin_feature_list_free (playbin->elements);
  11.     res =
  12.         gst_element_factory_list_get_elements
  13.         (GST_ELEMENT_FACTORY_TYPE_DECODABLE, GST_RANK_MARGINAL);
  14.     tmp =
  15.         gst_element_factory_list_get_elements
  16.         (GST_ELEMENT_FACTORY_TYPE_AUDIOVIDEO_SINKS, GST_RANK_MARGINAL);
  17.     playbin->elements = g_list_concat (res, tmp);
  18.     playbin->elements = g_list_sort (playbin->elements, compare_factories_func);
  19.   }
  20.   if (!playbin->aelements || playbin->elements_cookie != cookie) {
  21.     if (playbin->aelements)
  22.       g_sequence_free (playbin->aelements);
  23.     playbin->aelements = avelements_create (playbin, TRUE);
  24.   }
  25.   if (!playbin->velements || playbin->elements_cookie != cookie) {
  26.     if (playbin->velements)
  27.       g_sequence_free (playbin->velements);
  28.     playbin->velements = avelements_create (playbin, FALSE);
  29.   }
  30.   playbin->elements_cookie = cookie;
  31. }
复制代码
也就是同过gst_element_factory_list_get_elements从registry中获取type是GST_ELEMENT_FACTORY_TYPE_DECODABLE,GST_ELEMENT_FACTORY_TYPE_AUDIOVIDEO_SINKS,优先级高于GST_RANK_MARGINAL的factory。
  1. #define GST_ELEMENT_FACTORY_TYPE_DECODABLE \
  2.   ((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))
  3. #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
  1. GList *
  2. gst_element_factory_list_get_elements (GstElementFactoryListType type,
  3.     GstRank minrank)
  4. {
  5.   GList *result;
  6.   FilterData data;
  7.   /* prepare type */
  8.   data.type = type;
  9.   data.minrank = minrank;
  10.   /* get the feature list using the filter */
  11.   result = gst_registry_feature_filter (gst_registry_get (),
  12.       (GstPluginFeatureFilter) element_filter, FALSE, &data);
  13.   /* sort on rank and name */
  14.   result = g_list_sort (result, gst_plugin_feature_rank_compare_func);
  15.   return result;
  16. }
  17. //根据rank和type选择
  18. static gboolean
  19. element_filter (GstPluginFeature * feature, FilterData * data)
  20. {
  21.   gboolean res;
  22.   /* we only care about element factories */
  23.   if (G_UNLIKELY (!GST_IS_ELEMENT_FACTORY (feature)))
  24.     return FALSE;
  25.   res = (gst_plugin_feature_get_rank (feature) >= data->minrank) &&
  26.       gst_element_factory_list_is_type (GST_ELEMENT_FACTORY_CAST (feature),
  27.       data->type);
  28.   return res;
  29. }
  30. //factory_type的判断逻辑
  31. gboolean
  32. gst_element_factory_list_is_type (GstElementFactory * factory,
  33.     GstElementFactoryListType type)
  34. {
  35.   gboolean res = FALSE;
  36.   const gchar *klass;
  37.   klass =
  38.       gst_element_factory_get_metadata (factory, GST_ELEMENT_METADATA_KLASS);
  39.   if (klass == NULL) {
  40.     GST_ERROR_OBJECT (factory, "element factory is missing klass identifiers");
  41.     return res;
  42.   }
  43.   /* Filter by element type first, as soon as it matches
  44.    * one type, we skip all other tests */
  45.   if (!res && (type & GST_ELEMENT_FACTORY_TYPE_SINK))
  46.     res = (strstr (klass, "Sink") != NULL);
  47.   if (!res && (type & GST_ELEMENT_FACTORY_TYPE_SRC))
  48.     res = (strstr (klass, "Source") != NULL);
  49.   if (!res && (type & GST_ELEMENT_FACTORY_TYPE_DECODER))
  50.     res = (strstr (klass, "Decoder") != NULL);
  51.   if (!res && (type & GST_ELEMENT_FACTORY_TYPE_ENCODER))
  52.     res = (strstr (klass, "Encoder") != NULL);
  53.   if (!res && (type & GST_ELEMENT_FACTORY_TYPE_MUXER))
  54.     res = (strstr (klass, "Muxer") != NULL);
  55.   if (!res && (type & GST_ELEMENT_FACTORY_TYPE_DEMUXER))
  56.     res = (strstr (klass, "Demux") != NULL);
  57.   /* FIXME : We're actually parsing two Classes here... */
  58.   if (!res && (type & GST_ELEMENT_FACTORY_TYPE_PARSER))
  59.     res = ((strstr (klass, "Parser") != NULL)
  60.         && (strstr (klass, "Codec") != NULL));
  61.   if (!res && (type & GST_ELEMENT_FACTORY_TYPE_DEPAYLOADER))
  62.     res = (strstr (klass, "Depayloader") != NULL);
  63.   if (!res && (type & GST_ELEMENT_FACTORY_TYPE_PAYLOADER))
  64.     res = (strstr (klass, "Payloader") != NULL);
  65.   if (!res && (type & GST_ELEMENT_FACTORY_TYPE_FORMATTER))
  66.     res = (strstr (klass, "Formatter") != NULL);
  67.   if (!res && (type & GST_ELEMENT_FACTORY_TYPE_DECRYPTOR))
  68.     res = (strstr (klass, "Decryptor") != NULL);
  69.   if (!res && (type & GST_ELEMENT_FACTORY_TYPE_ENCRYPTOR))
  70.     res = (strstr (klass, "Encryptor") != NULL);
  71.   if (!res && (type & GST_ELEMENT_FACTORY_TYPE_HARDWARE))
  72.     res = (strstr (klass, "Hardware") != NULL);
  73.   /* Filter by media type now, we only test if it
  74.    * matched any of the types above or only checking the media
  75.    * type was requested. */
  76.   if ((res || !(type & (GST_ELEMENT_FACTORY_TYPE_MAX_ELEMENTS - 1)))
  77.       && (type & (GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO |
  78.               GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO |
  79.               GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE |
  80.               GST_ELEMENT_FACTORY_TYPE_MEDIA_SUBTITLE |
  81.               GST_ELEMENT_FACTORY_TYPE_MEDIA_METADATA)))
  82.     res = ((type & GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO)
  83.         && (strstr (klass, "Audio") != NULL))
  84.         || ((type & GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO)
  85.         && (strstr (klass, "Video") != NULL))
  86.         || ((type & GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE)
  87.         && (strstr (klass, "Image") != NULL)) ||
  88.         ((type & GST_ELEMENT_FACTORY_TYPE_MEDIA_SUBTITLE)
  89.         && (strstr (klass, "Subtitle") != NULL)) ||
  90.         ((type & GST_ELEMENT_FACTORY_TYPE_MEDIA_METADATA)
  91.         && (strstr (klass, "Metadata") != NULL));
  92.   return res;
  93. }
  94. //根据rank排序
  95. gint
  96. gst_plugin_feature_rank_compare_func (gconstpointer p1, gconstpointer p2)
  97. {
  98.   GstPluginFeature *f1, *f2;
  99.   gint diff;
  100.   f1 = (GstPluginFeature *) p1;
  101.   f2 = (GstPluginFeature *) p2;
  102.   diff = f2->rank - f1->rank;
  103.   if (diff != 0)
  104.     return diff;
  105.   diff = strcmp (GST_OBJECT_NAME (f1), GST_OBJECT_NAME (f2));
  106.   return diff;
  107. }
复制代码
(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 */
  1. static GSequence *
  2. avelements_create (GstPlayBin * playbin, gboolean isaudioelement)
  3. {
  4.   GstElementFactory *d_factory, *s_factory;
  5.   GList *dec_list, *sink_list, *dl, *sl;
  6.   GSequence *ave_seq = NULL;
  7.   GstAVElement *ave;
  8.   guint n_common_cf = 0;
  9.   //选择符合要求的音视频添加到对应的sink_list和dec_list
  10.   if (isaudioelement) {
  11.     sink_list = gst_element_factory_list_get_elements
  12.         (GST_ELEMENT_FACTORY_TYPE_SINK |
  13.         GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO, GST_RANK_MARGINAL);
  14.     dec_list =
  15.         gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_DECODER
  16.         | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO, GST_RANK_MARGINAL);
  17.   } else {
  18.     sink_list = gst_element_factory_list_get_elements
  19.         (GST_ELEMENT_FACTORY_TYPE_SINK |
  20.         GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO |
  21.         GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE, GST_RANK_MARGINAL);
  22.     dec_list =
  23.         gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_DECODER
  24.         | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO |
  25.         GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE, GST_RANK_MARGINAL);
  26.   }
  27.   /* create a list of audio/video elements. Each element in the list
  28.    * is holding an audio/video decoder and an audio/video sink in which
  29.    * the decoders srcpad template caps and sink element's sinkpad template
  30.    * caps are compatible */
  31.   dl = dec_list;
  32.   sl = sink_list;
  33.   
  34.   ave_seq = g_sequence_new ((GDestroyNotify) avelements_free);
  35.   //查找可以匹配的dec和sink,组合形式的ave,并保存到ave_seq,函数最后会返回
  36.   /****
  37.         * typedef struct
  38.         *{
  39.         *  GstElementFactory *dec;       /* audio:video decoder */
  40.         *  GstElementFactory *sink;      /* audio:video sink */
  41.         *  guint n_comm_cf;              /* number of common caps features */
  42.         *} GstAVElement;
  43.   *****/
  44.   
  45.   for (; dl; dl = dl->next) {
  46.     d_factory = (GstElementFactory *) dl->data;
  47.     for (; sl; sl = sl->next) {
  48.       s_factory = (GstElementFactory *) sl->data;
  49.       n_common_cf =
  50.           gst_playback_utils_get_n_common_capsfeatures (d_factory, s_factory,
  51.           gst_play_bin_get_flags (playbin), isaudioelement);
  52.       if (n_common_cf < 1)
  53.         continue;
  54.       ave = g_slice_new (GstAVElement);
  55.       ave->dec = gst_object_ref (d_factory);
  56.       ave->sink = gst_object_ref (s_factory);
  57.       ave->n_comm_cf = n_common_cf;
  58.       g_sequence_append (ave_seq, ave);
  59.     }
  60.     sl = sink_list;
  61.   }
  62.   g_sequence_sort (ave_seq, (GCompareDataFunc) avelement_compare_decoder, NULL);
  63.   gst_plugin_feature_list_free (dec_list);
  64.   gst_plugin_feature_list_free (sink_list);
  65.   return ave_seq;
  66. }
复制代码
主要看下gst_playback_utils_get_n_common_capsfeatures怎样计算common caps features
  1.   for (i = 0; i < fact1_caps_size; i++) {
  2.     fact1_features =
  3.         gst_caps_get_features ((const GstCaps *) fact1_tmpl_caps, i);
  4.     if (gst_caps_features_is_any (fact1_features))
  5.       continue;
  6.     fact1_struct =
  7.         gst_caps_get_structure ((const GstCaps *) fact1_tmpl_caps, i);
  8.     for (j = 0; j < fact2_caps_size; j++) {
  9.       fact2_features =
  10.           gst_caps_get_features ((const GstCaps *) fact2_tmpl_caps, j);
  11.       if (gst_caps_features_is_any (fact2_features))
  12.         continue;
  13.       fact2_struct =
  14.           gst_caps_get_structure ((const GstCaps *) fact2_tmpl_caps, j);
  15.       /* A common caps feature is given if the caps features are equal
  16.        * and the structures can intersect. If the NATIVE_AUDIO/NATIVE_VIDEO
  17.        * flags are not set we also allow if both structures are raw caps with
  18.        * system memory caps features, because in that case we have converters in
  19.        * place.
  20.        */
  21.       if (gst_caps_features_is_equal (fact1_features, fact2_features) &&
  22.           (gst_structure_can_intersect (fact1_struct, fact2_struct) ||
  23.               (!native_raw
  24.                   && gst_caps_features_is_equal (fact1_features,
  25.                       GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY)
  26.                   && gst_structure_can_intersect (raw_struct, fact1_struct)
  27.                   && gst_structure_can_intersect (raw_struct, fact2_struct)))
  28.           && !is_included (cf_list, fact2_features)) {
  29.         cf_list = g_list_prepend (cf_list, fact2_features);
  30.         n_common_cf++;
  31.       }
  32.     }
  33.   }
复制代码
 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));
  1. GList *
  2. gst_element_factory_list_filter (GList * list,
  3.     const GstCaps * caps, GstPadDirection direction, gboolean subsetonly)
  4. {
  5.   GQueue results = G_QUEUE_INIT;
  6.   GST_DEBUG ("finding factories");
  7.   /* loop over all the factories */
  8.   for (; list; list = list->next) {
  9.     GstElementFactory *factory;
  10.     const GList *templates;
  11.     GList *walk;
  12.     factory = (GstElementFactory *) list->data;
  13.     GST_DEBUG ("Trying %s",
  14.         gst_plugin_feature_get_name ((GstPluginFeature *) factory));
  15.     /* get the templates from the element factory */
  16.     templates = gst_element_factory_get_static_pad_templates (factory);
  17.     for (walk = (GList *) templates; walk; walk = g_list_next (walk)) {
  18.       GstStaticPadTemplate *templ = walk->data;
  19.       /* we only care about the sink templates */
  20.       if (templ->direction == direction) {
  21.         GstCaps *tmpl_caps;
  22.         /* try to intersect the caps with the caps of the template */
  23.         tmpl_caps = gst_static_caps_get (&templ->static_caps);
  24.         /* FIXME, intersect is not the right method, we ideally want to check
  25.          * for a subset here */
  26.         /* check if the intersection is empty */
  27.         if ((subsetonly && gst_caps_is_subset (caps, tmpl_caps)) ||
  28.             (!subsetonly && gst_caps_can_intersect (caps, tmpl_caps))) {
  29.           /* non empty intersection, we can use this element */
  30.           g_queue_push_tail (&results, gst_object_ref (factory));
  31.           gst_caps_unref (tmpl_caps);
  32.           break;
  33.         }
  34.         gst_caps_unref (tmpl_caps);
  35.       }
  36.     }
  37.   }
  38.   return results.head;
  39. }
复制代码
3.然后继续后续处理,判定找到factory_list中第一个audio/video decoder的位置
  1.   /* check whether the caps are asking for a list of audio/video decoders */
  2.   tmp = factory_list;
  3.   if (!gst_caps_is_any (caps)) {
  4.     for (; tmp; tmp = tmp->next) {
  5.       GstElementFactory *factory = (GstElementFactory *) tmp->data;
  6.       isvideodeclist = gst_element_factory_list_is_type (factory,
  7.           GST_ELEMENT_FACTORY_TYPE_DECODER |
  8.           GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO |
  9.           GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE);
  10.       isaudiodeclist = gst_element_factory_list_is_type (factory,
  11.           GST_ELEMENT_FACTORY_TYPE_DECODER |
  12.           GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO);
  13.       if (isaudiodeclist || isvideodeclist)
  14.         break;
  15.     }
  16.   }
  17.   if (isaudiodeclist || isvideodeclist) {
  18.     GSequence **ave_list;
  19.     GstPlayFlags flags;
  20.     if (isaudiodeclist)
  21.       ave_list = &playbin->aelements;
  22.     else
  23.       ave_list = &playbin->velements;
  24.     flags = gst_play_bin_get_flags (playbin);
  25.     //创建decoder_list
  26.     g_mutex_lock (&playbin->elements_lock);
  27.     /* sort factory_list based on the GstAVElement list priority */
  28.     factory_list = create_decoders_list (factory_list, *ave_list, flags);
  29.     g_mutex_unlock (&playbin->elements_lock);
  30.   }
复制代码
  1. static GList *
  2. create_decoders_list (GList * factory_list, GSequence * avelements,
  3.     GstPlayFlags flags)
  4. {
  5.   GList *dec_list = NULL, *tmp;
  6.   GList *ave_list = NULL;
  7.   GList *ave_free_list = NULL;
  8.   GstAVElement *ave, *best_ave;
  9.   g_return_val_if_fail (factory_list != NULL, NULL);
  10.   g_return_val_if_fail (avelements != NULL, NULL);
  11.   for (tmp = factory_list; tmp; tmp = tmp->next) {
  12.     GstElementFactory *factory = (GstElementFactory *) tmp->data;
  13.     /* if there are parsers or sink elements, add them first */ //parsers or sink elements直接dec_list,如果不是走下面流程添加到ave_list
  14.     if (gst_element_factory_list_is_type (factory,
  15.             GST_ELEMENT_FACTORY_TYPE_PARSER) ||
  16.         gst_element_factory_list_is_type (factory,
  17.             GST_ELEMENT_FACTORY_TYPE_SINK)) {
  18.       dec_list = g_list_prepend (dec_list, gst_object_ref (factory));
  19.     } else if (!(((flags & GST_PLAY_FLAG_FORCE_SW_DECODERS) != 0) //如果没有同时满足以下两个条件则为TRUE:强制软件解码且factory 是硬件解码器类型
  20.             && gst_element_factory_list_is_type (factory,
  21.                 GST_ELEMENT_FACTORY_TYPE_HARDWARE))) {
  22.       GSequenceIter *seq_iter;
  23.       seq_iter =
  24.           g_sequence_lookup (avelementszh, factory,
  25.           (GCompareDataFunc) avelement_lookup_decoder, NULL);//avelements中查找,匹配条件avelement_lookup_decoder
  26.       if (!seq_iter) {
  27.         GstAVElement *ave = g_slice_new0 (GstAVElement);
  28.         ave->dec = factory;
  29.         ave->sink = NULL;
  30.         /* There's at least raw */
  31.         ave->n_comm_cf = 1;
  32.         ave_list = g_list_prepend (ave_list, ave);
  33.         /* We need to free these later */
  34.         ave_free_list = g_list_prepend (ave_free_list, ave);
  35.         continue;
  36.       }
  37.       /* Go to first iter with that decoder */
  38.       do {
  39.         GSequenceIter *tmp_seq_iter;
  40.         tmp_seq_iter = g_sequence_iter_prev (seq_iter);
  41.         if (!avelement_iter_is_equal (tmp_seq_iter, factory))
  42.           break;
  43.         seq_iter = tmp_seq_iter;
  44.       } while (!g_sequence_iter_is_begin (seq_iter));
  45.       /* Get the best ranked GstAVElement for that factory */
  46.       best_ave = NULL;
  47.       while (!g_sequence_iter_is_end (seq_iter)
  48.           && avelement_iter_is_equal (seq_iter, factory)) {
  49.         ave = g_sequence_get (seq_iter);
  50.         if (!best_ave || avelement_compare (ave, best_ave) < 0) //最佳匹配,匹配条件avelement_compare
  51.           best_ave = ave;
  52.         seq_iter = g_sequence_iter_next (seq_iter);
  53.       }
  54.       ave_list = g_list_prepend (ave_list, best_ave);
  55.     }
  56.   }
  57.   /* Sort all GstAVElements by their relative ranks and insert
  58.    * into the decoders list */
  59.   ave_list = g_list_sort (ave_list, (GCompareFunc) avelement_compare);
  60.   for (tmp = ave_list; tmp; tmp = tmp->next) {
  61.     ave = (GstAVElement *) tmp->data;
  62.     dec_list = g_list_prepend (dec_list, gst_object_ref (ave->dec));//prepend是添加到list的头部,所以需要后面的翻转
  63.   }
  64.   g_list_free (ave_list);
  65.   gst_plugin_feature_list_free (factory_list);
  66.   for (tmp = ave_free_list; tmp; tmp = tmp->next)
  67.     g_slice_free (GstAVElement, tmp->data);
  68.   g_list_free (ave_free_list);
  69.   //所以parse和sink都被添加到了前面,其他的根据rank等排序
  70.   dec_list = g_list_reverse (dec_list);
  71.   return dec_list;
  72. }
  73. static gint
  74. avelement_compare (gconstpointer p1, gconstpointer p2)
  75. {
  76.   GstAVElement *v1, *v2;
  77.   GstPluginFeature *fd1, *fd2, *fs1, *fs2;
  78.   gint64 diff, v1_rank, v2_rank;
  79.   v1 = (GstAVElement *) p1;
  80.   v2 = (GstAVElement *) p2;
  81.   fd1 = (GstPluginFeature *) v1->dec;
  82.   fd2 = (GstPluginFeature *) v2->dec;
  83.   //优先比较sink的rank,没有在比较dec的rank
  84.   /* If both have a sink, we also compare their ranks */
  85.   if (v1->sink && v2->sink) {
  86.     fs1 = (GstPluginFeature *) v1->sink;
  87.     fs2 = (GstPluginFeature *) v2->sink;
  88.     v1_rank = (gint64) gst_plugin_feature_get_rank (fd1) *
  89.         gst_plugin_feature_get_rank (fs1);
  90.     v2_rank = (gint64) gst_plugin_feature_get_rank (fd2) *
  91.         gst_plugin_feature_get_rank (fs2);
  92.   } else {
  93.     v1_rank = gst_plugin_feature_get_rank (fd1);
  94.     v2_rank = gst_plugin_feature_get_rank (fd2);
  95.     fs1 = fs2 = NULL;
  96.   }
  97.   /* comparison based on the rank */
  98.   diff = v2_rank - v1_rank;
  99.   if (diff < 0)
  100.     return -1;
  101.   else if (diff > 0)
  102.     return 1;
  103.   //比较number of common caps feature,多的优先
  104.   /* comparison based on number of common caps features */
  105.   diff = v2->n_comm_cf - v1->n_comm_cf;
  106.   if (diff != 0)
  107.     return diff;
  108.   if (fs1 && fs2) {
  109.     /* comparison based on the name of sink elements */
  110.     diff = strcmp (GST_OBJECT_NAME (fs1), GST_OBJECT_NAME (fs2));
  111.     if (diff != 0)
  112.       return diff;
  113.   }
  114.   /* comparison based on the name of decoder elements */
  115.   return strcmp (GST_OBJECT_NAME (fd1), GST_OBJECT_NAME (fd2));
  116. }
复制代码
这里留意下list中的排序吧:parse和sink最前,其他会按照优先级(rank)、共有 caps 特性数量、吸收器名称息争码器名称的顺序分列 。
后续如果应有sink则将sink插入到list中,基本也就完成了autoplug_factories_cb流程了。
 二、autoplug_select_cb
  1.   GstPlayBin *playbin;
  2.   GstElement *element;
  3.   const gchar *klass;
  4.   GstPlaySinkType type;
  5.   GstElement **sinkp;
  6.   GList *ave_list = NULL, *l;
  7.   GstAVElement *ave = NULL;
  8.   GSequence *ave_seq = NULL;
  9.   GSequenceIter *seq_iter;
  10.   gboolean created_sink = FALSE;
  11.   {省略}  
  12.   if (isaudiodec) {
  13.       ave_seq = playbin->aelements;
  14.       sinkp = &group->audio_sink;
  15.     } else {
  16.       ave_seq = playbin->velements;
  17.       sinkp = &group->video_sink;
  18.     }
  19.     seq_iter =
  20.         g_sequence_lookup (ave_seq, factory,
  21.         (GCompareDataFunc) avelement_lookup_decoder, NULL);
  22.     if (seq_iter) {
  23.       /* Go to first iter with that decoder */
  24.       do {
  25.         GSequenceIter *tmp_seq_iter;
  26.         tmp_seq_iter = g_sequence_iter_prev (seq_iter);
  27.         if (!avelement_iter_is_equal (tmp_seq_iter, factory))
  28.           break;
  29.         seq_iter = tmp_seq_iter;
  30.       } while (!g_sequence_iter_is_begin (seq_iter));
  31.       while (!g_sequence_iter_is_end (seq_iter)
  32.           && avelement_iter_is_equal (seq_iter, factory)) {
  33.         ave = g_sequence_get (seq_iter);
  34.         ave_list = g_list_prepend (ave_list, ave);
  35.         seq_iter = g_sequence_iter_next (seq_iter);
  36.       }
  37.       /* Sort all GstAVElements by their relative ranks and insert
  38.        * into the decoders list */
  39.       ave_list = g_list_sort (ave_list, (GCompareFunc) avelement_compare);
  40.     } else {
  41.       ave_list = g_list_prepend (ave_list, NULL);
  42.     }
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

羊蹓狼

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表