opengl: implement subpictures renderer
[vlc.git] / modules / packetizer / mlp.c
blob308e7fca04fc99be1b5d61245cb1837e453c7b54
1 /*****************************************************************************
2 * mlp.c: packetize MLP/TrueHD audio
3 *****************************************************************************
4 * Copyright (C) 2008 Laurent Aimar
6 * Authors: Laurent Aimar < fenrir _AT videolan _DOT_ org >
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
23 /*****************************************************************************
24 * Preamble
25 *****************************************************************************/
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
30 #include <vlc_common.h>
31 #include <vlc_plugin.h>
32 #include <vlc_codec.h>
33 #include <vlc_block_helper.h>
34 #include <vlc_bits.h>
35 #include <assert.h>
37 #include "packetizer_helper.h"
38 #include "a52.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 typedef struct
75 * Input properties
77 int i_state;
79 block_bytestream_t bytestream;
82 * Common properties
84 date_t end_date;
85 bool b_discontinuity;
87 vlc_tick_t i_pts;
88 int i_frame_size;
90 bool b_mlp;
91 mlp_header_t mlp;
92 } decoder_sys_t;
94 #define MLP_MAX_SUBSTREAMS (16)
95 #define MLP_HEADER_SYNC (28)
96 #define MLP_HEADER_SIZE (4 + MLP_HEADER_SYNC + 4 * MLP_MAX_SUBSTREAMS)
98 static const uint8_t pu_start_code[3] = { 0xf8, 0x72, 0x6f };
101 * It parse MLP sync info.
103 * TODO handle CRC (at offset 26)
105 static int TrueHdChannels( int i_map )
107 static const uint8_t pu_thd[13] =
109 2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1
111 int i_count = 0;
113 for( int i = 0; i < 13; i++ )
115 if( i_map & (1<<i) )
116 i_count += pu_thd[i];
118 return i_count;
121 static int MlpParse( mlp_header_t *p_mlp, const uint8_t p_hdr[MLP_HEADER_SYNC] )
123 bs_t s;
125 assert( !memcmp( p_hdr, pu_start_code, 3 ) );
127 /* TODO Checksum ? */
129 /* */
130 bs_init( &s, &p_hdr[3], MLP_HEADER_SYNC - 3 );
132 /* Stream type */
133 p_mlp->i_type = bs_read( &s, 8 );
134 int i_rate_idx1;
136 if( p_mlp->i_type == 0xbb ) /* MLP */
138 static const unsigned pu_channels[32] = {
139 1, 2, 3, 4, 3, 4, 5, 3, 4, 5, 4, 5, 6, 4, 5, 4,
140 5, 6, 5, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
143 bs_skip( &s, 4 + 4 );
145 i_rate_idx1 = bs_read( &s, 4 );
147 // Just skip the 4 following, since we don't use it
148 // const int i_rate_idx2 = bs_read( &s, 4 );
149 bs_skip( &s, 4 );
151 bs_skip( &s, 11 );
153 const int i_channel_idx = bs_read( &s, 5 );
154 p_mlp->i_channels = pu_channels[i_channel_idx];
156 else if( p_mlp->i_type == 0xba ) /* True HD */
158 i_rate_idx1 = bs_read( &s, 4 );
160 bs_skip( &s, 8 );
162 const int i_channel1 = bs_read( &s, 5 );
164 bs_skip( &s, 2 );
166 const int i_channel2 = bs_read( &s, 13 );
167 if( i_channel2 )
168 p_mlp->i_channels = TrueHdChannels( i_channel2 );
169 else
170 p_mlp->i_channels = TrueHdChannels( i_channel1 );
172 else
174 return VLC_EGENERIC;
177 if( i_rate_idx1 == 0x0f )
178 p_mlp->i_rate = 0;
179 else
180 p_mlp->i_rate = ( ( i_rate_idx1 & 0x8 ) ? 44100 : 48000 ) << (i_rate_idx1 & 0x7);
181 p_mlp->i_channels_conf = 0; /* TODO ? */
183 p_mlp->i_samples = 40 << ( i_rate_idx1 & 0x07 );
185 bs_skip( &s, 48 );
187 p_mlp->b_vbr = bs_read( &s, 1 );
188 p_mlp->i_bitrate = ( bs_read( &s, 15 ) * p_mlp->i_rate + 8) / 16;
190 p_mlp->i_substreams = bs_read( &s, 4 );
191 bs_skip( &s, 4 + 11 * 8 );
193 //fprintf( stderr, "i_samples = %d channels:%d rate:%d bitsrate=%d substreams=%d\n",
194 // p_mlp->i_samples, p_mlp->i_channels, p_mlp->i_rate, p_mlp->i_bitrate, p_mlp->i_substreams );
195 return VLC_SUCCESS;
198 static int SyncInfo( const uint8_t *p_hdr, bool *pb_mlp, mlp_header_t *p_mlp )
200 /* Check major sync presence */
201 const bool b_has_sync = !memcmp( &p_hdr[4], pu_start_code, 3 );
203 /* Wait for a major sync */
204 if( !b_has_sync && !*pb_mlp )
205 return 0;
207 /* Parse major sync if present */
208 if( b_has_sync )
210 *pb_mlp = !MlpParse( p_mlp, &p_hdr[4] );
212 if( !*pb_mlp )
213 return 0;
216 if( !b_has_sync )
218 int i_tmp = 0 ^ p_hdr[0] ^ p_hdr[1] ^ p_hdr[2] ^ p_hdr[3];
219 const uint8_t *p = &p_hdr[4];
221 for( unsigned i = 0; i < p_mlp->i_substreams; i++ )
223 i_tmp ^= *p++;
224 i_tmp ^= *p++;
225 if( p[-2] & 0x80 )
227 i_tmp ^= *p++;
228 i_tmp ^= *p++;
231 i_tmp = ( i_tmp >> 4 ) ^ i_tmp;
233 if( ( i_tmp & 0x0f ) != 0x0f )
234 return 0;
237 /* */
238 const int i_word = ( ( p_hdr[0] << 8 ) | p_hdr[1] ) & 0xfff;
239 return i_word * 2;
243 * It returns the size of an AC3/EAC3 frame (or 0 if invalid)
245 static int SyncInfoDolby( const uint8_t *p_buf )
247 vlc_a52_header_t a52;
248 if( vlc_a52_header_Parse( &a52, p_buf, MLP_HEADER_SIZE ) == VLC_SUCCESS )
249 return a52.i_size;
250 else
251 return 0;
254 static void Flush( decoder_t *p_dec )
256 decoder_sys_t *p_sys = p_dec->p_sys;
258 p_sys->b_mlp = false;
259 p_sys->i_state = STATE_NOSYNC;
260 p_sys->b_discontinuity = true;
261 block_BytestreamEmpty( &p_sys->bytestream );
262 date_Set( &p_sys->end_date, VLC_TICK_INVALID );
265 static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
267 decoder_sys_t *p_sys = p_dec->p_sys;
268 uint8_t p_header[MLP_HEADER_SIZE];
269 block_t *p_out_buffer;
271 block_t *p_block = pp_block ? *pp_block : NULL;
273 if ( p_block )
275 if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
277 /* First always drain complete blocks before discontinuity */
278 block_t *p_drain = Packetize( p_dec, NULL );
279 if( p_drain )
280 return p_drain;
282 Flush( p_dec );
284 if( p_block->i_flags & BLOCK_FLAG_CORRUPTED )
286 block_Release( p_block );
287 return NULL;
291 if( p_block->i_pts == VLC_TICK_INVALID &&
292 date_Get( &p_sys->end_date ) == VLC_TICK_INVALID )
294 /* We've just started the stream, wait for the first PTS. */
295 msg_Dbg( p_dec, "waiting for PTS" );
296 block_Release( p_block );
297 return NULL;
300 block_BytestreamPush( &p_sys->bytestream, p_block );
303 for( ;; )
305 switch( p_sys->i_state )
307 case STATE_NOSYNC:
308 while( !block_PeekBytes( &p_sys->bytestream, p_header, MLP_HEADER_SIZE ) )
310 if( SyncInfo( p_header, &p_sys->b_mlp, &p_sys->mlp ) > 0 )
312 p_sys->i_state = STATE_SYNC;
313 break;
315 else if( SyncInfoDolby( p_header ) > 0 )
317 p_sys->i_state = STATE_SYNC;
318 break;
320 block_SkipByte( &p_sys->bytestream );
322 if( p_sys->i_state != STATE_SYNC )
324 block_BytestreamFlush( &p_sys->bytestream );
326 /* Need more data */
327 return NULL;
329 /* fallthrough */
331 case STATE_SYNC:
332 /* New frame, set the Presentation Time Stamp */
333 p_sys->i_pts = p_sys->bytestream.p_block->i_pts;
334 if( p_sys->i_pts != VLC_TICK_INVALID &&
335 p_sys->i_pts != date_Get( &p_sys->end_date ) )
337 date_Set( &p_sys->end_date, p_sys->i_pts );
339 p_sys->i_state = STATE_HEADER;
340 /* fallthrough */
342 case STATE_HEADER:
343 /* Get a MLP header */
344 if( block_PeekBytes( &p_sys->bytestream, p_header, MLP_HEADER_SIZE ) )
346 /* Need more data */
347 return NULL;
350 /* Check if frame is valid and get frame info */
351 p_sys->i_frame_size = SyncInfoDolby( p_header );
352 if( p_sys->i_frame_size <= 0 )
353 p_sys->i_frame_size = SyncInfo( p_header, &p_sys->b_mlp, &p_sys->mlp );
354 if( p_sys->i_frame_size <= 0 )
356 msg_Dbg( p_dec, "emulated sync word" );
357 block_SkipByte( &p_sys->bytestream );
358 p_sys->b_mlp = false;
359 p_sys->i_state = STATE_NOSYNC;
360 break;
362 p_sys->i_state = STATE_NEXT_SYNC;
363 /* fallthrough */
365 case STATE_NEXT_SYNC:
366 /* Check if next expected frame contains the sync word */
367 if( block_PeekOffsetBytes( &p_sys->bytestream,
368 p_sys->i_frame_size, p_header, MLP_HEADER_SIZE ) )
370 if( p_block == NULL ) /* drain */
372 p_sys->i_state = STATE_GET_DATA;
373 break;
375 /* Need more data */
376 return NULL;
379 bool b_mlp = p_sys->b_mlp;
380 mlp_header_t mlp = p_sys->mlp;
381 if( SyncInfo( p_header, &b_mlp, &mlp ) <= 0 && SyncInfoDolby( p_header ) <= 0 )
383 msg_Dbg( p_dec, "emulated sync word "
384 "(no sync on following frame)" );
385 p_sys->b_mlp = false;
386 p_sys->i_state = STATE_NOSYNC;
387 block_SkipByte( &p_sys->bytestream );
388 break;
390 p_sys->i_state = STATE_GET_DATA;
391 break;
393 case STATE_GET_DATA:
394 /* Make sure we have enough data. */
395 if( block_WaitBytes( &p_sys->bytestream, p_sys->i_frame_size ) )
397 /* Need more data */
398 return NULL;
400 p_sys->i_state = STATE_SEND_DATA;
401 /* fallthrough */
403 case STATE_SEND_DATA:
404 /* When we reach this point we already know we have enough
405 * data available. */
406 p_out_buffer = block_Alloc( p_sys->i_frame_size );
407 if( !p_out_buffer )
408 return NULL;
410 /* Copy the whole frame into the buffer */
411 block_GetBytes( &p_sys->bytestream,
412 p_out_buffer->p_buffer, p_out_buffer->i_buffer );
414 /* Just ignore (E)AC3 frames */
415 if( SyncInfoDolby( p_out_buffer->p_buffer ) > 0 )
417 block_Release( p_out_buffer );
418 p_sys->i_state = STATE_NOSYNC;
419 break;
422 /* Setup output */
423 if( p_dec->fmt_out.audio.i_rate != p_sys->mlp.i_rate )
425 msg_Info( p_dec, "MLP channels: %d samplerate: %d",
426 p_sys->mlp.i_channels, p_sys->mlp.i_rate );
428 if( p_sys->mlp.i_rate > 0 )
429 date_Change( &p_sys->end_date, p_sys->mlp.i_rate, 1 );
432 p_dec->fmt_out.audio.i_rate = p_sys->mlp.i_rate;
433 p_dec->fmt_out.audio.i_channels = p_sys->mlp.i_channels;
434 p_dec->fmt_out.audio.i_physical_channels = p_sys->mlp.i_channels_conf;
435 p_dec->fmt_out.audio.i_bytes_per_frame = p_sys->i_frame_size;
436 p_dec->fmt_out.audio.i_frame_length = p_sys->mlp.i_samples;
438 p_out_buffer->i_pts = p_out_buffer->i_dts = date_Get( &p_sys->end_date );
439 p_out_buffer->i_nb_samples = p_sys->mlp.i_samples;
441 p_out_buffer->i_length =
442 date_Increment( &p_sys->end_date, p_sys->mlp.i_samples ) - p_out_buffer->i_pts;
444 /* Make sure we don't reuse the same pts twice */
445 if( p_sys->i_pts == p_sys->bytestream.p_block->i_pts )
446 p_sys->i_pts = p_sys->bytestream.p_block->i_pts = VLC_TICK_INVALID;
448 if( p_sys->b_discontinuity )
450 p_out_buffer->i_flags |= BLOCK_FLAG_DISCONTINUITY;
451 p_sys->b_discontinuity = false;
454 /* So p_block doesn't get re-added several times */
455 if( pp_block )
456 *pp_block = block_BytestreamPop( &p_sys->bytestream );
458 p_sys->i_state = STATE_NOSYNC;
460 return p_out_buffer;
464 return NULL;
467 static int Open( vlc_object_t *p_this )
469 decoder_t *p_dec = (decoder_t*)p_this;
470 decoder_sys_t *p_sys;
472 if( p_dec->fmt_in.i_codec != VLC_CODEC_MLP &&
473 p_dec->fmt_in.i_codec != VLC_CODEC_TRUEHD )
474 return VLC_EGENERIC;
476 /* */
477 p_dec->p_sys = p_sys = malloc( sizeof(*p_sys) );
478 if( !p_sys )
479 return VLC_ENOMEM;
481 /* */
482 p_sys->i_state = STATE_NOSYNC;
483 date_Init( &p_sys->end_date, 1, 1 );
485 block_BytestreamInit( &p_sys->bytestream );
486 p_sys->b_mlp = false;
487 p_sys->b_discontinuity = false;
489 /* Set output properties (Passthrough only) */
490 p_dec->fmt_out.i_codec = p_dec->fmt_in.i_codec;
491 p_dec->fmt_out.audio.i_rate = 0;
493 /* Set callback */
494 p_dec->pf_packetize = Packetize;
495 p_dec->pf_flush = Flush;
496 p_dec->pf_get_cc = NULL;
497 return VLC_SUCCESS;
500 static void Close( vlc_object_t *p_this )
502 decoder_t *p_dec = (decoder_t*)p_this;
503 decoder_sys_t *p_sys = p_dec->p_sys;
505 block_BytestreamRelease( &p_sys->bytestream );
507 free( p_sys );