[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