| @@ -1613,14 +1613,17 @@ static av_cold int TX_NAME(ff_tx_rdft_init)(AVTXContext *s, · 1612 unmodified lines |
| 1613 | 1613 | int ret; |
| 1614 | 1614 | double f, m; |
| 1615 | 1615 | TXSample *tab; |
| 1616 | + int len4 = FFALIGN(len, 4) / 4; |
| 1616 | 1617 | |
| 1617 | 1618 | s->scale_d = *((SCALE_TYPE *)scale); |
| 1618 | 1619 | s->scale_f = s->scale_d; |
| 1619 | 1620 | |
| 1621 | + flags &= ~(AV_TX_REAL_TO_REAL | AV_TX_REAL_TO_IMAGINARY); |
| 1622 | + |
| 1620 | 1623 | if ((ret = ff_tx_init_subtx(s, TX_TYPE(FFT), flags, NULL, len >> 1, inv, scale))) |
| 1621 | 1624 | return ret; |
| 1622 | 1625 | |
| 1623 | | − if (!(s->exp = av_mallocz((8 + (len >> 2) - 1)*sizeof(*s->exp)))) |
| 1626 | + if (!(s->exp = av_mallocz((8 + 2*len4)*sizeof(*s->exp)))) |
| 1624 | 1627 | return AVERROR(ENOMEM); |
| 1625 | 1628 | |
| 1626 | 1629 | tab = (TXSample *)s->exp; |
| @@ -1639,17 +1642,20 @@ static av_cold int TX_NAME(ff_tx_rdft_init)(AVTXContext *s, · 12 unmodified lines |
| 1639 | 1642 | *tab++ = RESCALE( (0.5 - inv) * m); |
| 1640 | 1643 | *tab++ = RESCALE(-(0.5 - inv) * m); |
| 1641 | 1644 | |
| 1642 | | − for (int i = 0; i < len >> 2; i++) |
| 1645 | + for (int i = 0; i < len4; i++) |
| 1643 | 1646 | *tab++ = RESCALE(cos(i*f)); |
| 1644 | | − for (int i = len >> 2; i >= 0; i--) |
| 1645 | | − *tab++ = RESCALE(cos(i*f) * (inv ? +1.0 : -1.0)); |
| 1647 | + |
| 1648 | + tab = ((TXSample *)s->exp) + len4 + 8; |
| 1649 | + |
| 1650 | + for (int i = 0; i < len4; i++) |
| 1651 | + *tab++ = RESCALE(cos(((float)len/4.0 - (float)i + 0)*f) * (inv ? +1.0 : -1.0)); |
| 1646 | 1652 | |
| 1647 | 1653 | return 0; |
| 1648 | 1654 | } |
| 1649 | 1655 | |
| 1650 | | −#define DECL_RDFT(name, inv) \ |
| 1651 | | −static void TX_NAME(ff_tx_rdft_ ##name)(AVTXContext *s, void *_dst, \ |
| 1652 | | − void *_src, ptrdiff_t stride) \ |
| 1656 | +#define DECL_RDFT(n, inv) \ |
| 1657 | +static void TX_NAME(ff_tx_rdft_ ##n)(AVTXContext *s, void *_dst, \ |
| 1658 | + void *_src, ptrdiff_t stride) \ |
| 1653 | 1659 | { \ |
| 1654 | 1660 | const int len2 = s->len >> 1; \ |
| 1655 | 1661 | const int len4 = s->len >> 2; \ |
| @@ -1698,40 +1704,131 @@ static void TX_NAME(ff_tx_rdft_ ##name)(AVTXContext *s, void *_dst, \ · 42 unmodified lines |
| 1698 | 1704 | data[len2].re = data[0].im; \ |
| 1699 | 1705 | data[ 0].im = data[len2].im = 0; \ |
| 1700 | 1706 | } \ |
| 1701 | | −} |
| 1707 | +} \ |
| 1708 | + \ |
| 1709 | +static const FFTXCodelet TX_NAME(ff_tx_rdft_ ##n## _def) = { \ |
| 1710 | + .name = TX_NAME_STR("rdft_" #n), \ |
| 1711 | + .function = TX_NAME(ff_tx_rdft_ ##n), \ |
| 1712 | + .type = TX_TYPE(RDFT), \ |
| 1713 | + .flags = AV_TX_UNALIGNED | AV_TX_INPLACE | FF_TX_OUT_OF_PLACE | \ |
| 1714 | + (inv ? FF_TX_INVERSE_ONLY : FF_TX_FORWARD_ONLY), \ |
| 1715 | + .factors = { 4, TX_FACTOR_ANY }, \ |
| 1716 | + .nb_factors = 2, \ |
| 1717 | + .min_len = 4, \ |
| 1718 | + .max_len = TX_LEN_UNLIMITED, \ |
| 1719 | + .init = TX_NAME(ff_tx_rdft_init), \ |
| 1720 | + .cpu_flags = FF_TX_CPU_FLAGS_ALL, \ |
| 1721 | + .prio = FF_TX_PRIO_BASE, \ |
| 1722 | +}; |
| 1702 | 1723 | |
| 1703 | | −DECL_RDFT(r2c, 0) |
| 1704 | | −DECL_RDFT(c2r, 1) |
| 1724 | +DECL_RDFT(r2c, 0) |
| 1725 | +DECL_RDFT(c2r, 1) |
| 1705 | 1726 | |
| 1706 | | −static const FFTXCodelet TX_NAME(ff_tx_rdft_r2c_def) = { |
| 1707 | | − .name = TX_NAME_STR("rdft_r2c"), |
| 1708 | | − .function = TX_NAME(ff_tx_rdft_r2c), |
| 1709 | | − .type = TX_TYPE(RDFT), |
| 1710 | | − .flags = AV_TX_UNALIGNED | AV_TX_INPLACE | |
| 1711 | | − FF_TX_OUT_OF_PLACE | FF_TX_FORWARD_ONLY, |
| 1712 | | − .factors = { 2, TX_FACTOR_ANY }, |
| 1713 | | − .nb_factors = 2, |
| 1714 | | − .min_len = 2, |
| 1715 | | − .max_len = TX_LEN_UNLIMITED, |
| 1716 | | − .init = TX_NAME(ff_tx_rdft_init), |
| 1717 | | − .cpu_flags = FF_TX_CPU_FLAGS_ALL, |
| 1718 | | − .prio = FF_TX_PRIO_BASE, |
| 1727 | +#define DECL_RDFT_HALF(n, mode, mod2) \ |
| 1728 | +static void TX_NAME(ff_tx_rdft_ ##n)(AVTXContext *s, void *_dst, \ |
| 1729 | + void *_src, ptrdiff_t stride) \ |
| 1730 | +{ \ |
| 1731 | + const int len = s->len; \ |
| 1732 | + const int len2 = len >> 1; \ |
| 1733 | + const int len4 = len >> 2; \ |
| 1734 | + const int aligned_len4 = FFALIGN(len, 4)/4; \ |
| 1735 | + const TXSample *fact = (void *)s->exp; \ |
| 1736 | + const TXSample *tcos = fact + 8; \ |
| 1737 | + const TXSample *tsin = tcos + aligned_len4; \ |
| 1738 | + TXComplex *data = _dst; \ |
| 1739 | + TXSample *out = _dst; /* Half-complex is forward-only */ \ |
| 1740 | + TXSample tmp_dc; \ |
| 1741 | + av_unused TXSample tmp_mid; \ |
| 1742 | + TXSample tmp[4]; \ |
| 1743 | + TXComplex sf, sl; \ |
| 1744 | + \ |
| 1745 | + s->fn[0](&s->sub[0], _dst, _src, sizeof(TXComplex)); \ |
| 1746 | + \ |
| 1747 | + tmp_dc = data[0].re; \ |
| 1748 | + data[ 0].re = tmp_dc + data[0].im; \ |
| 1749 | + tmp_dc = tmp_dc - data[0].im; \ |
| 1750 | + \ |
| 1751 | + data[ 0].re = MULT(fact[0], data[ 0].re); \ |
| 1752 | + tmp_dc = MULT(fact[1], tmp_dc); \ |
| 1753 | + data[len4].re = MULT(fact[2], data[len4].re); \ |
| 1754 | + \ |
| 1755 | + if (!mod2) { \ |
| 1756 | + data[len4].im = MULT(fact[3], data[len4].im); \ |
| 1757 | + } else { \ |
| 1758 | + sf = data[len4]; \ |
| 1759 | + sl = data[len4 + 1]; \ |
| 1760 | + if (mode == AV_TX_REAL_TO_REAL) \ |
| 1761 | + tmp[0] = MULT(fact[4], (sf.re + sl.re)); \ |
| 1762 | + else \ |
| 1763 | + tmp[0] = MULT(fact[5], (sf.im - sl.im)); \ |
| 1764 | + tmp[1] = MULT(fact[6], (sf.im + sl.im)); \ |
| 1765 | + tmp[2] = MULT(fact[7], (sf.re - sl.re)); \ |
| 1766 | + \ |
| 1767 | + if (mode == AV_TX_REAL_TO_REAL) { \ |
| 1768 | + tmp[3] = tmp[1]*tcos[len4] - tmp[2]*tsin[len4]; \ |
| 1769 | + tmp_mid = (tmp[0] - tmp[3]); \ |
| 1770 | + } else { \ |
| 1771 | + tmp[3] = tmp[1]*tsin[len4] + tmp[2]*tcos[len4]; \ |
| 1772 | + tmp_mid = (tmp[0] + tmp[3]); \ |
| 1773 | + } \ |
| 1774 | + } \ |
| 1775 | + \ |
| 1776 | + /* NOTE: unrolling this breaks non-mod8 lengths */ \ |
| 1777 | + for (int i = 1; i <= len4; i++) { \ |
| 1778 | + TXSample tmp[4]; \ |
| 1779 | + TXComplex sf = data[i]; \ |
| 1780 | + TXComplex sl = data[len2 - i]; \ |
| 1781 | + \ |
| 1782 | + if (mode == AV_TX_REAL_TO_REAL) \ |
| 1783 | + tmp[0] = MULT(fact[4], (sf.re + sl.re)); \ |
| 1784 | + else \ |
| 1785 | + tmp[0] = MULT(fact[5], (sf.im - sl.im)); \ |
| 1786 | + \ |
| 1787 | + tmp[1] = MULT(fact[6], (sf.im + sl.im)); \ |
| 1788 | + tmp[2] = MULT(fact[7], (sf.re - sl.re)); \ |
| 1789 | + \ |
| 1790 | + if (mode == AV_TX_REAL_TO_REAL) { \ |
| 1791 | + tmp[3] = tmp[1]*tcos[i] - tmp[2]*tsin[i]; \ |
| 1792 | + out[i] = (tmp[0] + tmp[3]); \ |
| 1793 | + out[len - i] = (tmp[0] - tmp[3]); \ |
| 1794 | + } else { \ |
| 1795 | + tmp[3] = tmp[1]*tsin[i] + tmp[2]*tcos[i]; \ |
| 1796 | + out[i - 1] = (tmp[3] - tmp[0]); \ |
| 1797 | + out[len - i - 1] = (tmp[0] + tmp[3]); \ |
| 1798 | + } \ |
| 1799 | + } \ |
| 1800 | + \ |
| 1801 | + for (int i = 1; i < (len4 + (mode == AV_TX_REAL_TO_IMAGINARY)); i++) \ |
| 1802 | + out[len2 - i] = out[len - i]; \ |
| 1803 | + \ |
| 1804 | + if (mode == AV_TX_REAL_TO_REAL) { \ |
| 1805 | + out[len2] = tmp_dc; \ |
| 1806 | + if (mod2) \ |
| 1807 | + out[len4 + 1] = tmp_mid; \ |
| 1808 | + } else if (mod2) { \ |
| 1809 | + out[len4] = tmp_mid; \ |
| 1810 | + } \ |
| 1811 | +} \ |
| 1812 | + \ |
| 1813 | +static const FFTXCodelet TX_NAME(ff_tx_rdft_ ##n## _def) = { \ |
| 1814 | + .name = TX_NAME_STR("rdft_" #n), \ |
| 1815 | + .function = TX_NAME(ff_tx_rdft_ ##n), \ |
| 1816 | + .type = TX_TYPE(RDFT), \ |
| 1817 | + .flags = AV_TX_UNALIGNED | AV_TX_INPLACE | mode | \ |
| 1818 | + FF_TX_OUT_OF_PLACE | FF_TX_FORWARD_ONLY, \ |
| 1819 | + .factors = { 2 + 2*(!mod2), TX_FACTOR_ANY }, \ |
| 1820 | + .nb_factors = 2, \ |
| 1821 | + .min_len = 2 + 2*(!mod2), \ |
| 1822 | + .max_len = TX_LEN_UNLIMITED, \ |
| 1823 | + .init = TX_NAME(ff_tx_rdft_init), \ |
| 1824 | + .cpu_flags = FF_TX_CPU_FLAGS_ALL, \ |
| 1825 | + .prio = FF_TX_PRIO_BASE, \ |
| 1719 | 1826 | }; |
| 1720 | 1827 | |
| 1721 | | −static const FFTXCodelet TX_NAME(ff_tx_rdft_c2r_def) = { |
| 1722 | | − .name = TX_NAME_STR("rdft_c2r"), |
| 1723 | | − .function = TX_NAME(ff_tx_rdft_c2r), |
| 1724 | | − .type = TX_TYPE(RDFT), |
| 1725 | | − .flags = AV_TX_UNALIGNED | AV_TX_INPLACE | |
| 1726 | | − FF_TX_OUT_OF_PLACE | FF_TX_INVERSE_ONLY, |
| 1727 | | − .factors = { 2, TX_FACTOR_ANY }, |
| 1728 | | − .nb_factors = 2, |
| 1729 | | − .min_len = 2, |
| 1730 | | − .max_len = TX_LEN_UNLIMITED, |
| 1731 | | − .init = TX_NAME(ff_tx_rdft_init), |
| 1732 | | − .cpu_flags = FF_TX_CPU_FLAGS_ALL, |
| 1733 | | − .prio = FF_TX_PRIO_BASE, |
| 1734 | | −}; |
| 1828 | +DECL_RDFT_HALF(r2r, AV_TX_REAL_TO_REAL, 0) |
| 1829 | +DECL_RDFT_HALF(r2r_mod2, AV_TX_REAL_TO_REAL, 1) |
| 1830 | +DECL_RDFT_HALF(r2i, AV_TX_REAL_TO_IMAGINARY, 0) |
| 1831 | +DECL_RDFT_HALF(r2i_mod2, AV_TX_REAL_TO_IMAGINARY, 1) |
| 1735 | 1832 | |
| 1736 | 1833 | static av_cold int TX_NAME(ff_tx_dct_init)(AVTXContext *s, |
| 1737 | 1834 | const FFTXCodelet *cd, |
| @@ -1997,6 +2094,10 @@ const FFTXCodelet * const TX_NAME(ff_tx_codelet_list)[] = { · 259 unmodified lines |
| 1997 | 2094 | &TX_NAME(ff_tx_mdct_naive_inv_def), |
| 1998 | 2095 | &TX_NAME(ff_tx_mdct_inv_full_def), |
| 1999 | 2096 | &TX_NAME(ff_tx_rdft_r2c_def), |
| 2097 | + &TX_NAME(ff_tx_rdft_r2r_def), |
| 2098 | + &TX_NAME(ff_tx_rdft_r2r_mod2_def), |
| 2099 | + &TX_NAME(ff_tx_rdft_r2i_def), |
| 2100 | + &TX_NAME(ff_tx_rdft_r2i_mod2_def), |
| 2000 | 2101 | &TX_NAME(ff_tx_rdft_c2r_def), |
| 2001 | 2102 | &TX_NAME(ff_tx_dctII_def), |
| 2002 | 2103 | &TX_NAME(ff_tx_dctIII_def), |