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>
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.
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.
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., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
22 * SECTION:element-dtsdec
24 * Digital Theatre System (DTS) audio decoder
27 * <title>Example launch line</title>
29 * gst-launch dvdreadsrc title=1 ! mpegpsdemux ! dtsdec ! audioresample ! audioconvert ! alsasink
30 * ]| Play a DTS audio track from a dvd.
32 * gst-launch filesrc location=abc.dts ! dtsdec ! audioresample ! audioconvert ! alsasink
33 * ]| Decode a standalone file and play it.
46 #include <gst/audio/multichannel.h>
53 typedef struct dts_state_s dca_state_t;
54 #define DCA_MONO DTS_MONO
55 #define DCA_CHANNEL DTS_CHANNEL
56 #define DCA_STEREO DTS_STEREO
57 #define DCA_STEREO_SUMDIFF DTS_STEREO_SUMDIFF
58 #define DCA_STEREO_TOTAL DTS_STEREO_TOTAL
60 #define DCA_2F1R DTS_2F1R
61 #define DCA_3F1R DTS_3F1R
62 #define DCA_2F2R DTS_2F2R
63 #define DCA_3F2R DTS_3F2R
64 #define DCA_4F2R DTS_4F2R
65 #define DCA_DOLBY DTS_DOLBY
66 #define DCA_CHANNEL_MAX DTS_CHANNEL_MAX
67 #define DCA_CHANNEL_BITS DTS_CHANNEL_BITS
68 #define DCA_CHANNEL_MASK DTS_CHANNEL_MASK
69 #define DCA_LFE DTS_LFE
70 #define DCA_ADJUST_LEVEL DTS_ADJUST_LEVEL
72 #define dca_init dts_init
73 #define dca_syncinfo dts_syncinfo
74 #define dca_frame dts_frame
75 #define dca_dynrng dts_dynrng
76 #define dca_blocks_num dts_blocks_num
77 #define dca_block dts_block
78 #define dca_samples dts_samples
79 #define dca_free dts_free
82 #include "gstdtsdec.h"
84 #include <liboil/liboil.h>
85 #include <liboil/liboilcpu.h>
86 #include <liboil/liboilfunction.h>
88 static const GstElementDetails gst_dtsdec_details =
89 GST_ELEMENT_DETAILS ("DTS audio decoder",
90 "Codec/Decoder/Audio",
91 "Decodes DTS audio streams",
92 "Jan Schmidt <thaytan@noraisin.net>\n"
93 "Ronald Bultje <rbultje@ronald.bitfreak.net>");
95 #if defined(LIBDTS_FIXED) || defined(LIBDCA_FIXED)
96 #define SAMPLE_WIDTH 16
97 #elif defined (LIBDTS_DOUBLE) || defined(LIBDCA_DOUBLE)
98 #define SAMPLE_WIDTH 64
100 #define SAMPLE_WIDTH 32
103 GST_DEBUG_CATEGORY_STATIC (dtsdec_debug);
104 #define GST_CAT_DEFAULT (dtsdec_debug)
112 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
115 GST_STATIC_CAPS ("audio/x-dts; audio/x-private1-dts")
118 #if defined(LIBDTS_FIXED) || defined(LIBDCA_FIXED)
119 #define DTS_CAPS "audio/x-raw-int, " \
120 "endianness = (int) " G_STRINGIFY (G_BYTE_ORDER) ", " \
121 "signed = (boolean) true, " \
122 "width = (int) " G_STRINGIFY (SAMPLE_WIDTH) ", " \
125 #define DTS_CAPS "audio/x-raw-float, " \
126 "endianness = (int) " G_STRINGIFY (G_BYTE_ORDER) ", " \
127 "width = (int) " G_STRINGIFY (SAMPLE_WIDTH)
130 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
133 GST_STATIC_CAPS (DTS_CAPS ", "
134 "rate = (int) [ 4000, 96000 ], " "channels = (int) [ 1, 6 ]")
137 GST_BOILERPLATE (GstDtsDec, gst_dtsdec, GstElement, GST_TYPE_ELEMENT);
139 static gboolean gst_dtsdec_sink_setcaps (GstPad * pad, GstCaps * caps);
140 static gboolean gst_dtsdec_sink_event (GstPad * pad, GstEvent * event);
141 static GstFlowReturn gst_dtsdec_chain (GstPad * pad, GstBuffer * buf);
142 static GstFlowReturn gst_dtsdec_chain_raw (GstPad * pad, GstBuffer * buf);
143 static GstStateChangeReturn gst_dtsdec_change_state (GstElement * element,
144 GstStateChange transition);
146 static void gst_dtsdec_set_property (GObject * object, guint prop_id,
147 const GValue * value, GParamSpec * pspec);
148 static void gst_dtsdec_get_property (GObject * object, guint prop_id,
149 GValue * value, GParamSpec * pspec);
153 gst_dtsdec_base_init (gpointer g_class)
155 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
157 gst_element_class_add_pad_template (element_class,
158 gst_static_pad_template_get (&sink_factory));
159 gst_element_class_add_pad_template (element_class,
160 gst_static_pad_template_get (&src_factory));
161 gst_element_class_set_details (element_class, &gst_dtsdec_details);
163 GST_DEBUG_CATEGORY_INIT (dtsdec_debug, "dtsdec", 0, "DTS/DCA audio decoder");
167 gst_dtsdec_class_init (GstDtsDecClass * klass)
169 GObjectClass *gobject_class;
170 GstElementClass *gstelement_class;
173 gobject_class = (GObjectClass *) klass;
174 gstelement_class = (GstElementClass *) klass;
176 gobject_class->set_property = gst_dtsdec_set_property;
177 gobject_class->get_property = gst_dtsdec_get_property;
179 gstelement_class->change_state = gst_dtsdec_change_state;
184 * Set to true to apply the recommended DTS dynamic range compression
185 * to the audio stream. Dynamic range compression makes loud sounds
186 * softer and soft sounds louder, so you can more easily listen
187 * to the stream without disturbing other people.
189 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DRC,
190 g_param_spec_boolean ("drc", "Dynamic Range Compression",
191 "Use Dynamic Range Compression", FALSE, G_PARAM_READWRITE));
195 klass->dts_cpuflags = 0;
196 cpuflags = oil_cpu_get_flags ();
197 if (cpuflags & OIL_IMPL_FLAG_MMX)
198 klass->dts_cpuflags |= MM_ACCEL_X86_MMX;
199 if (cpuflags & OIL_IMPL_FLAG_3DNOW)
200 klass->dts_cpuflags |= MM_ACCEL_X86_3DNOW;
201 if (cpuflags & OIL_IMPL_FLAG_MMXEXT)
202 klass->dts_cpuflags |= MM_ACCEL_X86_MMXEXT;
204 GST_LOG ("CPU flags: dts=%08x, liboil=%08x", klass->dts_cpuflags, cpuflags);
208 gst_dtsdec_init (GstDtsDec * dtsdec, GstDtsDecClass * g_class)
210 /* create the sink and src pads */
211 dtsdec->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink");
212 gst_pad_set_setcaps_function (dtsdec->sinkpad,
213 GST_DEBUG_FUNCPTR (gst_dtsdec_sink_setcaps));
214 gst_pad_set_chain_function (dtsdec->sinkpad,
215 GST_DEBUG_FUNCPTR (gst_dtsdec_chain));
216 gst_pad_set_event_function (dtsdec->sinkpad,
217 GST_DEBUG_FUNCPTR (gst_dtsdec_sink_event));
218 gst_element_add_pad (GST_ELEMENT (dtsdec), dtsdec->sinkpad);
220 dtsdec->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
221 gst_element_add_pad (GST_ELEMENT (dtsdec), dtsdec->srcpad);
223 dtsdec->request_channels = DCA_CHANNEL;
224 dtsdec->dynamic_range_compression = FALSE;
226 gst_segment_init (&dtsdec->segment, GST_FORMAT_UNDEFINED);
230 gst_dtsdec_channels (uint32_t flags, GstAudioChannelPosition ** pos)
233 GstAudioChannelPosition *tpos = NULL;
236 /* Allocate the maximum, for ease */
237 tpos = *pos = g_new (GstAudioChannelPosition, 7);
242 switch (flags & DCA_CHANNEL_MASK) {
246 tpos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_MONO;
248 /* case DCA_CHANNEL: */
250 case DCA_STEREO_SUMDIFF:
251 case DCA_STEREO_TOTAL:
255 tpos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
256 tpos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
262 tpos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
263 tpos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
264 tpos[2] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
270 tpos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
271 tpos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
272 tpos[2] = GST_AUDIO_CHANNEL_POSITION_REAR_CENTER;
278 tpos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
279 tpos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
280 tpos[2] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
281 tpos[3] = GST_AUDIO_CHANNEL_POSITION_REAR_CENTER;
287 tpos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
288 tpos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
289 tpos[2] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT;
290 tpos[3] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT;
296 tpos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
297 tpos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
298 tpos[2] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
299 tpos[3] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT;
300 tpos[4] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT;
306 tpos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER;
307 tpos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER;
308 tpos[2] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
309 tpos[3] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
310 tpos[4] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT;
311 tpos[5] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT;
315 g_warning ("dtsdec: invalid flags 0x%x", flags);
318 if (flags & DCA_LFE) {
320 tpos[chans] = GST_AUDIO_CHANNEL_POSITION_LFE;
329 clear_queued (GstDtsDec * dec)
331 g_list_foreach (dec->queued, (GFunc) gst_mini_object_unref, NULL);
332 g_list_free (dec->queued);
337 flush_queued (GstDtsDec * dec)
339 GstFlowReturn ret = GST_FLOW_OK;
341 while (dec->queued) {
342 GstBuffer *buf = GST_BUFFER_CAST (dec->queued->data);
344 GST_LOG_OBJECT (dec, "pushing buffer %p, timestamp %"
345 GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT, buf,
346 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
347 GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
349 /* iterate ouput queue an push downstream */
350 ret = gst_pad_push (dec->srcpad, buf);
352 dec->queued = g_list_delete_link (dec->queued, dec->queued);
358 gst_dtsdec_drain (GstDtsDec * dec)
360 GstFlowReturn ret = GST_FLOW_OK;
362 if (dec->segment.rate < 0.0) {
363 /* if we have some queued frames for reverse playback, flush
365 ret = flush_queued (dec);
371 gst_dtsdec_push (GstDtsDec * dtsdec,
372 GstPad * srcpad, int flags, sample_t * samples, GstClockTime timestamp)
376 GstFlowReturn result;
378 flags &= (DCA_CHANNEL_MASK | DCA_LFE);
379 chans = gst_dtsdec_channels (flags, NULL);
381 GST_ELEMENT_ERROR (GST_ELEMENT (dtsdec), STREAM, DECODE, (NULL),
382 ("Invalid channel flags: %d", flags));
383 return GST_FLOW_ERROR;
387 gst_pad_alloc_buffer_and_set_caps (srcpad, 0,
388 256 * chans * (SAMPLE_WIDTH / 8), GST_PAD_CAPS (srcpad), &buf);
389 if (result != GST_FLOW_OK)
392 for (n = 0; n < 256; n++) {
393 for (c = 0; c < chans; c++) {
394 ((sample_t *) GST_BUFFER_DATA (buf))[n * chans + c] =
395 samples[c * 256 + n];
398 GST_BUFFER_TIMESTAMP (buf) = timestamp;
399 GST_BUFFER_DURATION (buf) = 256 * GST_SECOND / dtsdec->sample_rate;
401 result = GST_FLOW_OK;
402 if ((buf = gst_audio_buffer_clip (buf, &dtsdec->segment,
403 dtsdec->sample_rate, (SAMPLE_WIDTH / 8) * chans))) {
404 /* set discont when needed */
405 if (dtsdec->discont) {
406 GST_LOG_OBJECT (dtsdec, "marking DISCONT");
407 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
408 dtsdec->discont = FALSE;
411 if (dtsdec->segment.rate > 0.0) {
412 GST_DEBUG_OBJECT (dtsdec,
413 "Pushing buffer with ts %" GST_TIME_FORMAT " duration %"
414 GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
415 GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
417 result = gst_pad_push (srcpad, buf);
419 /* reverse playback, queue frame till later when we get a discont. */
420 GST_DEBUG_OBJECT (dtsdec, "queued frame");
421 dtsdec->queued = g_list_prepend (dtsdec->queued, buf);
428 gst_dtsdec_renegotiate (GstDtsDec * dts)
430 GstAudioChannelPosition *pos;
431 GstCaps *caps = gst_caps_from_string (DTS_CAPS);
432 gint channels = gst_dtsdec_channels (dts->using_channels, &pos);
433 gboolean result = FALSE;
438 GST_INFO ("dtsdec renegotiate, channels=%d, rate=%d",
439 channels, dts->sample_rate);
441 gst_caps_set_simple (caps,
442 "channels", G_TYPE_INT, channels,
443 "rate", G_TYPE_INT, (gint) dts->sample_rate, NULL);
444 gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos);
447 if (!gst_pad_set_caps (dts->srcpad, caps))
454 gst_caps_unref (caps);
460 gst_dtsdec_sink_event (GstPad * pad, GstEvent * event)
462 GstDtsDec *dtsdec = GST_DTSDEC (gst_pad_get_parent (pad));
463 gboolean ret = FALSE;
465 GST_LOG_OBJECT (dtsdec, "%s event", GST_EVENT_TYPE_NAME (event));
467 switch (GST_EVENT_TYPE (event)) {
468 case GST_EVENT_NEWSEGMENT:{
471 gint64 start, end, pos;
474 gst_event_parse_new_segment (event, &update, &rate, &format, &start, &end,
477 /* drain queued buffers before activating the segment so that we can clip
478 * against the old segment first */
479 gst_dtsdec_drain (dtsdec);
481 if (format != GST_FORMAT_TIME || !GST_CLOCK_TIME_IS_VALID (start)) {
482 GST_WARNING ("No time in newsegment event %p (format is %s)",
483 event, gst_format_get_name (format));
484 gst_event_unref (event);
485 dtsdec->sent_segment = FALSE;
486 /* set some dummy values, FIXME: do proper conversion */
487 dtsdec->time = start = pos = 0;
488 format = GST_FORMAT_TIME;
491 dtsdec->time = start;
492 dtsdec->sent_segment = TRUE;
493 ret = gst_pad_push_event (dtsdec->srcpad, event);
496 gst_segment_set_newsegment (&dtsdec->segment, update, rate, format, start,
501 ret = gst_pad_push_event (dtsdec->srcpad, event);
504 gst_dtsdec_drain (dtsdec);
505 ret = gst_pad_push_event (dtsdec->srcpad, event);
507 case GST_EVENT_FLUSH_START:
508 ret = gst_pad_push_event (dtsdec->srcpad, event);
510 case GST_EVENT_FLUSH_STOP:
512 gst_buffer_unref (dtsdec->cache);
513 dtsdec->cache = NULL;
515 clear_queued (dtsdec);
516 gst_segment_init (&dtsdec->segment, GST_FORMAT_UNDEFINED);
517 ret = gst_pad_push_event (dtsdec->srcpad, event);
520 ret = gst_pad_push_event (dtsdec->srcpad, event);
524 gst_object_unref (dtsdec);
529 gst_dtsdec_update_streaminfo (GstDtsDec * dts)
533 taglist = gst_tag_list_new ();
535 gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND,
536 GST_TAG_AUDIO_CODEC, "DTS DCA",
537 GST_TAG_BITRATE, (guint) dts->bit_rate, NULL);
539 gst_element_found_tags_for_pad (GST_ELEMENT (dts), dts->srcpad, taglist);
543 gst_dtsdec_handle_frame (GstDtsDec * dts, guint8 * data,
544 guint length, gint flags, gint sample_rate, gint bit_rate)
546 gint channels, i, num_blocks;
547 gboolean need_renegotiation = FALSE;
549 /* go over stream properties, renegotiate or update streaminfo if needed */
550 if (dts->sample_rate != sample_rate) {
551 need_renegotiation = TRUE;
552 dts->sample_rate = sample_rate;
556 dts->stream_channels = flags & (DCA_CHANNEL_MASK | DCA_LFE);
559 if (bit_rate != dts->bit_rate) {
560 dts->bit_rate = bit_rate;
561 gst_dtsdec_update_streaminfo (dts);
564 /* If we haven't had an explicit number of channels chosen through properties
565 * at this point, choose what to downmix to now, based on what the peer will
566 * accept - this allows a52dec to do downmixing in preference to a
567 * downstream element such as audioconvert.
568 * FIXME: Add the property back in for forcing output channels.
570 if (dts->request_channels != DCA_CHANNEL) {
571 flags = dts->request_channels;
572 } else if (dts->flag_update) {
575 dts->flag_update = FALSE;
577 caps = gst_pad_get_allowed_caps (dts->srcpad);
578 if (caps && gst_caps_get_size (caps) > 0) {
579 GstCaps *copy = gst_caps_copy_nth (caps, 0);
580 GstStructure *structure = gst_caps_get_structure (copy, 0);
582 const int dts_channels[6] = {
585 DCA_STEREO | DCA_LFE,
591 /* Prefer the original number of channels, but fixate to something
592 * preferred (first in the caps) downstream if possible.
594 gst_structure_fixate_field_nearest_int (structure, "channels",
595 flags ? gst_dtsdec_channels (flags, NULL) : 6);
596 gst_structure_get_int (structure, "channels", &channels);
598 flags = dts_channels[channels - 1];
600 flags = dts_channels[5];
602 gst_caps_unref (copy);
604 flags = dts->stream_channels;
606 flags = DCA_3F2R | DCA_LFE;
610 gst_caps_unref (caps);
612 flags = dts->using_channels;
615 flags |= DCA_ADJUST_LEVEL;
617 if (dca_frame (dts->state, data, &flags, &dts->level, dts->bias)) {
618 GST_WARNING_OBJECT (dts, "dts_frame error");
622 channels = flags & (DCA_CHANNEL_MASK | DCA_LFE);
623 if (dts->using_channels != channels) {
624 need_renegotiation = TRUE;
625 dts->using_channels = channels;
628 /* negotiate if required */
629 if (need_renegotiation) {
630 GST_DEBUG ("dtsdec: sample_rate:%d stream_chans:0x%x using_chans:0x%x",
631 dts->sample_rate, dts->stream_channels, dts->using_channels);
632 if (!gst_dtsdec_renegotiate (dts)) {
633 GST_ELEMENT_ERROR (dts, CORE, NEGOTIATION, (NULL), (NULL));
634 return GST_FLOW_ERROR;
638 if (dts->dynamic_range_compression == FALSE) {
639 dca_dynrng (dts->state, NULL, NULL);
642 /* handle decoded data, one block is 256 samples */
643 num_blocks = dca_blocks_num (dts->state);
644 for (i = 0; i < num_blocks; i++) {
645 if (dca_block (dts->state)) {
646 /* Ignore errors, but mark a discont */
647 GST_WARNING_OBJECT (dts, "dts_block error %d", i);
653 ret = gst_dtsdec_push (dts, dts->srcpad, dts->using_channels,
654 dts->samples, dts->time);
655 if (ret != GST_FLOW_OK)
658 dts->time += GST_SECOND * 256 / dts->sample_rate;
665 gst_dtsdec_sink_setcaps (GstPad * pad, GstCaps * caps)
667 GstDtsDec *dts = GST_DTSDEC (gst_pad_get_parent (pad));
668 GstStructure *structure;
670 structure = gst_caps_get_structure (caps, 0);
672 if (structure && gst_structure_has_name (structure, "audio/x-private1-dts"))
675 dts->dvdmode = FALSE;
677 gst_object_unref (dts);
683 gst_dtsdec_chain (GstPad * pad, GstBuffer * buf)
685 GstFlowReturn ret = GST_FLOW_OK;
686 GstDtsDec *dts = GST_DTSDEC (GST_PAD_PARENT (pad));
689 if (GST_BUFFER_IS_DISCONT (buf)) {
690 GST_LOG_OBJECT (dts, "received DISCONT");
691 gst_dtsdec_drain (dts);
692 /* clear cache on discont and mark a discont in the element */
694 gst_buffer_unref (dts->cache);
701 gint size = GST_BUFFER_SIZE (buf);
702 guint8 *data = GST_BUFFER_DATA (buf);
707 goto not_enough_data;
709 first_access = (data[0] << 8) | data[1];
711 /* Skip the first_access header */
714 if (first_access > 1) {
715 /* Length of data before first_access */
716 len = first_access - 1;
718 if (len <= 0 || offset + len > size)
719 goto bad_first_access_parameter;
721 subbuf = gst_buffer_create_sub (buf, offset, len);
722 GST_BUFFER_TIMESTAMP (subbuf) = GST_CLOCK_TIME_NONE;
723 ret = gst_dtsdec_chain_raw (pad, subbuf);
724 if (ret != GST_FLOW_OK)
731 subbuf = gst_buffer_create_sub (buf, offset, len);
732 GST_BUFFER_TIMESTAMP (subbuf) = GST_BUFFER_TIMESTAMP (buf);
734 ret = gst_dtsdec_chain_raw (pad, subbuf);
737 /* first_access = 0 or 1, so if there's a timestamp it applies to the first byte */
738 subbuf = gst_buffer_create_sub (buf, offset, size - offset);
739 GST_BUFFER_TIMESTAMP (subbuf) = GST_BUFFER_TIMESTAMP (buf);
740 ret = gst_dtsdec_chain_raw (pad, subbuf);
743 gst_buffer_ref (buf);
744 ret = gst_dtsdec_chain_raw (pad, buf);
748 gst_buffer_unref (buf);
754 GST_ELEMENT_ERROR (GST_ELEMENT (dts), STREAM, DECODE, (NULL),
755 ("Insufficient data in buffer. Can't determine first_acess"));
756 gst_buffer_unref (buf);
757 return GST_FLOW_ERROR;
759 bad_first_access_parameter:
761 GST_ELEMENT_ERROR (GST_ELEMENT (dts), STREAM, DECODE, (NULL),
762 ("Bad first_access parameter (%d) in buffer", first_access));
763 gst_buffer_unref (buf);
764 return GST_FLOW_ERROR;
769 gst_dtsdec_chain_raw (GstPad * pad, GstBuffer * buf)
774 gint length = 0, flags, sample_rate, bit_rate, frame_length;
775 GstFlowReturn result = GST_FLOW_OK;
777 dts = GST_DTSDEC (GST_PAD_PARENT (pad));
779 if (!dts->sent_segment) {
782 /* Create a basic segment. Usually, we'll get a new-segment sent by
783 * another element that will know more information (a demuxer). If we're
784 * just looking at a raw AC3 stream, we won't - so we need to send one
785 * here, but we don't know much info, so just send a minimal TIME
788 gst_segment_init (&segment, GST_FORMAT_TIME);
789 gst_pad_push_event (dts->srcpad, gst_event_new_new_segment (FALSE,
790 segment.rate, segment.format, segment.start,
791 segment.duration, segment.start));
792 dts->sent_segment = TRUE;
795 /* merge with cache, if any. Also make sure timestamps match */
796 if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
797 dts->time = GST_BUFFER_TIMESTAMP (buf);
798 GST_DEBUG_OBJECT (dts,
799 "Received buffer with ts %" GST_TIME_FORMAT " duration %"
800 GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
801 GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
805 buf = gst_buffer_join (dts->cache, buf);
808 data = GST_BUFFER_DATA (buf);
809 size = GST_BUFFER_SIZE (buf);
811 /* find and read header */
812 bit_rate = dts->bit_rate;
813 sample_rate = dts->sample_rate;
816 length = dca_syncinfo (dts->state, data, &flags,
817 &sample_rate, &bit_rate, &frame_length);
820 /* shift window to re-find sync */
823 } else if (length <= size) {
824 GST_DEBUG ("Sync: frame size %d", length);
826 if (flags != dts->prev_flags)
827 dts->flag_update = TRUE;
828 dts->prev_flags = flags;
830 result = gst_dtsdec_handle_frame (dts, data, length,
831 flags, sample_rate, bit_rate);
832 if (result != GST_FLOW_OK) {
839 GST_LOG ("Not enough data available (needed %d had %d)", length, size);
846 GST_LOG ("No sync found");
850 dts->cache = gst_buffer_create_sub (buf,
851 GST_BUFFER_SIZE (buf) - size, size);
854 gst_buffer_unref (buf);
859 static GstStateChangeReturn
860 gst_dtsdec_change_state (GstElement * element, GstStateChange transition)
862 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
863 GstDtsDec *dts = GST_DTSDEC (element);
865 switch (transition) {
866 case GST_STATE_CHANGE_NULL_TO_READY:{
867 GstDtsDecClass *klass;
869 klass = GST_DTSDEC_CLASS (G_OBJECT_GET_CLASS (dts));
870 dts->state = dca_init (klass->dts_cpuflags);
873 case GST_STATE_CHANGE_READY_TO_PAUSED:
874 dts->samples = dca_samples (dts->state);
876 dts->sample_rate = -1;
877 dts->stream_channels = DCA_CHANNEL;
878 dts->using_channels = DCA_CHANNEL;
882 dts->sent_segment = FALSE;
883 dts->flag_update = TRUE;
884 gst_segment_init (&dts->segment, GST_FORMAT_UNDEFINED);
886 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
892 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
894 switch (transition) {
895 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
897 case GST_STATE_CHANGE_PAUSED_TO_READY:
900 gst_buffer_unref (dts->cache);
905 case GST_STATE_CHANGE_READY_TO_NULL:
906 dca_free (dts->state);
917 gst_dtsdec_set_property (GObject * object, guint prop_id, const GValue * value,
920 GstDtsDec *dts = GST_DTSDEC (object);
924 dts->dynamic_range_compression = g_value_get_boolean (value);
927 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
933 gst_dtsdec_get_property (GObject * object, guint prop_id, GValue * value,
936 GstDtsDec *dts = GST_DTSDEC (object);
940 g_value_set_boolean (value, dts->dynamic_range_compression);
943 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
949 plugin_init (GstPlugin * plugin)
951 if (!gst_element_register (plugin, "dtsdec", GST_RANK_PRIMARY,
958 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
961 "Decodes DTS audio streams",
962 plugin_init, VERSION, "GPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);