]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/gst-plugins-ugly0-10.git/blob - ext/a52dec/gsta52dec.c
Update for alloc_buffer changes.
[glsdk/gst-plugins-ugly0-10.git] / ext / a52dec / gsta52dec.c
1 /* GStreamer
2  * Copyright (C) <2001> David I. Lehn <dlehn@users.sourceforge.net>
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  */
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
24 #include <string.h>
26 #include <stdlib.h>
27 #include "_stdint.h"
29 #include <gst/gst.h>
30 #include <gst/audio/multichannel.h>
32 #include <a52dec/a52.h>
33 #include <a52dec/mm_accel.h>
34 #include "gsta52dec.h"
36 #include <liboil/liboil.h>
37 #include <liboil/liboilcpu.h>
38 #include <liboil/liboilfunction.h>
40 /* elementfactory information */
41 static GstElementDetails gst_a52dec_details = {
42   "ATSC A/52 audio decoder",
43   "Codec/Decoder/Audio",
44   "Decodes ATSC A/52 encoded audio streams",
45   "David I. Lehn <dlehn@users.sourceforge.net>",
46 };
48 #ifdef LIBA52_DOUBLE
49 #define SAMPLE_WIDTH 64
50 #else
51 #define SAMPLE_WIDTH 32
52 #endif
54 GST_DEBUG_CATEGORY_STATIC (a52dec_debug);
55 #define GST_CAT_DEFAULT (a52dec_debug)
57 /* A52Dec args */
58 enum
59 {
60   ARG_0,
61   ARG_DRC
62 };
64 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
65     GST_PAD_SINK,
66     GST_PAD_ALWAYS,
67     GST_STATIC_CAPS ("audio/x-ac3; audio/ac3; audio/x-private1-ac3")
68     );
70 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
71     GST_PAD_SRC,
72     GST_PAD_ALWAYS,
73     GST_STATIC_CAPS ("audio/x-raw-float, "
74         "endianness = (int) " G_STRINGIFY (G_BYTE_ORDER) ", "
75         "width = (int) " G_STRINGIFY (SAMPLE_WIDTH) ", "
76         "rate = (int) [ 4000, 96000 ], " "channels = (int) [ 1, 6 ]")
77     );
79 static void gst_a52dec_base_init (GstA52DecClass * klass);
80 static void gst_a52dec_class_init (GstA52DecClass * klass);
81 static void gst_a52dec_init (GstA52Dec * a52dec);
83 static GstFlowReturn gst_a52dec_chain (GstPad * pad, GstBuffer * buffer);
84 static GstFlowReturn gst_a52dec_chain_raw (GstPad * pad, GstBuffer * buf);
85 static gboolean gst_a52dec_sink_setcaps (GstPad * pad, GstCaps * caps);
86 static gboolean gst_a52dec_sink_event (GstPad * pad, GstEvent * event);
87 static GstStateChangeReturn gst_a52dec_change_state (GstElement * element,
88     GstStateChange transition);
90 static void gst_a52dec_set_property (GObject * object, guint prop_id,
91     const GValue * value, GParamSpec * pspec);
92 static void gst_a52dec_get_property (GObject * object, guint prop_id,
93     GValue * value, GParamSpec * pspec);
95 static GstElementClass *parent_class = NULL;
97 GType
98 gst_a52dec_get_type (void)
99 {
100   static GType a52dec_type = 0;
102   if (!a52dec_type) {
103     static const GTypeInfo a52dec_info = {
104       sizeof (GstA52DecClass),
105       (GBaseInitFunc) gst_a52dec_base_init,
106       NULL,
107       (GClassInitFunc) gst_a52dec_class_init,
108       NULL,
109       NULL,
110       sizeof (GstA52Dec),
111       0,
112       (GInstanceInitFunc) gst_a52dec_init,
113     };
115     a52dec_type =
116         g_type_register_static (GST_TYPE_ELEMENT, "GstA52Dec", &a52dec_info, 0);
117   }
118   return a52dec_type;
121 static void
122 gst_a52dec_base_init (GstA52DecClass * klass)
124   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
126   gst_element_class_add_pad_template (element_class,
127       gst_static_pad_template_get (&sink_factory));
128   gst_element_class_add_pad_template (element_class,
129       gst_static_pad_template_get (&src_factory));
130   gst_element_class_set_details (element_class, &gst_a52dec_details);
132   GST_DEBUG_CATEGORY_INIT (a52dec_debug, "a52dec", 0,
133       "AC3/A52 software decoder");
136 static void
137 gst_a52dec_class_init (GstA52DecClass * klass)
139   GObjectClass *gobject_class;
140   GstElementClass *gstelement_class;
141   guint cpuflags;
143   gobject_class = (GObjectClass *) klass;
144   gstelement_class = (GstElementClass *) klass;
146   parent_class = g_type_class_peek_parent (klass);
148   gobject_class->set_property = gst_a52dec_set_property;
149   gobject_class->get_property = gst_a52dec_get_property;
151   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_a52dec_change_state);
153   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DRC,
154       g_param_spec_boolean ("drc", "Dynamic Range Compression",
155           "Use Dynamic Range Compression", FALSE, G_PARAM_READWRITE));
157   oil_init ();
159   klass->a52_cpuflags = 0;
160   cpuflags = oil_cpu_get_flags ();
161   if (cpuflags & OIL_IMPL_FLAG_MMX)
162     klass->a52_cpuflags |= MM_ACCEL_X86_MMX;
163   if (cpuflags & OIL_IMPL_FLAG_3DNOW)
164     klass->a52_cpuflags |= MM_ACCEL_X86_3DNOW;
165   if (cpuflags & OIL_IMPL_FLAG_MMXEXT)
166     klass->a52_cpuflags |= MM_ACCEL_X86_MMXEXT;
168   GST_LOG ("CPU flags: a52=%08x, liboil=%08x", klass->a52_cpuflags, cpuflags);
171 static void
172 gst_a52dec_init (GstA52Dec * a52dec)
174   GstElementClass *klass = GST_ELEMENT_GET_CLASS (a52dec);
176   /* create the sink and src pads */
177   a52dec->sinkpad =
178       gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
179           "sink"), "sink");
180   gst_pad_set_setcaps_function (a52dec->sinkpad,
181       GST_DEBUG_FUNCPTR (gst_a52dec_sink_setcaps));
182   gst_pad_set_chain_function (a52dec->sinkpad,
183       GST_DEBUG_FUNCPTR (gst_a52dec_chain));
184   gst_pad_set_event_function (a52dec->sinkpad,
185       GST_DEBUG_FUNCPTR (gst_a52dec_sink_event));
186   gst_element_add_pad (GST_ELEMENT (a52dec), a52dec->sinkpad);
188   a52dec->srcpad =
189       gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
190           "src"), "src");
191   gst_pad_use_fixed_caps (a52dec->srcpad);
192   gst_element_add_pad (GST_ELEMENT (a52dec), a52dec->srcpad);
194   a52dec->dynamic_range_compression = FALSE;
195   a52dec->cache = NULL;
198 static int
199 gst_a52dec_channels (int flags, GstAudioChannelPosition ** _pos)
201   int chans = 0;
202   GstAudioChannelPosition *pos = NULL;
204   /* allocated just for safety. Number makes no sense */
205   if (_pos) {
206     pos = g_new (GstAudioChannelPosition, 6);
207     *_pos = pos;
208   }
210   if (flags & A52_LFE) {
211     chans += 1;
212     if (pos) {
213       pos[0] = GST_AUDIO_CHANNEL_POSITION_LFE;
214     }
215   }
216   flags &= A52_CHANNEL_MASK;
217   switch (flags) {
218     case A52_3F2R:
219       if (pos) {
220         pos[0 + chans] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
221         pos[1 + chans] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
222         pos[2 + chans] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
223         pos[3 + chans] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT;
224         pos[4 + chans] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT;
225       }
226       chans += 5;
227       break;
228     case A52_2F2R:
229       if (pos) {
230         pos[0 + chans] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
231         pos[1 + chans] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
232         pos[2 + chans] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT;
233         pos[3 + chans] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT;
234       }
235       chans += 4;
236       break;
237     case A52_3F1R:
238       if (pos) {
239         pos[0 + chans] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
240         pos[1 + chans] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
241         pos[2 + chans] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
242         pos[3 + chans] = GST_AUDIO_CHANNEL_POSITION_REAR_CENTER;
243       }
244       chans += 4;
245       break;
246     case A52_2F1R:
247       if (pos) {
248         pos[0 + chans] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
249         pos[1 + chans] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
250         pos[2 + chans] = GST_AUDIO_CHANNEL_POSITION_REAR_CENTER;
251       }
252       chans += 3;
253       break;
254     case A52_3F:
255       if (pos) {
256         pos[0 + chans] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
257         pos[1 + chans] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
258         pos[2 + chans] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
259       }
260       chans += 3;
261       break;
262       /*case A52_CHANNEL: */
263     case A52_STEREO:
264     case A52_DOLBY:
265       if (pos) {
266         pos[0 + chans] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
267         pos[1 + chans] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
268       }
269       chans += 2;
270       break;
271     default:
272       /* error */
273       g_warning ("a52dec invalid flags %d", flags);
274       g_free (pos);
275       return 0;
276   }
278   return chans;
281 static GstFlowReturn
282 gst_a52dec_push (GstA52Dec * a52dec,
283     GstPad * srcpad, int flags, sample_t * samples, GstClockTime timestamp)
285   GstBuffer *buf;
286   int chans, n, c;
287   GstFlowReturn result;
289   flags &= (A52_CHANNEL_MASK | A52_LFE);
290   chans = gst_a52dec_channels (flags, NULL);
291   if (!chans) {
292     return GST_FLOW_ERROR;
293   }
295   result =
296       gst_pad_alloc_buffer_and_set_caps (srcpad, 0,
297       256 * chans * (SAMPLE_WIDTH / 8), GST_PAD_CAPS (srcpad), &buf);
298   if (result != GST_FLOW_OK)
299     return result;
301   for (n = 0; n < 256; n++) {
302     for (c = 0; c < chans; c++) {
303       ((sample_t *) GST_BUFFER_DATA (buf))[n * chans + c] =
304           samples[c * 256 + n];
305     }
306   }
307   GST_BUFFER_TIMESTAMP (buf) = timestamp;
308   GST_BUFFER_DURATION (buf) = 256 * GST_SECOND / a52dec->sample_rate;
310   GST_DEBUG_OBJECT (a52dec,
311       "Pushing buffer with ts %" GST_TIME_FORMAT " duration %" GST_TIME_FORMAT,
312       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
313       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
315   return gst_pad_push (srcpad, buf);
318 static gboolean
319 gst_a52dec_reneg (GstPad * pad)
321   GstAudioChannelPosition *pos;
322   GstA52Dec *a52dec = GST_A52DEC (gst_pad_get_parent (pad));
323   gint channels = gst_a52dec_channels (a52dec->using_channels, &pos);
324   GstCaps *caps = NULL;
325   gboolean result = FALSE;
327   if (!channels)
328     goto done;
330   GST_INFO ("a52dec: reneg channels:%d rate:%d\n",
331       channels, a52dec->sample_rate);
333   caps = gst_caps_new_simple ("audio/x-raw-float",
334       "endianness", G_TYPE_INT, G_BYTE_ORDER,
335       "width", G_TYPE_INT, SAMPLE_WIDTH,
336       "channels", G_TYPE_INT, channels,
337       "rate", G_TYPE_INT, a52dec->sample_rate, NULL);
338   gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos);
339   g_free (pos);
341   if (!gst_pad_set_caps (pad, caps))
342     goto done;
344   result = TRUE;
346 done:
347   if (caps)
348     gst_caps_unref (caps);
349   gst_object_unref (GST_OBJECT (a52dec));
350   return result;
353 static gboolean
354 gst_a52dec_sink_event (GstPad * pad, GstEvent * event)
356   GstA52Dec *a52dec = GST_A52DEC (gst_pad_get_parent (pad));
357   gboolean ret = FALSE;
359   GST_LOG ("Handling %s event", GST_EVENT_TYPE_NAME (event));
361   switch (GST_EVENT_TYPE (event)) {
362     case GST_EVENT_NEWSEGMENT:{
363       GstFormat format;
364       gint64 val;
366       gst_event_parse_new_segment (event, NULL, NULL, &format, &val, NULL,
367           NULL);
368       if (format != GST_FORMAT_TIME || !GST_CLOCK_TIME_IS_VALID (val)) {
369         GST_WARNING ("No time in newsegment event %p", event);
370       } else {
371         a52dec->time = val;
372       }
374       if (a52dec->cache) {
375         gst_buffer_unref (a52dec->cache);
376         a52dec->cache = NULL;
377       }
378       ret = gst_pad_event_default (pad, event);
379       break;
380     }
381     case GST_EVENT_TAG:
382     case GST_EVENT_EOS:{
383       ret = gst_pad_event_default (pad, event);
384       break;
385     }
386     case GST_EVENT_FLUSH_START:
387       ret = gst_pad_event_default (pad, event);
388       break;
389     case GST_EVENT_FLUSH_STOP:
390       if (a52dec->cache) {
391         gst_buffer_unref (a52dec->cache);
392         a52dec->cache = NULL;
393       }
394       ret = gst_pad_event_default (pad, event);
395       break;
396     default:
397       ret = gst_pad_event_default (pad, event);
398       break;
399   }
401   gst_object_unref (a52dec);
402   return ret;
405 static void
406 gst_a52dec_update_streaminfo (GstA52Dec * a52dec)
408   GstTagList *taglist;
410   taglist = gst_tag_list_new ();
412   gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
413       GST_TAG_BITRATE, (guint) a52dec->bit_rate, NULL);
415   gst_element_found_tags_for_pad (GST_ELEMENT (a52dec),
416       GST_PAD (a52dec->srcpad), taglist);
419 static GstFlowReturn
420 gst_a52dec_handle_frame (GstA52Dec * a52dec, guint8 * data,
421     guint length, gint flags, gint sample_rate, gint bit_rate)
423   gint channels, i;
424   gboolean need_reneg = FALSE;
426   /* update stream information, renegotiate or re-streaminfo if needed */
427   need_reneg = FALSE;
428   if (a52dec->sample_rate != sample_rate) {
429     need_reneg = TRUE;
430     a52dec->sample_rate = sample_rate;
431   }
433   if (flags) {
434     a52dec->stream_channels = flags & (A52_CHANNEL_MASK | A52_LFE);
435   }
437   if (bit_rate != a52dec->bit_rate) {
438     a52dec->bit_rate = bit_rate;
439     gst_a52dec_update_streaminfo (a52dec);
440   }
442   /* process */
443   flags = a52dec->request_channels;     /* | A52_ADJUST_LEVEL; */
444   a52dec->level = 1;
445   if (a52_frame (a52dec->state, data, &flags, &a52dec->level, a52dec->bias)) {
446     GST_WARNING ("a52_frame error");
447     return GST_FLOW_OK;
448   }
449   channels = flags & (A52_CHANNEL_MASK | A52_LFE);
450   if (a52dec->using_channels != channels) {
451     need_reneg = TRUE;
452     a52dec->using_channels = channels;
453   }
455   /* negotiate if required */
456   if (need_reneg == TRUE) {
457     GST_DEBUG ("a52dec reneg: sample_rate:%d stream_chans:%d using_chans:%d\n",
458         a52dec->sample_rate, a52dec->stream_channels, a52dec->using_channels);
459     if (!gst_a52dec_reneg (a52dec->srcpad)) {
460       GST_ELEMENT_ERROR (a52dec, CORE, NEGOTIATION, (NULL), (NULL));
461       return GST_FLOW_ERROR;
462     }
463   }
465   if (a52dec->dynamic_range_compression == FALSE) {
466     a52_dynrng (a52dec->state, NULL, NULL);
467   }
469   /* each frame consists of 6 blocks */
470   for (i = 0; i < 6; i++) {
471     if (a52_block (a52dec->state)) {
472       GST_WARNING ("a52_block error %d", i);
473     } else {
474       GstFlowReturn ret;
476       /* push on */
477       ret = gst_a52dec_push (a52dec, a52dec->srcpad, a52dec->using_channels,
478           a52dec->samples, a52dec->time);
479       if (ret != GST_FLOW_OK)
480         return ret;
481     }
482     a52dec->time += 256 * GST_SECOND / a52dec->sample_rate;
483   }
485   return GST_FLOW_OK;
488 static gboolean
489 gst_a52dec_sink_setcaps (GstPad * pad, GstCaps * caps)
491   GstA52Dec *a52dec = GST_A52DEC (gst_pad_get_parent (pad));
492   GstStructure *structure;
494   structure = gst_caps_get_structure (caps, 0);
496   if (structure && gst_structure_has_name (structure, "audio/x-private1-ac3"))
497     a52dec->dvdmode = TRUE;
498   else
499     a52dec->dvdmode = FALSE;
501   gst_object_unref (a52dec);
503   return TRUE;
506 static GstFlowReturn
507 gst_a52dec_chain (GstPad * pad, GstBuffer * buf)
509   GstA52Dec *a52dec = GST_A52DEC (gst_pad_get_parent (pad));
510   GstFlowReturn ret;
512   if (a52dec->dvdmode) {
513     gint size = GST_BUFFER_SIZE (buf);
514     guchar *data = GST_BUFFER_DATA (buf);
515     gint first_access;
516     gint offset;
517     gint len;
518     GstBuffer *subbuf;
520     if (size < 2) {
521       GST_ERROR_OBJECT (pad, "Insufficient data in buffer. "
522           "Can't determine first_acess");
523       ret = GST_FLOW_ERROR;
524       goto done;
525     }
527     first_access = (data[0] << 8) | data[1];
529     /* Skip the first_access header */
530     offset = 2;
532     if (first_access > 1) {
533       /* Length of data before first_access */
534       len = first_access - 1;
536       if (len <= 0 || offset + len > size) {
537         GST_ERROR_OBJECT (pad, "Bad first_access parameter in buffer");
538         ret = GST_FLOW_ERROR;
539         goto done;
540       }
542       subbuf = gst_buffer_create_sub (buf, offset, len);
543       GST_BUFFER_TIMESTAMP (subbuf) = GST_CLOCK_TIME_NONE;
544       ret = gst_a52dec_chain_raw (pad, subbuf);
545       if (ret != GST_FLOW_OK)
546         goto done;
548       offset += len;
549       len = size - offset;
551       if (len > 0) {
552         subbuf = gst_buffer_create_sub (buf, offset, len);
553         GST_BUFFER_TIMESTAMP (subbuf) = GST_BUFFER_TIMESTAMP (buf);
555         ret = gst_a52dec_chain_raw (pad, subbuf);
556       }
557     } else {
558       /* No first_access, so no timestamp */
559       subbuf = gst_buffer_create_sub (buf, offset, size - offset);
560       GST_BUFFER_TIMESTAMP (subbuf) = GST_CLOCK_TIME_NONE;
561       ret = gst_a52dec_chain_raw (pad, subbuf);
562     }
563   } else {
564     ret = gst_a52dec_chain_raw (pad, buf);
565   }
567 done:
568   gst_object_unref (a52dec);
570   return ret;
573 static GstFlowReturn
574 gst_a52dec_chain_raw (GstPad * pad, GstBuffer * buf)
576   GstA52Dec *a52dec = GST_A52DEC (gst_pad_get_parent (pad));
577   guint8 *data;
578   guint size;
579   gint length = 0, flags, sample_rate, bit_rate;
580   GstFlowReturn result = GST_FLOW_OK;
582   /* merge with cache, if any. Also make sure timestamps match */
583   if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
584     a52dec->time = GST_BUFFER_TIMESTAMP (buf);
585     GST_DEBUG_OBJECT (a52dec,
586         "Received buffer with ts %" GST_TIME_FORMAT " duration %"
587         GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
588         GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
589   }
591   if (a52dec->cache) {
592     buf = gst_buffer_join (a52dec->cache, buf);
593     a52dec->cache = NULL;
594   }
595   data = GST_BUFFER_DATA (buf);
596   size = GST_BUFFER_SIZE (buf);
598   /* find and read header */
599   bit_rate = a52dec->bit_rate;
600   sample_rate = a52dec->sample_rate;
601   flags = 0;
602   while (size >= 7) {
603     length = a52_syncinfo (data, &flags, &sample_rate, &bit_rate);
604     if (length == 0) {
605       /* no sync */
606       data++;
607       size--;
608     } else if (length <= size) {
609       GST_DEBUG ("Sync: %d", length);
610       result = gst_a52dec_handle_frame (a52dec, data,
611           length, flags, sample_rate, bit_rate);
612       if (result != GST_FLOW_OK) {
613         size = 0;
614         break;
615       }
616       size -= length;
617       data += length;
618     } else {
619       /* not enough data */
620       GST_LOG ("Not enough data available");
621       break;
622     }
623   }
625   /* keep cache */
626   if (length == 0) {
627     GST_LOG ("No sync found");
628   }
630   if (size > 0) {
631     a52dec->cache = gst_buffer_create_sub (buf,
632         GST_BUFFER_SIZE (buf) - size, size);
633   }
635   gst_buffer_unref (buf);
636   gst_object_unref (a52dec);
638   return result;
641 static GstStateChangeReturn
642 gst_a52dec_change_state (GstElement * element, GstStateChange transition)
644   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
645   GstA52Dec *a52dec = GST_A52DEC (element);
647   switch (transition) {
648     case GST_STATE_CHANGE_NULL_TO_READY:{
649       GstA52DecClass *klass;
651       klass = GST_A52DEC_CLASS (G_OBJECT_GET_CLASS (a52dec));
652       a52dec->state = a52_init (klass->a52_cpuflags);
653       break;
654     }
655     case GST_STATE_CHANGE_READY_TO_PAUSED:
656       a52dec->samples = a52_samples (a52dec->state);
657       a52dec->bit_rate = -1;
658       a52dec->sample_rate = -1;
659       a52dec->stream_channels = A52_CHANNEL;
660       a52dec->request_channels = A52_3F2R | A52_LFE;
661       a52dec->using_channels = A52_CHANNEL;
662       a52dec->level = 1;
663       a52dec->bias = 0;
664       a52dec->time = 0;
665       break;
666     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
667       break;
668     default:
669       break;
670   }
672   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
674   switch (transition) {
675     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
676       break;
677     case GST_STATE_CHANGE_PAUSED_TO_READY:
678       a52dec->samples = NULL;
679       if (a52dec->cache) {
680         gst_buffer_unref (a52dec->cache);
681         a52dec->cache = NULL;
682       }
683       break;
684     case GST_STATE_CHANGE_READY_TO_NULL:
685       a52_free (a52dec->state);
686       a52dec->state = NULL;
687       break;
688     default:
689       break;
690   }
692   return ret;
695 static void
696 gst_a52dec_set_property (GObject * object, guint prop_id, const GValue * value,
697     GParamSpec * pspec)
699   GstA52Dec *src = GST_A52DEC (object);
701   switch (prop_id) {
702     case ARG_DRC:
703       GST_OBJECT_LOCK (src);
704       src->dynamic_range_compression = g_value_get_boolean (value);
705       GST_OBJECT_UNLOCK (src);
706       break;
707     default:
708       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
709       break;
710   }
713 static void
714 gst_a52dec_get_property (GObject * object, guint prop_id, GValue * value,
715     GParamSpec * pspec)
717   GstA52Dec *src = GST_A52DEC (object);
719   switch (prop_id) {
720     case ARG_DRC:
721       GST_OBJECT_LOCK (src);
722       g_value_set_boolean (value, src->dynamic_range_compression);
723       GST_OBJECT_UNLOCK (src);
724       break;
725     default:
726       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
727       break;
728   }
731 static gboolean
732 plugin_init (GstPlugin * plugin)
734   if (!gst_element_register (plugin, "a52dec", GST_RANK_PRIMARY,
735           GST_TYPE_A52DEC))
736     return FALSE;
738   return TRUE;
741 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
742     GST_VERSION_MINOR,
743     "a52dec",
744     "Decodes ATSC A/52 encoded audio streams",
745     plugin_init, VERSION, "GPL", GST_PACKAGE, GST_ORIGIN);