1 /*****************************************************************************
2 * dts.c: parse DTS audio sync info and packetize the stream
3 *****************************************************************************
4 * Copyright (C) 2003 VideoLAN
5 * $Id: dts.c,v 1.5 2003/11/16 21:07:30 gbazin Exp $
7 * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
8 * Gildas Bazin <gbazin@netcourrier.com>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
30 #include <string.h> /* memcpy() */
33 #include <vlc/decoder.h>
34 #include <vlc/input.h>
36 #include "vlc_block_helper.h"
38 #define DTS_HEADER_SIZE 10
40 /*****************************************************************************
41 * decoder_sys_t : decoder descriptor
42 *****************************************************************************/
46 vlc_bool_t b_packetizer;
53 block_bytestream_t bytestream;
58 audio_date_t end_date;
62 int i_frame_size, i_bit_rate;
63 unsigned int i_frame_length, i_rate, i_channels, i_channels_conf;
65 /* This is very hacky. For DTS over S/PDIF we apparently need to send
66 * 3 frames at a time. This should likely be moved to the output stage. */
68 aout_buffer_t *p_aout_buffer; /* current aout buffer being filled */
82 /****************************************************************************
84 ****************************************************************************/
85 static int OpenDecoder ( vlc_object_t * );
86 static int OpenPacketizer( vlc_object_t * );
87 static void CloseDecoder ( vlc_object_t * );
88 static void *DecodeBlock ( decoder_t *, block_t ** );
90 static int SyncInfo ( const byte_t *, unsigned int *, unsigned int *,
91 unsigned int *, unsigned int *, unsigned int * );
93 static uint8_t *GetOutBuffer ( decoder_t *, void ** );
94 static aout_buffer_t *GetAoutBuffer( decoder_t * );
95 static block_t *GetSoutBuffer( decoder_t * );
97 /*****************************************************************************
99 *****************************************************************************/
101 set_description( _("DTS parser") );
102 set_capability( "decoder", 100 );
103 set_callbacks( OpenDecoder, CloseDecoder );
106 set_description( _("DTS audio packetizer") );
107 set_capability( "packetizer", 10 );
108 set_callbacks( OpenPacketizer, NULL );
111 /*****************************************************************************
112 * OpenDecoder: probe the decoder and return score
113 *****************************************************************************/
114 static int OpenDecoder( vlc_object_t *p_this )
116 decoder_t *p_dec = (decoder_t*)p_this;
117 decoder_sys_t *p_sys;
119 if( p_dec->fmt_in.i_codec != VLC_FOURCC('d','t','s',' ')
120 && p_dec->fmt_in.i_codec != VLC_FOURCC('d','t','s','b') )
125 /* Allocate the memory needed to store the decoder's structure */
126 if( ( p_dec->p_sys = p_sys =
127 (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
129 msg_Err( p_dec, "out of memory" );
134 p_sys->b_packetizer = VLC_FALSE;
135 p_sys->i_state = STATE_NOSYNC;
136 aout_DateSet( &p_sys->end_date, 0 );
137 p_sys->i_frames_in_buf = 0;
139 p_sys->bytestream = block_BytestreamInit( p_dec );
141 /* Set output properties */
142 p_dec->fmt_out.i_cat = AUDIO_ES;
143 p_dec->fmt_out.i_codec = VLC_FOURCC('d','t','s',' ');
146 p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **))
148 p_dec->pf_packetize = (block_t *(*)(decoder_t *, block_t **))
154 static int OpenPacketizer( vlc_object_t *p_this )
156 decoder_t *p_dec = (decoder_t*)p_this;
158 int i_ret = OpenDecoder( p_this );
160 if( i_ret == VLC_SUCCESS ) p_dec->p_sys->b_packetizer = VLC_TRUE;
165 /****************************************************************************
166 * DecodeBlock: the whole thing
167 ****************************************************************************
168 * This function is called just after the thread is launched.
169 ****************************************************************************/
170 static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
172 decoder_sys_t *p_sys = p_dec->p_sys;
173 uint8_t p_header[DTS_HEADER_SIZE];
177 if( !pp_block || !*pp_block ) return NULL;
179 if( !aout_DateGet( &p_sys->end_date ) && !(*pp_block)->i_pts )
181 /* We've just started the stream, wait for the first PTS. */
182 block_Release( *pp_block );
186 if( (*pp_block)->b_discontinuity )
188 p_sys->i_state = STATE_NOSYNC;
191 block_BytestreamPush( &p_sys->bytestream, *pp_block );
195 switch( p_sys->i_state )
198 /* Look for sync dword - should be 0x7ffe8001 */
199 while( block_PeekBytes( &p_sys->bytestream, p_header, 4 )
202 if( p_header[0] == 0x7f && p_header[1] == 0xfe &&
203 p_header[2] == 0x80 && p_header[3] == 0x01 )
205 p_sys->i_state = STATE_SYNC;
208 block_SkipByte( &p_sys->bytestream );
210 if( p_sys->i_state != STATE_SYNC )
212 block_BytestreamFlush( &p_sys->bytestream );
219 /* New frame, set the Presentation Time Stamp */
220 p_sys->i_pts = p_sys->bytestream.p_block->i_pts;
221 if( p_sys->i_pts != 0 &&
222 p_sys->i_pts != aout_DateGet( &p_sys->end_date ) )
224 aout_DateSet( &p_sys->end_date, p_sys->i_pts );
226 p_sys->i_state = STATE_HEADER;
229 /* Get DTS frame header (DTS_HEADER_SIZE bytes) */
230 if( block_PeekBytes( &p_sys->bytestream, p_header,
231 DTS_HEADER_SIZE ) != VLC_SUCCESS )
237 /* Check if frame is valid and get frame info */
238 p_sys->i_frame_size = SyncInfo( p_header,
240 &p_sys->i_channels_conf,
243 &p_sys->i_frame_length );
244 if( !p_sys->i_frame_size )
246 msg_Dbg( p_dec, "emulated sync word" );
247 block_SkipByte( &p_sys->bytestream );
248 p_sys->i_state = STATE_NOSYNC;
251 p_sys->i_state = STATE_NEXT_SYNC;
253 case STATE_NEXT_SYNC:
254 /* TODO: If pp_block == NULL, flush the buffer without checking the
257 /* Check if next expected frame contains the sync word */
258 if( block_PeekOffsetBytes( &p_sys->bytestream,
259 p_sys->i_frame_size, p_header, 4 )
266 if( p_header[0] == 0x7f && p_header[1] == 0xfe &&
267 p_header[2] == 0x80 && p_header[3] == 0x01 )
269 msg_Dbg( p_dec, "emulated sync word "
270 "(no sync on following frame)" );
271 p_sys->i_state = STATE_NOSYNC;
272 block_SkipByte( &p_sys->bytestream );
275 p_sys->i_state = STATE_SEND_DATA;
279 /* Make sure we have enough data.
280 * (Not useful if we went through NEXT_SYNC) */
281 if( block_WaitBytes( &p_sys->bytestream,
282 p_sys->i_frame_size ) != VLC_SUCCESS )
287 p_sys->i_state = STATE_SEND_DATA;
289 case STATE_SEND_DATA:
290 if( !(p_buf = GetOutBuffer( p_dec, &p_out_buffer )) )
292 //p_dec->b_error = VLC_TRUE;
296 /* Copy the whole frame into the buffer. When we reach this point
297 * we already know we have enough data available. */
298 block_GetBytes( &p_sys->bytestream, p_buf, p_sys->i_frame_size );
300 /* Make sure we don't reuse the same pts twice */
301 if( p_sys->i_pts == p_sys->bytestream.p_block->i_pts )
302 p_sys->i_pts = p_sys->bytestream.p_block->i_pts = 0;
304 /* So p_block doesn't get re-added several times */
305 *pp_block = block_BytestreamPop( &p_sys->bytestream );
307 p_sys->i_state = STATE_NOSYNC;
309 if( !p_sys->b_packetizer )
311 if( p_sys->i_frames_in_buf != 3 ) return NULL;
314 p_sys->i_frames_in_buf = 0;
315 p_sys->p_aout_buffer = 0;
326 /*****************************************************************************
327 * CloseDecoder: clean up the decoder
328 *****************************************************************************/
329 static void CloseDecoder( vlc_object_t *p_this )
331 decoder_t *p_dec = (decoder_t*)p_this;
332 decoder_sys_t *p_sys = p_dec->p_sys;
334 block_BytestreamRelease( &p_sys->bytestream );
339 /*****************************************************************************
341 *****************************************************************************/
342 static uint8_t *GetOutBuffer( decoder_t *p_dec, void **pp_out_buffer )
344 decoder_sys_t *p_sys = p_dec->p_sys;
347 if( p_dec->fmt_out.audio.i_rate != p_sys->i_rate )
349 msg_Info( p_dec, "DTS channels:%d samplerate:%d bitrate:%d",
350 p_sys->i_channels, p_sys->i_rate, p_sys->i_bit_rate );
352 aout_DateInit( &p_sys->end_date, p_sys->i_rate );
353 aout_DateSet( &p_sys->end_date, p_sys->i_pts );
356 p_dec->fmt_out.audio.i_rate = p_sys->i_rate;
357 p_dec->fmt_out.audio.i_channels = p_sys->i_channels;
358 p_dec->fmt_out.audio.i_bitrate = p_sys->i_bit_rate;
359 p_dec->fmt_out.audio.i_bytes_per_frame = p_sys->i_frame_size;
360 p_dec->fmt_out.audio.i_frame_length = p_sys->i_frame_length;
362 p_dec->fmt_out.audio.i_original_channels = p_sys->i_channels_conf;
363 p_dec->fmt_out.audio.i_physical_channels =
364 p_sys->i_channels_conf & AOUT_CHAN_PHYSMASK;
366 if( p_sys->b_packetizer )
368 block_t *p_sout_buffer = GetSoutBuffer( p_dec );
369 p_buf = p_sout_buffer ? p_sout_buffer->p_buffer : NULL;
370 *pp_out_buffer = p_sout_buffer;
374 if( !p_sys->i_frames_in_buf )
376 p_sys->p_aout_buffer = GetAoutBuffer( p_dec );
378 p_buf = p_sys->p_aout_buffer ? p_sys->p_aout_buffer->p_buffer +
379 p_sys->i_frames_in_buf * p_sys->i_frame_size : NULL;
380 *pp_out_buffer = p_sys->p_aout_buffer;
383 p_sys->i_frames_in_buf++;
388 /*****************************************************************************
390 *****************************************************************************/
391 static aout_buffer_t *GetAoutBuffer( decoder_t *p_dec )
393 decoder_sys_t *p_sys = p_dec->p_sys;
394 aout_buffer_t *p_buf;
396 p_buf = p_dec->pf_aout_buffer_new( p_dec, p_sys->i_frame_length * 3 );
397 if( p_buf == NULL ) return NULL;
399 p_buf->start_date = aout_DateGet( &p_sys->end_date );
401 aout_DateIncrement( &p_sys->end_date, p_sys->i_frame_length * 3 );
406 /*****************************************************************************
408 *****************************************************************************/
409 static block_t *GetSoutBuffer( decoder_t *p_dec )
411 decoder_sys_t *p_sys = p_dec->p_sys;
414 p_block = block_New( p_dec, p_sys->i_frame_size );
415 if( p_block == NULL ) return NULL;
417 p_block->i_pts = p_block->i_dts = aout_DateGet( &p_sys->end_date );
419 p_block->i_length = aout_DateIncrement( &p_sys->end_date,
420 p_sys->i_frame_length ) - p_block->i_pts;
425 /*****************************************************************************
426 * SyncInfo: parse DTS sync info
427 *****************************************************************************/
428 static int SyncInfo( const byte_t * p_buf,
429 unsigned int * pi_channels,
430 unsigned int * pi_channels_conf,
431 unsigned int * pi_sample_rate,
432 unsigned int * pi_bit_rate,
433 unsigned int * pi_frame_length )
435 unsigned int i_bit_rate;
436 unsigned int i_audio_mode;
437 unsigned int i_sample_rate;
438 unsigned int i_frame_size;
439 unsigned int i_frame_length;
441 static const unsigned int ppi_dts_samplerate[] =
443 0, 8000, 16000, 32000, 64000, 128000,
444 11025, 22050, 44010, 88020, 176400,
445 12000, 24000, 48000, 96000, 192000
448 static const unsigned int ppi_dts_bitrate[] =
450 32000, 56000, 64000, 96000, 112000, 128000,
451 192000, 224000, 256000, 320000, 384000,
452 448000, 512000, 576000, 640000, 768000,
453 896000, 1024000, 1152000, 1280000, 1344000,
454 1408000, 1411200, 1472000, 1536000, 1920000,
455 2048000, 3072000, 3840000, 4096000, 0, 0
458 if( (p_buf[0] != 0x7f) || (p_buf[1] != 0xfe) ||
459 (p_buf[2] != 0x80) || (p_buf[3] != 0x01) )
464 i_frame_length = (p_buf[4] & 0x01) << 6 | (p_buf[5] >> 2);
465 i_frame_size = (p_buf[5] & 0x03) << 12 | (p_buf[6] << 4) |
468 i_audio_mode = (p_buf[7] & 0x0f) << 2 | (p_buf[8] >> 6);
469 i_sample_rate = (p_buf[8] >> 2) & 0x0f;
470 i_bit_rate = (p_buf[8] & 0x03) << 3 | ((p_buf[9] >> 5) & 0x07);
472 switch( i_audio_mode )
476 *pi_channels_conf = AOUT_CHAN_CENTER;
479 /* Dual-mono = stereo + dual-mono */
480 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
488 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
493 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
499 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
505 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
506 AOUT_CHAN_CENTER | AOUT_CHAN_LFE;
511 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
512 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
517 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
518 AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT |
525 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
526 AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT |
527 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
532 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
533 AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT |
534 AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_REARLEFT |
541 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
542 AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT |
543 AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_REARLEFT |
544 AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE;
548 if( i_audio_mode <= 63 )
552 *pi_channels_conf = 0;
561 if( i_sample_rate >= sizeof( ppi_dts_samplerate ) /
562 sizeof( ppi_dts_samplerate[0] ) )
567 *pi_sample_rate = ppi_dts_samplerate[ i_sample_rate ];
569 if( i_bit_rate >= sizeof( ppi_dts_bitrate ) /
570 sizeof( ppi_dts_bitrate[0] ) )
575 *pi_bit_rate = ppi_dts_bitrate[ i_bit_rate ];
577 *pi_frame_length = (i_frame_length + 1) * 32;
579 return( i_frame_size + 1 );