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
gst_dtsdec_class_init(GstDtsDecClass * klass)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
gst_dtsdec_init(GstDtsDec * dtsdec)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
gst_dtsdec_start(GstAudioDecoder * dec)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
gst_dtsdec_stop(GstAudioDecoder * dec)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
gst_dtsdec_parse(GstAudioDecoder * bdec,GstAdapter * adapter,gint * _offset,gint * len)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
gst_dtsdec_channels(uint32_t flags,GstAudioChannelPosition * pos)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
gst_dtsdec_renegotiate(GstDtsDec * dts)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
gst_dtsdec_update_streaminfo(GstDtsDec * dts)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
gst_dtsdec_handle_frame(GstAudioDecoder * bdec,GstBuffer * buffer)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
gst_dtsdec_set_format(GstAudioDecoder * bdec,GstCaps * caps)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
gst_dtsdec_chain(GstPad * pad,GstObject * parent,GstBuffer * buf)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
gst_dtsdec_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)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
gst_dtsdec_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)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
dtsdec_element_init(GstPlugin * plugin)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
plugin_init(GstPlugin * plugin)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);
814