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