You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

723 lines
22KB

  1. /*
  2. * The simplest mpeg encoder (well, it was the simplest!)
  3. * Copyright (c) 2000,2001 Fabrice Bellard.
  4. *
  5. * This library is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU Lesser General Public
  7. * License as published by the Free Software Foundation; either
  8. * version 2 of the License, or (at your option) any later version.
  9. *
  10. * This library is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * Lesser General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Lesser General Public
  16. * License along with this library; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. *
  19. * Optimized for ia32 cpus by Nick Kurshev <nickols_k@mail.ru>
  20. * h263, mpeg1, mpeg2 dequantizer & draw_edges by Michael Niedermayer <michaelni@gmx.at>
  21. */
  22. #include "../dsputil.h"
  23. #include "../mpegvideo.h"
  24. #include "../avcodec.h"
  25. extern uint8_t zigzag_direct_noperm[64];
  26. extern uint16_t inv_zigzag_direct16[64];
  27. static const unsigned long long int mm_wabs __attribute__ ((aligned(8))) = 0xffffffffffffffffULL;
  28. static const unsigned long long int mm_wone __attribute__ ((aligned(8))) = 0x0001000100010001ULL;
  29. static void dct_unquantize_h263_intra_mmx(MpegEncContext *s,
  30. DCTELEM *block, int n, int qscale)
  31. {
  32. int level, qmul, qadd, nCoeffs;
  33. qmul = qscale << 1;
  34. assert(s->block_last_index[n]>=0 || s->h263_aic);
  35. if (!s->h263_aic) {
  36. if (n < 4)
  37. level = block[0] * s->y_dc_scale;
  38. else
  39. level = block[0] * s->c_dc_scale;
  40. qadd = (qscale - 1) | 1;
  41. }else{
  42. qadd = 0;
  43. level= block[0];
  44. }
  45. if(s->ac_pred)
  46. nCoeffs=63;
  47. else
  48. nCoeffs= s->inter_scantable.raster_end[ s->block_last_index[n] ];
  49. //printf("%d %d ", qmul, qadd);
  50. asm volatile(
  51. "movd %1, %%mm6 \n\t" //qmul
  52. "packssdw %%mm6, %%mm6 \n\t"
  53. "packssdw %%mm6, %%mm6 \n\t"
  54. "movd %2, %%mm5 \n\t" //qadd
  55. "pxor %%mm7, %%mm7 \n\t"
  56. "packssdw %%mm5, %%mm5 \n\t"
  57. "packssdw %%mm5, %%mm5 \n\t"
  58. "psubw %%mm5, %%mm7 \n\t"
  59. "pxor %%mm4, %%mm4 \n\t"
  60. ".balign 16\n\t"
  61. "1: \n\t"
  62. "movq (%0, %3), %%mm0 \n\t"
  63. "movq 8(%0, %3), %%mm1 \n\t"
  64. "pmullw %%mm6, %%mm0 \n\t"
  65. "pmullw %%mm6, %%mm1 \n\t"
  66. "movq (%0, %3), %%mm2 \n\t"
  67. "movq 8(%0, %3), %%mm3 \n\t"
  68. "pcmpgtw %%mm4, %%mm2 \n\t" // block[i] < 0 ? -1 : 0
  69. "pcmpgtw %%mm4, %%mm3 \n\t" // block[i] < 0 ? -1 : 0
  70. "pxor %%mm2, %%mm0 \n\t"
  71. "pxor %%mm3, %%mm1 \n\t"
  72. "paddw %%mm7, %%mm0 \n\t"
  73. "paddw %%mm7, %%mm1 \n\t"
  74. "pxor %%mm0, %%mm2 \n\t"
  75. "pxor %%mm1, %%mm3 \n\t"
  76. "pcmpeqw %%mm7, %%mm0 \n\t" // block[i] == 0 ? -1 : 0
  77. "pcmpeqw %%mm7, %%mm1 \n\t" // block[i] == 0 ? -1 : 0
  78. "pandn %%mm2, %%mm0 \n\t"
  79. "pandn %%mm3, %%mm1 \n\t"
  80. "movq %%mm0, (%0, %3) \n\t"
  81. "movq %%mm1, 8(%0, %3) \n\t"
  82. "addl $16, %3 \n\t"
  83. "jng 1b \n\t"
  84. ::"r" (block+nCoeffs), "g"(qmul), "g" (qadd), "r" (2*(-nCoeffs))
  85. : "memory"
  86. );
  87. block[0]= level;
  88. }
  89. static void dct_unquantize_h263_inter_mmx(MpegEncContext *s,
  90. DCTELEM *block, int n, int qscale)
  91. {
  92. int qmul, qadd, nCoeffs;
  93. qmul = qscale << 1;
  94. qadd = (qscale - 1) | 1;
  95. assert(s->block_last_index[n]>=0 || s->h263_aic);
  96. nCoeffs= s->inter_scantable.raster_end[ s->block_last_index[n] ];
  97. //printf("%d %d ", qmul, qadd);
  98. asm volatile(
  99. "movd %1, %%mm6 \n\t" //qmul
  100. "packssdw %%mm6, %%mm6 \n\t"
  101. "packssdw %%mm6, %%mm6 \n\t"
  102. "movd %2, %%mm5 \n\t" //qadd
  103. "pxor %%mm7, %%mm7 \n\t"
  104. "packssdw %%mm5, %%mm5 \n\t"
  105. "packssdw %%mm5, %%mm5 \n\t"
  106. "psubw %%mm5, %%mm7 \n\t"
  107. "pxor %%mm4, %%mm4 \n\t"
  108. ".balign 16\n\t"
  109. "1: \n\t"
  110. "movq (%0, %3), %%mm0 \n\t"
  111. "movq 8(%0, %3), %%mm1 \n\t"
  112. "pmullw %%mm6, %%mm0 \n\t"
  113. "pmullw %%mm6, %%mm1 \n\t"
  114. "movq (%0, %3), %%mm2 \n\t"
  115. "movq 8(%0, %3), %%mm3 \n\t"
  116. "pcmpgtw %%mm4, %%mm2 \n\t" // block[i] < 0 ? -1 : 0
  117. "pcmpgtw %%mm4, %%mm3 \n\t" // block[i] < 0 ? -1 : 0
  118. "pxor %%mm2, %%mm0 \n\t"
  119. "pxor %%mm3, %%mm1 \n\t"
  120. "paddw %%mm7, %%mm0 \n\t"
  121. "paddw %%mm7, %%mm1 \n\t"
  122. "pxor %%mm0, %%mm2 \n\t"
  123. "pxor %%mm1, %%mm3 \n\t"
  124. "pcmpeqw %%mm7, %%mm0 \n\t" // block[i] == 0 ? -1 : 0
  125. "pcmpeqw %%mm7, %%mm1 \n\t" // block[i] == 0 ? -1 : 0
  126. "pandn %%mm2, %%mm0 \n\t"
  127. "pandn %%mm3, %%mm1 \n\t"
  128. "movq %%mm0, (%0, %3) \n\t"
  129. "movq %%mm1, 8(%0, %3) \n\t"
  130. "addl $16, %3 \n\t"
  131. "jng 1b \n\t"
  132. ::"r" (block+nCoeffs), "g"(qmul), "g" (qadd), "r" (2*(-nCoeffs))
  133. : "memory"
  134. );
  135. }
  136. /*
  137. NK:
  138. Note: looking at PARANOID:
  139. "enable all paranoid tests for rounding, overflows, etc..."
  140. #ifdef PARANOID
  141. if (level < -2048 || level > 2047)
  142. fprintf(stderr, "unquant error %d %d\n", i, level);
  143. #endif
  144. We can suppose that result of two multiplications can't be greate of 0xFFFF
  145. i.e. is 16-bit, so we use here only PMULLW instruction and can avoid
  146. a complex multiplication.
  147. =====================================================
  148. Full formula for multiplication of 2 integer numbers
  149. which are represent as high:low words:
  150. input: value1 = high1:low1
  151. value2 = high2:low2
  152. output: value3 = value1*value2
  153. value3=high3:low3 (on overflow: modulus 2^32 wrap-around)
  154. this mean that for 0x123456 * 0x123456 correct result is 0x766cb0ce4
  155. but this algorithm will compute only 0x66cb0ce4
  156. this limited by 16-bit size of operands
  157. ---------------------------------
  158. tlow1 = high1*low2
  159. tlow2 = high2*low1
  160. tlow1 = tlow1 + tlow2
  161. high3:low3 = low1*low2
  162. high3 += tlow1
  163. */
  164. static void dct_unquantize_mpeg1_intra_mmx(MpegEncContext *s,
  165. DCTELEM *block, int n, int qscale)
  166. {
  167. int nCoeffs;
  168. const uint16_t *quant_matrix;
  169. int block0;
  170. assert(s->block_last_index[n]>=0);
  171. nCoeffs= s->intra_scantable.raster_end[ s->block_last_index[n] ]+1;
  172. if (n < 4)
  173. block0 = block[0] * s->y_dc_scale;
  174. else
  175. block0 = block[0] * s->c_dc_scale;
  176. /* XXX: only mpeg1 */
  177. quant_matrix = s->intra_matrix;
  178. asm volatile(
  179. "pcmpeqw %%mm7, %%mm7 \n\t"
  180. "psrlw $15, %%mm7 \n\t"
  181. "movd %2, %%mm6 \n\t"
  182. "packssdw %%mm6, %%mm6 \n\t"
  183. "packssdw %%mm6, %%mm6 \n\t"
  184. "movl %3, %%eax \n\t"
  185. ".balign 16\n\t"
  186. "1: \n\t"
  187. "movq (%0, %%eax), %%mm0 \n\t"
  188. "movq 8(%0, %%eax), %%mm1 \n\t"
  189. "movq (%1, %%eax), %%mm4 \n\t"
  190. "movq 8(%1, %%eax), %%mm5 \n\t"
  191. "pmullw %%mm6, %%mm4 \n\t" // q=qscale*quant_matrix[i]
  192. "pmullw %%mm6, %%mm5 \n\t" // q=qscale*quant_matrix[i]
  193. "pxor %%mm2, %%mm2 \n\t"
  194. "pxor %%mm3, %%mm3 \n\t"
  195. "pcmpgtw %%mm0, %%mm2 \n\t" // block[i] < 0 ? -1 : 0
  196. "pcmpgtw %%mm1, %%mm3 \n\t" // block[i] < 0 ? -1 : 0
  197. "pxor %%mm2, %%mm0 \n\t"
  198. "pxor %%mm3, %%mm1 \n\t"
  199. "psubw %%mm2, %%mm0 \n\t" // abs(block[i])
  200. "psubw %%mm3, %%mm1 \n\t" // abs(block[i])
  201. "pmullw %%mm4, %%mm0 \n\t" // abs(block[i])*q
  202. "pmullw %%mm5, %%mm1 \n\t" // abs(block[i])*q
  203. "pxor %%mm4, %%mm4 \n\t"
  204. "pxor %%mm5, %%mm5 \n\t" // FIXME slow
  205. "pcmpeqw (%0, %%eax), %%mm4 \n\t" // block[i] == 0 ? -1 : 0
  206. "pcmpeqw 8(%0, %%eax), %%mm5 \n\t" // block[i] == 0 ? -1 : 0
  207. "psraw $3, %%mm0 \n\t"
  208. "psraw $3, %%mm1 \n\t"
  209. "psubw %%mm7, %%mm0 \n\t"
  210. "psubw %%mm7, %%mm1 \n\t"
  211. "por %%mm7, %%mm0 \n\t"
  212. "por %%mm7, %%mm1 \n\t"
  213. "pxor %%mm2, %%mm0 \n\t"
  214. "pxor %%mm3, %%mm1 \n\t"
  215. "psubw %%mm2, %%mm0 \n\t"
  216. "psubw %%mm3, %%mm1 \n\t"
  217. "pandn %%mm0, %%mm4 \n\t"
  218. "pandn %%mm1, %%mm5 \n\t"
  219. "movq %%mm4, (%0, %%eax) \n\t"
  220. "movq %%mm5, 8(%0, %%eax) \n\t"
  221. "addl $16, %%eax \n\t"
  222. "js 1b \n\t"
  223. ::"r" (block+nCoeffs), "r"(quant_matrix+nCoeffs), "g" (qscale), "g" (-2*nCoeffs)
  224. : "%eax", "memory"
  225. );
  226. block[0]= block0;
  227. }
  228. static void dct_unquantize_mpeg1_inter_mmx(MpegEncContext *s,
  229. DCTELEM *block, int n, int qscale)
  230. {
  231. int nCoeffs;
  232. const uint16_t *quant_matrix;
  233. assert(s->block_last_index[n]>=0);
  234. nCoeffs= s->intra_scantable.raster_end[ s->block_last_index[n] ]+1;
  235. quant_matrix = s->inter_matrix;
  236. asm volatile(
  237. "pcmpeqw %%mm7, %%mm7 \n\t"
  238. "psrlw $15, %%mm7 \n\t"
  239. "movd %2, %%mm6 \n\t"
  240. "packssdw %%mm6, %%mm6 \n\t"
  241. "packssdw %%mm6, %%mm6 \n\t"
  242. "movl %3, %%eax \n\t"
  243. ".balign 16\n\t"
  244. "1: \n\t"
  245. "movq (%0, %%eax), %%mm0 \n\t"
  246. "movq 8(%0, %%eax), %%mm1 \n\t"
  247. "movq (%1, %%eax), %%mm4 \n\t"
  248. "movq 8(%1, %%eax), %%mm5 \n\t"
  249. "pmullw %%mm6, %%mm4 \n\t" // q=qscale*quant_matrix[i]
  250. "pmullw %%mm6, %%mm5 \n\t" // q=qscale*quant_matrix[i]
  251. "pxor %%mm2, %%mm2 \n\t"
  252. "pxor %%mm3, %%mm3 \n\t"
  253. "pcmpgtw %%mm0, %%mm2 \n\t" // block[i] < 0 ? -1 : 0
  254. "pcmpgtw %%mm1, %%mm3 \n\t" // block[i] < 0 ? -1 : 0
  255. "pxor %%mm2, %%mm0 \n\t"
  256. "pxor %%mm3, %%mm1 \n\t"
  257. "psubw %%mm2, %%mm0 \n\t" // abs(block[i])
  258. "psubw %%mm3, %%mm1 \n\t" // abs(block[i])
  259. "paddw %%mm0, %%mm0 \n\t" // abs(block[i])*2
  260. "paddw %%mm1, %%mm1 \n\t" // abs(block[i])*2
  261. "paddw %%mm7, %%mm0 \n\t" // abs(block[i])*2 + 1
  262. "paddw %%mm7, %%mm1 \n\t" // abs(block[i])*2 + 1
  263. "pmullw %%mm4, %%mm0 \n\t" // (abs(block[i])*2 + 1)*q
  264. "pmullw %%mm5, %%mm1 \n\t" // (abs(block[i])*2 + 1)*q
  265. "pxor %%mm4, %%mm4 \n\t"
  266. "pxor %%mm5, %%mm5 \n\t" // FIXME slow
  267. "pcmpeqw (%0, %%eax), %%mm4 \n\t" // block[i] == 0 ? -1 : 0
  268. "pcmpeqw 8(%0, %%eax), %%mm5 \n\t" // block[i] == 0 ? -1 : 0
  269. "psraw $4, %%mm0 \n\t"
  270. "psraw $4, %%mm1 \n\t"
  271. "psubw %%mm7, %%mm0 \n\t"
  272. "psubw %%mm7, %%mm1 \n\t"
  273. "por %%mm7, %%mm0 \n\t"
  274. "por %%mm7, %%mm1 \n\t"
  275. "pxor %%mm2, %%mm0 \n\t"
  276. "pxor %%mm3, %%mm1 \n\t"
  277. "psubw %%mm2, %%mm0 \n\t"
  278. "psubw %%mm3, %%mm1 \n\t"
  279. "pandn %%mm0, %%mm4 \n\t"
  280. "pandn %%mm1, %%mm5 \n\t"
  281. "movq %%mm4, (%0, %%eax) \n\t"
  282. "movq %%mm5, 8(%0, %%eax) \n\t"
  283. "addl $16, %%eax \n\t"
  284. "js 1b \n\t"
  285. ::"r" (block+nCoeffs), "r"(quant_matrix+nCoeffs), "g" (qscale), "g" (-2*nCoeffs)
  286. : "%eax", "memory"
  287. );
  288. }
  289. static void dct_unquantize_mpeg2_intra_mmx(MpegEncContext *s,
  290. DCTELEM *block, int n, int qscale)
  291. {
  292. int nCoeffs;
  293. const uint16_t *quant_matrix;
  294. int block0;
  295. assert(s->block_last_index[n]>=0);
  296. if(s->alternate_scan) nCoeffs= 63; //FIXME
  297. else nCoeffs= s->intra_scantable.raster_end[ s->block_last_index[n] ];
  298. if (n < 4)
  299. block0 = block[0] * s->y_dc_scale;
  300. else
  301. block0 = block[0] * s->c_dc_scale;
  302. quant_matrix = s->intra_matrix;
  303. asm volatile(
  304. "pcmpeqw %%mm7, %%mm7 \n\t"
  305. "psrlw $15, %%mm7 \n\t"
  306. "movd %2, %%mm6 \n\t"
  307. "packssdw %%mm6, %%mm6 \n\t"
  308. "packssdw %%mm6, %%mm6 \n\t"
  309. "movl %3, %%eax \n\t"
  310. ".balign 16\n\t"
  311. "1: \n\t"
  312. "movq (%0, %%eax), %%mm0 \n\t"
  313. "movq 8(%0, %%eax), %%mm1 \n\t"
  314. "movq (%1, %%eax), %%mm4 \n\t"
  315. "movq 8(%1, %%eax), %%mm5 \n\t"
  316. "pmullw %%mm6, %%mm4 \n\t" // q=qscale*quant_matrix[i]
  317. "pmullw %%mm6, %%mm5 \n\t" // q=qscale*quant_matrix[i]
  318. "pxor %%mm2, %%mm2 \n\t"
  319. "pxor %%mm3, %%mm3 \n\t"
  320. "pcmpgtw %%mm0, %%mm2 \n\t" // block[i] < 0 ? -1 : 0
  321. "pcmpgtw %%mm1, %%mm3 \n\t" // block[i] < 0 ? -1 : 0
  322. "pxor %%mm2, %%mm0 \n\t"
  323. "pxor %%mm3, %%mm1 \n\t"
  324. "psubw %%mm2, %%mm0 \n\t" // abs(block[i])
  325. "psubw %%mm3, %%mm1 \n\t" // abs(block[i])
  326. "pmullw %%mm4, %%mm0 \n\t" // abs(block[i])*q
  327. "pmullw %%mm5, %%mm1 \n\t" // abs(block[i])*q
  328. "pxor %%mm4, %%mm4 \n\t"
  329. "pxor %%mm5, %%mm5 \n\t" // FIXME slow
  330. "pcmpeqw (%0, %%eax), %%mm4 \n\t" // block[i] == 0 ? -1 : 0
  331. "pcmpeqw 8(%0, %%eax), %%mm5 \n\t" // block[i] == 0 ? -1 : 0
  332. "psraw $3, %%mm0 \n\t"
  333. "psraw $3, %%mm1 \n\t"
  334. "pxor %%mm2, %%mm0 \n\t"
  335. "pxor %%mm3, %%mm1 \n\t"
  336. "psubw %%mm2, %%mm0 \n\t"
  337. "psubw %%mm3, %%mm1 \n\t"
  338. "pandn %%mm0, %%mm4 \n\t"
  339. "pandn %%mm1, %%mm5 \n\t"
  340. "movq %%mm4, (%0, %%eax) \n\t"
  341. "movq %%mm5, 8(%0, %%eax) \n\t"
  342. "addl $16, %%eax \n\t"
  343. "jng 1b \n\t"
  344. ::"r" (block+nCoeffs), "r"(quant_matrix+nCoeffs), "g" (qscale), "g" (-2*nCoeffs)
  345. : "%eax", "memory"
  346. );
  347. block[0]= block0;
  348. //Note, we dont do mismatch control for intra as errors cannot accumulate
  349. }
  350. static void dct_unquantize_mpeg2_inter_mmx(MpegEncContext *s,
  351. DCTELEM *block, int n, int qscale)
  352. {
  353. int nCoeffs;
  354. const uint16_t *quant_matrix;
  355. assert(s->block_last_index[n]>=0);
  356. if(s->alternate_scan) nCoeffs= 63; //FIXME
  357. else nCoeffs= s->intra_scantable.raster_end[ s->block_last_index[n] ];
  358. quant_matrix = s->inter_matrix;
  359. asm volatile(
  360. "pcmpeqw %%mm7, %%mm7 \n\t"
  361. "psrlq $48, %%mm7 \n\t"
  362. "movd %2, %%mm6 \n\t"
  363. "packssdw %%mm6, %%mm6 \n\t"
  364. "packssdw %%mm6, %%mm6 \n\t"
  365. "movl %3, %%eax \n\t"
  366. ".balign 16\n\t"
  367. "1: \n\t"
  368. "movq (%0, %%eax), %%mm0 \n\t"
  369. "movq 8(%0, %%eax), %%mm1 \n\t"
  370. "movq (%1, %%eax), %%mm4 \n\t"
  371. "movq 8(%1, %%eax), %%mm5 \n\t"
  372. "pmullw %%mm6, %%mm4 \n\t" // q=qscale*quant_matrix[i]
  373. "pmullw %%mm6, %%mm5 \n\t" // q=qscale*quant_matrix[i]
  374. "pxor %%mm2, %%mm2 \n\t"
  375. "pxor %%mm3, %%mm3 \n\t"
  376. "pcmpgtw %%mm0, %%mm2 \n\t" // block[i] < 0 ? -1 : 0
  377. "pcmpgtw %%mm1, %%mm3 \n\t" // block[i] < 0 ? -1 : 0
  378. "pxor %%mm2, %%mm0 \n\t"
  379. "pxor %%mm3, %%mm1 \n\t"
  380. "psubw %%mm2, %%mm0 \n\t" // abs(block[i])
  381. "psubw %%mm3, %%mm1 \n\t" // abs(block[i])
  382. "paddw %%mm0, %%mm0 \n\t" // abs(block[i])*2
  383. "paddw %%mm1, %%mm1 \n\t" // abs(block[i])*2
  384. "pmullw %%mm4, %%mm0 \n\t" // abs(block[i])*2*q
  385. "pmullw %%mm5, %%mm1 \n\t" // abs(block[i])*2*q
  386. "paddw %%mm4, %%mm0 \n\t" // (abs(block[i])*2 + 1)*q
  387. "paddw %%mm5, %%mm1 \n\t" // (abs(block[i])*2 + 1)*q
  388. "pxor %%mm4, %%mm4 \n\t"
  389. "pxor %%mm5, %%mm5 \n\t" // FIXME slow
  390. "pcmpeqw (%0, %%eax), %%mm4 \n\t" // block[i] == 0 ? -1 : 0
  391. "pcmpeqw 8(%0, %%eax), %%mm5 \n\t" // block[i] == 0 ? -1 : 0
  392. "psrlw $4, %%mm0 \n\t"
  393. "psrlw $4, %%mm1 \n\t"
  394. "pxor %%mm2, %%mm0 \n\t"
  395. "pxor %%mm3, %%mm1 \n\t"
  396. "psubw %%mm2, %%mm0 \n\t"
  397. "psubw %%mm3, %%mm1 \n\t"
  398. "pandn %%mm0, %%mm4 \n\t"
  399. "pandn %%mm1, %%mm5 \n\t"
  400. "pxor %%mm4, %%mm7 \n\t"
  401. "pxor %%mm5, %%mm7 \n\t"
  402. "movq %%mm4, (%0, %%eax) \n\t"
  403. "movq %%mm5, 8(%0, %%eax) \n\t"
  404. "addl $16, %%eax \n\t"
  405. "jng 1b \n\t"
  406. "movd 124(%0, %3), %%mm0 \n\t"
  407. "movq %%mm7, %%mm6 \n\t"
  408. "psrlq $32, %%mm7 \n\t"
  409. "pxor %%mm6, %%mm7 \n\t"
  410. "movq %%mm7, %%mm6 \n\t"
  411. "psrlq $16, %%mm7 \n\t"
  412. "pxor %%mm6, %%mm7 \n\t"
  413. "pslld $31, %%mm7 \n\t"
  414. "psrlq $15, %%mm7 \n\t"
  415. "pxor %%mm7, %%mm0 \n\t"
  416. "movd %%mm0, 124(%0, %3) \n\t"
  417. ::"r" (block+nCoeffs), "r"(quant_matrix+nCoeffs), "g" (qscale), "r" (-2*nCoeffs)
  418. : "%eax", "memory"
  419. );
  420. }
  421. /* draw the edges of width 'w' of an image of size width, height
  422. this mmx version can only handle w==8 || w==16 */
  423. static void draw_edges_mmx(uint8_t *buf, int wrap, int width, int height, int w)
  424. {
  425. uint8_t *ptr, *last_line;
  426. int i;
  427. last_line = buf + (height - 1) * wrap;
  428. /* left and right */
  429. ptr = buf;
  430. if(w==8)
  431. {
  432. asm volatile(
  433. "1: \n\t"
  434. "movd (%0), %%mm0 \n\t"
  435. "punpcklbw %%mm0, %%mm0 \n\t"
  436. "punpcklwd %%mm0, %%mm0 \n\t"
  437. "punpckldq %%mm0, %%mm0 \n\t"
  438. "movq %%mm0, -8(%0) \n\t"
  439. "movq -8(%0, %2), %%mm1 \n\t"
  440. "punpckhbw %%mm1, %%mm1 \n\t"
  441. "punpckhwd %%mm1, %%mm1 \n\t"
  442. "punpckhdq %%mm1, %%mm1 \n\t"
  443. "movq %%mm1, (%0, %2) \n\t"
  444. "addl %1, %0 \n\t"
  445. "cmpl %3, %0 \n\t"
  446. " jb 1b \n\t"
  447. : "+r" (ptr)
  448. : "r" (wrap), "r" (width), "r" (ptr + wrap*height)
  449. );
  450. }
  451. else
  452. {
  453. asm volatile(
  454. "1: \n\t"
  455. "movd (%0), %%mm0 \n\t"
  456. "punpcklbw %%mm0, %%mm0 \n\t"
  457. "punpcklwd %%mm0, %%mm0 \n\t"
  458. "punpckldq %%mm0, %%mm0 \n\t"
  459. "movq %%mm0, -8(%0) \n\t"
  460. "movq %%mm0, -16(%0) \n\t"
  461. "movq -8(%0, %2), %%mm1 \n\t"
  462. "punpckhbw %%mm1, %%mm1 \n\t"
  463. "punpckhwd %%mm1, %%mm1 \n\t"
  464. "punpckhdq %%mm1, %%mm1 \n\t"
  465. "movq %%mm1, (%0, %2) \n\t"
  466. "movq %%mm1, 8(%0, %2) \n\t"
  467. "addl %1, %0 \n\t"
  468. "cmpl %3, %0 \n\t"
  469. " jb 1b \n\t"
  470. : "+r" (ptr)
  471. : "r" (wrap), "r" (width), "r" (ptr + wrap*height)
  472. );
  473. }
  474. for(i=0;i<w;i+=4) {
  475. /* top and bottom (and hopefully also the corners) */
  476. ptr= buf - (i + 1) * wrap - w;
  477. asm volatile(
  478. "1: \n\t"
  479. "movq (%1, %0), %%mm0 \n\t"
  480. "movq %%mm0, (%0) \n\t"
  481. "movq %%mm0, (%0, %2) \n\t"
  482. "movq %%mm0, (%0, %2, 2) \n\t"
  483. "movq %%mm0, (%0, %3) \n\t"
  484. "addl $8, %0 \n\t"
  485. "cmpl %4, %0 \n\t"
  486. " jb 1b \n\t"
  487. : "+r" (ptr)
  488. : "r" ((int)buf - (int)ptr - w), "r" (-wrap), "r" (-wrap*3), "r" (ptr+width+2*w)
  489. );
  490. ptr= last_line + (i + 1) * wrap - w;
  491. asm volatile(
  492. "1: \n\t"
  493. "movq (%1, %0), %%mm0 \n\t"
  494. "movq %%mm0, (%0) \n\t"
  495. "movq %%mm0, (%0, %2) \n\t"
  496. "movq %%mm0, (%0, %2, 2) \n\t"
  497. "movq %%mm0, (%0, %3) \n\t"
  498. "addl $8, %0 \n\t"
  499. "cmpl %4, %0 \n\t"
  500. " jb 1b \n\t"
  501. : "+r" (ptr)
  502. : "r" ((int)last_line - (int)ptr - w), "r" (wrap), "r" (wrap*3), "r" (ptr+width+2*w)
  503. );
  504. }
  505. }
  506. static void denoise_dct_mmx(MpegEncContext *s, DCTELEM *block){
  507. const int intra= s->mb_intra;
  508. int *sum= s->dct_error_sum[intra];
  509. uint16_t *offset= s->dct_offset[intra];
  510. s->dct_count[intra]++;
  511. asm volatile(
  512. "pxor %%mm7, %%mm7 \n\t"
  513. "1: \n\t"
  514. "pxor %%mm0, %%mm0 \n\t"
  515. "pxor %%mm1, %%mm1 \n\t"
  516. "movq (%0), %%mm2 \n\t"
  517. "movq 8(%0), %%mm3 \n\t"
  518. "pcmpgtw %%mm2, %%mm0 \n\t"
  519. "pcmpgtw %%mm3, %%mm1 \n\t"
  520. "pxor %%mm0, %%mm2 \n\t"
  521. "pxor %%mm1, %%mm3 \n\t"
  522. "psubw %%mm0, %%mm2 \n\t"
  523. "psubw %%mm1, %%mm3 \n\t"
  524. "movq %%mm2, %%mm4 \n\t"
  525. "movq %%mm3, %%mm5 \n\t"
  526. "psubusw (%2), %%mm2 \n\t"
  527. "psubusw 8(%2), %%mm3 \n\t"
  528. "pxor %%mm0, %%mm2 \n\t"
  529. "pxor %%mm1, %%mm3 \n\t"
  530. "psubw %%mm0, %%mm2 \n\t"
  531. "psubw %%mm1, %%mm3 \n\t"
  532. "movq %%mm2, (%0) \n\t"
  533. "movq %%mm3, 8(%0) \n\t"
  534. "movq %%mm4, %%mm2 \n\t"
  535. "movq %%mm5, %%mm3 \n\t"
  536. "punpcklwd %%mm7, %%mm4 \n\t"
  537. "punpckhwd %%mm7, %%mm2 \n\t"
  538. "punpcklwd %%mm7, %%mm5 \n\t"
  539. "punpckhwd %%mm7, %%mm3 \n\t"
  540. "paddd (%1), %%mm4 \n\t"
  541. "paddd 8(%1), %%mm2 \n\t"
  542. "paddd 16(%1), %%mm5 \n\t"
  543. "paddd 24(%1), %%mm3 \n\t"
  544. "movq %%mm4, (%1) \n\t"
  545. "movq %%mm2, 8(%1) \n\t"
  546. "movq %%mm5, 16(%1) \n\t"
  547. "movq %%mm3, 24(%1) \n\t"
  548. "addl $16, %0 \n\t"
  549. "addl $32, %1 \n\t"
  550. "addl $16, %2 \n\t"
  551. "cmpl %3, %0 \n\t"
  552. " jb 1b \n\t"
  553. : "+r" (block), "+r" (sum), "+r" (offset)
  554. : "r"(block+64)
  555. );
  556. }
  557. static void denoise_dct_sse2(MpegEncContext *s, DCTELEM *block){
  558. const int intra= s->mb_intra;
  559. int *sum= s->dct_error_sum[intra];
  560. uint16_t *offset= s->dct_offset[intra];
  561. s->dct_count[intra]++;
  562. asm volatile(
  563. "pxor %%xmm7, %%xmm7 \n\t"
  564. "1: \n\t"
  565. "pxor %%xmm0, %%xmm0 \n\t"
  566. "pxor %%xmm1, %%xmm1 \n\t"
  567. "movdqa (%0), %%xmm2 \n\t"
  568. "movdqa 16(%0), %%xmm3 \n\t"
  569. "pcmpgtw %%xmm2, %%xmm0 \n\t"
  570. "pcmpgtw %%xmm3, %%xmm1 \n\t"
  571. "pxor %%xmm0, %%xmm2 \n\t"
  572. "pxor %%xmm1, %%xmm3 \n\t"
  573. "psubw %%xmm0, %%xmm2 \n\t"
  574. "psubw %%xmm1, %%xmm3 \n\t"
  575. "movdqa %%xmm2, %%xmm4 \n\t"
  576. "movdqa %%xmm3, %%xmm5 \n\t"
  577. "psubusw (%2), %%xmm2 \n\t"
  578. "psubusw 16(%2), %%xmm3 \n\t"
  579. "pxor %%xmm0, %%xmm2 \n\t"
  580. "pxor %%xmm1, %%xmm3 \n\t"
  581. "psubw %%xmm0, %%xmm2 \n\t"
  582. "psubw %%xmm1, %%xmm3 \n\t"
  583. "movdqa %%xmm2, (%0) \n\t"
  584. "movdqa %%xmm3, 16(%0) \n\t"
  585. "movdqa %%xmm4, %%xmm6 \n\t"
  586. "movdqa %%xmm5, %%xmm0 \n\t"
  587. "punpcklwd %%xmm7, %%xmm4 \n\t"
  588. "punpckhwd %%xmm7, %%xmm6 \n\t"
  589. "punpcklwd %%xmm7, %%xmm5 \n\t"
  590. "punpckhwd %%xmm7, %%xmm0 \n\t"
  591. "paddd (%1), %%xmm4 \n\t"
  592. "paddd 16(%1), %%xmm6 \n\t"
  593. "paddd 32(%1), %%xmm5 \n\t"
  594. "paddd 48(%1), %%xmm0 \n\t"
  595. "movdqa %%xmm4, (%1) \n\t"
  596. "movdqa %%xmm6, 16(%1) \n\t"
  597. "movdqa %%xmm5, 32(%1) \n\t"
  598. "movdqa %%xmm0, 48(%1) \n\t"
  599. "addl $32, %0 \n\t"
  600. "addl $64, %1 \n\t"
  601. "addl $32, %2 \n\t"
  602. "cmpl %3, %0 \n\t"
  603. " jb 1b \n\t"
  604. : "+r" (block), "+r" (sum), "+r" (offset)
  605. : "r"(block+64)
  606. );
  607. }
  608. #undef HAVE_MMX2
  609. #define RENAME(a) a ## _MMX
  610. #define RENAMEl(a) a ## _mmx
  611. #include "mpegvideo_mmx_template.c"
  612. #define HAVE_MMX2
  613. #undef RENAME
  614. #undef RENAMEl
  615. #define RENAME(a) a ## _MMX2
  616. #define RENAMEl(a) a ## _mmx2
  617. #include "mpegvideo_mmx_template.c"
  618. #undef RENAME
  619. #undef RENAMEl
  620. #define RENAME(a) a ## _SSE2
  621. #define RENAMEl(a) a ## _sse2
  622. #include "mpegvideo_mmx_template.c"
  623. void MPV_common_init_mmx(MpegEncContext *s)
  624. {
  625. if (mm_flags & MM_MMX) {
  626. const int dct_algo = s->avctx->dct_algo;
  627. s->dct_unquantize_h263_intra = dct_unquantize_h263_intra_mmx;
  628. s->dct_unquantize_h263_inter = dct_unquantize_h263_inter_mmx;
  629. s->dct_unquantize_mpeg1_intra = dct_unquantize_mpeg1_intra_mmx;
  630. s->dct_unquantize_mpeg1_inter = dct_unquantize_mpeg1_inter_mmx;
  631. s->dct_unquantize_mpeg2_intra = dct_unquantize_mpeg2_intra_mmx;
  632. s->dct_unquantize_mpeg2_inter = dct_unquantize_mpeg2_inter_mmx;
  633. draw_edges = draw_edges_mmx;
  634. if (mm_flags & MM_SSE2) {
  635. s->denoise_dct= denoise_dct_sse2;
  636. } else {
  637. s->denoise_dct= denoise_dct_mmx;
  638. }
  639. if(dct_algo==FF_DCT_AUTO || dct_algo==FF_DCT_MMX){
  640. if(mm_flags & MM_SSE2){
  641. s->dct_quantize= dct_quantize_SSE2;
  642. } else if(mm_flags & MM_MMXEXT){
  643. s->dct_quantize= dct_quantize_MMX2;
  644. } else {
  645. s->dct_quantize= dct_quantize_MMX;
  646. }
  647. }
  648. }
  649. }