various: fix pad template leaks
[platform/upstream/gstreamer.git] / ext / libmng / gstmngdec.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  *
4  * This library is distributed in the hope that it will be useful,
5  * but WITHOUT ANY WARRANTY; without even the implied warranty of
6  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
7  * Library General Public License for more details.
8  *
9  * You should have received a copy of the GNU Library General Public
10  * License along with this library; if not, write to the
11  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
12  * Boston, MA 02111-1307, USA.
13  *
14  */
15
16 #ifdef HAVE_CONFIG_H
17 #include "config.h"
18 #endif
19 #include <string.h>
20 #include <gst/gst.h>
21 #include "gstmngdec.h"
22 #include <gst/video/video.h>
23
24 /* Filter signals and args */
25 enum
26 {
27   /* FILL ME */
28   LAST_SIGNAL
29 };
30
31 enum
32 {
33   PROP_0
34 };
35
36 static GstStaticPadTemplate gst_mng_dec_src_pad_template =
37     GST_STATIC_PAD_TEMPLATE ("src",
38     GST_PAD_SRC,
39     GST_PAD_ALWAYS,
40     GST_STATIC_CAPS (GST_VIDEO_CAPS_RGBA ";" GST_VIDEO_CAPS_RGB)
41     );
42
43 static GstStaticPadTemplate gst_mng_dec_sink_pad_template =
44 GST_STATIC_PAD_TEMPLATE ("sink",
45     GST_PAD_SINK,
46     GST_PAD_ALWAYS,
47     GST_STATIC_CAPS ("video/x-mng, "
48         "width = (int) [ 16, 4096 ], "
49         "height = (int) [ 16, 4096 ], " "framerate = (double) [ 0.0, MAX ]")
50     );
51
52 static void gst_mng_dec_get_property (GObject * object,
53     guint prop_id, GValue * value, GParamSpec * pspec);
54 static void gst_mng_dec_set_property (GObject * object,
55     guint prop_id, const GValue * value, GParamSpec * pspec);
56
57 static GstStateChangeReturn gst_mng_dec_change_state (GstElement * element,
58     GstStateChange transition);
59
60 static gboolean gst_mng_dec_sink_event (GstPad * pad, GstEvent * event);
61
62 GST_BOILERPLATE (GstMngDec, gst_mng_dec, GstElement, GST_TYPE_ELEMENT);
63
64 static void
65 gst_mng_dec_base_init (gpointer g_class)
66 {
67   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
68
69   gst_element_class_add_static_pad_template (element_class,
70       &gst_mng_dec_src_pad_template);
71   gst_element_class_add_static_pad_template (element_class,
72       &gst_mng_dec_sink_pad_template);
73   gst_element_class_set_details_simple (element_class, "MNG video decoder",
74       "Codec/Decoder/Video",
75       "Decode a mng video to raw images", "Wim Taymans <wim@fluendo.com>");
76 }
77
78 static void
79 gst_mng_dec_class_init (GstMngDecClass * klass)
80 {
81   GObjectClass *gobject_class;
82   GstElementClass *gstelement_class;
83
84   gobject_class = (GObjectClass *) klass;
85   gstelement_class = (GstElementClass *) klass;
86
87   gobject_class->get_property = gst_mng_dec_get_property;
88   gobject_class->set_property = gst_mng_dec_set_property;
89
90   gstelement_class->change_state = gst_mng_dec_change_state;
91 }
92
93 static gboolean
94 gst_mng_dec_sink_setcaps (GstPad * pad, GstCaps * caps)
95 {
96   GstMngDec *mngdec;
97   GstStructure *structure;
98
99   mngdec = GST_MNG_DEC (gst_pad_get_parent (pad));
100
101   structure = gst_caps_get_structure (caps, 0);
102   gst_structure_get_double (structure, "framerate", &mngdec->fps);
103
104   gst_object_unref (mngdec);
105
106   return TRUE;
107 }
108
109 static void
110 gst_mng_dec_init (GstMngDec * mngdec, GstMngDecClass * gclass)
111 {
112   mngdec->sinkpad =
113       gst_pad_new_from_static_template (&gst_mng_dec_sink_pad_template, "sink");
114   gst_element_add_pad (GST_ELEMENT (mngdec), mngdec->sinkpad);
115
116   mngdec->srcpad =
117       gst_pad_new_from_static_template (&gst_mng_dec_src_pad_template, "src");
118   gst_element_add_pad (GST_ELEMENT (mngdec), mngdec->srcpad);
119
120   gst_pad_set_setcaps_function (mngdec->sinkpad, gst_mng_dec_sink_setcaps);
121   gst_pad_set_event_function (mngdec->sinkpad, gst_mng_dec_sink_event);
122   //gst_pad_set_getcaps_function (mngdec->srcpad, gst_mng_dec_src_getcaps);
123
124   mngdec->mng = NULL;
125   mngdec->buffer_out = NULL;
126
127   mngdec->color_type = -1;
128   mngdec->width = -1;
129   mngdec->height = -1;
130   mngdec->fps = -1;
131 }
132
133 #if 0
134 static GstCaps *
135 gst_mng_dec_src_getcaps (GstPad * pad)
136 {
137   GstMngDec *mngdec;
138   GstCaps *caps;
139   gint i;
140   GstPadTemplate *templ;
141   GstCaps *inter;
142
143   mngdec = GST_MNG_DEC (gst_pad_get_parent (pad));
144   templ = gst_static_pad_template_get (&gst_mng_dec_src_pad_template);
145   caps = gst_caps_copy (gst_pad_template_get_caps (templ));
146
147   if (mngdec->color_type != -1) {
148     GstCaps *to_inter = NULL;
149
150     switch (mngdec->color_type) {
151       case MNG_COLORTYPE_RGB:
152         to_inter = gst_caps_new_simple ("video/x-raw-rgb",
153             "bpp", G_TYPE_INT, 24, NULL);
154         break;
155       case MNG_COLORTYPE_RGBA:
156         to_inter = gst_caps_new_simple ("video/x-raw-rgb",
157             "bpp", G_TYPE_INT, 32, NULL);
158         break;
159       case MNG_COLORTYPE_GRAY:
160       case MNG_COLORTYPE_INDEXED:
161       case MNG_COLORTYPE_GRAYA:
162       default:
163         GST_ELEMENT_ERROR (mngdec, STREAM, NOT_IMPLEMENTED, (NULL),
164             ("mngdec does not support grayscale or paletted data yet"));
165         break;
166     }
167     inter = gst_caps_intersect (caps, to_inter);
168     gst_caps_free (caps);
169     gst_caps_free (to_inter);
170     caps = inter;
171   }
172
173   for (i = 0; i < gst_caps_get_size (caps); i++) {
174     GstStructure *structure = gst_caps_get_structure (caps, i);
175
176     if (mngdec->width != -1) {
177       gst_structure_set (structure, "width", G_TYPE_INT, mngdec->width, NULL);
178     }
179
180     if (mngdec->height != -1) {
181       gst_structure_set (structure, "height", G_TYPE_INT, mngdec->height, NULL);
182     }
183
184     if (mngdec->fps != -1) {
185       gst_structure_set (structure,
186           "framerate", G_TYPE_DOUBLE, mngdec->fps, NULL);
187     }
188   }
189
190   gst_object_unref (mngdec);
191   gst_object_unref (templ);
192
193   return caps;
194 }
195 #endif
196
197 #if 0
198 static void
199 gst_mng_dec_loop (GstElement * element)
200 {
201   GstMngDec *mngdec;
202   mng_retcode ret;
203
204   mngdec = GST_MNG_DEC (element);
205
206   if (mngdec->first) {
207     GST_DEBUG ("display");
208     ret = mng_readdisplay (mngdec->mng);
209     mngdec->first = FALSE;
210   } else {
211     GST_DEBUG ("resume");
212     ret = mng_display_resume (mngdec->mng);
213   }
214   if (ret == MNG_NEEDTIMERWAIT) {
215     /* libmng needs more data later on */
216   } else {
217     /* assume EOS here */
218     gst_pad_push_event (mngdec->srcpad, (gst_event_new_eos ()));
219   }
220 }
221 #endif
222
223 static void
224 gst_mng_dec_get_property (GObject * object,
225     guint prop_id, GValue * value, GParamSpec * pspec)
226 {
227   GstMngDec *mngdec;
228
229   mngdec = GST_MNG_DEC (object);
230
231   switch (prop_id) {
232     default:
233       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
234       break;
235   }
236 }
237
238
239 static void
240 gst_mng_dec_set_property (GObject * object,
241     guint prop_id, const GValue * value, GParamSpec * pspec)
242 {
243   GstMngDec *mngdec;
244
245   mngdec = GST_MNG_DEC (object);
246
247   switch (prop_id) {
248     default:
249       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
250       break;
251   }
252 }
253
254 static mng_bool
255 mngdec_error (mng_handle mng, mng_int32 code, mng_int8 severity,
256     mng_chunkid chunktype, mng_uint32 chunkseq,
257     mng_int32 extra1, mng_int32 extra2, mng_pchar text)
258 {
259   GstMngDec *mngdec;
260
261   mngdec = GST_MNG_DEC (mng_get_userdata (mng));
262
263   GST_ERROR_OBJECT (mngdec, "error in chunk %4.4s (%d): %s",
264       (gchar *) & chunktype, chunkseq, text);
265
266   return FALSE;
267 }
268
269 static mng_bool
270 mngdec_openstream (mng_handle mng)
271 {
272   GstMngDec *mngdec;
273
274   mngdec = GST_MNG_DEC (mng_get_userdata (mng));
275
276   return MNG_TRUE;
277 }
278
279 static mng_bool
280 mngdec_closestream (mng_handle mng)
281 {
282   GstMngDec *mngdec;
283
284   mngdec = GST_MNG_DEC (mng_get_userdata (mng));
285
286   return MNG_TRUE;
287 }
288
289 static gboolean
290 gst_mng_dec_sink_event (GstPad * pad, GstEvent * event)
291 {
292   GstEventType type;
293   GstMngDec *mngdec;
294
295   mngdec = GST_MNG_DEC_CAST (gst_pad_get_parent (pad));
296
297   type = GST_EVENT_TYPE (event);
298
299   GST_DEBUG_OBJECT (mngdec, "mngdec: event %p %d", event, type);
300
301   switch (type) {
302     case GST_EVENT_EOS:
303       break;
304     case GST_EVENT_FLUSH_START:
305       break;
306     case GST_EVENT_FLUSH_STOP:
307       break;
308     case GST_EVENT_NEWSEGMENT:
309       break;
310     default:
311       break;
312   }
313   gst_event_unref (event);
314
315   return TRUE;
316 }
317
318 static mng_bool
319 mngdec_readdata (mng_handle mng, mng_ptr buffer,
320     mng_uint32 size, mng_uint32 * bytesread)
321 {
322   GstMngDec *mngdec;
323 #if 0
324   guint8 *bytes;
325   guint32 read;
326 #endif
327
328   mngdec = GST_MNG_DEC (mng_get_userdata (mng));
329
330   GST_DEBUG ("read data %d", size);
331
332 #if 0
333   do {
334     read = gst_bytestream_peek_bytes (mngdec->bs, &bytes, size);
335     if (read != size) {
336       if (!mngdec_handle_sink_event (mngdec)) {
337         /* EOS */
338         *bytesread = 0;
339         return MNG_FALSE;
340       }
341     } else {
342       break;
343     }
344   } while (TRUE);
345
346   memcpy (buffer, bytes, size);
347   gst_bytestream_flush_fast (mngdec->bs, read);
348   *bytesread = size;
349 #endif
350
351   return MNG_TRUE;
352 }
353
354 static mng_uint32
355 mngdec_gettickcount (mng_handle mng)
356 {
357   GTimeVal time;
358   guint32 val;
359
360   g_get_current_time (&time);
361
362   val = time.tv_sec * 1000 + time.tv_usec;
363   GST_DEBUG ("get tick count %d", val);
364
365   return val;
366 }
367
368 static mng_bool
369 mngdec_settimer (mng_handle mng, mng_uint32 msecs)
370 {
371   GstMngDec *mngdec;
372
373   mngdec = GST_MNG_DEC (mng_get_userdata (mng));
374   //mymng->delay = msecs;
375   GST_DEBUG ("set timer %d", msecs);
376
377   return MNG_TRUE;
378 }
379
380 static mng_bool
381 mngdec_processheader (mng_handle mng, mng_uint32 width, mng_uint32 height)
382 {
383   GstMngDec *mngdec;
384   guint32 playtime;
385   guint32 framecount;
386   guint32 ticks;
387
388   mngdec = GST_MNG_DEC (mng_get_userdata (mng));
389
390   GST_DEBUG ("process header %d %d", width, height);
391
392   playtime = mng_get_playtime (mng);
393   framecount = mng_get_framecount (mng);
394   ticks = mng_get_ticks (mng);
395
396   if (playtime == 0) {
397     mngdec->fps = ticks;
398   } else {
399     mngdec->fps = ((gfloat) ticks) / playtime;
400   }
401
402   if (mngdec->width != width || mngdec->height != height) {
403     mngdec->width = width;
404     mngdec->stride = ((width + 3) & ~3) * 4;
405     mngdec->height = height;
406
407 #if 0
408     if (GST_PAD_LINK_FAILED (gst_pad_renegotiate (mngdec->srcpad))) {
409       GST_ELEMENT_ERROR (mngdec, CORE, NEGOTIATION, (NULL), (NULL));
410       return MNG_FALSE;
411     }
412 #endif
413
414     mngdec->buffer_out =
415         gst_buffer_new_and_alloc (mngdec->height * mngdec->stride);
416   }
417   return MNG_TRUE;
418 }
419
420 static mng_ptr
421 mngdec_getcanvasline (mng_handle mng, mng_uint32 line)
422 {
423   GstMngDec *mngdec;
424
425   mngdec = GST_MNG_DEC (mng_get_userdata (mng));
426
427   GST_DEBUG ("get canvas line %d", line);
428
429   return (mng_ptr) (GST_BUFFER_DATA (mngdec->buffer_out) +
430       (line * mngdec->stride));
431 }
432
433 static mng_bool
434 mngdec_refresh (mng_handle mng, mng_uint32 x, mng_uint32 y,
435     mng_uint32 w, mng_uint32 h)
436 {
437   GstMngDec *mngdec;
438   guint32 current;
439
440   mngdec = GST_MNG_DEC (mng_get_userdata (mng));
441
442   current = mng_get_currentplaytime (mng);
443
444   GST_DEBUG ("refresh %d %d %d %d", x, y, w, h);
445   if (h == mngdec->height) {
446     GstBuffer *out = gst_buffer_copy (mngdec->buffer_out);
447
448     gst_pad_push (mngdec->srcpad, out);
449   }
450
451   return MNG_TRUE;
452 }
453
454 static GstStateChangeReturn
455 gst_mng_dec_change_state (GstElement * element, GstStateChange transition)
456 {
457   GstStateChangeReturn ret;
458   GstMngDec *mngdec = GST_MNG_DEC (element);
459
460   switch (transition) {
461     case GST_STATE_CHANGE_NULL_TO_READY:
462       /* init library, make sure to pass an alloc function that sets the
463        * memory to 0 */
464       mngdec->mng =
465           mng_initialize (mngdec, (mng_memalloc) g_malloc0,
466           (mng_memfree) g_free, MNG_NULL);
467       if (mngdec->mng == MNG_NULL) {
468         return GST_STATE_CHANGE_FAILURE;
469       }
470       /* set the callbacks */
471       mng_setcb_errorproc (mngdec->mng, mngdec_error);
472       mng_setcb_openstream (mngdec->mng, mngdec_openstream);
473       mng_setcb_closestream (mngdec->mng, mngdec_closestream);
474       mng_setcb_readdata (mngdec->mng, mngdec_readdata);
475       mng_setcb_gettickcount (mngdec->mng, mngdec_gettickcount);
476       mng_setcb_settimer (mngdec->mng, mngdec_settimer);
477       mng_setcb_processheader (mngdec->mng, mngdec_processheader);
478       mng_setcb_getcanvasline (mngdec->mng, mngdec_getcanvasline);
479       mng_setcb_refresh (mngdec->mng, mngdec_refresh);
480       mng_set_canvasstyle (mngdec->mng, MNG_CANVAS_RGBA8);
481       mng_set_doprogressive (mngdec->mng, MNG_FALSE);
482       break;
483     case GST_STATE_CHANGE_READY_TO_PAUSED:
484       mngdec->first = TRUE;
485       break;
486     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
487       break;
488     default:
489       break;
490   }
491
492   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
493
494   switch (transition) {
495     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
496       break;
497     case GST_STATE_CHANGE_PAUSED_TO_READY:
498       break;
499     case GST_STATE_CHANGE_READY_TO_NULL:
500       mng_cleanup (&mngdec->mng);
501       break;
502     default:
503       break;
504   }
505   return ret;
506 }