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 G_DEFINE_TYPE (GstDtsDec, gst_dtsdec, GST_TYPE_AUDIO_DECODER);
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
147 static void
gst_dtsdec_class_init(GstDtsDecClass * klass)148 gst_dtsdec_class_init (GstDtsDecClass * klass)
149 {
150 GObjectClass *gobject_class;
151 GstElementClass *gstelement_class;
152 GstAudioDecoderClass *gstbase_class;
153 guint cpuflags;
154
155 gobject_class = (GObjectClass *) klass;
156 gstelement_class = (GstElementClass *) klass;
157 gstbase_class = (GstAudioDecoderClass *) klass;
158
159 gobject_class->set_property = gst_dtsdec_set_property;
160 gobject_class->get_property = gst_dtsdec_get_property;
161
162 gst_element_class_add_static_pad_template (gstelement_class, &sink_factory);
163 gst_element_class_add_static_pad_template (gstelement_class, &src_factory);
164 gst_element_class_set_static_metadata (gstelement_class, "DTS audio decoder",
165 "Codec/Decoder/Audio",
166 "Decodes DTS audio streams",
167 "Jan Schmidt <thaytan@noraisin.net>, "
168 "Ronald Bultje <rbultje@ronald.bitfreak.net>");
169
170 gstbase_class->start = GST_DEBUG_FUNCPTR (gst_dtsdec_start);
171 gstbase_class->stop = GST_DEBUG_FUNCPTR (gst_dtsdec_stop);
172 gstbase_class->set_format = GST_DEBUG_FUNCPTR (gst_dtsdec_set_format);
173 gstbase_class->parse = GST_DEBUG_FUNCPTR (gst_dtsdec_parse);
174 gstbase_class->handle_frame = GST_DEBUG_FUNCPTR (gst_dtsdec_handle_frame);
175
176 /**
177 * GstDtsDec::drc
178 *
179 * Set to true to apply the recommended DTS dynamic range compression
180 * to the audio stream. Dynamic range compression makes loud sounds
181 * softer and soft sounds louder, so you can more easily listen
182 * to the stream without disturbing other people.
183 */
184 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DRC,
185 g_param_spec_boolean ("drc", "Dynamic Range Compression",
186 "Use Dynamic Range Compression", FALSE,
187 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
188
189 klass->dts_cpuflags = 0;
190
191 #if HAVE_ORC
192 cpuflags = orc_target_get_default_flags (orc_target_get_by_name ("mmx"));
193 if (cpuflags & ORC_TARGET_MMX_MMX)
194 klass->dts_cpuflags |= MM_ACCEL_X86_MMX;
195 if (cpuflags & ORC_TARGET_MMX_3DNOW)
196 klass->dts_cpuflags |= MM_ACCEL_X86_3DNOW;
197 if (cpuflags & ORC_TARGET_MMX_MMXEXT)
198 klass->dts_cpuflags |= MM_ACCEL_X86_MMXEXT;
199 #else
200 cpuflags = 0;
201 klass->dts_cpuflags = 0;
202 #endif
203
204 GST_LOG ("CPU flags: dts=%08x, orc=%08x", klass->dts_cpuflags, cpuflags);
205 }
206
207 static void
gst_dtsdec_init(GstDtsDec * dtsdec)208 gst_dtsdec_init (GstDtsDec * dtsdec)
209 {
210 dtsdec->request_channels = DCA_CHANNEL;
211 dtsdec->dynamic_range_compression = FALSE;
212
213 gst_audio_decoder_set_use_default_pad_acceptcaps (GST_AUDIO_DECODER_CAST
214 (dtsdec), TRUE);
215 GST_PAD_SET_ACCEPT_TEMPLATE (GST_AUDIO_DECODER_SINK_PAD (dtsdec));
216
217 /* retrieve and intercept base class chain.
218 * Quite HACKish, but that's dvd specs for you,
219 * since one buffer needs to be split into 2 frames */
220 dtsdec->base_chain = GST_PAD_CHAINFUNC (GST_AUDIO_DECODER_SINK_PAD (dtsdec));
221 gst_pad_set_chain_function (GST_AUDIO_DECODER_SINK_PAD (dtsdec),
222 GST_DEBUG_FUNCPTR (gst_dtsdec_chain));
223 }
224
225 static gboolean
gst_dtsdec_start(GstAudioDecoder * dec)226 gst_dtsdec_start (GstAudioDecoder * dec)
227 {
228 GstDtsDec *dts = GST_DTSDEC (dec);
229 GstDtsDecClass *klass;
230
231 GST_DEBUG_OBJECT (dec, "start");
232
233 klass = GST_DTSDEC_CLASS (G_OBJECT_GET_CLASS (dts));
234 dts->state = dca_init (klass->dts_cpuflags);
235 dts->samples = dca_samples (dts->state);
236 dts->bit_rate = -1;
237 dts->sample_rate = -1;
238 dts->stream_channels = DCA_CHANNEL;
239 dts->using_channels = DCA_CHANNEL;
240 dts->level = 1;
241 dts->bias = 0;
242 dts->flag_update = TRUE;
243
244 /* call upon legacy upstream byte support (e.g. seeking) */
245 gst_audio_decoder_set_estimate_rate (dec, TRUE);
246
247 return TRUE;
248 }
249
250 static gboolean
gst_dtsdec_stop(GstAudioDecoder * dec)251 gst_dtsdec_stop (GstAudioDecoder * dec)
252 {
253 GstDtsDec *dts = GST_DTSDEC (dec);
254
255 GST_DEBUG_OBJECT (dec, "stop");
256
257 dts->samples = NULL;
258 if (dts->state) {
259 dca_free (dts->state);
260 dts->state = NULL;
261 }
262
263 return TRUE;
264 }
265
266 static GstFlowReturn
gst_dtsdec_parse(GstAudioDecoder * bdec,GstAdapter * adapter,gint * _offset,gint * len)267 gst_dtsdec_parse (GstAudioDecoder * bdec, GstAdapter * adapter,
268 gint * _offset, gint * len)
269 {
270 GstDtsDec *dts;
271 guint8 *data;
272 gint av, size;
273 gint length = 0, flags, sample_rate, bit_rate, frame_length;
274 GstFlowReturn result = GST_FLOW_EOS;
275
276 dts = GST_DTSDEC (bdec);
277
278 size = av = gst_adapter_available (adapter);
279 data = (guint8 *) gst_adapter_map (adapter, av);
280
281 /* find and read header */
282 bit_rate = dts->bit_rate;
283 sample_rate = dts->sample_rate;
284 flags = 0;
285 while (size >= 7) {
286 length = dca_syncinfo (dts->state, data, &flags,
287 &sample_rate, &bit_rate, &frame_length);
288
289 if (length == 0) {
290 /* shift window to re-find sync */
291 data++;
292 size--;
293 } else if (length <= size) {
294 GST_LOG_OBJECT (dts, "Sync: frame size %d", length);
295 result = GST_FLOW_OK;
296 break;
297 } else {
298 GST_LOG_OBJECT (dts, "Not enough data available (needed %d had %d)",
299 length, size);
300 break;
301 }
302 }
303 gst_adapter_unmap (adapter);
304
305 *_offset = av - size;
306 *len = length;
307
308 return result;
309 }
310
311 static gint
gst_dtsdec_channels(uint32_t flags,GstAudioChannelPosition * pos)312 gst_dtsdec_channels (uint32_t flags, GstAudioChannelPosition * pos)
313 {
314 gint chans = 0;
315
316 switch (flags & DCA_CHANNEL_MASK) {
317 case DCA_MONO:
318 chans = 1;
319 if (pos) {
320 pos[0] = GST_AUDIO_CHANNEL_POSITION_MONO;
321 }
322 break;
323 /* case DCA_CHANNEL: */
324 case DCA_STEREO:
325 case DCA_STEREO_SUMDIFF:
326 case DCA_STEREO_TOTAL:
327 case DCA_DOLBY:
328 chans = 2;
329 if (pos) {
330 pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
331 pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
332 }
333 break;
334 case DCA_3F:
335 chans = 3;
336 if (pos) {
337 pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
338 pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
339 pos[2] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
340 }
341 break;
342 case DCA_2F1R:
343 chans = 3;
344 if (pos) {
345 pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
346 pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
347 pos[2] = GST_AUDIO_CHANNEL_POSITION_REAR_CENTER;
348 }
349 break;
350 case DCA_3F1R:
351 chans = 4;
352 if (pos) {
353 pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
354 pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
355 pos[2] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
356 pos[3] = GST_AUDIO_CHANNEL_POSITION_REAR_CENTER;
357 }
358 break;
359 case DCA_2F2R:
360 chans = 4;
361 if (pos) {
362 pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
363 pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
364 pos[2] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT;
365 pos[3] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT;
366 }
367 break;
368 case DCA_3F2R:
369 chans = 5;
370 if (pos) {
371 pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
372 pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
373 pos[2] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
374 pos[3] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT;
375 pos[4] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT;
376 }
377 break;
378 case DCA_4F2R:
379 chans = 6;
380 if (pos) {
381 pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER;
382 pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER;
383 pos[2] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
384 pos[3] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
385 pos[4] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT;
386 pos[5] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT;
387 }
388 break;
389 default:
390 g_warning ("dtsdec: invalid flags 0x%x", flags);
391 return 0;
392 }
393 if (flags & DCA_LFE) {
394 if (pos) {
395 pos[chans] = GST_AUDIO_CHANNEL_POSITION_LFE1;
396 }
397 chans += 1;
398 }
399
400 return chans;
401 }
402
403 static gboolean
gst_dtsdec_renegotiate(GstDtsDec * dts)404 gst_dtsdec_renegotiate (GstDtsDec * dts)
405 {
406 gint channels;
407 gboolean result = FALSE;
408 GstAudioChannelPosition from[7], to[7];
409 GstAudioInfo info;
410
411 channels = gst_dtsdec_channels (dts->using_channels, from);
412
413 if (channels <= 0 || channels > 7)
414 goto done;
415
416 GST_INFO_OBJECT (dts, "dtsdec renegotiate, channels=%d, rate=%d",
417 channels, dts->sample_rate);
418
419 memcpy (to, from, sizeof (GstAudioChannelPosition) * channels);
420 gst_audio_channel_positions_to_valid_order (to, channels);
421 gst_audio_get_channel_reorder_map (channels, from, to,
422 dts->channel_reorder_map);
423
424
425 gst_audio_info_init (&info);
426 gst_audio_info_set_format (&info,
427 SAMPLE_TYPE, dts->sample_rate, channels, (channels > 1 ? to : NULL));
428
429 if (!gst_audio_decoder_set_output_format (GST_AUDIO_DECODER (dts), &info))
430 goto done;
431
432 result = TRUE;
433
434 done:
435 return result;
436 }
437
438 static void
gst_dtsdec_update_streaminfo(GstDtsDec * dts)439 gst_dtsdec_update_streaminfo (GstDtsDec * dts)
440 {
441 GstTagList *taglist;
442
443 if (dts->bit_rate > 3) {
444 taglist = gst_tag_list_new_empty ();
445 /* 1 => open bitrate, 2 => variable bitrate, 3 => lossless */
446 gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_BITRATE,
447 (guint) dts->bit_rate, NULL);
448 gst_audio_decoder_merge_tags (GST_AUDIO_DECODER (dts), taglist,
449 GST_TAG_MERGE_REPLACE);
450 if (taglist)
451 gst_tag_list_unref (taglist);
452 }
453 }
454
455 static GstFlowReturn
gst_dtsdec_handle_frame(GstAudioDecoder * bdec,GstBuffer * buffer)456 gst_dtsdec_handle_frame (GstAudioDecoder * bdec, GstBuffer * buffer)
457 {
458 GstDtsDec *dts;
459 gint channels, i, num_blocks;
460 gboolean need_renegotiation = FALSE;
461 guint8 *data;
462 GstMapInfo map;
463 gint chans;
464 #ifndef G_DISABLE_ASSERT
465 gsize size;
466 gint length;
467 #endif
468 gint flags, sample_rate, bit_rate, frame_length;
469 GstFlowReturn result = GST_FLOW_OK;
470 GstBuffer *outbuf;
471
472 dts = GST_DTSDEC (bdec);
473
474 /* no fancy draining */
475 if (G_UNLIKELY (!buffer))
476 return GST_FLOW_OK;
477
478 /* parsed stuff already, so this should work out fine */
479 gst_buffer_map (buffer, &map, GST_MAP_READ);
480 data = map.data;
481
482 #ifndef G_DISABLE_ASSERT
483 size = map.size;
484 g_assert (size >= 7);
485 #endif
486
487 bit_rate = dts->bit_rate;
488 sample_rate = dts->sample_rate;
489 flags = 0;
490
491 #ifndef G_DISABLE_ASSERT
492 length = dca_syncinfo (dts->state, data, &flags, &sample_rate, &bit_rate,
493 &frame_length);
494 g_assert (length == size);
495 #else
496 (void) dca_syncinfo (dts->state, data, &flags, &sample_rate, &bit_rate,
497 &frame_length);
498 #endif
499
500 if (flags != dts->prev_flags) {
501 dts->prev_flags = flags;
502 dts->flag_update = TRUE;
503 }
504
505 /* go over stream properties, renegotiate or update streaminfo if needed */
506 if (dts->sample_rate != sample_rate) {
507 need_renegotiation = TRUE;
508 dts->sample_rate = sample_rate;
509 }
510
511 if (flags) {
512 dts->stream_channels = flags & (DCA_CHANNEL_MASK | DCA_LFE);
513 }
514
515 if (bit_rate != dts->bit_rate) {
516 dts->bit_rate = bit_rate;
517 gst_dtsdec_update_streaminfo (dts);
518 }
519
520 /* If we haven't had an explicit number of channels chosen through properties
521 * at this point, choose what to downmix to now, based on what the peer will
522 * accept - this allows a52dec to do downmixing in preference to a
523 * downstream element such as audioconvert.
524 * FIXME: Add the property back in for forcing output channels.
525 */
526 if (dts->request_channels != DCA_CHANNEL) {
527 flags = dts->request_channels;
528 } else if (dts->flag_update) {
529 GstCaps *caps;
530
531 dts->flag_update = FALSE;
532
533 caps = gst_pad_get_allowed_caps (GST_AUDIO_DECODER_SRC_PAD (dts));
534 if (caps && gst_caps_get_size (caps) > 0) {
535 GstCaps *copy = gst_caps_copy_nth (caps, 0);
536 GstStructure *structure = gst_caps_get_structure (copy, 0);
537 gint channels;
538 const int dts_channels[6] = {
539 DCA_MONO,
540 DCA_STEREO,
541 DCA_STEREO | DCA_LFE,
542 DCA_2F2R,
543 DCA_2F2R | DCA_LFE,
544 DCA_3F2R | DCA_LFE,
545 };
546
547 /* Prefer the original number of channels, but fixate to something
548 * preferred (first in the caps) downstream if possible.
549 */
550 gst_structure_fixate_field_nearest_int (structure, "channels",
551 flags ? gst_dtsdec_channels (flags, NULL) : 6);
552 gst_structure_get_int (structure, "channels", &channels);
553 if (channels <= 6)
554 flags = dts_channels[channels - 1];
555 else
556 flags = dts_channels[5];
557
558 gst_caps_unref (copy);
559 } else if (flags) {
560 flags = dts->stream_channels;
561 } else {
562 flags = DCA_3F2R | DCA_LFE;
563 }
564
565 if (caps)
566 gst_caps_unref (caps);
567 } else {
568 flags = dts->using_channels;
569 }
570
571 /* process */
572 flags |= DCA_ADJUST_LEVEL;
573 dts->level = 1;
574 if (dca_frame (dts->state, data, &flags, &dts->level, dts->bias)) {
575 gst_buffer_unmap (buffer, &map);
576 GST_AUDIO_DECODER_ERROR (dts, 1, STREAM, DECODE, (NULL),
577 ("dts_frame error"), result);
578 goto exit;
579 }
580 gst_buffer_unmap (buffer, &map);
581
582 channels = flags & (DCA_CHANNEL_MASK | DCA_LFE);
583 if (dts->using_channels != channels) {
584 need_renegotiation = TRUE;
585 dts->using_channels = channels;
586 }
587
588 /* negotiate if required */
589 if (need_renegotiation) {
590 GST_DEBUG_OBJECT (dts,
591 "dtsdec: sample_rate:%d stream_chans:0x%x using_chans:0x%x",
592 dts->sample_rate, dts->stream_channels, dts->using_channels);
593 if (!gst_dtsdec_renegotiate (dts))
594 goto failed_negotiation;
595 }
596
597 if (dts->dynamic_range_compression == FALSE) {
598 dca_dynrng (dts->state, NULL, NULL);
599 }
600
601 flags &= (DCA_CHANNEL_MASK | DCA_LFE);
602 chans = gst_dtsdec_channels (flags, NULL);
603 if (!chans)
604 goto invalid_flags;
605
606 /* handle decoded data, one block is 256 samples */
607 num_blocks = dca_blocks_num (dts->state);
608 outbuf =
609 gst_buffer_new_and_alloc (256 * chans * (SAMPLE_WIDTH / 8) * num_blocks);
610
611 gst_buffer_map (outbuf, &map, GST_MAP_WRITE);
612 data = map.data;
613 {
614 guint8 *ptr = data;
615 for (i = 0; i < num_blocks; i++) {
616 if (dca_block (dts->state)) {
617 /* also marks discont */
618 GST_AUDIO_DECODER_ERROR (dts, 1, STREAM, DECODE, (NULL),
619 ("error decoding block %d", i), result);
620 if (result != GST_FLOW_OK)
621 goto exit;
622 } else {
623 gint n, c;
624 gint *reorder_map = dts->channel_reorder_map;
625
626 for (n = 0; n < 256; n++) {
627 for (c = 0; c < chans; c++) {
628 ((sample_t *) ptr)[n * chans + reorder_map[c]] =
629 dts->samples[c * 256 + n];
630 }
631 }
632 }
633 ptr += 256 * chans * (SAMPLE_WIDTH / 8);
634 }
635 }
636 gst_buffer_unmap (outbuf, &map);
637
638 result = gst_audio_decoder_finish_frame (bdec, outbuf, 1);
639
640 exit:
641 return result;
642
643 /* ERRORS */
644 failed_negotiation:
645 {
646 GST_ELEMENT_ERROR (dts, CORE, NEGOTIATION, (NULL), (NULL));
647 return GST_FLOW_ERROR;
648 }
649 invalid_flags:
650 {
651 GST_ELEMENT_ERROR (GST_ELEMENT (dts), STREAM, DECODE, (NULL),
652 ("Invalid channel flags: %d", flags));
653 return GST_FLOW_ERROR;
654 }
655 }
656
657 static gboolean
gst_dtsdec_set_format(GstAudioDecoder * bdec,GstCaps * caps)658 gst_dtsdec_set_format (GstAudioDecoder * bdec, GstCaps * caps)
659 {
660 GstDtsDec *dts = GST_DTSDEC (bdec);
661 GstStructure *structure;
662
663 structure = gst_caps_get_structure (caps, 0);
664
665 if (structure && gst_structure_has_name (structure, "audio/x-private1-dts"))
666 dts->dvdmode = TRUE;
667 else
668 dts->dvdmode = FALSE;
669
670 return TRUE;
671 }
672
673 static GstFlowReturn
gst_dtsdec_chain(GstPad * pad,GstObject * parent,GstBuffer * buf)674 gst_dtsdec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
675 {
676 GstFlowReturn ret = GST_FLOW_OK;
677 GstDtsDec *dts = GST_DTSDEC (parent);
678 gint first_access;
679
680 if (dts->dvdmode) {
681 guint8 data[2];
682 gsize size;
683 gint offset, len;
684 GstBuffer *subbuf;
685
686 size = gst_buffer_get_size (buf);
687 if (size < 2)
688 goto not_enough_data;
689
690 gst_buffer_extract (buf, 0, data, 2);
691 first_access = (data[0] << 8) | data[1];
692
693 /* Skip the first_access header */
694 offset = 2;
695
696 if (first_access > 1) {
697 /* Length of data before first_access */
698 len = first_access - 1;
699
700 if (len <= 0 || offset + len > size)
701 goto bad_first_access_parameter;
702
703 subbuf = gst_buffer_copy_region (buf, GST_BUFFER_COPY_ALL, offset, len);
704 GST_BUFFER_TIMESTAMP (subbuf) = GST_CLOCK_TIME_NONE;
705 ret = dts->base_chain (pad, parent, subbuf);
706 if (ret != GST_FLOW_OK) {
707 gst_buffer_unref (buf);
708 goto done;
709 }
710
711 offset += len;
712 len = size - offset;
713
714 if (len > 0) {
715 subbuf = gst_buffer_copy_region (buf, GST_BUFFER_COPY_ALL, offset, len);
716 GST_BUFFER_TIMESTAMP (subbuf) = GST_BUFFER_TIMESTAMP (buf);
717
718 ret = dts->base_chain (pad, parent, subbuf);
719 }
720 gst_buffer_unref (buf);
721 } else {
722 /* first_access = 0 or 1, so if there's a timestamp it applies to the first byte */
723 subbuf =
724 gst_buffer_copy_region (buf, GST_BUFFER_COPY_ALL, offset,
725 size - offset);
726 GST_BUFFER_TIMESTAMP (subbuf) = GST_BUFFER_TIMESTAMP (buf);
727 ret = dts->base_chain (pad, parent, subbuf);
728 gst_buffer_unref (buf);
729 }
730 } else {
731 ret = dts->base_chain (pad, parent, buf);
732 }
733
734 done:
735 return ret;
736
737 /* ERRORS */
738 not_enough_data:
739 {
740 GST_ELEMENT_ERROR (GST_ELEMENT (dts), STREAM, DECODE, (NULL),
741 ("Insufficient data in buffer. Can't determine first_acess"));
742 gst_buffer_unref (buf);
743 return GST_FLOW_ERROR;
744 }
745 bad_first_access_parameter:
746 {
747 GST_ELEMENT_ERROR (GST_ELEMENT (dts), STREAM, DECODE, (NULL),
748 ("Bad first_access parameter (%d) in buffer", first_access));
749 gst_buffer_unref (buf);
750 return GST_FLOW_ERROR;
751 }
752 }
753
754 static void
gst_dtsdec_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)755 gst_dtsdec_set_property (GObject * object, guint prop_id, const GValue * value,
756 GParamSpec * pspec)
757 {
758 GstDtsDec *dts = GST_DTSDEC (object);
759
760 switch (prop_id) {
761 case PROP_DRC:
762 dts->dynamic_range_compression = g_value_get_boolean (value);
763 break;
764 default:
765 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
766 break;
767 }
768 }
769
770 static void
gst_dtsdec_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)771 gst_dtsdec_get_property (GObject * object, guint prop_id, GValue * value,
772 GParamSpec * pspec)
773 {
774 GstDtsDec *dts = GST_DTSDEC (object);
775
776 switch (prop_id) {
777 case PROP_DRC:
778 g_value_set_boolean (value, dts->dynamic_range_compression);
779 break;
780 default:
781 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
782 break;
783 }
784 }
785
786 static gboolean
plugin_init(GstPlugin * plugin)787 plugin_init (GstPlugin * plugin)
788 {
789 GST_DEBUG_CATEGORY_INIT (dtsdec_debug, "dtsdec", 0, "DTS/DCA audio decoder");
790
791 #if HAVE_ORC
792 orc_init ();
793 #endif
794
795 if (!gst_element_register (plugin, "dtsdec", GST_RANK_PRIMARY,
796 GST_TYPE_DTSDEC))
797 return FALSE;
798
799 return TRUE;
800 }
801
802 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
803 GST_VERSION_MINOR,
804 dtsdec,
805 "Decodes DTS audio streams",
806 plugin_init, VERSION, "GPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);
807