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.6 2003/11/16 22:54:12 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_bytes_per_frame = p_sys->i_frame_size;
359 p_dec->fmt_out.audio.i_frame_length = p_sys->i_frame_length;
361 p_dec->fmt_out.audio.i_original_channels = p_sys->i_channels_conf;
362 p_dec->fmt_out.audio.i_physical_channels =
363 p_sys->i_channels_conf & AOUT_CHAN_PHYSMASK;
365 p_dec->fmt_out.i_bitrate = p_sys->i_bit_rate;
367 if( p_sys->b_packetizer )
369 block_t *p_sout_buffer = GetSoutBuffer( p_dec );
370 p_buf = p_sout_buffer ? p_sout_buffer->p_buffer : NULL;
371 *pp_out_buffer = p_sout_buffer;
375 if( !p_sys->i_frames_in_buf )
377 p_sys->p_aout_buffer = GetAoutBuffer( p_dec );
379 p_buf = p_sys->p_aout_buffer ? p_sys->p_aout_buffer->p_buffer +
380 p_sys->i_frames_in_buf * p_sys->i_frame_size : NULL;
381 *pp_out_buffer = p_sys->p_aout_buffer;
384 p_sys->i_frames_in_buf++;
389 /*****************************************************************************
391 *****************************************************************************/
392 static aout_buffer_t *GetAoutBuffer( decoder_t *p_dec )
394 decoder_sys_t *p_sys = p_dec->p_sys;
395 aout_buffer_t *p_buf;
397 p_buf = p_dec->pf_aout_buffer_new( p_dec, p_sys->i_frame_length * 3 );
398 if( p_buf == NULL ) return NULL;
400 p_buf->start_date = aout_DateGet( &p_sys->end_date );
402 aout_DateIncrement( &p_sys->end_date, p_sys->i_frame_length * 3 );
407 /*****************************************************************************
409 *****************************************************************************/
410 static block_t *GetSoutBuffer( decoder_t *p_dec )
412 decoder_sys_t *p_sys = p_dec->p_sys;
415 p_block = block_New( p_dec, p_sys->i_frame_size );
416 if( p_block == NULL ) return NULL;
418 p_block->i_pts = p_block->i_dts = aout_DateGet( &p_sys->end_date );
420 p_block->i_length = aout_DateIncrement( &p_sys->end_date,
421 p_sys->i_frame_length ) - p_block->i_pts;
426 /*****************************************************************************
427 * SyncInfo: parse DTS sync info
428 *****************************************************************************/
429 static int SyncInfo( const byte_t * p_buf,
430 unsigned int * pi_channels,
431 unsigned int * pi_channels_conf,
432 unsigned int * pi_sample_rate,
433 unsigned int * pi_bit_rate,
434 unsigned int * pi_frame_length )
436 unsigned int i_bit_rate;
437 unsigned int i_audio_mode;
438 unsigned int i_sample_rate;
439 unsigned int i_frame_size;
440 unsigned int i_frame_length;
442 static const unsigned int ppi_dts_samplerate[] =
444 0, 8000, 16000, 32000, 64000, 128000,
445 11025, 22050, 44010, 88020, 176400,
446 12000, 24000, 48000, 96000, 192000
449 static const unsigned int ppi_dts_bitrate[] =
451 32000, 56000, 64000, 96000, 112000, 128000,
452 192000, 224000, 256000, 320000, 384000,
453 448000, 512000, 576000, 640000, 768000,
454 896000, 1024000, 1152000, 1280000, 1344000,
455 1408000, 1411200, 1472000, 1536000, 1920000,
456 2048000, 3072000, 3840000, 4096000, 0, 0
459 if( (p_buf[0] != 0x7f) || (p_buf[1] != 0xfe) ||
460 (p_buf[2] != 0x80) || (p_buf[3] != 0x01) )
465 i_frame_length = (p_buf[4] & 0x01) << 6 | (p_buf[5] >> 2);
466 i_frame_size = (p_buf[5] & 0x03) << 12 | (p_buf[6] << 4) |
469 i_audio_mode = (p_buf[7] & 0x0f) << 2 | (p_buf[8] >> 6);
470 i_sample_rate = (p_buf[8] >> 2) & 0x0f;
471 i_bit_rate = (p_buf[8] & 0x03) << 3 | ((p_buf[9] >> 5) & 0x07);
473 switch( i_audio_mode )
477 *pi_channels_conf = AOUT_CHAN_CENTER;
480 /* Dual-mono = stereo + dual-mono */
481 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
489 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
494 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
500 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
506 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
507 AOUT_CHAN_CENTER | AOUT_CHAN_LFE;
512 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
513 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
518 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
519 AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT |
526 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
527 AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT |
528 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
533 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
534 AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT |
535 AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_REARLEFT |
542 *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
543 AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT |
544 AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_REARLEFT |
545 AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE;
549 if( i_audio_mode <= 63 )
553 *pi_channels_conf = 0;
562 if( i_sample_rate >= sizeof( ppi_dts_samplerate ) /
563 sizeof( ppi_dts_samplerate[0] ) )
568 *pi_sample_rate = ppi_dts_samplerate[ i_sample_rate ];
570 if( i_bit_rate >= sizeof( ppi_dts_bitrate ) /
571 sizeof( ppi_dts_bitrate[0] ) )
576 *pi_bit_rate = ppi_dts_bitrate[ i_bit_rate ];
578 *pi_frame_length = (i_frame_length + 1) * 32;
580 return( i_frame_size + 1 );