This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch master
in repository ffmpeg.

commit cad555d0a49155252eac0c57fe1c4733eb6adbf6
Author:     Ramiro Polla <[email protected]>
AuthorDate: Fri Sep 19 16:53:49 2025 +0200
Commit:     Ramiro Polla <[email protected]>
CommitDate: Fri Feb 20 16:32:10 2026 +0100

    avcodec/mjpegdec: improve unescaping of SOS fields
    
    For non-jpegls:
    
    Changes the behaviour to be more in line with IJG's reference 
implementation:
    - optional 0xFF fill bytes in a stuffed zero byte sequence (which is an
      invalid pattern according to the standard) are now discarded:
        "FF (FF)? 00" => "FF" instead of "FF 00"
    - sequences with optional 0xFF fill bytes and a marker are no longer copied:
        "FF (FF)? XX" => "" instead of "FF XX"
    - a trailing 0xFF byte is no longer issued when a valid "0xFF 0xXX" marker
      is found:
        "FF XX" => "" instead of "FF"
    
    For jpegls:
    
    Changes the behaviour to be more in line with IJG's (non-jpegls) reference
    implementation, similar to the changes above:
    - optional 0xFF fill bytes in a stuffed zero bit sequence (which is an
      invalid pattern according to the standard) are now discarded:
      "FF (FF)? 0b0xxxxxxx" => "FF 0bxxxxxxx" instead of "FF 7F XX"
    - sequences with optional 0xFF fill bytes and a marker are no longer copied:
      "FF (FF)? 0b1xxxxxxx" => "" instead of "FF 7F"
    
    Unescaping for jpegls is now done in one pass instead of two. The first
    pass used to detect the length of the buffer, while the second pass would
    copy up to the detected length.
    
    Note that jpegls restart markers are still not supported.
    
    There is also a speed up with the new implementations, mostly due to the
    usage of memchr() as suggested by Andreas Rheinhardt 
<[email protected]>
---
 libavcodec/mjpegdec.c | 135 ++++++++++++++++++++++++--------------------------
 1 file changed, 66 insertions(+), 69 deletions(-)

diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c
index cd36bc6022..ef8c694a76 100644
--- a/libavcodec/mjpegdec.c
+++ b/libavcodec/mjpegdec.c
@@ -2256,94 +2256,91 @@ static int mjpeg_unescape_sos(MJpegDecodeContext *s)
         const uint8_t *src = buf_ptr;
         const uint8_t *ptr = src;
         uint8_t *dst = s->buffer;
