]> git.sesse.net Git - vlc/blob - modules/packetizer/mlp.c
Use var_InheritString for --decklink-video-connection.
[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     unsigned i_rate;
60     unsigned i_channels;
61     int i_channels_conf;
62     unsigned i_samples;
63
64     bool b_vbr;
65     unsigned  i_bitrate;
66
67     unsigned  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 > VLC_TS_INVALID &&
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                 const mtime_t i_end_date = date_Get( &p_sys->end_date );
306                 date_Init( &p_sys->end_date, p_sys->mlp.i_rate, 1 );
307                 date_Set( &p_sys->end_date, i_end_date );
308             }
309
310             p_dec->fmt_out.audio.i_rate     = p_sys->mlp.i_rate;
311             p_dec->fmt_out.audio.i_channels = p_sys->mlp.i_channels;
312             p_dec->fmt_out.audio.i_original_channels = p_sys->mlp.i_channels_conf;
313             p_dec->fmt_out.audio.i_physical_channels = p_sys->mlp.i_channels_conf & AOUT_CHAN_PHYSMASK;
314
315             p_out_buffer->i_pts = p_out_buffer->i_dts = date_Get( &p_sys->end_date );
316
317             p_out_buffer->i_length =
318                 date_Increment( &p_sys->end_date, p_sys->mlp.i_samples ) - p_out_buffer->i_pts;
319
320             /* Make sure we don't reuse the same pts twice */
321             if( p_sys->i_pts == p_sys->bytestream.p_block->i_pts )
322                 p_sys->i_pts = p_sys->bytestream.p_block->i_pts = VLC_TS_INVALID;
323
324             /* So p_block doesn't get re-added several times */
325             *pp_block = block_BytestreamPop( &p_sys->bytestream );
326
327             p_sys->i_state = STATE_NOSYNC;
328
329             return p_out_buffer;
330         }
331     }
332
333     return NULL;
334 }
335
336 /*****************************************************************************
337  * Close:
338  *****************************************************************************/
339 static void Close( vlc_object_t *p_this )
340 {
341     decoder_t *p_dec = (decoder_t*)p_this;
342     decoder_sys_t *p_sys = p_dec->p_sys;
343
344     block_BytestreamRelease( &p_sys->bytestream );
345
346     free( p_sys );
347 }
348
349 /**
350  * It parse MLP sync info.
351  *
352  * TODO handle CRC (at offset 26)
353   */
354
355 static int TrueHdChannels( int i_map )
356 {
357     static const uint8_t pu_thd[13] =
358     {
359          2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1
360     };
361     int i_count = 0;
362
363     for( int i = 0; i < 13; i++ )
364     {
365         if( i_map & (1<<i) )
366             i_count += pu_thd[i];
367     }
368     return i_count;
369 }
370
371 static int MlpParse( mlp_header_t *p_mlp, const uint8_t p_hdr[MLP_HEADER_SYNC] )
372 {
373     bs_t s;
374
375     assert( !memcmp( p_hdr, pu_start_code, 3 ) );
376
377     /* TODO Checksum ? */
378
379     /* */
380     bs_init( &s, &p_hdr[3], MLP_HEADER_SYNC - 3 );
381
382     /* Stream type */
383     p_mlp->i_type = bs_read( &s, 8 );
384     int i_rate_idx1;
385
386     if( p_mlp->i_type == 0xbb )        /* MLP */
387     {
388         static const unsigned pu_channels[32] = {
389             1, 2, 3, 4, 3, 4, 5, 3, 4, 5, 4, 5, 6, 4, 5, 4,
390             5, 6, 5, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
391         };
392
393         bs_skip( &s, 4 + 4 );
394
395         i_rate_idx1 = bs_read( &s, 4 );
396
397         // Just skip the 4 following, since we don't use it
398         // const int i_rate_idx2 = bs_read( &s, 4 );
399         bs_skip( &s, 4 );
400
401         bs_skip( &s, 11 );
402
403         const int i_channel_idx = bs_read( &s, 5 );
404         p_mlp->i_channels = pu_channels[i_channel_idx];
405     }
406     else if( p_mlp->i_type == 0xba )   /* True HD */
407     {
408         i_rate_idx1 = bs_read( &s, 4 );
409
410         bs_skip( &s, 8 );
411
412         const int i_channel1 = bs_read( &s, 5 );
413
414         bs_skip( &s, 2 );
415
416         const int i_channel2 = bs_read( &s, 13 );
417         if( i_channel2 )
418             p_mlp->i_channels = TrueHdChannels( i_channel2 );
419         else
420             p_mlp->i_channels = TrueHdChannels( i_channel1 );
421     }
422     else
423     {
424         return VLC_EGENERIC;
425     }
426
427     if( i_rate_idx1 == 0x0f )
428         p_mlp->i_rate = 0;
429     else
430         p_mlp->i_rate = ( ( i_rate_idx1 & 0x8 ) ? 44100 : 48000 ) << (i_rate_idx1 & 0x7);
431     p_mlp->i_channels_conf = 0; /* TODO ? */
432
433     p_mlp->i_samples = 40 << ( i_rate_idx1 & 0x07 );
434
435     bs_skip( &s, 48 );
436
437     p_mlp->b_vbr = bs_read( &s, 1 );
438     p_mlp->i_bitrate = ( bs_read( &s, 15 ) * p_mlp->i_rate + 8) / 16;
439
440     p_mlp->i_substreams = bs_read( &s, 4 );
441     bs_skip( &s, 4 + 11 * 8 );
442
443     //fprintf( stderr, "i_samples = %d channels:%d rate:%d bitsrate=%d substreams=%d\n",
444     //        p_mlp->i_samples, p_mlp->i_channels, p_mlp->i_rate, p_mlp->i_bitrate, p_mlp->i_substreams );
445     return VLC_SUCCESS;
446 }
447
448 static int SyncInfo( const uint8_t *p_hdr, bool *pb_mlp, mlp_header_t *p_mlp )
449 {
450     /* Check major sync presence */
451     const bool b_has_sync = !memcmp( &p_hdr[4], pu_start_code, 3 );
452
453     /* Wait for a major sync */
454     if( !b_has_sync && !*pb_mlp )
455         return 0;
456
457     /* Parse major sync if present */
458     if( b_has_sync )
459     {
460         *pb_mlp = !MlpParse( p_mlp, &p_hdr[4] );
461
462         if( !*pb_mlp )
463             return 0;
464     }
465
466     /* Check parity TODO even with major sync */
467     if( 1 )
468     {
469         int i_tmp = 0 ^ p_hdr[0] ^ p_hdr[1] ^ p_hdr[2] ^ p_hdr[3];
470         const uint8_t *p = &p_hdr[4 + ( b_has_sync ? 28 : 0 )];
471
472         for( unsigned i = 0; i < p_mlp->i_substreams; i++ )
473         {
474             i_tmp ^= *p++;
475             i_tmp ^= *p++;
476             if( p[-2] & 0x80 )
477             {
478                 i_tmp ^= *p++;
479                 i_tmp ^= *p++;
480             }
481         }
482         i_tmp = ( i_tmp >> 4 ) ^ i_tmp;
483
484         if( ( i_tmp & 0x0f ) != 0x0f )
485             return 0;
486     }
487
488     /* */
489     const int i_word = ( ( p_hdr[0] << 8 ) | p_hdr[1] ) & 0xfff;
490     return i_word * 2;
491 }
492
493 /**
494  * It returns the size of an AC3 frame (or 0 if invalid)
495  */
496 static int GetAc3Size( const uint8_t *p_buf )
497 {
498     static const int pi_rate[] = { 32,  40,  48,  56,  64,  80,  96, 112,
499                                 128, 160, 192, 224, 256, 320, 384, 448,
500                                 512, 576, 640 };
501     /* */
502     const int i_frmsizecod = p_buf[4] & 63;
503     if( i_frmsizecod >= 38 )
504         return 0;
505
506     const int bitrate = pi_rate[i_frmsizecod >> 1];
507
508     switch( p_buf[4] & 0xc0 )
509     {
510     case 0:
511         return 4 * bitrate;
512     case 0x40:
513         return 2 * (320 * bitrate / 147 + (i_frmsizecod & 1));
514     case 0x80:
515         return 6 * bitrate;
516     default:
517         return 0;
518     }
519 }
520
521 /**
522  * It return the size of a EAC3 frame (or 0 if invalid)
523  */
524 static int GetEac3Size( const uint8_t *p_buf )
525 {
526     int i_frame_size;
527     int i_bytes;
528
529     i_frame_size = ( ( p_buf[2] << 8 ) | p_buf[3] ) & 0x7ff;
530     if( i_frame_size < 2 )
531         return 0;
532     i_bytes = 2 * ( i_frame_size + 1 );
533
534     return i_bytes;
535 }
536
537 /**
538  * It returns the size of an AC3/EAC3 frame (or 0 if invalid)
539  */
540 static int SyncInfoDolby( const uint8_t *p_buf )
541 {
542     int bsid;
543
544     /* Check synword */
545     if( p_buf[0] != 0x0b || p_buf[1] != 0x77 )
546         return 0;
547
548     /* Check bsid */
549     bsid = p_buf[5] >> 3;
550     if( bsid > 16 )
551         return 0;
552
553     if( bsid <= 10 )
554         return GetAc3Size( p_buf );
555     else
556         return GetEac3Size( p_buf );
557 }
558