## ffmpeg / libavcodec / ppc / idct_altivec.c @ 186447f8

History | View | Annotate | Download (8.52 KB)

1 | 05c4072b | Michael Niedermayer | ```
/*
``` |
---|---|---|---|

2 | ```
* Copyright (c) 2001 Michel Lespinasse
``` |
||

3 | ```
*
``` |
||

4 | ```
* This library is free software; you can redistribute it and/or
``` |
||

5 | ```
* modify it under the terms of the GNU Lesser General Public
``` |
||

6 | ```
* License as published by the Free Software Foundation; either
``` |
||

7 | ```
* version 2 of the License, or (at your option) any later version.
``` |
||

8 | ```
*
``` |
||

9 | ```
* This library is distributed in the hope that it will be useful,
``` |
||

10 | ```
* but WITHOUT ANY WARRANTY; without even the implied warranty of
``` |
||

11 | ```
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
``` |
||

12 | ```
* Lesser General Public License for more details.
``` |
||

13 | ```
*
``` |
||

14 | ```
* You should have received a copy of the GNU Lesser General Public
``` |
||

15 | ```
* License along with this library; if not, write to the Free Software
``` |
||

16 | ```
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
``` |
||

17 | ```
*
``` |
||

18 | ```
*/
``` |
||

19 | |||

20 | ```
/*
``` |
||

21 | ```
* NOTE: This code is based on GPL code from the libmpeg2 project. The
``` |
||

22 | ```
* author, Michel Lespinasses, has given explicit permission to release
``` |
||

23 | ```
* under LGPL as part of ffmpeg.
``` |
||

24 | ```
*
``` |
||

25 | ```
*/
``` |
||

26 | |||

27 | ```
/*
``` |
||

28 | ```
* FFMpeg integration by Dieter Shirley
``` |
||

29 | ```
*
``` |
||

30 | ```
* This file is a direct copy of the altivec idct module from the libmpeg2
``` |
||

31 | ```
* project. I've deleted all of the libmpeg2 specific code, renamed the functions and
``` |
||

32 | ```
* re-ordered the function parameters. The only change to the IDCT function
``` |
||

33 | ```
* itself was to factor out the partial transposition, and to perform a full
``` |
||

34 | ```
* transpose at the end of the function.
``` |
||

35 | ```
*/
``` |
||

36 | |||

37 | |||

38 | #include <stdlib.h> /* malloc(), free() */ |
||

39 | #include <string.h> |
||

40 | #include "../dsputil.h" |
||

41 | a9a07762 | Michael Niedermayer | |

42 | #include "gcc_fixes.h" |
||

43 | |||

44 | db40a39a | Michael Niedermayer | #include "dsputil_altivec.h" |

45 | 05c4072b | Michael Niedermayer | |

46 | #define vector_s16_t vector signed short |
||

47 | #define vector_u16_t vector unsigned short |
||

48 | #define vector_s8_t vector signed char |
||

49 | #define vector_u8_t vector unsigned char |
||

50 | #define vector_s32_t vector signed int |
||

51 | #define vector_u32_t vector unsigned int |
||

52 | |||

53 | ```
#define IDCT_HALF \
``` |
||

54 | ```
/* 1st stage */ \
``` |
||

55 | t1 = vec_mradds (a1, vx7, vx1 ); \ |
||

56 | t8 = vec_mradds (a1, vx1, vec_subs (zero, vx7)); \ |
||

57 | t7 = vec_mradds (a2, vx5, vx3); \ |
||

58 | t3 = vec_mradds (ma2, vx3, vx5); \ |
||

59 | \ |
||

60 | ```
/* 2nd stage */ \
``` |
||

61 | t5 = vec_adds (vx0, vx4); \ |
||

62 | t0 = vec_subs (vx0, vx4); \ |
||

63 | t2 = vec_mradds (a0, vx6, vx2); \ |
||

64 | t4 = vec_mradds (a0, vx2, vec_subs (zero, vx6)); \ |
||

65 | t6 = vec_adds (t8, t3); \ |
||

66 | t3 = vec_subs (t8, t3); \ |
||

67 | t8 = vec_subs (t1, t7); \ |
||

68 | t1 = vec_adds (t1, t7); \ |
||

69 | \ |
||

70 | ```
/* 3rd stage */ \
``` |
||

71 | t7 = vec_adds (t5, t2); \ |
||

