[vlc-commits] [Git][videolan/vlc][master] 7 commits: packetizer: flac: don't send invalid frame on drain

Jean-Baptiste Kempf (@jbk) gitlab at videolan.org
Wed Jul 20 07:34:49 UTC 2022



Jean-Baptiste Kempf pushed to branch master at VideoLAN / VLC


Commits:
599757d9 by Francois Cartegnie at 2022-07-20T07:16:28+00:00
packetizer: flac: don't send invalid frame on drain

- - - - -
d2312650 by Francois Cartegnie at 2022-07-20T07:16:28+00:00
packetizer: flac: fix potential endless loop on drain

- - - - -
6aeaeb61 by Francois Cartegnie at 2022-07-20T07:16:28+00:00
packetizer: flac: add comments

- - - - -
1cd8422a by Francois Cartegnie at 2022-07-20T07:16:28+00:00
packetizer: flac: fix fixed blocksize streams last pts

- - - - -
54ffcdec by Francois Cartegnie at 2022-07-20T07:16:28+00:00
packetizer: flac: remove useless frame_size

- - - - -
1c03970b by Francois Cartegnie at 2022-07-20T07:16:28+00:00
packetizer: flac: move frame check outside reader

- - - - -
1db4d294 by Francois Cartegnie at 2022-07-20T07:16:28+00:00
packetizer: flac: do not check min frame size for fixed block

cannot pass on truncated end

- - - - -


2 changed files:

- modules/packetizer/flac.c
- modules/packetizer/flac.h


Changes:

=====================================
modules/packetizer/flac.c
=====================================
@@ -75,7 +75,6 @@ typedef struct
     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;
@@ -347,6 +346,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;
@@ -368,10 +368,12 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block)
             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;
@@ -379,9 +381,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
@@ -393,14 +395,19 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block)
 
     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;
             }
@@ -413,12 +420,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;
         }
@@ -428,9 +437,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;
@@ -441,9 +452,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;
@@ -467,17 +480,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 )
             {
@@ -492,10 +501,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 +533,7 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block)
         }
 
 
-        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 );
@@ -539,7 +551,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;
 
@@ -571,7 +582,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_TICK_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_TICK_0 + vlc_tick_from_samples(blocksize * i_fsnumber, samplerate);
+    {
+        const unsigned fixedblocksize = stream_info ? stream_info->min_blocksize : blocksize;
+        h->i_pts = VLC_TICK_0 + vlc_tick_from_samples(fixedblocksize * i_fsnumber, samplerate);
+    }
     else /* Variable blocksize stream / Samples */
         h->i_pts = VLC_TICK_0 + vlc_tick_from_samples(i_fsnumber, samplerate);
 



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/8e2c76e5f523106375ca8612ade8a51bb7a6c926...1db4d294ca8185e5a9e25d823c40677831d9f538

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/8e2c76e5f523106375ca8612ade8a51bb7a6c926...1db4d294ca8185e5a9e25d823c40677831d9f538
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