[FFmpeg-cvslog] avcodec/rpzaenc: stop assuming prev and current frame linesize match

Paul B Mahol git at videolan.org
Sun Nov 13 01:16:08 EET 2022


ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Sat Nov 12 23:44:01 2022 +0100| [31e1b614f683940ffe6c1fd0f33f658b3e7c845f] | committer: Paul B Mahol

avcodec/rpzaenc: stop assuming prev and current frame linesize match

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=31e1b614f683940ffe6c1fd0f33f658b3e7c845f
---

 libavcodec/rpzaenc.c | 53 ++++++++++++++++++++++++++++++++++------------------
 1 file changed, 35 insertions(+), 18 deletions(-)

diff --git a/libavcodec/rpzaenc.c b/libavcodec/rpzaenc.c
index 4ced9523e2..880f6f71dc 100644
--- a/libavcodec/rpzaenc.c
+++ b/libavcodec/rpzaenc.c
@@ -80,6 +80,7 @@ typedef struct BlockInfo {
     int block_index;
     uint16_t start;
     int rowstride;
+    int prev_rowstride;
     int blocks_per_row;
     int total_blocks;
 } BlockInfo;
@@ -113,7 +114,7 @@ static void get_colors(const uint8_t *min, const uint8_t *max, uint8_t color4[4]
 }
 
 /* Fill BlockInfo struct with information about a 4x4 block of the image */
-static int get_block_info(BlockInfo *bi, int block)
+static int get_block_info(BlockInfo *bi, int block, int prev_frame)
 {
     bi->row = block / bi->blocks_per_row;
     bi->col = block % bi->blocks_per_row;
@@ -132,7 +133,7 @@ static int get_block_info(BlockInfo *bi, int block)
         bi->block_height = 4;
     }
 
-    return block ? (bi->col * 4) + (bi->row * bi->rowstride * 4) : 0;
+    return block ? (bi->col * 4) + (bi->row * (prev_frame ? bi->prev_rowstride : bi->rowstride) * 4) : 0;
 }
 
 static uint16_t rgb24_to_rgb555(const uint8_t *rgb24)
@@ -253,7 +254,7 @@ static int compare_blocks(const uint16_t *block1, const uint16_t *block2,
                 return -1;
             }
         }
-        block1 += bi->rowstride;
+        block1 += bi->prev_rowstride;
         block2 += bi->rowstride;
     }
     return 0;
