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.
Unified · Split
| @@ -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 | ||
| 454 | static void destroy_buffers(SANMVideoContext *ctx) | 454 | static 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 | ||
| 467 | static av_cold int init_buffers(SANMVideoContext *ctx) | 468 | static 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 | |||
| 932 | static int old_codec2(SANMVideoContext *ctx, GetByteContext *gb, int top, | 934 | static 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 | ||
| 950 | static int old_codec20(SANMVideoContext *ctx, int w, int h) | 952 | static 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 the | 1690 | /* 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 | ||
| 1730 | static int process_ftch(SANMVideoContext *ctx, int size) | 1749 | 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 | |||
| 2196 | static int copy_output(SANMVideoContext *ctx, SANMFrameHeader *hdr) | 2215 | static 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; |