close #333784 unref the result of gst_pad_get_parent() by: Christophe Fergeau.
[platform/upstream/gstreamer.git] / ext / speex / gstspeexdec.c
1 /* GStreamer
2  * Copyright (C) 2004 Wim Taymans <wim@fluendo.com>
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 #ifdef HAVE_CONFIG_H
21 #  include "config.h"
22 #endif
23
24 #include "gstspeexdec.h"
25 #include <string.h>
26 //#include <gst/tag/tag.h>
27
28 GST_DEBUG_CATEGORY (speexdec_debug);
29 #define GST_CAT_DEFAULT speexdec_debug
30
31 static GstElementDetails speex_dec_details = {
32   "SpeexDec",
33   "Codec/Decoder/Audio",
34   "decode speex streams to audio",
35   "Wim Taymans <wim@fluendo.com>",
36 };
37
38 #define DEFAULT_ENH             TRUE
39
40 enum
41 {
42   ARG_0,
43   ARG_ENH
44 };
45
46 static GstStaticPadTemplate speex_dec_src_factory =
47 GST_STATIC_PAD_TEMPLATE ("src",
48     GST_PAD_SRC,
49     GST_PAD_ALWAYS,
50     GST_STATIC_CAPS ("audio/x-raw-int, "
51         "rate = (int) [ 6000, 48000 ], "
52         "channels = (int) [ 1, 2 ], "
53         "endianness = (int) BYTE_ORDER, "
54         "signed = (boolean) true, " "width = (int) 16, " "depth = (int) 16")
55     );
56
57 static GstStaticPadTemplate speex_dec_sink_factory =
58 GST_STATIC_PAD_TEMPLATE ("sink",
59     GST_PAD_SINK,
60     GST_PAD_ALWAYS,
61     GST_STATIC_CAPS ("audio/x-speex")
62     );
63
64 GST_BOILERPLATE (GstSpeexDec, gst_speex_dec, GstElement, GST_TYPE_ELEMENT);
65
66 static gboolean speex_dec_event (GstPad * pad, GstEvent * event);
67 static GstFlowReturn speex_dec_chain (GstPad * pad, GstBuffer * buf);
68 static GstStateChangeReturn speex_dec_change_state (GstElement * element,
69     GstStateChange transition);
70
71 static gboolean speex_dec_src_event (GstPad * pad, GstEvent * event);
72 static gboolean speex_dec_src_query (GstPad * pad, GstQuery * query);
73 static gboolean speex_dec_convert (GstPad * pad,
74     GstFormat src_format, gint64 src_value,
75     GstFormat * dest_format, gint64 * dest_value);
76
77 static void gst_speexdec_get_property (GObject * object, guint prop_id,
78     GValue * value, GParamSpec * pspec);
79 static void gst_speexdec_set_property (GObject * object, guint prop_id,
80     const GValue * value, GParamSpec * pspec);
81
82 static void
83 gst_speex_dec_base_init (gpointer g_class)
84 {
85   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
86
87   gst_element_class_add_pad_template (element_class,
88       gst_static_pad_template_get (&speex_dec_src_factory));
89   gst_element_class_add_pad_template (element_class,
90       gst_static_pad_template_get (&speex_dec_sink_factory));
91   gst_element_class_set_details (element_class, &speex_dec_details);
92 }
93
94 static void
95 gst_speex_dec_class_init (GstSpeexDecClass * klass)
96 {
97   GObjectClass *gobject_class;
98   GstElementClass *gstelement_class;
99
100   gobject_class = (GObjectClass *) klass;
101   gstelement_class = (GstElementClass *) klass;
102
103   gobject_class->set_property = gst_speexdec_set_property;
104   gobject_class->get_property = gst_speexdec_get_property;
105
106   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ENH,
107       g_param_spec_boolean ("enh", "Enh", "Enable perceptual enhancement",
108           DEFAULT_ENH, G_PARAM_READWRITE));
109
110   gstelement_class->change_state = speex_dec_change_state;
111
112   GST_DEBUG_CATEGORY_INIT (speexdec_debug, "speexdec", 0,
113       "speex decoding element");
114 }
115
116 static const GstQueryType *
117 speex_get_query_types (GstPad * pad)
118 {
119   static const GstQueryType speex_dec_src_query_types[] = {
120     GST_QUERY_POSITION,
121     GST_QUERY_DURATION,
122     0
123   };
124
125   return speex_dec_src_query_types;
126 }
127
128 static void
129 gst_speex_dec_init (GstSpeexDec * dec, GstSpeexDecClass * g_class)
130 {
131   dec->sinkpad =
132       gst_pad_new_from_template (gst_static_pad_template_get
133       (&speex_dec_sink_factory), "sink");
134   gst_pad_set_chain_function (dec->sinkpad, speex_dec_chain);
135   gst_pad_set_event_function (dec->sinkpad, speex_dec_event);
136   gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad);
137
138   dec->srcpad =
139       gst_pad_new_from_template (gst_static_pad_template_get
140       (&speex_dec_src_factory), "src");
141   gst_pad_use_fixed_caps (dec->srcpad);
142   gst_pad_set_event_function (dec->srcpad, speex_dec_src_event);
143   gst_pad_set_query_type_function (dec->srcpad, speex_get_query_types);
144   gst_pad_set_query_function (dec->srcpad, speex_dec_src_query);
145   gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
146
147   dec->enh = DEFAULT_ENH;
148 }
149
150 static gboolean
151 speex_dec_convert (GstPad * pad,
152     GstFormat src_format, gint64 src_value,
153     GstFormat * dest_format, gint64 * dest_value)
154 {
155   gboolean res = TRUE;
156   GstSpeexDec *dec;
157   guint64 scale = 1;
158
159   dec = GST_SPEEXDEC (gst_pad_get_parent (pad));
160
161   if (dec->packetno < 1) {
162     res = FALSE;
163     goto cleanup;
164   }
165
166   if (pad == dec->sinkpad &&
167       (src_format == GST_FORMAT_BYTES || *dest_format == GST_FORMAT_BYTES)) {
168     res = FALSE;
169     goto cleanup;
170   }
171
172   switch (src_format) {
173     case GST_FORMAT_TIME:
174       switch (*dest_format) {
175         case GST_FORMAT_BYTES:
176           scale = sizeof (float) * dec->header->nb_channels;
177         case GST_FORMAT_DEFAULT:
178           *dest_value = scale * (src_value * dec->header->rate / GST_SECOND);
179           break;
180         default:
181           res = FALSE;
182       }
183       break;
184     case GST_FORMAT_DEFAULT:
185       switch (*dest_format) {
186         case GST_FORMAT_BYTES:
187           *dest_value = src_value * sizeof (float) * dec->header->nb_channels;
188           break;
189         case GST_FORMAT_TIME:
190           *dest_value = src_value * GST_SECOND / dec->header->rate;
191           break;
192         default:
193           res = FALSE;
194       }
195       break;
196     case GST_FORMAT_BYTES:
197       switch (*dest_format) {
198         case GST_FORMAT_DEFAULT:
199           *dest_value = src_value / (sizeof (float) * dec->header->nb_channels);
200           break;
201         case GST_FORMAT_TIME:
202           *dest_value = src_value * GST_SECOND /
203               (dec->header->rate * sizeof (float) * dec->header->nb_channels);
204           break;
205         default:
206           res = FALSE;
207       }
208       break;
209     default:
210       res = FALSE;
211   }
212
213 cleanup:
214   gst_object_unref (dec);
215   return res;
216 }
217
218 static gboolean
219 speex_dec_src_query (GstPad * pad, GstQuery * query)
220 {
221   GstSpeexDec *dec = GST_SPEEXDEC (GST_OBJECT_PARENT (pad));
222   gboolean res = FALSE;
223
224   switch (GST_QUERY_TYPE (query)) {
225     case GST_QUERY_POSITION:
226     {
227       gint64 cur;
228       GstFormat format;
229
230       gst_query_parse_position (query, &format, NULL);
231
232       if ((res = speex_dec_convert (dec->srcpad, GST_FORMAT_DEFAULT,
233                   dec->samples_out, &format, &cur))) {
234         gst_query_set_position (query, format, cur);
235       }
236       break;
237     }
238     case GST_QUERY_DURATION:
239     {
240       GstPad *peer;
241       GstFormat my_format = GST_FORMAT_TIME;
242       gint64 total_samples;
243
244       if (!(peer = gst_pad_get_peer (dec->sinkpad)))
245         break;
246
247       gst_pad_query_duration (peer, &my_format, &total_samples);
248       gst_object_unref (peer);
249
250       if ((res = speex_dec_convert (dec->srcpad, GST_FORMAT_DEFAULT,
251                   total_samples, &my_format, &total_samples))) {
252         gst_query_set_duration (query, GST_FORMAT_TIME, total_samples);
253       }
254       break;
255     }
256     default:
257       res = gst_pad_query_default (pad, query);
258       break;
259   }
260
261   return TRUE;
262 }
263
264 static gboolean
265 speex_dec_src_event (GstPad * pad, GstEvent * event)
266 {
267   gboolean res = TRUE;
268   GstSpeexDec *dec = GST_SPEEXDEC (gst_pad_get_parent (pad));
269
270   switch (GST_EVENT_TYPE (event)) {
271     case GST_EVENT_SEEK:{
272       gint64 cur, stop;
273       GstFormat format, my_format = GST_FORMAT_DEFAULT;
274       GstSeekType cur_type, stop_type;
275       GstSeekFlags flags;
276
277       gst_event_parse_seek (event, NULL, &format, &flags, &cur_type, &cur,
278           &stop_type, &stop);
279
280       /* convert to samples_out */
281       if (speex_dec_convert (pad, format, cur, &my_format, &cur) &&
282           (stop == -1 ||
283               speex_dec_convert (pad, format, stop, &my_format, &stop))) {
284         GstEvent *real_seek = gst_event_new_seek (1.0, GST_FORMAT_DEFAULT,
285             flags, cur_type, cur, stop_type, stop);
286
287         res = gst_pad_send_event (GST_PAD_PEER (dec->sinkpad), real_seek);
288       } else
289         res = FALSE;
290       gst_event_unref (event);
291       break;
292     }
293     default:
294       res = gst_pad_event_default (pad, event);
295       break;
296   }
297
298   gst_object_unref (dec);
299
300   return res;
301 }
302
303 static gboolean
304 speex_dec_event (GstPad * pad, GstEvent * event)
305 {
306   GstSpeexDec *dec = GST_SPEEXDEC (GST_OBJECT_PARENT (pad));
307   gint64 value, time;
308   GstFormat fmt;
309
310   GST_LOG_OBJECT (dec, "handling event");
311   switch (GST_EVENT_TYPE (event)) {
312     case GST_EVENT_NEWSEGMENT:
313       gst_event_parse_new_segment (event, NULL, NULL, &fmt, &value, NULL, NULL);
314       if (fmt == GST_FORMAT_DEFAULT) {
315         dec->samples_out = value;
316         GST_DEBUG_OBJECT (dec,
317             "setting samples_out to %" G_GUINT64_FORMAT " after discont",
318             value);
319       } else {
320         GST_WARNING_OBJECT (dec,
321             "discont event didn't include offset, we might set it wrong now");
322         value = 0;
323       }
324       if (dec->packetno < 2) {
325         if (dec->samples_out != 0)
326           GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL),
327               ("can't handle discont before parsing first 2 packets"));
328         dec->packetno = 0;
329         gst_pad_push_event (dec->srcpad,
330             gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
331                 0, GST_CLOCK_TIME_NONE, 0));
332       } else {
333         GstFormat time_format = GST_FORMAT_TIME;
334
335         dec->packetno = 2;
336         /* if one of them works, all of them work */
337         if (speex_dec_convert (dec->srcpad, GST_FORMAT_DEFAULT,
338                 dec->samples_out, &time_format, &time)) {
339           gst_pad_push_event (dec->srcpad,
340               gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
341                   time, GST_CLOCK_TIME_NONE, 0));
342         } else {
343           GST_ERROR_OBJECT (dec,
344               "failed to parse data for DISCONT event, not sending any");
345         }
346       }
347       gst_event_unref (event);
348       break;
349     default:
350       return gst_pad_event_default (dec->sinkpad, event);
351   }
352
353   return TRUE;
354 }
355
356 static GstFlowReturn
357 speex_dec_chain (GstPad * pad, GstBuffer * buf)
358 {
359   GstFlowReturn res;
360   GstSpeexDec *dec;
361   GstFlowReturn result;
362
363   dec = GST_SPEEXDEC (gst_pad_get_parent (pad));
364
365   if (dec->packetno == 0) {
366     GstCaps *caps;
367
368     /* get the header */
369     dec->header = speex_packet_to_header ((char *) GST_BUFFER_DATA (buf),
370         GST_BUFFER_SIZE (buf));
371     gst_buffer_unref (buf);
372     if (!dec->header) {
373       GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
374           (NULL), ("couldn't read header"));
375       result = GST_FLOW_ERROR;
376       goto cleanup;
377     }
378     if (dec->header->mode >= SPEEX_NB_MODES) {
379       GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
380           (NULL),
381           ("Mode number %d does not (yet/any longer) exist in this version",
382               dec->header->mode));
383       result = GST_FLOW_ERROR;
384       goto cleanup;
385     }
386
387     dec->mode = (SpeexMode *) speex_mode_list[dec->header->mode];
388
389     /* initialize the decoder */
390     dec->state = speex_decoder_init (dec->mode);
391     if (!dec->state) {
392       GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
393           (NULL), ("couldn't initialize decoder"));
394       gst_buffer_unref (buf);
395       result = GST_FLOW_ERROR;
396       goto cleanup;
397     }
398
399     speex_decoder_ctl (dec->state, SPEEX_SET_ENH, &dec->enh);
400     speex_decoder_ctl (dec->state, SPEEX_GET_FRAME_SIZE, &dec->frame_size);
401
402     if (dec->header->nb_channels != 1) {
403       dec->callback.callback_id = SPEEX_INBAND_STEREO;
404       dec->callback.func = speex_std_stereo_request_handler;
405       dec->callback.data = &dec->stereo;
406       speex_decoder_ctl (dec->state, SPEEX_SET_HANDLER, &dec->callback);
407     }
408
409     speex_decoder_ctl (dec->state, SPEEX_SET_SAMPLING_RATE, &dec->header->rate);
410
411     speex_bits_init (&dec->bits);
412
413     /* set caps */
414     caps = gst_caps_new_simple ("audio/x-raw-int",
415         "rate", G_TYPE_INT, dec->header->rate,
416         "channels", G_TYPE_INT, dec->header->nb_channels,
417         "signed", G_TYPE_BOOLEAN, TRUE,
418         "endianness", G_TYPE_INT, G_BYTE_ORDER,
419         "width", G_TYPE_INT, 16, "depth", G_TYPE_INT, 16, NULL);
420
421     if (!gst_pad_set_caps (dec->srcpad, caps)) {
422       gst_caps_unref (caps);
423       result = GST_FLOW_NOT_NEGOTIATED;
424       goto cleanup;
425     }
426     gst_caps_unref (caps);
427     gst_pad_push_event (dec->srcpad,
428         gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
429             0, GST_CLOCK_TIME_NONE, 0));
430   } else if (dec->packetno == 1) {
431     gchar *encoder = NULL;
432
433     /* FIXME parse comments */
434     GstTagList *list = gst_tag_list_new ();     //gst_tag_list_from_vorbiscomment_buffer (buf, "", 1,
435
436 //        &encoder);
437
438     gst_buffer_unref (buf);
439
440     if (!list) {
441       GST_WARNING_OBJECT (dec, "couldn't decode comments");
442       list = gst_tag_list_new ();
443     }
444     if (encoder) {
445       gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
446           GST_TAG_ENCODER, encoder, NULL);
447       g_free (encoder);
448     }
449     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
450         GST_TAG_AUDIO_CODEC, "Speex", NULL);
451     /*
452        gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
453        GST_TAG_ENCODER_VERSION, dec->vi.version, NULL);
454
455        if (dec->vi.bitrate_upper > 0)
456        gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
457        GST_TAG_MAXIMUM_BITRATE, (guint) vd->vi.bitrate_upper, NULL);
458        if (vd->vi.bitrate_nominal > 0)
459        gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
460        GST_TAG_NOMINAL_BITRATE, (guint) vd->vi.bitrate_nominal, NULL);
461        if (vd->vi.bitrate_lower > 0)
462        gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
463        GST_TAG_MINIMUM_BITRATE, (guint) vd->vi.bitrate_lower, NULL);
464      */
465     gst_element_found_tags_for_pad (GST_ELEMENT (dec), dec->srcpad, list);
466   } else {
467     gint i;
468
469     /* send data to the bitstream */
470     speex_bits_read_from (&dec->bits, (char *) GST_BUFFER_DATA (buf),
471         GST_BUFFER_SIZE (buf));
472     gst_buffer_unref (buf);
473
474     /* now decode each frame */
475     for (i = 0; i < dec->header->frames_per_packet; i++) {
476       gint ret;
477       GstBuffer *outbuf;
478       gint16 *out_data;
479
480       ret = speex_decode (dec->state, &dec->bits, dec->output);
481       if (ret == -1) {
482         /* uh? end of stream */
483         GST_WARNING_OBJECT (dec, "Unexpected end of stream found");
484         break;
485       } else if (ret == -2) {
486         GST_WARNING_OBJECT (dec, "Decoding error: corrupted stream?");
487         break;
488       }
489       if (speex_bits_remaining (&dec->bits) < 0) {
490         GST_WARNING_OBJECT (dec, "Decoding overflow: corrupted stream?");
491         break;
492       }
493       if (dec->header->nb_channels == 2)
494         speex_decode_stereo (dec->output, dec->frame_size, &dec->stereo);
495
496       if ((res =
497               gst_pad_alloc_buffer_and_set_caps (dec->srcpad,
498                   GST_BUFFER_OFFSET_NONE,
499                   dec->frame_size * dec->header->nb_channels * 2,
500                   GST_PAD_CAPS (dec->srcpad), &outbuf)) != GST_FLOW_OK)
501         return res;
502       out_data = (gint16 *) GST_BUFFER_DATA (outbuf);
503
504       /*PCM saturation (just in case) */
505       for (i = 0; i < dec->frame_size * dec->header->nb_channels; i++) {
506         if (dec->output[i] > 32767.0)
507           out_data[i] = 32767;
508         else if (dec->output[i] < -32768.0)
509           out_data[i] = -32768;
510         else
511           out_data[i] = (gint16) dec->output[i];
512       }
513
514       GST_BUFFER_OFFSET (outbuf) = dec->samples_out;
515       GST_BUFFER_OFFSET_END (outbuf) = dec->samples_out + dec->frame_size;
516       GST_BUFFER_TIMESTAMP (outbuf) =
517           dec->samples_out * GST_SECOND / dec->header->rate;
518       GST_BUFFER_DURATION (outbuf) =
519           dec->frame_size * GST_SECOND / dec->header->rate;
520       res = gst_pad_push (dec->srcpad, outbuf);
521       if (res != GST_FLOW_OK && res != GST_FLOW_NOT_LINKED)
522         return res;
523       dec->samples_out += dec->frame_size;
524     }
525   }
526   dec->packetno++;
527   result = GST_FLOW_OK;
528
529 cleanup:
530   gst_object_unref (dec);
531
532   return result;
533 }
534
535 static void
536 gst_speexdec_get_property (GObject * object, guint prop_id,
537     GValue * value, GParamSpec * pspec)
538 {
539   GstSpeexDec *speexdec;
540
541   g_return_if_fail (GST_IS_SPEEXDEC (object));
542
543   speexdec = GST_SPEEXDEC (object);
544
545   switch (prop_id) {
546     case ARG_ENH:
547       g_value_set_boolean (value, speexdec->enh);
548       break;
549     default:
550       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
551       break;
552   }
553 }
554
555 static void
556 gst_speexdec_set_property (GObject * object, guint prop_id,
557     const GValue * value, GParamSpec * pspec)
558 {
559   GstSpeexDec *speexdec;
560
561   g_return_if_fail (GST_IS_SPEEXDEC (object));
562
563   speexdec = GST_SPEEXDEC (object);
564
565   switch (prop_id) {
566     case ARG_ENH:
567       speexdec->enh = g_value_get_boolean (value);
568       break;
569     default:
570       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
571       break;
572   }
573 }
574
575
576 static GstStateChangeReturn
577 speex_dec_change_state (GstElement * element, GstStateChange transition)
578 {
579   GstSpeexDec *vd = GST_SPEEXDEC (element);
580
581   switch (transition) {
582     case GST_STATE_CHANGE_NULL_TO_READY:
583       break;
584     case GST_STATE_CHANGE_READY_TO_PAUSED:
585       break;
586     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
587       break;
588     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
589       break;
590     case GST_STATE_CHANGE_PAUSED_TO_READY:
591       vd->packetno = 0;
592       vd->samples_out = 0;
593       break;
594     case GST_STATE_CHANGE_READY_TO_NULL:
595       break;
596     default:
597       break;
598   }
599
600   return parent_class->change_state (element, transition);
601 }