]> git.sesse.net Git - vlc/blob - modules/codec/dts.c
5d777d4f01eb29dd47e0d4fb5693d7e52e9d49f3
[vlc] / modules / codec / dts.c
1 /*****************************************************************************
2  * dts.c: parse DTS audio sync info and packetize the stream
3  *****************************************************************************
4  * Copyright (C) 2003-2009 VLC authors and VideoLAN
5  * $Id$
6  *
7  * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
8  *          Gildas Bazin <gbazin@netcourrier.com>
9  *
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.
14  *
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.
19  *
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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32 #include <assert.h>
33
34 #include <vlc_common.h>
35 #include <vlc_plugin.h>
36 #include <vlc_codec.h>
37 #include <vlc_block_helper.h>
38 #include <vlc_bits.h>
39 #include <vlc_modules.h>
40 #include <vlc_cpu.h>
41
42 #include "../packetizer/packetizer_helper.h"
43 #include "dts_header.h"
44
45 /*****************************************************************************
46  * Module descriptor
47  *****************************************************************************/
48 static int  OpenDecoder   ( vlc_object_t * );
49 static int  OpenPacketizer( vlc_object_t * );
50 static void CloseCommon   ( vlc_object_t * );
51
52 vlc_module_begin ()
53     set_description( N_("DTS parser") )
54     set_capability( "decoder", 100 )
55     set_callbacks( OpenDecoder, CloseCommon )
56
57     add_submodule ()
58     set_description( N_("DTS audio packetizer") )
59     set_capability( "packetizer", 10 )
60     set_callbacks( OpenPacketizer, CloseCommon )
61 vlc_module_end ()
62
63 /*****************************************************************************
64  * decoder_sys_t : decoder descriptor
65  *****************************************************************************/
66 struct decoder_sys_t
67 {
68     /* Module mode */
69     bool b_packetizer;
70
71     /*
72      * Input properties
73      */
74     int i_state;
75
76     block_bytestream_t bytestream;
77
78     /*
79      * Common properties
80      */
81     date_t  end_date;
82
83     mtime_t i_pts;
84
85     bool         b_dts_hd;  /* Is the current frame a DTS HD one */
86     unsigned int i_bit_rate;
87     unsigned int i_frame_size;
88     unsigned int i_frame_length;
89     unsigned int i_rate;
90     unsigned int i_channels;
91     unsigned int i_channels_conf;
92 };
93
94 /****************************************************************************
95  * Local prototypes
96  ****************************************************************************/
97 static int OpenCommon( vlc_object_t *, bool b_packetizer );
98 static block_t *DecodeBlock( decoder_t *, block_t ** );
99
100 static int  SyncInfo( const uint8_t *, bool *, unsigned int *, unsigned int *,
101                       unsigned int *, unsigned int *, unsigned int * );
102
103 static uint8_t *GetOutBuffer ( decoder_t *, block_t ** );
104 static block_t *GetAoutBuffer( decoder_t * );
105 static block_t *GetSoutBuffer( decoder_t * );
106
107 /*****************************************************************************
108  * OpenDecoder: probe the decoder
109  *****************************************************************************/
110 static int OpenDecoder( vlc_object_t *p_this )
111 {
112     /* HACK: Don't use this codec if we don't have an dts audio filter */
113     if( !module_exists( "dtstofloat32" ) )
114         return VLC_EGENERIC;
115
116     return OpenCommon( p_this, false );
117 }
118
119 /*****************************************************************************
120  * OpenPacketizer: probe the packetizer
121  *****************************************************************************/
122 static int OpenPacketizer( vlc_object_t *p_this )
123 {
124     return OpenCommon( p_this, true );
125 }
126
127 /*****************************************************************************
128  * OpenCommon:
129  *****************************************************************************/
130 static int OpenCommon( vlc_object_t *p_this, bool b_packetizer )
131 {
132     decoder_t *p_dec = (decoder_t*)p_this;
133     decoder_sys_t *p_sys;
134
135     if( p_dec->fmt_in.i_codec != VLC_CODEC_DTS )
136         return VLC_EGENERIC;
137
138     /* Allocate the memory needed to store the decoder's structure */
139     if( ( p_dec->p_sys = p_sys = malloc(sizeof(*p_sys)) ) == NULL )
140         return VLC_ENOMEM;
141
142     /* Misc init */
143     p_sys->b_packetizer = b_packetizer;
144     p_sys->i_state = STATE_NOSYNC;
145     date_Set( &p_sys->end_date, 0 );
146     p_sys->b_dts_hd = false;
147     p_sys->i_pts = VLC_TS_INVALID;
148
149     block_BytestreamInit( &p_sys->bytestream );
150
151     /* Set output properties */
152     p_dec->fmt_out.i_cat = AUDIO_ES;
153     p_dec->fmt_out.i_codec = VLC_CODEC_DTS;
154     p_dec->fmt_out.audio.i_rate = 0; /* So end_date gets initialized */
155
156     /* Set callback */
157     p_dec->pf_decode_audio = DecodeBlock;
158     p_dec->pf_packetize    = DecodeBlock;
159
160     return VLC_SUCCESS;
161 }
162
163 /****************************************************************************
164  * DecodeBlock: the whole thing
165  ****************************************************************************/
166 static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
167 {
168     decoder_sys_t *p_sys = p_dec->p_sys;
169     uint8_t p_header[DTS_HEADER_SIZE];
170     uint8_t *p_buf;
171     block_t *p_out_buffer;
172
173     if( !pp_block || !*pp_block )
174         return NULL;
175
176     if( (*pp_block)->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
177     {
178         if( (*pp_block)->i_flags&BLOCK_FLAG_CORRUPTED )
179         {
180             p_sys->i_state = STATE_NOSYNC;
181             block_BytestreamEmpty( &p_sys->bytestream );
182         }
183         date_Set( &p_sys->end_date, 0 );
184         block_Release( *pp_block );
185         return NULL;
186     }
187
188     if( !date_Get( &p_sys->end_date ) && (*pp_block)->i_pts <= VLC_TS_INVALID )
189     {
190         /* We've just started the stream, wait for the first PTS. */
191         block_Release( *pp_block );
192         return NULL;
193     }
194
195     block_BytestreamPush( &p_sys->bytestream, *pp_block );
196
197     while( 1 )
198     {
199         switch( p_sys->i_state )
200         {
201         case STATE_NOSYNC:
202             /* Look for sync code - should be 0x7ffe8001 */
203             while( block_PeekBytes( &p_sys->bytestream, p_header, 6 )
204                    == VLC_SUCCESS )
205             {
206                 if( SyncCode( p_header ) == VLC_SUCCESS )
207                 {
208                     p_sys->i_state = STATE_SYNC;
209                     break;
210                 }
211                 block_SkipByte( &p_sys->bytestream );
212             }
213             if( p_sys->i_state != STATE_SYNC )
214             {
215                 block_BytestreamFlush( &p_sys->bytestream );
216
217                 /* Need more data */
218                 return NULL;
219             }
220
221         case STATE_SYNC:
222             /* New frame, set the Presentation Time Stamp */
223             p_sys->i_pts = p_sys->bytestream.p_block->i_pts;
224             if( p_sys->i_pts > VLC_TS_INVALID &&
225                 p_sys->i_pts != date_Get( &p_sys->end_date ) )
226             {
227                 date_Set( &p_sys->end_date, p_sys->i_pts );
228             }
229             p_sys->i_state = STATE_HEADER;
230
231         case STATE_HEADER:
232             /* Get DTS frame header (DTS_HEADER_SIZE bytes) */
233             if( block_PeekBytes( &p_sys->bytestream, p_header,
234                                  DTS_HEADER_SIZE ) != VLC_SUCCESS )
235             {
236                 /* Need more data */
237                 return NULL;
238             }
239
240             /* Check if frame is valid and get frame info */
241             p_sys->i_frame_size = SyncInfo( p_header,
242                                             &p_sys->b_dts_hd,
243                                             &p_sys->i_channels,
244                                             &p_sys->i_channels_conf,
245                                             &p_sys->i_rate,
246                                             &p_sys->i_bit_rate,
247                                             &p_sys->i_frame_length );
248             if( !p_sys->i_frame_size )
249             {
250                 msg_Dbg( p_dec, "emulated sync word" );
251                 block_SkipByte( &p_sys->bytestream );
252                 p_sys->i_state = STATE_NOSYNC;
253                 break;
254             }
255             p_sys->i_state = STATE_NEXT_SYNC;
256
257         case STATE_NEXT_SYNC:
258             /* TODO: If pp_block == NULL, flush the buffer without checking the
259              * next sync word */
260
261             /* Check if next expected frame contains the sync word */
262             if( block_PeekOffsetBytes( &p_sys->bytestream,
263                                        p_sys->i_frame_size, p_header, 6 )
264                 != VLC_SUCCESS )
265             {
266                 /* Need more data */
267                 return NULL;
268             }
269
270             if( p_sys->b_packetizer &&
271                 p_header[0] == 0 && p_header[1] == 0 )
272             {
273                 /* DTS wav files and audio CD's use stuffing */
274                 p_sys->i_state = STATE_SEND_DATA;
275                 break;
276             }
277
278             if( SyncCode( p_header ) != VLC_SUCCESS )
279             {
280                 msg_Dbg( p_dec, "emulated sync word "
281                          "(no sync on following frame): %2.2x%2.2x%2.2x%2.2x",
282                          (int)p_header[0], (int)p_header[1],
283                          (int)p_header[2], (int)p_header[3] );
284                 p_sys->i_state = STATE_NOSYNC;
285                 block_SkipByte( &p_sys->bytestream );
286                 break;
287             }
288             p_sys->i_state = STATE_SEND_DATA;
289             break;
290
291         case STATE_GET_DATA:
292             /* Make sure we have enough data.
293              * (Not useful if we went through NEXT_SYNC) */
294             if( block_WaitBytes( &p_sys->bytestream,
295                                  p_sys->i_frame_size ) != VLC_SUCCESS )
296             {
297                 /* Need more data */
298                 return NULL;
299             }
300             p_sys->i_state = STATE_SEND_DATA;
301
302         case STATE_SEND_DATA:
303             if( p_sys->b_dts_hd  )
304             {
305                 /* Ignore DTS-HD */
306                 block_SkipBytes( &p_sys->bytestream, p_sys->i_frame_size );
307                 p_sys->i_state = STATE_NOSYNC;
308                 break;
309             }
310
311             if( !(p_buf = GetOutBuffer( p_dec, &p_out_buffer )) )
312             {
313                 //p_dec->b_error = true;
314                 return NULL;
315             }
316
317             /* Copy the whole frame into the buffer. When we reach this point
318              * we already know we have enough data available. */
319             block_GetBytes( &p_sys->bytestream,
320                             p_buf, __MIN( p_sys->i_frame_size, p_out_buffer->i_buffer ) );
321
322             /* Make sure we don't reuse the same pts twice */
323             if( p_sys->i_pts == p_sys->bytestream.p_block->i_pts )
324                 p_sys->i_pts = p_sys->bytestream.p_block->i_pts = VLC_TS_INVALID;
325
326             p_sys->i_state = STATE_NOSYNC;
327
328             /* So p_block doesn't get re-added several times */
329             *pp_block = block_BytestreamPop( &p_sys->bytestream );
330
331             return p_out_buffer;
332         }
333     }
334
335     return NULL;
336 }
337
338 /*****************************************************************************
339  * CloseCommon: clean up the decoder
340  *****************************************************************************/
341 static void CloseCommon( vlc_object_t *p_this )
342 {
343     decoder_t *p_dec = (decoder_t*)p_this;
344     decoder_sys_t *p_sys = p_dec->p_sys;
345
346     block_BytestreamRelease( &p_sys->bytestream );
347
348     free( p_sys );
349 }
350
351 /*****************************************************************************
352  * GetOutBuffer:
353  *****************************************************************************/
354 static uint8_t *GetOutBuffer( decoder_t *p_dec, block_t **pp_out_buffer )
355 {
356     decoder_sys_t *p_sys = p_dec->p_sys;
357     uint8_t *p_buf;
358
359     if( p_dec->fmt_out.audio.i_rate != p_sys->i_rate )
360     {
361         msg_Info( p_dec, "DTS channels:%d samplerate:%d bitrate:%d",
362                   p_sys->i_channels, p_sys->i_rate, p_sys->i_bit_rate );
363
364         date_Init( &p_sys->end_date, p_sys->i_rate, 1 );
365         date_Set( &p_sys->end_date, p_sys->i_pts );
366     }
367
368     p_dec->fmt_out.audio.i_rate     = p_sys->i_rate;
369     p_dec->fmt_out.audio.i_channels = p_sys->i_channels;
370     /* Hack for DTS S/PDIF filter which needs to pad the DTS frames */
371     p_dec->fmt_out.audio.i_bytes_per_frame =
372         __MAX( p_sys->i_frame_size, p_sys->i_frame_length * 4 );
373     p_dec->fmt_out.audio.i_frame_length = p_sys->i_frame_length;
374
375     p_dec->fmt_out.audio.i_original_channels = p_sys->i_channels_conf;
376     p_dec->fmt_out.audio.i_physical_channels =
377         p_sys->i_channels_conf & AOUT_CHAN_PHYSMASK;
378
379     p_dec->fmt_out.i_bitrate = p_sys->i_bit_rate;
380
381     if( p_sys->b_packetizer )
382     {
383         block_t *p_sout_buffer = GetSoutBuffer( p_dec );
384         p_buf = p_sout_buffer ? p_sout_buffer->p_buffer : NULL;
385         *pp_out_buffer = p_sout_buffer;
386     }
387     else
388     {
389         block_t *p_aout_buffer = GetAoutBuffer( p_dec );
390         p_buf = p_aout_buffer ? p_aout_buffer->p_buffer : NULL;
391         *pp_out_buffer = p_aout_buffer;
392     }
393
394     return p_buf;
395 }
396
397 /*****************************************************************************
398  * GetAoutBuffer:
399  *****************************************************************************/
400 static block_t *GetAoutBuffer( decoder_t *p_dec )
401 {
402     decoder_sys_t *p_sys = p_dec->p_sys;
403     block_t *p_buf;
404
405     /* Hack for DTS S/PDIF filter which needs to send 3 frames at a time
406      * (plus a few header bytes) */
407     p_buf = decoder_NewAudioBuffer( p_dec, p_sys->i_frame_length * 4 );
408     if( p_buf == NULL ) return NULL;
409
410     p_buf->i_nb_samples = p_sys->i_frame_length;
411     p_buf->i_buffer = p_sys->i_frame_size;
412
413     p_buf->i_pts = date_Get( &p_sys->end_date );
414     p_buf->i_length = date_Increment( &p_sys->end_date, p_sys->i_frame_length )
415                       - p_buf->i_pts;
416
417     return p_buf;
418 }
419
420 /*****************************************************************************
421  * GetSoutBuffer:
422  *****************************************************************************/
423 static block_t *GetSoutBuffer( decoder_t *p_dec )
424 {
425     decoder_sys_t *p_sys = p_dec->p_sys;
426     block_t *p_block;
427
428     p_block = block_Alloc( p_sys->i_frame_size );
429     if( p_block == NULL ) return NULL;
430
431     p_block->i_pts = p_block->i_dts = date_Get( &p_sys->end_date );
432
433     p_block->i_length = date_Increment( &p_sys->end_date,
434         p_sys->i_frame_length ) - p_block->i_pts;
435
436     return p_block;
437 }
438
439 /*****************************************************************************
440  * SyncInfo: parse DTS sync info
441  *****************************************************************************/
442 static const unsigned int ppi_dts_samplerate[] =
443 {
444     0, 8000, 16000, 32000, 0, 0, 11025, 22050, 44100, 0, 0,
445     12000, 24000, 48000, 96000, 192000
446 };
447
448 static const unsigned int ppi_dts_bitrate[] =
449 {
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, 1/*open*/, 2/*variable*/, 3/*lossless*/
456 };
457
458 static int SyncInfo( const uint8_t *p_buf,
459                      bool *pb_dts_hd,
460                      unsigned int *pi_channels,
461                      unsigned int *pi_channels_conf,
462                      unsigned int *pi_sample_rate,
463                      unsigned int *pi_bit_rate,
464                      unsigned int *pi_frame_length )
465 {
466     unsigned int i_audio_mode;
467
468     unsigned int i_frame_size = GetSyncInfo( p_buf, pb_dts_hd,
469             pi_sample_rate, pi_bit_rate, pi_frame_length, &i_audio_mode);
470
471     if( *pb_dts_hd == true )
472         return i_frame_size;
473
474     switch( i_audio_mode & 0xFFFF )
475     {
476         case 0x0:
477             /* Mono */
478             *pi_channels = 1;
479             *pi_channels_conf = AOUT_CHAN_CENTER;
480             break;
481         case 0x1:
482             /* Dual-mono = stereo + dual-mono */
483             *pi_channels = 2;
484             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
485                            AOUT_CHAN_DUALMONO;
486             break;
487         case 0x2:
488         case 0x3:
489         case 0x4:
490             /* Stereo */
491             *pi_channels = 2;
492             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
493             break;
494         case 0x5:
495             /* 3F */
496             *pi_channels = 3;
497             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
498                                 AOUT_CHAN_CENTER;
499             break;
500         case 0x6:
501             /* 2F/1R */
502             *pi_channels = 3;
503             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
504                                 AOUT_CHAN_REARCENTER;
505             break;
506         case 0x7:
507             /* 3F/1R */
508             *pi_channels = 4;
509             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
510                                 AOUT_CHAN_CENTER | AOUT_CHAN_REARCENTER;
511             break;
512         case 0x8:
513             /* 2F2R */
514             *pi_channels = 4;
515             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
516                                 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
517             break;
518         case 0x9:
519             /* 3F2R */
520             *pi_channels = 5;
521             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
522                                 AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT |
523                                 AOUT_CHAN_REARRIGHT;
524             break;
525         case 0xA:
526         case 0xB:
527             /* 2F2M2R */
528             *pi_channels = 6;
529             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
530                                 AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT |
531                                 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
532             break;
533         case 0xC:
534             /* 3F2M2R */
535             *pi_channels = 7;
536             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
537                                 AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT |
538                                 AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_REARLEFT |
539                                 AOUT_CHAN_REARRIGHT;
540             break;
541         case 0xD:
542         case 0xE:
543             /* 3F2M2R/LFE */
544             *pi_channels = 8;
545             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
546                                 AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT |
547                                 AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_REARLEFT |
548                                 AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE;
549             break;
550
551         case 0xF:
552         default:
553             if( (i_audio_mode & 0xFFFF) >= 0x10 )
554             {
555                 /* User defined */
556                 *pi_channels = 0;
557                 *pi_channels_conf = 0;
558             }
559             else return 0;
560
561             break;
562     }
563
564     if( *pi_channels && (i_audio_mode & 0x10000) )
565     {
566         (*pi_channels)++;
567         *pi_channels_conf |= AOUT_CHAN_LFE;
568     }
569
570     if( *pi_sample_rate >= sizeof( ppi_dts_samplerate ) /
571                            sizeof( ppi_dts_samplerate[0] ) )
572     {
573         return 0;
574     }
575     *pi_sample_rate = ppi_dts_samplerate[ *pi_sample_rate ];
576     if( !*pi_sample_rate ) return 0;
577
578     if( *pi_bit_rate >= sizeof( ppi_dts_bitrate ) /
579                         sizeof( ppi_dts_bitrate[0] ) )
580     {
581         return 0;
582     }
583     *pi_bit_rate = ppi_dts_bitrate[ *pi_bit_rate ];
584     if( !*pi_bit_rate ) return 0;
585
586     *pi_frame_length = (*pi_frame_length + 1) * 32;
587
588     return i_frame_size;
589 }