]> git.sesse.net Git - vlc/blob - modules/packetizer/mlp.c
opus: update i_buffer when memmoving decoder output
[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                 if( p_sys->mlp.i_rate > 0 )
297                 {
298                     const mtime_t i_end_date = date_Get( &p_sys->end_date );
299                     date_Init( &p_sys->end_date, p_sys->mlp.i_rate, 1 );
300                     date_Set( &p_sys->end_date, i_end_date );
301                 }
302             }
303
304             p_dec->fmt_out.audio.i_rate     = p_sys->mlp.i_rate;
305             p_dec->fmt_out.audio.i_channels = p_sys->mlp.i_channels;
306             p_dec->fmt_out.audio.i_original_channels = p_sys->mlp.i_channels_conf;
307             p_dec->fmt_out.audio.i_physical_channels = p_sys->mlp.i_channels_conf;
308
309             p_out_buffer->i_pts = p_out_buffer->i_dts = date_Get( &p_sys->end_date );
310
311             p_out_buffer->i_length =
312                 date_Increment( &p_sys->end_date, p_sys->mlp.i_samples ) - p_out_buffer->i_pts;
313
314             /* Make sure we don't reuse the same pts twice */
315             if( p_sys->i_pts == p_sys->bytestream.p_block->i_pts )
316                 p_sys->i_pts = p_sys->bytestream.p_block->i_pts = VLC_TS_INVALID;
317
318             /* So p_block doesn't get re-added several times */
319             *pp_block = block_BytestreamPop( &p_sys->bytestream );
320
321             p_sys->i_state = STATE_NOSYNC;
322
323             return p_out_buffer;
324         }
325     }
326
327     return NULL;
328 }
329
330 /*****************************************************************************
331  * Close:
332  *****************************************************************************/
333 static void Close( vlc_object_t *p_this )
334 {
335     decoder_t *p_dec = (decoder_t*)p_this;
336     decoder_sys_t *p_sys = p_dec->p_sys;
337
338     block_BytestreamRelease( &p_sys->bytestream );
339
340     free( p_sys );
341 }
342
343 /**
344  * It parse MLP sync info.
345  *
346  * TODO handle CRC (at offset 26)
347   */
348
349 static int TrueHdChannels( int i_map )
350 {
351     static const uint8_t pu_thd[13] =
352     {
353          2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1
354     };
355     int i_count = 0;
356
357     for( int i = 0; i < 13; i++ )
358     {
359         if( i_map & (1<<i) )
360             i_count += pu_thd[i];
361     }
362     return i_count;
363 }
364
365 static int MlpParse( mlp_header_t *p_mlp, const uint8_t p_hdr[MLP_HEADER_SYNC] )
366 {
367     bs_t s;
368
369     assert( !memcmp( p_hdr, pu_start_code, 3 ) );
370
371     /* TODO Checksum ? */
372
373     /* */
374     bs_init( &s, &p_hdr[3], MLP_HEADER_SYNC - 3 );
375
376     /* Stream type */
377     p_mlp->i_type = bs_read( &s, 8 );
378     int i_rate_idx1;
379
380     if( p_mlp->i_type == 0xbb )        /* MLP */
381     {
382         static const unsigned pu_channels[32] = {
383             1, 2, 3, 4, 3, 4, 5, 3, 4, 5, 4, 5, 6, 4, 5, 4,
384             5, 6, 5, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
385         };
386
387         bs_skip( &s, 4 + 4 );
388
389         i_rate_idx1 = bs_read( &s, 4 );
390
391         // Just skip the 4 following, since we don't use it
392         // const int i_rate_idx2 = bs_read( &s, 4 );
393         bs_skip( &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( unsigned 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