-
-        #define copy_data_segment(skip) do {       \
-            ptrdiff_t length = (ptr - src) - (skip);  \
-            if (length > 0) {                         \
-                memcpy(dst, src, length);             \
-                dst += length;                        \
-                src = ptr;                            \
-            }                                         \
-        } while (0)
-
-            while (ptr < buf_end) {
-                uint8_t x = *(ptr++);
-
-                if (x == 0xff) {
-                    ptrdiff_t skip = 0;
-                    while (ptr < buf_end && x == 0xff) {
-                        x = *(ptr++);
-                        skip++;
-                    }
-
-                    /* 0xFF, 0xFF, ... */
-                    if (skip > 1) {
-                        copy_data_segment(skip);
-
-                        /* decrement src as it is equal to ptr after the
-                         * copy_data_segment macro and we might want to
-                         * copy the current value of x later on */
-                        src--;
-                    }
-
-                    if (x < RST0 || x > RST7) {
-                        copy_data_segment(1);
-                        if (x)
-                            break;
-                    }
+        PutByteContext pb;
+
+        bytestream2_init_writer(&pb, dst, buf_end - src);
+
+        while ((ptr = memchr(ptr, 0xff, buf_end - ptr))) {
+            ptr++;
+            if (ptr < buf_end) {
+                /* Copy verbatim data. */
+                ptrdiff_t length = (ptr - 1) - src;
+                if (length > 0)
+                    bytestream2_put_bufferu(&pb, src, length);
+
+                uint8_t x = *ptr++;
+                /* Discard multiple optional 0xFF fill bytes. */
+                while (x == 0xff && ptr < buf_end)
+                    x = *ptr++;
+
+                src = ptr;
+                if (x == 0) {
+                    /* Stuffed zero byte */
+                    bytestream2_put_byteu(&pb, 0xff);
+                } else if (x >= RST0 && x <= RST7) {
+                    /* Restart marker */
+                    bytestream2_put_be16u(&pb, 0xff00 | x);
+                } else {
+                    /* Non-restart marker */
+                    goto found;
                 }
             }
-            if (src < ptr)
-                copy_data_segment(0);
-        #undef copy_data_segment
+        }
+        /* Copy remaining verbatim data. */
+        ptr = buf_end;
+        ptrdiff_t length = ptr - src;
+        if (length > 0)
+            bytestream2_put_bufferu(&pb, src, length);
 
+found:
         unescaped_buf_ptr  = s->buffer;
-        unescaped_buf_size = dst - s->buffer;
+        unescaped_buf_size = bytestream2_tell_p(&pb);
         memset(s->buffer + unescaped_buf_size, 0,
                AV_INPUT_BUFFER_PADDING_SIZE);
 
         av_log(s->avctx, AV_LOG_DEBUG, "escaping removed %td bytes\n",
-               (buf_end - buf_ptr) - (dst - s->buffer));
+               (buf_end - buf_ptr) - (unescaped_buf_size));
     } else {
         const uint8_t *src = buf_ptr;
+        const uint8_t *ptr = src;
         uint8_t *dst  = s->buffer;
-        int bit_count = 0;
-        int t = 0, b = 0;
         PutBitContext pb;
 
-        /* find marker */
-        while (src + t < buf_end) {
-            uint8_t x = src[t++];
-            if (x == 0xff) {
-                while ((src + t < buf_end) && x == 0xff)
-                    x = src[t++];
-                if (x & 0x80) {
-                    t -= FFMIN(2, t);
-                    break;
-                }
-            }
-        }
-        bit_count = t * 8;
-        init_put_bits(&pb, dst, t);
-
-        /* unescape bitstream */
-        while (b < t) {
-            uint8_t x = src[b++];
-            put_bits(&pb, 8, x);
-            if (x == 0xFF && b < t) {
-                x = src[b++];
-                if (x & 0x80) {
-                    av_log(s->avctx, AV_LOG_WARNING, "Invalid escape 
sequence\n");
-                    x &= 0x7f;
+        init_put_bits(&pb, dst, buf_end - src);
+
+        while ((ptr = memchr(ptr, 0xff, buf_end - ptr))) {
+            ptr++;
+            if (ptr < buf_end) {
+                /* Copy verbatim data. */
+                ptrdiff_t length = (ptr - 1) - src;
+                if (length > 0)
+                    ff_copy_bits(&pb, src, length * 8);
+
+                uint8_t x = *ptr++;
+                /* Discard multiple optional 0xFF fill bytes. */
+                while (x == 0xff && ptr < buf_end)
+                    x = *ptr++;
+
+                src = ptr;
+                if (!(x & 0x80)) {
+                    /* Stuffed zero bit */
+                    put_bits(&pb, 15, 0x7f80 | x);
+                } else {
+                    goto found_ls;
                 }
-                put_bits(&pb, 7, x);
-                bit_count--;
             }
         }
+        /* Copy remaining verbatim data. */
+        ptr = buf_end;
+        ptrdiff_t length = ptr - src;
+        if (length > 0)
+            ff_copy_bits(&pb, src, length * 8);
+
+found_ls:
         flush_put_bits(&pb);
 
         unescaped_buf_ptr  = dst;
-        unescaped_buf_size = (bit_count + 7) >> 3;
+        unescaped_buf_size = put_bytes_output(&pb);
         memset(s->buffer + unescaped_buf_size, 0,
                AV_INPUT_BUFFER_PADDING_SIZE);
     }

_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to