History

avcodec/sanm: support "StarWars - Making Magic" video

Videos of "StarWars - Making Magic" consist of 640x480 codec3 frames which establish a background, and a 320x240 codec48 video put on top at random left/top offsets. To support this, a new default buffer "fbuf", which holds the final image to be presented, is added, since codec37/47/48 need their 2/3 buffers to be private to themselves. The decoded result is then copied to the fbuf, honoring the left/top offsets if required.

Manuel Lauss committed 1 year ago

Commit 37064b21 parent 9369ebf1 file · +42 −23Browse files

Showing the changes to libavcodec (1 of 1 file). Show all

Unified · Split

libavcodec/sanm.c+42−23
@@ -274,9 +274,9 @@ typedef struct SANMVideoContext { · 273 unmodified lines
274274 int prev_seq;
275275
276276 AVFrame *frame;
277− uint16_t *frm0, *frm1, *frm2;
277+ uint16_t *fbuf, *frm0, *frm1, *frm2;
278278 uint8_t *stored_frame;
279− uint32_t frm0_size, frm1_size, frm2_size;
279+ uint32_t fbuf_size, frm0_size, frm1_size, frm2_size;
280280 uint32_t stored_frame_size;
281281
282282 uint8_t *rle_buf;
@@ -453,6 +453,7 @@ static void init_sizes(SANMVideoContext *ctx, int width, int height) · 170 unmodified lines
453453
454454 static void destroy_buffers(SANMVideoContext *ctx)
455455 {
456+ av_freep(&ctx->fbuf);
456457 av_freep(&ctx->frm0);
457458 av_freep(&ctx->frm1);
458459 av_freep(&ctx->frm2);
@@ -466,6 +467,7 @@ static void destroy_buffers(SANMVideoContext *ctx) · 7 unmodified lines
466467
467468 static av_cold int init_buffers(SANMVideoContext *ctx)
468469 {
470+ av_fast_padded_mallocz(&ctx->fbuf, &ctx->fbuf_size, ctx->buf_size);
469471 av_fast_padded_mallocz(&ctx->frm0, &ctx->frm0_size, ctx->buf_size);
470472 av_fast_padded_mallocz(&ctx->frm1, &ctx->frm1_size, ctx->buf_size);
471473 av_fast_padded_mallocz(&ctx->frm2, &ctx->frm2_size, ctx->buf_size);
@@ -674,7 +676,7 @@ static int old_codec4(SANMVideoContext *ctx, GetByteContext *gb, int top, int le · 202 unmodified lines
674676 {
675677 const uint16_t p = ctx->pitch;
676678 const uint32_t maxpxo = ctx->height * p;
677− uint8_t mask, bits, idx, *gs, *dst = (uint8_t *)ctx->frm0;
679+ uint8_t mask, bits, idx, *gs, *dst = (uint8_t *)ctx->fbuf;
678680 int i, j, k, l, bit, ret;
679681 int32_t pxoff, pxo2;
680682
@@ -805,7 +807,7 @@ static int old_codec23(SANMVideoContext *ctx, GetByteContext *gb, int top, int l · 124 unmodified lines
805807 if (bytestream2_get_bytes_left(gb) < 1)
806808 return 0; /* some c23 frames just set up the LUT */
807809
808− dst = (uint8_t *)ctx->frm0;
810+ dst = (uint8_t *)ctx->fbuf;
809811 for (i = 0; i < height; i++) {
810812 if (bytestream2_get_bytes_left(gb) < 2)
811813 return 0;
@@ -840,10 +842,10 @@ static int old_codec21(SANMVideoContext *ctx, GetByteContext *gb, int top, int l · 28 unmodified lines
840842 int width, int height)
841843 {
842844 const uint32_t maxpxo = ctx->height * ctx->pitch;
843− uint8_t *dst = (uint8_t *)ctx->frm0, c;
845+ uint8_t *dst = (uint8_t *)ctx->fbuf, c;
844846 int i, j, k, pc, sk, pxoff;
845847
846− dst = (uint8_t *)ctx->frm0;
848+ dst = (uint8_t *)ctx->fbuf;
847849 for (i = 0; i < height; i++) {
848850 if (bytestream2_get_bytes_left(gb) < 2)
849851 return 0;
@@ -884,7 +886,7 @@ static int old_codec1(SANMVideoContext *ctx, GetByteContext *gb, int top, · 34 unmodified lines
884886 {
885887 int i, j, len, flag, code, val, end, pxoff;
886888 const int maxpxo = ctx->height * ctx->pitch;
887− uint8_t *dst = (uint8_t *)ctx->frm0;
889+ uint8_t *dst = (uint8_t *)ctx->fbuf;
888890
889891 for (i = 0; i < height; i++) {
890892 if (bytestream2_get_bytes_left(gb) < 2)
@@ -932,7 +934,7 @@ static int old_codec1(SANMVideoContext *ctx, GetByteContext *gb, int top, · 41 unmodified lines
932934 static int old_codec2(SANMVideoContext *ctx, GetByteContext *gb, int top,
933935 int left, int width, int height)
934936 {
935− uint8_t *dst = (uint8_t *)ctx->frm0, col;
937+ uint8_t *dst = (uint8_t *)ctx->fbuf, col;
936938 int16_t xpos = left, ypos = top;
937939
938940 while (bytestream2_get_bytes_left(gb) > 3) {
@@ -949,7 +951,7 @@ static int old_codec2(SANMVideoContext *ctx, GetByteContext *gb, int top, · 10 unmodified lines
949951
950952 static int old_codec20(SANMVideoContext *ctx, int w, int h)
951953 {
952− uint8_t *dst = (uint8_t *)ctx->frm0;
954+ uint8_t *dst = (uint8_t *)ctx->fbuf;
953955
954956 if (bytestream2_get_bytes_left(&ctx->gb) < w * h)
955957 return AVERROR_INVALIDDATA;
@@ -1008,10 +1010,10 @@ static int old_codec37(SANMVideoContext *ctx, int width, int height) · 52 unmodified lines
10081010 ctx->rotate_code = 0;
10091011
10101012 if (((seq & 1) || !(flags & 1)) && (compr && compr != 2)) {
1011− FFSWAP(uint16_t*, ctx->frm1, ctx->frm2);
1013+ FFSWAP(uint16_t*, ctx->frm0, ctx->frm2);
10121014 }
10131015
1014− dst = ((uint8_t*)ctx->frm1);
1016+ dst = ((uint8_t*)ctx->frm0);
10151017 prev = ((uint8_t*)ctx->frm2);
10161018
10171019 if (mvoff > 2) {
@@ -1145,7 +1147,6 @@ static int old_codec37(SANMVideoContext *ctx, int width, int height) · 127 unmodified lines
11451147 return AVERROR_PATCHWELCOME;
11461148 }
11471149
1148− memcpy(ctx->frm0, ctx->frm1, ctx->buf_size);
11491150 return 0;
11501151 }
11511152
@@ -1603,7 +1604,7 @@ static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb) · 451 unmodified lines
16031604 uint16_t w, h, parm2;
16041605 uint8_t codec, param;
16051606 int16_t left, top;
1606− int fsc, sote;
1607+ int fsc, sote, ret;
16071608
16081609 codec = bytestream2_get_byteu(gb);
16091610 param = bytestream2_get_byteu(gb);
@@ -1686,13 +1687,11 @@ static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb) · 76 unmodified lines
16861687 }
16871688 }
16881689
1689− /* on first FOBJ, when the codec is not one of the
1690− * full-buffer codecs (37/47/48), frm0 needs to be cleared.
1691− */
1690+ /* clear the main buffer on the first fob */
16921691 if (ctx->first_fob) {
16931692 ctx->first_fob = 0;
16941693 if (!fsc)
1695− memset(ctx->frm0, 0, ctx->frm0_size);
1694+ memset(ctx->fbuf, 0, ctx->frm0_size);
16961695 }
16971696
16981697 switch (codec) {
@@ -1713,18 +1712,38 @@ static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb) · 14 unmodified lines
17131712 case 23:
17141713 return old_codec23(ctx, gb, top, left, w, h, param, parm2);
17151714 case 37:
1716− return old_codec37(ctx, w, h);
1715+ ret = old_codec37(ctx, w, h); break;
17171716 case 45:
17181717 return 0;
17191718 case 47:
1720− return old_codec47(ctx, w, h);
1719+ ret = old_codec47(ctx, w, h); break;
17211720 case 48:
1722− return old_codec48(ctx, w, h);
1721+ ret = old_codec48(ctx, w, h); break;
17231722 default:
17241723 avpriv_request_sample(ctx->avctx, "Subcodec %d", codec);
17251724 ctx->frame->flags |= AV_FRAME_FLAG_CORRUPT;
17261725 return 0;
17271726 }
1727+ if (ret)
1728+ return ret;
1729+
1730+ /* copy the codec37/47/48 result to main buffer */
1731+ if ((w == ctx->width) && (h == ctx->height)) {
1732+ memcpy(ctx->fbuf, ctx->frm0, ctx->fbuf_size);
1733+ } else {
1734+ uint8_t *dst = (uint8_t *)ctx->fbuf + left + top * ctx->pitch;
1735+ const uint8_t *src = (uint8_t *)ctx->frm0;
1736+ const int cw = FFMIN(w, ctx->width - left);
1737+ const int ch = FFMIN(h, ctx->height - top);
1738+ if ((cw > 0) && (ch > 0) && (left >= 0) && (top >= 0)) {
1739+ for (int i = 0; i < ch; i++) {
1740+ memcpy(dst, src, cw);
1741+ dst += ctx->pitch;
1742+ src += w;
1743+ }
1744+ }
1745+ }
1746+ return 0;
17281747 }
17291748
17301749 static int process_ftch(SANMVideoContext *ctx, int size)
@@ -2196,7 +2215,7 @@ static void fill_frame(uint16_t *pbuf, int buf_size, uint16_t color) · 465 unmodified lines
21962215 static int copy_output(SANMVideoContext *ctx, SANMFrameHeader *hdr)
21972216 {
21982217 uint8_t *dst;
2199− const uint8_t *src = (uint8_t*) ctx->frm0;
2218+ const uint8_t *src = hdr ? (uint8_t *)ctx->frm0 : (uint8_t *)ctx->fbuf;
22002219 int ret, height = ctx->height;
22012220 ptrdiff_t dstpitch, srcpitch = ctx->pitch * (hdr ? sizeof(ctx->frm0[0]) : 1);
22022221
@@ -2279,7 +2298,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, · 76 unmodified lines
22792298 ret = AVERROR(ENOMEM);
22802299 }
22812300 } else {
2282− memcpy(ctx->stored_frame, ctx->frm0, ctx->buf_size);
2301+ memcpy(ctx->stored_frame, ctx->fbuf, ctx->buf_size);
22832302 }
22842303 }
22852304 break;
@@ -2295,7 +2314,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, · 9 unmodified lines
22952314 if (ret = process_ftch(ctx, size))
22962315 return ret;
22972316 } else {
2298− memcpy(ctx->frm0, ctx->stored_frame, ctx->buf_size);
2317+ memcpy(ctx->fbuf, ctx->stored_frame, ctx->buf_size);
22992318 }
23002319 have_img = 1;
23012320 break;

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