]> git.sesse.net Git - vlc/blob - modules/packetizer/mlp.c
h264 packetizer: use VLC_TS_INVALID
[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                 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 = VLC_TS_INVALID;
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
396         // Just skip the 4 following, since we don't use it
397         // const int i_rate_idx2 = bs_read( &s, 4 );
398         bs_skip( &s, 4 );
399
400         bs_skip( &s, 11 );
401
402         const int i_channel_idx = bs_read( &s, 5 );
403         p_mlp->i_channels = pu_channels[i_channel_idx];
404     }
405     else if( p_mlp->i_type == 0xba )   /* True HD */
406     {
407         i_rate_idx1 = bs_read( &s, 4 );
408
409         bs_skip( &s, 8 );
410
411         const int i_channel1 = bs_read( &s, 5 );
412
413         bs_skip( &s, 2 );
414
415         const int i_channel2 = bs_read( &s, 13 );
416         if( i_channel2 )
417             p_mlp->i_channels = TrueHdChannels( i_channel2 );
418         else
419             p_mlp->i_channels = TrueHdChannels( i_channel1 );
420     }
421     else
422     {
423         return VLC_EGENERIC;
424     }
425
426     if( i_rate_idx1 == 0x0f )
427         p_mlp->i_rate = 0;
428     else
429         p_mlp->i_rate = ( ( i_rate_idx1 & 0x8 ) ? 44100 : 48000 ) << (i_rate_idx1 & 0x7);
430     p_mlp->i_channels_conf = 0; /* TODO ? */
431
432     p_mlp->i_samples = 40 << ( i_rate_idx1 & 0x07 );
433
434     bs_skip( &s, 48 );
435
436     p_mlp->b_vbr = bs_read( &s, 1 );
437     p_mlp->i_bitrate = ( bs_read( &s, 15 ) * p_mlp->i_rate + 8) / 16;
438
439     p_mlp->i_substreams = bs_read( &s, 4 );
440     bs_skip( &s, 4 + 11 * 8 );
441
442     //fprintf( stderr, "i_samples = %d channels:%d rate:%d bitsrate=%d substreams=%d\n",
443     //        p_mlp->i_samples, p_mlp->i_channels, p_mlp->i_rate, p_mlp->i_bitrate, p_mlp->i_substreams );
444     return VLC_SUCCESS;
445 }
446
447 static int SyncInfo( const uint8_t *p_hdr, bool *pb_mlp, mlp_header_t *p_mlp )
448 {
449     /* Check major sync presence */
450     const bool b_has_sync = !memcmp( &p_hdr[4], pu_start_code, 3 );
451
452     /* Wait for a major sync */
453     if( !b_has_sync && !*pb_mlp )
454         return 0;
455
456     /* Parse major sync if present */
457     if( b_has_sync )
458     {
459         *pb_mlp = !MlpParse( p_mlp, &p_hdr[4] );
460
461         if( !*pb_mlp )
462             return 0;
463     }
464
465     /* Check parity TODO even with major sync */
466     if( 1 )
467     {
468         int i_tmp = 0 ^ p_hdr[0] ^ p_hdr[1] ^ p_hdr[2] ^ p_hdr[3];
469         const uint8_t *p = &p_hdr[4 + ( b_has_sync ? 28 : 0 )];
470
471         for( unsigned i = 0; i < p_mlp->i_substreams; i++ )
472         {
473             i_tmp ^= *p++;
474             i_tmp ^= *p++;
475             if( p[-2] & 0x80 )
476             {
477                 i_tmp ^= *p++;
478                 i_tmp ^= *p++;
479             }
480         }
481         i_tmp = ( i_tmp >> 4 ) ^ i_tmp;
482
483         if( ( i_tmp & 0x0f ) != 0x0f )
484             return 0;
485     }
486
487     /* */
488     const int i_word = ( ( p_hdr[0] << 8 ) | p_hdr[1] ) & 0xfff;
489     return i_word * 2;
490 }
491
492 /**
493  * It returns the size of an AC3 frame (or 0 if invalid)
494  */
495 static int GetAc3Size( const uint8_t *p_buf )
496 {
497     static const int pi_rate[] = { 32,  40,  48,  56,  64,  80,  96, 112,
498                                 128, 160, 192, 224, 256, 320, 384, 448,
499                                 512, 576, 640 };
500     /* */
501     const int i_frmsizecod = p_buf[4] & 63;
502     if( i_frmsizecod >= 38 )
503         return 0;
504
505     const int bitrate = pi_rate[i_frmsizecod >> 1];
506
507     switch( p_buf[4] & 0xc0 )
508     {
509     case 0:
510         return 4 * bitrate;
511     case 0x40:
512         return 2 * (320 * bitrate / 147 + (i_frmsizecod & 1));
513     case 0x80:
514         return 6 * bitrate;
515     default:
516         return 0;
517     }
518 }
519
520 /**
521  * It return the size of a EAC3 frame (or 0 if invalid)
522  */
523 static int GetEac3Size( const uint8_t *p_buf )
524 {
525     int i_frame_size;
526     int i_bytes;
527
528     i_frame_size = ( ( p_buf[2] << 8 ) | p_buf[3] ) & 0x7ff;
529     if( i_frame_size < 2 )
530         return 0;
531     i_bytes = 2 * ( i_frame_size + 1 );
532
533     return i_bytes;
534 }
535
536 /**
537  * It returns the size of an AC3/EAC3 frame (or 0 if invalid)
538  */
539 static int SyncInfoDolby( const uint8_t *p_buf )
540 {
541     int bsid;
542
543     /* Check synword */
544     if( p_buf[0] != 0x0b || p_buf[1] != 0x77 )
545         return 0;
546
547     /* Check bsid */
548     bsid = p_buf[5] >> 3;
549     if( bsid > 16 )
550         return 0;
551
552     if( bsid <= 10 )
553         return GetAc3Size( p_buf );
554     else
555         return GetEac3Size( p_buf );
556 }
557