00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "stdafx.h"
00023 #include "MemSubPic.h"
00024
00025
00026
00027 unsigned char Clip_base[256*3];
00028 unsigned char* Clip = Clip_base + 256;
00029
00030 const int c2y_cyb = int(0.114*219/255*65536+0.5);
00031 const int c2y_cyg = int(0.587*219/255*65536+0.5);
00032 const int c2y_cyr = int(0.299*219/255*65536+0.5);
00033 const int c2y_cu = int(1.0/2.018*1024+0.5);
00034 const int c2y_cv = int(1.0/1.596*1024+0.5);
00035
00036 int c2y_yb[256];
00037 int c2y_yg[256];
00038 int c2y_yr[256];
00039
00040 const int y2c_cbu = int(2.018*65536+0.5);
00041 const int y2c_cgu = int(0.391*65536+0.5);
00042 const int y2c_cgv = int(0.813*65536+0.5);
00043 const int y2c_crv = int(1.596*65536+0.5);
00044 int y2c_bu[256];
00045 int y2c_gu[256];
00046 int y2c_gv[256];
00047 int y2c_rv[256];
00048
00049 const int cy_cy = int(255.0/219.0*65536+0.5);
00050 const int cy_cy2 = int(255.0/219.0*32768+0.5);
00051
00052 bool fColorConvInitOK = false;
00053
00054 void ColorConvInit()
00055 {
00056 if(fColorConvInitOK) return;
00057
00058 int i;
00059
00060 for(i = 0; i < 256; i++)
00061 {
00062 Clip_base[i] = 0;
00063 Clip_base[i+256] = i;
00064 Clip_base[i+512] = 255;
00065 }
00066
00067 for(i = 0; i < 256; i++)
00068 {
00069 c2y_yb[i] = c2y_cyb*i;
00070 c2y_yg[i] = c2y_cyg*i;
00071 c2y_yr[i] = c2y_cyr*i;
00072
00073 y2c_bu[i] = y2c_cbu*(i-128);
00074 y2c_gu[i] = y2c_cgu*(i-128);
00075 y2c_gv[i] = y2c_cgv*(i-128);
00076 y2c_rv[i] = y2c_crv*(i-128);
00077 }
00078
00079 fColorConvInitOK = true;
00080 }
00081
00082 #define rgb2yuv(r1,g1,b1,r2,g2,b2) \
00083 int y1 = (c2y_yb[b1] + c2y_yg[g1] + c2y_yr[r1] + 0x108000) >> 16; \
00084 int y2 = (c2y_yb[b2] + c2y_yg[g2] + c2y_yr[r2] + 0x108000) >> 16; \
00085 \
00086 int scaled_y = (y1+y2-32) * cy_cy2; \
00087 \
00088 unsigned char u = Clip[(((((b1+b2)<<15) - scaled_y) >> 10) * c2y_cu + 0x800000 + 0x8000) >> 16]; \
00089 unsigned char v = Clip[(((((r1+r2)<<15) - scaled_y) >> 10) * c2y_cv + 0x800000 + 0x8000) >> 16]; \
00090
00091
00092
00093
00094
00095 CMemSubPic::CMemSubPic(SubPicDesc& spd)
00096 : m_spd(spd)
00097 {
00098 m_maxsize.SetSize(spd.w, spd.h);
00099 m_rcDirty.SetRect(0, 0, spd.w, spd.h);
00100 }
00101
00102 CMemSubPic::~CMemSubPic()
00103 {
00104 delete [] m_spd.bits, m_spd.bits = NULL;
00105 }
00106
00107
00108
00109 STDMETHODIMP_(void*) CMemSubPic::GetObject()
00110 {
00111 return (void*)&m_spd;
00112 }
00113
00114 STDMETHODIMP CMemSubPic::GetDesc(SubPicDesc& spd)
00115 {
00116 spd.type = m_spd.type;
00117 spd.w = m_size.cx;
00118 spd.h = m_size.cy;
00119 spd.bpp = m_spd.bpp;
00120 spd.pitch = m_spd.pitch;
00121 spd.bits = m_spd.bits;
00122 spd.bitsU = m_spd.bitsU;
00123 spd.bitsV = m_spd.bitsV;
00124 spd.vidrect = m_vidrect;
00125
00126 return S_OK;
00127 }
00128
00129 STDMETHODIMP CMemSubPic::CopyTo(ISubPic* pSubPic)
00130 {
00131 HRESULT hr;
00132 if(FAILED(hr = __super::CopyTo(pSubPic)))
00133 return hr;
00134
00135 SubPicDesc src, dst;
00136 if(FAILED(GetDesc(src)) || FAILED(pSubPic->GetDesc(dst)))
00137 return E_FAIL;
00138
00139 int w = m_rcDirty.Width(), h = m_rcDirty.Height();
00140
00141 BYTE* s = (BYTE*)src.bits + src.pitch*m_rcDirty.top + m_rcDirty.left*4;
00142 BYTE* d = (BYTE*)dst.bits + dst.pitch*m_rcDirty.top + m_rcDirty.left*4;
00143
00144 for(int j = 0; j < h; j++, s += src.pitch, d += dst.pitch)
00145 memcpy(d, s, w*4);
00146
00147 return S_OK;
00148 }
00149
00150 STDMETHODIMP CMemSubPic::ClearDirtyRect(DWORD color)
00151 {
00152 if(m_rcDirty.IsRectEmpty())
00153 return S_FALSE;
00154
00155 BYTE* p = (BYTE*)m_spd.bits + m_spd.pitch*m_rcDirty.top + m_rcDirty.left*(m_spd.bpp>>3);
00156 for(int j = 0, h = m_rcDirty.Height(); j < h; j++, p += m_spd.pitch)
00157 {
00158
00159
00160 int w = m_rcDirty.Width();
00161 __asm
00162 {
00163 mov eax, color
00164 mov ecx, w
00165 mov edi, p
00166 cld
00167 rep stosd
00168 }
00169 }
00170
00171 m_rcDirty.SetRectEmpty();
00172
00173 return S_OK;
00174 }
00175
00176 STDMETHODIMP CMemSubPic::Lock(SubPicDesc& spd)
00177 {
00178 return GetDesc(spd);
00179 }
00180
00181 STDMETHODIMP CMemSubPic::Unlock(RECT* pDirtyRect)
00182 {
00183 m_rcDirty = pDirtyRect ? *pDirtyRect : CRect(0,0,m_spd.w,m_spd.h);
00184
00185 if(m_rcDirty.IsRectEmpty())
00186 return S_OK;
00187
00188 if(m_spd.type == MSP_YUY2 || m_spd.type == MSP_YV12 || m_spd.type == MSP_IYUV || m_spd.type == MSP_AYUV)
00189 {
00190 ColorConvInit();
00191
00192 if(m_spd.type == MSP_YUY2 || m_spd.type == MSP_YV12 || m_spd.type == MSP_IYUV)
00193 {
00194 m_rcDirty.left &= ~1;
00195 m_rcDirty.right = (m_rcDirty.right+1)&~1;
00196
00197 if(m_spd.type == MSP_YV12 || m_spd.type == MSP_IYUV)
00198 {
00199 m_rcDirty.top &= ~1;
00200 m_rcDirty.bottom = (m_rcDirty.bottom+1)&~1;
00201 }
00202 }
00203 }
00204
00205 int w = m_rcDirty.Width(), h = m_rcDirty.Height();
00206
00207 BYTE* top = (BYTE*)m_spd.bits + m_spd.pitch*m_rcDirty.top + m_rcDirty.left*4;
00208 BYTE* bottom = top + m_spd.pitch*h;
00209
00210 if(m_spd.type == MSP_RGB16)
00211 {
00212 for(; top < bottom ; top += m_spd.pitch)
00213 {
00214 DWORD* s = (DWORD*)top;
00215 DWORD* e = s + w;
00216 for(; s < e; s++)
00217 {
00218 *s = ((*s>>3)&0x1f000000)|((*s>>8)&0xf800)|((*s>>5)&0x07e0)|((*s>>3)&0x001f);
00219
00220 }
00221 }
00222 }
00223 else if(m_spd.type == MSP_RGB15)
00224 {
00225 for(; top < bottom; top += m_spd.pitch)
00226 {
00227 DWORD* s = (DWORD*)top;
00228 DWORD* e = s + w;
00229 for(; s < e; s++)
00230 {
00231 *s = ((*s>>3)&0x1f000000)|((*s>>9)&0x7c00)|((*s>>6)&0x03e0)|((*s>>3)&0x001f);
00232
00233 }
00234 }
00235 }
00236 else if(m_spd.type == MSP_YUY2 || m_spd.type == MSP_YV12 || m_spd.type == MSP_IYUV)
00237 {
00238 for(; top < bottom ; top += m_spd.pitch)
00239 {
00240 BYTE* s = top;
00241 BYTE* e = s + w*4;
00242 for(; s < e; s+=8)
00243 {
00244 if((s[3]+s[7]) < 0x1fe)
00245 {
00246 s[1] = (c2y_yb[s[0]] + c2y_yg[s[1]] + c2y_yr[s[2]] + 0x108000) >> 16;
00247 s[5] = (c2y_yb[s[4]] + c2y_yg[s[5]] + c2y_yr[s[6]] + 0x108000) >> 16;
00248
00249 int scaled_y = (s[1]+s[5]-32) * cy_cy2;
00250
00251 s[0] = Clip[(((((s[0]+s[4])<<15) - scaled_y) >> 10) * c2y_cu + 0x800000 + 0x8000) >> 16];
00252 s[4] = Clip[(((((s[2]+s[6])<<15) - scaled_y) >> 10) * c2y_cv + 0x800000 + 0x8000) >> 16];
00253 }
00254 else
00255 {
00256 s[1] = s[5] = 0x10;
00257 s[0] = s[4] = 0x80;
00258 }
00259 }
00260 }
00261 }
00262 else if(m_spd.type == MSP_AYUV)
00263 {
00264 for(; top < bottom ; top += m_spd.pitch)
00265 {
00266 BYTE* s = top;
00267 BYTE* e = s + w*4;
00268 for(; s < e; s+=4)
00269 {
00270 if(s[3] < 0xff)
00271 {
00272 int y = (c2y_yb[s[0]] + c2y_yg[s[1]] + c2y_yr[s[2]] + 0x108000) >> 16;
00273 int scaled_y = (y-32) * cy_cy;
00274 s[1] = Clip[((((s[0]<<16) - scaled_y) >> 10) * c2y_cu + 0x800000 + 0x8000) >> 16];
00275 s[0] = Clip[((((s[2]<<16) - scaled_y) >> 10) * c2y_cv + 0x800000 + 0x8000) >> 16];
00276 s[2] = y;
00277 }
00278 else
00279 {
00280 s[0] = s[1] = 0x80;
00281 s[2] = 0x10;
00282 }
00283 }
00284 }
00285 }
00286
00287 return S_OK;
00288 }
00289
00290 STDMETHODIMP CMemSubPic::AlphaBlt(RECT* pSrc, RECT* pDst, SubPicDesc* pTarget)
00291 {
00292 ASSERT(pTarget);
00293
00294 if(!pSrc || !pDst || !pTarget)
00295 return E_POINTER;
00296
00297 const SubPicDesc& src = m_spd;
00298 SubPicDesc dst = *pTarget;
00299
00300 if(src.type != dst.type)
00301 return E_INVALIDARG;
00302
00303 CRect rs(*pSrc), rd(*pDst);
00304
00305 if(dst.h < 0)
00306 {
00307 dst.h = -dst.h;
00308 rd.bottom = dst.h - rd.bottom;
00309 rd.top = dst.h - rd.top;
00310 }
00311
00312 if(rs.Width() != rd.Width() || rs.Height() != abs(rd.Height()))
00313 return E_INVALIDARG;
00314
00315 int w = rs.Width(), h = rs.Height();
00316
00317 BYTE* s = (BYTE*)src.bits + src.pitch*rs.top + rs.left*4;
00318 BYTE* d = (BYTE*)dst.bits + dst.pitch*rd.top + ((rd.left*dst.bpp)>>3);
00319
00320 if(rd.top > rd.bottom)
00321 {
00322 if(dst.type == MSP_RGB32 || dst.type == MSP_RGB24
00323 || dst.type == MSP_RGB16 || dst.type == MSP_RGB15
00324 || dst.type == MSP_YUY2 || dst.type == MSP_AYUV)
00325 {
00326 d = (BYTE*)dst.bits + dst.pitch*(rd.top-1) + (rd.left*dst.bpp>>3);
00327 }
00328 else if(dst.type == MSP_YV12 || dst.type == MSP_IYUV)
00329 {
00330 d = (BYTE*)dst.bits + dst.pitch*(rd.top-1) + (rd.left*8>>3);
00331 }
00332 else
00333 {
00334 return E_NOTIMPL;
00335 }
00336
00337 dst.pitch = -dst.pitch;
00338 }
00339
00340 for(int j = 0; j < h; j++, s += src.pitch, d += dst.pitch)
00341 {
00342 if(dst.type == MSP_RGB32 || dst.type == MSP_AYUV)
00343 {
00344 BYTE* s2 = s;
00345 BYTE* s2end = s2 + w*4;
00346 DWORD* d2 = (DWORD*)d;
00347 for(; s2 < s2end; s2 += 4, d2++)
00348 {
00349 if(s2[3] < 0xff)
00350 {
00351 *d2 = (((((*d2&0x00ff00ff)*s2[3])>>8) + (*((DWORD*)s2)&0x00ff00ff))&0x00ff00ff)
00352 | (((((*d2&0x0000ff00)*s2[3])>>8) + (*((DWORD*)s2)&0x0000ff00))&0x0000ff00);
00353 }
00354 }
00355 }
00356 else if(dst.type == MSP_RGB24)
00357 {
00358 BYTE* s2 = s;
00359 BYTE* s2end = s2 + w*4;
00360 BYTE* d2 = d;
00361 for(; s2 < s2end; s2 += 4, d2 += 3)
00362 {
00363 if(s2[3] < 0xff)
00364 {
00365 d2[0] = ((d2[0]*s2[3])>>8) + s2[0];
00366 d2[1] = ((d2[1]*s2[3])>>8) + s2[1];
00367 d2[2] = ((d2[2]*s2[3])>>8) + s2[2];
00368 }
00369 }
00370 }
00371 else if(dst.type == MSP_RGB16)
00372 {
00373 BYTE* s2 = s;
00374 BYTE* s2end = s2 + w*4;
00375 WORD* d2 = (WORD*)d;
00376 for(; s2 < s2end; s2 += 4, d2++)
00377 {
00378 if(s2[3] < 0x1f)
00379 {
00380
00381 *d2 = (WORD)((((((*d2&0xf81f)*s2[3])>>5) + (*(DWORD*)s2&0xf81f))&0xf81f)
00382 | (((((*d2&0x07e0)*s2[3])>>5) + (*(DWORD*)s2&0x07e0))&0x07e0));
00383
00384
00385
00386
00387 }
00388 }
00389 }
00390 else if(dst.type == MSP_RGB15)
00391 {
00392 BYTE* s2 = s;
00393 BYTE* s2end = s2 + w*4;
00394 WORD* d2 = (WORD*)d;
00395 for(; s2 < s2end; s2 += 4, d2++)
00396 {
00397 if(s2[3] < 0x1f)
00398 {
00399 *d2 = (WORD)((((((*d2&0x7c1f)*s2[3])>>5) + (*(DWORD*)s2&0x7c1f))&0x7c1f)
00400 | (((((*d2&0x03e0)*s2[3])>>5) + (*(DWORD*)s2&0x03e0))&0x03e0));
00401
00402
00403
00404 }
00405 }
00406 }
00407 else if(dst.type == MSP_YUY2)
00408 {
00409
00410 unsigned int ia, c;
00411
00412 BYTE* s2 = s;
00413 BYTE* s2end = s2 + w*4;
00414 DWORD* d2 = (DWORD*)d;
00415 for(; s2 < s2end; s2 += 8, d2++)
00416 {
00417 ia = (s2[3]+s2[7])>>1;
00418 if(ia < 0xff)
00419 {
00420
00421
00422
00423
00424
00425
00426
00427 static const __int64 _8181 = 0x0080001000800010i64;
00428
00429 ia = (ia<<24)|(s2[7]<<16)|(ia<<8)|s2[3];
00430 c = (s2[4]<<24)|(s2[5]<<16)|(s2[0]<<8)|s2[1];
00431
00432 __asm
00433 {
00434 mov esi, s2
00435 mov edi, d2
00436 pxor mm0, mm0
00437 movq mm1, _8181
00438 movd mm2, c
00439 punpcklbw mm2, mm0
00440 movd mm3, [edi]
00441 punpcklbw mm3, mm0
00442 movd mm4, ia
00443 punpcklbw mm4, mm0
00444 psrlw mm4, 1
00445 psubsw mm3, mm1
00446 pmullw mm3, mm4
00447 psraw mm3, 7
00448 paddsw mm3, mm2
00449 packuswb mm3, mm3
00450 movd [edi], mm3
00451 };
00452 }
00453 }
00454 }
00455 else if(dst.type == MSP_YV12 || dst.type == MSP_IYUV)
00456 {
00457 BYTE* s2 = s;
00458 BYTE* s2end = s2 + w*4;
00459 BYTE* d2 = d;
00460 for(; s2 < s2end; s2 += 4, d2++)
00461 {
00462 if(s2[3] < 0xff)
00463 {
00464 d2[0] = (((d2[0]-0x10)*s2[3])>>8) + s2[1];
00465 }
00466 }
00467 }
00468 else
00469 {
00470 return E_NOTIMPL;
00471 }
00472 }
00473
00474 dst.pitch = abs(dst.pitch);
00475
00476 if(dst.type == MSP_YV12 || dst.type == MSP_IYUV)
00477 {
00478 int w2 = w/2, h2 = h/2;
00479
00480 if(!dst.pitchUV)
00481 {
00482 dst.pitchUV = dst.pitch/2;
00483 }
00484
00485 int sizep4 = dst.pitchUV*dst.h/2;
00486
00487 BYTE* ss[2];
00488 ss[0] = (BYTE*)src.bits + src.pitch*rs.top + rs.left*4;
00489 ss[1] = ss[0] + 4;
00490
00491 if(!dst.bitsU || !dst.bitsV)
00492 {
00493 dst.bitsU = (BYTE*)dst.bits + dst.pitch*dst.h;
00494 dst.bitsV = dst.bitsU + dst.pitchUV*dst.h/2;
00495
00496 if(dst.type == MSP_YV12)
00497 {
00498 BYTE* p = dst.bitsU;
00499 dst.bitsU = dst.bitsV;
00500 dst.bitsV = p;
00501 }
00502 }
00503
00504 BYTE* dd[2];
00505 dd[0] = dst.bitsU + dst.pitchUV*rd.top/2 + rd.left/2;
00506 dd[1] = dst.bitsV + dst.pitchUV*rd.top/2 + rd.left/2;
00507
00508 if(rd.top > rd.bottom)
00509 {
00510 dd[0] = dst.bitsU + dst.pitchUV*(rd.top/2-1) + rd.left/2;
00511 dd[1] = dst.bitsV + dst.pitchUV*(rd.top/2-1) + rd.left/2;
00512 dst.pitchUV = -dst.pitchUV;
00513 }
00514
00515 for(int i = 0; i < 2; i++)
00516 {
00517 s = ss[i]; d = dd[i];
00518 BYTE* is = ss[1-i];
00519 for(int j = 0; j < h2; j++, s += src.pitch*2, d += dst.pitchUV, is += src.pitch*2)
00520 {
00521 BYTE* s2 = s;
00522 BYTE* s2end = s2 + w*4;
00523 BYTE* d2 = d;
00524 BYTE* is2 = is;
00525 for(; s2 < s2end; s2 += 8, d2++, is2 += 8)
00526 {
00527 unsigned int ia = (s2[3]+s2[3+src.pitch]+is2[3]+is2[3+src.pitch])>>2;
00528 if(ia < 0xff)
00529 {
00530 *d2 = (((*d2-0x80)*ia)>>8) + ((s2[0]+s2[src.pitch])>>1);
00531 }
00532 }
00533 }
00534 }
00535 }
00536
00537 __asm emms;
00538
00539 return S_OK;
00540 }
00541
00542
00543
00544
00545
00546 CMemSubPicAllocator::CMemSubPicAllocator(int type, SIZE maxsize)
00547 : ISubPicAllocatorImpl(maxsize, false, false)
00548 , m_type(type)
00549 , m_maxsize(maxsize)
00550 {
00551 }
00552
00553
00554
00555 bool CMemSubPicAllocator::Alloc(bool fStatic, ISubPic** ppSubPic)
00556 {
00557 if(!ppSubPic)
00558 return(false);
00559
00560 SubPicDesc spd;
00561 spd.w = m_maxsize.cx;
00562 spd.h = m_maxsize.cy;
00563 spd.bpp = 32;
00564 spd.pitch = (spd.w*spd.bpp)>>3;
00565 spd.type = m_type;
00566 if(!(spd.bits = new BYTE[spd.pitch*spd.h]))
00567 return(false);
00568
00569 if(!(*ppSubPic = new CMemSubPic(spd)))
00570 return(false);
00571
00572 (*ppSubPic)->AddRef();
00573
00574 return(true);
00575 }