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