Browse Source

demux: es: rework reading frame header

pull/141/head
Francois Cartegnie 4 years ago
committed by Steve Lhomme
parent
commit
e95d07a745
  1. 5
      modules/access/rtp/mpeg12.c
  2. 99
      modules/packetizer/mpegaudio.c
  3. 92
      modules/packetizer/mpegaudio.h

5
modules/access/rtp/mpeg12.c

@ -141,9 +141,8 @@ static void rtp_mpa_decode(struct vlc_rtp_pt *pt, void *data, block_t *block,
/* This RTP payload format does atypically not flag end-of-frames, so
* we have to parse the MPEG Audio frame header to find out. */
unsigned chans, conf, mode, srate, brate, samples, maxsize, layer;
int frame_size = SyncInfo(ntoh32(header), &chans, &conf, &mode, &srate,
&brate, &samples, &maxsize, &layer);
struct mpga_frameheader_s fh;
int frame_size = mpga_decode_frameheader(ntoh32(header), &fh);
/* If the frame size is unknown due to free bit rate, then we can only
* sense the completion of the frame when the next frame starts. */
if (frame_size <= 0) {

99
modules/packetizer/mpegaudio.c

@ -62,9 +62,7 @@ typedef struct
vlc_tick_t i_pts;
int i_frame_size, i_free_frame_size;
unsigned int i_channels_conf, i_chan_mode, i_channels;
unsigned int i_rate, i_max_frame_size, i_frame_length;
unsigned int i_layer, i_bit_rate;
struct mpga_frameheader_s header;
bool b_discontinuity;
} decoder_sys_t;
@ -109,29 +107,30 @@ static uint8_t *GetOutBuffer( decoder_t *p_dec, block_t **pp_out_buffer )
{
decoder_sys_t *p_sys = p_dec->p_sys;
if( p_dec->fmt_out.audio.i_rate != p_sys->i_rate ||
if( p_dec->fmt_out.audio.i_rate != p_sys->header.i_sample_rate ||
date_Get( &p_sys->end_date ) == VLC_TICK_INVALID )
{
msg_Dbg( p_dec, "MPGA channels:%d samplerate:%d bitrate:%d",
p_sys->i_channels, p_sys->i_rate, p_sys->i_bit_rate );
msg_Dbg( p_dec, "MPGA channels:%"PRIu8" samplerate:%u bitrate:%"PRIu16,
p_sys->header.i_channels, p_sys->header.i_sample_rate,
p_sys->header.i_bit_rate );
if( p_sys->end_date.i_divider_num == 0 )
date_Init( &p_sys->end_date, p_sys->i_rate, 1 );
date_Init( &p_sys->end_date, p_sys->header.i_sample_rate, 1 );
else
date_Change( &p_sys->end_date, p_sys->i_rate, 1 );
date_Change( &p_sys->end_date, p_sys->header.i_sample_rate, 1 );
date_Set( &p_sys->end_date, p_sys->i_pts );
}
p_dec->fmt_out.i_profile = p_sys->i_layer;
p_dec->fmt_out.audio.i_rate = p_sys->i_rate;
p_dec->fmt_out.audio.i_channels = p_sys->i_channels;
p_dec->fmt_out.audio.i_frame_length = p_sys->i_frame_length;
p_dec->fmt_out.audio.i_bytes_per_frame = p_sys->i_max_frame_size;
p_dec->fmt_out.i_profile = p_sys->header.i_layer;
p_dec->fmt_out.audio.i_rate = p_sys->header.i_sample_rate;
p_dec->fmt_out.audio.i_channels = p_sys->header.i_channels;
p_dec->fmt_out.audio.i_frame_length = p_sys->header.i_samples_per_frame;
p_dec->fmt_out.audio.i_bytes_per_frame = p_sys->header.i_max_frame_size;
p_dec->fmt_out.audio.i_physical_channels = p_sys->i_channels_conf;
p_dec->fmt_out.audio.i_chan_mode = p_sys->i_chan_mode;
p_dec->fmt_out.audio.i_physical_channels = p_sys->header.i_channels_conf;
p_dec->fmt_out.audio.i_chan_mode = p_sys->header.i_chan_mode;
p_dec->fmt_out.i_bitrate = p_sys->i_bit_rate * 1000;
p_dec->fmt_out.i_bitrate = p_sys->header.i_bit_rate * 1000U;
block_t *p_block = block_Alloc( p_sys->i_frame_size );
if( p_block == NULL )
@ -139,7 +138,7 @@ static uint8_t *GetOutBuffer( decoder_t *p_dec, block_t **pp_out_buffer )
p_block->i_pts = p_block->i_dts = date_Get( &p_sys->end_date );
p_block->i_length =
date_Increment( &p_sys->end_date, p_sys->i_frame_length ) - p_block->i_pts;
date_Increment( &p_sys->end_date, p_sys->header.i_samples_per_frame ) - p_block->i_pts;
*pp_out_buffer = p_block;
return p_block->p_buffer;
@ -248,16 +247,7 @@ static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
i_header = GetDWBE(p_header);
/* Check if frame is valid and get frame info */
p_sys->i_frame_size = SyncInfo( i_header,
&p_sys->i_channels,
&p_sys->i_channels_conf,
&p_sys->i_chan_mode,
&p_sys->i_rate,
&p_sys->i_bit_rate,
&p_sys->i_frame_length,
&p_sys->i_max_frame_size,
&p_sys->i_layer );
p_sys->i_frame_size = mpga_decode_frameheader( i_header, &p_sys->header );
if( p_sys->i_frame_size == -1 )
{
msg_Dbg( p_dec, "emulated startcode" );
@ -266,7 +256,7 @@ static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
break;
}
if( p_sys->i_bit_rate == 0 )
if( p_sys->header.i_bit_rate == 0 )
{
/* Free bitrate, but 99% emulated startcode :( */
if( p_sys->i_free_frame_size == MPGA_HEADER_SIZE )
@ -299,33 +289,22 @@ static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
{
/* Startcode is fine, let's try the header as an extra check */
int i_next_frame_size;
unsigned int i_next_channels, i_next_stereo_mode, i_next_channels_conf;
unsigned int i_next_rate, i_next_bit_rate;
unsigned int i_next_frame_length, i_next_max_frame_size;
unsigned int i_next_layer;
/* Build frame header */
i_header = GetDWBE(p_header);
i_next_frame_size = SyncInfo( i_header,
&i_next_channels,
&i_next_channels_conf,
&i_next_stereo_mode,
&i_next_rate,
&i_next_bit_rate,
&i_next_frame_length,
&i_next_max_frame_size,
&i_next_layer );
struct mpga_frameheader_s nextheader;
i_next_frame_size = mpga_decode_frameheader( i_header, &nextheader );
/* Free bitrate only */
if( p_sys->i_bit_rate == 0 && i_next_frame_size == -1 )
if( p_sys->header.i_bit_rate == 0 && i_next_frame_size == -1 )
{
if( (unsigned int)p_sys->i_frame_size >
p_sys->i_max_frame_size )
p_sys->header.i_max_frame_size )
{
msg_Dbg( p_dec, "frame too big %d > %d "
msg_Dbg( p_dec, "frame too big %d > %u "
"(emulated startcode ?)", p_sys->i_frame_size,
p_sys->i_max_frame_size );
p_sys->header.i_max_frame_size );
block_SkipByte( &p_sys->bytestream );
p_sys->i_state = STATE_NOSYNC;
p_sys->i_free_frame_size = MPGA_HEADER_SIZE;
@ -345,14 +324,14 @@ static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
}
/* Check info is in sync with previous one */
if( i_next_channels_conf != p_sys->i_channels_conf ||
i_next_stereo_mode != p_sys->i_chan_mode ||
i_next_rate != p_sys->i_rate ||
i_next_layer != p_sys->i_layer ||
i_next_frame_length != p_sys->i_frame_length )
if( nextheader.i_channels_conf != p_sys->header.i_channels_conf ||
nextheader.i_chan_mode != p_sys->header.i_chan_mode ||
nextheader.i_sample_rate != p_sys->header.i_sample_rate ||
nextheader.i_layer != p_sys->header.i_layer ||
nextheader.i_samples_per_frame != p_sys->header.i_samples_per_frame )
{
/* Free bitrate only */
if( p_sys->i_bit_rate == 0 )
if( p_sys->header.i_bit_rate == 0 )
{
p_sys->i_frame_size++;
break;
@ -366,9 +345,9 @@ static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
}
/* Free bitrate only */
if( p_sys->i_bit_rate == 0 )
if( p_sys->header.i_bit_rate == 0 )
{
if( i_next_bit_rate != 0 )
if( nextheader.i_bit_rate != 0 )
{
p_sys->i_frame_size++;
break;
@ -379,14 +358,14 @@ static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
else
{
/* Free bitrate only */
if( p_sys->i_bit_rate == 0 )
if( p_sys->header.i_bit_rate == 0 )
{
if( (unsigned int)p_sys->i_frame_size >
p_sys->i_max_frame_size )
p_sys->header.i_max_frame_size )
{
msg_Dbg( p_dec, "frame too big %d > %d "
msg_Dbg( p_dec, "frame too big %d > %u "
"(emulated startcode ?)", p_sys->i_frame_size,
p_sys->i_max_frame_size );
p_sys->header.i_max_frame_size );
block_SkipByte( &p_sys->bytestream );
p_sys->i_state = STATE_NOSYNC;
p_sys->i_free_frame_size = MPGA_HEADER_SIZE;
@ -426,7 +405,7 @@ static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
}
/* Free bitrate only */
if( p_sys->i_bit_rate == 0 )
if( p_sys->header.i_bit_rate == 0 )
{
p_sys->i_free_frame_size = p_sys->i_frame_size;
}
@ -504,9 +483,7 @@ static int Open( vlc_object_t *p_this )
p_sys->b_discontinuity = false;
p_sys->i_frame_size = 0;
p_sys->i_channels_conf = p_sys->i_chan_mode = p_sys->i_channels =
p_sys->i_rate = p_sys->i_max_frame_size = p_sys->i_frame_length =
p_sys->i_layer = p_sys->i_bit_rate = 0;
memset(&p_sys->header, 0, sizeof(p_sys->header));
/* Set output properties */
p_dec->fmt_out.i_codec = VLC_CODEC_MPGA;

92
modules/packetizer/mpegaudio.h

@ -2,6 +2,7 @@
* mpegaudio.h:
*****************************************************************************
* Copyright (C) 2001-2016 VLC authors and VideoLAN
* 2022 VideoLabs
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org>
@ -26,19 +27,24 @@
#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_max_frame_size;
};
/*****************************************************************************
* SyncInfo: parse MPEG audio sync info
* mpgaDecodeFrameHeader: parse MPEG audio sync info
*****************************************************************************/
static int SyncInfo(uint32_t i_header, unsigned int *restrict pi_channels,
unsigned int *restrict pi_channels_conf,
unsigned int *restrict pi_chan_mode,
unsigned int *restrict pi_sample_rate,
unsigned int *restrict pi_bit_rate,
unsigned int *restrict pi_frame_length,
unsigned int *restrict pi_max_frame_size,
unsigned int *restrict pi_layer)
static int mpga_decode_frameheader(uint32_t i_header, struct mpga_frameheader_s *h)
{
static const unsigned short ppi_bitrate[2][3][16] =
static const uint16_t ppi_bitrate[2][3][16] =
{
{
/* v1 l1 */
@ -65,7 +71,7 @@ static int SyncInfo(uint32_t i_header, unsigned int *restrict pi_channels,
}
};
static const unsigned short ppi_samplerate[2][4] = /* version 1 then 2 */
static const uint16_t ppi_samplerate[2][4] = /* version 1 then 2 */
{
{ 44100, 48000, 32000, 0 },
{ 22050, 24000, 16000, 0 }
@ -74,20 +80,20 @@ static int SyncInfo(uint32_t i_header, unsigned int *restrict pi_channels,
int i_frame_size;
bool b_mpeg_2_5 = 1 - ((i_header & 0x100000) >> 20);
int i_version = 1 - ((i_header & 0x80000) >> 19);
*pi_layer = 4 - ((i_header & 0x60000) >> 17);
unsigned i_version_index = 1 - ((i_header & 0x80000) >> 19);
h->i_layer = 4 - ((i_header & 0x60000) >> 17);
//bool b_crc = !((i_header >> 16) & 0x01);
int i_bitrate_index = (i_header & 0xf000) >> 12;
int i_samplerate_index = (i_header & 0xc00) >> 10;
unsigned i_bitrate_index = (i_header & 0xf000) >> 12;
unsigned i_samplerate_index = (i_header & 0xc00) >> 10;
bool b_padding = (i_header & 0x200) >> 9;
/* Extension */
int i_mode = (i_header & 0xc0) >> 6;
uint8_t i_mode = (i_header & 0xc0) >> 6;
/* Modeext, copyright & original */
int i_emphasis = i_header & 0x3;
uint8_t i_emphasis = i_header & 0x3;
*pi_chan_mode = 0;
h->i_chan_mode = 0;
if (*pi_layer == 4
if (h->i_layer == 4
|| i_bitrate_index == 0x0f
|| i_samplerate_index == 0x03
|| i_emphasis == 0x02)
@ -96,48 +102,48 @@ static int SyncInfo(uint32_t i_header, unsigned int *restrict pi_channels,
switch (i_mode)
{
case 2: /* dual-mono */
*pi_chan_mode = AOUT_CHANMODE_DUALMONO;
h->i_chan_mode = AOUT_CHANMODE_DUALMONO;
/* fall through */
case 0: /* stereo */
case 1: /* joint stereo */
*pi_channels = 2;
*pi_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
h->i_channels = 2;
h->i_channels_conf = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
break;
case 3: /* mono */
*pi_channels = 1;
*pi_channels_conf = AOUT_CHAN_CENTER;
h->i_channels = 1;
h->i_channels_conf = AOUT_CHAN_CENTER;
break;
}
int i_max_bit_rate = ppi_bitrate[i_version][*pi_layer-1][14];
*pi_bit_rate = ppi_bitrate[i_version][*pi_layer-1][i_bitrate_index];
*pi_sample_rate = ppi_samplerate[i_version][i_samplerate_index];
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)
*pi_sample_rate /= 2;
h->i_sample_rate /= 2;
switch (*pi_layer)
switch (h->i_layer)
{
case 1:
i_frame_size = (12000 * *pi_bit_rate / *pi_sample_rate +
i_frame_size = (12000 * h->i_bit_rate / h->i_sample_rate +
b_padding) * 4;
*pi_max_frame_size = (12000 * i_max_bit_rate /
*pi_sample_rate + 1) * 4;
*pi_frame_length = 384;
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:
i_frame_size = 144000 * *pi_bit_rate / *pi_sample_rate + b_padding;
*pi_max_frame_size = 144000 * i_max_bit_rate / *pi_sample_rate + 1;
*pi_frame_length = 1152;
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:
i_frame_size = (i_version ? 72000 : 144000) *
*pi_bit_rate / *pi_sample_rate + b_padding;
*pi_max_frame_size = (i_version ? 72000 : 144000) *
i_max_bit_rate / *pi_sample_rate + 1;
*pi_frame_length = i_version ? 576 : 1152;
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:
@ -145,8 +151,8 @@ static int SyncInfo(uint32_t i_header, unsigned int *restrict pi_channels,
}
/* Free bitrate mode can support higher bitrates */
if (*pi_bit_rate == 0)
*pi_max_frame_size *= 2;
if (h->i_bit_rate == 0)
h->i_max_frame_size *= 2;
return i_frame_size;
}

Loading…
Cancel
Save