00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "stdafx.h"
00020 #include <math.h>
00021 #include "DirectVobSubFilter.h"
00022 #include "..\..\..\DSUtil\DSUtil.h"
00023 #include "..\..\..\DSUtil\MediaTypes.h"
00024
00025 #include <initguid.h>
00026 #include "..\..\..\..\include\moreuuids.h"
00027
00028 extern int c2y_yb[256];
00029 extern int c2y_yg[256];
00030 extern int c2y_yr[256];
00031 extern void ColorConvInit();
00032
00033 void BltLineRGB32(DWORD* d, BYTE* sub, int w, const GUID& subtype)
00034 {
00035 if(subtype == MEDIASUBTYPE_YV12 || subtype == MEDIASUBTYPE_I420 || subtype == MEDIASUBTYPE_IYUV)
00036 {
00037 BYTE* db = (BYTE*)d;
00038 BYTE* dbtend = db + w;
00039
00040 for(; db < dbtend; sub+=4, db++)
00041 {
00042 if(sub[3] < 0xff)
00043 {
00044 int y = (c2y_yb[sub[0]] + c2y_yg[sub[1]] + c2y_yr[sub[2]] + 0x108000) >> 16;
00045 *db = y;
00046 }
00047 }
00048 }
00049 else if(subtype == MEDIASUBTYPE_YUY2)
00050 {
00051 WORD* ds = (WORD*)d;
00052 WORD* dstend = ds + w;
00053
00054 for(; ds < dstend; sub+=4, ds++)
00055 {
00056 if(sub[3] < 0xff)
00057 {
00058 int y = (c2y_yb[sub[0]] + c2y_yg[sub[1]] + c2y_yr[sub[2]] + 0x108000) >> 16;
00059 *ds = 0x8000|y;
00060 }
00061 }
00062 }
00063 else if(subtype == MEDIASUBTYPE_RGB555)
00064 {
00065 WORD* ds = (WORD*)d;
00066 WORD* dstend = ds + w;
00067
00068 for(; ds < dstend; sub+=4, ds++)
00069 {
00070 if(sub[3] < 0xff)
00071 {
00072 *ds = ((*((DWORD*)sub)>>9)&0x7c00)|((*((DWORD*)sub)>>6)&0x03e0)|((*((DWORD*)sub)>>3)&0x001f);
00073 }
00074 }
00075 }
00076 else if(subtype == MEDIASUBTYPE_RGB565)
00077 {
00078 WORD* ds = (WORD*)d;
00079 WORD* dstend = ds + w;
00080
00081 for(; ds < dstend; sub+=4, ds++)
00082 {
00083 if(sub[3] < 0xff)
00084 {
00085 *ds = ((*((DWORD*)sub)>>8)&0xf800)|((*((DWORD*)sub)>>5)&0x07e0)|((*((DWORD*)sub)>>3)&0x001f);
00086 }
00087 }
00088 }
00089 else if(subtype == MEDIASUBTYPE_RGB24)
00090 {
00091 BYTE* dt = (BYTE*)d;
00092 BYTE* dstend = dt + w*3;
00093
00094 for(; dt < dstend; sub+=4, dt+=3)
00095 {
00096 if(sub[3] < 0xff)
00097 {
00098 dt[0] = sub[0];
00099 dt[1] = sub[1];
00100 dt[2] = sub[2];
00101 }
00102 }
00103 }
00104 else if(subtype == MEDIASUBTYPE_RGB32 || subtype == MEDIASUBTYPE_ARGB32)
00105 {
00106 DWORD* dstend = d + w;
00107
00108 for(; d < dstend; sub+=4, d++)
00109 {
00110 if(sub[3] < 0xff) *d = *((DWORD*)sub)&0xffffff;
00111 }
00112 }
00113 }
00114
00115
00116 void Scale2x(const GUID& subtype, BYTE* d, int dpitch, BYTE* s, int spitch, int w, int h)
00117 {
00118 if(subtype == MEDIASUBTYPE_YV12 || subtype == MEDIASUBTYPE_I420 || subtype == MEDIASUBTYPE_IYUV)
00119 {
00120 BYTE* s1;
00121 BYTE* s2;
00122 BYTE* d1;
00123
00124 for(s1 = s, s2 = s + h*spitch, d1 = d; s1 < s2; d1 += dpitch)
00125 {
00126 BYTE* stmp = s1 + spitch;
00127 BYTE* dtmp = d1 + dpitch;
00128
00129 for(BYTE* s3 = s1 + (w-1); s1 < s3; s1 += 1, d1 += 2)
00130 {
00131 d1[0] = s1[0];
00132 d1[1] = (s1[0]+s1[1])>>1;
00133 }
00134
00135 d1[0] = d1[1] = s1[0];
00136
00137 s1 += 1;
00138 d1 += 2;
00139
00140 s1 = stmp;
00141 d1 = dtmp;
00142 }
00143
00144 AvgLines8(d, h*2, dpitch);
00145 }
00146 else if(subtype == MEDIASUBTYPE_YUY2)
00147 {
00148 unsigned __int64 __0xffffffff00000000 = 0xffffffff00000000;
00149 unsigned __int64 __0x00000000ffffffff = 0x00000000ffffffff;
00150 unsigned __int64 __0x00ff00ff00ff00ff = 0x00ff00ff00ff00ff;
00151
00152 BYTE* s1;
00153 BYTE* s2;
00154 BYTE* d1;
00155
00156 for(s1 = s, s2 = s + h*spitch, d1 = d; s1 < s2; d1 += dpitch)
00157 {
00158 BYTE* stmp = s1 + spitch;
00159 BYTE* dtmp = d1 + dpitch;
00160
00161
00162
00163
00164
00165 __asm
00166 {
00167 mov esi, s1
00168 mov edi, d1
00169
00170 mov ecx, w
00171 shr ecx, 1
00172 dec ecx
00173
00174 movq mm4, __0x00ff00ff00ff00ff
00175 movq mm5, __0x00000000ffffffff
00176 movq mm6, __0xffffffff00000000
00177 row_loop1:
00178 movq mm0, [esi]
00179 movq mm2, mm0
00180
00181 pand mm0, mm4
00182 psrlw mm2, 8
00183
00184
00185 movq mm1, mm0
00186
00187 pand mm0, mm5
00188
00189 psllq mm1, 16
00190 pand mm1, mm6
00191
00192 por mm1, mm0
00193
00194 punpcklwd mm0, mm0
00195
00196 paddw mm0, mm1
00197 psrlw mm0, 1
00198
00199
00200 movq mm1, mm2
00201 punpckldq mm1, mm1
00202
00203 paddw mm1, mm2
00204 psrlw mm1, 1
00205
00206
00207 psllw mm1, 8
00208 por mm0, mm1
00209
00210 movq [edi], mm0
00211
00212 lea esi, [esi+4]
00213 lea edi, [edi+8]
00214
00215 dec ecx
00216 jnz row_loop1
00217
00218 mov s1, esi
00219 mov d1, edi
00220 };
00221
00222 *d1++ = s1[0];
00223 *d1++ = s1[1];
00224 *d1++ =(s1[0]+s1[2])>>1;
00225 *d1++ = s1[3];
00226
00227 *d1++ = s1[2];
00228 *d1++ = s1[1];
00229 *d1++ = s1[2];
00230 *d1++ = s1[3];
00231
00232 s1 += 4;
00233
00234 s1 = stmp;
00235 d1 = dtmp;
00236 }
00237
00238 AvgLines8(d, h*2, dpitch);
00239 }
00240 else if(subtype == MEDIASUBTYPE_RGB555)
00241 {
00242 BYTE* s1;
00243 BYTE* s2;
00244 BYTE* d1;
00245
00246 for(s1 = s, s2 = s + h*spitch, d1 = d; s1 < s2; d1 += dpitch)
00247 {
00248 BYTE* stmp = s1 + spitch;
00249 BYTE* dtmp = d1 + dpitch;
00250
00251 for(BYTE* s3 = s1 + (w-1)*2; s1 < s3; s1 += 2, d1 += 4)
00252 {
00253 *((WORD*)d1) = *((WORD*)s1);
00254 *((WORD*)d1+1) =
00255 ((((*((WORD*)s1)&0x7c00) + (*((WORD*)s1+1)&0x7c00)) >> 1)&0x7c00)|
00256 ((((*((WORD*)s1)&0x03e0) + (*((WORD*)s1+1)&0x03e0)) >> 1)&0x03e0)|
00257 ((((*((WORD*)s1)&0x001f) + (*((WORD*)s1+1)&0x001f)) >> 1)&0x001f);
00258 }
00259
00260 *((WORD*)d1) = *((WORD*)s1);
00261 *((WORD*)d1+1) = *((WORD*)s1);
00262
00263 s1 += 2;
00264 d1 += 4;
00265
00266 s1 = stmp;
00267 d1 = dtmp;
00268 }
00269
00270 AvgLines555(d, h*2, dpitch);
00271 }
00272 else if(subtype == MEDIASUBTYPE_RGB565)
00273 {
00274 BYTE* s1;
00275 BYTE* s2;
00276 BYTE* d1;
00277
00278 for(s1 = s, s2 = s + h*spitch, d1 = d; s1 < s2; d1 += dpitch)
00279 {
00280 BYTE* stmp = s1 + spitch;
00281 BYTE* dtmp = d1 + dpitch;
00282
00283 for(BYTE* s3 = s1 + (w-1)*2; s1 < s3; s1 += 2, d1 += 4)
00284 {
00285 *((WORD*)d1) = *((WORD*)s1);
00286 *((WORD*)d1+1) =
00287 ((((*((WORD*)s1)&0xf800) + (*((WORD*)s1+1)&0xf800)) >> 1)&0xf800)|
00288 ((((*((WORD*)s1)&0x07e0) + (*((WORD*)s1+1)&0x07e0)) >> 1)&0x07e0)|
00289 ((((*((WORD*)s1)&0x001f) + (*((WORD*)s1+1)&0x001f)) >> 1)&0x001f);
00290 }
00291
00292 *((WORD*)d1) = *((WORD*)s1);
00293 *((WORD*)d1+1) = *((WORD*)s1);
00294
00295 s1 += 2;
00296 d1 += 4;
00297
00298 s1 = stmp;
00299 d1 = dtmp;
00300 }
00301
00302 AvgLines565(d, h*2, dpitch);
00303 }
00304 else if(subtype == MEDIASUBTYPE_RGB24)
00305 {
00306 BYTE* s1;
00307 BYTE* s2;
00308 BYTE* d1;
00309
00310 for(s1 = s, s2 = s + h*spitch, d1 = d; s1 < s2; d1 += dpitch)
00311 {
00312 BYTE* stmp = s1 + spitch;
00313 BYTE* dtmp = d1 + dpitch;
00314
00315 for(BYTE* s3 = s1 + (w-1)*3; s1 < s3; s1 += 3, d1 += 6)
00316 {
00317 d1[0] = s1[0];
00318 d1[1] = s1[1];
00319 d1[2] = s1[2];
00320 d1[3] = (s1[0]+s1[3])>>1;
00321 d1[4] = (s1[1]+s1[4])>>1;
00322 d1[5] = (s1[2]+s1[5])>>1;
00323 }
00324
00325 d1[0] = d1[3] = s1[0];
00326 d1[1] = d1[4] = s1[1];
00327 d1[2] = d1[5] = s1[2];
00328
00329 s1 += 3;
00330 d1 += 6;
00331
00332 s1 = stmp;
00333 d1 = dtmp;
00334 }
00335
00336 AvgLines8(d, h*2, dpitch);
00337 }
00338 else if(subtype == MEDIASUBTYPE_RGB32 || subtype == MEDIASUBTYPE_ARGB32)
00339 {
00340 BYTE* s1;
00341 BYTE* s2;
00342 BYTE* d1;
00343
00344 for(s1 = s, s2 = s + h*spitch, d1 = d; s1 < s2; d1 += dpitch)
00345 {
00346 BYTE* stmp = s1 + spitch;
00347 BYTE* dtmp = d1 + dpitch;
00348
00349 __asm
00350 {
00351 mov esi, s1
00352 mov edi, d1
00353
00354 mov ecx, w
00355 dec ecx
00356
00357 pxor mm0, mm0
00358 row_loop3:
00359 movq mm1, [esi]
00360 movq mm2, mm1
00361
00362 punpcklbw mm1, mm0
00363 punpckhbw mm2, mm0
00364
00365 paddw mm2, mm1
00366 psrlw mm2, 1
00367
00368 packuswb mm1, mm2
00369
00370 movq [edi], mm1
00371
00372 lea esi, [esi+4]
00373 lea edi, [edi+8]
00374
00375 dec ecx
00376 jnz row_loop3
00377
00378 mov s1, esi
00379 mov d1, edi
00380 };
00381
00382 *((DWORD*)d1) = *((DWORD*)s1);
00383 *((DWORD*)d1+1) = *((DWORD*)s1);
00384
00385 s1 += 4;
00386 d1 += 8;
00387
00388 s1 = stmp;
00389 d1 = dtmp;
00390 }
00391
00392 AvgLines8(d, h*2, dpitch);
00393 }
00394
00395 __asm emms;
00396 }
00397
00398 HRESULT CDirectVobSubFilter::Copy(BYTE* pSub, BYTE* pIn, CSize sub, CSize in, int bpp, const GUID& subtype, DWORD black)
00399 {
00400 int wIn = in.cx, hIn = in.cy, pitchIn = ((wIn*bpp>>3)+3)&~3;
00401 int wSub = sub.cx, hSub = sub.cy, pitchSub = ((wSub*bpp>>3)+3)&~3;
00402 bool fScale2x = wIn*2 <= wSub;
00403
00404 if(fScale2x) wIn <<= 1, hIn <<= 1;
00405
00406 int left = ((wSub - wIn)>>1)&~1;
00407 int mid = wIn;
00408 int right = left + ((wSub - wIn)&1);
00409
00410 int dpLeft = left*bpp>>3;
00411 int dpMid = mid*bpp>>3;
00412 int dpRight = right*bpp>>3;
00413
00414 ASSERT(wSub >= wIn);
00415
00416 {
00417 int i = 0, j = 0;
00418
00419 j += (hSub - hIn) >> 1;
00420
00421 for(; i < j; i++, pSub += pitchSub)
00422 {
00423 memsetd(pSub, black, dpLeft+dpMid+dpRight);
00424 }
00425
00426 j += hIn;
00427
00428 if(hIn > hSub)
00429 pIn += pitchIn * ((hIn - hSub) >> (fScale2x?2:1));
00430
00431 if(fScale2x)
00432 {
00433 Scale2x(subtype,
00434 pSub + dpLeft, pitchSub, pIn, pitchIn,
00435 in.cx, (min(j, hSub) - i) >> 1);
00436
00437 for(int k = min(j, hSub); i < k; i++, pIn += pitchIn, pSub += pitchSub)
00438 {
00439 memsetd(pSub, black, dpLeft);
00440 memsetd(pSub + dpLeft+dpMid, black, dpRight);
00441 }
00442 }
00443 else
00444 {
00445 for(int k = min(j, hSub); i < k; i++, pIn += pitchIn, pSub += pitchSub)
00446 {
00447 memsetd(pSub, black, dpLeft);
00448 memcpy(pSub + dpLeft, pIn, dpMid);
00449 memsetd(pSub + dpLeft+dpMid, black, dpRight);
00450 }
00451 }
00452
00453 j = hSub;
00454
00455 for(; i < j; i++, pSub += pitchSub)
00456 {
00457 memsetd(pSub, black, dpLeft+dpMid+dpRight);
00458 }
00459 }
00460
00461 return NOERROR;
00462 }
00463
00464 void CDirectVobSubFilter::PrintMessages(BYTE* pOut)
00465 {
00466 if(!m_hdc || !m_hbm)
00467 return;
00468
00469 ColorConvInit();
00470
00471 const GUID& subtype = m_pOutput->CurrentMediaType().subtype;
00472
00473 BITMAPINFOHEADER bihOut;
00474 ExtractBIH(&m_pOutput->CurrentMediaType(), &bihOut);
00475
00476 CString msg, tmp;
00477
00478 if(m_fOSD)
00479 {
00480 tmp.Format(_T("in: %dx%d %s\nout: %dx%d %s\n"),
00481 m_w, m_h,
00482 Subtype2String(m_pInput->CurrentMediaType().subtype),
00483 bihOut.biWidth, bihOut.biHeight,
00484 Subtype2String(m_pOutput->CurrentMediaType().subtype));
00485 msg += tmp;
00486
00487 tmp.Format(_T("real fps: %.3f, current fps: %.3f\nmedia time: %d, subtitle time: %d [ms]\nframe number: %d (calculated)\nrate: %.4f\n"),
00488 m_fps, m_fMediaFPSEnabled?m_MediaFPS:fabs(m_fps),
00489 (int)m_tPrev.Millisecs(), (int)(CalcCurrentTime()/10000),
00490 (int)(m_tPrev.m_time * m_fps / 10000000),
00491 m_pInput->CurrentRate());
00492 msg += tmp;
00493
00494 CAutoLock cAutoLock(&m_csQueueLock);
00495
00496 if(m_pSubPicQueue)
00497 {
00498 int nSubPics = -1;
00499 REFERENCE_TIME rtNow = -1, rtStart = -1, rtStop = -1;
00500 m_pSubPicQueue->GetStats(nSubPics, rtNow, rtStart, rtStop);
00501 tmp.Format(_T("queue stats: %I64d - %I64d [ms]\n"), rtStart/10000, rtStop/10000);
00502 msg += tmp;
00503
00504 for(int i = 0; i < nSubPics; i++)
00505 {
00506 m_pSubPicQueue->GetStats(i, rtStart, rtStop);
00507 tmp.Format(_T("%d: %I64d - %I64d [ms]\n"), i, rtStart/10000, rtStop/10000);
00508 msg += tmp;
00509 }
00510
00511 }
00512 }
00513
00514 if(msg.IsEmpty()) return;
00515
00516 HANDLE hOldBitmap = SelectObject(m_hdc, m_hbm);
00517 HANDLE hOldFont = SelectObject(m_hdc, m_hfont);
00518
00519 SetTextColor(m_hdc, 0xffffff);
00520 SetBkMode(m_hdc, TRANSPARENT);
00521 SetMapMode(m_hdc, MM_TEXT);
00522
00523 BITMAP bm;
00524 GetObject(m_hbm, sizeof(BITMAP), &bm);
00525
00526 CRect r(0, 0, bm.bmWidth, bm.bmHeight);
00527 DrawText(m_hdc, msg, _tcslen(msg), &r, DT_CALCRECT|DT_EXTERNALLEADING|DT_NOPREFIX|DT_WORDBREAK);
00528
00529 r += CPoint(10, 10);
00530 r &= CRect(0, 0, bm.bmWidth, bm.bmHeight);
00531
00532 DrawText(m_hdc, msg, _tcslen(msg), &r, DT_LEFT|DT_TOP|DT_NOPREFIX|DT_WORDBREAK);
00533
00534 BYTE* pIn = (BYTE*)bm.bmBits;
00535 int pitchIn = bm.bmWidthBytes;
00536 int pitchOut = bihOut.biWidth * bihOut.biBitCount >> 3;
00537
00538 if(subtype == MEDIASUBTYPE_YV12 || subtype == MEDIASUBTYPE_I420 || subtype == MEDIASUBTYPE_IYUV)
00539 pitchOut = bihOut.biWidth;
00540
00541 pitchIn = (pitchIn+3)&~3;
00542 pitchOut = (pitchOut+3)&~3;
00543
00544 if(bihOut.biHeight > 0 && bihOut.biCompression <= 3)
00545 {
00546 pOut += pitchOut * (abs(bihOut.biHeight)-1);
00547 pitchOut = -pitchOut;
00548 }
00549
00550 pIn += pitchIn * r.top;
00551 pOut += pitchOut * r.top;
00552
00553 for(int w = min(r.right, m_w), h = r.Height(); h--; pIn += pitchIn, pOut += pitchOut)
00554 {
00555 BltLineRGB32((DWORD*)pOut, pIn, w, subtype);
00556 memsetd(pIn, 0xff000000, r.right*4);
00557 }
00558
00559 SelectObject(m_hdc, hOldBitmap);
00560 SelectObject(m_hdc, hOldFont);
00561 }