1 /*****************************************************************************
2 * lpcm.c: lpcm decoder/packetizer module
3 *****************************************************************************
4 * Copyright (C) 1999-2008 VLC authors and VideoLAN
7 * Authors: Samuel Hocevar <sam@zoy.org>
8 * Henri Fallon <henri@videolan.org>
9 * Christophe Massiot <massiot@via.ecp.fr>
10 * Gildas Bazin <gbazin@videolan.org>
11 * Lauren Aimar <fenrir _AT_ videolan _DOT_ org >
12 * Steinar H. Gunderson <steinar+vlc@gunderson.no>
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU Lesser General Public License as published by
16 * the Free Software Foundation; either version 2.1 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Lesser General Public License for more details.
24 * You should have received a copy of the GNU Lesser General Public License
25 * along with this program; if not, write to the Free Software Foundation,
26 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
27 *****************************************************************************/
29 /*****************************************************************************
31 *****************************************************************************/
36 #include <vlc_common.h>
37 #include <vlc_plugin.h>
38 #include <vlc_codec.h>
43 /*****************************************************************************
45 *****************************************************************************/
46 static int OpenDecoder ( vlc_object_t * );
47 static int OpenPacketizer( vlc_object_t * );
48 static void CloseCommon ( vlc_object_t * );
51 static int OpenEncoder ( vlc_object_t * );
52 static void CloseEncoder ( vlc_object_t * );
53 static block_t *EncodeFrames( encoder_t *, block_t * );
58 set_category( CAT_INPUT )
59 set_subcategory( SUBCAT_INPUT_ACODEC )
60 set_description( N_("Linear PCM audio decoder") )
61 set_capability( "decoder", 100 )
62 set_callbacks( OpenDecoder, CloseCommon )
65 set_description( N_("Linear PCM audio packetizer") )
66 set_capability( "packetizer", 100 )
67 set_callbacks( OpenPacketizer, CloseCommon )
71 set_description( N_("Linear PCM audio encoder") )
72 set_capability( "encoder", 100 )
73 set_callbacks( OpenEncoder, CloseEncoder )
74 add_shortcut( "lpcm" )
80 /*****************************************************************************
81 * decoder_sys_t : lpcm decoder descriptor
82 *****************************************************************************/
94 unsigned i_header_size;
113 * - number of frames in this packet (8 bits)
114 * - first access unit (16 bits) == 0x0003 ?
118 * - current frame (5 bits)
119 * - quantisation (2 bits) 0 == 16bps, 1 == 20bps, 2 == 24bps, 3 == illegal
120 * - frequency (2 bits) 0 == 48 kHz, 1 == 96 kHz, 2 == 44.1 kHz, 3 == 32 kHz
122 * - number of channels - 1 (3 bits) 1 == 2 channels
123 * - dynamic range (8 bits) 0x80 == neutral
125 * LPCM DVD-A header (http://dvd-audio.sourceforge.net/spec/aob.shtml)
126 * - continuity counter (8 bits, clipped to 0x00-0x1f)
127 * - header size (16 bits)
128 * - byte pointer to start of first audio frame.
129 * - unknown (8bits, 0x10 for stereo, 0x00 for surround)
130 * - sample size (4+4 bits)
131 * - samplerate (4+4 bits)
133 * - group assignment (8 bits)
135 * - padding(variable)
138 * - unknown (16 bits)
139 * - number of channels (4 bits)
140 * - frequency (4 bits)
141 * - bits per sample (2 bits)
145 #define LPCM_VOB_HEADER_LEN (6)
146 #define LPCM_AOB_HEADER_LEN (11)
147 #define LPCM_BD_HEADER_LEN (4)
160 unsigned pi_position[6];
163 /*****************************************************************************
165 *****************************************************************************/
166 static block_t *DecodeFrame ( decoder_t *, block_t ** );
169 static int VobHeader( unsigned *pi_rate,
170 unsigned *pi_channels, unsigned *pi_original_channels,
172 const uint8_t *p_header );
173 static void VobExtract( block_t *, block_t *, unsigned i_bits );
175 static int AobHeader( unsigned *pi_rate,
176 unsigned *pi_channels, unsigned *pi_layout,
178 unsigned *pi_padding,
180 const uint8_t *p_header );
181 static void AobExtract( block_t *, block_t *, unsigned i_bits, aob_group_t p_group[2] );
183 static int BdHeader( unsigned *pi_rate,
184 unsigned *pi_channels,
185 unsigned *pi_channels_padding,
186 unsigned *pi_original_channels,
188 const uint8_t *p_header );
189 static void BdExtract( block_t *, block_t *, unsigned, unsigned, unsigned, unsigned );
192 /*****************************************************************************
194 *****************************************************************************/
195 static int OpenCommon( vlc_object_t *p_this, bool b_packetizer )
197 decoder_t *p_dec = (decoder_t*)p_this;
198 decoder_sys_t *p_sys;
202 switch( p_dec->fmt_in.i_codec )
205 case VLC_CODEC_DVD_LPCM:
207 i_header_size = LPCM_VOB_HEADER_LEN;
210 case VLC_CODEC_DVDA_LPCM:
212 i_header_size = LPCM_AOB_HEADER_LEN;
215 case VLC_CODEC_BD_LPCM:
217 i_header_size = LPCM_BD_HEADER_LEN;
223 /* Allocate the memory needed to store the decoder's structure */
224 if( ( p_dec->p_sys = p_sys = malloc(sizeof(decoder_sys_t)) ) == NULL )
228 p_sys->b_packetizer = b_packetizer;
229 date_Set( &p_sys->end_date, 0 );
230 p_sys->i_type = i_type;
231 p_sys->i_header_size = i_header_size;
233 /* Set output properties */
234 p_dec->fmt_out.i_cat = AUDIO_ES;
241 p_dec->fmt_out.i_codec = VLC_CODEC_DVD_LPCM;
244 p_dec->fmt_out.i_codec = VLC_CODEC_DVDA_LPCM;
249 p_dec->fmt_out.i_codec = VLC_CODEC_BD_LPCM;
255 switch( p_dec->fmt_out.audio.i_bitspersample )
259 p_dec->fmt_out.i_codec = VLC_CODEC_S32N;
260 p_dec->fmt_out.audio.i_bitspersample = 32;
263 p_dec->fmt_out.i_codec = VLC_CODEC_S16N;
264 p_dec->fmt_out.audio.i_bitspersample = 16;
270 p_dec->pf_decode_audio = DecodeFrame;
271 p_dec->pf_packetize = DecodeFrame;
275 static int OpenDecoder( vlc_object_t *p_this )
277 return OpenCommon( p_this, false );
279 static int OpenPacketizer( vlc_object_t *p_this )
281 return OpenCommon( p_this, true );
284 /*****************************************************************************
285 * DecodeFrame: decodes an lpcm frame.
286 ****************************************************************************
287 * Beware, this function must be fed with complete frames (PES packet).
288 *****************************************************************************/
289 static block_t *DecodeFrame( decoder_t *p_dec, block_t **pp_block )
291 decoder_sys_t *p_sys = p_dec->p_sys;
293 unsigned int i_rate = 0, i_original_channels = 0, i_channels = 0, i_bits = 0;
296 if( !pp_block || !*pp_block ) return NULL;
299 *pp_block = NULL; /* So the packet doesn't get re-sent */
301 /* Date management */
302 if( p_block->i_pts > VLC_TS_INVALID &&
303 p_block->i_pts != date_Get( &p_sys->end_date ) )
305 date_Set( &p_sys->end_date, p_block->i_pts );
308 if( !date_Get( &p_sys->end_date ) )
310 /* We've just started the stream, wait for the first PTS. */
311 block_Release( p_block );
315 if( p_block->i_buffer <= p_sys->i_header_size )
317 msg_Err(p_dec, "frame is too short");
318 block_Release( p_block );
323 unsigned i_channels_padding = 0;
324 unsigned i_padding = 0;
325 aob_group_t p_aob_group[2];
326 switch( p_sys->i_type )
329 i_ret = VobHeader( &i_rate, &i_channels, &i_original_channels, &i_bits,
333 i_ret = AobHeader( &i_rate, &i_channels, &i_original_channels, &i_bits, &i_padding,
338 i_ret = BdHeader( &i_rate, &i_channels, &i_channels_padding, &i_original_channels, &i_bits,
345 if( i_ret || p_block->i_buffer <= p_sys->i_header_size + i_padding )
347 msg_Warn( p_dec, "no frame sync or too small frame" );
348 block_Release( p_block );
352 /* Set output properties */
353 if( p_dec->fmt_out.audio.i_rate != i_rate )
355 date_Init( &p_sys->end_date, i_rate, 1 );
356 date_Set( &p_sys->end_date, p_block->i_pts );
358 p_dec->fmt_out.audio.i_rate = i_rate;
359 p_dec->fmt_out.audio.i_channels = i_channels;
360 p_dec->fmt_out.audio.i_original_channels = i_original_channels;
361 p_dec->fmt_out.audio.i_physical_channels = i_original_channels;
363 i_frame_length = (p_block->i_buffer - p_sys->i_header_size - i_padding) /
364 (i_channels + i_channels_padding) * 8 / i_bits;
366 if( p_sys->b_packetizer )
368 p_block->i_pts = p_block->i_dts = date_Get( &p_sys->end_date );
370 date_Increment( &p_sys->end_date, i_frame_length ) -
373 /* Just pass on the incoming frame */
381 p_dec->fmt_out.i_codec = VLC_CODEC_S16N;
382 p_dec->fmt_out.audio.i_bitspersample = 16;
386 p_dec->fmt_out.i_codec = VLC_CODEC_S32N;
387 p_dec->fmt_out.audio.i_bitspersample = 32;
391 block_t *p_aout_buffer;
392 p_aout_buffer = decoder_NewAudioBuffer( p_dec, i_frame_length );
396 p_aout_buffer->i_pts = date_Get( &p_sys->end_date );
397 p_aout_buffer->i_length =
398 date_Increment( &p_sys->end_date, i_frame_length )
399 - p_aout_buffer->i_pts;
401 p_block->p_buffer += p_sys->i_header_size + i_padding;
402 p_block->i_buffer -= p_sys->i_header_size + i_padding;
404 switch( p_sys->i_type )
407 VobExtract( p_aout_buffer, p_block, i_bits );
410 AobExtract( p_aout_buffer, p_block, i_bits, p_aob_group );
415 BdExtract( p_aout_buffer, p_block, i_frame_length, i_channels, i_channels_padding, i_bits );
419 block_Release( p_block );
420 return p_aout_buffer;
424 /*****************************************************************************
425 * CloseCommon : lpcm decoder destruction
426 *****************************************************************************/
427 static void CloseCommon( vlc_object_t *p_this )
429 decoder_t *p_dec = (decoder_t*)p_this;
430 free( p_dec->p_sys );
434 /*****************************************************************************
435 * OpenEncoder: lpcm encoder construction
436 *****************************************************************************/
437 static int OpenEncoder( vlc_object_t *p_this )
439 encoder_t *p_enc = (encoder_t *)p_this;
440 encoder_sys_t *p_sys;
442 /* We only support DVD LPCM yet. */
443 if( p_enc->fmt_out.i_codec != VLC_CODEC_DVD_LPCM )
446 if( p_enc->fmt_in.audio.i_rate != 48000 &&
447 p_enc->fmt_in.audio.i_rate != 96000 &&
448 p_enc->fmt_in.audio.i_rate != 44100 &&
449 p_enc->fmt_in.audio.i_rate != 32000 )
451 msg_Err( p_enc, "DVD LPCM supports only sample rates of 48, 96, 44.1 or 32 kHz" );
455 if( p_enc->fmt_in.audio.i_channels > 8 )
457 msg_Err( p_enc, "DVD LPCM supports a maximum of eight channels" );
461 /* Allocate the memory needed to store the encoder's structure */
462 if( ( p_enc->p_sys = p_sys =
463 (encoder_sys_t *)malloc(sizeof(encoder_sys_t)) ) == NULL )
466 /* In DVD LCPM, a frame is always 150 PTS ticks. */
467 p_sys->i_frame_samples = p_enc->fmt_in.audio.i_rate * 150 / 90000;
468 p_sys->p_buffer = xmalloc(p_sys->i_frame_samples
469 * p_enc->fmt_in.audio.i_channels * 16);
470 p_sys->i_buffer_used = 0;
471 p_sys->i_frame_num = 0;
473 p_sys->i_channels = p_enc->fmt_in.audio.i_channels;
474 p_sys->i_rate = p_enc->fmt_in.audio.i_rate;
476 p_enc->pf_encode_audio = EncodeFrames;
477 p_enc->fmt_in.i_codec = p_enc->fmt_out.i_codec;
479 p_enc->fmt_in.audio.i_bitspersample = 16;
480 p_enc->fmt_in.i_codec = VLC_CODEC_S16N;
482 p_enc->fmt_out.i_bitrate =
483 p_enc->fmt_in.audio.i_channels *
484 p_enc->fmt_in.audio.i_rate *
485 p_enc->fmt_in.audio.i_bitspersample *
486 (p_sys->i_frame_samples + LPCM_VOB_HEADER_LEN) /
487 p_sys->i_frame_samples;
492 /*****************************************************************************
493 * CloseEncoder: lpcm encoder destruction
494 *****************************************************************************/
495 static void CloseEncoder ( vlc_object_t *p_this )
497 encoder_t *p_enc = (encoder_t *)p_this;
498 encoder_sys_t *p_sys = p_enc->p_sys;
500 free( p_sys->p_buffer );
504 /*****************************************************************************
505 * EncodeFrames: encode zero or more LCPM audio packets
506 *****************************************************************************/
507 static block_t *EncodeFrames( encoder_t *p_enc, block_t *p_aout_buf )
509 encoder_sys_t *p_sys = p_enc->p_sys;
510 block_t *p_first_block = NULL, *p_last_block = NULL;
512 if( !p_aout_buf || !p_aout_buf->i_buffer ) return NULL;
514 const int i_num_frames = ( p_sys->i_buffer_used + p_aout_buf->i_nb_samples ) /
515 p_sys->i_frame_samples;
516 const int i_leftover_samples = ( p_sys->i_buffer_used + p_aout_buf->i_nb_samples ) %
517 p_sys->i_frame_samples;
518 const int i_frame_size = p_sys->i_frame_samples * p_sys->i_channels * 2 + LPCM_VOB_HEADER_LEN;
519 const int i_start_offset = -p_sys->i_buffer_used;
521 uint8_t i_freq_code = 0;
523 switch( p_sys->i_rate ) {
540 int i_bytes_consumed = 0;
542 for ( int i = 0; i < i_num_frames; ++i )
544 block_t *p_block = block_Alloc( i_frame_size );
548 uint8_t *frame = (uint8_t *)p_block->p_buffer;
549 frame[0] = 1; /* one frame in packet */
551 frame[2] = 0; /* no first access unit */
552 frame[3] = (p_sys->i_frame_num + i) & 0x1f; /* no emphasis, no mute */
553 frame[4] = (i_freq_code << 4) | (p_sys->i_channels - 1);
554 frame[5] = 0x80; /* neutral dynamic range */
556 const int i_consume_samples = p_sys->i_frame_samples - p_sys->i_buffer_used;
557 const int i_kept_bytes = p_sys->i_buffer_used * p_sys->i_channels * 2;
558 const int i_consume_bytes = i_consume_samples * p_sys->i_channels * 2;
560 #ifdef WORDS_BIGENDIAN
561 memcpy( frame + 6, p_sys->p_buffer, i_kept_bytes );
562 memcpy( frame + 6 + i_kept_bytes, p_aout_buf->p_buffer + i_bytes_consumed,
565 swab( p_sys->p_buffer, frame + 6, i_kept_bytes );
566 swab( p_aout_buf->p_buffer + i_bytes_consumed, frame + 6 + i_kept_bytes,
570 p_sys->i_frame_num++;
571 p_sys->i_buffer_used = 0;
572 i_bytes_consumed += i_consume_bytes;
574 /* We need to find i_length by means of next_pts due to possible roundoff errors. */
575 mtime_t this_pts = p_aout_buf->i_pts +
576 (i * p_sys->i_frame_samples + i_start_offset) * CLOCK_FREQ / p_sys->i_rate;
577 mtime_t next_pts = p_aout_buf->i_pts +
578 ((i + 1) * p_sys->i_frame_samples + i_start_offset) * CLOCK_FREQ / p_sys->i_rate;
580 p_block->i_pts = p_block->i_dts = this_pts;
581 p_block->i_length = next_pts - this_pts;
584 p_first_block = p_last_block = p_block;
586 p_last_block = p_last_block->p_next = p_block;
589 memcpy( p_sys->p_buffer,
590 p_aout_buf->p_buffer + i_bytes_consumed,
591 i_leftover_samples * p_sys->i_channels * 2 );
592 p_sys->i_buffer_used = i_leftover_samples;
594 return p_first_block;
598 /*****************************************************************************
600 *****************************************************************************/
601 static int VobHeader( unsigned *pi_rate,
602 unsigned *pi_channels, unsigned *pi_original_channels,
604 const uint8_t *p_header )
606 const uint8_t i_header = p_header[4];
608 switch( (i_header >> 4) & 0x3 )
624 *pi_channels = (i_header & 0x7) + 1;
625 switch( *pi_channels - 1 )
628 *pi_original_channels = AOUT_CHAN_CENTER;
631 *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
634 /* This is unsure. */
635 *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_LFE;
638 *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
639 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
642 /* This is unsure. */
643 *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
644 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
648 *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
649 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
650 | AOUT_CHAN_CENTER | AOUT_CHAN_LFE;
653 *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
654 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
655 | AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT
656 | AOUT_CHAN_MIDDLERIGHT;
659 *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
660 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
661 | AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT
662 | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE;
666 switch( (i_header >> 6) & 0x3 )
680 /* Check frame sync and drop it. */
681 if( p_header[5] != 0x80 )
686 static const unsigned p_aob_group1[21][6] = {
687 { AOUT_CHAN_CENTER, 0 },
688 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 },
689 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 },
690 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 },
691 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 },
692 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 },
693 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 },
694 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 },
695 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 },
696 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 },
697 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 },
698 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 },
699 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 },
700 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER, 0 },
701 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER, 0 },
702 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER, 0 },
703 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER, 0 },
704 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER, 0 },
705 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 },
706 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 },
707 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 },
709 static const unsigned p_aob_group2[21][6] = {
712 { AOUT_CHAN_REARCENTER, 0 },
713 { AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 },
714 { AOUT_CHAN_LFE, 0 },
715 { AOUT_CHAN_LFE, AOUT_CHAN_REARCENTER, 0 },
716 { AOUT_CHAN_LFE, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 },
717 { AOUT_CHAN_CENTER, 0 },
718 { AOUT_CHAN_CENTER, AOUT_CHAN_REARCENTER, 0 },
719 { AOUT_CHAN_CENTER, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 },
720 { AOUT_CHAN_CENTER, AOUT_CHAN_LFE, 0 },
721 { AOUT_CHAN_CENTER, AOUT_CHAN_LFE, AOUT_CHAN_REARCENTER, 0 },
722 { AOUT_CHAN_CENTER, AOUT_CHAN_LFE, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 },
723 { AOUT_CHAN_REARCENTER, 0 },
724 { AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 },
725 { AOUT_CHAN_LFE, 0 },
726 { AOUT_CHAN_LFE, AOUT_CHAN_REARCENTER, 0 },
727 { AOUT_CHAN_LFE, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 },
728 { AOUT_CHAN_LFE, 0 },
729 { AOUT_CHAN_CENTER, 0 },
730 { AOUT_CHAN_CENTER, AOUT_CHAN_LFE, 0 },
733 static int AobHeader( unsigned *pi_rate,
734 unsigned *pi_channels, unsigned *pi_layout,
736 unsigned *pi_padding,
738 const uint8_t *p_header )
740 const unsigned i_header_size = GetWBE( &p_header[1] );
741 if( i_header_size + 3 < LPCM_AOB_HEADER_LEN )
744 *pi_padding = 3+i_header_size - LPCM_AOB_HEADER_LEN;
746 const int i_index_size_g1 = (p_header[6] >> 4) & 0x0f;
747 const int i_index_size_g2 = (p_header[6] ) & 0x0f;
748 const int i_index_rate_g1 = (p_header[7] >> 4) & 0x0f;
749 const int i_index_rate_g2 = (p_header[7] ) & 0x0f;
750 const int i_assignment = p_header[9];
753 if( i_index_size_g1 > 0x02 ||
754 ( i_index_size_g2 != 0x0f && i_index_size_g2 > 0x02 ) )
756 if( (i_index_rate_g1 & 0x07) > 0x02 ||
757 ( i_index_rate_g2 != 0x0f && (i_index_rate_g1 & 0x07) > 0x02 ) )
759 if( i_assignment > 20 )
763 *pi_bits = 16 + 4 * i_index_size_g1;
764 if( i_index_rate_g1 & 0x08 )
765 *pi_rate = 44100 << (i_index_rate_g1 & 0x07);
767 *pi_rate = 48000 << (i_index_rate_g1 & 0x07);
771 unsigned i_channels1 = 0;
772 unsigned i_layout1 = 0;
773 for( int i = 0; p_aob_group1[i_assignment][i] != 0; i++ )
776 i_layout1 |= p_aob_group1[i_assignment][i];
779 unsigned i_channels2 = 0;
780 unsigned i_layout2 = 0;
781 if( i_index_size_g2 != 0x0f && i_index_rate_g2 != 0x0f )
783 for( int i = 0; p_aob_group2[i_assignment][i] != 0; i++ )
786 i_layout2 |= p_aob_group2[i_assignment][i];
788 assert( (i_layout1 & i_layout2) == 0 );
790 /* It is enabled only when presents and compatible wih group1 */
791 const bool b_group2_used = i_index_size_g1 == i_index_size_g2 &&
792 i_index_rate_g1 == i_index_rate_g2;
795 *pi_channels = i_channels1 + ( b_group2_used ? i_channels2 : 0 );
796 *pi_layout = i_layout1 | ( b_group2_used ? i_layout2 : 0 );
799 for( unsigned i = 0; i < 2; i++ )
801 const unsigned *p_aob = i == 0 ? p_aob_group1[i_assignment] :
802 p_aob_group2[i_assignment];
803 g[i].i_channels = i == 0 ? i_channels1 :
806 g[i].b_used = i == 0 || b_group2_used;
809 for( unsigned j = 0; j < g[i].i_channels; j++ )
811 g[i].pi_position[j] = 0;
812 for( int k = 0; pi_vlc_chan_order_wg4[k] != 0; k++ )
814 const unsigned i_channel = pi_vlc_chan_order_wg4[k];
815 if( i_channel == p_aob[j] )
817 if( (*pi_layout) & i_channel )
818 g[i].pi_position[j]++;
825 static int BdHeader( unsigned *pi_rate,
826 unsigned *pi_channels,
827 unsigned *pi_channels_padding,
828 unsigned *pi_original_channels,
830 const uint8_t *p_header )
832 const uint32_t h = GetDWBE( p_header );
833 switch( ( h & 0xf000) >> 12 )
837 *pi_original_channels = AOUT_CHAN_CENTER;
841 *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
845 *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER;
849 *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARCENTER;
853 *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
854 AOUT_CHAN_REARCENTER;
858 *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
859 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
863 *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
864 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
868 *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
869 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT |
874 *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
875 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT |
876 AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT;
880 *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
881 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT |
882 AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT |
889 *pi_channels_padding = *pi_channels & 1;
891 switch( (h >> 6) & 0x03 )
896 case 2: /* 20 bits but samples are stored on 24 bits */
897 case 3: /* 24 bits */
903 switch( (h >> 8) & 0x0f )
920 static void VobExtract( block_t *p_aout_buffer, block_t *p_block,
923 /* 20/24 bits LPCM use special packing */
926 uint32_t *p_out = (uint32_t *)p_aout_buffer->p_buffer;
928 while( p_block->i_buffer / 12 )
931 *(p_out++) = (p_block->p_buffer[ 0] << 24)
932 | (p_block->p_buffer[ 1] << 16)
933 | (p_block->p_buffer[ 8] << 8);
935 *(p_out++) = (p_block->p_buffer[ 2] << 24)
936 | (p_block->p_buffer[ 3] << 16)
937 | (p_block->p_buffer[ 9] << 8);
939 *(p_out++) = (p_block->p_buffer[ 4] << 24)
940 | (p_block->p_buffer[ 5] << 16)
941 | (p_block->p_buffer[10] << 8);
943 *(p_out++) = (p_block->p_buffer[ 6] << 24)
944 | (p_block->p_buffer[ 7] << 16)
945 | (p_block->p_buffer[11] << 8);
947 p_block->i_buffer -= 12;
948 p_block->p_buffer += 12;
951 else if( i_bits == 20 )
953 uint32_t *p_out = (uint32_t *)p_aout_buffer->p_buffer;
955 while( p_block->i_buffer / 10 )
958 *(p_out++) = ( p_block->p_buffer[0] << 24)
959 | ( p_block->p_buffer[1] << 16)
960 | ((p_block->p_buffer[8] & 0xF0) << 8);
962 *(p_out++) = ( p_block->p_buffer[2] << 24)
963 | ( p_block->p_buffer[3] << 16)
964 | ((p_block->p_buffer[8] & 0x0F) << 12);
966 *(p_out++) = ( p_block->p_buffer[4] << 24)
967 | ( p_block->p_buffer[5] << 16)
968 | ((p_block->p_buffer[9] & 0xF0) << 8);
970 *(p_out++) = ( p_block->p_buffer[6] << 24)
971 | ( p_block->p_buffer[7] << 16)
972 | ((p_block->p_buffer[9] & 0x0F) << 12);
974 p_block->i_buffer -= 10;
975 p_block->p_buffer += 10;
980 assert( i_bits == 16 );
981 #ifdef WORDS_BIGENDIAN
982 memcpy( p_aout_buffer->p_buffer, p_block->p_buffer, p_block->i_buffer );
984 swab( p_block->p_buffer, p_aout_buffer->p_buffer, p_block->i_buffer );
988 static void AobExtract( block_t *p_aout_buffer,
989 block_t *p_block, unsigned i_bits, aob_group_t p_group[2] )
991 const unsigned i_channels = p_group[0].i_channels +
992 ( p_group[1].b_used ? p_group[1].i_channels : 0 );
993 uint8_t *p_out = p_aout_buffer->p_buffer;
995 while( p_block->i_buffer > 0 )
997 for( int i = 0; i < 2; i++ )
999 const aob_group_t *g = &p_group[1-i];
1000 const unsigned int i_group_size = 2 * g->i_channels * i_bits / 8;
1002 if( p_block->i_buffer < i_group_size )
1004 p_block->i_buffer = 0;
1007 for( unsigned n = 0; n < 2; n++ )
1009 for( unsigned j = 0; j < g->i_channels && g->b_used; j++ )
1011 const int i_src = n * g->i_channels + j;
1012 const int i_dst = n * i_channels + g->pi_position[j];
1016 p_out[3*i_dst+0] = p_block->p_buffer[2*i_src+0];
1017 p_out[3*i_dst+1] = p_block->p_buffer[2*i_src+1];
1018 p_out[3*i_dst+2] = p_block->p_buffer[4*g->i_channels+i_src];
1020 else if( i_bits == 20 )
1022 p_out[3*i_dst+0] = p_block->p_buffer[2*i_src+0];
1023 p_out[3*i_dst+1] = p_block->p_buffer[2*i_src+1];
1025 p_out[3*i_dst+2] = (p_block->p_buffer[4*g->i_channels+i_src] ) & 0xf0;
1027 p_out[3*i_dst+2] = (p_block->p_buffer[4*g->i_channels+i_src] << 4) & 0xf0;
1031 assert( i_bits == 16 );
1032 p_out[2*i_dst+0] = p_block->p_buffer[2*i_src+0];
1033 p_out[2*i_dst+1] = p_block->p_buffer[2*i_src+1];
1038 p_block->i_buffer -= i_group_size;
1039 p_block->p_buffer += i_group_size;
1042 p_out += (i_bits == 16 ? 2 : 3) * i_channels * 2;
1046 static void BdExtract( block_t *p_aout_buffer, block_t *p_block,
1047 unsigned i_frame_length,
1048 unsigned i_channels, unsigned i_channels_padding,
1051 if( i_channels_padding > 0 )
1053 uint8_t *p_src = p_block->p_buffer;
1054 uint8_t *p_dst = p_aout_buffer->p_buffer;
1055 while( i_frame_length > 0 )
1057 #ifdef WORDS_BIGENDIAN
1058 memcpy( p_dst, p_src, i_channels * i_bits / 8 );
1060 swab( p_dst, p_src, i_channels * i_bits / 8 );
1062 p_src += (i_channels + i_channels_padding) * i_bits / 8;
1063 p_dst += (i_channels + 0) * i_bits / 8;
1069 #ifdef WORDS_BIGENDIAN
1070 memcpy( p_aout_buffer->p_buffer, p_block->p_buffer, p_block->i_buffer );
1072 swab( p_block->p_buffer, p_aout_buffer->p_buffer, p_block->i_buffer );