+ *pi_channels = (i_header & 0x7) + 1;
+ switch( *pi_channels - 1 )
+ {
+ case 0:
+ *pi_original_channels = AOUT_CHAN_CENTER;
+ break;
+ case 1:
+ *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
+ break;
+ case 2:
+ /* This is unsure. */
+ *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_LFE;
+ break;
+ case 3:
+ *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
+ | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
+ break;
+ case 4:
+ /* This is unsure. */
+ *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
+ | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
+ | AOUT_CHAN_LFE;
+ break;
+ case 5:
+ *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
+ | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
+ | AOUT_CHAN_CENTER | AOUT_CHAN_LFE;
+ break;
+ case 6:
+ *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
+ | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
+ | AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT
+ | AOUT_CHAN_MIDDLERIGHT;
+ break;
+ case 7:
+ *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
+ | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
+ | AOUT_CHAN_CENTER | AOUT_CHAN_MIDDLELEFT
+ | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE;
+ break;
+ }
+
+ switch( (i_header >> 6) & 0x3 )
+ {
+ case 2:
+ *pi_bits = 24;
+ break;
+ case 1:
+ *pi_bits = 20;
+ break;
+ case 0:
+ default:
+ *pi_bits = 16;
+ break;
+ }
+
+ /* Check frame sync and drop it. */
+ if( p_header[5] != 0x80 )
+ return -1;
+ return 0;
+}
+
+static const unsigned p_aob_group1[21][6] = {
+ { AOUT_CHAN_CENTER, 0 },
+ { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 },
+ { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 },
+ { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 },
+ { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 },
+ { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 },
+ { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 },
+ { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 },
+ { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 },
+ { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 },
+ { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 },
+ { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 },
+ { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, 0 },
+ { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER, 0 },
+ { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER, 0 },
+ { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER, 0 },
+ { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER, 0 },
+ { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER, 0 },
+ { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 },
+ { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 },
+ { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 },
+};
+static const unsigned p_aob_group2[21][6] = {
+ { 0 },
+ { 0 },
+ { AOUT_CHAN_REARCENTER, 0 },
+ { AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 },
+ { AOUT_CHAN_LFE, 0 },
+ { AOUT_CHAN_LFE, AOUT_CHAN_REARCENTER, 0 },
+ { AOUT_CHAN_LFE, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 },
+ { AOUT_CHAN_CENTER, 0 },
+ { AOUT_CHAN_CENTER, AOUT_CHAN_REARCENTER, 0 },
+ { AOUT_CHAN_CENTER, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 },
+ { AOUT_CHAN_CENTER, AOUT_CHAN_LFE, 0 },
+ { AOUT_CHAN_CENTER, AOUT_CHAN_LFE, AOUT_CHAN_REARCENTER, 0 },
+ { AOUT_CHAN_CENTER, AOUT_CHAN_LFE, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 },
+ { AOUT_CHAN_REARCENTER, 0 },
+ { AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 },
+ { AOUT_CHAN_LFE, 0 },
+ { AOUT_CHAN_LFE, AOUT_CHAN_REARCENTER, 0 },
+ { AOUT_CHAN_LFE, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 },
+ { AOUT_CHAN_LFE, 0 },
+ { AOUT_CHAN_CENTER, 0 },
+ { AOUT_CHAN_CENTER, AOUT_CHAN_LFE, 0 },
+};
+
+static int AobHeader( unsigned *pi_rate,
+ unsigned *pi_channels, unsigned *pi_layout,
+ unsigned *pi_bits,
+ unsigned *pi_padding,
+ aob_group_t g[2],
+ const uint8_t *p_header )
+{
+ const unsigned i_header_size = GetWBE( &p_header[1] );
+ if( i_header_size + 3 < LPCM_AOB_HEADER_LEN )
+ return VLC_EGENERIC;
+
+ *pi_padding = 3+i_header_size - LPCM_AOB_HEADER_LEN;
+
+ const int i_index_size_g1 = (p_header[6] >> 4) & 0x0f;
+ const int i_index_size_g2 = (p_header[6] ) & 0x0f;
+ const int i_index_rate_g1 = (p_header[7] >> 4) & 0x0f;
+ const int i_index_rate_g2 = (p_header[7] ) & 0x0f;
+ const int i_assignment = p_header[9];
+
+ /* Validate */
+ if( i_index_size_g1 > 0x02 ||
+ ( i_index_size_g2 != 0x0f && i_index_size_g2 > 0x02 ) )
+ return VLC_EGENERIC;
+ if( (i_index_rate_g1 & 0x07) > 0x02 ||
+ ( i_index_rate_g2 != 0x0f && (i_index_rate_g1 & 0x07) > 0x02 ) )
+ return VLC_EGENERIC;
+ if( i_assignment > 20 )
+ return VLC_EGENERIC;
+
+ /* */
+ *pi_bits = 16 + 4 * i_index_size_g1;
+ if( i_index_rate_g1 & 0x08 )
+ *pi_rate = 44100 << (i_index_rate_g1 & 0x07);
+ else
+ *pi_rate = 48000 << (i_index_rate_g1 & 0x07);