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