You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
158 lines
5.4 KiB
158 lines
5.4 KiB
/*****************************************************************************
|
|
* mpegaudio.h:
|
|
*****************************************************************************
|
|
* Copyright (C) 2001-2016 VLC authors and VideoLAN
|
|
* 2022 VideoLabs
|
|
*
|
|
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
|
|
* Eric Petit <titer@videolan.org>
|
|
* Christophe Massiot <massiot@via.ecp.fr>
|
|
* Gildas Bazin <gbazin@videolan.org>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation; either version 2.1 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
|
|
*****************************************************************************/
|
|
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
|
|
struct mpga_frameheader_s
|
|
{
|
|
uint8_t i_layer;
|
|
uint8_t i_channels;
|
|
uint16_t i_channels_conf;
|
|
uint16_t i_chan_mode;
|
|
uint16_t i_bit_rate;
|
|
uint16_t i_sample_rate;
|
|
uint16_t i_samples_per_frame;
|
|
unsigned int i_frame_size;
|
|
unsigned int i_max_frame_size;
|
|
};
|
|
|
|
/*****************************************************************************
|
|
* mpgaDecodeFrameHeader: parse MPEG audio sync info
|
|
* returns 0 on success, -1 on failure
|
|
*****************************************************************************/
|
|
static int mpga_decode_frameheader(uint32_t i_header, struct mpga_frameheader_s *h)
|
|
{
|
|
static const uint16_t ppi_bitrate[2][3][16] =
|
|
{
|
|
{
|
|
/* v1 l1 */
|
|
{ 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384,
|
|
416, 448, 0},
|
|
/* v1 l2 */
|
|
{ 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256,
|
|
320, 384, 0},
|
|
/* v1 l3 */
|
|
{ 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224,
|
|
256, 320, 0}
|
|
},
|
|
|
|
{
|
|
/* v2 l1 */
|
|
{ 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192,
|
|
224, 256, 0},
|
|
/* v2 l2 */
|
|
{ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128,
|
|
144, 160, 0},
|
|
/* v2 l3 */
|
|
{ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128,
|
|
144, 160, 0}
|
|
}
|
|
};
|
|
|
|
static const uint16_t ppi_samplerate[2][4] = /* version 1 then 2 */
|
|
{
|
|
{ 44100, 48000, 32000, 0 },
|
|
{ 22050, 24000, 16000, 0 }
|
|
};
|
|
|
|
bool b_mpeg_2_5 = 1 - ((i_header & 0x100000) >> 20);
|
|
unsigned i_version_index = 1 - ((i_header & 0x80000) >> 19);
|
|
h->i_layer = 4 - ((i_header & 0x60000) >> 17);
|
|
//bool b_crc = !((i_header >> 16) & 0x01);
|
|
unsigned i_bitrate_index = (i_header & 0xf000) >> 12;
|
|
unsigned i_samplerate_index = (i_header & 0xc00) >> 10;
|
|
bool b_padding = (i_header & 0x200) >> 9;
|
|
/* Extension */
|
|
uint8_t i_mode = (i_header & 0xc0) >> 6;
|
|
/* Modeext, copyright & original */
|
|
uint8_t i_emphasis = i_header & 0x3;
|
|
|
|
h->i_chan_mode = 0;
|
|
|
|
if (h->i_layer == 4
|
|
|| i_bitrate_index == 0x0f
|
|
|| i_samplerate_index == 0x03
|
|
|| i_emphasis == 0x02)
|
|
return -1;
|
|
|
|
switch (i_mode)
|
|
{
|
|
case 2: /* dual-mono */
|
|
h->i_chan_mode = AOUT_CHANMODE_DUALMONO;
|
|
/* fall through */
|
|
case 0: /* stereo */
|
|
case 1: /* joint stereo */
|
|
h->i_channels = 2;
|
|
h->i_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
|
|
break;
|
|
case 3: /* mono */
|
|
h->i_channels = 1;
|
|
h->i_channels_conf = AOUT_CHAN_CENTER;
|
|
break;
|
|
}
|
|
|
|
uint16_t i_max_bit_rate = ppi_bitrate[i_version_index][h->i_layer-1][14];
|
|
h->i_bit_rate = ppi_bitrate[i_version_index][h->i_layer-1][i_bitrate_index];
|
|
h->i_sample_rate = ppi_samplerate[i_version_index][i_samplerate_index];
|
|
|
|
if (b_mpeg_2_5)
|
|
h->i_sample_rate /= 2;
|
|
|
|
switch (h->i_layer)
|
|
{
|
|
case 1:
|
|
h->i_frame_size = (12000 * h->i_bit_rate / h->i_sample_rate +
|
|
b_padding) * 4;
|
|
h->i_max_frame_size = (12000 * i_max_bit_rate /
|
|
h->i_sample_rate + 1) * 4;
|
|
h->i_samples_per_frame = 384;
|
|
break;
|
|
|
|
case 2:
|
|
h->i_frame_size = 144000 * h->i_bit_rate / h->i_sample_rate + b_padding;
|
|
h->i_max_frame_size = 144000 * i_max_bit_rate / h->i_sample_rate + 1;
|
|
h->i_samples_per_frame = 1152;
|
|
break;
|
|
|
|
case 3:
|
|
h->i_frame_size = (i_version_index ? 72000 : 144000) *
|
|
h->i_bit_rate / h->i_sample_rate + b_padding;
|
|
h->i_max_frame_size = (i_version_index ? 72000 : 144000) *
|
|
i_max_bit_rate / h->i_sample_rate + 1;
|
|
h->i_samples_per_frame = i_version_index ? 576 : 1152;
|
|
break;
|
|
|
|
default:
|
|
vlc_assert_unreachable();
|
|
}
|
|
|
|
/* Free bitrate mode can support higher bitrates */
|
|
if (h->i_bit_rate == 0)
|
|
h->i_max_frame_size *= 2;
|
|
|
|
return 0;
|
|
}
|
|
|