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