[vlc-commits] packetizer: flac: process end of streambuffer (fix #10340)

Francois Cartegnie git at videolan.org
Fri Jan 10 15:31:36 CET 2014


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Fri Jan 10 15:13:10 2014 +0100| [34abc32f966699536c14e922995389921afb1d61] | committer: Francois Cartegnie

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

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=34abc32f966699536c14e922995389921afb1d61
---

 modules/packetizer/flac.c |   81 +++++++++++++++++++++++++++++++++------------
 1 file changed, 59 insertions(+), 22 deletions(-)

diff --git a/modules/packetizer/flac.c b/modules/packetizer/flac.c
index f9e3de5..5e8a582 100644
--- a/modules/packetizer/flac.c
+++ b/modules/packetizer/flac.c
@@ -507,20 +507,20 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block)
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
     uint8_t p_header[MAX_FLAC_HEADER_SIZE];
-    block_t *out;
+    block_t *out, *in = NULL;
 
-    if (!pp_block || !*pp_block)
-        return NULL;
-
-    block_t *in = *pp_block;
+    if ( pp_block && *pp_block)
+    {
+        in = *pp_block;
 
-    if (in->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED)) {
-        if (in->i_flags&BLOCK_FLAG_CORRUPTED) {
-            p_sys->i_state = STATE_NOSYNC;
-            block_BytestreamEmpty(&p_sys->bytestream);
+        if (in->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED)) {
+            if (in->i_flags&BLOCK_FLAG_CORRUPTED) {
+                p_sys->i_state = STATE_NOSYNC;
+                block_BytestreamEmpty(&p_sys->bytestream);
+            }
+            block_Release(*pp_block);
+            return NULL;
         }
-        block_Release(*pp_block);
-        return NULL;
     }
 
     if (!p_sys->b_stream_info)
@@ -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 ( 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. */
             block_Release(in);
@@ -543,7 +543,8 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block)
         p_sys->i_rate = p_dec->fmt_out.audio.i_rate;
     }
 
-    block_BytestreamPush(&p_sys->bytestream, in);
+    if ( in )
+        block_BytestreamPush(&p_sys->bytestream, in);
 
     while (1) switch (p_sys->i_state) {
     case STATE_NOSYNC:
@@ -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
          */
     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,
          * 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)
             crc = flac_crc16(crc, buf[i]);
         free(buf);
         p_sys->crc = crc;
-    }
-
 
         /* Check if next expected frame contains the sync word */
         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)
                 p_sys->i_state = STATE_NOSYNC;
                 return NULL;
             }
-            /* Need more data */
-            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 */
+                return NULL;
+            }
+        }
+    }
     case STATE_SEND_DATA:
         out = block_Alloc(p_sys->i_frame_size);
 
@@ -681,7 +715,10 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block)
                 pi_channels_maps[p_sys->stream_info.channels];
 
         /* So p_block doesn't get re-added several times */
-        *pp_block = block_BytestreamPop(&p_sys->bytestream);
+        if ( in )
+            *pp_block = block_BytestreamPop(&p_sys->bytestream);
+        else
+            block_BytestreamFlush(&p_sys->bytestream);
 
         p_sys->i_state = STATE_NOSYNC;
 



More information about the vlc-commits mailing list