vd.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:26k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. // VirtualDub - Video processing and capture application
  2. // Copyright (C) 1998-2001 Avery Lee
  3. //
  4. // This program is free software; you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation; either version 2 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // This program 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
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with this program; if not, write to the Free Software
  16. // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. //
  18. //  Notes: 
  19. //  - BitBltFromI420ToRGB is from VirtualDub
  20. // - The core assembly function of CCpuID is from DVD2AVI
  21. // (- vd.cpp/h should be renamed to something more sensible already :)
  22. #include "stdafx.h"
  23. #include "vd.h"
  24. #pragma warning(disable : 4799) // no emms... blahblahblah
  25. #define ReadTSC( x ) __asm cpuid 
  26. __asm rdtsc 
  27. __asm mov dword ptr x,eax 
  28. __asm mov dword ptr x+4,edx
  29. CCpuID::CCpuID()
  30. {
  31. DWORD flags = 0;
  32. __asm
  33. {
  34. mov eax, 1
  35. cpuid
  36. test edx, 0x00800000 // STD MMX
  37. jz TEST_SSE
  38. or [flags], 1
  39. TEST_SSE:
  40. test edx, 0x02000000 // STD SSE
  41. jz TEST_SSE2
  42. or [flags], 2
  43. or [flags], 4
  44. TEST_SSE2:
  45. test edx, 0x04000000 // SSE2
  46. jz TEST_3DNOW
  47. or [flags], 8
  48. TEST_3DNOW:
  49. mov eax, 0x80000001
  50. cpuid
  51. test edx, 0x80000000 // 3D NOW
  52. jz TEST_SSEMMX
  53. or [flags], 16
  54. TEST_SSEMMX:
  55. test edx, 0x00400000 // SSE MMX
  56. jz TEST_END
  57. or [flags], 2
  58. TEST_END:
  59. }
  60. m_flags = (flag_t)flags;
  61. }
  62. CCpuID g_cpuid;
  63. void memcpy_accel(void* dst, const void* src, size_t len)
  64. {
  65. if((g_cpuid.m_flags & CCpuID::sse2) && len >= 128 
  66. && !((DWORD)src&15) && !((DWORD)dst&15))
  67. {
  68. __asm
  69. {
  70. mov     esi, dword ptr [src]
  71. mov     edi, dword ptr [dst]
  72. mov     ecx, len
  73. shr     ecx, 7
  74. memcpy_accel_sse2_loop:
  75. prefetchnta [esi+16*8]
  76. movdqa xmm0, [esi]
  77. movdqa xmm1, [esi+16*1]
  78. movdqa xmm2, [esi+16*2]
  79. movdqa xmm3, [esi+16*3]
  80. movdqa xmm4, [esi+16*4]
  81. movdqa xmm5, [esi+16*5]
  82. movdqa xmm6, [esi+16*6]
  83. movdqa xmm7, [esi+16*7]
  84. movntps [edi], xmm0
  85. movntps [edi+16*1], xmm1
  86. movntps [edi+16*2], xmm2
  87. movntps [edi+16*3], xmm3
  88. movntps [edi+16*4], xmm4
  89. movntps [edi+16*5], xmm5
  90. movntps [edi+16*6], xmm6
  91. movntps [edi+16*7], xmm7
  92. add esi, 128
  93. add edi, 128
  94. dec ecx
  95. jnz memcpy_accel_sse2_loop
  96. mov     ecx, len
  97. and     ecx, 127
  98. cmp     ecx, 0
  99. je memcpy_accel_sse2_end
  100. memcpy_accel_sse2_loop2:
  101. mov dl, byte ptr[esi] 
  102. mov byte ptr[edi], dl
  103. inc esi
  104. inc edi
  105. dec ecx
  106. jne memcpy_accel_sse2_loop2
  107. memcpy_accel_sse2_end:
  108. emms
  109. sfence
  110. }
  111. }
  112. else if((g_cpuid.m_flags & CCpuID::ssefpu) && len >= 128 
  113. && !((DWORD)src&15) && !((DWORD)dst&15))
  114. {
  115. __asm
  116. {
  117. mov     esi, dword ptr [src]
  118. mov     edi, dword ptr [dst]
  119. mov     ecx, len
  120. shr     ecx, 7
  121. memcpy_accel_sse_loop:
  122. prefetchnta [esi+16*8]
  123. movaps xmm0, [esi]
  124. movaps xmm1, [esi+16*1]
  125. movaps xmm2, [esi+16*2]
  126. movaps xmm3, [esi+16*3]
  127. movaps xmm4, [esi+16*4]
  128. movaps xmm5, [esi+16*5]
  129. movaps xmm6, [esi+16*6]
  130. movaps xmm7, [esi+16*7]
  131. movntps [edi], xmm0
  132. movntps [edi+16*1], xmm1
  133. movntps [edi+16*2], xmm2
  134. movntps [edi+16*3], xmm3
  135. movntps [edi+16*4], xmm4
  136. movntps [edi+16*5], xmm5
  137. movntps [edi+16*6], xmm6
  138. movntps [edi+16*7], xmm7
  139. add esi, 128
  140. add edi, 128
  141. dec ecx
  142. jnz memcpy_accel_sse_loop
  143. mov     ecx, len
  144. and     ecx, 127
  145. cmp     ecx, 0
  146. je memcpy_accel_sse_end
  147. memcpy_accel_sse_loop2:
  148. mov dl, byte ptr[esi] 
  149. mov byte ptr[edi], dl
  150. inc esi
  151. inc edi
  152. dec ecx
  153. jne memcpy_accel_sse_loop2
  154. memcpy_accel_sse_end:
  155. emms
  156. sfence
  157. }
  158. }
  159. else if((g_cpuid.m_flags & CCpuID::mmx) && len >= 64
  160. && !((DWORD)src&7) && !((DWORD)dst&7))
  161. {
  162. __asm 
  163. {
  164. mov     esi, dword ptr [src]
  165. mov     edi, dword ptr [dst]
  166. mov     ecx, len
  167. shr     ecx, 6
  168. memcpy_accel_mmx_loop:
  169. movq    mm0, qword ptr [esi]
  170. movq    mm1, qword ptr [esi+8*1]
  171. movq    mm2, qword ptr [esi+8*2]
  172. movq    mm3, qword ptr [esi+8*3]
  173. movq    mm4, qword ptr [esi+8*4]
  174. movq    mm5, qword ptr [esi+8*5]
  175. movq    mm6, qword ptr [esi+8*6]
  176. movq    mm7, qword ptr [esi+8*7]
  177. movq    qword ptr [edi], mm0
  178. movq    qword ptr [edi+8*1], mm1
  179. movq    qword ptr [edi+8*2], mm2
  180. movq    qword ptr [edi+8*3], mm3
  181. movq    qword ptr [edi+8*4], mm4
  182. movq    qword ptr [edi+8*5], mm5
  183. movq    qword ptr [edi+8*6], mm6
  184. movq    qword ptr [edi+8*7], mm7
  185. add     esi, 64
  186. add     edi, 64
  187. dec ecx
  188. jnz memcpy_accel_mmx_loop
  189. mov     ecx, len
  190. and     ecx, 63
  191. cmp     ecx, 0
  192. je memcpy_accel_mmx_end
  193. memcpy_accel_mmx_loop2:
  194. mov dl, byte ptr [esi] 
  195. mov byte ptr [edi], dl
  196. inc esi
  197. inc edi
  198. dec ecx
  199. jne memcpy_accel_mmx_loop2
  200. memcpy_accel_mmx_end:
  201. emms
  202. }
  203. }
  204. else
  205. {
  206. memcpy(dst, src, len);
  207. }
  208. }
  209. bool BitBltFromI420ToI420(int w, int h, BYTE* dsty, BYTE* dstu, BYTE* dstv, int dstpitch, BYTE* srcy, BYTE* srcu, BYTE* srcv, int srcpitch)
  210. {
  211. if(w&1) return(false);
  212. int pitch = min(abs(srcpitch), abs(dstpitch));
  213. for(int y = 0; y < h; y++, srcy += srcpitch, dsty += dstpitch)
  214. memcpy_accel(dsty, srcy, pitch);
  215. srcpitch >>= 1;
  216. dstpitch >>= 1;
  217. pitch = min(abs(srcpitch), abs(dstpitch));
  218. for(int y = 0; y < h; y+=2, srcu += srcpitch, dstu += dstpitch)
  219. memcpy_accel(dstu, srcu, pitch);
  220. for(int y = 0; y < h; y+=2, srcv += srcpitch, dstv += dstpitch)
  221. memcpy_accel(dstv, srcv, pitch);
  222. return(true);
  223. }
  224. bool BitBltFromYUY2ToYUY2(int w, int h, BYTE* dst, int dstpitch, BYTE* src, int srcpitch)
  225. {
  226. int pitch = min(abs(srcpitch), abs(dstpitch));
  227. for(int y = 0; y < h; y++, src += srcpitch, dst += dstpitch)
  228. memcpy_accel(dst, src, pitch);
  229. return(true);
  230. }
  231. extern "C" void asm_YUVtoRGB32_row(void* ARGB1, void* ARGB2, BYTE* Y1, BYTE* Y2, BYTE* U, BYTE* V, long width);
  232. extern "C" void asm_YUVtoRGB24_row(void* ARGB1, void* ARGB2, BYTE* Y1, BYTE* Y2, BYTE* U, BYTE* V, long width);
  233. extern "C" void asm_YUVtoRGB16_row(void* ARGB1, void* ARGB2, BYTE* Y1, BYTE* Y2, BYTE* U, BYTE* V, long width);
  234. extern "C" void asm_YUVtoRGB32_row_MMX(void* ARGB1, void* ARGB2, BYTE* Y1, BYTE* Y2, BYTE* U, BYTE* V, long width);
  235. extern "C" void asm_YUVtoRGB24_row_MMX(void* ARGB1, void* ARGB2, BYTE* Y1, BYTE* Y2, BYTE* U, BYTE* V, long width);
  236. extern "C" void asm_YUVtoRGB16_row_MMX(void* ARGB1, void* ARGB2, BYTE* Y1, BYTE* Y2, BYTE* U, BYTE* V, long width);
  237. extern "C" void asm_YUVtoRGB32_row_ISSE(void* ARGB1, void* ARGB2, BYTE* Y1, BYTE* Y2, BYTE* U, BYTE* V, long width);
  238. extern "C" void asm_YUVtoRGB24_row_ISSE(void* ARGB1, void* ARGB2, BYTE* Y1, BYTE* Y2, BYTE* U, BYTE* V, long width);
  239. extern "C" void asm_YUVtoRGB16_row_ISSE(void* ARGB1, void* ARGB2, BYTE* Y1, BYTE* Y2, BYTE* U, BYTE* V, long width);
  240. bool BitBltFromI420ToRGB(int w, int h, BYTE* dst, int dstpitch, int dbpp, BYTE* srcy, BYTE* srcu, BYTE* srcv, int srcpitch)
  241. {
  242. if(w<=0 || h<=0 || (w&1) || (h&1))
  243. return(false);
  244. void (*asm_YUVtoRGB_row)(void* ARGB1, void* ARGB2, BYTE* Y1, BYTE* Y2, BYTE* U, BYTE* V, long width) = NULL;;
  245. if((g_cpuid.m_flags & CCpuID::ssefpu) && !(w&7))
  246. {
  247. switch(dbpp)
  248. {
  249. case 16: asm_YUVtoRGB_row = asm_YUVtoRGB16_row/*_ISSE*/; break; // TODO: fix _ISSE (555->565)
  250. case 24: asm_YUVtoRGB_row = asm_YUVtoRGB24_row_ISSE; break;
  251. case 32: asm_YUVtoRGB_row = asm_YUVtoRGB32_row_ISSE; break;
  252. }
  253. }
  254. else if((g_cpuid.m_flags & CCpuID::mmx) && !(w&7))
  255. {
  256. switch(dbpp)
  257. {
  258. case 16: asm_YUVtoRGB_row = asm_YUVtoRGB16_row/*_MMX*/; break; // TODO: fix _MMX (555->565)
  259. case 24: asm_YUVtoRGB_row = asm_YUVtoRGB24_row_MMX; break;
  260. case 32: asm_YUVtoRGB_row = asm_YUVtoRGB32_row_MMX; break;
  261. }
  262. }
  263. else
  264. {
  265. switch(dbpp)
  266. {
  267. case 16: asm_YUVtoRGB_row = asm_YUVtoRGB16_row; break;
  268. case 24: asm_YUVtoRGB_row = asm_YUVtoRGB24_row; break;
  269. case 32: asm_YUVtoRGB_row = asm_YUVtoRGB32_row; break;
  270. }
  271. }
  272. if(!asm_YUVtoRGB_row) 
  273. return(false);
  274. do
  275. {
  276. asm_YUVtoRGB_row(dst + dstpitch, dst, srcy + srcpitch, srcy, srcu, srcv, w/2);
  277. dst += 2*dstpitch;
  278. srcy += srcpitch*2;
  279. srcu += srcpitch/2;
  280. srcv += srcpitch/2;
  281. }
  282. while(h -= 2);
  283. if(g_cpuid.m_flags & CCpuID::mmx)
  284. __asm emms
  285. if(g_cpuid.m_flags & CCpuID::ssefpu)
  286. __asm sfence
  287. return true;
  288. }
  289. static void yuvtoyuy2row_c(BYTE* dst, BYTE* srcy, BYTE* srcu, BYTE* srcv, DWORD width)
  290. {
  291. WORD* dstw = (WORD*)dst;
  292. for(; width > 1; width -= 2)
  293. {
  294. *dstw++ = (*srcu++<<8)|*srcy++;
  295. *dstw++ = (*srcv++<<8)|*srcy++;
  296. }
  297. }
  298. static void __declspec(naked) yuvtoyuy2row_MMX(BYTE* dst, BYTE* srcy, BYTE* srcu, BYTE* srcv, DWORD width)
  299. {
  300. __asm {
  301. push ebp
  302. push edi
  303. push esi
  304. push ebx
  305. mov edi, [esp+20] // dst
  306. mov ebp, [esp+24] // srcy
  307. mov ebx, [esp+28] // srcu
  308. mov esi, [esp+32] // srcv
  309. mov ecx, [esp+36] // width
  310. shr ecx, 3
  311. yuvtoyuy2row_loop:
  312. movd mm0, [ebx]
  313. punpcklbw mm0, [esi]
  314. movq mm1, [ebp]
  315. movq mm2, mm1
  316. punpcklbw mm1, mm0
  317. punpckhbw mm2, mm0
  318. movq [edi], mm1
  319. movq [edi+8], mm2
  320. add ebp, 8
  321. add ebx, 4
  322. add esi, 4
  323.         add edi, 16
  324. dec ecx
  325. jnz yuvtoyuy2row_loop
  326. pop ebx
  327. pop esi
  328. pop edi
  329. pop ebp
  330. ret
  331. };
  332. }
  333. static void yuvtoyuy2row_avg_c(BYTE* dst, BYTE* srcy, BYTE* srcu, BYTE* srcv, DWORD width, DWORD pitchuv)
  334. {
  335. WORD* dstw = (WORD*)dst;
  336. for(; width > 1; width -= 2, srcu++, srcv++)
  337. {
  338. *dstw++ = (((srcu[0]+srcu[pitchuv])>>1)<<8)|*srcy++;
  339. *dstw++ = (((srcv[0]+srcv[pitchuv])>>1)<<8)|*srcy++;
  340. }
  341. }
  342. static void __declspec(naked) yuvtoyuy2row_avg_MMX(BYTE* dst, BYTE* srcy, BYTE* srcu, BYTE* srcv, DWORD width, DWORD pitchuv)
  343. {
  344. static const __int64 mask = 0x7f7f7f7f7f7f7f7fi64;
  345. __asm {
  346. push ebp
  347. push edi
  348. push esi
  349. push ebx
  350. movq mm7, mask
  351. mov edi, [esp+20] // dst
  352. mov ebp, [esp+24] // srcy
  353. mov ebx, [esp+28] // srcu
  354. mov esi, [esp+32] // srcv
  355. mov ecx, [esp+36] // width
  356. mov eax, [esp+40] // pitchuv
  357. shr ecx, 3
  358. yuvtoyuy2row_avg_loop:
  359. movd mm0, [ebx]
  360. punpcklbw mm0, [esi]
  361. movq mm1, mm0
  362. movd mm2, [ebx + eax]
  363. punpcklbw mm2, [esi + eax]
  364. movq mm3, mm2
  365. // (x+y)>>1 == (x&y)+((x^y)>>1)
  366. pand mm0, mm2
  367. pxor mm1, mm3
  368. psrlq mm1, 1
  369. pand mm1, mm7
  370. paddb mm0, mm1
  371. movq mm1, [ebp]
  372. movq mm2, mm1
  373. punpcklbw mm1, mm0
  374. punpckhbw mm2, mm0
  375. movq [edi], mm1
  376. movq [edi+8], mm2
  377. add ebp, 8
  378. add ebx, 4
  379. add esi, 4
  380.         add edi, 16
  381. dec ecx
  382. jnz yuvtoyuy2row_avg_loop
  383. pop ebx
  384. pop esi
  385. pop edi
  386. pop ebp
  387. ret
  388. };
  389. }
  390. bool BitBltFromI420ToYUY2(int w, int h, BYTE* dst, int dstpitch, BYTE* srcy, BYTE* srcu, BYTE* srcv, int srcpitch)
  391. {
  392. if(w<=0 || h<=0 || (w&1) || (h&1))
  393. return(false);
  394. if(srcpitch == 0) srcpitch = w;
  395. void (*yuvtoyuy2row)(BYTE* dst, BYTE* srcy, BYTE* srcu, BYTE* srcv, DWORD width) = NULL;
  396. void (*yuvtoyuy2row_avg)(BYTE* dst, BYTE* srcy, BYTE* srcu, BYTE* srcv, DWORD width, DWORD pitchuv) = NULL;
  397. if((g_cpuid.m_flags & CCpuID::mmx) && !(w&7))
  398. {
  399. yuvtoyuy2row = yuvtoyuy2row_MMX;
  400. yuvtoyuy2row_avg = yuvtoyuy2row_avg_MMX;
  401. }
  402. else
  403. {
  404. yuvtoyuy2row = yuvtoyuy2row_c;
  405. yuvtoyuy2row_avg = yuvtoyuy2row_avg_c;
  406. }
  407. if(!yuvtoyuy2row) 
  408. return(false);
  409. do
  410. {
  411. yuvtoyuy2row(dst, srcy, srcu, srcv, w);
  412. yuvtoyuy2row_avg(dst + dstpitch, srcy + srcpitch, srcu, srcv, w, srcpitch/2);
  413. dst += 2*dstpitch;
  414. srcy += srcpitch*2;
  415. srcu += srcpitch/2;
  416. srcv += srcpitch/2;
  417. }
  418. while((h -= 2) > 2);
  419. yuvtoyuy2row(dst, srcy, srcu, srcv, w);
  420. yuvtoyuy2row(dst + dstpitch, srcy + srcpitch, srcu, srcv, w);
  421. if(g_cpuid.m_flags & CCpuID::mmx)
  422. __asm emms
  423. return(true);
  424. }
  425. bool BitBltFromRGBToRGB(int w, int h, BYTE* dst, int dstpitch, int dbpp, BYTE* src, int srcpitch, int sbpp)
  426. {
  427. if(dbpp == sbpp)
  428. {
  429. int bytes = w*dbpp>>3;
  430. for(int y = 0; y < h; y++, src += srcpitch, dst += dstpitch)
  431. memcpy_accel(dst, src, bytes);
  432. return(true);
  433. }
  434. if(sbpp != 16 && sbpp != 24 && sbpp != 32
  435. || dbpp != 16 && dbpp != 24 && dbpp != 32)
  436. return(false);
  437. if(dbpp == 16)
  438. {
  439. for(int y = 0; y < h; y++, src += srcpitch, dst += dstpitch)
  440. {
  441. if(sbpp == 24)
  442. {
  443. BYTE* s = (BYTE*)src;
  444. WORD* d = (WORD*)dst;
  445. for(int x = 0; x < w; x++, s+=3, d++)
  446. *d = (WORD)(((*((DWORD*)s)>>8)&0xf800)|((*((DWORD*)s)>>5)&0x07e0)|((*((DWORD*)s)>>3)&0x1f));
  447. }
  448. else if(sbpp == 32)
  449. {
  450. DWORD* s = (DWORD*)src;
  451. WORD* d = (WORD*)dst;
  452. for(int x = 0; x < w; x++, s++, d++)
  453. *d = (WORD)(((*s>>8)&0xf800)|((*s>>5)&0x07e0)|((*s>>3)&0x1f));
  454. }
  455. }
  456. }
  457. else if(dbpp == 24)
  458. {
  459. for(int y = 0; y < h; y++, src += srcpitch, dst += dstpitch)
  460. {
  461. if(sbpp == 16)
  462. {
  463. WORD* s = (WORD*)src;
  464. BYTE* d = (BYTE*)dst;
  465. for(int x = 0; x < w; x++, s++, d+=3)
  466. { // not tested, r-g-b might be in reverse
  467. d[0] = (*s&0x001f)<<3;
  468. d[1] = (*s&0x07e0)<<5;
  469. d[2] = (*s&0xf800)<<8;
  470. }
  471. }
  472. else if(sbpp == 32)
  473. {
  474. BYTE* s = (BYTE*)src;
  475. BYTE* d = (BYTE*)dst;
  476. for(int x = 0; x < w; x++, s+=4, d+=3)
  477. {d[0] = s[0]; d[1] = s[1]; d[2] = s[2];}
  478. }
  479. }
  480. }
  481. else if(dbpp == 32)
  482. {
  483. for(int y = 0; y < h; y++, src += srcpitch, dst += dstpitch)
  484. {
  485. if(sbpp == 16)
  486. {
  487. WORD* s = (WORD*)src;
  488. DWORD* d = (DWORD*)dst;
  489. for(int x = 0; x < w; x++, s++, d++)
  490. *d = ((*s&0xf800)<<8)|((*s&0x07e0)<<5)|((*s&0x001f)<<3);
  491. }
  492. else if(sbpp == 24)
  493. {
  494. BYTE* s = (BYTE*)src;
  495. DWORD* d = (DWORD*)dst;
  496. for(int x = 0; x < w; x++, s+=3, d++)
  497. *d = *((DWORD*)s)&0xffffff;
  498. }
  499. }
  500. }
  501. return(true);
  502. }
  503. static void asm_blend_row_clipped_c(BYTE* dst, BYTE* src, DWORD w, DWORD srcpitch)
  504. {
  505. BYTE* src2 = src + srcpitch;
  506. do {*dst++ = (*src++ + *src2++ + 1) >> 1;}
  507. while(w--);
  508. }
  509. static void asm_blend_row_c(BYTE* dst, BYTE* src, DWORD w, DWORD srcpitch)
  510. {
  511. BYTE* src2 = src + srcpitch;
  512. BYTE* src3 = src2 + srcpitch;
  513. do {*dst++ = (*src++ + (*src2++ << 1) + *src3++ + 2) >> 2;}
  514. while(w--);
  515. }
  516. static void __declspec(naked) asm_blend_row_clipped_MMX(BYTE* dst, BYTE* src, DWORD w, DWORD srcpitch)
  517. {
  518. static const __int64 _x0001000100010001 = 0x0001000100010001;
  519. __asm {
  520. push ebp
  521. push edi
  522. push esi
  523. push ebx
  524. mov edi,[esp+20]
  525. mov esi,[esp+24]
  526. sub edi,esi
  527. mov ebp,[esp+28]
  528. mov edx,[esp+32]
  529. shr ebp, 3
  530. movq mm6, _x0001000100010001
  531. pxor mm7, mm7
  532. xloop:
  533. movq mm0, [esi]
  534. movq mm3, mm0
  535. punpcklbw mm0, mm7
  536. punpckhbw mm3, mm7
  537. movq mm1, [esi+edx]
  538. movq mm4, mm1
  539. punpcklbw mm1, mm7
  540. punpckhbw mm4, mm7
  541. paddw mm1, mm0
  542. paddw mm1, mm6
  543. psrlw mm1, 1
  544. paddw mm4, mm3
  545. paddw mm4, mm6
  546. psrlw mm4, 1
  547. add esi, 8
  548. packuswb mm1, mm4
  549. movq [edi+esi-8], mm1
  550. dec ebp
  551. jne xloop
  552. pop ebx
  553. pop esi
  554. pop edi
  555. pop ebp
  556. ret
  557. };
  558. }
  559. static void __declspec(naked) asm_blend_row_MMX(BYTE* dst, BYTE* src, DWORD w, DWORD srcpitch)
  560. {
  561. static const __int64 mask0 = 0xfcfcfcfcfcfcfcfci64;
  562. static const __int64 mask1 = 0x7f7f7f7f7f7f7f7fi64;
  563. static const __int64 mask2 = 0x3f3f3f3f3f3f3f3fi64;
  564. static const __int64 _x0002000200020002 = 0x0002000200020002;
  565. __asm {
  566. push ebp
  567. push edi
  568. push esi
  569. push ebx
  570. mov edi, [esp+20]
  571. mov esi, [esp+24]
  572. sub edi, esi
  573. mov ebp, [esp+28]
  574. mov edx, [esp+32]
  575. shr ebp, 3
  576. movq mm6, _x0002000200020002
  577. pxor mm7, mm7
  578. xloop:
  579. movq mm0, [esi]
  580. movq mm3, mm0
  581. punpcklbw mm0, mm7
  582. punpckhbw mm3, mm7
  583. movq mm1, [esi+edx]
  584. movq mm4, mm1
  585. punpcklbw mm1, mm7
  586. punpckhbw mm4, mm7
  587. movq mm2, [esi+edx*2]
  588. movq mm5, mm2
  589. punpcklbw mm2, mm7
  590. punpckhbw mm5, mm7
  591. psllw mm1, 1
  592. paddw mm1, mm0
  593. paddw mm1, mm2
  594. paddw mm1, mm6
  595. psrlw mm1, 2
  596. psllw mm4, 1
  597. paddw mm4, mm3
  598. paddw mm4, mm5
  599. paddw mm4, mm6
  600. psrlw mm4, 2
  601. add esi, 8
  602. packuswb mm1, mm4
  603. movq [edi+esi-8], mm1
  604. dec ebp
  605. jne xloop
  606. // sadly the original code makes a lot of visible banding artifacts on yuv
  607. // (it seems those shiftings without rounding introduce too much error)
  608. /*
  609. mov edi,[esp+20]
  610. mov esi,[esp+24]
  611. sub edi,esi
  612. mov ebp,[esp+28]
  613. mov edx,[esp+32]
  614. movq mm5,mask0
  615. movq mm6,mask1
  616. movq mm7,mask2
  617. shr ebp,1
  618. jz oddpart
  619. xloop:
  620. movq mm2,[esi]
  621. movq mm0,mm5
  622. movq mm1,[esi+edx]
  623. pand mm0,mm2
  624. psrlq mm1,1
  625. movq mm2,[esi+edx*2]
  626. psrlq mm2,2
  627. pand mm1,mm6
  628. psrlq mm0,2
  629. pand mm2,mm7
  630. paddb mm0,mm1
  631. add esi,8
  632. paddb mm0,mm2
  633. dec ebp
  634. movq [edi+esi-8],mm0
  635. jne xloop
  636. oddpart:
  637. test byte ptr [esp+28],1
  638. jz nooddpart
  639. mov ecx,[esi]
  640. mov eax,0fcfcfcfch
  641. mov ebx,[esi+edx]
  642. and eax,ecx
  643. shr ebx,1
  644. mov ecx,[esi+edx*2]
  645. shr ecx,2
  646. and ebx,07f7f7f7fh
  647. shr eax,2
  648. and ecx,03f3f3f3fh
  649. add eax,ebx
  650. add eax,ecx
  651. mov [edi+esi],eax
  652. nooddpart:
  653. */
  654. pop ebx
  655. pop esi
  656. pop edi
  657. pop ebp
  658. ret
  659. };
  660. }
  661. __declspec(align(16)) static BYTE const_1_16_bytes[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
  662. static void asm_blend_row_SSE2(BYTE* dst, BYTE* src, DWORD w, DWORD srcpitch)
  663. {
  664. __asm
  665. {
  666. mov edx, srcpitch
  667. mov esi, src
  668. mov edi, dst
  669. sub edi, esi
  670. mov ecx, w
  671. mov ebx, ecx
  672. shr ecx, 4
  673. and ebx, 15
  674. movdqa xmm7, [const_1_16_bytes] 
  675. asm_blend_row_SSE2_loop:
  676. movdqa xmm0, [esi]
  677. movdqa xmm1, [esi+edx]
  678. movdqa xmm2, [esi+edx*2]
  679. pavgb xmm0, xmm1
  680. pavgb xmm2, xmm1
  681. psubusb xmm0, xmm7
  682. pavgb xmm0, xmm2
  683. movdqa [esi+edi], xmm0
  684. add esi, 16
  685. dec ecx
  686. jnz asm_blend_row_SSE2_loop
  687. test ebx,15
  688. jz asm_blend_row_SSE2_end
  689. mov ecx, ebx
  690. xor ax, ax
  691. xor bx, bx
  692. xor dx, dx
  693. asm_blend_row_SSE2_loop2:
  694. mov al, [esi]
  695. mov bl, [esi+edx]
  696. mov dl, [esi+edx*2]
  697. add ax, bx
  698. inc ax
  699. shr ax, 1
  700. add dx, bx
  701. inc dx
  702. shr dx, 1
  703. add ax, dx
  704. shr ax, 1
  705. mov [esi+edi], al
  706. inc esi
  707. dec ecx
  708. jnz asm_blend_row_SSE2_loop2
  709. asm_blend_row_SSE2_end:
  710. }
  711. }
  712. static void asm_blend_row_clipped_SSE2(BYTE* dst, BYTE* src, DWORD w, DWORD srcpitch)
  713. {
  714. __asm
  715. {
  716. mov edx, srcpitch
  717. mov esi, src
  718. mov edi, dst
  719. sub edi, esi
  720. mov ecx, w
  721. mov ebx, ecx
  722. shr ecx, 4
  723. and ebx, 15
  724. movdqa xmm7, [const_1_16_bytes] 
  725. asm_blend_row_clipped_SSE2_loop:
  726. movdqa xmm0, [esi]
  727. movdqa xmm1, [esi+edx]
  728. pavgb xmm0, xmm1
  729. movdqa [esi+edi], xmm0
  730. add esi, 16
  731. dec ecx
  732. jnz asm_blend_row_clipped_SSE2_loop
  733. test ebx,15
  734. jz asm_blend_row_clipped_SSE2_end
  735. mov ecx, ebx
  736. xor ax, ax
  737. xor bx, bx
  738. asm_blend_row_clipped_SSE2_loop2:
  739. mov al, [esi]
  740. mov bl, [esi+edx]
  741. add ax, bx
  742. inc ax
  743. shr ax, 1
  744. mov [esi+edi], al
  745. inc esi
  746. dec ecx
  747. jnz asm_blend_row_clipped_SSE2_loop2
  748. asm_blend_row_clipped_SSE2_end:
  749. }
  750. }
  751. void DeinterlaceBlend(BYTE* dst, BYTE* src, DWORD rowbytes, DWORD h, DWORD dstpitch, DWORD srcpitch)
  752. {
  753. void (*asm_blend_row_clipped)(BYTE* dst, BYTE* src, DWORD w, DWORD srcpitch) = NULL;
  754. void (*asm_blend_row)(BYTE* dst, BYTE* src, DWORD w, DWORD srcpitch) = NULL;
  755. if((g_cpuid.m_flags & CCpuID::sse2) && !((DWORD)src&0xf) && !((DWORD)dst&0xf) && !(srcpitch&0xf))
  756. {
  757. asm_blend_row_clipped = asm_blend_row_clipped_SSE2;
  758. asm_blend_row = asm_blend_row_SSE2;
  759. }
  760. else if(g_cpuid.m_flags & CCpuID::mmx)
  761. {
  762. asm_blend_row_clipped = asm_blend_row_clipped_MMX;
  763. asm_blend_row = asm_blend_row_MMX;
  764. }
  765. else
  766. {
  767. asm_blend_row_clipped = asm_blend_row_clipped_c;
  768. asm_blend_row = asm_blend_row_c;
  769. }
  770. if(!asm_blend_row_clipped)
  771. return;
  772. asm_blend_row_clipped(dst, src, rowbytes, srcpitch);
  773. if((h -= 2) > 0) do
  774. {
  775. dst += dstpitch;
  776. asm_blend_row(dst, src, rowbytes, srcpitch);
  777.         src += srcpitch;
  778. }
  779. while(--h);
  780. asm_blend_row_clipped(dst + dstpitch, src, rowbytes, srcpitch);
  781. if(g_cpuid.m_flags & CCpuID::mmx)
  782. __asm emms
  783. }
  784. void AvgLines8(BYTE* dst, DWORD h, DWORD pitch)
  785. {
  786. if(h <= 1) return;
  787. BYTE* s = dst;
  788. BYTE* d = dst + (h-2)*pitch;
  789. for(; s < d; s += pitch*2)
  790. {
  791. BYTE* tmp = s;
  792. if((g_cpuid.m_flags & CCpuID::sse2) && !((DWORD)tmp&0xf) && !((DWORD)pitch&0xf))
  793. {
  794. __asm
  795. {
  796. mov esi, tmp
  797. mov ebx, pitch
  798. mov ecx, ebx
  799. shr ecx, 4
  800. AvgLines8_sse2_loop:
  801. movdqa xmm0, [esi]
  802. pavgb xmm0, [esi+ebx*2]
  803. movdqa [esi+ebx], xmm0
  804. add esi, 16
  805. dec ecx
  806. jnz AvgLines8_sse2_loop
  807. mov tmp, esi
  808. }
  809. for(int i = pitch&7; i--; tmp++)
  810. {
  811. tmp[pitch] = (tmp[0] + tmp[pitch<<1] + 1) >> 1;
  812. }
  813. }
  814. else if(g_cpuid.m_flags & CCpuID::mmx)
  815. {
  816. __asm
  817. {
  818. mov esi, tmp
  819. mov ebx, pitch
  820. mov ecx, ebx
  821. shr ecx, 3
  822. pxor mm7, mm7
  823. AvgLines8_mmx_loop:
  824. movq mm0, [esi]
  825. movq mm1, mm0
  826. punpcklbw mm0, mm7
  827. punpckhbw mm1, mm7
  828. movq mm2, [esi+ebx*2]
  829. movq mm3, mm2
  830. punpcklbw mm2, mm7
  831. punpckhbw mm3, mm7
  832. paddw mm0, mm2
  833. psrlw mm0, 1
  834. paddw mm1, mm3
  835. psrlw mm1, 1
  836. packuswb mm0, mm1
  837. movq [esi+ebx], mm0
  838. lea esi, [esi+8]
  839. dec ecx
  840. jnz AvgLines8_mmx_loop
  841. mov tmp, esi
  842. }
  843. for(int i = pitch&7; i--; tmp++)
  844. {
  845. tmp[pitch] = (tmp[0] + tmp[pitch<<1] + 1) >> 1;
  846. }
  847. }
  848. else
  849. {
  850. for(int i = pitch; i--; tmp++)
  851. {
  852. tmp[pitch] = (tmp[0] + tmp[pitch<<1] + 1) >> 1;
  853. }
  854. }
  855. }
  856. if(!(h&1) && h >= 2)
  857. {
  858. dst += (h-2)*pitch;
  859. memcpy_accel(dst + pitch, dst, pitch);
  860. }
  861. __asm emms;
  862. }
  863. void AvgLines555(BYTE* dst, DWORD h, DWORD pitch)
  864. {
  865. if(h <= 1) return;
  866. unsigned __int64 __0x7c007c007c007c00 = 0x7c007c007c007c00;
  867. unsigned __int64 __0x03e003e003e003e0 = 0x03e003e003e003e0;
  868. unsigned __int64 __0x001f001f001f001f = 0x001f001f001f001f;
  869. BYTE* s = dst;
  870. BYTE* d = dst + (h-2)*pitch;
  871. for(; s < d; s += pitch*2)
  872. {
  873. BYTE* tmp = s;
  874. __asm
  875. {
  876. mov esi, tmp
  877. mov ebx, pitch
  878. mov ecx, ebx
  879. shr ecx, 3
  880. movq mm6, __0x03e003e003e003e0
  881. movq mm7, __0x001f001f001f001f
  882. AvgLines555_loop:
  883. movq mm0, [esi]
  884. movq mm1, mm0
  885. movq mm2, mm0
  886. psrlw mm0, 10 // red1 bits: mm0 = 001f001f001f001f
  887. pand mm1, mm6 // green1 bits: mm1 = 03e003e003e003e0
  888. pand mm2, mm7 // blue1 bits: mm2 = 001f001f001f001f
  889. movq mm3, [esi+ebx*2]
  890. movq mm4, mm3
  891. movq mm5, mm3
  892. psrlw mm3, 10 // red2 bits: mm3 = 001f001f001f001f
  893. pand mm4, mm6 // green2 bits: mm4 = 03e003e003e003e0
  894. pand mm5, mm7 // blue2 bits: mm5 = 001f001f001f001f
  895. paddw mm0, mm3
  896. psrlw mm0, 1 // (red1+red2)/2
  897. psllw mm0, 10 // red bits at 7c007c007c007c00
  898. paddw mm1, mm4
  899. psrlw mm1, 1 // (green1+green2)/2
  900. pand mm1, mm6 // green bits at 03e003e003e003e0
  901. paddw mm2, mm5
  902. psrlw mm2, 1 // (blue1+blue2)/2
  903. // blue bits at 001f001f001f001f (no need to pand, lower bits were discareded)
  904. por mm0, mm1
  905. por mm0, mm2
  906. movq [esi+ebx], mm0
  907. lea esi, [esi+8]
  908. dec ecx
  909. jnz AvgLines555_loop
  910. mov tmp, esi
  911. }
  912. for(int i = (pitch&7)>>1; i--; tmp++)
  913. {
  914. tmp[pitch] = 
  915. ((((*tmp&0x7c00) + (tmp[pitch<<1]&0x7c00)) >> 1)&0x7c00)|
  916. ((((*tmp&0x03e0) + (tmp[pitch<<1]&0x03e0)) >> 1)&0x03e0)|
  917. ((((*tmp&0x001f) + (tmp[pitch<<1]&0x001f)) >> 1)&0x001f);
  918. }
  919. }
  920. if(!(h&1) && h >= 2)
  921. {
  922. dst += (h-2)*pitch;
  923. memcpy_accel(dst + pitch, dst, pitch);
  924. }
  925. __asm emms;
  926. }
  927. void AvgLines565(BYTE* dst, DWORD h, DWORD pitch)
  928. {
  929. if(h <= 1) return;
  930. unsigned __int64 __0xf800f800f800f800 = 0xf800f800f800f800;
  931. unsigned __int64 __0x07e007e007e007e0 = 0x07e007e007e007e0;
  932. unsigned __int64 __0x001f001f001f001f = 0x001f001f001f001f;
  933. BYTE* s = dst;
  934. BYTE* d = dst + (h-2)*pitch;
  935. for(; s < d; s += pitch*2)
  936. {
  937. WORD* tmp = (WORD*)s;
  938. __asm
  939. {
  940. mov esi, tmp
  941. mov ebx, pitch
  942. mov ecx, ebx
  943. shr ecx, 3
  944. movq mm6, __0x07e007e007e007e0
  945. movq mm7, __0x001f001f001f001f
  946. AvgLines565_loop:
  947. movq mm0, [esi]
  948. movq mm1, mm0
  949. movq mm2, mm0
  950. psrlw mm0, 11 // red1 bits: mm0 = 001f001f001f001f
  951. pand mm1, mm6 // green1 bits: mm1 = 07e007e007e007e0
  952. pand mm2, mm7 // blue1 bits: mm2 = 001f001f001f001f
  953. movq mm3, [esi+ebx*2]
  954. movq mm4, mm3
  955. movq mm5, mm3
  956. psrlw mm3, 11 // red2 bits: mm3 = 001f001f001f001f
  957. pand mm4, mm6 // green2 bits: mm4 = 07e007e007e007e0
  958. pand mm5, mm7 // blue2 bits: mm5 = 001f001f001f001f
  959. paddw mm0, mm3
  960. psrlw mm0, 1 // (red1+red2)/2
  961. psllw mm0, 11 // red bits at f800f800f800f800
  962. paddw mm1, mm4
  963. psrlw mm1, 1 // (green1+green2)/2
  964. pand mm1, mm6 // green bits at 03e003e003e003e0
  965. paddw mm2, mm5
  966. psrlw mm2, 1 // (blue1+blue2)/2
  967. // blue bits at 001f001f001f001f (no need to pand, lower bits were discareded)
  968. por mm0, mm1
  969. por mm0, mm2
  970. movq [esi+ebx], mm0
  971. lea esi, [esi+8]
  972. dec ecx
  973. jnz AvgLines565_loop
  974. mov tmp, esi
  975. }
  976. for(int i = (pitch&7)>>1; i--; tmp++)
  977. {
  978. tmp[pitch] = 
  979. ((((*tmp&0xf800) + (tmp[pitch<<1]&0xf800)) >> 1)&0xf800)|
  980. ((((*tmp&0x07e0) + (tmp[pitch<<1]&0x07e0)) >> 1)&0x07e0)|
  981. ((((*tmp&0x001f) + (tmp[pitch<<1]&0x001f)) >> 1)&0x001f);
  982. }
  983. }
  984. if(!(h&1) && h >= 2)
  985. {
  986. dst += (h-2)*pitch;
  987. memcpy_accel(dst + pitch, dst, pitch);
  988. }
  989. __asm emms;
  990. }
  991. extern "C" void mmx_YUY2toRGB24(const BYTE* src, BYTE* dst, const BYTE* src_end, int src_pitch, int row_size, bool rec709);
  992. extern "C" void mmx_YUY2toRGB32(const BYTE* src, BYTE* dst, const BYTE* src_end, int src_pitch, int row_size, bool rec709);
  993. bool BitBltFromYUY2ToRGB(int w, int h, BYTE* dst, int dstpitch, int dbpp, BYTE* src, int srcpitch)
  994. {
  995. void (* YUY2toRGB)(const BYTE* src, BYTE* dst, const BYTE* src_end, int src_pitch, int row_size, bool rec709) = NULL;
  996. if(g_cpuid.m_flags & CCpuID::mmx)
  997. {
  998. YUY2toRGB = 
  999. dbpp == 32 ? mmx_YUY2toRGB32 :
  1000. dbpp == 24 ? mmx_YUY2toRGB24 :
  1001. // dbpp == 16 ? mmx_YUY2toRGB16 : // TODO
  1002. NULL;
  1003. }
  1004. else
  1005. {
  1006. // TODO
  1007. }
  1008. if(!YUY2toRGB) return(false);
  1009. YUY2toRGB(src, dst, src + h*srcpitch, srcpitch, w, false);
  1010. return(true);
  1011. }