[vlc-commits] [Git][videolan/vlc][master] 16 commits: demux: es: rework reading frame header
Steve Lhomme (@robUx4)
gitlab at videolan.org
Tue Oct 11 07:54:41 UTC 2022
Steve Lhomme pushed to branch master at VideoLAN / VLC
Commits:
e95d07a7 by Francois Cartegnie at 2022-10-11T07:29:22+00:00
demux: es: rework reading frame header
- - - - -
fa7e7858 by Francois Cartegnie at 2022-10-11T07:29:22+00:00
demux: es: store frame size in header struct
- - - - -
ad00a35e by Francois Cartegnie at 2022-10-11T07:29:22+00:00
demux: es: use frame_samples from header
- - - - -
67f1d4ea by Francois Cartegnie at 2022-10-11T07:29:22+00:00
demux: es: rework reading Xing
- - - - -
c08a96bd by Francois Cartegnie at 2022-10-11T07:29:22+00:00
demux: es: read Lavc mpga infotag
- - - - -
469fb119 by Francois Cartegnie at 2022-10-11T07:29:22+00:00
demux: es: parse VBRI
- - - - -
7ef33903 by Francois Cartegnie at 2022-10-11T07:29:22+00:00
demux: es: skip Xing header
- - - - -
6bd816c9 by Francois Cartegnie at 2022-10-11T07:29:22+00:00
demux: es: store precomputed track duration
- - - - -
7d0cc3d4 by Francois Cartegnie at 2022-10-11T07:29:22+00:00
demux: es: have mllt seek check itself
- - - - -
f4563754 by Francois Cartegnie at 2022-10-11T07:29:22+00:00
demux: es: fix few types
- - - - -
b5b92f73 by Francois Cartegnie at 2022-10-11T07:29:22+00:00
demux: es: unify seeking
- - - - -
4c80da12 by Francois Cartegnie at 2022-10-11T07:29:22+00:00
demux: es: add Xing TOC based seeking
- - - - -
b41c65b4 by Francois Cartegnie at 2022-10-11T07:29:22+00:00
demux: es: use temp var for packetizer
- - - - -
4cfdffe1 by Francois Cartegnie at 2022-10-11T07:29:22+00:00
demux: es: early set bitrate from Xing header
- - - - -
c534d5d7 by Francois Cartegnie at 2022-10-11T07:29:22+00:00
demux: es: don't change packetizer fmtout
- - - - -
9dafb994 by Francois Cartegnie at 2022-10-11T07:29:22+00:00
demux: es: set audio channel type
- - - - -
4 changed files:
- modules/access/rtp/mpeg12.c
- modules/demux/mpeg/es.c
- modules/packetizer/mpegaudio.c
- modules/packetizer/mpegaudio.h
Changes:
=====================================
modules/access/rtp/mpeg12.c
=====================================
@@ -141,12 +141,17 @@ 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;
+ if(mpga_decode_frameheader(ntoh32(header), &fh))
+ {
+ vlc_warning(log, "malformatted header");
+ block->i_flags |= BLOCK_FLAG_CORRUPTED;
+ break;
+ }
+
/* 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) {
+ if (fh.i_frame_size == 0) {
if (sys->offset >= MAX_PACKET_SIZE) {
vlc_warning(log, "oversized packet (%zu bytes)", sys->offset);
rtp_mpa_send(sys);
@@ -154,14 +159,14 @@ static void rtp_mpa_decode(struct vlc_rtp_pt *pt, void *data, block_t *block,
break;
}
- if ((size_t)frame_size == sys->offset) {
+ if (fh.i_frame_size == sys->offset) {
rtp_mpa_send(sys);
break;
}
/* If the frame size is larger than the current offset, then we need to
* wait for the next fragment. */
- if ((size_t)frame_size > sys->offset)
+ if (fh.i_frame_size > sys->offset)
break;
if (offset != 0) {
@@ -171,10 +176,10 @@ static void rtp_mpa_decode(struct vlc_rtp_pt *pt, void *data, block_t *block,
}
/* The RTP packet contains multiple small frames. */
- block_t *frame = block_Alloc(frame_size);
+ block_t *frame = block_Alloc(fh.i_frame_size);
if (likely(frame != NULL)) {
assert(block->p_next == NULL); /* Only one block to copy from */
- memcpy(frame->p_buffer, block->p_buffer, frame_size);
+ memcpy(frame->p_buffer, block->p_buffer, frame->i_buffer);
frame->i_flags = block->i_flags;
frame->i_pts = block->i_pts;
vlc_rtp_es_send(sys->es, frame);
@@ -183,8 +188,8 @@ static void rtp_mpa_decode(struct vlc_rtp_pt *pt, void *data, block_t *block,
} else
block->i_flags = BLOCK_FLAG_DISCONTINUITY;
- block->p_buffer += frame_size;
- block->i_buffer -= frame_size;
+ block->p_buffer += fh.i_frame_size;
+ block->i_buffer -= fh.i_frame_size;
block->i_pts = VLC_TICK_INVALID;
}
return;
=====================================
modules/demux/mpeg/es.c
=====================================
@@ -2,6 +2,7 @@
* es.c : Generic audio ES input module for vlc
*****************************************************************************
* Copyright (C) 2001-2008 VLC authors and VideoLAN
+ * 2022 VideoLabs
*
* Authors: Laurent Aimar <fenrir at via.ecp.fr>
* Gildas Bazin <gbazin at videolan.org>
@@ -38,6 +39,7 @@
#include "../../packetizer/a52.h"
#include "../../packetizer/dts_header.h"
+#include "../../packetizer/mpegaudio.h"
#include "../../meta_engine/ID3Tag.h"
#include "../../meta_engine/ID3Text.h"
#include "../../meta_engine/ID3Meta.h"
@@ -96,12 +98,6 @@ typedef struct
int (*pf_init)( demux_t *p_demux );
} codec_t;
-typedef struct
-{
- char psz_version[10];
- int i_lowpass;
-} lame_extra_t;
-
typedef struct
{
vlc_tick_t i_time;
@@ -127,6 +123,211 @@ typedef struct
seekpoint_t *p_seekpoint;
} chap_entry_t;
+/* Mpga specific */
+#define XING_FIELD_STREAMFRAMES (1 << 0)
+#define XING_FIELD_STREAMBYTES (1 << 1)
+#define XING_FIELD_TOC (1 << 2)
+#define XING_FIELD_QUALITY (1 << 3)
+#define XING_MIN_TAG_SIZE 42
+#define XING_TOC_COUNTBYTES 100
+#define XING_MAX_TAG_SIZE (XING_MIN_TAG_SIZE + 4 + 4 + XING_TOC_COUNTBYTES + 4 + 2)
+#define XING_SUB_ETE_NOK_OTAE XING_MIN_TAG_SIZE
+
+struct xing_info_s
+{
+ uint32_t i_frames;
+ uint32_t i_bytes;
+ uint32_t i_quality;
+ vlc_fourcc_t infotag;
+ vlc_fourcc_t encoder;
+ uint8_t rgi_toc[XING_TOC_COUNTBYTES];
+ float f_peak_signal;
+ float f_radio_replay_gain;
+ float f_audiophile_replay_gain;
+ enum
+ {
+ XING_MODE_UNKNOWN = 0,
+ XING_MODE_CBR = 1,
+ XING_MODE_ABR = 2,
+ XING_MODE_VBR1 = 3,
+ XING_MODE_VBR2 = 4,
+ XING_MODE_VBR3 = 5,
+ XING_MODE_VBR4 = 6,
+ XING_MODE_CBR_2PASS = 8,
+ XING_MODE_ABR_2PASS = 9,
+ } brmode;
+ enum
+ {
+ XING_AUDIOMODE_UNKNOWN = 0,
+ XING_AUDIOMODE_DPL = 1,
+ XING_AUDIOMODE_DPL2 = 2,
+ XING_AUDIOMODE_AMBISONICS = 3,
+ } audiomode;
+ uint8_t bitrate_avg;
+ uint16_t i_delay_samples;
+ uint16_t i_padding_samples;
+ uint32_t i_music_length;
+};
+
+static int ParseXing( const uint8_t *p_buf, size_t i_buf, struct xing_info_s *xing )
+{
+ if( i_buf < XING_MIN_TAG_SIZE )
+ return VLC_EGENERIC;
+
+ vlc_fourcc_t infotag = VLC_FOURCC(p_buf[0], p_buf[1], p_buf[2], p_buf[3]);
+
+ /* L3Enc VBR info */
+ if( infotag == VLC_FOURCC('V','B','R','I') )
+ {
+ if( GetWBE( &p_buf[4] ) != 0x0001 )
+ return VLC_EGENERIC;
+ xing->i_bytes = GetDWBE( &p_buf[10] );
+ xing->i_frames = GetDWBE( &p_buf[14] );
+ xing->infotag = infotag;
+ return VLC_SUCCESS;
+ }
+ /* Xing VBR/CBR tags */
+ else if( infotag != VLC_FOURCC('X','i','n','g') &&
+ infotag != VLC_FOURCC('I','n','f','o') )
+ {
+ return VLC_EGENERIC;
+ }
+
+ xing->infotag = infotag;
+
+ const uint32_t i_flags = GetDWBE( &p_buf[4] );
+ /* compute our variable struct size for early checks */
+ const unsigned varsz[4] = { ((i_flags & 0x01) ? 4 : 0),
+ ((i_flags & 0x02) ? 4 : 0),
+ ((i_flags & 0x04) ? XING_TOC_COUNTBYTES : 0),
+ ((i_flags & 0x08) ? 4 : 0) };
+ const unsigned i_varallsz = varsz[0] + varsz[1] + varsz[2] + varsz[3];
+ const unsigned i_tag_total = XING_MIN_TAG_SIZE + i_varallsz;
+
+ if( i_buf < i_tag_total )
+ return VLC_EGENERIC;
+
+ if( i_flags & XING_FIELD_STREAMFRAMES )
+ xing->i_frames = GetDWBE( &p_buf[8] );
+ if( i_flags & XING_FIELD_STREAMBYTES )
+ xing->i_bytes = GetDWBE( &p_buf[8 + varsz[0]] );
+ if( i_flags & XING_FIELD_TOC )
+ memcpy( xing->rgi_toc, &p_buf[8 + varsz[0] + varsz[1]], XING_TOC_COUNTBYTES );
+ if( i_flags & XING_FIELD_QUALITY )
+ xing->i_quality = GetDWBE( &p_buf[8 + varsz[0] + varsz[1] + varsz[2]] );
+
+ /* pointer past optional members */
+ const uint8_t *p_fixed = &p_buf[8 + i_varallsz];
+
+ /* Original Xing encoder header stops here */
+
+ xing->encoder = VLC_FOURCC(p_fixed[0], p_fixed[1], p_fixed[2], p_fixed[3]); /* char version[9] start */
+
+ if( xing->encoder != VLC_FOURCC('L','A','M','E') &&
+ xing->encoder != VLC_FOURCC('L','a','v','c') &&
+ xing->encoder != VLC_FOURCC('L','a','v','f') )
+ return VLC_SUCCESS;
+
+ xing->brmode = p_fixed[8] & 0x0f; /* version upper / mode lower */
+ uint32_t peak_signal = GetDWBE( &p_fixed[11] );
+ xing->f_peak_signal = peak_signal / 8388608.0; /* pow(2, 23) */
+ uint16_t gain = GetWBE( &p_fixed[15] );
+ xing->f_radio_replay_gain = (gain & 0x1FF) / /* 9bits val stored x10 */
+ ((gain & 0x200) ? -10.0 : 10.0); /* -sign bit on bit 6 */
+ gain = GetWBE( &p_fixed[17] );
+ xing->f_radio_replay_gain = (gain & 0x1FF) / /* 9bits val stored x10 */
+ ((gain & 0x200) ? -10.0 : 10.0); /* -sign bit on bit 6 */
+ /* flags @19 */
+ xing->bitrate_avg = (p_fixed[20] != 0xFF) ? p_fixed[20] : 0; /* clipped to 255, so it's unknown from there */
+ xing->i_delay_samples = (p_fixed[21] << 4) | (p_fixed[22] >> 4); /* upper 12bits */
+ xing->i_padding_samples = ((p_fixed[22] & 0x0F) << 8) | p_fixed[23]; /* lower 12bits */
+ xing->audiomode = (p_fixed[26] >> 3) & 0x07; /* over 16bits, 2b unused / 3b mode / 11b preset */
+ xing->i_music_length = GetDWBE( &p_fixed[28] );
+
+ return VLC_SUCCESS;
+}
+
+static int MpgaGetCBRSeekpoint( const struct mpga_frameheader_s *mpgah,
+ const struct xing_info_s *xing,
+ uint64_t i_seekablesize,
+ double f_pos, vlc_tick_t *pi_time, uint64_t *pi_offset )
+{
+ if( xing->infotag != 0 &&
+ xing->infotag != VLC_FOURCC('I','n','f','o') &&
+ xing->brmode != XING_MODE_CBR &&
+ xing->brmode != XING_MODE_CBR_2PASS )
+ return -1;
+
+ if( !mpgah->i_sample_rate || !mpgah->i_samples_per_frame || !mpgah->i_frame_size )
+ return -1;
+
+ uint32_t i_total_frames = xing->i_frames ? xing->i_frames
+ : i_seekablesize / mpgah->i_frame_size;
+
+ /* xing must be optional here */
+ uint32_t i_frame = i_total_frames * f_pos;
+ *pi_offset = i_frame * mpgah->i_frame_size;
+ *pi_time = vlc_tick_from_samples( i_frame * mpgah->i_samples_per_frame,
+ mpgah->i_sample_rate ) + VLC_TICK_0;
+
+ return 0;
+}
+
+static int SeekByPosUsingXingTOC( const struct mpga_frameheader_s *mpgah,
+ const struct xing_info_s *xing,double pos,
+ vlc_tick_t *pi_time, uint64_t *pi_offset )
+{
+ if( !xing->rgi_toc[XING_TOC_COUNTBYTES - 1] ||
+ !mpgah->i_sample_rate || !mpgah->i_samples_per_frame )
+ return -1;
+
+ unsigned syncentry = pos * XING_TOC_COUNTBYTES;
+ syncentry = VLC_CLIP(syncentry, 0, XING_TOC_COUNTBYTES - 1);
+ unsigned syncframe = syncentry * xing->i_frames / XING_TOC_COUNTBYTES;
+
+ *pi_time = vlc_tick_from_samples( syncframe * mpgah->i_samples_per_frame,
+ mpgah->i_sample_rate ) + VLC_TICK_0;
+ *pi_offset = xing->rgi_toc[syncentry] * xing->i_bytes / 256;
+
+ return 0;
+}
+
+static int SeekByTimeUsingXingTOC( const struct mpga_frameheader_s *mpgah,
+ const struct xing_info_s *xing,
+ vlc_tick_t *pi_time, uint64_t *pi_offset )
+{
+ if( !mpgah->i_sample_rate || !mpgah->i_samples_per_frame || !xing->i_frames ||
+ *pi_time < VLC_TICK_0 )
+ return -1;
+
+ uint32_t sample = samples_from_vlc_tick( *pi_time - VLC_TICK_0, mpgah->i_sample_rate );
+ uint64_t totalsamples = mpgah->i_samples_per_frame * (uint64_t) xing->i_frames;
+
+ return SeekByPosUsingXingTOC( mpgah, xing, (double)sample / totalsamples,
+ pi_time, pi_offset );
+}
+
+static int MpgaSeek( const struct mpga_frameheader_s *mpgah,
+ const struct xing_info_s *xing,
+ uint64_t i_seekablesize, double f_pos,
+ vlc_tick_t *pi_time, uint64_t *pi_offset )
+{
+ if( f_pos >= 0 ) /* Set Pos */
+ {
+ if( !MpgaGetCBRSeekpoint( mpgah, xing, i_seekablesize,
+ f_pos, pi_time, pi_offset ) )
+ {
+ return 0;
+ }
+ }
+
+ if( *pi_time != VLC_TICK_INVALID &&
+ !SeekByTimeUsingXingTOC( mpgah, xing, pi_time, pi_offset ) )
+ return 0;
+
+ return SeekByPosUsingXingTOC( mpgah, xing, f_pos, pi_time, pi_offset );
+}
+
typedef struct
{
codec_t codec;
@@ -140,15 +341,16 @@ typedef struct
vlc_tick_t i_pts;
vlc_tick_t i_time_offset;
- int64_t i_bytes;
+ uint64_t i_bytes;
bool b_big_endian;
bool b_estimate_bitrate;
- int i_bitrate_avg; /* extracted from Xing header */
+ unsigned i_bitrate; /* extracted from Xing header */
+ vlc_tick_t i_duration;
bool b_initial_sync_failed;
- int i_packet_size;
+ unsigned i_packet_size;
uint64_t i_stream_offset;
unsigned i_demux_flags;
@@ -156,15 +358,8 @@ typedef struct
float f_fps;
/* Mpga specific */
- struct
- {
- int i_frames;
- int i_bytes;
- int i_bitrate_avg;
- int i_frame_samples;
- lame_extra_t lame;
- bool b_lame;
- } xing;
+ struct mpga_frameheader_s mpgah;
+ struct xing_info_s xing;
float rgf_replay_gain[AUDIO_REPLAY_GAIN_MAX];
float rgf_replay_peak[AUDIO_REPLAY_GAIN_MAX];
@@ -196,7 +391,7 @@ static int ThdProbe( demux_t *p_demux, uint64_t *pi_offset );
static int MlpInit( demux_t *p_demux );
static bool Parse( demux_t *p_demux, block_t **pp_output );
-static uint64_t SeekByMlltTable( demux_t *p_demux, vlc_tick_t *pi_time );
+static int SeekByMlltTable( sync_table_t *, vlc_tick_t *, uint64_t * );
static const codec_t p_codecs[] = {
{ VLC_CODEC_MP4A, false, "mp4 audio", AacProbe, AacInit },
@@ -233,7 +428,8 @@ static int OpenCommon( demux_t *p_demux,
p_sys->b_start = true;
p_sys->i_stream_offset = i_bs_offset;
p_sys->b_estimate_bitrate = true;
- p_sys->i_bitrate_avg = 0;
+ p_sys->i_bitrate = 0;
+ p_sys->i_duration = 0;
p_sys->b_big_endian = false;
p_sys->f_fps = var_InheritFloat( p_demux, "es-fps" );
p_sys->p_packetized_data = NULL;
@@ -252,6 +448,12 @@ static int OpenCommon( demux_t *p_demux,
return VLC_EGENERIC;
}
+ if( vlc_stream_Seek( p_demux->s, p_sys->i_stream_offset ) )
+ {
+ free( p_sys );
+ return VLC_EGENERIC;
+ }
+
msg_Dbg( p_demux, "detected format %4.4s", (const char*)&p_sys->codec.i_codec );
/* Load the audio packetizer */
@@ -391,7 +593,7 @@ static int Demux( demux_t *p_demux )
}
/* Re-estimate bitrate */
if( p_sys->b_estimate_bitrate && p_sys->i_pts > VLC_TICK_FROM_MS(500) )
- p_sys->i_bitrate_avg = 8 * CLOCK_FREQ * p_sys->i_bytes
+ p_sys->i_bitrate = 8 * CLOCK_FREQ * p_sys->i_bytes
/ (p_sys->i_pts - 1);
p_sys->i_bytes += p_block_out->i_buffer;
@@ -426,19 +628,27 @@ static void Close( vlc_object_t * p_this )
/*****************************************************************************
* Time seek:
*****************************************************************************/
-static int MovetoTimePos( demux_t *p_demux, vlc_tick_t i_time, uint64_t i_pos )
+static void PostSeekCleanup( demux_sys_t *p_sys, vlc_tick_t i_time )
{
- demux_sys_t *p_sys = p_demux->p_sys;
- int i_ret = vlc_stream_Seek( p_demux->s, p_sys->i_stream_offset + i_pos );
- if( i_ret != VLC_SUCCESS )
- return i_ret;
- p_sys->i_time_offset = i_time - p_sys->i_pts;
+ /* Fix time_offset */
+ if( i_time >= 0 )
+ p_sys->i_time_offset = i_time - p_sys->i_pts;
/* And reset buffered data */
if( p_sys->p_packetized_data )
block_ChainRelease( p_sys->p_packetized_data );
p_sys->p_packetized_data = NULL;
+ /* Reset chapter if any */
p_sys->chapters.i_current = 0;
p_sys->i_demux_flags |= INPUT_UPDATE_SEEKPOINT;
+}
+
+static int MovetoTimePos( demux_t *p_demux, vlc_tick_t i_time, uint64_t i_pos )
+{
+ demux_sys_t *p_sys = p_demux->p_sys;
+ int i_ret = vlc_stream_Seek( p_demux->s, p_sys->i_stream_offset + i_pos );
+ if( i_ret != VLC_SUCCESS )
+ return i_ret;
+ PostSeekCleanup( p_sys, i_time );
return VLC_SUCCESS;
}
@@ -463,17 +673,23 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
case DEMUX_GET_LENGTH:
{
+ if( p_sys->i_duration > 0 )
+ {
+ *va_arg( args, vlc_tick_t * ) = p_sys->i_duration;
+ return VLC_SUCCESS;
+ }
+ /* compute length from bitrate */
va_list ap;
int i_ret;
va_copy ( ap, args );
i_ret = demux_vaControlHelper( p_demux->s, p_sys->i_stream_offset,
- -1, p_sys->i_bitrate_avg, 1, i_query, ap );
+ -1, p_sys->i_bitrate, 1, i_query, ap );
va_end( ap );
/* No bitrate, we can't have it precisely, but we can compute
* a raw approximation with time/position */
- if( i_ret && !p_sys->i_bitrate_avg )
+ if( i_ret && !p_sys->i_bitrate )
{
float f_pos = (double)(uint64_t)( vlc_stream_Tell( p_demux->s ) ) /
(double)(uint64_t)( stream_Size( p_demux->s ) );
@@ -493,15 +709,71 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
}
case DEMUX_SET_TIME:
- if( p_sys->mllt.p_bits )
+ case DEMUX_SET_POSITION:
+ {
+ vlc_tick_t i_time;
+ double f_pos;
+ uint64_t i_offset;
+
+ va_list ap;
+ va_copy ( ap, args ); /* don't break args for helper fallback */
+ if( i_query == DEMUX_SET_TIME )
+ {
+ i_time = va_arg(ap, vlc_tick_t);
+ f_pos = p_sys->i_duration ? i_time / (double) p_sys->i_duration : -1.0;
+ if( f_pos > 1.0 )
+ f_pos = 1.0;
+ }
+ else
+ {
+ f_pos = va_arg(ap, double);
+ i_time = p_sys->i_duration ? p_sys->i_duration * f_pos : VLC_TICK_INVALID;
+ }
+ va_end( ap );
+
+ /* Try to use ID3 table */
+ if( !SeekByMlltTable( &p_sys->mllt, &i_time, &i_offset ) )
+ return MovetoTimePos( p_demux, i_time, i_offset );
+
+ if( p_sys->codec.i_codec == VLC_CODEC_MPGA )
{
- vlc_tick_t i_time = va_arg(args, vlc_tick_t);
- uint64_t i_pos = SeekByMlltTable( p_demux, &i_time );
- return MovetoTimePos( p_demux, i_time, i_pos );
+ uint64_t streamsize;
+ if( !vlc_stream_GetSize( p_demux->s, &streamsize ) &&
+ streamsize > p_sys->i_stream_offset )
+ streamsize -= p_sys->i_stream_offset;
+ else
+ streamsize = 0;
+
+ if( !MpgaSeek( &p_sys->mpgah, &p_sys->xing,
+ streamsize, f_pos, &i_time, &i_offset ) )
+ {
+ return MovetoTimePos( p_demux, i_time, i_offset );
+ }
}
+
+ /* fallback on bitrate / file position seeking */
+ i_time = VLC_TICK_INVALID;
+ int ret = demux_vaControlHelper( p_demux->s, p_sys->i_stream_offset, -1,
+ p_sys->i_bitrate, 1, i_query, args );
+ if( ret != VLC_SUCCESS )
+ return ret; /* not much we can do */
+
+ if( p_sys->i_bitrate > 0 )
+ {
+ i_offset = vlc_stream_Tell( p_demux->s ); /* new pos */
+ i_time = VLC_TICK_0;
+ if( likely(i_offset > p_sys->i_stream_offset) )
+ {
+ i_offset -= p_sys->i_stream_offset;
+ i_time += vlc_tick_from_samples( i_offset * 8, p_sys->i_bitrate );
+ }
+ }
+ PostSeekCleanup( p_sys, i_time );
+
/* FIXME TODO: implement a high precision seek (with mp3 parsing)
* needed for multi-input */
- break;
+ return VLC_SUCCESS;
+ }
case DEMUX_GET_TITLE_INFO:
{
@@ -575,34 +847,8 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
}
}
- int ret = demux_vaControlHelper( p_demux->s, p_sys->i_stream_offset, -1,
- p_sys->i_bitrate_avg, 1, i_query, args );
- if( ret != VLC_SUCCESS )
- return ret;
-
- if( i_query == DEMUX_SET_POSITION || i_query == DEMUX_SET_TIME )
- {
- if( p_sys->i_bitrate_avg > 0 )
- {
- vlc_tick_t i_time = vlc_tick_from_samples(
- ( vlc_stream_Tell(p_demux->s) - p_sys->i_stream_offset ) * 8
- , p_sys->i_bitrate_avg );
-
- /* Fix time_offset */
- if( i_time >= 0 )
- p_sys->i_time_offset = i_time - p_sys->i_pts;
- /* And reset buffered data */
- if( p_sys->p_packetized_data )
- block_ChainRelease( p_sys->p_packetized_data );
- p_sys->p_packetized_data = NULL;
- }
-
- /* Reset chapter if any */
- p_sys->chapters.i_current = 0;
- p_sys->i_demux_flags |= INPUT_UPDATE_SEEKPOINT;
- }
-
- return VLC_SUCCESS;
+ return demux_vaControlHelper( p_demux->s, p_sys->i_stream_offset, -1,
+ p_sys->i_bitrate, 1, i_query, args );
}
/*****************************************************************************
@@ -651,33 +897,36 @@ static bool Parse( demux_t *p_demux, block_t **pp_output )
}
p_sys->b_initial_sync_failed = p_sys->b_start; /* Only try to resync once */
- while( ( p_block_out = p_sys->p_packetizer->pf_packetize( p_sys->p_packetizer, p_block_in ? &p_block_in : NULL ) ) )
+ decoder_t *p_packetizer = p_sys->p_packetizer;
+ while( ( p_block_out = p_packetizer->pf_packetize( p_packetizer, p_block_in ? &p_block_in : NULL ) ) )
{
p_sys->b_initial_sync_failed = false;
while( p_block_out )
{
if( !p_sys->p_es )
{
- p_sys->p_packetizer->fmt_out.b_packetized = true;
- p_sys->p_packetizer->fmt_out.i_id = 0;
- p_sys->p_es = es_out_Add( p_demux->out,
- &p_sys->p_packetizer->fmt_out);
-
+ es_format_t fmt;
+ es_format_Init( &fmt, p_packetizer->fmt_out.i_cat, p_packetizer->fmt_out.i_codec );
+ es_format_Copy( &fmt, &p_packetizer->fmt_out );
- /* Try the xing header */
- if( p_sys->xing.i_bytes && p_sys->xing.i_frames &&
- p_sys->xing.i_frame_samples )
+ switch( p_sys->xing.audiomode )
{
- p_sys->i_bitrate_avg = p_sys->xing.i_bytes * INT64_C(8) *
- p_sys->p_packetizer->fmt_out.audio.i_rate /
- p_sys->xing.i_frames / p_sys->xing.i_frame_samples;
-
- if( p_sys->i_bitrate_avg > 0 )
- p_sys->b_estimate_bitrate = false;
+ case XING_AUDIOMODE_AMBISONICS:
+ fmt.audio.channel_type = AUDIO_CHANNEL_TYPE_AMBISONICS;
+ break;
+ default:
+ break;
}
+
+ fmt.b_packetized = true;
+ fmt.i_id = 0;
+ p_sys->p_es = es_out_Add( p_demux->out, &fmt );
+
/* Use the bitrate as initual value */
if( p_sys->b_estimate_bitrate )
- p_sys->i_bitrate_avg = p_sys->p_packetizer->fmt_out.i_bitrate;
+ p_sys->i_bitrate = fmt.i_bitrate;
+
+ es_format_Clean( &fmt );
}
block_t *p_next = p_block_out->p_next;
@@ -896,22 +1145,6 @@ static int MpgaCheckSync( const uint8_t *p_peek )
#define MPGA_VERSION( h ) ( 1 - (((h)>>19)&0x01) )
#define MPGA_MODE(h) (((h)>> 6)&0x03)
-static int MpgaGetFrameSamples( uint32_t h )
-{
- const int i_layer = 3 - (((h)>>17)&0x03);
- switch( i_layer )
- {
- case 0:
- return 384;
- case 1:
- return 1152;
- case 2:
- return MPGA_VERSION(h) ? 576 : 1152;
- default:
- return 0;
- }
-}
-
static int MpgaProbe( demux_t *p_demux, uint64_t *pi_offset )
{
const uint16_t rgi_twocc[] = { WAVE_FORMAT_MPEG, WAVE_FORMAT_MPEGLAYER3, WAVE_FORMAT_UNKNOWN };
@@ -965,78 +1198,37 @@ static int MpgaProbe( demux_t *p_demux, uint64_t *pi_offset )
return VLC_SUCCESS;
}
-static void MpgaXingSkip( const uint8_t **pp_xing, int *pi_xing, int i_count )
-{
- if(i_count > *pi_xing )
- i_count = *pi_xing;
-
- (*pp_xing) += i_count;
- (*pi_xing) -= i_count;
-}
-
-static uint32_t MpgaXingGetDWBE( const uint8_t **pp_xing, int *pi_xing, uint32_t i_default )
-{
- if( *pi_xing < 4 )
- return i_default;
-
- uint32_t v = GetDWBE( *pp_xing );
-
- MpgaXingSkip( pp_xing, pi_xing, 4 );
-
- return v;
-}
-
-static uint16_t MpgaXingGetWBE( const uint8_t **pp_xing, int *pi_xing, uint16_t i_default )
-{
- if( *pi_xing < 2 )
- return i_default;
-
- uint16_t v = GetWBE( *pp_xing );
-
- MpgaXingSkip( pp_xing, pi_xing, 2 );
-
- return v;
-}
-
-static double MpgaXingLameConvertGain( uint16_t x )
-{
- double gain = (x & 0x1FF) / 10.0;
-
- return x & 0x200 ? -gain : gain;
-}
-
-static double MpgaXingLameConvertPeak( uint32_t x )
+static int SeekByMlltTable( sync_table_t *mllt, vlc_tick_t *pi_time, uint64_t *pi_offset )
{
- return x / 8388608.0; /* pow(2, 23) */
-}
+ if( !mllt->p_bits )
+ return -1;
-static uint64_t SeekByMlltTable( demux_t *p_demux, vlc_tick_t *pi_time )
-{
- demux_sys_t *p_sys = p_demux->p_sys;
- sync_table_ctx_t *p_cur = &p_sys->mllt.current;
+ sync_table_ctx_t *p_cur = &mllt->current;
/* reset or init context */
if( *pi_time < p_cur->i_time || !p_cur->br.p )
{
p_cur->i_time = 0;
p_cur->i_pos = 0;
- bs_init(&p_cur->br, p_sys->mllt.p_bits, p_sys->mllt.i_bits);
+ bs_init(&p_cur->br, mllt->p_bits, mllt->i_bits);
}
while(!bs_eof(&p_cur->br))
{
- const uint32_t i_bytesdev = bs_read(&p_cur->br, p_sys->mllt.i_bits_per_bytes_dev);
- const uint32_t i_msdev = bs_read(&p_cur->br, p_sys->mllt.i_bits_per_ms_dev);
+ const uint32_t i_bytesdev = bs_read(&p_cur->br, mllt->i_bits_per_bytes_dev);
+ const uint32_t i_msdev = bs_read(&p_cur->br, mllt->i_bits_per_ms_dev);
if(bs_error(&p_cur->br))
break;
- const vlc_tick_t i_deltatime = VLC_TICK_FROM_MS(p_sys->mllt.i_ms_btw_refs + i_msdev);
+ const vlc_tick_t i_deltatime = VLC_TICK_FROM_MS(mllt->i_ms_btw_refs + i_msdev);
if( p_cur->i_time + i_deltatime > *pi_time )
break;
p_cur->i_time += i_deltatime;
- p_cur->i_pos += p_sys->mllt.i_bytes_btw_refs + i_bytesdev;
+ p_cur->i_pos += mllt->i_bytes_btw_refs + i_bytesdev;
}
*pi_time = p_cur->i_time;
- return p_cur->i_pos;
+ *pi_offset = p_cur->i_pos;
+
+ return 0;
}
static int ID3TAG_Parse_Handler( uint32_t i_tag, const uint8_t *p_payload, size_t i_payload, void *p_priv )
@@ -1172,12 +1364,10 @@ static int MpgaInit( demux_t *p_demux )
return VLC_SUCCESS;
const uint32_t header = GetDWBE( p_peek );
- if( !MpgaCheckSync( p_peek ) )
+ if( !MpgaCheckSync( p_peek ) || mpga_decode_frameheader( header, &p_sys->mpgah ) )
return VLC_SUCCESS;
/* Xing header */
- const uint8_t *p_xing = p_peek;
- int i_xing = i_peek;
int i_skip;
if( MPGA_VERSION( header ) == 0 )
@@ -1185,60 +1375,60 @@ static int MpgaInit( demux_t *p_demux )
else
i_skip = MPGA_MODE( header ) != 3 ? 21 : 13;
- if( i_skip + 8 >= i_xing || memcmp( &p_xing[i_skip], "Xing", 4 ) )
+ if( i_skip >= i_peek )
return VLC_SUCCESS;
- const uint32_t i_flags = GetDWBE( &p_xing[i_skip+4] );
-
- MpgaXingSkip( &p_xing, &i_xing, i_skip + 8 );
-
- if( i_flags&0x01 )
- p_sys->xing.i_frames = MpgaXingGetDWBE( &p_xing, &i_xing, 0 );
- if( i_flags&0x02 )
- p_sys->xing.i_bytes = MpgaXingGetDWBE( &p_xing, &i_xing, 0 );
- if( i_flags&0x04 ) /* TODO Support XING TOC to improve seeking accuracy */
- MpgaXingSkip( &p_xing, &i_xing, 100 );
- if( i_flags&0x08 )
- {
- /* FIXME: doesn't return the right bitrage average, at least
- with some MP3's */
- p_sys->xing.i_bitrate_avg = MpgaXingGetDWBE( &p_xing, &i_xing, 0 );
- msg_Dbg( p_demux, "xing vbr value present (%d)",
- p_sys->xing.i_bitrate_avg );
- }
-
- if( p_sys->xing.i_frames > 0 && p_sys->xing.i_bytes > 0 )
+ struct xing_info_s *xing = &p_sys->xing;
+ if( ParseXing( &p_peek[i_skip], i_peek - i_skip, xing ) == VLC_SUCCESS )
{
- p_sys->xing.i_frame_samples = MpgaGetFrameSamples( header );
- msg_Dbg( p_demux, "xing frames&bytes value present "
- "(%d bytes, %d frames, %d samples/frame)",
- p_sys->xing.i_bytes, p_sys->xing.i_frames,
- p_sys->xing.i_frame_samples );
- }
+ const uint64_t i_total_samples = xing->i_frames * (uint64_t) p_sys->mpgah.i_samples_per_frame;
+ const uint64_t i_dropped_samples = xing->i_delay_samples + xing->i_padding_samples;
- if( i_xing >= 20 && memcmp( p_xing, "LAME", 4 ) == 0)
- {
- p_sys->xing.b_lame = true;
- lame_extra_t *p_lame = &p_sys->xing.lame;
+ if( p_sys->mpgah.i_sample_rate && i_dropped_samples < i_total_samples )
+ {
+ uint64_t i_stream_size;
+ /* We only set duration if we can't check (then compute it using bitrate/size)
+ or if we verified the file isn't truncated */
+ if( xing->i_bytes == 0 ||
+ vlc_stream_GetSize( p_demux->s, &i_stream_size ) ||
+ i_stream_size >= xing->i_bytes + p_sys->mpgah.i_frame_size )
+ {
+ p_sys->i_duration = vlc_tick_from_samples( i_total_samples - i_dropped_samples,
+ p_sys->mpgah.i_sample_rate );
+ }
+ }
- memcpy( p_lame->psz_version, p_xing, 9 );
- p_lame->psz_version[9] = '\0';
+ unsigned i_bitrate = 0;
+ if( xing->brmode == XING_MODE_ABR || xing->brmode == XING_MODE_ABR_2PASS )
+ i_bitrate = xing->bitrate_avg * 1000;
- MpgaXingSkip( &p_xing, &i_xing, 9 );
- MpgaXingSkip( &p_xing, &i_xing, 1 ); /* rev_method */
+ if( !i_bitrate && p_sys->mpgah.i_sample_rate &&
+ xing->i_bytes > p_sys->mpgah.i_frame_size )
+ {
+ unsigned d = vlc_tick_from_samples( i_total_samples, p_sys->mpgah.i_sample_rate );
+ if( d )
+ i_bitrate = (xing->i_bytes - p_sys->mpgah.i_frame_size) * 8 * CLOCK_FREQ / d;
+ }
- p_lame->i_lowpass = (*p_xing) * 100;
- MpgaXingSkip( &p_xing, &i_xing, 1 );
+ if( i_bitrate )
+ {
+ p_sys->i_bitrate = i_bitrate;
+ p_sys->b_estimate_bitrate = false;
+ }
- uint32_t peak = MpgaXingGetDWBE( &p_xing, &i_xing, 0 );
- uint16_t track = MpgaXingGetWBE( &p_xing, &i_xing, 0 );
- uint16_t album = MpgaXingGetWBE( &p_xing, &i_xing, 0 );
+ p_sys->rgf_replay_peak[AUDIO_REPLAY_GAIN_TRACK] = xing->f_peak_signal;
+ p_sys->rgf_replay_gain[AUDIO_REPLAY_GAIN_TRACK] = xing->f_radio_replay_gain;
+ p_sys->rgf_replay_gain[AUDIO_REPLAY_GAIN_ALBUM] = xing->f_audiophile_replay_gain;
- p_sys->rgf_replay_peak[AUDIO_REPLAY_GAIN_TRACK] = (float) MpgaXingLameConvertPeak( peak );
- p_sys->rgf_replay_gain[AUDIO_REPLAY_GAIN_TRACK] = (float) MpgaXingLameConvertGain( track );
- p_sys->rgf_replay_gain[AUDIO_REPLAY_GAIN_ALBUM] = (float) MpgaXingLameConvertGain( album );
+ msg_Dbg( p_demux, "Using '%4.4s' infotag"
+ "(%"PRIu32" bytes, %"PRIu32" frames, %u samples/frame)",
+ (char *) &xing->infotag,
+ xing->i_bytes, xing->i_frames,
+ p_sys->mpgah.i_samples_per_frame );
- MpgaXingSkip( &p_xing, &i_xing, 1 ); /* flags */
+ /* We'll need to skip that part for playback
+ * and avoid using it as container frame could be different rate/size */
+ p_sys->i_stream_offset += p_sys->mpgah.i_frame_size;
}
return VLC_SUCCESS;
=====================================
modules/packetizer/mpegaudio.c
=====================================
@@ -61,10 +61,8 @@ 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;
+ unsigned int i_free_frame_size;
+ struct mpga_frameheader_s header;
bool b_discontinuity;
} decoder_sys_t;
@@ -109,37 +107,38 @@ 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 );
+ block_t *p_block = block_Alloc( p_sys->header.i_frame_size );
if( p_block == NULL )
return NULL;
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,17 +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 );
-
- if( p_sys->i_frame_size == -1 )
+ if( mpga_decode_frameheader( i_header, &p_sys->header ) )
{
msg_Dbg( p_dec, "emulated startcode" );
block_SkipByte( &p_sys->bytestream );
@@ -266,7 +255,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 )
@@ -274,7 +263,7 @@ static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
msg_Dbg( p_dec, "free bitrate mode");
}
/* The -1 below is to account for the frame padding */
- p_sys->i_frame_size = p_sys->i_free_frame_size - 1;
+ p_sys->header.i_frame_size = p_sys->i_free_frame_size - 1;
}
p_sys->i_state = STATE_NEXT_SYNC;
@@ -283,7 +272,7 @@ static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
case STATE_NEXT_SYNC:
/* Check if next expected frame contains the sync word */
if( block_PeekOffsetBytes( &p_sys->bytestream,
- p_sys->i_frame_size, p_header,
+ p_sys->header.i_frame_size, p_header,
MAD_BUFFER_GUARD ) != VLC_SUCCESS )
{
if( p_block == NULL ) /* drain */
@@ -298,63 +287,51 @@ static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
if( p_header[0] == 0xff && (p_header[1] & 0xe0) == 0xe0 )
{
/* 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 );
-
- /* Free bitrate only */
- if( p_sys->i_bit_rate == 0 && i_next_frame_size == -1 )
+ struct mpga_frameheader_s nextheader;
+ if(mpga_decode_frameheader( i_header, &nextheader ))
{
- if( (unsigned int)p_sys->i_frame_size >
- p_sys->i_max_frame_size )
+ /* Free bitrate only */
+ if( p_sys->header.i_bit_rate == 0 )
+ {
+ if( p_sys->header.i_frame_size > p_sys->header.i_max_frame_size )
+ {
+ msg_Dbg( p_dec, "frame too big %u > %u "
+ "(emulated startcode ?)",
+ p_sys->header.i_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;
+ }
+ else
+ {
+ p_sys->header.i_frame_size++;
+ }
+ }
+ else
{
- msg_Dbg( p_dec, "frame too big %d > %d "
- "(emulated startcode ?)", p_sys->i_frame_size,
- p_sys->i_max_frame_size );
+ msg_Dbg( p_dec, "emulated startcode on next frame" );
block_SkipByte( &p_sys->bytestream );
p_sys->i_state = STATE_NOSYNC;
- p_sys->i_free_frame_size = MPGA_HEADER_SIZE;
- break;
}
-
- p_sys->i_frame_size++;
- break;
- }
-
- if( i_next_frame_size == -1 )
- {
- msg_Dbg( p_dec, "emulated startcode on next frame" );
- block_SkipByte( &p_sys->bytestream );
- p_sys->i_state = STATE_NOSYNC;
break;
}
/* 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++;
+ p_sys->header.i_frame_size++;
break;
}
@@ -366,11 +343,11 @@ 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++;
+ p_sys->header.i_frame_size++;
break;
}
}
@@ -379,21 +356,21 @@ 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 )
+ if( p_sys->header.i_frame_size > p_sys->header.i_max_frame_size )
{
- msg_Dbg( p_dec, "frame too big %d > %d "
- "(emulated startcode ?)", p_sys->i_frame_size,
- p_sys->i_max_frame_size );
+ msg_Dbg( p_dec, "frame too big %u > %u "
+ "(emulated startcode ?)",
+ p_sys->header.i_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;
break;
}
- p_sys->i_frame_size++;
+ p_sys->header.i_frame_size++;
break;
}
@@ -411,7 +388,7 @@ static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
/* Make sure we have enough data.
* (Not useful if we went through NEXT_SYNC) */
if( block_WaitBytes( &p_sys->bytestream,
- p_sys->i_frame_size ) != VLC_SUCCESS )
+ p_sys->header.i_frame_size ) != VLC_SUCCESS )
{
/* Need more data */
return NULL;
@@ -426,14 +403,16 @@ 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;
+ p_sys->i_free_frame_size = p_sys->header.i_frame_size;
}
/* Copy the whole frame into the buffer. */
- if (block_GetBytes( &p_sys->bytestream,
- p_buf, __MIN( (unsigned)p_sys->i_frame_size, p_out_buffer->i_buffer ) )) {
+ if ( block_GetBytes( &p_sys->bytestream, p_buf,
+ __MIN( p_sys->header.i_frame_size,
+ p_out_buffer->i_buffer ) ) )
+ {
block_Release(p_out_buffer);
return NULL;
}
@@ -502,11 +481,8 @@ static int Open( vlc_object_t *p_this )
block_BytestreamInit( &p_sys->bytestream );
p_sys->i_pts = VLC_TICK_INVALID;
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;
=====================================
modules/packetizer/mpegaudio.h
=====================================
@@ -2,6 +2,7 @@
* mpegaudio.h:
*****************************************************************************
* Copyright (C) 2001-2016 VLC authors and VideoLAN
+ * 2022 VideoLabs
*
* Authors: Laurent Aimar <fenrir at via.ecp.fr>
* Eric Petit <titer at videolan.org>
@@ -26,19 +27,26 @@
#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;
+};
+
/*****************************************************************************
- * SyncInfo: parse MPEG audio sync info
+ * mpgaDecodeFrameHeader: parse MPEG audio sync info
+ * returns 0 on success, -1 on failure
*****************************************************************************/
-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,29 +73,27 @@ 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 }
};
- 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 +
+ h->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;
+ 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:
- 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;
+ 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:
@@ -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;
+ return 0;
}
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/cbbd548c6529a50ca8738dcff118cabd7dd133e7...9dafb994caf9e3a21a0afa34e68bf3f13130ab5a
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/cbbd548c6529a50ca8738dcff118cabd7dd133e7...9dafb994caf9e3a21a0afa34e68bf3f13130ab5a
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance
More information about the vlc-commits
mailing list