2 * Copyright (C) 2007 Benjamin Otte <otte@gnome.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301 USA
24 #include <gst/pbutils/pbutils.h>
26 #include "swfdec_codec_gst.h"
27 #include "swfdec_debug.h"
28 #include "swfdec_internal.h"
33 swfdec_gst_buffer_new (SwfdecBuffer
*buffer
)
35 /* FIXME: make this a zero-copy operation */
38 g_return_val_if_fail (buffer
!= NULL
, NULL
);
40 ret
= gst_buffer_new_and_alloc (buffer
->length
);
41 memcpy (GST_BUFFER_DATA (ret
), buffer
->data
, buffer
->length
);
42 swfdec_buffer_unref (buffer
);
49 /* NB: try to mirror decodebin behavior */
51 swfdec_gst_feature_filter (GstPluginFeature
*feature
, gpointer caps
)
56 /* we only care about element factories */
57 if (!GST_IS_ELEMENT_FACTORY (feature
))
60 /* only decoders are interesting */
61 klass
= gst_element_factory_get_klass (GST_ELEMENT_FACTORY (feature
));
62 if (strstr (klass
, "Decoder") == NULL
)
65 /* only select elements with autoplugging rank */
66 if (gst_plugin_feature_get_rank (feature
) < GST_RANK_MARGINAL
)
69 /* only care about the right sink caps */
70 for (walk
= gst_element_factory_get_static_pad_templates (GST_ELEMENT_FACTORY (feature
));
71 walk
; walk
= walk
->next
) {
72 GstStaticPadTemplate
*template = walk
->data
;
74 GstCaps
*template_caps
;
76 if (template->direction
!= GST_PAD_SINK
)
79 template_caps
= gst_static_caps_get (&template->static_caps
);
80 intersect
= gst_caps_intersect (caps
, template_caps
);
82 gst_caps_unref (template_caps
);
83 if (gst_caps_is_empty (intersect
)) {
84 gst_caps_unref (intersect
);
86 gst_caps_unref (intersect
);
94 swfdec_gst_compare_features (gconstpointer a_
, gconstpointer b_
)
97 GstPluginFeature
*a
= GST_PLUGIN_FEATURE (a_
);
98 GstPluginFeature
*b
= GST_PLUGIN_FEATURE (b_
);
100 diff
= gst_plugin_feature_get_rank (b
) - gst_plugin_feature_get_rank (a
);
104 return strcmp (gst_plugin_feature_get_name (a
), gst_plugin_feature_get_name (b
));
108 swfdec_gst_get_element_factory (GstCaps
*caps
)
110 GstElementFactory
*ret
;
113 list
= gst_registry_feature_filter (gst_registry_get_default (),
114 swfdec_gst_feature_filter
, FALSE
, caps
);
118 list
= g_list_sort (list
, swfdec_gst_compare_features
);
120 gst_object_ref (ret
);
121 gst_plugin_feature_list_free (list
);
128 swfdec_gst_connect_srcpad (GstElement
*element
, GstCaps
*caps
)
130 GstPadTemplate
*tmpl
;
131 GstPad
*srcpad
, *sinkpad
;
133 sinkpad
= gst_element_get_pad (element
, "sink");
137 tmpl
= gst_pad_template_new ("src", GST_PAD_SRC
, GST_PAD_ALWAYS
, caps
);
138 srcpad
= gst_pad_new_from_template (tmpl
, "src");
139 g_object_unref (tmpl
);
140 if (gst_pad_link (srcpad
, sinkpad
) != GST_PAD_LINK_OK
)
143 gst_object_unref (sinkpad
);
144 gst_pad_set_active (srcpad
, TRUE
);
148 SWFDEC_ERROR ("failed to create or link srcpad");
149 gst_object_unref (sinkpad
);
150 gst_object_unref (srcpad
);
155 swfdec_gst_connect_sinkpad (GstElement
*element
, GstCaps
*caps
)
157 GstPadTemplate
*tmpl
;
158 GstPad
*srcpad
, *sinkpad
;
160 srcpad
= gst_element_get_pad (element
, "src");
164 tmpl
= gst_pad_template_new ("sink", GST_PAD_SINK
, GST_PAD_ALWAYS
, caps
);
165 sinkpad
= gst_pad_new_from_template (tmpl
, "sink");
166 g_object_unref (tmpl
);
167 if (gst_pad_link (srcpad
, sinkpad
) != GST_PAD_LINK_OK
)
170 gst_object_unref (srcpad
);
171 gst_pad_set_active (sinkpad
, TRUE
);
175 SWFDEC_ERROR ("failed to create or link sinkpad");
176 gst_object_unref (srcpad
);
177 gst_object_unref (sinkpad
);
184 swfdec_gst_chain_func (GstPad
*pad
, GstBuffer
*buffer
)
186 GQueue
*queue
= g_object_get_data (G_OBJECT (pad
), "swfdec-queue");
188 g_queue_push_tail (queue
, buffer
);
194 swfdec_gst_decoder_init (SwfdecGstDecoder
*dec
, GstCaps
*srccaps
, GstCaps
*sinkcaps
, ...)
197 GstElementFactory
*factory
;
202 factory
= swfdec_gst_get_element_factory (srccaps
);
203 dec
->bin
= gst_bin_new ("bin");
205 decoder
= gst_element_factory_create (factory
, "decoder");
206 gst_object_unref (factory
);
210 if (decoder
== NULL
) {
211 SWFDEC_ERROR ("failed to create decoder");
214 gst_bin_add (GST_BIN (dec
->bin
), decoder
);
215 dec
->src
= swfdec_gst_connect_srcpad (decoder
, srccaps
);
216 if (dec
->src
== NULL
)
219 /* plug transform elements */
220 va_start (args
, sinkcaps
);
221 while ((name
= va_arg (args
, const char *))) {
222 GstElement
*next
= gst_element_factory_make (name
, NULL
);
224 SWFDEC_ERROR ("failed to create '%s' element", name
);
227 gst_bin_add (GST_BIN (dec
->bin
), next
);
228 if (!gst_element_link (decoder
, next
)) {
229 SWFDEC_ERROR ("failed to link '%s' element to decoder", name
);
235 dec
->sink
= swfdec_gst_connect_sinkpad (decoder
, sinkcaps
);
236 if (dec
->sink
== NULL
)
238 gst_pad_set_chain_function (dec
->sink
, swfdec_gst_chain_func
);
239 dec
->queue
= g_queue_new ();
240 g_object_set_data (G_OBJECT (dec
->sink
), "swfdec-queue", dec
->queue
);
241 if (!gst_element_set_state (dec
->bin
, GST_STATE_PLAYING
) == GST_STATE_CHANGE_SUCCESS
) {
242 SWFDEC_ERROR ("could not change element state");
249 swfdec_gst_decoder_finish (SwfdecGstDecoder
*dec
)
252 gst_element_set_state (dec
->bin
, GST_STATE_NULL
);
253 g_object_unref (dec
->bin
);
257 g_object_unref (dec
->src
);
261 g_object_unref (dec
->sink
);
266 while ((buffer
= g_queue_pop_head (dec
->queue
)) != NULL
) {
267 gst_buffer_unref (buffer
);
269 g_queue_free (dec
->queue
);
275 swfdec_gst_decoder_set_codec_data (SwfdecGstDecoder
*dec
,
280 caps
= gst_pad_get_caps (dec
->src
);
281 caps
= gst_caps_make_writable (caps
);
283 gst_caps_set_simple (caps
, "codec_data", GST_TYPE_BUFFER
, buffer
, NULL
);
285 GstStructure
*structure
= gst_caps_get_structure (caps
, 0);
286 gst_structure_remove_field (structure
, "codec_data");
288 gst_pad_set_caps (dec
->src
, caps
);
289 gst_caps_unref (caps
);
293 swfdec_gst_decoder_push (SwfdecGstDecoder
*dec
, GstBuffer
*buffer
)
298 /* set caps if none set yet */
299 caps
= gst_buffer_get_caps (buffer
);
301 gst_caps_unref (caps
);
303 caps
= GST_PAD_CAPS (dec
->src
);
305 caps
= (GstCaps
*) gst_pad_get_pad_template_caps (dec
->src
);
306 g_assert (gst_caps_is_fixed (caps
));
307 gst_pad_set_caps (dec
->src
, caps
);
309 gst_buffer_set_caps (buffer
, GST_PAD_CAPS (dec
->src
));
312 ret
= gst_pad_push (dec
->src
, buffer
);
313 if (GST_FLOW_IS_SUCCESS (ret
))
315 SWFDEC_ERROR ("error %d pushing data", (int) ret
);
320 swfdec_gst_decoder_push_eos (SwfdecGstDecoder
*dec
)
322 gst_pad_push_event (dec
->src
, gst_event_new_eos ());
326 swfdec_gst_decoder_pull (SwfdecGstDecoder
*dec
)
328 return g_queue_pop_head (dec
->queue
);