gst-indent
[platform/upstream/gst-plugins-good.git] / gst / avi / gstavidecoder.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
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  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20
21 /*#define GST_DEBUG_ENABLED */
22 #include <string.h>
23
24 #include "gstavidecoder.h"
25
26
27
28 /* elementfactory information */
29 static GstElementDetails gst_avi_decoder_details = {
30   ".avi decoder",
31   "Decoder/Video",
32   "Decodes a .avi file into audio and video",
33   VERSION,
34   "Erik Walthinsen <omega@cse.ogi.edu>\n" "Wim Taymans <wim.taymans@tvd.be>",
35   "(C) 1999",
36 };
37
38 static GstCaps *avi_typefind (GstBuffer * buf, gpointer private);
39
40 /* typefactory for 'avi' */
41 static GstTypeDefinition avidefinition = {
42   "avidecoder_video/avi",
43   "video/avi",
44   ".avi",
45   avi_typefind,
46 };
47
48 /* AviDecoder signals and args */
49 enum
50 {
51   /* FILL ME */
52   LAST_SIGNAL
53 };
54
55 enum
56 {
57   ARG_0,
58   ARG_BITRATE,
59   ARG_MEDIA_TIME,
60   ARG_CURRENT_TIME,
61   /* FILL ME */
62 };
63
64 GST_PADTEMPLATE_FACTORY (sink_templ,
65     "sink",
66     GST_PAD_SINK,
67     GST_PAD_ALWAYS,
68     GST_CAPS_NEW ("avidecoder_sink",
69         "video/avi", "RIFF", GST_PROPS_STRING ("AVI")
70     )
71     )
72
73     GST_PADTEMPLATE_FACTORY (src_video_templ,
74     "video_src",
75     GST_PAD_SRC,
76     GST_PAD_ALWAYS,
77     GST_CAPS_NEW ("wincodec_src",
78         "video/raw",
79         "format", GST_PROPS_LIST (GST_PROPS_FOURCC (GST_MAKE_FOURCC ('Y', 'U', 'Y',
80                     '2')), GST_PROPS_FOURCC (GST_MAKE_FOURCC ('I', '4', '2', '0')),
81             GST_PROPS_FOURCC (GST_MAKE_FOURCC ('R', 'G', 'B', ' '))
82         ), "width", GST_PROPS_INT_RANGE (16, 4096), "height",
83         GST_PROPS_INT_RANGE (16, 4096)
84     )
85     )
86
87     GST_PADTEMPLATE_FACTORY (src_audio_templ,
88     "audio_src",
89     GST_PAD_SRC,
90     GST_PAD_ALWAYS,
91     GST_CAPS_NEW ("src_audio",
92         "audio/raw",
93         "format", GST_PROPS_STRING ("int"),
94         "law", GST_PROPS_INT (0),
95         "endianness", GST_PROPS_INT (G_BYTE_ORDER),
96         "signed", GST_PROPS_LIST (GST_PROPS_BOOLEAN (TRUE),
97             GST_PROPS_BOOLEAN (FALSE)
98         ), "width", GST_PROPS_LIST (GST_PROPS_INT (8), GST_PROPS_INT (16)
99         ), "depth", GST_PROPS_LIST (GST_PROPS_INT (8), GST_PROPS_INT (16)
100         ),
101         "rate", GST_PROPS_INT_RANGE (11025, 48000),
102         "channels", GST_PROPS_INT_RANGE (1, 2)
103     )
104     )
105
106      static void gst_avi_decoder_class_init (GstAviDecoderClass * klass);
107      static void gst_avi_decoder_init (GstAviDecoder * avi_decoder);
108
109      static void gst_avi_decoder_get_property (GObject * object, guint prop_id,
110     GValue * value, GParamSpec * pspec);
111
112
113
114      static GstElementClass *parent_class = NULL;
115
116 /*static guint gst_avi_decoder_signals[LAST_SIGNAL] = { 0 }; */
117
118 GType
119 gst_avi_decoder_get_type (void)
120 {
121   static GType avi_decoder_type = 0;
122
123   if (!avi_decoder_type) {
124     static const GTypeInfo avi_decoder_info = {
125       sizeof (GstAviDecoderClass),
126       NULL,
127       NULL,
128       (GClassInitFunc) gst_avi_decoder_class_init,
129       NULL,
130       NULL,
131       sizeof (GstAviDecoder),
132       0,
133       (GInstanceInitFunc) gst_avi_decoder_init,
134     };
135     avi_decoder_type =
136         g_type_register_static (GST_TYPE_BIN, "GstAviDecoder",
137         &avi_decoder_info, 0);
138   }
139   return avi_decoder_type;
140 }
141
142 static void
143 gst_avi_decoder_class_init (GstAviDecoderClass * klass)
144 {
145   GObjectClass *gobject_class;
146   GstElementClass *gstelement_class;
147
148   gobject_class = (GObjectClass *) klass;
149   gstelement_class = (GstElementClass *) klass;
150
151   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE, g_param_spec_long ("bitrate", "bitrate", "bitrate", G_MINLONG, G_MAXLONG, 0, G_PARAM_READABLE));        /* CHECKME */
152   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MEDIA_TIME, g_param_spec_long ("media_time", "media_time", "media_time", G_MINLONG, G_MAXLONG, 0, G_PARAM_READABLE));    /* CHECKME */
153   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_CURRENT_TIME, g_param_spec_long ("current_time", "current_time", "current_time", G_MINLONG, G_MAXLONG, 0, G_PARAM_READABLE));    /* CHECKME */
154
155   parent_class = g_type_class_ref (GST_TYPE_BIN);
156
157   gobject_class->get_property = gst_avi_decoder_get_property;
158 }
159
160 static void
161 gst_avi_decoder_new_pad (GstElement * element, GstPad * pad,
162     GstAviDecoder * avi_decoder)
163 {
164   GstCaps *caps;
165   GstCaps *targetcaps = NULL;
166   const gchar *format;
167   gboolean type_found;
168   GstElement *type;
169   GstElement *new_element = NULL;
170   gchar *padname = NULL;
171   gchar *gpadname = NULL;
172
173 #define AVI_TYPE_VIDEO  1
174 #define AVI_TYPE_AUDIO  2
175   gint media_type = 0;
176
177   GST_DEBUG (0, "avidecoder: new pad for element \"%s\"",
178       gst_element_get_name (element));
179
180   caps = gst_pad_get_caps (pad);
181   format = gst_caps_get_string (caps, "format");
182
183   if (!strcmp (format, "strf_vids")) {
184     targetcaps =
185         gst_padtemplate_get_caps (GST_PADTEMPLATE_GET (src_video_templ));
186     media_type = AVI_TYPE_VIDEO;
187     gpadname = g_strdup_printf ("video_%02d", avi_decoder->video_count++);
188   } else if (!strcmp (format, "strf_auds")) {
189     targetcaps =
190         gst_padtemplate_get_caps (GST_PADTEMPLATE_GET (src_audio_templ));
191     media_type = AVI_TYPE_AUDIO;
192     gpadname = g_strdup_printf ("audio_%02d", avi_decoder->audio_count++);
193   } else if (!strcmp (format, "strf_iavs")) {
194     targetcaps =
195         gst_padtemplate_get_caps (GST_PADTEMPLATE_GET (src_video_templ));
196     media_type = AVI_TYPE_VIDEO;
197     gpadname = g_strdup_printf ("video_%02d", avi_decoder->video_count++);
198   } else {
199     g_assert_not_reached ();
200   }
201
202   gst_element_set_state (GST_ELEMENT (avi_decoder), GST_STATE_PAUSED);
203
204   type = gst_elementfactory_make ("avitypes",
205       g_strdup_printf ("typeconvert%d", avi_decoder->count));
206
207   /* brin the element to the READY state so it can do our caps negotiation */
208   gst_element_set_state (type, GST_STATE_READY);
209
210   gst_pad_connect (pad, gst_element_get_pad (type, "sink"));
211   type_found = gst_util_get_bool_arg (G_OBJECT (type), "type_found");
212
213   if (type_found) {
214
215     gst_bin_add (GST_BIN (avi_decoder), type);
216
217     pad = gst_element_get_pad (type, "src");
218     caps = gst_pad_get_caps (pad);
219
220     if (gst_caps_is_always_compatible (caps, targetcaps)) {
221       gst_element_add_ghost_pad (GST_ELEMENT (avi_decoder),
222           gst_element_get_pad (type, "src"), gpadname);
223
224       avi_decoder->count++;
225       goto done;
226     }
227 #ifndef GST_DISABLE_AUTOPLUG
228     else {
229       GstAutoplug *autoplug;
230
231       autoplug = gst_autoplugfactory_make ("static");
232
233       new_element = gst_autoplug_to_caps (autoplug, caps, targetcaps, NULL);
234
235       padname = "src_00";
236     }
237 #endif /* GST_DISABLE_AUTOPLUG */
238   }
239
240   if (!new_element && (media_type == AVI_TYPE_VIDEO)) {
241     padname = "src";
242   } else if (!new_element && (media_type == AVI_TYPE_AUDIO)) {
243     /*FIXME */
244     padname = "src";
245   }
246
247   if (new_element) {
248     gst_pad_connect (pad, gst_element_get_pad (new_element, "sink"));
249     gst_element_set_name (new_element, g_strdup_printf ("element%d",
250             avi_decoder->count));
251     gst_bin_add (GST_BIN (avi_decoder), new_element);
252
253     gst_element_add_ghost_pad (GST_ELEMENT (avi_decoder),
254         gst_element_get_pad (new_element, padname), gpadname);
255
256     avi_decoder->count++;
257   } else {
258     g_warning ("avidecoder: could not autoplug\n");
259   }
260
261 done:
262   gst_element_set_state (GST_ELEMENT (avi_decoder), GST_STATE_PLAYING);
263 }
264
265 static void
266 gst_avi_decoder_init (GstAviDecoder * avi_decoder)
267 {
268   avi_decoder->demuxer = gst_elementfactory_make ("avidemux", "demux");
269
270   if (avi_decoder->demuxer) {
271     gst_bin_add (GST_BIN (avi_decoder), avi_decoder->demuxer);
272
273     gst_element_add_ghost_pad (GST_ELEMENT (avi_decoder),
274         gst_element_get_pad (avi_decoder->demuxer, "sink"), "sink");
275
276     g_signal_connect (G_OBJECT (avi_decoder->demuxer), "new_pad",
277         G_CALLBACK (gst_avi_decoder_new_pad), avi_decoder);
278   } else {
279     g_warning ("wow!, no avi demuxer found. help me\n");
280   }
281
282   avi_decoder->count = 0;
283   avi_decoder->audio_count = 0;
284   avi_decoder->video_count = 0;
285 }
286
287 static GstCaps *
288 avi_typefind (GstBuffer * buf, gpointer private)
289 {
290   gchar *data = GST_BUFFER_DATA (buf);
291   GstCaps *new;
292
293   GST_DEBUG (0, "avi_decoder: typefind");
294   if (strncmp (&data[0], "RIFF", 4))
295     return NULL;
296   if (strncmp (&data[8], "AVI ", 4))
297     return NULL;
298
299   new = GST_CAPS_NEW ("avi_typefind",
300       "video/avi", "RIFF", GST_PROPS_STRING ("AVI"));
301
302   return new;
303 }
304
305 static void
306 gst_avi_decoder_get_property (GObject * object, guint prop_id, GValue * value,
307     GParamSpec * pspec)
308 {
309   GstAviDecoder *src;
310
311   g_return_if_fail (GST_IS_AVI_DECODER (object));
312
313   src = GST_AVI_DECODER (object);
314
315   switch (prop_id) {
316     case ARG_BITRATE:
317       break;
318     case ARG_MEDIA_TIME:
319       g_value_set_long (value, gst_util_get_long_arg (G_OBJECT (src->demuxer),
320               "media_time"));
321       break;
322     case ARG_CURRENT_TIME:
323       g_value_set_long (value, gst_util_get_long_arg (G_OBJECT (src->demuxer),
324               "current_time"));
325       break;
326     default:
327       break;
328   }
329 }
330
331
332 static gboolean
333 plugin_init (GModule * module, GstPlugin * plugin)
334 {
335   GstElementFactory *factory;
336   GstTypeFactory *type;
337
338   /* create an elementfactory for the avi_decoder element */
339   factory = gst_elementfactory_new ("avidecoder", GST_TYPE_AVI_DECODER,
340       &gst_avi_decoder_details);
341   g_return_val_if_fail (factory != NULL, FALSE);
342
343   gst_elementfactory_add_padtemplate (factory,
344       GST_PADTEMPLATE_GET (src_audio_templ));
345   gst_elementfactory_add_padtemplate (factory,
346       GST_PADTEMPLATE_GET (src_video_templ));
347   gst_elementfactory_add_padtemplate (factory,
348       GST_PADTEMPLATE_GET (sink_templ));
349
350   type = gst_typefactory_new (&avidefinition);
351   gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (type));
352
353   gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
354
355   return TRUE;
356 }
357
358 GstPluginDesc plugin_desc = {
359   GST_VERSION_MAJOR,
360   GST_VERSION_MINOR,
361   "avidecoder",
362   plugin_init
363 };