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
274 int prev_seq;274 int prev_seq;
275 275
276 AVFrame *frame;276 AVFrame *frame;
277 uint16_t *frm0, *frm1, *frm2;277 uint16_t *fbuf, *frm0, *frm1, *frm2;
278 uint8_t *stored_frame;278 uint8_t *stored_frame;
279 uint32_t frm0_size, frm1_size, frm2_size;279 uint32_t fbuf_size, frm0_size, frm1_size, frm2_size;
280 uint32_t stored_frame_size;280 uint32_t stored_frame_size;
281 281
282 uint8_t *rle_buf;282 uint8_t *rle_buf;
@@ -453,6 +453,7 @@ static void init_sizes(SANMVideoContext *ctx, int width, int height) · 170 unmodified lines
453 453
454static void destroy_buffers(SANMVideoContext *ctx)454static void destroy_buffers(SANMVideoContext *ctx)
455{455{
456 av_freep(&ctx->fbuf);
456 av_freep(&ctx->frm0);457 av_freep(&ctx->frm0);
457 av_freep(&ctx->frm1);458 av_freep(&ctx->frm1);
458 av_freep(&ctx->frm2);459 av_freep(&ctx->frm2);
@@ -466,6 +467,7 @@ static void destroy_buffers(SANMVideoContext *ctx) · 7 unmodified lines
466 467
467static av_cold int init_buffers(SANMVideoContext *ctx)468static av_cold int init_buffers(SANMVideoContext *ctx)
468{469{
470 av_fast_padded_mallocz(&ctx->fbuf, &ctx->fbuf_size, ctx->buf_size);
469 av_fast_padded_mallocz(&ctx->frm0, &ctx->frm0_size, ctx->buf_size);471 av_fast_padded_mallocz(&ctx->frm0, &ctx->frm0_size, ctx->buf_size);
470 av_fast_padded_mallocz(&ctx->frm1, &ctx->frm1_size, ctx->buf_size);472 av_fast_padded_mallocz(&ctx->frm1, &ctx->frm1_size, ctx->buf_size);
471 av_fast_padded_mallocz(&ctx->frm2, &ctx->frm2_size, ctx->buf_size);473 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
674{676{
675 const uint16_t p = ctx->pitch;677 const uint16_t p = ctx->pitch;
676 const uint32_t maxpxo = ctx->height * p;678 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;
678 int i, j, k, l, bit, ret;680 int i, j, k, l, bit, ret;
679 int32_t pxoff, pxo2;681 int32_t pxoff, pxo2;
680 682
@@ -805,7 +807,7 @@ static int old_codec23(SANMVideoContext *ctx, GetByteContext *gb, int top, int l · 124 unmodified lines
805 if (bytestream2_get_bytes_left(gb) < 1)807 if (bytestream2_get_bytes_left(gb) < 1)
806 return 0; /* some c23 frames just set up the LUT */808 return 0; /* some c23 frames just set up the LUT */
807 809
808 dst = (uint8_t *)ctx->frm0;810 dst = (uint8_t *)ctx->fbuf;
809 for (i = 0; i < height; i++) {811 for (i = 0; i < height; i++) {
810 if (bytestream2_get_bytes_left(gb) < 2)812 if (bytestream2_get_bytes_left(gb) < 2)
811 return 0;813 return 0;
@@ -840,10 +842,10 @@ static int old_codec21(SANMVideoContext *ctx, GetByteContext *gb, int top, int l · 28 unmodified lines
840 int width, int height)842 int width, int height)
841{843{
842 const uint32_t maxpxo = ctx->height * ctx->pitch;844 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;
844 int i, j, k, pc, sk, pxoff;846 int i, j, k, pc, sk, pxoff;
845 847
846 dst = (uint8_t *)ctx->frm0;848 dst = (uint8_t *)ctx->fbuf;
847 for (i = 0; i < height; i++) {849 for (i = 0; i < height; i++) {
848 if (bytestream2_get_bytes_left(gb) < 2)850 if (bytestream2_get_bytes_left(gb) < 2)
849 return 0;851 return 0;
@@ -884,7 +886,7 @@ static int old_codec1(SANMVideoContext *ctx, GetByteContext *gb, int top, · 34 unmodified lines
884{886{
885 int i, j, len, flag, code, val, end, pxoff;887 int i, j, len, flag, code, val, end, pxoff;
886 const int maxpxo = ctx->height * ctx->pitch;888 const int maxpxo = ctx->height * ctx->pitch;
887 uint8_t *dst = (uint8_t *)ctx->frm0;889 uint8_t *dst = (uint8_t *)ctx->fbuf;
888 890
889 for (i = 0; i < height; i++) {891 for (i = 0; i < height; i++) {
890 if (bytestream2_get_bytes_left(gb) < 2)892 if (bytestream2_get_bytes_left(gb) < 2)
@@ -932,7 +934,7 @@ static int old_codec1(SANMVideoContext *ctx, GetByteContext *gb, int top, · 41 unmodified lines
932static int old_codec2(SANMVideoContext *ctx, GetByteContext *gb, int top,934static int old_codec2(SANMVideoContext *ctx, GetByteContext *gb, int top,
933 int left, int width, int height)935 int left, int width, int height)
934{936{
935 uint8_t *dst = (uint8_t *)ctx->frm0, col;937 uint8_t *dst = (uint8_t *)ctx->fbuf, col;
936 int16_t xpos = left, ypos = top;938 int16_t xpos = left, ypos = top;
937 939
938 while (bytestream2_get_bytes_left(gb) > 3) {940 while (bytestream2_get_bytes_left(gb) > 3) {
@@ -949,7 +951,7 @@ static int old_codec2(SANMVideoContext *ctx, GetByteContext *gb, int top, · 10 unmodified lines
949 951
950static int old_codec20(SANMVideoContext *ctx, int w, int h)952static int old_codec20(SANMVideoContext *ctx, int w, int h)
951{953{
952 uint8_t *dst = (uint8_t *)ctx->frm0;954 uint8_t *dst = (uint8_t *)ctx->fbuf;
953 955
954 if (bytestream2_get_bytes_left(&ctx->gb) < w * h)956 if (bytestream2_get_bytes_left(&ctx->gb) < w * h)
955 return AVERROR_INVALIDDATA;957 return AVERROR_INVALIDDATA;
@@ -1008,10 +1010,10 @@ static int old_codec37(SANMVideoContext *ctx, int width, int height) · 52 unmodified lines
1008 ctx->rotate_code = 0;1010 ctx->rotate_code = 0;
1009 1011
1010 if (((seq & 1) || !(flags & 1)) && (compr && compr != 2)) {1012 if (((seq & 1) || !(flags & 1)) && (compr && compr != 2)) {
1011 FFSWAP(uint16_t*, ctx->frm1, ctx->frm2);1013 FFSWAP(uint16_t*, ctx->frm0, ctx->frm2);
1012 }1014 }
1013 1015
1014 dst = ((uint8_t*)ctx->frm1);1016 dst = ((uint8_t*)ctx->frm0);
1015 prev = ((uint8_t*)ctx->frm2);1017 prev = ((uint8_t*)ctx->frm2);
1016 1018
1017 if (mvoff > 2) {1019 if (mvoff > 2) {
@@ -1145,7 +1147,6 @@ static int old_codec37(SANMVideoContext *ctx, int width, int height) · 127 unmodified lines
1145 return AVERROR_PATCHWELCOME;1147 return AVERROR_PATCHWELCOME;
1146 }1148 }
1147 1149
1148 memcpy(ctx->frm0, ctx->frm1, ctx->buf_size);
1149 return 0;1150 return 0;
1150}1151}
1151 1152
@@ -1603,7 +1604,7 @@ static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb) · 451 unmodified lines
1603 uint16_t w, h, parm2;1604 uint16_t w, h, parm2;
1604 uint8_t codec, param;1605 uint8_t codec, param;
1605 int16_t left, top;1606 int16_t left, top;
1606 int fsc, sote;1607 int fsc, sote, ret;
1607 1608
1608 codec = bytestream2_get_byteu(gb);1609 codec = bytestream2_get_byteu(gb);
1609 param = bytestream2_get_byteu(gb);1610 param = bytestream2_get_byteu(gb);
@@ -1686,13 +1687,11 @@ static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb) · 76 unmodified lines
1686 }1687 }
1687 }1688 }
1688 1689
1689 /* on first FOBJ, when the codec is not one of the1690 /* clear the main buffer on the first fob */
1690 * full-buffer codecs (37/47/48), frm0 needs to be cleared.
1691 */
1692 if (ctx->first_fob) {1691 if (ctx->first_fob) {
1693 ctx->first_fob = 0;1692 ctx->first_fob = 0;
1694 if (!fsc)1693 if (!fsc)
1695 memset(ctx->frm0, 0, ctx->frm0_size);1694 memset(ctx->fbuf, 0, ctx->frm0_size);
1696 }1695 }
1697 1696
1698 switch (codec) {1697 switch (codec) {
@@ -1713,18 +1712,38 @@ static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb) · 14 unmodified lines
1713 case 23:1712 case 23:
1714 return old_codec23(ctx, gb, top, left, w, h, param, parm2);1713 return old_codec23(ctx, gb, top, left, w, h, param, parm2);
1715 case 37:1714 case 37:
1716 return old_codec37(ctx, w, h);1715 ret = old_codec37(ctx, w, h); break;
1717 case 45:1716 case 45:
1718 return 0;1717 return 0;
1719 case 47:1718 case 47:
1720 return old_codec47(ctx, w, h);1719 ret = old_codec47(ctx, w, h); break;
1721 case 48:1720 case 48:
1722 return old_codec48(ctx, w, h);1721 ret = old_codec48(ctx, w, h); break;
1723 default:1722 default:
1724 avpriv_request_sample(ctx->avctx, "Subcodec %d", codec);1723 avpriv_request_sample(ctx->avctx, "Subcodec %d", codec);
1725 ctx->frame->flags |= AV_FRAME_FLAG_CORRUPT;1724 ctx->frame->flags |= AV_FRAME_FLAG_CORRUPT;
1726 return 0;1725 return 0;
1727 }1726 }
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;
1728}1747}
1729 1748
1730static int process_ftch(SANMVideoContext *ctx, int size)1749static 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
2196static int copy_output(SANMVideoContext *ctx, SANMFrameHeader *hdr)2215static int copy_output(SANMVideoContext *ctx, SANMFrameHeader *hdr)
2197{2216{
2198 uint8_t *dst;2217 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;
2200 int ret, height = ctx->height;2219 int ret, height = ctx->height;
2201 ptrdiff_t dstpitch, srcpitch = ctx->pitch * (hdr ? sizeof(ctx->frm0[0]) : 1);2220 ptrdiff_t dstpitch, srcpitch = ctx->pitch * (hdr ? sizeof(ctx->frm0[0]) : 1);
2202 2221
@@ -2279,7 +2298,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, · 76 unmodified lines
2279 ret = AVERROR(ENOMEM);2298 ret = AVERROR(ENOMEM);
2280 }2299 }
2281 } else {2300 } else {
2282 memcpy(ctx->stored_frame, ctx->frm0, ctx->buf_size);2301 memcpy(ctx->stored_frame, ctx->fbuf, ctx->buf_size);
2283 }2302 }
2284 }2303 }
2285 break;2304 break;
@@ -2295,7 +2314,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, · 9 unmodified lines
2295 if (ret = process_ftch(ctx, size))2314 if (ret = process_ftch(ctx, size))
2296 return ret;2315 return ret;
2297 } else {2316 } else {
2298 memcpy(ctx->frm0, ctx->stored_frame, ctx->buf_size);2317 memcpy(ctx->fbuf, ctx->stored_frame, ctx->buf_size);
2299 }2318 }
2300 have_img = 1;2319 have_img = 1;
2301 break;2320 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