72 | t2 = vec_subs (t5, t2); \ |
||

73 | t5 = vec_adds (t0, t4); \ |
||

74 | t0 = vec_subs (t0, t4); \ |
||

75 | t4 = vec_subs (t8, t3); \ |
||

76 | t3 = vec_adds (t8, t3); \ |
||

77 | \ |
||

78 | ```
/* 4th stage */ \
``` |
||

79 | vy0 = vec_adds (t7, t1); \ |
||

80 | vy7 = vec_subs (t7, t1); \ |
||

81 | vy1 = vec_mradds (c4, t3, t5); \ |
||

82 | vy6 = vec_mradds (mc4, t3, t5); \ |
||

83 | vy2 = vec_mradds (c4, t4, t0); \ |
||

84 | vy5 = vec_mradds (mc4, t4, t0); \ |
||

85 | vy3 = vec_adds (t2, t6); \ |
||

86 | vy4 = vec_subs (t2, t6); |
||

87 | |||

88 | |||

89 | ```
#define IDCT \
``` |
||

90 | vector_s16_t vx0, vx1, vx2, vx3, vx4, vx5, vx6, vx7; \ |
||

91 | vector_s16_t vy0, vy1, vy2, vy3, vy4, vy5, vy6, vy7; \ |
||

92 | vector_s16_t a0, a1, a2, ma2, c4, mc4, zero, bias; \ |
||

93 | vector_s16_t t0, t1, t2, t3, t4, t5, t6, t7, t8; \ |
||

94 | vector_u16_t shift; \ |
||

95 | \ |
||

96 | c4 = vec_splat (constants[0], 0); \ |
||

97 | a0 = vec_splat (constants[0], 1); \ |
||

98 | a1 = vec_splat (constants[0], 2); \ |
||

99 | a2 = vec_splat (constants[0], 3); \ |
||

100 | mc4 = vec_splat (constants[0], 4); \ |
||

101 | ma2 = vec_splat (constants[0], 5); \ |
||

102 | bias = (vector_s16_t)vec_splat ((vector_s32_t)constants[0], 3); \ |
||

103 | \ |
||

104 | ```
zero = vec_splat_s16 (0); \
``` |
||

105 | ```
shift = vec_splat_u16 (4); \
``` |
||

106 | \ |
||

107 | vx0 = vec_mradds (vec_sl (block[0], shift), constants[1], zero); \ |
||

108 | vx1 = vec_mradds (vec_sl (block[1], shift), constants[2], zero); \ |
||

109 | vx2 = vec_mradds (vec_sl (block[2], shift), constants[3], zero); \ |
||

110 | vx3 = vec_mradds (vec_sl (block[3], shift), constants[4], zero); \ |
||

111 | vx4 = vec_mradds (vec_sl (block[4], shift), constants[1], zero); \ |
||

112 | vx5 = vec_mradds (vec_sl (block[5], shift), constants[4], zero); \ |
||

113 | vx6 = vec_mradds (vec_sl (block[6], shift), constants[3], zero); \ |
||

114 | vx7 = vec_mradds (vec_sl (block[7], shift), constants[2], zero); \ |
||

115 | \ |
||

116 | IDCT_HALF \ |
||

117 | \ |
||

118 | vx0 = vec_mergeh (vy0, vy4); \ |
||

119 | vx1 = vec_mergel (vy0, vy4); \ |
||

120 | vx2 = vec_mergeh (vy1, vy5); \ |
||

121 | vx3 = vec_mergel (vy1, vy5); \ |
||

122 | vx4 = vec_mergeh (vy2, vy6); \ |
||

123 | vx5 = vec_mergel (vy2, vy6); \ |
||

124 | vx6 = vec_mergeh (vy3, vy7); \ |
||

125 | vx7 = vec_mergel (vy3, vy7); \ |
||

126 | \ |
||

127 | vy0 = vec_mergeh (vx0, vx4); \ |
||

128 | vy1 = vec_mergel (vx0, vx4); \ |
||

129 | vy2 = vec_mergeh (vx1, vx5); \ |
||

130 | vy3 = vec_mergel (vx1, vx5); \ |
||

131 | vy4 = vec_mergeh (vx2, vx6); \ |
||

132 | vy5 = vec_mergel (vx2, vx6); \ |
||

133 | vy6 = vec_mergeh (vx3, vx7); \ |
||