@@ -387,9 +388,11 @@ static int match_color(const uint16_t *color, uint8_t colors[4][3])
 static int encode_four_color_block(const uint8_t *min_color, const uint8_t *max_color,
                                    PutBitContext *pb, const uint16_t *block_ptr, const BlockInfo *bi)
 {
-    int x, y, idx;
+    const int y_size = FFMIN(4, bi->image_height - bi->row * 4);
+    const int x_size = FFMIN(4, bi->image_width  - bi->col * 4);
     uint8_t color4[4][3];
     uint16_t rounded_max, rounded_min;
+    int idx;
 
     // round min and max wider
     rounded_min = rgb24_to_rgb555(min_color);
@@ -403,13 +406,21 @@ static int encode_four_color_block(const uint8_t *min_color, const uint8_t *max_
 
     get_colors(min_color, max_color, color4);
 
-    for (y = 0; y < 4; y++) {
-        for (x = 0; x < 4; x++) {
+    for (int y = 0; y < y_size; y++) {
+        for (int x = 0; x < x_size; x++) {
             idx = match_color(&block_ptr[x], color4);
             put_bits(pb, 2, idx);
         }
+
+        for (int x = x_size; x < 4; x++)
+            put_bits(pb, 2, idx);
         block_ptr += bi->rowstride;
     }
+
+    for (int y = y_size; y < 4; y++) {
+        for (int x = 0; x < 4; x++)
+            put_bits(pb, 2, 0);
+    }
     return 1; // num blocks encoded
 }
 
@@ -421,10 +432,11 @@ static void update_block_in_prev_frame(const uint16_t *src_pixels,
                                        const BlockInfo *bi, int block_counter)
 {
     const int y_size = FFMIN(4, bi->image_height - bi->row * 4);
+    const int x_size = FFMIN(4, bi->image_width  - bi->col * 4) * 2;
 
     for (int y = 0; y < y_size; y++) {
-        memcpy(dest_pixels, src_pixels, 8);
-        dest_pixels += bi->rowstride;
+        memcpy(dest_pixels, src_pixels, x_size);
+        dest_pixels += bi->prev_rowstride;
         src_pixels += bi->rowstride;
     }
 }
@@ -556,6 +568,7 @@ static void rpza_encode_stream(RpzaContext *s, const AVFrame *pict)
     int total_blocks;
     int prev_block_offset;
     int block_offset = 0;
+    int pblock_offset = 0;
     uint8_t min = 0, max = 0;
     channel_offset chan;
     int i;
@@ -574,6 +587,7 @@ static void rpza_encode_stream(RpzaContext *s, const AVFrame *pict)
     bi.image_width = s->frame_width;
     bi.image_height = s->frame_height;
     bi.rowstride = pict->linesize[0] / 2;
+    bi.prev_rowstride = s->prev_frame->linesize[0] / 2;
 
     bi.blocks_per_row = (s->frame_width + 3) / 4;
 
@@ -586,8 +600,8 @@ static void rpza_encode_stream(RpzaContext *s, const AVFrame *pict)
             prev_block_offset = 0;
 
             while (n_blocks < 32 && block_counter + n_blocks < total_blocks) {
-
-                block_offset = get_block_info(&bi, block_counter + n_blocks);
+                block_offset  = get_block_info(&bi, block_counter + n_blocks, 0);
+                pblock_offset = get_block_info(&bi, block_counter + n_blocks, 1);
 
                 // multi-block opcodes cannot span multiple rows.
                 // If we're starting a new row, break out and write the opcode
@@ -602,7 +616,7 @@ static void rpza_encode_stream(RpzaContext *s, const AVFrame *pict)
 
                 prev_block_offset = block_offset;
 
-                if (compare_blocks(&prev_pixels[block_offset],
+                if (compare_blocks(&prev_pixels[pblock_offset],
                                    &src_pixels[block_offset], &bi, s->skip_frame_thresh) != 0) {
                     // write out skipable blocks
                     if (n_blocks) {
@@ -623,7 +637,7 @@ static void rpza_encode_stream(RpzaContext *s, const AVFrame *pict)
                  */
 
                 // update_block_in_prev_frame(&src_pixels[block_offset],
-                //   &prev_pixels[block_offset], &bi, block_counter + n_blocks);
+                //   &prev_pixels[pblock_offset], &bi, block_counter + n_blocks);
 
                 n_blocks++;
             }
@@ -639,7 +653,8 @@ static void rpza_encode_stream(RpzaContext *s, const AVFrame *pict)
             }
 
         } else {
-            block_offset = get_block_info(&bi, block_counter);
+            block_offset  = get_block_info(&bi, block_counter, 0);
+            pblock_offset = get_block_info(&bi, block_counter, 1);
         }
 post_skip :
 
@@ -653,11 +668,12 @@ post_skip :
 
             /* update this block in the previous frame buffer */
             update_block_in_prev_frame(&src_pixels[block_offset],
-                                       &prev_pixels[block_offset], &bi, block_counter + n_blocks);
+                                       &prev_pixels[pblock_offset], &bi, block_counter + n_blocks);
 
             // check for subsequent blocks with the same color
             while (n_blocks < 32 && block_counter + n_blocks < total_blocks) {
-                block_offset = get_block_info(&bi, block_counter + n_blocks);
+                block_offset  = get_block_info(&bi, block_counter + n_blocks, 0);
+                pblock_offset = get_block_info(&bi, block_counter + n_blocks, 1);
 
                 // multi-block opcodes cannot span multiple rows.
                 // If we've hit end of a row, break out and write the opcode
@@ -675,7 +691,7 @@ post_skip :
 
                 /* update this block in the previous frame buffer */
                 update_block_in_prev_frame(&src_pixels[block_offset],
-                                           &prev_pixels[block_offset], &bi, block_counter + n_blocks);
+                                           &prev_pixels[pblock_offset], &bi, block_counter + n_blocks);
 
                 n_blocks++;
             }
@@ -734,7 +750,8 @@ post_skip :
                 const uint16_t *row_ptr;
                 int y_size, rgb555;
 
-                block_offset = get_block_info(&bi, block_counter);
+                block_offset  = get_block_info(&bi, block_counter, 0);
+                pblock_offset = get_block_info(&bi, block_counter, 1);
 
                 row_ptr = &src_pixels[block_offset];
                 y_size = FFMIN(4, bi.image_height - bi.row * 4);
@@ -761,7 +778,7 @@ post_skip :
 
             /* update this block in the previous frame buffer */
             update_block_in_prev_frame(&src_pixels[block_offset],
-                                       &prev_pixels[block_offset], &bi, block_counter);
+                                       &prev_pixels[pblock_offset], &bi, block_counter);
         }
     }
 }



More information about the ffmpeg-cvslog mailing list