1 /* Copyright (C) <2014> Intel Corporation
2 * Copyright (C) <2014> Sreerenj Balachandran <sreerenj.balachandran@intel.com>
3 *
4 * Author: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <gst/gst.h>
27 #include "gstplaybackutils.h"
28
29 static GstStaticCaps raw_audio_caps = GST_STATIC_CAPS ("audio/x-raw(ANY)");
30 static GstStaticCaps raw_video_caps = GST_STATIC_CAPS ("video/x-raw(ANY)");
31
32 /* unref the caps after usage */
33 static GstCaps *
get_template_caps(GstElementFactory * factory,GstPadDirection direction)34 get_template_caps (GstElementFactory * factory, GstPadDirection direction)
35 {
36 const GList *templates;
37 GstStaticPadTemplate *templ = NULL;
38 GList *walk;
39
40 templates = gst_element_factory_get_static_pad_templates (factory);
41 for (walk = (GList *) templates; walk; walk = g_list_next (walk)) {
42 templ = walk->data;
43 if (templ->direction == direction)
44 break;
45 }
46 if (templ)
47 return gst_static_caps_get (&templ->static_caps);
48 else
49 return NULL;
50 }
51
52 static gboolean
is_included(GList * list,GstCapsFeatures * cf)53 is_included (GList * list, GstCapsFeatures * cf)
54 {
55 for (; list; list = list->next) {
56 if (gst_caps_features_is_equal ((GstCapsFeatures *) list->data, cf))
57 return TRUE;
58 }
59 return FALSE;
60 }
61
62 /* compute the number of common caps features */
63 guint
gst_playback_utils_get_n_common_capsfeatures(GstElementFactory * fact1,GstElementFactory * fact2,GstPlayFlags flags,gboolean isaudioelement)64 gst_playback_utils_get_n_common_capsfeatures (GstElementFactory * fact1,
65 GstElementFactory * fact2, GstPlayFlags flags, gboolean isaudioelement)
66 {
67 GstCaps *fact1_tmpl_caps, *fact2_tmpl_caps;
68 GstCapsFeatures *fact1_features, *fact2_features;
69 GstStructure *fact1_struct, *fact2_struct;
70 GList *cf_list = NULL;
71 guint fact1_caps_size, fact2_caps_size;
72 guint i, j, n_common_cf = 0;
73 GstCaps *raw_caps =
74 (isaudioelement) ? gst_static_caps_get (&raw_audio_caps) :
75 gst_static_caps_get (&raw_video_caps);
76 GstStructure *raw_struct = gst_caps_get_structure (raw_caps, 0);
77 gboolean native_raw =
78 (isaudioelement ? ! !(flags & GST_PLAY_FLAG_NATIVE_AUDIO) : ! !(flags &
79 GST_PLAY_FLAG_NATIVE_VIDEO));
80
81 fact1_tmpl_caps = get_template_caps (fact1, GST_PAD_SRC);
82 fact2_tmpl_caps = get_template_caps (fact2, GST_PAD_SINK);
83 if (!fact1_tmpl_caps || !fact2_tmpl_caps) {
84 GST_ERROR ("Failed to get template caps from decoder or sink");
85 if (fact1_tmpl_caps)
86 gst_caps_unref (fact1_tmpl_caps);
87 else if (fact2_tmpl_caps)
88 gst_caps_unref (fact2_tmpl_caps);
89 return 0;
90 }
91
92 fact1_caps_size = gst_caps_get_size (fact1_tmpl_caps);
93 fact2_caps_size = gst_caps_get_size (fact2_tmpl_caps);
94
95 for (i = 0; i < fact1_caps_size; i++) {
96 fact1_features =
97 gst_caps_get_features ((const GstCaps *) fact1_tmpl_caps, i);
98 if (gst_caps_features_is_any (fact1_features))
99 continue;
100 fact1_struct =
101 gst_caps_get_structure ((const GstCaps *) fact1_tmpl_caps, i);
102 for (j = 0; j < fact2_caps_size; j++) {
103
104 fact2_features =
105 gst_caps_get_features ((const GstCaps *) fact2_tmpl_caps, j);
106 if (gst_caps_features_is_any (fact2_features))
107 continue;
108 fact2_struct =
109 gst_caps_get_structure ((const GstCaps *) fact2_tmpl_caps, j);
110
111 /* A common caps feature is given if the caps features are equal
112 * and the structures can intersect. If the NATIVE_AUDIO/NATIVE_VIDEO
113 * flags are not set we also allow if both structures are raw caps with
114 * system memory caps features, because in that case we have converters in
115 * place.
116 */
117 if (gst_caps_features_is_equal (fact1_features, fact2_features) &&
118 (gst_structure_can_intersect (fact1_struct, fact2_struct) ||
119 (!native_raw
120 && gst_caps_features_is_equal (fact1_features,
121 GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY)
122 && gst_structure_can_intersect (raw_struct, fact1_struct)
123 && gst_structure_can_intersect (raw_struct, fact2_struct)))
124 && !is_included (cf_list, fact2_features)) {
125 cf_list = g_list_prepend (cf_list, fact2_features);
126 n_common_cf++;
127 }
128 }
129 }
130 if (cf_list)
131 g_list_free (cf_list);
132
133 gst_caps_unref (fact1_tmpl_caps);
134 gst_caps_unref (fact2_tmpl_caps);
135
136 return n_common_cf;
137 }
138
139 gint
gst_playback_utils_compare_factories_func(gconstpointer p1,gconstpointer p2)140 gst_playback_utils_compare_factories_func (gconstpointer p1, gconstpointer p2)
141 {
142 GstPluginFeature *f1, *f2;
143 gboolean is_parser1, is_parser2;
144
145 f1 = (GstPluginFeature *) p1;
146 f2 = (GstPluginFeature *) p2;
147
148 is_parser1 = gst_element_factory_list_is_type (GST_ELEMENT_FACTORY_CAST (f1),
149 GST_ELEMENT_FACTORY_TYPE_PARSER);
150 is_parser2 = gst_element_factory_list_is_type (GST_ELEMENT_FACTORY_CAST (f2),
151 GST_ELEMENT_FACTORY_TYPE_PARSER);
152
153
154 /* We want all parsers first as we always want to plug parsers
155 * before decoders */
156 if (is_parser1 && !is_parser2)
157 return -1;
158 else if (!is_parser1 && is_parser2)
159 return 1;
160
161 /* And if it's a both a parser we first sort by rank
162 * and then by factory name */
163 return gst_plugin_feature_rank_compare_func (p1, p2);
164 }
165