1 /*****************************************************************************
2 * mlp.c: packetize MLP/TrueHD audio
3 *****************************************************************************
4 * Copyright (C) 2008 Laurent Aimar
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 /*****************************************************************************
26 *****************************************************************************/
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33 #include <vlc_codec.h>
34 #include <vlc_block_helper.h>
38 #include "packetizer_helper.h"
40 /*****************************************************************************
42 *****************************************************************************/
43 static int Open ( vlc_object_t
* );
44 static void Close( vlc_object_t
* );
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
)
54 /*****************************************************************************
56 *****************************************************************************/
68 unsigned i_substreams
;
79 block_bytestream_t bytestream
;
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 /****************************************************************************
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
)
119 p_dec
->p_sys
= p_sys
= malloc( sizeof(*p_sys
) );
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;
136 p_dec
->pf_packetize
= Packetize
;
140 /****************************************************************************
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
;
150 if( !pp_block
|| !*pp_block
)
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
);
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
);
174 block_BytestreamPush( &p_sys
->bytestream
, *pp_block
);
178 switch( p_sys
->i_state
)
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
;
188 else if( SyncInfoDolby( p_header
) > 0 )
190 p_sys
->i_state
= STATE_SYNC
;
193 block_SkipByte( &p_sys
->bytestream
);
195 if( p_sys
->i_state
!= STATE_SYNC
)
197 block_BytestreamFlush( &p_sys
->bytestream
);
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
;
214 /* Get a MLP header */
215 if( block_PeekBytes( &p_sys
->bytestream
, p_header
, MLP_HEADER_SIZE
) )
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
;
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
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
) )
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
);
258 p_sys
->i_state
= STATE_SEND_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
) )
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
274 p_out_buffer
= block_Alloc( p_sys
->i_frame_size
);
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
;
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
;
330 /*****************************************************************************
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
);
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
357 for( int i
= 0; i
< 13; i
++ )
360 i_count
+= pu_thd
[i
];
365 static int MlpParse( mlp_header_t
*p_mlp
, const uint8_t p_hdr
[MLP_HEADER_SYNC
] )
369 assert( !memcmp( p_hdr
, pu_start_code
, 3 ) );
371 /* TODO Checksum ? */
374 bs_init( &s
, &p_hdr
[3], MLP_HEADER_SYNC
- 3 );
377 p_mlp
->i_type
= bs_read( &s
, 8 );
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 );
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 );
406 const int i_channel1
= bs_read( &s
, 5 );
410 const int i_channel2
= bs_read( &s
, 13 );
412 p_mlp
->i_channels
= TrueHdChannels( i_channel2
);
414 p_mlp
->i_channels
= TrueHdChannels( i_channel1
);
421 if( i_rate_idx1
== 0x0f )
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 );
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 );
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
)
451 /* Parse major sync if present */
454 *pb_mlp
= !MlpParse( p_mlp
, &p_hdr
[4] );
460 /* Check parity TODO even with major sync */
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
++ )
476 i_tmp
= ( i_tmp
>> 4 ) ^ i_tmp
;
478 if( ( i_tmp
& 0x0f ) != 0x0f )
483 const int i_word
= ( ( p_hdr
[0] << 8 ) | p_hdr
[1] ) & 0xfff;
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,
496 const int i_frmsizecod
= p_buf
[4] & 63;
497 if( i_frmsizecod
>= 38 )
500 const int bitrate
= pi_rate
[i_frmsizecod
>> 1];
502 switch( p_buf
[4] & 0xc0 )
507 return 2 * (320 * bitrate
/ 147 + (i_frmsizecod
& 1));
516 * It return the size of a EAC3 frame (or 0 if invalid)
518 static int GetEac3Size( const uint8_t *p_buf
)
523 i_frame_size
= ( ( p_buf
[2] << 8 ) | p_buf
[3] ) & 0x7ff;
524 if( i_frame_size
< 2 )
526 i_bytes
= 2 * ( i_frame_size
+ 1 );
532 * It returns the size of an AC3/EAC3 frame (or 0 if invalid)
534 static int SyncInfoDolby( const uint8_t *p_buf
)
539 if( p_buf
[0] != 0x0b || p_buf
[1] != 0x77 )
543 bsid
= p_buf
[5] >> 3;
548 return GetAc3Size( p_buf
);
550 return GetEac3Size( p_buf
);