]> git.sesse.net Git - vlc/blob - modules/packetizer/mlp.c
Used date_t instead of audio_date_t in packetizers.
[vlc] / modules / packetizer / mlp.c
1 /*****************************************************************************
2  * mlp.c: packetize MLP/TrueHD audio
3  *****************************************************************************
4  * Copyright (C) 2008 Laurent Aimar
5  * $Id$
6  *
7  * Authors: Laurent Aimar < fenrir _AT videolan _DOT_ org >
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33 #include <vlc_codec.h>
34 #include <vlc_aout.h>
35 #include <vlc_block_helper.h>
36 #include <vlc_bits.h>
37 #include <assert.h>
38
39 /*****************************************************************************
40  * Module descriptor
41  *****************************************************************************/
42 static int  Open ( vlc_object_t * );
43 static void Close( vlc_object_t * );
44
45 vlc_module_begin ()
46     set_category( CAT_SOUT )
47     set_subcategory( SUBCAT_SOUT_PACKETIZER )
48     set_description( N_("MLP/TrueHD parser") )
49     set_capability( "packetizer", 50 )
50     set_callbacks( Open, Close )
51 vlc_module_end ()
52
53 /*****************************************************************************
54  *
55  *****************************************************************************/
56 typedef struct
57 {
58     int i_type;
59     int i_rate;
60     int i_channels;
61     int i_channels_conf;
62     int i_samples;
63
64     bool b_vbr;
65     int  i_bitrate;
66
67     int  i_substreams;
68
69 } mlp_header_t;
70
71 struct decoder_sys_t
72 {
73     /*
74      * Input properties
75      */
76     int i_state;
77
78     block_bytestream_t bytestream;
79
80     /*
81      * Common properties
82      */
83     date_t  end_date;
84
85     mtime_t i_pts;
86     int i_frame_size;
87
88     bool         b_mlp;
89     mlp_header_t mlp;
90 };
91
92 enum {
93
94     STATE_NOSYNC,
95     STATE_SYNC,
96     STATE_HEADER,
97     STATE_NEXT_SYNC,
98     STATE_GET_DATA,
99     STATE_SEND_DATA
100 };
101
102 #define MLP_MAX_SUBSTREAMS (16)
103 #define MLP_HEADER_SYNC (28)
104 #define MLP_HEADER_SIZE (4 + MLP_HEADER_SYNC + 4 * MLP_MAX_SUBSTREAMS)
105
106 static const uint8_t pu_start_code[3] = { 0xf8, 0x72, 0x6f };
107
108 /****************************************************************************
109  * Local prototypes
110  ****************************************************************************/
111 static block_t *Packetize( decoder_t *, block_t **pp_block );
112 static int SyncInfo( const uint8_t *p_hdr, bool *pb_mlp, mlp_header_t *p_mlp );
113 static int SyncInfoDolby( const uint8_t *p_buf );
114
115 /*****************************************************************************
116  * Open: probe the decoder/packetizer and return score
117  *****************************************************************************/
118 static int Open( vlc_object_t *p_this )
119 {
120     decoder_t *p_dec = (decoder_t*)p_this;
121     decoder_sys_t *p_sys;
122
123     if( p_dec->fmt_in.i_codec != VLC_CODEC_MLP &&
124         p_dec->fmt_in.i_codec != VLC_CODEC_TRUEHD )
125         return VLC_EGENERIC;
126
127     /* */
128     p_dec->p_sys = p_sys = malloc( sizeof(*p_sys) );
129     if( !p_sys )
130         return VLC_ENOMEM;
131
132     /* */
133     p_sys->i_state = STATE_NOSYNC;
134     date_Set( &p_sys->end_date, 0 );
135
136     p_sys->bytestream = block_BytestreamInit();
137     p_sys->b_mlp = false;
138
139     /* Set output properties */
140     p_dec->fmt_out.i_cat = AUDIO_ES;
141     p_dec->fmt_out.i_codec = p_dec->fmt_in.i_codec;
142     p_dec->fmt_out.audio.i_rate = 0;
143
144     /* Set callback */
145     p_dec->pf_packetize = Packetize;
146     return VLC_SUCCESS;
147 }
148
149 /****************************************************************************
150  * Packetize:
151  ****************************************************************************/
152 static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
153 {
154     decoder_sys_t *p_sys = p_dec->p_sys;
155     uint8_t p_header[MLP_HEADER_SIZE];
156     block_t *p_out_buffer;
157
158     /* */
159     if( !pp_block || !*pp_block )
160         return NULL;
161
162     /* */
163     if( (*pp_block)->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
164     {
165         if( (*pp_block)->i_flags&BLOCK_FLAG_CORRUPTED )
166         {
167             p_sys->b_mlp = false;
168             p_sys->i_state = STATE_NOSYNC;
169             block_BytestreamEmpty( &p_sys->bytestream );
170         }
171         date_Set( &p_sys->end_date, 0 );
172         block_Release( *pp_block );
173         return NULL;
174     }
175
176     if( !date_Get( &p_sys->end_date ) && !(*pp_block)->i_pts )
177     {
178         /* We've just started the stream, wait for the first PTS. */
179         block_Release( *pp_block );
180         return NULL;
181     }
182
183     block_BytestreamPush( &p_sys->bytestream, *pp_block );
184
185     for( ;; )
186     {
187         switch( p_sys->i_state )
188         {
189         case STATE_NOSYNC:
190             while( !block_PeekBytes( &p_sys->bytestream, p_header, MLP_HEADER_SIZE ) )
191             {
192                 if( SyncInfo( p_header, &p_sys->b_mlp, &p_sys->mlp ) > 0 )
193                 {
194                     p_sys->i_state = STATE_SYNC;
195                     break;
196                 }
197                 else if( SyncInfoDolby( p_header ) > 0 )
198                 {
199                     p_sys->i_state = STATE_SYNC;
200                     break;
201                 }
202                 block_SkipByte( &p_sys->bytestream );
203             }
204             if( p_sys->i_state != STATE_SYNC )
205             {
206                 block_BytestreamFlush( &p_sys->bytestream );
207
208                 /* Need more data */
209                 return NULL;
210             }
211
212         case STATE_SYNC:
213             /* New frame, set the Presentation Time Stamp */
214             p_sys->i_pts = p_sys->bytestream.p_block->i_pts;
215             if( p_sys->i_pts != 0 &&
216                 p_sys->i_pts != date_Get( &p_sys->end_date ) )
217             {
218                 date_Set( &p_sys->end_date, p_sys->i_pts );
219             }
220             p_sys->i_state = STATE_HEADER;
221
222         case STATE_HEADER:
223             /* Get a MLP header */
224             if( block_PeekBytes( &p_sys->bytestream, p_header, MLP_HEADER_SIZE ) )
225             {
226                 /* Need more data */
227                 return NULL;
228             }
229
230             /* Check if frame is valid and get frame info */
231             p_sys->i_frame_size = SyncInfoDolby( p_header );
232             if( p_sys->i_frame_size <= 0 )
233                 p_sys->i_frame_size = SyncInfo( p_header, &p_sys->b_mlp, &p_sys->mlp );
234             if( p_sys->i_frame_size <= 0 )
235             {
236                 msg_Dbg( p_dec, "emulated sync word" );
237                 block_SkipByte( &p_sys->bytestream );
238                 p_sys->b_mlp = false;
239                 p_sys->i_state = STATE_NOSYNC;
240                 break;
241             }
242             p_sys->i_state = STATE_NEXT_SYNC;
243
244         case STATE_NEXT_SYNC:
245             /* TODO: If pp_block == NULL, flush the buffer without checking the
246              * next sync word */
247
248             /* Check if next expected frame contains the sync word */
249             if( block_PeekOffsetBytes( &p_sys->bytestream,
250                                        p_sys->i_frame_size, p_header, MLP_HEADER_SIZE ) )
251             {
252                 /* Need more data */
253                 return NULL;
254             }
255
256             bool b_mlp = p_sys->b_mlp;
257             mlp_header_t mlp = p_sys->mlp;
258             if( SyncInfo( p_header, &b_mlp, &mlp ) <= 0 && SyncInfoDolby( p_header ) <= 0 )
259             {
260                 msg_Dbg( p_dec, "emulated sync word "
261                          "(no sync on following frame)" );
262                 p_sys->b_mlp = false;
263                 p_sys->i_state = STATE_NOSYNC;
264                 block_SkipByte( &p_sys->bytestream );
265                 break;
266             }
267             p_sys->i_state = STATE_SEND_DATA;
268             break;
269
270         case STATE_GET_DATA:
271             /* Make sure we have enough data.
272              * (Not useful if we went through NEXT_SYNC) */
273             if( block_WaitBytes( &p_sys->bytestream, p_sys->i_frame_size ) )
274             {
275                 /* Need more data */
276                 return NULL;
277             }
278             p_sys->i_state = STATE_SEND_DATA;
279
280         case STATE_SEND_DATA:
281             /* When we reach this point we already know we have enough
282              * data available. */
283             p_out_buffer = block_New( p_dec, p_sys->i_frame_size );
284             if( !p_out_buffer )
285                 return NULL;
286
287             /* Copy the whole frame into the buffer */
288             block_GetBytes( &p_sys->bytestream,
289                             p_out_buffer->p_buffer, p_out_buffer->i_buffer );
290
291             /* Just ignore (E)AC3 frames */
292             if( SyncInfoDolby( p_out_buffer->p_buffer ) > 0 )
293             {
294                 block_Release( p_out_buffer );
295                 p_sys->i_state = STATE_NOSYNC;
296                 break;
297             }
298
299             /* Setup output */
300             if( p_dec->fmt_out.audio.i_rate != p_sys->mlp.i_rate )
301             {
302                 msg_Info( p_dec, "MLP channels: %d samplerate: %d",
303                           p_sys->mlp.i_channels, p_sys->mlp.i_rate );
304
305                 date_Init( &p_sys->end_date, p_sys->mlp.i_rate, 1 );
306                 date_Set( &p_sys->end_date, p_sys->i_pts );
307             }
308
309             p_dec->fmt_out.audio.i_rate     = p_sys->mlp.i_rate;
310             p_dec->fmt_out.audio.i_channels = p_sys->mlp.i_channels;
311             p_dec->fmt_out.audio.i_original_channels = p_sys->mlp.i_channels_conf;
312             p_dec->fmt_out.audio.i_physical_channels = p_sys->mlp.i_channels_conf & AOUT_CHAN_PHYSMASK;
313
314             p_out_buffer->i_pts = p_out_buffer->i_dts = date_Get( &p_sys->end_date );
315
316             p_out_buffer->i_length =
317                 date_Increment( &p_sys->end_date, p_sys->mlp.i_samples ) - p_out_buffer->i_pts;
318
319             /* Make sure we don't reuse the same pts twice */
320             if( p_sys->i_pts == p_sys->bytestream.p_block->i_pts )
321                 p_sys->i_pts = p_sys->bytestream.p_block->i_pts = 0;
322
323             /* So p_block doesn't get re-added several times */
324             *pp_block = block_BytestreamPop( &p_sys->bytestream );
325
326             p_sys->i_state = STATE_NOSYNC;
327
328             return p_out_buffer;
329         }
330     }
331
332     return NULL;
333 }
334
335 /*****************************************************************************
336  * Close:
337  *****************************************************************************/
338 static void Close( vlc_object_t *p_this )
339 {
340     decoder_t *p_dec = (decoder_t*)p_this;
341     decoder_sys_t *p_sys = p_dec->p_sys;
342
343     block_BytestreamRelease( &p_sys->bytestream );
344
345     free( p_sys );
346 }
347
348 /**
349  * It parse MLP sync info.
350  *
351  * TODO handle CRC (at offset 26)
352   */
353
354 static int TrueHdChannels( int i_map )
355 {
356     static const uint8_t pu_thd[13] =
357     {
358          2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1
359     };
360     int i_count = 0;
361
362     for( int i = 0; i < 13; i++ )
363     {
364         if( i_map & (1<<i) )
365             i_count += pu_thd[i];
366     }
367     return i_count;
368 }
369
370 static int MlpParse( mlp_header_t *p_mlp, const uint8_t p_hdr[MLP_HEADER_SYNC] )
371 {
372     bs_t s;
373
374     assert( !memcmp( p_hdr, pu_start_code, 3 ) );
375
376     /* TODO Checksum ? */
377
378     /* */
379     bs_init( &s, &p_hdr[3], MLP_HEADER_SYNC - 3 );
380
381     /* Stream type */
382     p_mlp->i_type = bs_read( &s, 8 );
383     int i_rate_idx1;
384
385     if( p_mlp->i_type == 0xbb )        /* MLP */
386     {
387         static const unsigned pu_channels[32] = {
388             1, 2, 3, 4, 3, 4, 5, 3, 4, 5, 4, 5, 6, 4, 5, 4,
389             5, 6, 5, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
390         };
391
392         bs_skip( &s, 4 + 4 );
393
394         i_rate_idx1 = bs_read( &s, 4 );
395         const int i_rate_idx2 = bs_read( &s, 4 );
396
397         bs_skip( &s, 11 );
398
399         const int i_channel_idx = bs_read( &s, 5 );
400         p_mlp->i_channels = pu_channels[i_channel_idx];
401     }
402     else if( p_mlp->i_type == 0xba )   /* True HD */
403     {
404         i_rate_idx1 = bs_read( &s, 4 );
405
406         bs_skip( &s, 8 );
407
408         const int i_channel1 = bs_read( &s, 5 );
409
410         bs_skip( &s, 2 );
411
412         const int i_channel2 = bs_read( &s, 13 );
413         if( i_channel2 )
414             p_mlp->i_channels = TrueHdChannels( i_channel2 );
415         else
416             p_mlp->i_channels = TrueHdChannels( i_channel1 );
417     }
418     else
419     {
420         return VLC_EGENERIC;
421     }
422
423     if( i_rate_idx1 == 0x0f )
424         p_mlp->i_rate = 0;
425     else
426         p_mlp->i_rate = ( ( i_rate_idx1 & 0x8 ) ? 44100 : 48000 ) << (i_rate_idx1 & 0x7);
427     p_mlp->i_channels_conf = 0; /* TODO ? */
428
429     p_mlp->i_samples = 40 << ( i_rate_idx1 & 0x07 );
430
431     bs_skip( &s, 48 );
432
433     p_mlp->b_vbr = bs_read( &s, 1 );
434     p_mlp->i_bitrate = ( bs_read( &s, 15 ) * p_mlp->i_rate + 8) / 16;
435
436     p_mlp->i_substreams = bs_read( &s, 4 );
437     bs_skip( &s, 4 + 11 * 8 );
438
439     //fprintf( stderr, "i_samples = %d channels:%d rate:%d bitsrate=%d substreams=%d\n",
440     //        p_mlp->i_samples, p_mlp->i_channels, p_mlp->i_rate, p_mlp->i_bitrate, p_mlp->i_substreams );
441     return VLC_SUCCESS;
442 }
443
444 static int SyncInfo( const uint8_t *p_hdr, bool *pb_mlp, mlp_header_t *p_mlp )
445 {
446     /* Check major sync presence */
447     const bool b_has_sync = !memcmp( &p_hdr[4], pu_start_code, 3 );
448
449     /* Wait for a major sync */
450     if( !b_has_sync && !*pb_mlp )
451         return 0;
452
453     /* Parse major sync if present */
454     if( b_has_sync )
455     {
456         *pb_mlp = !MlpParse( p_mlp, &p_hdr[4] );
457
458         if( !*pb_mlp )
459             return 0;
460     }
461
462     /* Check parity TODO even with major sync */
463     if( 1 )
464     {
465         int i_tmp = 0 ^ p_hdr[0] ^ p_hdr[1] ^ p_hdr[2] ^ p_hdr[3];
466         const uint8_t *p = &p_hdr[4 + ( b_has_sync ? 28 : 0 )];
467
468         for( int i = 0; i < p_mlp->i_substreams; i++ )
469         {
470             i_tmp ^= *p++;
471             i_tmp ^= *p++;
472             if( p[-2] & 0x80 )
473             {
474                 i_tmp ^= *p++;
475                 i_tmp ^= *p++;
476             }
477         }
478         i_tmp = ( i_tmp >> 4 ) ^ i_tmp;
479
480         if( ( i_tmp & 0x0f ) != 0x0f )
481             return 0;
482     }
483
484     /* */
485     const int i_word = ( ( p_hdr[0] << 8 ) | p_hdr[1] ) & 0xfff;
486     return i_word * 2;
487 }
488
489 /**
490  * It returns the size of an AC3 frame (or 0 if invalid)
491  */
492 static int GetAc3Size( const uint8_t *p_buf )
493 {
494     static const int pi_rate[] = { 32,  40,  48,  56,  64,  80,  96, 112,
495                                 128, 160, 192, 224, 256, 320, 384, 448,
496                                 512, 576, 640 };
497     /* */
498     const int i_frmsizecod = p_buf[4] & 63;
499     if( i_frmsizecod >= 38 )
500         return 0;
501
502     const int bitrate = pi_rate[i_frmsizecod >> 1];
503
504     switch( p_buf[4] & 0xc0 )
505     {
506     case 0:
507         return 4 * bitrate;
508     case 0x40:
509         return 2 * (320 * bitrate / 147 + (i_frmsizecod & 1));
510     case 0x80:
511         return 6 * bitrate;
512     default:
513         return 0;
514     }
515 }
516
517 /**
518  * It return the size of a EAC3 frame (or 0 if invalid)
519  */
520 static int GetEac3Size( const uint8_t *p_buf )
521 {
522     int i_frame_size;
523     int i_bytes;
524
525     i_frame_size = ( ( p_buf[2] << 8 ) | p_buf[3] ) & 0x7ff;
526     if( i_frame_size < 2 )
527         return 0;
528     i_bytes = 2 * ( i_frame_size + 1 );
529
530     return i_bytes;
531 }
532
533 /**
534  * It returns the size of an AC3/EAC3 frame (or 0 if invalid)
535  */
536 static int SyncInfoDolby( const uint8_t *p_buf )
537 {
538     int bsid;
539
540     /* Check synword */
541     if( p_buf[0] != 0x0b || p_buf[1] != 0x77 )
542         return 0;
543
544     /* Check bsid */
545     bsid = p_buf[5] >> 3;
546     if( bsid > 16 )
547         return 0;
548
549     if( bsid <= 10 )
550         return GetAc3Size( p_buf );
551     else
552         return GetEac3Size( p_buf );
553 }
554