The branch, master has been updated
via d058d5db102234d15ee421a23c96a12518aa2faa (commit)
from 8313dc1120a221962541000ae261c2f1fbc53a9e (commit)
- Log -----------------------------------------------------------------
commit d058d5db102234d15ee421a23c96a12518aa2faa
Author: Manuel Lauss <[email protected]>
AuthorDate: Thu Oct 30 16:01:10 2025 +0100
Commit: Lynne <[email protected]>
CommitDate: Tue Nov 4 10:28:57 2025 +0000
avcodec/sanm: implement codec45
This is a post-processing codec: given delta-x/y coordinates and a run
length,
the r/g/b components of the 4 surrounding pixels are summed up, and the
resulting
15bit value is used as index into a color quantization table to derive the
resulting pixel at the center.
It is only used in 10-20 frames of the Rebel Assault 2 LxxRETRY.SAN files
to slightly blur the outline of the "opening aperture" effect.
Signed-off-by: Manuel Lauss <[email protected]>
diff --git a/libavcodec/sanm.c b/libavcodec/sanm.c
index 742fc1d477..771ecf8246 100644
--- a/libavcodec/sanm.c
+++ b/libavcodec/sanm.c
@@ -297,6 +297,8 @@ typedef struct SANMVideoContext {
uint8_t c4tbl[2][256][16];
uint16_t c4param;
uint8_t c47cb[4];
+ uint8_t c45tbl1[0x300];
+ uint8_t c45tbl2[0x8000];
} SANMVideoContext;
enum GlyphEdge {
@@ -1946,6 +1948,66 @@ static int old_codec48(SANMVideoContext *ctx,
GetByteContext *gb, int top, int l
return 0;
}
+static void old_codec45(SANMVideoContext *ctx, GetByteContext *gb, int top,
int left, int flag)
+{
+ int t1, t2, i;
+
+ if (bytestream2_get_bytes_left(gb) < 6)
+ return;
+
+ bytestream2_skip(gb, 2);
+ t1 = bytestream2_get_le16u(gb);
+ t2 = bytestream2_get_byteu(gb);
+ bytestream2_skip(gb, 1);
+ if (t2 != 1)
+ return;
+ if (t1 == 0) {
+ if (bytestream2_get_bytes_left(gb) < 0x300)
+ return;
+ bytestream2_get_bufferu(gb, ctx->c45tbl1, 0x300);
+ i = 0;
+ while ((bytestream2_get_bytes_left(gb) > 1) && (i < 0x8000)) {
+ uint8_t len = bytestream2_get_byteu(gb);
+ uint8_t val = bytestream2_get_byteu(gb);
+ if ((i + len) > 0x8000)
+ len = 0x8000 - i;
+ memset(ctx->c45tbl2 + i, val, len);
+ i += len;
+ }
+ }
+
+ if (flag)
+ return;
+
+ while (bytestream2_get_bytes_left(gb) > 3) {
+ left += (int16_t)bytestream2_get_le16u(gb);
+ top += bytestream2_get_byteu(gb);
+ int len = bytestream2_get_byteu(gb);
+ while (len >= 0) {
+ if ((left > 0) && (top > 0) && (left < (ctx->width - 1))) {
+ if (top >= (ctx->height - 1))
+ return;
+
+ uint8_t *dst = (uint8_t *)ctx->fbuf + left + top * ctx->pitch;
+ unsigned int c1 = *(dst - 1) * 3;
+ unsigned int c2 = *(dst + 1) * 3;
+ unsigned int r = ctx->c45tbl1[c1 + 0] + ctx->c45tbl1[c2 + 0];
+ unsigned int g = ctx->c45tbl1[c1 + 1] + ctx->c45tbl1[c2 + 1];
+ unsigned int b = ctx->c45tbl1[c1 + 2] + ctx->c45tbl1[c2 + 2];
+ c1 = *(dst - ctx->pitch) * 3;
+ c2 = *(dst + ctx->pitch) * 3;
+ r += ctx->c45tbl1[c1 + 0] + ctx->c45tbl1[c2 + 0];
+ g += ctx->c45tbl1[c1 + 1] + ctx->c45tbl1[c2 + 1];
+ b += ctx->c45tbl1[c1 + 2] + ctx->c45tbl1[c2 + 2];
+ *dst = ctx->c45tbl2[((r << 5) & 0x7c00) | (g & 0x3e0) | (b >>
5)];
+ }
+ left++;
+ len--;
+ }
+ left--;
+ }
+}
+
static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb,
int xoff, int yoff)
{
@@ -1964,6 +2026,12 @@ static int process_frame_obj(SANMVideoContext *ctx,
GetByteContext *gb,
parm2 = bytestream2_get_le16u(gb);
if (w < 1 || h < 1 || w > 640 || h > 480 || left > 640 || top > 480 ||
left + w <= 0 || top + h <= 0) {
+ /* codec45 frames with data for the 2 tables have nonsensical
dimensions */
+ if (codec == 45) {
+ old_codec45(ctx, gb, 0, 0, 1);
+ return 0;
+ }
+
av_log(ctx->avctx, AV_LOG_WARNING,
"ignoring invalid fobj dimensions: c%d %d %d @ %d %d\n",
codec, w, h, left, top);
@@ -1980,7 +2048,7 @@ static int process_frame_obj(SANMVideoContext *ctx,
GetByteContext *gb,
if ((w == 640) && (h == 272) && (top == 60) && (codec == 47))
left = top = 0;
- if (!ctx->have_dimensions) {
+ if (!ctx->have_dimensions && (codec != 45)) {
int xres, yres;
if (ctx->subversion < 2) {
/* Rebel Assault 1: 384x242 internal size */
@@ -2073,7 +2141,7 @@ static int process_frame_obj(SANMVideoContext *ctx,
GetByteContext *gb,
case 37:
return old_codec37(ctx, gb, top, left, w, h); break;
case 45:
- return 0;
+ old_codec45(ctx, gb, top, left, 0); break;
case 47:
return old_codec47(ctx, gb, top, left, w, h); break;
case 48:
-----------------------------------------------------------------------
Summary of changes:
libavcodec/sanm.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 70 insertions(+), 2 deletions(-)
hooks/post-receive
--
_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]