134 | vy7 = vec_mergel (vx3, vx7); \ |
||

135 | \ |
||

136 | vx0 = vec_adds (vec_mergeh (vy0, vy4), bias); \ |
||

137 | vx1 = vec_mergel (vy0, vy4); \ |
||

138 | vx2 = vec_mergeh (vy1, vy5); \ |
||

139 | vx3 = vec_mergel (vy1, vy5); \ |
||

140 | vx4 = vec_mergeh (vy2, vy6); \ |
||

141 | vx5 = vec_mergel (vy2, vy6); \ |
||

142 | vx6 = vec_mergeh (vy3, vy7); \ |
||

143 | vx7 = vec_mergel (vy3, vy7); \ |
||

144 | \ |
||

145 | IDCT_HALF \ |
||

146 | \ |
||

147 | ```
shift = vec_splat_u16 (6); \
``` |
||

148 | vx0 = vec_sra (vy0, shift); \ |
||

149 | vx1 = vec_sra (vy1, shift); \ |
||

150 | vx2 = vec_sra (vy2, shift); \ |
||

151 | vx3 = vec_sra (vy3, shift); \ |
||

152 | vx4 = vec_sra (vy4, shift); \ |
||

153 | vx5 = vec_sra (vy5, shift); \ |
||

154 | vx6 = vec_sra (vy6, shift); \ |
||

155 | vx7 = vec_sra (vy7, shift); |
||

156 | |||

157 | 3b991c54 | Romain Dolbeau | |

158 | static const vector_s16_t constants[5] = { |
||

159 | a9a07762 | Michael Niedermayer | (vector_s16_t) AVV(23170, 13573, 6518, 21895, -23170, -21895, 32, 31), |

160 | (vector_s16_t) AVV(16384, 22725, 21407, 19266, 16384, 19266, 21407, 22725), |
||

161 | (vector_s16_t) AVV(22725, 31521, 29692, 26722, 22725, 26722, 29692, 31521), |
||

162 | (vector_s16_t) AVV(21407, 29692, 27969, 25172, 21407, 25172, 27969, 29692), |
||

163 | (vector_s16_t) AVV(19266, 26722, 25172, 22654, 19266, 22654, 25172, 26722) |
||

164 | 3b991c54 | Romain Dolbeau | }; |

165 | 05c4072b | Michael Niedermayer | |

166 | void idct_put_altivec(uint8_t* dest, int stride, vector_s16_t* block) |
||

167 | { |
||

168 | e45a2872 | Romain Dolbeau | ```
POWERPC_PERF_DECLARE(altivec_idct_put_num, 1);
``` |

169 | db40a39a | Michael Niedermayer | ```
#ifdef ALTIVEC_USE_REFERENCE_C_CODE
``` |

170 | e45a2872 | Romain Dolbeau | ```
POWERPC_PERF_START_COUNT(altivec_idct_put_num, 1);
``` |

171 | 0c1a9eda | Zdenek Kabelac | void simple_idct_put(uint8_t *dest, int line_size, int16_t *block); |

172 | simple_idct_put(dest, stride, (int16_t*)block); |
||

173 | e45a2872 | Romain Dolbeau | ```
POWERPC_PERF_STOP_COUNT(altivec_idct_put_num, 1);
``` |

174 | db40a39a | Michael Niedermayer | #else /* ALTIVEC_USE_REFERENCE_C_CODE */ |

175 | 05c4072b | Michael Niedermayer | vector_u8_t tmp; |

176 | |||

177 | e45a2872 | Romain Dolbeau | ```
POWERPC_PERF_START_COUNT(altivec_idct_put_num, 1);
``` |

178 | db40a39a | Michael Niedermayer | |

179 | 05c4072b | Michael Niedermayer | IDCT |

180 | |||

181 | ```
#define COPY(dest,src) \
``` |
||

182 | tmp = vec_packsu (src, src); \ |
||

183 | vec_ste ((vector_u32_t)tmp, 0, (unsigned int *)dest); \ |
||

184 | vec_ste ((vector_u32_t)tmp, 4, (unsigned int *)dest); |
||

185 | |||

186 | COPY (dest, vx0) dest += stride; |
||

187 | COPY (dest, vx1) dest += stride; |
||

188 | COPY (dest, vx2) dest += stride; |
||

189 | COPY (dest, vx3) dest += stride; |
||

190 | COPY (dest, vx4) dest += stride; |
||

191 | COPY (dest, vx5) dest += stride; |
||

192 | COPY (dest, vx6) dest += stride; |
||

193 | COPY (dest, vx7) |
||

194 | db40a39a | Michael Niedermayer | |

195 | e45a2872 | Romain Dolbeau | ```
POWERPC_PERF_STOP_COUNT(altivec_idct_put_num, 1);
``` |

196 | db40a39a | Michael Niedermayer | #endif /* ALTIVEC_USE_REFERENCE_C_CODE */ |

197 | 05c4072b | Michael Niedermayer | } |

