[vlc-commits] [Git][videolan/vlc][3.0.x] 7 commits: packetizer: flac: don't send invalid frame on drain
Jean-Baptiste Kempf (@jbk)
gitlab at videolan.org
Mon Aug 15 10:56:43 UTC 2022
Jean-Baptiste Kempf pushed to branch 3.0.x at VideoLAN / VLC
Commits:
a57c3a84 by Francois Cartegnie at 2022-08-11T17:48:54+02:00
packetizer: flac: don't send invalid frame on drain
(cherry picked from commit 599757d9e43df3b2c95106aff77e595ad0d9cfe9)
- - - - -
7628565d by Francois Cartegnie at 2022-08-11T17:58:10+02:00
packetizer: flac: fix potential endless loop on drain
(cherry picked from commit d231265080bead89e3b6e031d3a85c37eb2b01ec)
- - - - -
89fa35ef by Francois Cartegnie at 2022-08-11T17:58:18+02:00
packetizer: flac: add comments
(cherry picked from commit 6aeaeb610dc54af85c46a68159af2043feeae33d)
- - - - -
2b707aeb by Francois Cartegnie at 2022-08-11T17:59:59+02:00
packetizer: flac: fix fixed blocksize streams last pts
(cherry picked from commit 1cd8422afd1de99b80951817e89ad7271c8364e5)
- - - - -
afa25a99 by Francois Cartegnie at 2022-08-11T18:01:22+02:00
packetizer: flac: remove useless frame_size
(cherry picked from commit 54ffcdec205870e09d3a8cabf6c03e831fc95406)
- - - - -
affe9ad5 by Francois Cartegnie at 2022-08-11T18:04:20+02:00
packetizer: flac: move frame check outside reader
(cherry picked from commit 1c03970b91ac9fd9f75d144f9e301c7131445910)
- - - - -
07cd30a1 by Francois Cartegnie at 2022-08-11T18:04:21+02:00
packetizer: flac: do not check min frame size for fixed block
cannot pass on truncated end
(cherry picked from commit 1db4d294ca8185e5a9e25d823c40677831d9f538)
- - - - -
2 changed files:
- modules/packetizer/flac.c
- modules/packetizer/flac.h
Changes:
=====================================
modules/packetizer/flac.c
=====================================
@@ -76,7 +76,6 @@ struct decoder_sys_t
date_t pts;
struct flac_header_info headerinfo;
- size_t i_frame_size;
size_t i_last_frame_size;
uint16_t crc;
size_t i_buf;
@@ -348,6 +347,7 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block)
p_sys->i_state = STATE_SYNC;
}
+ /* First Sync is now on bytestream head, offset == 0 */
block_SkipBytes(&p_sys->bytestream, p_sys->i_offset);
block_BytestreamFlush(&p_sys->bytestream);
p_sys->i_offset = 0;
@@ -364,15 +364,18 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block)
/* fallthrough */
case STATE_HEADER:
+ {
/* Get FLAC frame header (MAX_FLAC_HEADER_SIZE bytes) */
if (block_PeekBytes(&p_sys->bytestream, p_header, FLAC_HEADER_SIZE_MAX))
return NULL; /* Need more data */
/* Check if frame is valid and get frame info */
- int i_ret = FLAC_ParseSyncInfo(p_header, FLAC_HEADER_SIZE_MAX,
- p_sys->b_stream_info ? &p_sys->stream_info : NULL,
- flac_crc8, &p_sys->headerinfo);
- if (!i_ret) {
+ const struct flac_stream_info *streaminfo =
+ p_sys->b_stream_info ? &p_sys->stream_info : NULL;
+ struct flac_header_info headerinfo;
+ int i_ret = FLAC_ParseSyncInfo(p_header, FLAC_HEADER_SIZE_MAX, streaminfo,
+ flac_crc8, &headerinfo);
+ if (!i_ret || !FLAC_CheckFrameInfo(streaminfo, &headerinfo)) {
msg_Dbg(p_dec, "emulated sync word");
block_SkipByte(&p_sys->bytestream);
p_sys->i_offset = 0;
@@ -380,9 +383,9 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block)
break;
}
+ p_sys->headerinfo = headerinfo;
p_sys->i_state = STATE_NEXT_SYNC;
- p_sys->i_offset = 1;
- p_sys->i_frame_size = 0;
+ p_sys->i_offset = FLAC_FRAME_SIZE_MIN;
p_sys->crc = 0;
/* We have to read until next frame sync code to compute current frame size
@@ -390,18 +393,24 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block)
* The confusing part below is that sync code needs to be verified in case
* it would appear in data, so we also need to check next frame header CRC
*/
+ }
/* fallthrough */
case STATE_NEXT_SYNC:
{
+ /* First Sync is on bytestream head, offset will be the position
+ * of the next sync code candidate */
if(block_FindStartcodeFromOffset(&p_sys->bytestream, &p_sys->i_offset,
NULL, 2,
FLACStartcodeHelper,
FLACStartcodeMatcher) != VLC_SUCCESS)
{
- if( pp_block == NULL ) /* EOF/Drain */
+ size_t i_remain = block_BytestreamRemaining( &p_sys->bytestream );
+ if( pp_block == NULL && i_remain > FLAC_FRAME_SIZE_MIN ) /* EOF/Drain */
{
- p_sys->i_offset = block_BytestreamRemaining( &p_sys->bytestream );
+ /* There is no other synccode in the bytestream,
+ * we assume the end of our flac frame is end of bytestream */
+ p_sys->i_offset = i_remain;
p_sys->i_state = STATE_GET_DATA;
continue;
}
@@ -414,12 +423,14 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block)
nextheader, FLAC_HEADER_SIZE_MAX))
return NULL; /* Need more data */
+ const struct flac_stream_info *streaminfo =
+ p_sys->b_stream_info ? &p_sys->stream_info : NULL;
struct flac_header_info dummy;
/* Check if frame is valid and get frame info */
- if(FLAC_ParseSyncInfo(nextheader, FLAC_HEADER_SIZE_MAX,
- p_sys->b_stream_info ? &p_sys->stream_info : NULL,
- NULL, &dummy) == 0)
+ if(!FLAC_ParseSyncInfo(nextheader, FLAC_HEADER_SIZE_MAX, streaminfo, NULL, &dummy)||
+ !FLAC_CheckFrameInfo(streaminfo, &dummy))
{
+ /* Keep trying to find next sync point in bytestream */
p_sys->i_offset++;
continue;
}
@@ -429,9 +440,11 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block)
}
case STATE_GET_DATA:
- if( p_sys->i_offset < FLAC_FRAME_SIZE_MIN ||
- ( p_sys->b_stream_info &&
- p_sys->stream_info.min_framesize > p_sys->i_offset ) )
+ /* i_offset is the next sync point candidate
+ * our frame_size is the offset from the first sync */
+ if( pp_block != NULL &&
+ p_sys->b_stream_info &&
+ p_sys->stream_info.min_framesize > p_sys->i_offset )
{
p_sys->i_offset += 1;
p_sys->i_state = STATE_NEXT_SYNC;
@@ -442,9 +455,11 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block)
p_sys->stream_info.max_framesize < p_sys->i_offset )
{
/* Something went wrong, truncate stream head and restart */
+ msg_Warn(p_dec, "discarding bytes as we're over framesize %u, %zu",
+ p_sys->stream_info.max_framesize,
+ p_sys->i_offset);
block_SkipBytes( &p_sys->bytestream, FLAC_HEADER_SIZE_MAX + 2 );
block_BytestreamFlush( &p_sys->bytestream );
- p_sys->i_frame_size = 0;
p_sys->crc = 0;
p_sys->i_offset = 0;
p_sys->i_state = STATE_NOSYNC;
@@ -468,17 +483,13 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block)
return NULL;
}
- /* Copy from previous sync point (frame_size) up to to current (offset) */
- block_PeekOffsetBytes( &p_sys->bytestream, p_sys->i_frame_size,
- &p_sys->p_buf[p_sys->i_frame_size],
- p_sys->i_offset - p_sys->i_frame_size );
+ /* Copy from previous sync point up to to current (offset) */
+ block_PeekOffsetBytes( &p_sys->bytestream, 0, p_sys->p_buf, p_sys->i_offset );
/* update crc to include this data chunk */
- for( size_t i = p_sys->i_frame_size; i < p_sys->i_offset - 2; i++ )
+ for( size_t i = 0; i < p_sys->i_offset - 2; i++ )
p_sys->crc = flac_crc16( p_sys->crc, p_sys->p_buf[i] );
- p_sys->i_frame_size = p_sys->i_offset;
-
uint16_t stream_crc = GetWBE(&p_sys->p_buf[p_sys->i_offset - 2]);
if( stream_crc != p_sys->crc )
{
@@ -493,10 +504,13 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block)
p_sys->i_state = STATE_SEND_DATA;
+ /* frame size between the two sync codes is now known */
+ p_sys->i_last_frame_size = p_sys->i_offset;
+ p_sys->i_buf = p_sys->i_offset;
+
/* clean */
block_SkipBytes( &p_sys->bytestream, p_sys->i_offset );
block_BytestreamFlush( &p_sys->bytestream );
- p_sys->i_last_frame_size = p_sys->i_frame_size;
p_sys->i_offset = 0;
p_sys->crc = 0;
@@ -521,7 +535,7 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block)
p_sys->bytestream.p_block->i_pts = VLC_TS_INVALID;
}
- out = block_heap_Alloc( p_sys->p_buf, p_sys->i_frame_size );
+ out = block_heap_Alloc( p_sys->p_buf, p_sys->i_buf );
if( out )
{
out->i_dts = out->i_pts = date_Get( &p_sys->pts );
@@ -541,7 +555,6 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block)
p_sys->i_buf = 0;
p_sys->p_buf = NULL;
- p_sys->i_frame_size = 0;
p_sys->i_offset = 0;
p_sys->i_state = STATE_NOSYNC;
@@ -573,7 +586,6 @@ static int Open(vlc_object_t *p_this)
p_sys->i_offset = 0;
p_sys->b_stream_info = false;
p_sys->i_last_frame_size = FLAC_FRAME_SIZE_MIN;
- p_sys->i_frame_size = 0;
p_sys->headerinfo.i_pts = VLC_TS_INVALID;
p_sys->i_buf = 0;
p_sys->p_buf = NULL;
=====================================
modules/packetizer/flac.h
=====================================
@@ -115,6 +115,24 @@ static inline int64_t read_utf8(const uint8_t *p_buf, unsigned i_buf, int *pi_re
return i_result;
}
+static inline int FLAC_CheckFrameInfo(const struct flac_stream_info *stream_info,
+ const struct flac_header_info *h)
+{
+ /* Sanity check using stream info header when possible */
+ if (stream_info)
+ {
+ if ((stream_info->min_blocksize != stream_info->max_blocksize &&
+ h->i_frame_length < stream_info->min_blocksize) ||
+ h->i_frame_length > stream_info->max_blocksize)
+ return 0;
+ if (h->i_bits_per_sample != stream_info->bits_per_sample)
+ return 0;
+ if (h->i_rate != stream_info->sample_rate)
+ return 0;
+ }
+ return 1;
+}
+
/*****************************************************************************
* FLAC_ParseSyncInfo: parse FLAC sync info
* - stream_info can be NULL
@@ -268,20 +286,12 @@ static inline int FLAC_ParseSyncInfo(const uint8_t *p_buf, unsigned i_buf,
pf_crc8(p_buf, i_header) != p_buf[i_header])
return 0;
- /* Sanity check using stream info header when possible */
- if (stream_info) {
- if (blocksize < stream_info->min_blocksize ||
- blocksize > stream_info->max_blocksize)
- return 0;
- if ((unsigned)bits_per_sample != stream_info->bits_per_sample)
- return 0;
- if (samplerate != stream_info->sample_rate)
- return 0;
- }
-
/* Compute from frame absolute time */
if ( (p_buf[1] & 0x01) == 0 ) /* Fixed blocksize stream / Frames */
- h->i_pts = VLC_TS_0 + CLOCK_FREQ * blocksize * i_fsnumber / samplerate;
+ {
+ const unsigned fixedblocksize = stream_info ? stream_info->min_blocksize : blocksize;
+ h->i_pts = VLC_TS_0 + CLOCK_FREQ * fixedblocksize * i_fsnumber / samplerate;
+ }
else /* Variable blocksize stream / Samples */
h->i_pts = VLC_TS_0 + CLOCK_FREQ * i_fsnumber / samplerate;
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/5d8eed501f537b29a7f9e3f9490c7215b4df36e4...07cd30a1cae34560e8d39be318847669c7306573
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/5d8eed501f537b29a7f9e3f9490c7215b4df36e4...07cd30a1cae34560e8d39be318847669c7306573
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