]> git.sesse.net Git - vlc/blob - modules/packetizer/mlp.c
Used VLC_CODEC_* and vlc_fourcc_GetCodec when suitable.
[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     audio_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         return VLC_EGENERIC;
125
126     /* */
127     p_dec->p_sys = p_sys = malloc( sizeof(*p_sys) );
128     if( !p_sys )
129         return VLC_ENOMEM;
130
131     /* */
132     p_sys->i_state = STATE_NOSYNC;
133     aout_DateSet( &p_sys->end_date, 0 );
134
135     p_sys->bytestream = block_BytestreamInit();
136     p_sys->b_mlp = false;
137
138     /* Set output properties */
139     p_dec->fmt_out.i_cat = AUDIO_ES;
140     p_dec->fmt_out.i_codec = VLC_CODEC_MLP;
141     p_dec->fmt_out.audio.i_rate = 0;
142
143     /* Set callback */
144     p_dec->pf_packetize = Packetize;
145     return VLC_SUCCESS;
146 }
147
148 /****************************************************************************
149  * Packetize:
150  ****************************************************************************/
151 static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
152 {
153     decoder_sys_t *p_sys = p_dec->p_sys;
154     uint8_t p_header[MLP_HEADER_SIZE];
155     block_t *p_out_buffer;
156
157     /* */
158     if( !pp_block || !*pp_block )
159         return NULL;
160
161     /* */
162     if( (*pp_block)->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
163     {
164         if( (*pp_block)->i_flags&BLOCK_FLAG_CORRUPTED )
165         {
166             p_sys->b_mlp = false;
167             p_sys->i_state = STATE_NOSYNC;
168             block_BytestreamEmpty( &p_sys->bytestream );
169         }
170         aout_DateSet( &p_sys->end_date, 0 );
171         block_Release( *pp_block );
172         return NULL;
173     }
174
175     if( !aout_DateGet( &p_sys->end_date ) && !(*pp_block)->i_pts )
176     {
177         /* We've just started the stream, wait for the first PTS. */
178         block_Release( *pp_block );
179         return NULL;
180     }
181
182     block_BytestreamPush( &p_sys->bytestream, *pp_block );
183
184     for( ;; )
185     {
186         switch( p_sys->i_state )
187         {
188         case STATE_NOSYNC:
189             while( !block_PeekBytes( &p_sys->bytestream, p_header, MLP_HEADER_SIZE ) )
190             {
191                 if( SyncInfo( p_header, &p_sys->b_mlp, &p_sys->mlp ) > 0 )
192                 {
193                     p_sys->i_state = STATE_SYNC;
194                     break;
195                 }
196                 else if( SyncInfoDolby( p_header ) > 0 )
197                 {
198                     p_sys->i_state = STATE_SYNC;
199                     break;
200                 }
201                 block_SkipByte( &p_sys->bytestream );
202             }
203             if( p_sys->i_state != STATE_SYNC )
204             {
205                 block_BytestreamFlush( &p_sys->bytestream );
206
207                 /* Need more data */
208                 return NULL;
209             }
210
211         case STATE_SYNC:
212             /* New frame, set the Presentation Time Stamp */
213             p_sys->i_pts = p_sys->bytestream.p_block->i_pts;
214             if( p_sys->i_pts != 0 &&
215                 p_sys->i_pts != aout_DateGet( &p_sys->end_date ) )
216             {
217                 aout_DateSet( &p_sys->end_date, p_sys->i_pts );
218             }
219             p_sys->i_state = STATE_HEADER;
220
221         case STATE_HEADER:
222             /* Get a MLP header */
223             if( block_PeekBytes( &p_sys->bytestream, p_header, MLP_HEADER_SIZE ) )
224             {
225                 /* Need more data */
226                 return NULL;
227             }
228
229             /* Check if frame is valid and get frame info */
230             p_sys->i_frame_size = SyncInfoDolby( p_header );
231             if( p_sys->i_frame_size <= 0 )
232                 p_sys->i_frame_size = SyncInfo( p_header, &p_sys->b_mlp, &p_sys->mlp );
233             if( p_sys->i_frame_size <= 0 )
234             {
235                 msg_Dbg( p_dec, "emulated sync word" );
236                 block_SkipByte( &p_sys->bytestream );
237                 p_sys->b_mlp = false;
238                 p_sys->i_state = STATE_NOSYNC;
239                 break;
240             }
241             p_sys->i_state = STATE_NEXT_SYNC;
242
243         case STATE_NEXT_SYNC:
244             /* TODO: If pp_block == NULL, flush the buffer without checking the
245              * next sync word */
246
247             /* Check if next expected frame contains the sync word */
248             if( block_PeekOffsetBytes( &p_sys->bytestream,
249                                        p_sys->i_frame_size, p_header, MLP_HEADER_SIZE ) )
250             {
251                 /* Need more data */
252                 return NULL;
253             }
254
255             bool b_mlp = p_sys->b_mlp;
256             mlp_header_t mlp = p_sys->mlp;
257             if( SyncInfo( p_header, &b_mlp, &mlp ) <= 0 && SyncInfoDolby( p_header ) <= 0 )
258             {
259                 msg_Dbg( p_dec, "emulated sync word "
260                          "(no sync on following frame)" );
261                 p_sys->b_mlp = false;
262                 p_sys->i_state = STATE_NOSYNC;
263                 block_SkipByte( &p_sys->bytestream );
264                 break;
265             }
266             p_sys->i_state = STATE_SEND_DATA;
267             break;
268
269         case STATE_GET_DATA:
270             /* Make sure we have enough data.
271              * (Not useful if we went through NEXT_SYNC) */
272             if( block_WaitBytes( &p_sys->bytestream, p_sys->i_frame_size ) )
273             {
274                 /* Need more data */
275                 return NULL;
276             }
277             p_sys->i_state = STATE_SEND_DATA;
278
279         case STATE_SEND_DATA:
280             /* When we reach this point we already know we have enough
281              * data available. */
282             p_out_buffer = block_New( p_dec, p_sys->i_frame_size );
283             if( !p_out_buffer )
284                 return NULL;
285
286             /* Copy the whole frame into the buffer */
287             block_GetBytes( &p_sys->bytestream,
288                             p_out_buffer->p_buffer, p_out_buffer->i_buffer );
289
290             /* Just ignore (E)AC3 frames */
291             if( SyncInfoDolby( p_out_buffer->p_buffer ) > 0 )
292             {
293                 block_Release( p_out_buffer );
294                 p_sys->i_state = STATE_NOSYNC;
295                 break;
296             }
297
298             /* Setup output */
299             if( p_dec->fmt_out.audio.i_rate != p_sys->mlp.i_rate )
300             {
301                 msg_Info( p_dec, "MLP channels: %d samplerate: %d",
302                           p_sys->mlp.i_channels, p_sys->mlp.i_rate );
303
304                 aout_DateInit( &p_sys->end_date, p_sys->mlp.i_rate );
305                 aout_DateSet( &p_sys->end_date, p_sys->i_pts );
306             }
307
308             p_dec->fmt_out.audio.i_rate     = p_sys->mlp.i_rate;
309             p_dec->fmt_out.audio.i_channels = p_sys->mlp.i_channels;
310             p_dec->fmt_out.audio.i_original_channels = p_sys->mlp.i_channels_conf;
311             p_dec->fmt_out.audio.i_physical_channels = p_sys->mlp.i_channels_conf & AOUT_CHAN_PHYSMASK;
312
313             p_out_buffer->i_pts = p_out_buffer->i_dts = aout_DateGet( &p_sys->end_date );
314
315             p_out_buffer->i_length =
316                 aout_DateIncrement( &p_sys->end_date, p_sys->mlp.i_samples ) - p_out_buffer->i_pts;
317
318             /* Make sure we don't reuse the same pts twice */
319             if( p_sys->i_pts == p_sys->bytestream.p_block->i_pts )
320                 p_sys->i_pts = p_sys->bytestream.p_block->i_pts = 0;
321
322             /* So p_block doesn't get re-added several times */
323             *pp_block = block_BytestreamPop( &p_sys->bytestream );
324
325             p_sys->i_state = STATE_NOSYNC;
326
327             return p_out_buffer;
328         }
329     }
330
331     return NULL;
332 }
333
334 /*****************************************************************************
335  * Close:
336  *****************************************************************************/
337 static void Close( vlc_object_t *p_this )
338 {
339     decoder_t *p_dec = (decoder_t*)p_this;
340     decoder_sys_t *p_sys = p_dec->p_sys;
341
342     block_BytestreamRelease( &p_sys->bytestream );
343
344     free( p_sys );
345 }
346
347 /**
348  * It parse MLP sync info.
349  *
350  * TODO handle CRC (at offset 26)
351   */
352
353 static int TrueHdChannels( int i_map )
354 {
355     static const uint8_t pu_thd[13] =
356     {
357          2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1
358     };
359     int i_count = 0;
360
361     for( int i = 0; i < 13; i++ )
362     {
363         if( i_map & (1<<i) )
364             i_count += pu_thd[i];
365     }
366     return i_count;
367 }
368
369 static int MlpParse( mlp_header_t *p_mlp, const uint8_t p_hdr[MLP_HEADER_SYNC] )
370 {
371     bs_t s;
372
373     assert( !memcmp( p_hdr, pu_start_code, 3 ) );
374
375     /* TODO Checksum ? */
376
377     /* */
378     bs_init( &s, &p_hdr[3], MLP_HEADER_SYNC - 3 );
379
380     /* Stream type */
381     p_mlp->i_type = bs_read( &s, 8 );
382     int i_rate_idx1;
383
384     if( p_mlp->i_type == 0xbb )        /* MLP */
385     {
386         static const unsigned pu_channels[32] = {
387             1, 2, 3, 4, 3, 4, 5, 3, 4, 5, 4, 5, 6, 4, 5, 4,
388             5, 6, 5, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
389         };
390
391         bs_skip( &s, 4 + 4 );
392
393         i_rate_idx1 = bs_read( &s, 4 );
394         const int i_rate_idx2 = bs_read( &s, 4 );
395
396         bs_skip( &s, 11 );
397
398         const int i_channel_idx = bs_read( &s, 5 );
399         p_mlp->i_channels = pu_channels[i_channel_idx];
400     }
401     else if( p_mlp->i_type == 0xba )   /* True HD */
402     {
403         i_rate_idx1 = bs_read( &s, 4 );
404
405         bs_skip( &s, 8 );
406
407         const int i_channel1 = bs_read( &s, 5 );
408
409         bs_skip( &s, 2 );
410
411         const int i_channel2 = bs_read( &s, 13 );
412         if( i_channel2 )
413             p_mlp->i_channels = TrueHdChannels( i_channel2 );
414         else
415             p_mlp->i_channels = TrueHdChannels( i_channel1 );
416     }
417     else
418     {
419         return VLC_EGENERIC;
420     }
421
422     if( i_rate_idx1 == 0x0f )
423         p_mlp->i_rate = 0;
424     else
425         p_mlp->i_rate = ( ( i_rate_idx1 & 0x8 ) ? 44100 : 48000 ) << (i_rate_idx1 & 0x7);
426     p_mlp->i_channels_conf = 0; /* TODO ? */
427
428     p_mlp->i_samples = 40 << ( i_rate_idx1 & 0x07 );
429
430     bs_skip( &s, 48 );
431
432     p_mlp->b_vbr = bs_read( &s, 1 );
433     p_mlp->i_bitrate = ( bs_read( &s, 15 ) * p_mlp->i_rate + 8) / 16;
434
435     p_mlp->i_substreams = bs_read( &s, 4 );
436     bs_skip( &s, 4 + 11 * 8 );
437
438     //fprintf( stderr, "i_samples = %d channels:%d rate:%d bitsrate=%d substreams=%d\n",
439     //        p_mlp->i_samples, p_mlp->i_channels, p_mlp->i_rate, p_mlp->i_bitrate, p_mlp->i_substreams );
440     return VLC_SUCCESS;
441 }
442
443 static int SyncInfo( const uint8_t *p_hdr, bool *pb_mlp, mlp_header_t *p_mlp )
444 {
445     /* Check major sync presence */
446     const bool b_has_sync = !memcmp( &p_hdr[4], pu_start_code, 3 );
447
448     /* Wait for a major sync */
449     if( !b_has_sync && !*pb_mlp )
450         return 0;
451
452     /* Parse major sync if present */
453     if( b_has_sync )
454     {
455         *pb_mlp = !MlpParse( p_mlp, &p_hdr[4] );
456
457         if( !*pb_mlp )
458             return 0;
459     }
460
461     /* Check parity TODO even with major sync */
462     if( 1 )
463     {
464         int i_tmp = 0 ^ p_hdr[0] ^ p_hdr[1] ^ p_hdr[2] ^ p_hdr[3];
465         const uint8_t *p = &p_hdr[4 + ( b_has_sync ? 28 : 0 )];
466
467         for( int i = 0; i < p_mlp->i_substreams; i++ )
468         {
469             i_tmp ^= *p++;
470             i_tmp ^= *p++;
471             if( p[-2] & 0x80 )
472             {
473                 i_tmp ^= *p++;
474                 i_tmp ^= *p++;
475             }
476         }
477         i_tmp = ( i_tmp >> 4 ) ^ i_tmp;
478
479         if( ( i_tmp & 0x0f ) != 0x0f )
480             return 0;
481     }
482
483     /* */
484     const int i_word = ( ( p_hdr[0] << 8 ) | p_hdr[1] ) & 0xfff;
485     return i_word * 2;
486 }
487
488 /**
489  * It returns the size of an AC3 frame (or 0 if invalid)
490  */
491 static int GetAc3Size( const uint8_t *p_buf )
492 {
493     static const int pi_rate[] = { 32,  40,  48,  56,  64,  80,  96, 112,
494                                 128, 160, 192, 224, 256, 320, 384, 448,
495                                 512, 576, 640 };
496     /* */
497     const int i_frmsizecod = p_buf[4] & 63;
498     if( i_frmsizecod >= 38 )
499         return 0;
500
501     const int bitrate = pi_rate[i_frmsizecod >> 1];
502
503     switch( p_buf[4] & 0xc0 )
504     {
505     case 0:
506         return 4 * bitrate;
507     case 0x40:
508         return 2 * (320 * bitrate / 147 + (i_frmsizecod & 1));
509     case 0x80:
510         return 6 * bitrate;
511     default:
512         return 0;
513     }
514 }
515
516 /**
517  * It return the size of a EAC3 frame (or 0 if invalid)
518  */
519 static int GetEac3Size( const uint8_t *p_buf )
520 {
521     int i_frame_size;
522     int i_bytes;
523
524     i_frame_size = ( ( p_buf[2] << 8 ) | p_buf[3] ) & 0x7ff;
525     if( i_frame_size < 2 )
526         return 0;
527     i_bytes = 2 * ( i_frame_size + 1 );
528
529     return i_bytes;
530 }
531
532 /**
533  * It returns the size of an AC3/EAC3 frame (or 0 if invalid)
534  */
535 static int SyncInfoDolby( const uint8_t *p_buf )
536 {
537     int bsid;
538
539     /* Check synword */
540     if( p_buf[0] != 0x0b || p_buf[1] != 0x77 )
541         return 0;
542
543     /* Check bsid */
544     bsid = p_buf[5] >> 3;
545     if( bsid > 16 )
546         return 0;
547
548     if( bsid <= 10 )
549         return GetAc3Size( p_buf );
550     else
551         return GetEac3Size( p_buf );
552 }
553