Change the size detection a bit to recognize common video sizes, as the FOBJ codecs>=37 cannot always be trusted, since they can be embedded in a larger frame.
Unified · Split
| @@ -1603,6 +1603,7 @@ static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb) · 1602 unmodified lines | ||
| 1603 | 1603 | uint16_t w, h, parm2; |
| 1604 | 1604 | uint8_t codec, param; |
| 1605 | 1605 | int16_t left, top; |
| 1606 | + int fsc, sote; | |
| 1606 | 1607 | |
| 1607 | 1608 | codec = bytestream2_get_byteu(gb); |
| 1608 | 1609 | param = bytestream2_get_byteu(gb); |
| @@ -1620,6 +1621,14 @@ static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb) · 11 unmodified lines | ||
| 1620 | 1621 | return 0; |
| 1621 | 1622 | } |
| 1622 | 1623 | |
| 1624 | + /* codecs with their own buffers */ | |
| 1625 | + fsc = (codec == 37 || codec == 47 || codec == 48); | |
| 1626 | + | |
| 1627 | + /* special case for "Shadows of the Empire" videos */ | |
| 1628 | + sote = ((w == 640) && (h == 272) && (codec == 47)); | |
| 1629 | + if (sote) | |
| 1630 | + left = top = 0; | |
| 1631 | + | |
| 1623 | 1632 | if (!ctx->have_dimensions) { |
| 1624 | 1633 | int xres, yres; |
| 1625 | 1634 | if (ctx->subversion < 2) { |
| @@ -1633,12 +1642,24 @@ static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb) · 7 unmodified lines | ||
| 1633 | 1642 | yres = h; |
| 1634 | 1643 | ctx->have_dimensions = 1; |
| 1635 | 1644 | } else { |
| 1636 | − /* Rebel Assault 2: 424x260 internal size */ | |
| 1637 | − if (((left + w) == 424) && ((top + h) == 260)) | |
| 1645 | + /* detect common sizes */ | |
| 1646 | + xres = w + left; | |
| 1647 | + yres = h + top; | |
| 1648 | + if (sote) { | |
| 1649 | + /* SotE: has top=60 at all times to center video | |
| 1650 | + * inside the 640x480 game window | |
| 1651 | + */ | |
| 1652 | + xres = w; | |
| 1653 | + yres = h; | |
| 1638 | 1654 | ctx->have_dimensions = 1; |
| 1655 | + } else if (((xres == 424) && (yres == 260)) || /* RA1 */ | |
| 1656 | + ((xres == 320) && (yres == 200)) || /* ft/dig/... */ | |
| 1657 | + ((xres == 640) && (yres == 480))) { /* ol/comi/mots... */ | |
| 1658 | + ctx->have_dimensions = 1; | |
| 1659 | + } | |
| 1639 | 1660 | |
| 1640 | − xres = FFMAX(left + w, ctx->width); | |
| 1641 | − yres = FFMAX(top + h, ctx->height); | |
| 1661 | + xres = FFMAX(xres, ctx->width); | |
| 1662 | + yres = FFMAX(yres, ctx->height); | |
| 1642 | 1663 | } |
| 1643 | 1664 | |
| 1644 | 1665 | if (ctx->width < xres || ctx->height < yres) { |
| @@ -1652,8 +1673,7 @@ static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb) · 7 unmodified lines | ||
| 1652 | 1673 | } |
| 1653 | 1674 | } |
| 1654 | 1675 | } else { |
| 1655 | − if (((left + w > ctx->width) || (top + h > ctx->height)) | |
| 1656 | − && (codec >= 37)) { | |
| 1676 | + if (((left + w > ctx->width) || (top + h > ctx->height)) && fsc) { | |
| 1657 | 1677 | /* correct unexpected overly large frames: this happens |
| 1658 | 1678 | * for instance with The Dig's sq1.san video: it has a few |
| 1659 | 1679 | * (all black) 640x480 frames halfway in, while the rest is |
| @@ -1671,7 +1691,7 @@ static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb) · 11 unmodified lines | ||
| 1671 | 1691 | */ |
| 1672 | 1692 | if (ctx->first_fob) { |
| 1673 | 1693 | ctx->first_fob = 0; |
| 1674 | − if (codec < 37) | |
| 1694 | + if (!fsc) | |
| 1675 | 1695 | memset(ctx->frm0, 0, ctx->frm0_size); |
| 1676 | 1696 | } |
| 1677 | 1697 | |