Copy.cpp

00001 // Copyright 2003-2005 Gabest
00002 // http://www.gabest.org
00003 //
00004 // This program is free software; you can redistribute it and/or modify
00005 // it under the terms of the GNU General Public License as published by
00006 // the Free Software Foundation; either version 2 of the License, or
00007 // (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with this program; if not, write to the Free Software
00016 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit
00017 // http://www.gnu.org/copyleft/gpl.html
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; // w/o colors 
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; // w/o colors 
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 /* ResX2 */
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) // TODO: replace this mess with mmx code
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                         // row0, 4 pixels: y1|u1|y2|v1|y3|u2|y4|v2
00162                         // ->
00163                         // row0, 8 pixels: y1|u1|(y1+y2)/2|v1|y2|(u1+u2)/2|(y2+y3)/2|(v1+v2)/2
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        // mm0 = 00y400y300y200y1
00182                                 psrlw   mm2, 8          // mm2 = 00u200v200u100v1
00183 
00184 
00185                                 movq    mm1, mm0
00186 
00187                                 pand    mm0, mm5        // mm0 = 0000000000y200y1
00188 
00189                                 psllq   mm1, 16
00190                                 pand    mm1, mm6        // mm1 = 00y300y200000000
00191 
00192                                 por             mm1, mm0        // mm1 = 00y300y200y200y1
00193 
00194                                 punpcklwd mm0, mm0      // mm0 = 00y200y200y100y1
00195 
00196                                 paddw   mm0, mm1
00197                                 psrlw   mm0, 1          // mm0 = (mm0 + mm1) / 2
00198 
00199 
00200                                 movq    mm1, mm2
00201                                 punpckldq       mm1, mm1 // mm1 = 00u100v100u100v1
00202 
00203                                 paddw   mm1, mm2
00204                                 psrlw   mm1, 1          // mm1 = (mm1 + mm2) / 2
00205 
00206 
00207                                 psllw   mm1, 8
00208                                 por             mm0, mm1        // mm0 = (v1+v2)/2|(y2+y3)/2|(u1+u2)/2|y2|v1|(y1+y2)/2|u1|y1
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) // TODO: replace this mess with mmx code
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) // TODO: replace this mess with mmx code
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) // TODO: replace this mess with mmx code
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      // mm1 = 00xx00r100g100b1
00363                                 punpckhbw mm2, mm0      // mm2 = 00xx00r200g200b2
00364 
00365                                 paddw   mm2, mm1
00366                                 psrlw   mm2, 1          // mm2 = (mm1 + mm2) / 2
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) // flip if the dst bitmap is flipped rgb (m_hbm is a top-down bitmap, not like the subpictures)
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 }

Generated on Tue Dec 13 14:47:51 2005 for guliverkli by  doxygen 1.4.5