198 | |||

199 | void idct_add_altivec(uint8_t* dest, int stride, vector_s16_t* block) |
||

200 | { |
||

201 | e45a2872 | Romain Dolbeau | ```
POWERPC_PERF_DECLARE(altivec_idct_add_num, 1);
``` |

202 | db40a39a | Michael Niedermayer | ```
#ifdef ALTIVEC_USE_REFERENCE_C_CODE
``` |

203 | e45a2872 | Romain Dolbeau | ```
POWERPC_PERF_START_COUNT(altivec_idct_add_num, 1);
``` |

204 | 0c1a9eda | Zdenek Kabelac | void simple_idct_add(uint8_t *dest, int line_size, int16_t *block); |

205 | simple_idct_add(dest, stride, (int16_t*)block); |
||

206 | e45a2872 | Romain Dolbeau | ```
POWERPC_PERF_STOP_COUNT(altivec_idct_add_num, 1);
``` |

207 | db40a39a | Michael Niedermayer | #else /* ALTIVEC_USE_REFERENCE_C_CODE */ |

208 | 05c4072b | Michael Niedermayer | vector_u8_t tmp; |

209 | vector_s16_t tmp2, tmp3; |
||

210 | vector_u8_t perm0; |
||

211 | vector_u8_t perm1; |
||

212 | vector_u8_t p0, p1, p; |
||

213 | |||

214 | e45a2872 | Romain Dolbeau | ```
POWERPC_PERF_START_COUNT(altivec_idct_add_num, 1);
``` |

215 | db40a39a | Michael Niedermayer | |

216 | 05c4072b | Michael Niedermayer | IDCT |

217 | |||

218 | ```
p0 = vec_lvsl (0, dest);
``` |
||

219 | p1 = vec_lvsl (stride, dest); |
||

220 | ```
p = vec_splat_u8 (-1);
``` |
||

221 | perm0 = vec_mergeh (p, p0); |
||

222 | perm1 = vec_mergeh (p, p1); |
||

223 | |||

224 | ```
#define ADD(dest,src,perm) \
``` |
||

225 | ```
/* *(uint64_t *)&tmp = *(uint64_t *)dest; */ \
``` |
||

226 | ```
tmp = vec_ld (0, dest); \
``` |
||

227 | tmp2 = (vector_s16_t)vec_perm (tmp, (vector_u8_t)zero, perm); \ |
||

228 | tmp3 = vec_adds (tmp2, src); \ |
||

229 | tmp = vec_packsu (tmp3, tmp3); \ |
||

230 | vec_ste ((vector_u32_t)tmp, 0, (unsigned int *)dest); \ |
||

231 | vec_ste ((vector_u32_t)tmp, 4, (unsigned int *)dest); |
||

232 | |||

233 | ADD (dest, vx0, perm0) dest += stride; |
||

234 | ADD (dest, vx1, perm1) dest += stride; |
||

235 | ADD (dest, vx2, perm0) dest += stride; |
||

236 | ADD (dest, vx3, perm1) dest += stride; |
||

237 | ADD (dest, vx4, perm0) dest += stride; |
||

238 | ADD (dest, vx5, perm1) dest += stride; |
||

239 | ADD (dest, vx6, perm0) dest += stride; |
||

240 | ADD (dest, vx7, perm1) |
||

241 | db40a39a | Michael Niedermayer | |

242 | e45a2872 | Romain Dolbeau | ```
POWERPC_PERF_STOP_COUNT(altivec_idct_add_num, 1);
``` |

243 | db40a39a | Michael Niedermayer | #endif /* ALTIVEC_USE_REFERENCE_C_CODE */ |

244 | 05c4072b | Michael Niedermayer | } |