s/Gnome-Streamer/GStreamer/
[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"
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   /* brin the element to the READY state so it can do our caps negotiation */
219   gst_element_set_state (type, GST_STATE_READY);
220
221   gst_pad_connect (pad, gst_element_get_pad (type, "sink"));
222   type_found = gst_util_get_bool_arg (G_OBJECT (type), "type_found");
223
224   if (type_found) {
225
226     gst_bin_add (GST_BIN (avi_decoder), type);
227     
228     pad = gst_element_get_pad (type, "src");
229     caps = gst_pad_get_caps (pad);
230
231     if (gst_caps_check_compatibility (caps, targetcaps)) {
232       gst_element_add_ghost_pad (GST_ELEMENT (avi_decoder), 
233             gst_element_get_pad (type, "src"), gpadname);
234
235       avi_decoder->count++;
236       goto done;
237     }
238 #ifndef GST_DISABLE_AUTOPLUG
239     else {
240       GstAutoplug *autoplug;
241       autoplug = gst_autoplugfactory_make("static");
242
243       new_element = gst_autoplug_to_caps (autoplug, caps, targetcaps, NULL);
244
245       padname = "src_00";
246     }
247 #endif /* GST_DISABLE_AUTOPLUG */
248   }
249
250   if (!new_element && (media_type == AVI_TYPE_VIDEO)) {
251     padname = "src";
252   }
253   else if (!new_element && (media_type == AVI_TYPE_AUDIO)) {
254     /*FIXME */
255     padname = "src";
256   }
257
258   if (new_element) {
259     gst_pad_connect (pad, gst_element_get_pad (new_element, "sink"));
260     gst_element_set_name (new_element, g_strdup_printf ("element%d", avi_decoder->count));
261     gst_bin_add (GST_BIN (avi_decoder), new_element);
262
263     gst_element_add_ghost_pad (GST_ELEMENT (avi_decoder), 
264             gst_element_get_pad (new_element, padname), gpadname);
265
266     avi_decoder->count++;
267   }
268   else {
269     g_warning ("avidecoder: could not autoplug\n");
270   }
271
272 done: 
273   gst_element_set_state (GST_ELEMENT (avi_decoder), GST_STATE_PLAYING);
274 }
275
276 static void 
277 gst_avi_decoder_init (GstAviDecoder *avi_decoder) 
278 {
279   avi_decoder->demuxer = gst_elementfactory_make ("avidemux", "demux");
280
281   if (avi_decoder->demuxer) {
282     gst_bin_add (GST_BIN (avi_decoder), avi_decoder->demuxer);
283
284     gst_element_add_ghost_pad (GST_ELEMENT (avi_decoder), 
285                     gst_element_get_pad (avi_decoder->demuxer, "sink"), "sink");
286
287     g_signal_connect (G_OBJECT (avi_decoder->demuxer),"new_pad", G_CALLBACK (gst_avi_decoder_new_pad),
288                     avi_decoder);
289   }
290   else {
291     g_warning ("wow!, no avi demuxer found. help me\n");
292   }
293
294   avi_decoder->count = 0;
295   avi_decoder->audio_count = 0;
296   avi_decoder->video_count = 0;
297 }
298
299 static GstCaps*
300 avi_typefind (GstBuffer *buf,
301               gpointer private)
302 {
303   gchar *data = GST_BUFFER_DATA (buf);
304   GstCaps *new;
305
306   GST_DEBUG (0,"avi_decoder: typefind\n");
307   if (strncmp (&data[0], "RIFF", 4)) return NULL;
308   if (strncmp (&data[8], "AVI ", 4)) return NULL;
309
310   new = GST_CAPS_NEW ("avi_typefind",
311                       "video/avi", 
312                         "RIFF", GST_PROPS_STRING ("AVI"));
313
314   return new;
315 }
316
317 static void
318 gst_avi_decoder_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
319 {
320   GstAviDecoder *src;
321
322   g_return_if_fail (GST_IS_AVI_DECODER (object));
323
324   src = GST_AVI_DECODER (object);
325
326   switch(prop_id) {
327     case ARG_BITRATE:
328       break;
329     case ARG_MEDIA_TIME:
330       g_value_set_long (value, gst_util_get_long_arg (G_OBJECT (src->demuxer), "media_time"));
331       break;
332     case ARG_CURRENT_TIME:
333       g_value_set_long (value, gst_util_get_long_arg (G_OBJECT (src->demuxer), "current_time"));
334       break;
335     default:
336       break;
337   }
338 }
339
340
341 static gboolean
342 plugin_init (GModule *module, GstPlugin *plugin)
343 {
344   GstElementFactory *factory;
345   GstTypeFactory *type;
346
347   /* create an elementfactory for the avi_decoder element */
348   factory = gst_elementfactory_new ("avidecoder", GST_TYPE_AVI_DECODER,
349                                     &gst_avi_decoder_details);
350   g_return_val_if_fail (factory != NULL, FALSE);
351
352   gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (src_audio_templ));
353   gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (src_video_templ));
354   gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (sink_templ));
355
356   type = gst_typefactory_new (&avidefinition);
357   gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (type));
358
359   gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
360
361   return TRUE;
362 }
363
364 GstPluginDesc plugin_desc = {
365   GST_VERSION_MAJOR,
366   GST_VERSION_MINOR,
367   "avidecoder",
368   plugin_init
369 };
370