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.
Showing the changes to libavcodec (1 of 1 file). Show all
Unified · Split
| @@ -274,9 +274,9 @@ typedef struct SANMVideoContext { · 273 unmodified lines | ||
| 274 | 274 | int prev_seq; |
| 275 | 275 | |
| 276 | 276 | AVFrame *frame; |
| 277 | − uint16_t *frm0, *frm1, *frm2; | |
| 277 | + uint16_t *fbuf, *frm0, *frm1, *frm2; | |
| 278 | 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 | 280 | uint32_t stored_frame_size; |
| 281 | 281 | |
| 282 | 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 | 454 | static void destroy_buffers(SANMVideoContext *ctx) |
| 455 | 455 | { |
| 456 | + av_freep(&ctx->fbuf); | |
| 456 | 457 | av_freep(&ctx->frm0); |
| 457 | 458 | av_freep(&ctx->frm1); |
| 458 | 459 | av_freep(&ctx->frm2); |
| @@ -466,6 +467,7 @@ static void destroy_buffers(SANMVideoContext *ctx) · 7 unmodified lines | ||
| 466 | 467 | |
| 467 | 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 | 471 | av_fast_padded_mallocz(&ctx->frm0, &ctx->frm0_size, ctx->buf_size); |
| 470 | 472 | av_fast_padded_mallocz(&ctx->frm1, &ctx->frm1_size, ctx->buf_size); |
| 471 | 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 | 677 | const uint16_t p = ctx->pitch; |
| 676 | 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 | 680 | int i, j, k, l, bit, ret; |
| 679 | 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 | 807 | if (bytestream2_get_bytes_left(gb) < 1) |
| 806 | 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 | 811 | for (i = 0; i < height; i++) { |
| 810 | 812 | if (bytestream2_get_bytes_left(gb) < 2) |
| 811 | 813 | return 0; |
| @@ -840,10 +842,10 @@ static int old_codec21(SANMVideoContext *ctx, GetByteContext *gb, int top, int l · 28 unmodified lines | ||
| 840 | 842 | int width, int height) |
| 841 | 843 | { |
| 842 | 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 | 846 | int i, j, k, pc, sk, pxoff; |
| 845 | 847 | |
| 846 | − dst = (uint8_t *)ctx->frm0; | |
| 848 | + dst = (uint8_t *)ctx->fbuf; | |
| 847 | 849 | for (i = 0; i < height; i++) { |
| 848 | 850 | if (bytestream2_get_bytes_left(gb) < 2) |
| 849 | 851 | return 0; |
| @@ -884,7 +886,7 @@ static int old_codec1(SANMVideoContext *ctx, GetByteContext *gb, int top, · 34 unmodified lines | ||
| 884 | 886 | { |
| 885 | 887 | int i, j, len, flag, code, val, end, pxoff; |
| 886 | 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 | 891 | for (i = 0; i < height; i++) { |
| 890 | 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 | 934 | static int old_codec2(SANMVideoContext *ctx, GetByteContext *gb, int top, |
| 933 | 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 | 938 | int16_t xpos = left, ypos = top; |
| 937 | 939 | |
| 938 | 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 | 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 | 956 | if (bytestream2_get_bytes_left(&ctx->gb) < w * h) |
| 955 | 957 | return AVERROR_INVALIDDATA; |
| @@ -1008,10 +1010,10 @@ static int old_codec37(SANMVideoContext *ctx, int width, int height) · 52 unmodified lines | ||
| 1008 | 1010 | ctx->rotate_code = 0; |
| 1009 | 1011 | |
| 1010 | 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 | 1017 | prev = ((uint8_t*)ctx->frm2); |
| 1016 | 1018 | |
| 1017 | 1019 | if (mvoff > 2) { |
| @@ -1145,7 +1147,6 @@ static int old_codec37(SANMVideoContext *ctx, int width, int height) · 127 unmodified lines | ||
| 1145 | 1147 | return AVERROR_PATCHWELCOME; |
| 1146 | 1148 | } |
| 1147 | 1149 | |
| 1148 | − memcpy(ctx->frm0, ctx->frm1, ctx->buf_size); | |
| 1149 | 1150 | return 0; |
| 1150 | 1151 | } |
| 1151 | 1152 | |
| @@ -1603,7 +1604,7 @@ static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb) · 451 unmodified lines | ||
| 1603 | 1604 | uint16_t w, h, parm2; |
| 1604 | 1605 | uint8_t codec, param; |
| 1605 | 1606 | int16_t left, top; |
| 1606 | − int fsc, sote; | |
| 1607 | + int fsc, sote, ret; | |
| 1607 | 1608 | |
| 1608 | 1609 | codec = bytestream2_get_byteu(gb); |
| 1609 | 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 | − * full-buffer codecs (37/47/48), frm0 needs to be cleared. | |
| 1691 | − */ | |
| 1690 | + /* clear the main buffer on the first fob */ | |
| 1692 | 1691 | if (ctx->first_fob) { |
| 1693 | 1692 | ctx->first_fob = 0; |
| 1694 | 1693 | if (!fsc) |
| 1695 | − memset(ctx->frm0, 0, ctx->frm0_size); | |
| 1694 | + memset(ctx->fbuf, 0, ctx->frm0_size); | |
| 1696 | 1695 | } |
| 1697 | 1696 | |
| 1698 | 1697 | switch (codec) { |
| @@ -1713,18 +1712,38 @@ static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb) · 14 unmodified lines | ||
| 1713 | 1712 | case 23: |
| 1714 | 1713 | return old_codec23(ctx, gb, top, left, w, h, param, parm2); |
| 1715 | 1714 | case 37: |
| 1716 | − return old_codec37(ctx, w, h); | |
| 1715 | + ret = old_codec37(ctx, w, h); break; | |
| 1717 | 1716 | case 45: |
| 1718 | 1717 | return 0; |
| 1719 | 1718 | case 47: |
| 1720 | − return old_codec47(ctx, w, h); | |
| 1719 | + ret = old_codec47(ctx, w, h); break; | |
| 1721 | 1720 | case 48: |
| 1722 | − return old_codec48(ctx, w, h); | |
| 1721 | + ret = old_codec48(ctx, w, h); break; | |
| 1723 | 1722 | default: |
| 1724 | 1723 | avpriv_request_sample(ctx->avctx, "Subcodec %d", codec); |
| 1725 | 1724 | ctx->frame->flags |= AV_FRAME_FLAG_CORRUPT; |
| 1726 | 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 | 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 | 2215 | static int copy_output(SANMVideoContext *ctx, SANMFrameHeader *hdr) |
| 2197 | 2216 | { |
| 2198 | 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 | 2219 | int ret, height = ctx->height; |
| 2201 | 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 | 2298 | ret = AVERROR(ENOMEM); |
| 2280 | 2299 | } |
| 2281 | 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 | 2304 | break; |
| @@ -2295,7 +2314,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, · 9 unmodified lines | ||
| 2295 | 2314 | if (ret = process_ftch(ctx, size)) |
| 2296 | 2315 | return ret; |
| 2297 | 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 | 2319 | have_img = 1; |
| 2301 | 2320 | break; |