idctmmx.c
上传用户:hhs829
上传日期:2022-06-17
资源大小:586k
文件大小:13k
源码类别:

DirextX编程

开发平台:

Visual C++

  1. //////////////////////////////////////////////////////////////////////
  2. //  not functional
  3. //////////////////////////////////////////////////////////////////////
  4. // MPEG2AVI
  5. // -------- 
  6. //  v0.16B34
  7. //    performance optimization, idct_mmx32_rows() and idct_mmx32_cols() now
  8. //    transpose their respective outputs "in-place" (saves a bit of time)
  9. //
  10. //  v0.16B33 initial release
  11. //
  12. // MMX32 iDCT algorithm  (IEEE-1180 compliant) :: idct_mmx32()
  13. //
  14. //  This IDCT implementation is based on Intel Application Note AP-922.
  15. //
  16. //  This file implements the idct algorithm with no transpose.
  17. //  The other file (idctmm32_transpose.c) is faster, but transposes the 
  18. //  output-matrix.  (Intel's code-listing produces a transposed output.)
  19. //
  20. //  ALGORITHM OVERVIEW
  21. //  ------------------
  22. // This was one of the harder pieces of work to code.
  23. // Intel's app-note focuses on the numerical theory/issues of the IDCT 
  24. // implementation, but assumes the programmer is familiar with the
  25. // requisite mathematics, leaving the exact form of the complete IDCT 
  26. // code-listing up to the programmer's imagination.
  27. //
  28. // I played around with Intel's code-fragments for quite a few hours.  
  29. // This file is *A* working IDCT implementation, but it may not be
  30. // the implementation Intel originally intended.  Rest assured, I've
  31. // done everything in my power to guarantee its correctness. 
  32. // This implementation passes all six IEEE accuracy tests by a fair margin.
  33. //
  34. //   My IDCT algorithm consists of 4 steps:
  35. //
  36. //   1) IDCT-row transformation (using the IDCT-row function) on all 8 rows
  37. //      This yields an intermediate 8x8 matrix.
  38. //
  39. //   2) transpose of intermediate matrix (mandatory)
  40. //
  41. //   3) IDCT-row transformation (2nd time) on all 8 rows of the 
  42. //      intermediate matrix.
  43. //      At this point, we have the final-result, in transposed form.
  44. //
  45. //   4) post-transformation matrix transpose 
  46. //      (not necessary if the input-data is already transposed, this could
  47. //       be done during the MPEG "zig-zag" scan, but since my algorithm
  48. //       requires at least one transpose operation, why not re-use the
  49. //       transpose-code.)
  50. //
  51. //   Although the (1st) and (3rd) steps use the same basic row-transform 
  52. //   operation, the (3rd) step uses different shift&round constants 
  53. //   (explained later.)
  54. //
  55. //   Also note that the intermediate transpose (2) would not be neccessary,
  56. //   if the subsequent operation were a iDCT-column transformation.  Since
  57. //   we only have the iDCT-row transform, we transpose the intermediate
  58. //   matrix and use the iDCT-row transform a 2nd time.  I suppose one
  59. //   a faster (but more complicated) code-implementation is possible, 
  60. //   if these steps were merged.
  61. //
  62. //   I had to change some constants/variables for my method to work :
  63. //
  64. //      As given by Intel, #SHIFT_INV_COL and #RND_INV_COL are wrong.  
  65. //      Not surprising since I'm probably implementing the IDCT in
  66. //      perverse fashion.  
  67. //      round_inv_col[], which is given as "4 short" values, should have the
  68. //      same dimensions as round_inv_row[].  The corrected variables are 
  69. //      shown.
  70. //
  71. //      Intel's code defines 4 tables of constants.  My code only uses only
  72. //      one of these tables, row#0.  
  73. //
  74. //   IMPLEMENTATION DETAILs
  75. //   ----------------------
  76. // 
  77. //   I divided the 4-steps of my algorithm into two subroutines,
  78. //    1) idct_mmx32_rows() - transforms 8 rows, then transpose
  79. //    2) idct_mmx32_cols() - transforms 8 rows, then transpose
  80. //       yields final result ("drop-in" direct replacement for INT32 IDCT)
  81. //
  82. //   idct_mmx32_cols() is a carbon-copy of idct_mmx32_rows(), i.e. both
  83. //   execute a row-by-row transformations.  Only the shift&rounding 
  84. //   coefficients differ.
  85. //
  86. //      In the 1st function (rows), the shift & round instructions use 
  87. //       SHIFT_INV_ROW & round_inv_row[] (renamed to r_inv_row[])
  88. //
  89. //      In the 2nd function (cols)-> r_inv_col[], and
  90. //       SHIFT_INV_COL & round_inv_col[] (renamed to r_inv_col[])
  91. //
  92. //   Each function contains an integrated transpose-operator, which comes
  93. //   AFTER the primary transformation operation.  In the future, I'll optimize
  94. //   the code to do more of the transpose-work "in-place".  Right now, I've
  95. //   left the code as two subroutines and a main calling function, so other
  96. //   people can read the code more easily.
  97. //;=============================================================================
  98. //;
  99. //;  AP-922   http://developer.intel.com/vtune/cbts/strmsimd
  100. //; These examples contain code fragments for first stage iDCT 8x8
  101. //; (for rows) and first stage DCT 8x8 (for columns)
  102. //;
  103. //;=============================================================================
  104. #define BITS_INV_ACC 4 // 4 or 5 for IEEE
  105. // 5 yields higher accuracy, but lessens dynamic range on the input matrix
  106. #define SHIFT_INV_ROW (16 - BITS_INV_ACC)
  107. #define SHIFT_INV_COL (1 + BITS_INV_ACC + 14)
  108. #define RND_INV_ROW (1 << (SHIFT_INV_ROW-1))
  109. #define RND_INV_COL (1 << (SHIFT_INV_COL-1)) 
  110. #define RND_INV_CORR (RND_INV_COL - 1)
  111. const static int r_inv_row[2] = { RND_INV_ROW, RND_INV_ROW};
  112. const static int r_inv_col[2] = {RND_INV_COL, RND_INV_COL};
  113. const static int r_inv_corr[2] = {RND_INV_CORR, RND_INV_CORR};
  114. static const short tab_i_01234567[] = {
  115. 16384, 16384, 16384, -16384, 21407, 8867, 8867, -21407,
  116. 16384, -16384, 16384, 16384, -8867, 21407, -21407, -8867,
  117. 22725, 12873, 19266, -22725, 19266, 4520, -4520, -12873,
  118. 12873, 4520, 4520, 19266, -22725, 19266, -12873, -22725,
  119. };
  120. #define INP eax
  121. #define OUT ecx
  122. #define TABLE ebx
  123. #define round_inv_row edx
  124. #define round_inv_col edx
  125. #define ROW_STRIDE 16
  126. static __int64 qwTemp[32];
  127. __forceinline static void idct_mmx32_rows(short *block);
  128. __forceinline static void idct_mmx32_cols(short *block);
  129. // public interface to MMX32 IDCT 8x8 operation
  130. void MMX_IDCT(short *block)
  131. {
  132. idct_mmx32_rows(block);
  133. idct_mmx32_cols(block);
  134. }
  135. static void idct_mmx32_rows(short *block)
  136. {
  137. __asm
  138. {
  139. mov INP, [block]
  140. mov edi, 0x00
  141. lea TABLE, [tab_i_01234567]
  142. lea OUT, [qwTemp]
  143. lea round_inv_row, [r_inv_row]
  144. lpa:
  145. movq mm0, [INP]
  146. movq mm1, [INP+8]
  147. movq mm2, mm0
  148. movq mm3, [TABLE]
  149. punpcklwd mm0, mm1
  150. movq mm5, mm0
  151. punpckldq mm0, mm0
  152. movq mm4, [TABLE+8]
  153. punpckhwd mm2, mm1
  154. pmaddwd mm3, mm0
  155. movq mm6, mm2
  156. movq mm1, [TABLE+32]
  157. punpckldq mm2, mm2
  158. pmaddwd mm4, mm2
  159. punpckhdq mm5, mm5
  160. pmaddwd mm0, [TABLE+16]
  161. punpckhdq mm6, mm6
  162. movq mm7, [TABLE+40]
  163. pmaddwd mm1, mm5
  164. paddd mm3, [round_inv_row]
  165. pmaddwd mm7, mm6
  166. pmaddwd mm2, [TABLE+24]
  167. paddd mm3, mm4
  168. pmaddwd mm5, [TABLE+48]
  169. movq mm4, mm3
  170. pmaddwd mm6, [TABLE+56]
  171. paddd mm1, mm7
  172. paddd mm0, [round_inv_row]
  173. psubd mm3, mm1
  174. psrad mm3, SHIFT_INV_ROW
  175. paddd mm1, mm4
  176. paddd mm0, mm2
  177. psrad mm1, SHIFT_INV_ROW
  178. paddd mm5, mm6
  179. movq mm4, mm0
  180. paddd mm0, mm5
  181. psubd mm4, mm5
  182. add INP, 16
  183. psrad mm4, SHIFT_INV_ROW
  184. psrad mm0, SHIFT_INV_ROW
  185. packssdw mm4, mm3
  186. packssdw mm1, mm0
  187. movq mm7, mm4
  188. psrld mm4, 16
  189. movq [OUT], mm1
  190. pslld mm7, 16
  191. por mm7, mm4
  192. movq mm3, [TABLE]
  193. movq [OUT+8], mm7
  194. add edi, 0x01
  195. add OUT, 16
  196. cmp edi, 0x08
  197. jl lpa
  198. lea OUT, [qwTemp]
  199. movq mm0, [OUT+ROW_STRIDE*0]
  200. movq mm1, [OUT+ROW_STRIDE*1]
  201. movq mm4, mm0
  202. movq mm2, [OUT+ROW_STRIDE*2]
  203. punpcklwd mm0, mm1
  204. movq mm3, [OUT+ROW_STRIDE*3]
  205. punpckhwd mm4, mm1
  206. movq mm6, mm2
  207. punpcklwd mm2, mm3
  208. punpckhwd mm6, mm3
  209. movq mm1, mm0
  210. mov INP, [block]
  211. punpckldq mm0, mm2
  212. movq mm3, mm4
  213. punpckhdq mm1, mm2
  214. movq [INP+ROW_STRIDE*0], mm0
  215. punpckldq mm4, mm6
  216. movq mm0, [OUT+ROW_STRIDE*4+8]
  217. punpckhdq mm3, mm6
  218. movq [INP+ROW_STRIDE*2], mm4
  219. movq mm4, mm0
  220. movq [INP+ROW_STRIDE*1], mm1
  221. movq mm1, [OUT+ROW_STRIDE*5+8]
  222. movq [INP+ROW_STRIDE*3], mm3
  223. punpcklwd mm0, mm1
  224. movq mm2, [OUT+ROW_STRIDE*6+8]
  225. punpckhwd mm4, mm1
  226. movq mm3, [OUT+ROW_STRIDE*7+8]
  227. movq mm6, mm2
  228. punpcklwd mm2, mm3
  229. movq mm1, mm0
  230. punpckhwd mm6, mm3
  231. movq mm3, mm4
  232. punpckldq mm0, mm2
  233. punpckhdq mm1, mm2
  234. movq [INP+ROW_STRIDE*4+8], mm0
  235. punpckldq mm4, mm6
  236. movq mm0, [OUT+ROW_STRIDE*4]
  237. punpckhdq mm3, mm6
  238. movq [INP+ROW_STRIDE*6+8], mm4
  239. movq mm4, mm0
  240. movq [INP+ROW_STRIDE*5+8], mm1
  241. movq mm1, [OUT+ROW_STRIDE*5]
  242. movq [INP+ROW_STRIDE*7+8], mm3
  243. punpcklwd mm0, mm1
  244. movq mm2, [OUT+ROW_STRIDE*6]
  245. punpckhwd mm4, mm1
  246. movq mm3, [OUT+ROW_STRIDE*7]
  247. movq mm6, mm2
  248. punpcklwd mm2, mm3
  249. movq mm1, mm0
  250. punpckhwd mm6, mm3
  251. movq mm3, mm4
  252. punpckldq mm0, mm2
  253. punpckhdq mm1, mm2
  254. movq [INP+ROW_STRIDE*0+8], mm0
  255. punpckldq mm4, mm6
  256. movq mm0, [OUT+ROW_STRIDE*0+8]
  257. punpckhdq mm3, mm6
  258. movq [INP+ROW_STRIDE*2+8], mm4
  259. movq mm4, mm0
  260. movq [INP+ROW_STRIDE*1+8], mm1
  261. movq mm1, [OUT+ROW_STRIDE*1+8]
  262. movq [INP+ROW_STRIDE*3+8], mm3
  263. punpcklwd mm0, mm1
  264. movq mm2, [OUT+ROW_STRIDE*2+8]
  265. punpckhwd mm4, mm1
  266. movq mm3, [OUT+ROW_STRIDE*3+8]
  267. movq mm6, mm2
  268. punpcklwd mm2, mm3
  269. movq mm1, mm0
  270. punpckhwd mm6, mm3
  271. movq mm3, mm4
  272. punpckldq mm0, mm2
  273. punpckhdq mm1, mm2
  274. movq [INP+ROW_STRIDE*4], mm0
  275. punpckldq mm4, mm6
  276. movq [INP+ROW_STRIDE*5], mm1
  277. punpckhdq mm3, mm6
  278. movq [INP+ROW_STRIDE*6], mm4
  279. movq [INP+ROW_STRIDE*7], mm3
  280. }
  281. }
  282. static void idct_mmx32_cols(short *block)
  283. {
  284. __asm
  285. {
  286. mov INP, [block]
  287. mov edi, 0x00
  288. lea TABLE, [tab_i_01234567]
  289. lea OUT, [qwTemp]
  290. lea round_inv_col, [r_inv_col]
  291. acc_idct_colloop1:
  292. movq mm0, [INP]
  293. movq mm1, [INP+8]
  294. movq mm2, mm0
  295. movq mm3, [TABLE]
  296. punpcklwd mm0, mm1
  297. movq mm5, mm0
  298. punpckldq mm0, mm0
  299. movq mm4, [TABLE+8]
  300. punpckhwd mm2, mm1
  301. pmaddwd mm3, mm0
  302. movq mm6, mm2
  303. movq mm1, [TABLE+32]
  304. punpckldq mm2, mm2
  305. pmaddwd mm4, mm2
  306. punpckhdq mm5, mm5
  307. pmaddwd mm0, [TABLE+16]
  308. punpckhdq mm6, mm6
  309. movq mm7, [TABLE+40]
  310. pmaddwd mm1, mm5
  311. paddd mm3, [round_inv_col]
  312. pmaddwd mm7, mm6
  313. pmaddwd mm2, [TABLE+24]
  314. paddd mm3, mm4
  315. pmaddwd mm5, [TABLE+48]
  316. movq mm4, mm3
  317. pmaddwd mm6, [TABLE+56]
  318. paddd mm1, mm7
  319. paddd mm0, [round_inv_col]
  320. psubd mm3, mm1
  321. psrad mm3, SHIFT_INV_COL
  322. paddd mm1, mm4
  323. paddd mm0, mm2
  324. psrad mm1, SHIFT_INV_COL
  325. paddd mm5, mm6
  326. movq mm4, mm0
  327. paddd mm0, mm5
  328. psubd mm4, mm5
  329. add INP, 16
  330. psrad mm4, SHIFT_INV_COL
  331. add TABLE, 0
  332. psrad mm0, SHIFT_INV_COL
  333. packssdw mm4, mm3
  334. packssdw mm1, mm0
  335. movq mm7, mm4
  336. psrld mm4, 16
  337. movq [OUT], mm1
  338. pslld mm7, 16
  339. por mm7, mm4
  340. movq [OUT+8], mm7
  341. add edi, 0x01
  342. add OUT, 16
  343. cmp edi, 0x08
  344. jl acc_idct_colloop1
  345. lea OUT, [qwTemp]
  346. movq mm0, [OUT+ROW_STRIDE*0]
  347. movq mm1, [OUT+ROW_STRIDE*1]
  348. movq mm4, mm0
  349. movq mm2, [OUT+ROW_STRIDE*2]
  350. punpcklwd mm0, mm1
  351. movq mm3, [OUT+ROW_STRIDE*3]
  352. punpckhwd mm4, mm1
  353. movq mm6, mm2
  354. punpcklwd mm2, mm3
  355. punpckhwd mm6, mm3
  356. movq mm1, mm0
  357. mov INP, [block]
  358. punpckldq mm0, mm2
  359. movq mm3, mm4
  360. punpckhdq mm1, mm2
  361. movq [INP+ROW_STRIDE*0], mm0
  362. punpckldq mm4, mm6
  363. movq mm0, [OUT+ROW_STRIDE*4+8]
  364. punpckhdq mm3, mm6
  365. movq [INP+ROW_STRIDE*2], mm4
  366. movq mm4, mm0
  367. movq [INP+ROW_STRIDE*1], mm1
  368. movq mm1, [OUT+ROW_STRIDE*5+8]
  369. movq [INP+ROW_STRIDE*3], mm3
  370. punpcklwd mm0, mm1
  371. movq mm2, [OUT+ROW_STRIDE*6+8]
  372. punpckhwd mm4, mm1
  373. movq mm3, [OUT+ROW_STRIDE*7+8]
  374. movq mm6, mm2
  375. punpcklwd mm2, mm3
  376. movq mm1, mm0
  377. punpckhwd mm6, mm3
  378. movq mm3, mm4
  379. punpckldq mm0, mm2
  380. punpckhdq mm1, mm2
  381. movq [INP+ROW_STRIDE*4+8], mm0
  382. punpckldq mm4, mm6
  383. movq mm0, [OUT+ROW_STRIDE*4]
  384. punpckhdq mm3, mm6
  385. movq [INP+ROW_STRIDE*6+8], mm4
  386. movq mm4, mm0
  387. movq [INP+ROW_STRIDE*5+8], mm1
  388. movq mm1, [OUT+ROW_STRIDE*5]
  389. movq [INP+ROW_STRIDE*7+8], mm3
  390. punpcklwd mm0, mm1
  391. movq mm2, [OUT+ROW_STRIDE*6]
  392. punpckhwd mm4, mm1
  393. movq mm3, [OUT+ROW_STRIDE*7]
  394. movq mm6, mm2
  395. punpcklwd mm2, mm3
  396. movq mm1, mm0
  397. punpckhwd mm6, mm3
  398. movq mm3, mm4
  399. punpckldq mm0, mm2
  400. punpckhdq mm1, mm2
  401. movq [INP+ROW_STRIDE*0+8], mm0
  402. punpckldq mm4, mm6
  403. movq mm0, [OUT+ROW_STRIDE*0+8]
  404. punpckhdq mm3, mm6
  405. movq [INP+ROW_STRIDE*2+8], mm4
  406. movq mm4, mm0
  407. movq [INP+ROW_STRIDE*1+8], mm1
  408. movq mm1, [OUT + ROW_STRIDE*1+8]
  409. movq [INP+ROW_STRIDE*3+8], mm3
  410. punpcklwd mm0, mm1
  411. movq mm2, [OUT+ROW_STRIDE*2+8]
  412. punpckhwd mm4, mm1
  413. movq mm3, [OUT+ROW_STRIDE*3+8]
  414. movq mm6, mm2
  415. punpcklwd mm2, mm3
  416. movq mm1, mm0
  417. punpckhwd mm6, mm3
  418. movq mm3, mm4
  419. punpckldq mm0, mm2
  420. punpckhdq mm1, mm2
  421. movq [INP+ROW_STRIDE*4], mm0
  422. punpckldq mm4, mm6
  423. movq [INP+ROW_STRIDE*5], mm1
  424. punpckhdq mm3, mm6
  425. movq [INP+ROW_STRIDE*6], mm4
  426. movq [INP+ROW_STRIDE*7], mm3
  427. }
  428. }