]> git.sesse.net Git - vlc/blob - modules/codec/dts.c
* ALL: final improvements to the decoders/packetizers api.
[vlc] / modules / codec / dts.c
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 $
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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>                                              /* memcpy() */
31
32 #include <vlc/vlc.h>
33 #include <vlc/decoder.h>
34 #include <vlc/input.h>
35
36 #include "vlc_block_helper.h"
37
38 #define DTS_HEADER_SIZE 10
39
40 /*****************************************************************************
41  * decoder_sys_t : decoder descriptor
42  *****************************************************************************/
43 struct decoder_sys_t
44 {
45     /* Module mode */
46     vlc_bool_t b_packetizer;
47
48     /*
49      * Input properties
50      */
51     int i_state;
52
53     block_bytestream_t bytestream;
54
55     /*
56      * Common properties
57      */
58     audio_date_t   end_date;
59
60     mtime_t i_pts;
61
62     int i_frame_size, i_bit_rate;
63     unsigned int i_frame_length, i_rate, i_channels, i_channels_conf;
64
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. */
67     int i_frames_in_buf;
68     aout_buffer_t *p_aout_buffer;        /* current aout buffer being filled */
69
70 };
71
72 enum {
73
74     STATE_NOSYNC,
75     STATE_SYNC,
76     STATE_HEADER,
77     STATE_NEXT_SYNC,
78     STATE_GET_DATA,
79     STATE_SEND_DATA
80 };
81
82 /****************************************************************************
83  * Local prototypes
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 ** );
89
90 static int  SyncInfo      ( const byte_t *, unsigned int *, unsigned int *,
91                             unsigned int *, unsigned int *, unsigned int * );
92
93 static uint8_t       *GetOutBuffer ( decoder_t *, void ** );
94 static aout_buffer_t *GetAoutBuffer( decoder_t * );
95 static block_t       *GetSoutBuffer( decoder_t * );
96
97 /*****************************************************************************
98  * Module descriptor
99  *****************************************************************************/
100 vlc_module_begin();
101     set_description( _("DTS parser") );
102     set_capability( "decoder", 100 );
103     set_callbacks( OpenDecoder, CloseDecoder );
104
105     add_submodule();
106     set_description( _("DTS audio packetizer") );
107     set_capability( "packetizer", 10 );
108     set_callbacks( OpenPacketizer, NULL );
109 vlc_module_end();
110
111 /*****************************************************************************
112  * OpenDecoder: probe the decoder and return score
113  *****************************************************************************/
114 static int OpenDecoder( vlc_object_t *p_this )
115 {
116     decoder_t *p_dec = (decoder_t*)p_this;
117     decoder_sys_t *p_sys;
118
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') )
121     {
122         return VLC_EGENERIC;
123     }
124
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 )
128     {
129         msg_Err( p_dec, "out of memory" );
130         return VLC_EGENERIC;
131     }
132
133     /* Misc init */
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;
138
139     p_sys->bytestream = block_BytestreamInit( p_dec );
140
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',' ');
144
145     /* Set callback */
146     p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **))
147         DecodeBlock;
148     p_dec->pf_packetize    = (block_t *(*)(decoder_t *, block_t **))
149         DecodeBlock;
150
151     return VLC_SUCCESS;
152 }
153
154 static int OpenPacketizer( vlc_object_t *p_this )
155 {
156     decoder_t *p_dec = (decoder_t*)p_this;
157
158     int i_ret = OpenDecoder( p_this );
159
160     if( i_ret == VLC_SUCCESS ) p_dec->p_sys->b_packetizer = VLC_TRUE;
161
162     return i_ret;
163 }
164
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 )
171 {
172     decoder_sys_t *p_sys = p_dec->p_sys;
173     uint8_t p_header[DTS_HEADER_SIZE];
174     uint8_t *p_buf;
175     void *p_out_buffer;
176
177     if( !pp_block || !*pp_block ) return NULL;
178
179     if( !aout_DateGet( &p_sys->end_date ) && !(*pp_block)->i_pts )
180     {
181         /* We've just started the stream, wait for the first PTS. */
182         block_Release( *pp_block );
183         return NULL;
184     }
185
186     if( (*pp_block)->b_discontinuity )
187     {
188         p_sys->i_state = STATE_NOSYNC;
189     }
190
191     block_BytestreamPush( &p_sys->bytestream, *pp_block );
192
193     while( 1 )
194     {
195         switch( p_sys->i_state )
196         {
197         case STATE_NOSYNC:
198             /* Look for sync dword - should be 0x7ffe8001 */
199             while( block_PeekBytes( &p_sys->bytestream, p_header, 4 )
200                    == VLC_SUCCESS )
201             {
202                 if( p_header[0] == 0x7f && p_header[1] == 0xfe &&
203                     p_header[2] == 0x80 && p_header[3] == 0x01 )
204                 {
205                     p_sys->i_state = STATE_SYNC;
206                     break;
207                 }
208                 block_SkipByte( &p_sys->bytestream );
209             }
210             if( p_sys->i_state != STATE_SYNC )
211             {
212                 block_BytestreamFlush( &p_sys->bytestream );
213
214                 /* Need more data */
215                 return NULL;
216             }
217
218         case STATE_SYNC:
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 ) )
223             {
224                 aout_DateSet( &p_sys->end_date, p_sys->i_pts );
225             }
226             p_sys->i_state = STATE_HEADER;
227
228         case 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 )
232             {
233                 /* Need more data */
234                 return NULL;
235             }
236
237             /* Check if frame is valid and get frame info */
238             p_sys->i_frame_size = SyncInfo( p_header,
239                                             &p_sys->i_channels,
240                                             &p_sys->i_channels_conf,
241                                             &p_sys->i_rate,
242                                             &p_sys->i_bit_rate,
243                                             &p_sys->i_frame_length );
244             if( !p_sys->i_frame_size )
245             {
246                 msg_Dbg( p_dec, "emulated sync word" );
247                 block_SkipByte( &p_sys->bytestream );
248                 p_sys->i_state = STATE_NOSYNC;
249                 break;
250             }
251             p_sys->i_state = STATE_NEXT_SYNC;
252
253         case STATE_NEXT_SYNC:
254             /* TODO: If pp_block == NULL, flush the buffer without checking the
255              * next sync word */
256
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 )
260                 != VLC_SUCCESS )
261             {
262                 /* Need more data */
263                 return NULL;
264             }
265
266             if( p_header[0] == 0x7f && p_header[1] == 0xfe &&
267                 p_header[2] == 0x80 && p_header[3] == 0x01 )
268             {
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 );
273                 break;
274             }
275             p_sys->i_state = STATE_SEND_DATA;
276             break;
277
278         case STATE_GET_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 )
283             {
284                 /* Need more data */
285                 return NULL;
286             }
287             p_sys->i_state = STATE_SEND_DATA;
288
289         case STATE_SEND_DATA:
290             if( !(p_buf = GetOutBuffer( p_dec, &p_out_buffer )) )
291             {
292                 //p_dec->b_error = VLC_TRUE;
293                 return NULL;
294             }
295
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 );
299
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;
303
304             /* So p_block doesn't get re-added several times */
305             *pp_block = block_BytestreamPop( &p_sys->bytestream );
306
307             p_sys->i_state = STATE_NOSYNC;
308
309             if( !p_sys->b_packetizer )
310             {
311                 if( p_sys->i_frames_in_buf != 3 ) return NULL;
312                 else
313                 {
314                     p_sys->i_frames_in_buf = 0;
315                     p_sys->p_aout_buffer = 0;
316                 }
317             }
318
319             return p_out_buffer;
320         }
321     }
322
323     return NULL;
324 }
325
326 /*****************************************************************************
327  * CloseDecoder: clean up the decoder
328  *****************************************************************************/
329 static void CloseDecoder( vlc_object_t *p_this )
330 {
331     decoder_t *p_dec = (decoder_t*)p_this;
332     decoder_sys_t *p_sys = p_dec->p_sys;
333
334     block_BytestreamRelease( &p_sys->bytestream );
335
336     free( p_sys );
337 }
338
339 /*****************************************************************************
340  * GetOutBuffer:
341  *****************************************************************************/
342 static uint8_t *GetOutBuffer( decoder_t *p_dec, void **pp_out_buffer )
343 {
344     decoder_sys_t *p_sys = p_dec->p_sys;
345     uint8_t *p_buf;
346
347     if( p_dec->fmt_out.audio.i_rate != p_sys->i_rate )
348     {
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 );
351
352         aout_DateInit( &p_sys->end_date, p_sys->i_rate );
353         aout_DateSet( &p_sys->end_date, p_sys->i_pts );
354     }
355
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;
361
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;
365
366     if( p_sys->b_packetizer )
367     {
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;
371     }
372     else
373     {
374         if( !p_sys->i_frames_in_buf )
375         {
376             p_sys->p_aout_buffer = GetAoutBuffer( p_dec );
377         }
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;
381     }
382
383     p_sys->i_frames_in_buf++;
384
385     return p_buf;
386 }
387
388 /*****************************************************************************
389  * GetAoutBuffer:
390  *****************************************************************************/
391 static aout_buffer_t *GetAoutBuffer( decoder_t *p_dec )
392 {
393     decoder_sys_t *p_sys = p_dec->p_sys;
394     aout_buffer_t *p_buf;
395
396     p_buf = p_dec->pf_aout_buffer_new( p_dec, p_sys->i_frame_length * 3 );
397     if( p_buf == NULL ) return NULL;
398
399     p_buf->start_date = aout_DateGet( &p_sys->end_date );
400     p_buf->end_date =
401         aout_DateIncrement( &p_sys->end_date, p_sys->i_frame_length * 3 );
402
403     return p_buf;
404 }
405
406 /*****************************************************************************
407  * GetSoutBuffer:
408  *****************************************************************************/
409 static block_t *GetSoutBuffer( decoder_t *p_dec )
410 {
411     decoder_sys_t *p_sys = p_dec->p_sys;
412     block_t *p_block;
413
414     p_block = block_New( p_dec, p_sys->i_frame_size );
415     if( p_block == NULL ) return NULL;
416
417     p_block->i_pts = p_block->i_dts = aout_DateGet( &p_sys->end_date );
418
419     p_block->i_length = aout_DateIncrement( &p_sys->end_date,
420         p_sys->i_frame_length ) - p_block->i_pts;
421
422     return p_block;
423 }
424
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 )
434 {
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;
440
441     static const unsigned int ppi_dts_samplerate[] =
442     {
443         0, 8000, 16000, 32000, 64000, 128000,
444         11025, 22050, 44010, 88020, 176400,
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, 4096000, 0, 0
456     };
457
458     if( (p_buf[0] != 0x7f) || (p_buf[1] != 0xfe) ||
459         (p_buf[2] != 0x80) || (p_buf[3] != 0x01) )
460     {
461         return( 0 );
462     }
463
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) |
466                    (p_buf[7] >> 4);
467
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);
471
472     switch( i_audio_mode )
473     {
474         case 0x0:
475             /* Mono */
476             *pi_channels_conf = AOUT_CHAN_CENTER;
477             break;
478         case 0x1:
479             /* Dual-mono = stereo + dual-mono */
480             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
481                            AOUT_CHAN_DUALMONO;
482             break;
483         case 0x2:
484         case 0x3:
485         case 0x4:
486             /* Stereo */
487             *pi_channels = 2;
488             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
489             break;
490         case 0x5:
491             /* 3F */
492             *pi_channels = 3;
493             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
494                                 AOUT_CHAN_CENTER;
495             break;
496         case 0x6:
497             /* 2F/LFE */
498             *pi_channels = 3;
499             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
500                                 AOUT_CHAN_LFE;
501             break;
502         case 0x7:
503             /* 3F/LFE */
504             *pi_channels = 4;
505             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
506                                 AOUT_CHAN_CENTER | AOUT_CHAN_LFE;
507             break;
508         case 0x8:
509             /* 2F2R */
510             *pi_channels = 4;
511             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
512                                 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
513             break;
514         case 0x9:
515             /* 3F2R */
516             *pi_channels = 5;
517             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
518                                 AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT |
519                                 AOUT_CHAN_REARRIGHT;
520             break;
521         case 0xA:
522         case 0xB:
523             /* 2F2M2R */
524             *pi_channels = 6;
525             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
526                                 AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT |
527                                 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
528             break;
529         case 0xC:
530             /* 3F2M2R */
531             *pi_channels = 7;
532             *pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
533                                 AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT |
534                                 AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_REARLEFT |
535                                 AOUT_CHAN_REARRIGHT;
536             break;
537         case 0xD:
538         case 0xE:
539             /* 3F2M2R/LFE */
540             *pi_channels = 8;
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;
545             break;
546
547         default:
548             if( i_audio_mode <= 63 )
549             {
550                 /* User defined */
551                 *pi_channels = 0;
552                 *pi_channels_conf = 0; 
553             }
554             else
555             {
556                 return( 0 );
557             }
558             break;
559     }
560
561     if( i_sample_rate >= sizeof( ppi_dts_samplerate ) /
562                          sizeof( ppi_dts_samplerate[0] ) )
563     {
564         return( 0 );
565     }
566
567     *pi_sample_rate = ppi_dts_samplerate[ i_sample_rate ];
568
569     if( i_bit_rate >= sizeof( ppi_dts_bitrate ) /
570                       sizeof( ppi_dts_bitrate[0] ) )
571     {
572         return( 0 );
573     }
574
575     *pi_bit_rate = ppi_dts_bitrate[ i_bit_rate ];
576
577     *pi_frame_length = (i_frame_length + 1) * 32;
578
579     return( i_frame_size + 1 );
580 }