Back to development
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-bad / ext / dts / gstdtsdec.c
1 /* GStreamer DTS decoder plugin based on libdtsdec
2  * Copyright (C) 2004 Ronald Bultje <rbultje@ronald.bitfreak.net>
3  * Copyright (C) 2009 Jan Schmidt <thaytan@noraisin.net>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20
21 /**
22  * SECTION:element-dtsdec
23  * @title: dtsdec
24  *
25  * Digital Theatre System (DTS) audio decoder
26  *
27  * ## Example launch line
28  * |[
29  * gst-launch-1.0 dvdreadsrc title=1 ! mpegpsdemux ! dtsdec ! audioresample ! audioconvert ! alsasink
30  * ]| Play a DTS audio track from a dvd.
31  * |[
32  * gst-launch-1.0 filesrc location=abc.dts ! dtsdec ! audioresample ! audioconvert ! alsasink
33  * ]| Decode a standalone file and play it.
34  *
35  */
36
37 #ifdef HAVE_CONFIG_H
38 #include "config.h"
39 #endif
40
41 #ifdef HAVE_STDINT_H
42 #include <stdint.h>
43 #endif
44
45 #include <string.h>
46 #include <stdlib.h>
47
48 #include <gst/gst.h>
49 #include <gst/audio/audio.h>
50
51 #ifndef DTS_OLD
52 #include <dca.h>
53 #else
54 #include <dts.h>
55
56 typedef struct dts_state_s dca_state_t;
57 #define DCA_MONO DTS_MONO
58 #define DCA_CHANNEL DTS_CHANNEL
59 #define DCA_STEREO DTS_STEREO
60 #define DCA_STEREO_SUMDIFF DTS_STEREO_SUMDIFF
61 #define DCA_STEREO_TOTAL DTS_STEREO_TOTAL
62 #define DCA_3F DTS_3F
63 #define DCA_2F1R DTS_2F1R
64 #define DCA_3F1R DTS_3F1R
65 #define DCA_2F2R DTS_2F2R
66 #define DCA_3F2R DTS_3F2R
67 #define DCA_4F2R DTS_4F2R
68 #define DCA_DOLBY DTS_DOLBY
69 #define DCA_CHANNEL_MAX DTS_CHANNEL_MAX
70 #define DCA_CHANNEL_BITS DTS_CHANNEL_BITS
71 #define DCA_CHANNEL_MASK DTS_CHANNEL_MASK
72 #define DCA_LFE DTS_LFE
73 #define DCA_ADJUST_LEVEL DTS_ADJUST_LEVEL
74
75 #define dca_init dts_init
76 #define dca_syncinfo dts_syncinfo
77 #define dca_frame dts_frame
78 #define dca_dynrng dts_dynrng
79 #define dca_blocks_num dts_blocks_num
80 #define dca_block dts_block
81 #define dca_samples dts_samples
82 #define dca_free dts_free
83 #endif
84
85 #include "gstdtsdec.h"
86
87 #if HAVE_ORC
88 #include <orc/orc.h>
89 #endif
90
91 #if defined(LIBDTS_FIXED) || defined(LIBDCA_FIXED)
92 #define SAMPLE_WIDTH 16
93 #define SAMPLE_FORMAT GST_AUDIO_NE(S16)
94 #define SAMPLE_TYPE GST_AUDIO_FORMAT_S16
95 #elif defined (LIBDTS_DOUBLE) || defined(LIBDCA_DOUBLE)
96 #define SAMPLE_WIDTH 64
97 #define SAMPLE_FORMAT GST_AUDIO_NE(F64)
98 #define SAMPLE_TYPE GST_AUDIO_FORMAT_F64
99 #else
100 #define SAMPLE_WIDTH 32
101 #define SAMPLE_FORMAT GST_AUDIO_NE(F32)
102 #define SAMPLE_TYPE GST_AUDIO_FORMAT_F32
103 #endif
104
105 GST_DEBUG_CATEGORY_STATIC (dtsdec_debug);
106 #define GST_CAT_DEFAULT (dtsdec_debug)
107
108 enum
109 {
110   PROP_0,
111   PROP_DRC
112 };
113
114 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
115     GST_PAD_SINK,
116     GST_PAD_ALWAYS,
117     GST_STATIC_CAPS ("audio/x-dts; audio/x-private1-dts")
118     );
119
120 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
121     GST_PAD_SRC,
122     GST_PAD_ALWAYS,
123     GST_STATIC_CAPS ("audio/x-raw, "
124         "format = (string) " SAMPLE_FORMAT ", "
125         "layout = (string) interleaved, "
126         "rate = (int) [ 4000, 96000 ], " "channels = (int) [ 1, 6 ]")
127     );
128
129
130
131 static gboolean gst_dtsdec_start (GstAudioDecoder * dec);
132 static gboolean gst_dtsdec_stop (GstAudioDecoder * dec);
133 static gboolean gst_dtsdec_set_format (GstAudioDecoder * bdec, GstCaps * caps);
134 static GstFlowReturn gst_dtsdec_parse (GstAudioDecoder * dec,
135     GstAdapter * adapter, gint * offset, gint * length);
136 static GstFlowReturn gst_dtsdec_handle_frame (GstAudioDecoder * dec,
137     GstBuffer * buffer);
138
139 static GstFlowReturn gst_dtsdec_chain (GstPad * pad, GstObject * parent,
140     GstBuffer * buf);
141
142 static void gst_dtsdec_set_property (GObject * object, guint prop_id,
143     const GValue * value, GParamSpec * pspec);
144 static void gst_dtsdec_get_property (GObject * object, guint prop_id,
145     GValue * value, GParamSpec * pspec);
146 static gboolean dtsdec_element_init (GstPlugin * plugin);
147
148 G_DEFINE_TYPE (GstDtsDec, gst_dtsdec, GST_TYPE_AUDIO_DECODER);
149 GST_ELEMENT_REGISTER_DEFINE_CUSTOM (dtsdec, dtsdec_element_init);
150
151 static void
152 gst_dtsdec_class_init (GstDtsDecClass * klass)
153 {
154   GObjectClass *gobject_class;
155   GstElementClass *gstelement_class;
156   GstAudioDecoderClass *gstbase_class;
157   guint cpuflags;
158
159   gobject_class = (GObjectClass *) klass;
160   gstelement_class = (GstElementClass *) klass;
161   gstbase_class = (GstAudioDecoderClass *) klass;
162
163   gobject_class->set_property = gst_dtsdec_set_property;
164   gobject_class->get_property = gst_dtsdec_get_property;
165
166   gst_element_class_add_static_pad_template (gstelement_class, &sink_factory);
167   gst_element_class_add_static_pad_template (gstelement_class, &src_factory);
168   gst_element_class_set_static_metadata (gstelement_class, "DTS audio decoder",
169       "Codec/Decoder/Audio",
170       "Decodes DTS audio streams",
171       "Jan Schmidt <thaytan@noraisin.net>, "
172       "Ronald Bultje <rbultje@ronald.bitfreak.net>");
173
174   gstbase_class->start = GST_DEBUG_FUNCPTR (gst_dtsdec_start);
175   gstbase_class->stop = GST_DEBUG_FUNCPTR (gst_dtsdec_stop);
176   gstbase_class->set_format = GST_DEBUG_FUNCPTR (gst_dtsdec_set_format);
177   gstbase_class->parse = GST_DEBUG_FUNCPTR (gst_dtsdec_parse);
178   gstbase_class->handle_frame = GST_DEBUG_FUNCPTR (gst_dtsdec_handle_frame);
179
180   /**
181    * GstDtsDec::drc
182    *
183    * Set to true to apply the recommended DTS dynamic range compression
184    * to the audio stream. Dynamic range compression makes loud sounds
185    * softer and soft sounds louder, so you can more easily listen
186    * to the stream without disturbing other people.
187    */
188   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DRC,
189       g_param_spec_boolean ("drc", "Dynamic Range Compression",
190           "Use Dynamic Range Compression", FALSE,
191           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
192
193   klass->dts_cpuflags = 0;
194
195 #if HAVE_ORC
196   cpuflags = orc_target_get_default_flags (orc_target_get_by_name ("mmx"));
197   if (cpuflags & ORC_TARGET_MMX_MMX)
198     klass->dts_cpuflags |= MM_ACCEL_X86_MMX;
199   if (cpuflags & ORC_TARGET_MMX_3DNOW)
200     klass->dts_cpuflags |= MM_ACCEL_X86_3DNOW;
201   if (cpuflags & ORC_TARGET_MMX_MMXEXT)
202     klass->dts_cpuflags |= MM_ACCEL_X86_MMXEXT;
203 #else
204   cpuflags = 0;
205   klass->dts_cpuflags = 0;
206 #endif
207
208   GST_LOG ("CPU flags: dts=%08x, orc=%08x", klass->dts_cpuflags, cpuflags);
209 }
210
211 static void
212 gst_dtsdec_init (GstDtsDec * dtsdec)
213 {
214   dtsdec->request_channels = DCA_CHANNEL;
215   dtsdec->dynamic_range_compression = FALSE;
216
217   gst_audio_decoder_set_use_default_pad_acceptcaps (GST_AUDIO_DECODER_CAST
218       (dtsdec), TRUE);
219   GST_PAD_SET_ACCEPT_TEMPLATE (GST_AUDIO_DECODER_SINK_PAD (dtsdec));
220
221   /* retrieve and intercept base class chain.
222    * Quite HACKish, but that's dvd specs for you,
223    * since one buffer needs to be split into 2 frames */
224   dtsdec->base_chain = GST_PAD_CHAINFUNC (GST_AUDIO_DECODER_SINK_PAD (dtsdec));
225   gst_pad_set_chain_function (GST_AUDIO_DECODER_SINK_PAD (dtsdec),
226       GST_DEBUG_FUNCPTR (gst_dtsdec_chain));
227 }
228
229 static gboolean
230 gst_dtsdec_start (GstAudioDecoder * dec)
231 {
232   GstDtsDec *dts = GST_DTSDEC (dec);
233   GstDtsDecClass *klass;
234
235   GST_DEBUG_OBJECT (dec, "start");
236
237   klass = GST_DTSDEC_CLASS (G_OBJECT_GET_CLASS (dts));
238   dts->state = dca_init (klass->dts_cpuflags);
239   dts->samples = dca_samples (dts->state);
240   dts->bit_rate = -1;
241   dts->sample_rate = -1;
242   dts->stream_channels = DCA_CHANNEL;
243   dts->using_channels = DCA_CHANNEL;
244   dts->level = 1;
245   dts->bias = 0;
246   dts->flag_update = TRUE;
247
248   /* call upon legacy upstream byte support (e.g. seeking) */
249   gst_audio_decoder_set_estimate_rate (dec, TRUE);
250
251   return TRUE;
252 }
253
254 static gboolean
255 gst_dtsdec_stop (GstAudioDecoder * dec)
256 {
257   GstDtsDec *dts = GST_DTSDEC (dec);
258
259   GST_DEBUG_OBJECT (dec, "stop");
260
261   dts->samples = NULL;
262   if (dts->state) {
263     dca_free (dts->state);
264     dts->state = NULL;
265   }
266
267   return TRUE;
268 }
269
270 static GstFlowReturn
271 gst_dtsdec_parse (GstAudioDecoder * bdec, GstAdapter * adapter,
272     gint * _offset, gint * len)
273 {
274   GstDtsDec *dts;
275   guint8 *data;
276   gint av, size;
277   gint length = 0, flags, sample_rate, bit_rate, frame_length;
278   GstFlowReturn result = GST_FLOW_EOS;
279
280   dts = GST_DTSDEC (bdec);
281
282   size = av = gst_adapter_available (adapter);
283   data = (guint8 *) gst_adapter_map (adapter, av);
284
285   /* find and read header */
286   bit_rate = dts->bit_rate;
287   sample_rate = dts->sample_rate;
288   flags = 0;
289   while (size >= 7) {
290     length = dca_syncinfo (dts->state, data, &flags,
291         &sample_rate, &bit_rate, &frame_length);
292
293     if (length == 0) {
294       /* shift window to re-find sync */
295       data++;
296       size--;
297     } else if (length <= size) {
298       GST_LOG_OBJECT (dts, "Sync: frame size %d", length);
299       result = GST_FLOW_OK;
300       break;
301     } else {
302       GST_LOG_OBJECT (dts, "Not enough data available (needed %d had %d)",
303           length, size);
304       break;
305     }
306   }
307   gst_adapter_unmap (adapter);
308
309   *_offset = av - size;
310   *len = length;
311
312   return result;
313 }
314
315 static gint
316 gst_dtsdec_channels (uint32_t flags, GstAudioChannelPosition * pos)
317 {
318   gint chans = 0;
319
320   switch (flags & DCA_CHANNEL_MASK) {
321     case DCA_MONO:
322       chans = 1;
323       if (pos) {
324         pos[0] = GST_AUDIO_CHANNEL_POSITION_MONO;
325       }
326       break;
327       /* case DCA_CHANNEL: */
328     case DCA_STEREO:
329     case DCA_STEREO_SUMDIFF:
330     case DCA_STEREO_TOTAL:
331     case DCA_DOLBY:
332       chans = 2;
333       if (pos) {
334         pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
335         pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
336       }
337       break;
338     case DCA_3F:
339       chans = 3;
340       if (pos) {
341         pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
342         pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
343         pos[2] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
344       }
345       break;
346     case DCA_2F1R:
347       chans = 3;
348       if (pos) {
349         pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
350         pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
351         pos[2] = GST_AUDIO_CHANNEL_POSITION_REAR_CENTER;
352       }
353       break;
354     case DCA_3F1R:
355       chans = 4;
356       if (pos) {
357         pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
358         pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
359         pos[2] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
360         pos[3] = GST_AUDIO_CHANNEL_POSITION_REAR_CENTER;
361       }
362       break;
363     case DCA_2F2R:
364       chans = 4;
365       if (pos) {
366         pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
367         pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
368         pos[2] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT;
369         pos[3] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT;
370       }
371       break;
372     case DCA_3F2R:
373       chans = 5;
374       if (pos) {
375         pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
376         pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
377         pos[2] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
378         pos[3] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT;
379         pos[4] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT;
380       }
381       break;
382     case DCA_4F2R:
383       chans = 6;
384       if (pos) {
385         pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER;
386         pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER;
387         pos[2] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
388         pos[3] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
389         pos[4] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT;
390         pos[5] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT;
391       }
392       break;
393     default:
394       g_warning ("dtsdec: invalid flags 0x%x", flags);
395       return 0;
396   }
397   if (flags & DCA_LFE) {
398     if (pos) {
399       pos[chans] = GST_AUDIO_CHANNEL_POSITION_LFE1;
400     }
401     chans += 1;
402   }
403
404   return chans;
405 }
406
407 static gboolean
408 gst_dtsdec_renegotiate (GstDtsDec * dts)
409 {
410   gint channels;
411   gboolean result = FALSE;
412   GstAudioChannelPosition from[7], to[7];
413   GstAudioInfo info;
414
415   channels = gst_dtsdec_channels (dts->using_channels, from);
416
417   if (channels <= 0 || channels > 7)
418     goto done;
419
420   GST_INFO_OBJECT (dts, "dtsdec renegotiate, channels=%d, rate=%d",
421       channels, dts->sample_rate);
422
423   memcpy (to, from, sizeof (GstAudioChannelPosition) * channels);
424   gst_audio_channel_positions_to_valid_order (to, channels);
425   gst_audio_get_channel_reorder_map (channels, from, to,
426       dts->channel_reorder_map);
427
428
429   gst_audio_info_init (&info);
430   gst_audio_info_set_format (&info,
431       SAMPLE_TYPE, dts->sample_rate, channels, (channels > 1 ? to : NULL));
432
433   if (!gst_audio_decoder_set_output_format (GST_AUDIO_DECODER (dts), &info))
434     goto done;
435
436   result = TRUE;
437
438 done:
439   return result;
440 }
441
442 static void
443 gst_dtsdec_update_streaminfo (GstDtsDec * dts)
444 {
445   GstTagList *taglist;
446
447   if (dts->bit_rate > 3) {
448     taglist = gst_tag_list_new_empty ();
449     /* 1 => open bitrate, 2 => variable bitrate, 3 => lossless */
450     gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_BITRATE,
451         (guint) dts->bit_rate, NULL);
452     gst_audio_decoder_merge_tags (GST_AUDIO_DECODER (dts), taglist,
453         GST_TAG_MERGE_REPLACE);
454     if (taglist)
455       gst_tag_list_unref (taglist);
456   }
457 }
458
459 static GstFlowReturn
460 gst_dtsdec_handle_frame (GstAudioDecoder * bdec, GstBuffer * buffer)
461 {
462   GstDtsDec *dts;
463   gint channels, i, num_blocks;
464   gboolean need_renegotiation = FALSE;
465   guint8 *data;
466   GstMapInfo map;
467   gint chans;
468 #ifndef G_DISABLE_ASSERT
469   gsize size;
470   gint length;
471 #endif
472   gint flags, sample_rate, bit_rate, frame_length;
473   GstFlowReturn result = GST_FLOW_OK;
474   GstBuffer *outbuf;
475
476   dts = GST_DTSDEC (bdec);
477
478   /* no fancy draining */
479   if (G_UNLIKELY (!buffer))
480     return GST_FLOW_OK;
481
482   /* parsed stuff already, so this should work out fine */
483   gst_buffer_map (buffer, &map, GST_MAP_READ);
484   data = map.data;
485
486 #ifndef G_DISABLE_ASSERT
487   size = map.size;
488   g_assert (size >= 7);
489 #endif
490
491   bit_rate = dts->bit_rate;
492   sample_rate = dts->sample_rate;
493   flags = 0;
494
495 #ifndef G_DISABLE_ASSERT
496   length = dca_syncinfo (dts->state, data, &flags, &sample_rate, &bit_rate,
497       &frame_length);
498   g_assert (length == size);
499 #else
500   (void) dca_syncinfo (dts->state, data, &flags, &sample_rate, &bit_rate,
501       &frame_length);
502 #endif
503
504   if (flags != dts->prev_flags) {
505     dts->prev_flags = flags;
506     dts->flag_update = TRUE;
507   }
508
509   /* go over stream properties, renegotiate or update streaminfo if needed */
510   if (dts->sample_rate != sample_rate) {
511     need_renegotiation = TRUE;
512     dts->sample_rate = sample_rate;
513   }
514
515   if (flags) {
516     dts->stream_channels = flags & (DCA_CHANNEL_MASK | DCA_LFE);
517   }
518
519   if (bit_rate != dts->bit_rate) {
520     dts->bit_rate = bit_rate;
521     gst_dtsdec_update_streaminfo (dts);
522   }
523
524   /* If we haven't had an explicit number of channels chosen through properties
525    * at this point, choose what to downmix to now, based on what the peer will 
526    * accept - this allows a52dec to do downmixing in preference to a 
527    * downstream element such as audioconvert.
528    * FIXME: Add the property back in for forcing output channels.
529    */
530   if (dts->request_channels != DCA_CHANNEL) {
531     flags = dts->request_channels;
532   } else if (dts->flag_update) {
533     GstCaps *caps;
534
535     dts->flag_update = FALSE;
536
537     caps = gst_pad_get_allowed_caps (GST_AUDIO_DECODER_SRC_PAD (dts));
538     if (caps && gst_caps_get_size (caps) > 0) {
539       GstCaps *copy = gst_caps_copy_nth (caps, 0);
540       GstStructure *structure = gst_caps_get_structure (copy, 0);
541       gint channels;
542       const int dts_channels[6] = {
543         DCA_MONO,
544         DCA_STEREO,
545         DCA_STEREO | DCA_LFE,
546         DCA_2F2R,
547         DCA_2F2R | DCA_LFE,
548         DCA_3F2R | DCA_LFE,
549       };
550
551       /* Prefer the original number of channels, but fixate to something 
552        * preferred (first in the caps) downstream if possible.
553        */
554       gst_structure_fixate_field_nearest_int (structure, "channels",
555           flags ? gst_dtsdec_channels (flags, NULL) : 6);
556       gst_structure_get_int (structure, "channels", &channels);
557       if (channels <= 6)
558         flags = dts_channels[channels - 1];
559       else
560         flags = dts_channels[5];
561
562       gst_caps_unref (copy);
563     } else if (flags) {
564       flags = dts->stream_channels;
565     } else {
566       flags = DCA_3F2R | DCA_LFE;
567     }
568
569     if (caps)
570       gst_caps_unref (caps);
571   } else {
572     flags = dts->using_channels;
573   }
574
575   /* process */
576   flags |= DCA_ADJUST_LEVEL;
577   dts->level = 1;
578   if (dca_frame (dts->state, data, &flags, &dts->level, dts->bias)) {
579     gst_buffer_unmap (buffer, &map);
580     GST_AUDIO_DECODER_ERROR (dts, 1, STREAM, DECODE, (NULL),
581         ("dts_frame error"), result);
582     goto exit;
583   }
584   gst_buffer_unmap (buffer, &map);
585
586   channels = flags & (DCA_CHANNEL_MASK | DCA_LFE);
587   if (dts->using_channels != channels) {
588     need_renegotiation = TRUE;
589     dts->using_channels = channels;
590   }
591
592   /* negotiate if required */
593   if (need_renegotiation) {
594     GST_DEBUG_OBJECT (dts,
595         "dtsdec: sample_rate:%d stream_chans:0x%x using_chans:0x%x",
596         dts->sample_rate, dts->stream_channels, dts->using_channels);
597     if (!gst_dtsdec_renegotiate (dts))
598       goto failed_negotiation;
599   }
600
601   if (dts->dynamic_range_compression == FALSE) {
602     dca_dynrng (dts->state, NULL, NULL);
603   }
604
605   flags &= (DCA_CHANNEL_MASK | DCA_LFE);
606   chans = gst_dtsdec_channels (flags, NULL);
607   if (!chans)
608     goto invalid_flags;
609
610   /* handle decoded data, one block is 256 samples */
611   num_blocks = dca_blocks_num (dts->state);
612   outbuf =
613       gst_buffer_new_and_alloc (256 * chans * (SAMPLE_WIDTH / 8) * num_blocks);
614
615   gst_buffer_map (outbuf, &map, GST_MAP_WRITE);
616   data = map.data;
617   {
618     guint8 *ptr = data;
619     for (i = 0; i < num_blocks; i++) {
620       if (dca_block (dts->state)) {
621         /* also marks discont */
622         GST_AUDIO_DECODER_ERROR (dts, 1, STREAM, DECODE, (NULL),
623             ("error decoding block %d", i), result);
624         if (result != GST_FLOW_OK)
625           goto exit;
626       } else {
627         gint n, c;
628         gint *reorder_map = dts->channel_reorder_map;
629
630         for (n = 0; n < 256; n++) {
631           for (c = 0; c < chans; c++) {
632             ((sample_t *) ptr)[n * chans + reorder_map[c]] =
633                 dts->samples[c * 256 + n];
634           }
635         }
636       }
637       ptr += 256 * chans * (SAMPLE_WIDTH / 8);
638     }
639   }
640   gst_buffer_unmap (outbuf, &map);
641
642   result = gst_audio_decoder_finish_frame (bdec, outbuf, 1);
643
644 exit:
645   return result;
646
647   /* ERRORS */
648 failed_negotiation:
649   {
650     GST_ELEMENT_ERROR (dts, CORE, NEGOTIATION, (NULL), (NULL));
651     return GST_FLOW_ERROR;
652   }
653 invalid_flags:
654   {
655     GST_ELEMENT_ERROR (GST_ELEMENT (dts), STREAM, DECODE, (NULL),
656         ("Invalid channel flags: %d", flags));
657     return GST_FLOW_ERROR;
658   }
659 }
660
661 static gboolean
662 gst_dtsdec_set_format (GstAudioDecoder * bdec, GstCaps * caps)
663 {
664   GstDtsDec *dts = GST_DTSDEC (bdec);
665   GstStructure *structure;
666
667   structure = gst_caps_get_structure (caps, 0);
668
669   if (structure && gst_structure_has_name (structure, "audio/x-private1-dts"))
670     dts->dvdmode = TRUE;
671   else
672     dts->dvdmode = FALSE;
673
674   return TRUE;
675 }
676
677 static GstFlowReturn
678 gst_dtsdec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
679 {
680   GstFlowReturn ret = GST_FLOW_OK;
681   GstDtsDec *dts = GST_DTSDEC (parent);
682   gint first_access;
683
684   if (dts->dvdmode) {
685     guint8 data[2];
686     gsize size;
687     gint offset, len;
688     GstBuffer *subbuf;
689
690     size = gst_buffer_get_size (buf);
691     if (size < 2)
692       goto not_enough_data;
693
694     gst_buffer_extract (buf, 0, data, 2);
695     first_access = (data[0] << 8) | data[1];
696
697     /* Skip the first_access header */
698     offset = 2;
699
700     if (first_access > 1) {
701       /* Length of data before first_access */
702       len = first_access - 1;
703
704       if (len <= 0 || offset + len > size)
705         goto bad_first_access_parameter;
706
707       subbuf = gst_buffer_copy_region (buf, GST_BUFFER_COPY_ALL, offset, len);
708       GST_BUFFER_TIMESTAMP (subbuf) = GST_CLOCK_TIME_NONE;
709       ret = dts->base_chain (pad, parent, subbuf);
710       if (ret != GST_FLOW_OK) {
711         gst_buffer_unref (buf);
712         goto done;
713       }
714
715       offset += len;
716       len = size - offset;
717
718       if (len > 0) {
719         subbuf = gst_buffer_copy_region (buf, GST_BUFFER_COPY_ALL, offset, len);
720         GST_BUFFER_TIMESTAMP (subbuf) = GST_BUFFER_TIMESTAMP (buf);
721
722         ret = dts->base_chain (pad, parent, subbuf);
723       }
724       gst_buffer_unref (buf);
725     } else {
726       /* first_access = 0 or 1, so if there's a timestamp it applies to the first byte */
727       subbuf =
728           gst_buffer_copy_region (buf, GST_BUFFER_COPY_ALL, offset,
729           size - offset);
730       GST_BUFFER_TIMESTAMP (subbuf) = GST_BUFFER_TIMESTAMP (buf);
731       ret = dts->base_chain (pad, parent, subbuf);
732       gst_buffer_unref (buf);
733     }
734   } else {
735     ret = dts->base_chain (pad, parent, buf);
736   }
737
738 done:
739   return ret;
740
741 /* ERRORS */
742 not_enough_data:
743   {
744     GST_ELEMENT_ERROR (GST_ELEMENT (dts), STREAM, DECODE, (NULL),
745         ("Insufficient data in buffer. Can't determine first_acess"));
746     gst_buffer_unref (buf);
747     return GST_FLOW_ERROR;
748   }
749 bad_first_access_parameter:
750   {
751     GST_ELEMENT_ERROR (GST_ELEMENT (dts), STREAM, DECODE, (NULL),
752         ("Bad first_access parameter (%d) in buffer", first_access));
753     gst_buffer_unref (buf);
754     return GST_FLOW_ERROR;
755   }
756 }
757
758 static void
759 gst_dtsdec_set_property (GObject * object, guint prop_id, const GValue * value,
760     GParamSpec * pspec)
761 {
762   GstDtsDec *dts = GST_DTSDEC (object);
763
764   switch (prop_id) {
765     case PROP_DRC:
766       dts->dynamic_range_compression = g_value_get_boolean (value);
767       break;
768     default:
769       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
770       break;
771   }
772 }
773
774 static void
775 gst_dtsdec_get_property (GObject * object, guint prop_id, GValue * value,
776     GParamSpec * pspec)
777 {
778   GstDtsDec *dts = GST_DTSDEC (object);
779
780   switch (prop_id) {
781     case PROP_DRC:
782       g_value_set_boolean (value, dts->dynamic_range_compression);
783       break;
784     default:
785       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
786       break;
787   }
788 }
789
790 static gboolean
791 dtsdec_element_init (GstPlugin * plugin)
792 {
793   GST_DEBUG_CATEGORY_INIT (dtsdec_debug, "dtsdec", 0, "DTS/DCA audio decoder");
794
795 #if HAVE_ORC
796   orc_init ();
797 #endif
798
799   return gst_element_register (plugin, "dtsdec", GST_RANK_PRIMARY,
800       GST_TYPE_DTSDEC);
801 }
802
803 static gboolean
804 plugin_init (GstPlugin * plugin)
805 {
806   return GST_ELEMENT_REGISTER (dtsdec, plugin);
807 }
808
809 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
810     GST_VERSION_MINOR,
811     dtsdec,
812     "Decodes DTS audio streams",
813     plugin_init, VERSION, "GPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);