Commit 34abc32f authored by Francois Cartegnie's avatar Francois Cartegnie

packetizer: flac: process end of streambuffer (fix #10340)

parent f298d137
...@@ -507,12 +507,11 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block) ...@@ -507,12 +507,11 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block)
{ {
decoder_sys_t *p_sys = p_dec->p_sys; decoder_sys_t *p_sys = p_dec->p_sys;
uint8_t p_header[MAX_FLAC_HEADER_SIZE]; uint8_t p_header[MAX_FLAC_HEADER_SIZE];
block_t *out; block_t *out, *in = NULL;
if (!pp_block || !*pp_block) if ( pp_block && *pp_block)
return NULL; {
in = *pp_block;
block_t *in = *pp_block;
if (in->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED)) { if (in->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED)) {
if (in->i_flags&BLOCK_FLAG_CORRUPTED) { if (in->i_flags&BLOCK_FLAG_CORRUPTED) {
...@@ -522,6 +521,7 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block) ...@@ -522,6 +521,7 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block)
block_Release(*pp_block); block_Release(*pp_block);
return NULL; return NULL;
} }
}
if (!p_sys->b_stream_info) if (!p_sys->b_stream_info)
ProcessHeader(p_dec); ProcessHeader(p_dec);
...@@ -534,7 +534,7 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block) ...@@ -534,7 +534,7 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block)
if ( p_sys->i_pts <= VLC_TS_INVALID ) if ( p_sys->i_pts <= VLC_TS_INVALID )
{ {
if ( in->i_pts == p_sys->i_pts ) if ( in && in->i_pts == p_sys->i_pts )
{ {
/* We've just started the stream, wait for the first PTS. */ /* We've just started the stream, wait for the first PTS. */
block_Release(in); block_Release(in);
...@@ -543,6 +543,7 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block) ...@@ -543,6 +543,7 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block)
p_sys->i_rate = p_dec->fmt_out.audio.i_rate; p_sys->i_rate = p_dec->fmt_out.audio.i_rate;
} }
if ( in )
block_BytestreamPush(&p_sys->bytestream, in); block_BytestreamPush(&p_sys->bytestream, in);
while (1) switch (p_sys->i_state) { while (1) switch (p_sys->i_state) {
...@@ -596,9 +597,6 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block) ...@@ -596,9 +597,6 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block)
* it would appear in data, so we also need to check next frame header CRC * it would appear in data, so we also need to check next frame header CRC
*/ */
case STATE_NEXT_SYNC: case STATE_NEXT_SYNC:
/* TODO: If pp_block == NULL, flush the buffer without checking the
* next sync word */
{ {
/* Calculate the initial CRC for the minimal frame size, /* Calculate the initial CRC for the minimal frame size,
* We'll update it as we look for the next start code. */ * We'll update it as we look for the next start code. */
...@@ -616,8 +614,6 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block) ...@@ -616,8 +614,6 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block)
crc = flac_crc16(crc, buf[i]); crc = flac_crc16(crc, buf[i]);
free(buf); free(buf);
p_sys->crc = crc; p_sys->crc = crc;
}
/* Check if next expected frame contains the sync word */ /* Check if next expected frame contains the sync word */
while (!block_PeekOffsetBytes(&p_sys->bytestream, p_sys->i_frame_size, while (!block_PeekOffsetBytes(&p_sys->bytestream, p_sys->i_frame_size,
...@@ -663,10 +659,48 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block) ...@@ -663,10 +659,48 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block)
p_sys->i_state = STATE_NOSYNC; p_sys->i_state = STATE_NOSYNC;
return NULL; return NULL;
} }
if ( !in )
{
/* There's no following frame, so we need to read current
* data until the frame footer matches (crc16) == stream crc.
* In the worst case, if crc might be a false positive and data
* will be truncated. */
uint8_t crc_bytes[2];
if ( !block_PeekOffsetBytes(&p_sys->bytestream,
p_sys->i_frame_size - 2, crc_bytes, 2) )
{
while ( true )
{
/* Read the frame CRC */
uint16_t stream_crc = (crc_bytes[0] << 8) | crc_bytes[1];
/* Calculate the frame CRC: remove the last 2 bytes */
uint16_t crc = flac_crc16_undo(p_sys->crc, crc_bytes[1]);
crc = flac_crc16_undo(crc, crc_bytes[0]);
if (stream_crc == crc)
{
p_sys->i_state = STATE_SEND_DATA;
break;
}
p_sys->i_frame_size++;
if ( block_PeekOffsetBytes(&p_sys->bytestream,
p_sys->i_frame_size - 2, crc_bytes, 2) )
break;
/* Update current crc */
p_sys->crc = flac_crc16(p_sys->crc, crc_bytes[1]);
}
}
if ( p_sys->i_state != STATE_SEND_DATA )
return NULL;
}
else
{
/* Need more data */ /* Need more data */
return NULL; return NULL;
} }
}
}
case STATE_SEND_DATA: case STATE_SEND_DATA:
out = block_Alloc(p_sys->i_frame_size); out = block_Alloc(p_sys->i_frame_size);
...@@ -681,7 +715,10 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block) ...@@ -681,7 +715,10 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block)
pi_channels_maps[p_sys->stream_info.channels]; pi_channels_maps[p_sys->stream_info.channels];
/* So p_block doesn't get re-added several times */ /* So p_block doesn't get re-added several times */
if ( in )
*pp_block = block_BytestreamPop(&p_sys->bytestream); *pp_block = block_BytestreamPop(&p_sys->bytestream);
else
block_BytestreamFlush(&p_sys->bytestream);
p_sys->i_state = STATE_NOSYNC; p_sys->i_state = STATE_NOSYNC;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment