History

libavcodec/sanm: add codec47 interpolation table support

Some codec47 frames come with an interpolation table: Combining 2 adjacent pixels into a 16bit value, this value can then be used as index into the interpolation table to get a new pixel value. This is used for subcodec 1, which encodes a key- frame at half width and height, and makes these frame less blocky appearing.

Manuel Lauss committed 2 years ago

Commit 1e2a72a1 parent 44d32c81 file · +56 −11Browse files

Unified · Split

libavcodec/sanm.c+56−11
@@ -291,6 +291,7 @@ typedef struct SANMVideoContext { · 290 unmodified lines
291 291
292 int8_t p4x4glyphs[NGLYPHS][16];292 int8_t p4x4glyphs[NGLYPHS][16];
293 int8_t p8x8glyphs[NGLYPHS][64];293 int8_t p8x8glyphs[NGLYPHS][64];
294 uint8_t c47itbl[0x10000];
294} SANMVideoContext;295} SANMVideoContext;
295 296
296typedef struct SANMFrameHeader {297typedef struct SANMFrameHeader {
@@ -856,6 +857,55 @@ static int process_block(SANMVideoContext *ctx, uint8_t *dst, uint8_t *prev1, · 559 unmodified lines
856 return 0;857 return 0;
857}858}
858 859
860static void codec47_read_interptable(SANMVideoContext *ctx)
861{
862 uint8_t *p1, *p2, *itbl = ctx->c47itbl;
863 int i, j;
864
865 for (i = 0; i < 256; i++) {
866 p1 = p2 = itbl + i;
867 for (j = 256 - i; j; j--) {
868 *p1 = *p2 = bytestream2_get_byte(&ctx->gb);
869 p1 += 1;
870 p2 += 256;
871 }
872 itbl += 256;
873 }
874}
875
876static void codec47_comp1(SANMVideoContext *ctx, uint8_t *dst_in, int width,
877 int height, ptrdiff_t stride)
878{
879 uint8_t p1, *dst, *itbl = ctx->c47itbl;
880 uint16_t px;
881 int i, j;
882
883 dst = dst_in + stride;
884 for (i = 0; i < height; i += 2) {
885 p1 = bytestream2_get_byte(&ctx->gb);
886 *dst++ = p1;
887 *dst++ = p1;
888 px = p1;
889 for (j = 2; j < width; j += 2) {
890 p1 = bytestream2_get_byte(&ctx->gb);
891 px = (px << 8) | p1;
892 *dst++ = itbl[px];
893 *dst++ = p1;
894 }
895 dst += stride;
896 }
897
898 memcpy(dst_in, dst_in + stride, width);
899 dst = dst_in + stride + stride;
900 for (i = 2; i < height - 1; i += 2) {
901 for (j = 0; j < width; j++) {
902 px = (*(dst - stride) << 8) | *(dst + stride);
903 *dst++ = itbl[px];
904 }
905 dst += stride;
906 }
907}
908
859static int old_codec47(SANMVideoContext *ctx, int top,909static int old_codec47(SANMVideoContext *ctx, int top,
860 int left, int width, int height)910 int left, int width, int height)
861{911{
@@ -880,8 +930,11 @@ static int old_codec47(SANMVideoContext *ctx, int top, · 18 unmodified lines
880 av_log(ctx->avctx, AV_LOG_WARNING, "Decoded size is too large.\n");930 av_log(ctx->avctx, AV_LOG_WARNING, "Decoded size is too large.\n");
881 }931 }
882 932
883 if (skip & 1)933 if (skip & 1) {
884 bytestream2_skip(&ctx->gb, 0x8080);934 if (bytestream2_get_bytes_left(&ctx->gb) < 0x8080)
935 return AVERROR_INVALIDDATA;
936 codec47_read_interptable(ctx);
937 }
885 if (!seq) {938 if (!seq) {
886 ctx->prev_seq = -1;939 ctx->prev_seq = -1;
887 memset(prev1, 0, ctx->height * stride);940 memset(prev1, 0, ctx->height * stride);
@@ -900,15 +953,7 @@ static int old_codec47(SANMVideoContext *ctx, int top, · 12 unmodified lines
900 case 1:953 case 1:
901 if (bytestream2_get_bytes_left(&ctx->gb) < ((width + 1) >> 1) * ((height + 1) >> 1))954 if (bytestream2_get_bytes_left(&ctx->gb) < ((width + 1) >> 1) * ((height + 1) >> 1))
902 return AVERROR_INVALIDDATA;955 return AVERROR_INVALIDDATA;
903 for (j = 0; j < height; j += 2) {956 codec47_comp1(ctx, dst, width, height, stride);
904 for (i = 0; i < width; i += 2) {
905 dst[i] =
906 dst[i + 1] =
907 dst[stride + i] =
908 dst[stride + i + 1] = bytestream2_get_byteu(&ctx->gb);
909 }
910 dst += stride * 2;
911 }
912 break;957 break;
913 case 2:958 case 2:
914 if (seq == ctx->prev_seq + 1) {959 if (seq == ctx->prev_seq + 1) {

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t