GST_DEBUG reorganization containing loads of stuff:
[platform/upstream/gstreamer.git] / gst / gsttypefind.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wtay@chello.be>
4  *
5  * gsttypefind.c: 
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23
24 #include "gst_private.h"
25 #include "gsttype.h"
26 #include "gstinfo.h"
27 #include "gsttypefind.h"
28
29 #define DEFAULT_MAX_BUFFERS     1
30
31 GstElementDetails gst_type_find_details = {
32   "TypeFind",
33   "Generic",
34   "LGPL",
35   "Finds the media type of a stream",
36   VERSION,
37   "Erik Walthinsen <omega@cse.ogi.edu>,"
38   "Wim Taymans <wim.taymans@chello.be>",
39   "(C) 1999",
40 };
41
42
43 /* TypeFind signals and args */
44 enum {
45   HAVE_TYPE,
46   LAST_SIGNAL
47 };
48
49 enum {
50   ARG_0,
51   ARG_CAPS,
52   ARG_MAX_BUFFERS,
53 };
54
55
56 static void     gst_type_find_class_init        (GstTypeFindClass *klass);
57 static void     gst_type_find_init              (GstTypeFind *typefind);
58
59 static void     gst_type_find_set_property      (GObject *object, guint prop_id,
60                                                  const GValue *value, 
61                                                  GParamSpec *pspec);
62 static void     gst_type_find_get_property      (GObject *object, guint prop_id,
63                                                  GValue *value, 
64                                                  GParamSpec *pspec);
65
66 static void     gst_type_find_chain             (GstPad *pad, GstBuffer *buf);
67 static GstElementStateReturn
68                 gst_type_find_change_state      (GstElement *element);
69
70 static GstElementClass *parent_class = NULL;
71 static guint gst_type_find_signals[LAST_SIGNAL] = { 0 };
72
73 GType
74 gst_type_find_get_type (void)
75 {
76   static GType typefind_type = 0;
77
78   if (!typefind_type) {
79     static const GTypeInfo typefind_info = {
80       sizeof(GstTypeFindClass),
81       NULL,
82       NULL,
83       (GClassInitFunc)gst_type_find_class_init,
84       NULL,
85       NULL,
86       sizeof(GstTypeFind),
87       0,
88       (GInstanceInitFunc)gst_type_find_init,
89       NULL
90     };
91     typefind_type = g_type_register_static (GST_TYPE_ELEMENT, "GstTypeFind", &typefind_info, 0);
92   }
93   return typefind_type;
94 }
95
96 static void
97 gst_type_find_class_init (GstTypeFindClass *klass)
98 {
99   GObjectClass *gobject_class;
100   GstElementClass *gstelement_class;
101
102   gobject_class = (GObjectClass*)klass;
103   gstelement_class = (GstElementClass*)klass;
104
105   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
106
107   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_CAPS,
108     g_param_spec_pointer ("caps", "Caps", "Found capabilities", G_PARAM_READABLE));
109   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAX_BUFFERS,
110     g_param_spec_int ("max_buffers", 
111                       "Max Buffers", 
112                       "Maximal amount of buffers before giving en error (0 == unlimited)", 
113                       0, G_MAXINT, DEFAULT_MAX_BUFFERS, G_PARAM_READWRITE));
114
115   gst_type_find_signals[HAVE_TYPE] =
116       g_signal_new ("have_type", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
117                      G_STRUCT_OFFSET (GstTypeFindClass, have_type), NULL, NULL,
118                      g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1,
119                      G_TYPE_BOXED);
120
121   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_type_find_set_property);
122   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_type_find_get_property);
123
124   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_type_find_change_state);
125 }
126
127 static void
128 gst_type_find_init (GstTypeFind *typefind)
129 {
130   typefind->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
131   gst_element_add_pad (GST_ELEMENT (typefind), typefind->sinkpad);
132   gst_pad_set_chain_function (typefind->sinkpad, gst_type_find_chain);
133
134   typefind->num_buffer = 0;
135   typefind->max_buffers = DEFAULT_MAX_BUFFERS;
136   typefind->caps = NULL;
137 }
138
139 static void
140 gst_type_find_set_property (GObject *object, guint prop_id, 
141                             const GValue *value, GParamSpec *pspec)
142 {
143   GstTypeFind *typefind;
144
145   g_return_if_fail (GST_IS_TYPE_FIND (object));
146
147   typefind = GST_TYPE_FIND (object);
148
149   switch (prop_id) {
150     case ARG_MAX_BUFFERS:
151       typefind->max_buffers = g_value_get_int (value);
152       break;
153     default:
154       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
155       break;
156   }
157 }
158
159 static void
160 gst_type_find_get_property (GObject *object, guint prop_id, 
161                             GValue *value, GParamSpec *pspec)
162 {
163   GstTypeFind *typefind;
164
165   g_return_if_fail (GST_IS_TYPE_FIND (object));
166
167   typefind = GST_TYPE_FIND (object);
168
169   switch (prop_id) {
170     case ARG_CAPS:
171       g_value_set_pointer (value, typefind->caps);
172       break;
173     case ARG_MAX_BUFFERS:
174       g_value_set_int (value, typefind->max_buffers);
175       break;
176     default:
177       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
178       break;
179   }
180 }
181
182 static void
183 gst_type_find_chain (GstPad *pad, GstBuffer *buf)
184 {
185   GstTypeFind *typefind;
186   const GList *type_list;
187   GstType *type;
188
189   g_return_if_fail (GST_IS_PAD (pad));
190
191   typefind = GST_TYPE_FIND (GST_OBJECT_PARENT (pad));
192
193   GST_DEBUG ("got buffer of %d bytes in '%s'",
194         GST_BUFFER_SIZE (buf), GST_OBJECT_NAME (typefind));
195
196   type_list = gst_type_get_list ();
197
198   while (type_list) {
199     GSList *factories;
200     type = (GstType *) type_list->data;
201
202     factories = type->factories;
203
204     while (factories) {
205       GstTypeFactory *factory = GST_TYPE_FACTORY (factories->data);
206       GstTypeFindFunc typefindfunc = (GstTypeFindFunc)factory->typefindfunc;
207       GstCaps *caps;
208
209       GST_CAT_DEBUG (GST_CAT_TYPES, "try type (%p) :%d \"%s\" %p", 
210                  factory, type->id, type->mime, typefindfunc);
211       if (typefindfunc && (caps = typefindfunc (buf, factory))) {
212         GST_CAT_DEBUG (GST_CAT_TYPES, "found type: %d \"%s\" \"%s\"", 
213                    caps->id, type->mime, gst_caps_get_name (caps));
214         typefind->caps = caps;
215
216         if (gst_pad_try_set_caps (pad, caps) <= 0) {
217           g_warning ("typefind: found type but peer didn't accept it");
218         }
219
220         {
221           gst_object_ref (GST_OBJECT (typefind));
222           g_signal_emit (G_OBJECT (typefind), gst_type_find_signals[HAVE_TYPE], 0,
223                               typefind->caps);
224           gst_object_unref (GST_OBJECT (typefind));
225           goto end;
226         }
227       }
228       factories = g_slist_next (factories);
229     }
230     type_list = g_list_next (type_list);
231   }
232
233   typefind->num_buffer++;
234
235 end:
236   gst_buffer_unref (buf);
237
238   if (typefind->max_buffers && typefind->num_buffer >= typefind->max_buffers) {
239     gst_element_error (GST_ELEMENT (typefind), 
240                     "typefind could not determine type after %d buffers", typefind->num_buffer);
241   }
242 }
243
244 static GstElementStateReturn
245 gst_type_find_change_state (GstElement *element)
246 {
247   GstTypeFind *typefind;
248   GstElementStateReturn ret;
249
250   typefind = GST_TYPE_FIND (element);
251
252   switch (GST_STATE_TRANSITION (element)) {
253     case GST_STATE_NULL_TO_READY:
254       break;
255     case GST_STATE_READY_TO_PAUSED:
256       typefind->num_buffer = 0;
257       gst_caps_unref (typefind->caps);
258       typefind->caps = NULL;
259       break;
260     case GST_STATE_PAUSED_TO_PLAYING:
261     case GST_STATE_PLAYING_TO_PAUSED:
262     case GST_STATE_PAUSED_TO_READY:
263     case GST_STATE_READY_TO_NULL:
264       break;
265   }
266   
267   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element);
268   
269   return ret;
270 }