| @@ -1613,14 +1613,17 @@ static av_cold int TX_NAME(ff_tx_rdft_init)(AVTXContext *s, · 1612 unmodified lines |
| 1613 | int ret; | 1613 | int ret; |
| 1614 | double f, m; | 1614 | double f, m; |
| 1615 | TXSample *tab; | 1615 | TXSample *tab; |
| | 1616 | int len4 = FFALIGN(len, 4) / 4; |
| 1616 | | 1617 | |
| 1617 | s->scale_d = *((SCALE_TYPE *)scale); | 1618 | s->scale_d = *((SCALE_TYPE *)scale); |
| 1618 | s->scale_f = s->scale_d; | 1619 | s->scale_f = s->scale_d; |
| 1619 | | 1620 | |
| | 1621 | flags &= ~(AV_TX_REAL_TO_REAL | AV_TX_REAL_TO_IMAGINARY); |
| | 1622 | |
| 1620 | if ((ret = ff_tx_init_subtx(s, TX_TYPE(FFT), flags, NULL, len >> 1, inv, scale))) | 1623 | if ((ret = ff_tx_init_subtx(s, TX_TYPE(FFT), flags, NULL, len >> 1, inv, scale))) |
| 1621 | return ret; | 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 | return AVERROR(ENOMEM); | 1627 | return AVERROR(ENOMEM); |
| 1625 | | 1628 | |
| 1626 | tab = (TXSample *)s->exp; | 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 | *tab++ = RESCALE( (0.5 - inv) * m); | 1642 | *tab++ = RESCALE( (0.5 - inv) * m); |
| 1640 | *tab++ = RESCALE(-(0.5 - inv) * m); | 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 | *tab++ = RESCALE(cos(i*f)); | 1646 | *tab++ = RESCALE(cos(i*f)); |
| 1644 | for (int i = len >> 2; i >= 0; i--) | 1647 | |
| 1645 | *tab++ = RESCALE(cos(i*f) * (inv ? +1.0 : -1.0)); | 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 | return 0; | 1653 | return 0; |
| 1648 | } | 1654 | } |
| 1649 | | 1655 | |
| 1650 | #define DECL_RDFT(name, inv) \ | 1656 | #define DECL_RDFT(n, inv) \ |
| 1651 | static void TX_NAME(ff_tx_rdft_ ##name)(AVTXContext *s, void *_dst, \ | 1657 | static void TX_NAME(ff_tx_rdft_ ##n)(AVTXContext *s, void *_dst, \ |
| 1652 | void *_src, ptrdiff_t stride) \ | 1658 | void *_src, ptrdiff_t stride) \ |
| 1653 | { \ | 1659 | { \ |
| 1654 | const int len2 = s->len >> 1; \ | 1660 | const int len2 = s->len >> 1; \ |
| 1655 | const int len4 = s->len >> 2; \ | 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 | data[len2].re = data[0].im; \ | 1704 | data[len2].re = data[0].im; \ |
| 1699 | data[ 0].im = data[len2].im = 0; \ | 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) | 1724 | DECL_RDFT(r2c, 0) |
| 1704 | DECL_RDFT(c2r, 1) | 1725 | DECL_RDFT(c2r, 1) |
| 1705 | | 1726 | |
| 1706 | static const FFTXCodelet TX_NAME(ff_tx_rdft_r2c_def) = { | 1727 | #define DECL_RDFT_HALF(n, mode, mod2) \ |
| 1707 | .name = TX_NAME_STR("rdft_r2c"), | 1728 | static void TX_NAME(ff_tx_rdft_ ##n)(AVTXContext *s, void *_dst, \ |
| 1708 | .function = TX_NAME(ff_tx_rdft_r2c), | 1729 | void *_src, ptrdiff_t stride) \ |
| 1709 | .type = TX_TYPE(RDFT), | 1730 | { \ |
| 1710 | .flags = AV_TX_UNALIGNED | AV_TX_INPLACE | | 1731 | const int len = s->len; \ |
| 1711 | FF_TX_OUT_OF_PLACE | FF_TX_FORWARD_ONLY, | 1732 | const int len2 = len >> 1; \ |
| 1712 | .factors = { 2, TX_FACTOR_ANY }, | 1733 | const int len4 = len >> 2; \ |
| 1713 | .nb_factors = 2, | 1734 | const int aligned_len4 = FFALIGN(len, 4)/4; \ |
| 1714 | .min_len = 2, | 1735 | const TXSample *fact = (void *)s->exp; \ |
| 1715 | .max_len = TX_LEN_UNLIMITED, | 1736 | const TXSample *tcos = fact + 8; \ |
| 1716 | .init = TX_NAME(ff_tx_rdft_init), | 1737 | const TXSample *tsin = tcos + aligned_len4; \ |
| 1717 | .cpu_flags = FF_TX_CPU_FLAGS_ALL, | 1738 | TXComplex *data = _dst; \ |
| 1718 | .prio = FF_TX_PRIO_BASE, | 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) = { | 1828 | DECL_RDFT_HALF(r2r, AV_TX_REAL_TO_REAL, 0) |
| 1722 | .name = TX_NAME_STR("rdft_c2r"), | 1829 | DECL_RDFT_HALF(r2r_mod2, AV_TX_REAL_TO_REAL, 1) |
| 1723 | .function = TX_NAME(ff_tx_rdft_c2r), | 1830 | DECL_RDFT_HALF(r2i, AV_TX_REAL_TO_IMAGINARY, 0) |
| 1724 | .type = TX_TYPE(RDFT), | 1831 | DECL_RDFT_HALF(r2i_mod2, AV_TX_REAL_TO_IMAGINARY, 1) |
| 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 | }; | | |
| 1735 | | 1832 | |
| 1736 | static av_cold int TX_NAME(ff_tx_dct_init)(AVTXContext *s, | 1833 | static av_cold int TX_NAME(ff_tx_dct_init)(AVTXContext *s, |
| 1737 | const FFTXCodelet *cd, | 1834 | const FFTXCodelet *cd, |
| @@ -1997,6 +2094,10 @@ const FFTXCodelet * const TX_NAME(ff_tx_codelet_list)[] = { · 259 unmodified lines |
| 1997 | &TX_NAME(ff_tx_mdct_naive_inv_def), | 2094 | &TX_NAME(ff_tx_mdct_naive_inv_def), |
| 1998 | &TX_NAME(ff_tx_mdct_inv_full_def), | 2095 | &TX_NAME(ff_tx_mdct_inv_full_def), |
| 1999 | &TX_NAME(ff_tx_rdft_r2c_def), | 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 | &TX_NAME(ff_tx_rdft_c2r_def), | 2101 | &TX_NAME(ff_tx_rdft_c2r_def), |
| 2001 | &TX_NAME(ff_tx_dctII_def), | 2102 | &TX_NAME(ff_tx_dctII_def), |
| 2002 | &TX_NAME(ff_tx_dctIII_def), | 2103 | &TX_NAME(ff_tx_dctIII_def), |