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.9 2003/12/22 14:32:55 sam 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 *****************************************************************************/
29 #include <vlc/decoder.h>
31 #include "vlc_block_helper.h"
33 #define DTS_HEADER_SIZE 10
35 /*****************************************************************************
36 * decoder_sys_t : decoder descriptor
37 *****************************************************************************/
41 vlc_bool_t b_packetizer;
48 block_bytestream_t bytestream;
53 audio_date_t end_date;
57 int i_frame_size, i_bit_rate;
58 unsigned int i_frame_length, i_rate, i_channels, i_channels_conf;
60 /* This is very hacky. For DTS over S/PDIF we apparently need to send
61 * 3 frames at a time. This should likely be moved to the output stage. */
63 aout_buffer_t *p_aout_buffer; /* current aout buffer being filled */
77 /****************************************************************************
79 ****************************************************************************/
80 static int OpenDecoder ( vlc_object_t * );
81 static int OpenPacketizer( vlc_object_t * );
82 static void CloseDecoder ( vlc_object_t * );
83 static void *DecodeBlock ( decoder_t *, block_t ** );
85 static int SyncInfo ( const byte_t *, unsigned int *, unsigned int *,
86 unsigned int *, unsigned int *, unsigned int * );
88 static uint8_t *GetOutBuffer ( decoder_t *, void ** );
89 static aout_buffer_t *GetAoutBuffer( decoder_t * );
90 static block_t *GetSoutBuffer( decoder_t * );
92 /*****************************************************************************
94 *****************************************************************************/
96 set_description( _("DTS parser") );
97 set_capability( "decoder", 100 );
98 set_callbacks( OpenDecoder, CloseDecoder );
101 set_description( _("DTS audio packetizer") );
102 set_capability( "packetizer", 10 );
103 set_callbacks( OpenPacketizer, NULL );
106 /*****************************************************************************
107 * OpenDecoder: probe the decoder and return score
108 *****************************************************************************/
109 static int OpenDecoder( vlc_object_t *p_this )
111 decoder_t *p_dec = (decoder_t*)p_this;
112 decoder_sys_t *p_sys;
114 if( p_dec->fmt_in.i_codec != VLC_FOURCC('d','t','s',' ')
115 && p_dec->fmt_in.i_codec != VLC_FOURCC('d','t','s','b') )
120 /* Allocate the memory needed to store the decoder's structure */
121 if( ( p_dec->p_sys = p_sys =
122 (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
124 msg_Err( p_dec, "out of memory" );
129 p_sys->b_packetizer = VLC_FALSE;
130 p_sys->i_state = STATE_NOSYNC;
131 aout_DateSet( &p_sys->end_date, 0 );
132 p_sys->i_frames_in_buf = 0;
134 p_sys->bytestream = block_BytestreamInit( p_dec );
136 /* Set output properties */
137 p_dec->fmt_out.i_cat = AUDIO_ES;
138 p_dec->fmt_out.i_codec = VLC_FOURCC('d','t','s',' ');
141 p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **))
143 p_dec->pf_packetize = (block_t *(*)(decoder_t *, block_t **))
149 static int OpenPacketizer( vlc_object_t *p_this )
151 decoder_t *p_dec = (decoder_t*)p_this;
153 int i_ret = OpenDecoder( p_this );
155 if( i_ret == VLC_SUCCESS ) p_dec->p_sys->b_packetizer = VLC_TRUE;
160 /****************************************************************************
161 * DecodeBlock: the whole thing
162 ****************************************************************************
163 * This function is called just after the thread is launched.
164 ****************************************************************************/
165 static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
167 decoder_sys_t *p_sys = p_dec->p_sys;
168 uint8_t p_header[DTS_HEADER_SIZE];
172 if( !pp_block || !*pp_block ) return NULL;
174 if( !aout_DateGet( &p_sys->end_date ) && !(*pp_block)->i_pts )
176 /* We've just started the stream, wait for the first PTS. */
177 block_Release( *pp_block );
181 if( (*pp_block)->b_discontinuity )
183 p_sys->i_state = STATE_NOSYNC;
186 block_BytestreamPush( &p_sys->bytestream, *pp_block );
190 switch( p_sys->i_state )
193 /* Look for sync dword - should be 0x7ffe8001 */
194 while( block_PeekBytes( &p_sys->bytestream, p_header, 4 )
197 if( p_header[0] == 0x7f && p_header[1] == 0xfe &&
198 p_header[2] == 0x80 && p_header[3] == 0x01 )
200 p_sys->i_state = STATE_SYNC;
203 block_SkipByte( &p_sys->bytestream );
205 if( p_sys->i_state != STATE_SYNC )
207 block_BytestreamFlush( &p_sys->bytestream );
214 /* New frame, set the Presentation Time Stamp */
215 p_sys->i_pts = p_sys->bytestream.p_block->i_pts;
216 if( p_sys->i_pts != 0 &&
217 p_sys->i_pts != aout_DateGet( &p_sys->end_date ) )
219 aout_DateSet( &p_sys->end_date, p_sys->i_pts );
221 p_sys->i_state = STATE_HEADER;
224 /* Get DTS frame header (DTS_HEADER_SIZE bytes) */
225 if( block_PeekBytes( &p_sys->bytestream, p_header,
226 DTS_HEADER_SIZE ) != VLC_SUCCESS )
232 /* Check if frame is valid and get frame info */
233 p_sys->i_frame_size = SyncInfo( p_header,
235 &p_sys->i_channels_conf,
238 &p_sys->i_frame_length );
239 if( !p_sys->i_frame_size )
241 msg_Dbg( p_dec, "emulated sync word" );
242 block_SkipByte( &p_sys->bytestream );
243 p_sys->i_state = STATE_NOSYNC;
246 p_sys->i_state = STATE_NEXT_SYNC;
248 case STATE_NEXT_SYNC:
249 /* TODO: If pp_block == NULL, flush the buffer without checking the
252 /* Check if next expected frame contains the sync word */
253 if( block_PeekOffsetBytes( &p_sys->bytestream,
254 p_sys->i_frame_size, p_header, 4 )
261 if( p_header[0] != 0x7f || p_header[1] != 0xfe ||
262 p_header[2] != 0x80 || p_header[3] != 0x01 )
264 msg_Dbg( p_dec, "emulated sync word "
265 "(no sync on following frame) %2.2x%2.2x%2.2x%2.2x",
266 p_header[0], p_header[1], p_header[2], p_header[3] );
267 p_sys->i_state = STATE_NOSYNC;
268 block_SkipByte( &p_sys->bytestream );
271 p_sys->i_state = STATE_SEND_DATA;
275 /* Make sure we have enough data.
276 * (Not useful if we went through NEXT_SYNC) */
277 if( block_WaitBytes( &p_sys->bytestream,
278 p_sys->i_frame_size ) != VLC_SUCCESS )
283 p_sys->i_state = STATE_SEND_DATA;
285 case STATE_SEND_DATA:
286 if( !(p_buf = GetOutBuffer( p_dec, &p_out_buffer )) )
288 //p_dec->b_error = VLC_TRUE;
292 /* Copy the whole frame into the buffer. When we reach this point
293 * we already know we have enough data available. */
294 block_GetBytes( &p_sys->bytestream, p_buf, p_sys->i_frame_size );
296 /* Make sure we don't reuse the same pts twice */
297 if( p_sys->i_pts == p_sys->bytestream.p_block->i_pts )
298 p_sys->i_pts = p_sys->bytestream.p_block->i_pts = 0;
300 /* So p_block doesn't get re-added several times */
301 *pp_block = block_BytestreamPop( &p_sys->bytestream );
303 p_sys->i_state = STATE_NOSYNC;
305 if( !p_sys->b_packetizer )
307 if( p_sys->i_frames_in_buf != 3 ) return NULL;
310 p_sys->i_frames_in_buf = 0;
311 p_sys->p_aout_buffer = 0;
322 /*****************************************************************************
323 * CloseDecoder: clean up the decoder
324 *****************************************************************************/
325 static void CloseDecoder( vlc_object_t *p_this )
327 decoder_t *p_dec = (decoder_t*)p_this;
328 decoder_sys_t *p_sys = p_dec->p_sys;
330 block_BytestreamRelease( &p_sys->bytestream );
335 /*****************************************************************************
337 *****************************************************************************/
338 static uint8_t *GetOutBuffer( decoder_t *p_dec, void **pp_out_buffer )
340 decoder_sys_t *p_sys = p_dec->p_sys;
343 if( p_dec->fmt_out.audio.i_rate != p_sys->i_rate )
345 msg_Info( p_dec, "DTS channels:%d samplerate:%d bitrate:%d",
346 p_sys->i_channels, p_sys->i_rate, p_sys->i_bit_rate );
348 aout_DateInit( &p_sys->end_date, p_sys->i_rate );
349 aout_DateSet( &p_sys->end_date, p_sys->i_pts );
352 p_dec->fmt_out.audio.i_rate = p_sys->i_rate;
353 p_dec->fmt_out.audio.i_channels = p_sys->i_channels;
354 p_dec->fmt_out.audio.i_bytes_per_frame = p_sys->i_frame_size;
355 p_dec->fmt_out.audio.i_frame_length = p_sys->i_frame_length;
357 p_dec->fmt_out.audio.i_original_channels = p_sys->i_channels_conf;
358 p_dec->fmt_out.audio.i_physical_channels =
359 p_sys->i_channels_conf & AOUT_CHAN_PHYSMASK;
361 p_dec->fmt_out.i_bitrate = p_sys->i_bit_rate;
363 if( p_sys->b_packetizer )
365 block_t *p_sout_buffer = GetSoutBuffer( p_dec );
366 p_buf = p_sout_buffer ? p_sout_buffer->p_buffer : NULL;
367 *pp_out_buffer = p_sout_buffer;
371 if( !p_sys->i_frames_in_buf )
373 p_sys->p_aout_buffer = GetAoutBuffer( p_dec );
375 p_buf = p_sys->p_aout_buffer ? p_sys->p_aout_buffer->p_buffer +
376 p_sys->i_frames_in_buf * p_sys->i_frame_size : NULL;
377 *pp_out_buffer = p_sys->p_aout_buffer;
380 p_sys->i_frames_in_buf++;
385 /*****************************************************************************
387 *****************************************************************************/
388 static aout_buffer_t *GetAoutBuffer( decoder_t *p_dec )
390 decoder_sys_t *p_sys = p_dec->p_sys;
391 aout_buffer_t *p_buf;
393 p_buf = p_dec->pf_aout_buffer_new( p_dec, p_sys->i_frame_length * 3 );
394 if( p_buf == NULL ) return NULL;
396 p_buf->start_date = aout_DateGet( &p_sys->end_date );
398 aout_DateIncrement( &p_sys->end_date, p_sys->i_frame_length * 3 );
403 /*****************************************************************************
405 *****************************************************************************/
406 static block_t *GetSoutBuffer( decoder_t *p_dec )
408 decoder_sys_t *p_sys = p_dec->p_sys;
411 p_block = block_New( p_dec, p_sys->i_frame_size );
412 if( p_block == NULL ) return NULL;
414 p_block->i_pts = p_block->i_dts = aout_DateGet( &p_sys->end_date );
416 p_block->i_length = aout_DateIncrement( &p_sys->end_date,
417 p_sys->i_frame_length ) - p_block->i_pts;
422 /*****************************************************************************
423 * SyncInfo: parse DTS sync info
424 *****************************************************************************/
425 static int SyncInfo( const byte_t * p_buf,
426 unsigned int * pi_channels,
427 unsigned int * pi_channels_conf,
428 unsigned int * pi_sample_rate,
429 unsigned int * pi_bit_rate,
430 unsigned int * pi_frame_length )
432 unsigned int i_bit_rate;
433 unsigned int i_audio_mode;
434 unsigned int i_sample_rate;
435 unsigned int i_frame_size;
436 unsigned int i_frame_length;
438 static const unsigned int ppi_dts_samplerate[] =
440 0, 8000, 16000, 32000, 64000, 128000,
441 11025, 22050, 44010, 88020, 176400,
442 12000, 24000, 48000, 96000, 192000
445 static const unsigned int ppi_dts_bitrate[] =
447 32000, 56000, 64000, 96000, 112000, 128000,
448 192000, 224000, 256000, 320000, 384000,
449 448000, 512000, 576000, 640000, 768000,
450 896000, 1024000, 1152000, 1280000, 1344000,
451 1408000, 1411200, 1472000, 1536000, 1920000,
452 2048000, 3072000, 3840000, 4096000, 0, 0
455 if( (p_buf[0] != 0x7f) || (p_buf[1] != 0xfe) ||
456 (p_buf[2] != 0x80) || (p_buf[3] != 0x01) )
461 i_frame_length = (p_buf[4] & 0x01) << 6 | (p_buf[5] >> 2);
462 i_frame_size = (p_buf[5] & 0x03) << 12 | (p_buf[6] << 4) |
465 i_audio_mode = (p_buf[7] & 0x0f) << 2 | (p_buf[8] >> 6);
466 i_sample_rate = (p_buf[8] >> 2) & 0x0f;
467 i_bit_rate = (p_buf[8] & 0x03) << 3 | ((p_buf[9] >> 5) & 0x07);
469 switch( i_audio_mode )
473 *pi_channels_conf = AOUT_CHAN_CENTER;
476 /* Dual-mono = stereo + dual-mono */
477 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
485 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
490 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
496 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
502 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
503 AOUT_CHAN_CENTER | AOUT_CHAN_LFE;
508 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
509 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
514 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
515 AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT |
522 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
523 AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT |
524 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
529 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
530 AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT |
531 AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_REARLEFT |
538 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
539 AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT |
540 AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_REARLEFT |
541 AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE;
545 if( i_audio_mode <= 63 )
549 *pi_channels_conf = 0;
558 if( i_sample_rate >= sizeof( ppi_dts_samplerate ) /
559 sizeof( ppi_dts_samplerate[0] ) )
564 *pi_sample_rate = ppi_dts_samplerate[ i_sample_rate ];
566 if( i_bit_rate >= sizeof( ppi_dts_bitrate ) /
567 sizeof( ppi_dts_bitrate[0] ) )
572 *pi_bit_rate = ppi_dts_bitrate[ i_bit_rate ];
574 *pi_frame_length = (i_frame_length + 1) * 32;
576 return i_frame_size + 1;