audiobargraph_a: fix counter wrapping
[vlc/gmpfix.git] / modules / packetizer / mlp.c
blobffd57c46a0030e89ba829440e748c484a88b2317
1 /*****************************************************************************
2 * mlp.c: packetize MLP/TrueHD audio
3 *****************************************************************************
4 * Copyright (C) 2008 Laurent Aimar
5 * $Id$
7 * Authors: Laurent Aimar < fenrir _AT videolan _DOT_ org >
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.
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.
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 *****************************************************************************/
24 /*****************************************************************************
25 * Preamble
26 *****************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
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>
38 #include "packetizer_helper.h"
40 /*****************************************************************************
41 * Module descriptor
42 *****************************************************************************/
43 static int Open ( vlc_object_t * );
44 static void Close( vlc_object_t * );
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 ()
54 /*****************************************************************************
56 *****************************************************************************/
57 typedef struct
59 int i_type;
60 unsigned i_rate;
61 unsigned i_channels;
62 int i_channels_conf;
63 unsigned i_samples;
65 bool b_vbr;
66 unsigned i_bitrate;
68 unsigned i_substreams;
70 } mlp_header_t;
72 struct decoder_sys_t
75 * Input properties
77 int i_state;
79 block_bytestream_t bytestream;
82 * Common properties
84 date_t end_date;
86 mtime_t i_pts;
87 int i_frame_size;
89 bool b_mlp;
90 mlp_header_t mlp;
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)
97 static const uint8_t pu_start_code[3] = { 0xf8, 0x72, 0x6f };
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 );
106 /*****************************************************************************
107 * Open: probe the decoder/packetizer and return score
108 *****************************************************************************/
109 static int Open( vlc_object_t *p_this )
111 decoder_t *p_dec = (decoder_t*)p_this;
112 decoder_sys_t *p_sys;
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;
118 /* */
119 p_dec->p_sys = p_sys = malloc( sizeof(*p_sys) );
120 if( !p_sys )
121 return VLC_ENOMEM;
123 /* */
124 p_sys->i_state = STATE_NOSYNC;
125 date_Set( &p_sys->end_date, 0 );
127 block_BytestreamInit( &p_sys->bytestream );
128 p_sys->b_mlp = false;
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;
135 /* Set callback */
136 p_dec->pf_packetize = Packetize;
137 return VLC_SUCCESS;
140 /****************************************************************************
141 * Packetize:
142 ****************************************************************************/
143 static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
145 decoder_sys_t *p_sys = p_dec->p_sys;
146 uint8_t p_header[MLP_HEADER_SIZE];
147 block_t *p_out_buffer;
149 /* */
150 if( !pp_block || !*pp_block )
151 return NULL;
153 /* */
154 if( (*pp_block)->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
156 if( (*pp_block)->i_flags&BLOCK_FLAG_CORRUPTED )
158 p_sys->b_mlp = false;
159 p_sys->i_state = STATE_NOSYNC;
160 block_BytestreamEmpty( &p_sys->bytestream );
162 date_Set( &p_sys->end_date, 0 );
163 block_Release( *pp_block );
164 return NULL;
167 if( !date_Get( &p_sys->end_date ) && !(*pp_block)->i_pts )
169 /* We've just started the stream, wait for the first PTS. */
170 block_Release( *pp_block );
171 return NULL;
174 block_BytestreamPush( &p_sys->bytestream, *pp_block );
176 for( ;; )
178 switch( p_sys->i_state )
180 case STATE_NOSYNC:
181 while( !block_PeekBytes( &p_sys->bytestream, p_header, MLP_HEADER_SIZE ) )
183 if( SyncInfo( p_header, &p_sys->b_mlp, &p_sys->mlp ) > 0 )
185 p_sys->i_state = STATE_SYNC;
186 break;
188 else if( SyncInfoDolby( p_header ) > 0 )
190 p_sys->i_state = STATE_SYNC;
191 break;
193 block_SkipByte( &p_sys->bytestream );
195 if( p_sys->i_state != STATE_SYNC )
197 block_BytestreamFlush( &p_sys->bytestream );
199 /* Need more data */
200 return NULL;
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 ) )
209 date_Set( &p_sys->end_date, p_sys->i_pts );
211 p_sys->i_state = STATE_HEADER;
213 case STATE_HEADER:
214 /* Get a MLP header */
215 if( block_PeekBytes( &p_sys->bytestream, p_header, MLP_HEADER_SIZE ) )
217 /* Need more data */
218 return NULL;
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 )
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;
233 p_sys->i_state = STATE_NEXT_SYNC;
235 case STATE_NEXT_SYNC:
236 /* TODO: If pp_block == NULL, flush the buffer without checking the
237 * next sync word */
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 ) )
243 /* Need more data */
244 return NULL;
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 )
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;
258 p_sys->i_state = STATE_SEND_DATA;
259 break;
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 ) )
266 /* Need more data */
267 return NULL;
269 p_sys->i_state = STATE_SEND_DATA;
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;
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 );
282 /* Just ignore (E)AC3 frames */
283 if( SyncInfoDolby( p_out_buffer->p_buffer ) > 0 )
285 block_Release( p_out_buffer );
286 p_sys->i_state = STATE_NOSYNC;
287 break;
290 /* Setup output */
291 if( p_dec->fmt_out.audio.i_rate != p_sys->mlp.i_rate )
293 msg_Info( p_dec, "MLP channels: %d samplerate: %d",
294 p_sys->mlp.i_channels, p_sys->mlp.i_rate );
296 if( p_sys->mlp.i_rate > 0 )
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 );
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;
309 p_out_buffer->i_pts = p_out_buffer->i_dts = date_Get( &p_sys->end_date );
311 p_out_buffer->i_length =
312 date_Increment( &p_sys->end_date, p_sys->mlp.i_samples ) - p_out_buffer->i_pts;
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;
318 /* So p_block doesn't get re-added several times */
319 *pp_block = block_BytestreamPop( &p_sys->bytestream );
321 p_sys->i_state = STATE_NOSYNC;
323 return p_out_buffer;
327 return NULL;
330 /*****************************************************************************
331 * Close:
332 *****************************************************************************/
333 static void Close( vlc_object_t *p_this )
335 decoder_t *p_dec = (decoder_t*)p_this;
336 decoder_sys_t *p_sys = p_dec->p_sys;
338 block_BytestreamRelease( &p_sys->bytestream );
340 free( p_sys );
344 * It parse MLP sync info.
346 * TODO handle CRC (at offset 26)
349 static int TrueHdChannels( int i_map )
351 static const uint8_t pu_thd[13] =
353 2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1
355 int i_count = 0;
357 for( int i = 0; i < 13; i++ )
359 if( i_map & (1<<i) )
360 i_count += pu_thd[i];
362 return i_count;
365 static int MlpParse( mlp_header_t *p_mlp, const uint8_t p_hdr[MLP_HEADER_SYNC] )
367 bs_t s;
369 assert( !memcmp( p_hdr, pu_start_code, 3 ) );
371 /* TODO Checksum ? */
373 /* */
374 bs_init( &s, &p_hdr[3], MLP_HEADER_SYNC - 3 );
376 /* Stream type */
377 p_mlp->i_type = bs_read( &s, 8 );
378 int i_rate_idx1;
380 if( p_mlp->i_type == 0xbb ) /* MLP */
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,
387 bs_skip( &s, 4 + 4 );
389 i_rate_idx1 = bs_read( &s, 4 );
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 );
395 bs_skip( &s, 11 );
397 const int i_channel_idx = bs_read( &s, 5 );
398 p_mlp->i_channels = pu_channels[i_channel_idx];
400 else if( p_mlp->i_type == 0xba ) /* True HD */
402 i_rate_idx1 = bs_read( &s, 4 );
404 bs_skip( &s, 8 );
406 const int i_channel1 = bs_read( &s, 5 );
408 bs_skip( &s, 2 );
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 );
416 else
418 return VLC_EGENERIC;
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 ? */
427 p_mlp->i_samples = 40 << ( i_rate_idx1 & 0x07 );
429 bs_skip( &s, 48 );
431 p_mlp->b_vbr = bs_read( &s, 1 );
432 p_mlp->i_bitrate = ( bs_read( &s, 15 ) * p_mlp->i_rate + 8) / 16;
434 p_mlp->i_substreams = bs_read( &s, 4 );
435 bs_skip( &s, 4 + 11 * 8 );
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;
442 static int SyncInfo( const uint8_t *p_hdr, bool *pb_mlp, mlp_header_t *p_mlp )
444 /* Check major sync presence */
445 const bool b_has_sync = !memcmp( &p_hdr[4], pu_start_code, 3 );
447 /* Wait for a major sync */
448 if( !b_has_sync && !*pb_mlp )
449 return 0;
451 /* Parse major sync if present */
452 if( b_has_sync )
454 *pb_mlp = !MlpParse( p_mlp, &p_hdr[4] );
456 if( !*pb_mlp )
457 return 0;
460 /* Check parity TODO even with major sync */
461 if( 1 )
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 )];
466 for( unsigned i = 0; i < p_mlp->i_substreams; i++ )
468 i_tmp ^= *p++;
469 i_tmp ^= *p++;
470 if( p[-2] & 0x80 )
472 i_tmp ^= *p++;
473 i_tmp ^= *p++;
476 i_tmp = ( i_tmp >> 4 ) ^ i_tmp;
478 if( ( i_tmp & 0x0f ) != 0x0f )
479 return 0;
482 /* */
483 const int i_word = ( ( p_hdr[0] << 8 ) | p_hdr[1] ) & 0xfff;
484 return i_word * 2;
488 * It returns the size of an AC3 frame (or 0 if invalid)
490 static int GetAc3Size( const uint8_t *p_buf )
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;
500 const int bitrate = pi_rate[i_frmsizecod >> 1];
502 switch( p_buf[4] & 0xc0 )
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;
516 * It return the size of a EAC3 frame (or 0 if invalid)
518 static int GetEac3Size( const uint8_t *p_buf )
520 int i_frame_size;
521 int i_bytes;
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 );
528 return i_bytes;
532 * It returns the size of an AC3/EAC3 frame (or 0 if invalid)
534 static int SyncInfoDolby( const uint8_t *p_buf )
536 int bsid;
538 /* Check synword */
539 if( p_buf[0] != 0x0b || p_buf[1] != 0x77 )
540 return 0;
542 /* Check bsid */
543 bsid = p_buf[5] >> 3;
544 if( bsid > 16 )
545 return 0;
547 if( bsid <= 10 )
548 return GetAc3Size( p_buf );
549 else
550 return GetEac3Size( p_buf );