aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul B Mahol <onemda@gmail.com>2022-11-12 23:44:01 +0100
committerPaul B Mahol <onemda@gmail.com>2022-11-13 00:19:57 +0100
commit31e1b614f683940ffe6c1fd0f33f658b3e7c845f (patch)
tree4cd2b51a35d96af57659c95ac2a4819e22106453
parent5d7de322d494f45cafbe6f3fc734d979023973d2 (diff)
downloadffmpeg-31e1b614f683940ffe6c1fd0f33f658b3e7c845f.tar.gz
avcodec/rpzaenc: stop assuming prev and current frame linesize match
-rw-r--r--libavcodec/rpzaenc.c53
1 files 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);
}
}
}