Guest User

Superb

a guest
Oct 8th, 2012
371
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.24 KB | None | 0 0
  1. void CMainFrame::SaveThumbnails(LPCTSTR fn)
  2. {
  3.     if (!pMC || !pMS || GetPlaybackMode() != PM_FILE /*&& GetPlaybackMode() != PM_DVD*/) {
  4.         return;
  5.     }
  6.  
  7.     REFERENCE_TIME rtPos = GetPos();
  8.     REFERENCE_TIME rtDur = GetDur();
  9.  
  10.     if (rtDur <= 0) {
  11.         AfxMessageBox(IDS_MAINFRM_54, MB_ICONWARNING | MB_OK, 0);
  12.         return;
  13.     }
  14.  
  15.     pMC->Pause();
  16.     GetMediaState(); // wait for completion of the pause command
  17.  
  18.     CSize video, wh(0, 0), arxy(0, 0);
  19.  
  20.     if (m_pMFVDC) {
  21.         m_pMFVDC->GetNativeVideoSize(&wh, &arxy);
  22.     } else if (m_pCAP) {
  23.         wh = m_pCAP->GetVideoSize(false);
  24.         arxy = m_pCAP->GetVideoSize(true);
  25.     } else {
  26.         pBV->GetVideoSize(&wh.cx, &wh.cy);
  27.  
  28.         long arx = 0, ary = 0;
  29.         CComQIPtr<IBasicVideo2> pBV2 = pBV;
  30.         if (pBV2 && SUCCEEDED(pBV2->GetPreferredAspectRatio(&arx, &ary)) && arx > 0 && ary > 0) {
  31.             arxy.SetSize(arx, ary);
  32.         }
  33.     }
  34.  
  35.     if (wh.cx <= 0 || wh.cy <= 0) {
  36.         AfxMessageBox(IDS_MAINFRM_55, MB_ICONWARNING | MB_OK, 0);
  37.         return;
  38.     }
  39.  
  40.     // with the overlay mixer IBasicVideo2 won't tell the new AR when changed dynamically
  41.     DVD_VideoAttributes VATR;
  42.     if (GetPlaybackMode() == PM_DVD && SUCCEEDED(pDVDI->GetCurrentVideoAttributes(&VATR))) {
  43.         arxy.SetSize(VATR.ulAspectX, VATR.ulAspectY);
  44.     }
  45.  
  46.     video = (arxy.cx <= 0 || arxy.cy <= 0) ? wh : CSize(MulDiv(wh.cy, arxy.cx, arxy.cy), wh.cy);
  47.  
  48.     //
  49.  
  50.     const CAppSettings& s = AfxGetAppSettings();
  51.  
  52.     int cols = max(1, min(10, s.iThumbCols)), rows = max(1, min(20, s.iThumbRows));
  53.  
  54.     int margin = 5;
  55.     int infoheight = 70;
  56.     int width = max(256, min(2560, s.iThumbWidth));
  57.     int height = width * video.cy / video.cx * rows / cols + infoheight;
  58.  
  59.     int dibsize = sizeof(BITMAPINFOHEADER) + width * height * 4;
  60.  
  61.     CAutoVectorPtr<BYTE> dib;
  62.     if (!dib.Allocate(dibsize)) {
  63.         AfxMessageBox(IDS_MAINFRM_56, MB_ICONWARNING | MB_OK, 0);
  64.         return;
  65.     }
  66.  
  67.     BITMAPINFOHEADER* bih = (BITMAPINFOHEADER*)(BYTE*)dib;
  68.     memset(bih, 0, sizeof(BITMAPINFOHEADER));
  69.     bih->biSize = sizeof(BITMAPINFOHEADER);
  70.     bih->biWidth = width;
  71.     bih->biHeight = height;
  72.     bih->biPlanes = 1;
  73.     bih->biBitCount = 32;
  74.     bih->biCompression = BI_RGB;
  75.     bih->biSizeImage = width * height * 4;
  76.     memsetd(bih + 1, 0xffffff, bih->biSizeImage);
  77.  
  78.     SubPicDesc spd;
  79.     spd.w = width;
  80.     spd.h = height;
  81.     spd.bpp = 32;
  82.     spd.pitch = -width * 4;
  83.     spd.vidrect = CRect(0, 0, width, height);
  84.     spd.bits = (BYTE*)(bih + 1) + (width * 4) * (height - 1);
  85.  
  86.     {
  87.         BYTE* p = (BYTE*)spd.bits;
  88.         for (int y = 0; y < spd.h; y++, p += spd.pitch)
  89.             for (int x = 0; x < spd.w; x++) {
  90.                 ((DWORD*)p)[x] = 0x010101 * (0xe0 + 0x08 * y / spd.h + 0x18 * (spd.w - x) / spd.w);
  91.             }
  92.     }
  93.  
  94.     CCritSec csSubLock;
  95.     RECT bbox;
  96.  
  97.     for (int i = 1, pics = cols * rows; i <= pics; i++) {
  98.         REFERENCE_TIME rt = rtDur * i / (pics + 1);
  99.         DVD_HMSF_TIMECODE hmsf = RT2HMS_r(rt);
  100.  
  101.         SeekTo(rt);
  102.  
  103.         m_VolumeBeforeFrameStepping = m_wndToolBar.Volume;
  104.         pBA->put_Volume(-10000);
  105.  
  106.         HRESULT hr = pFS ? pFS->Step(1, NULL) : E_FAIL;
  107.  
  108.         if (FAILED(hr)) {
  109.             pBA->put_Volume(m_VolumeBeforeFrameStepping);
  110.             AfxMessageBox(IDS_FRAME_STEP_ERROR_RENDERER, MB_ICONEXCLAMATION | MB_OK, 0);
  111.             return;
  112.         }
  113.  
  114.         HANDLE hGraphEvent = NULL;
  115.         pME->GetEventHandle((OAEVENT*)&hGraphEvent);
  116.  
  117.         while (hGraphEvent && WaitForSingleObject(hGraphEvent, INFINITE) == WAIT_OBJECT_0) {
  118.             LONG evCode = 0;
  119.             LONG_PTR evParam1, evParam2;
  120.             while (pME && SUCCEEDED(pME->GetEvent(&evCode, &evParam1, &evParam2, 0))) {
  121.                 pME->FreeEventParams(evCode, evParam1, evParam2);
  122.                 if (EC_STEP_COMPLETE == evCode) {
  123.                     hGraphEvent = NULL;
  124.                 }
  125.             }
  126.         }
  127.  
  128.         pBA->put_Volume(m_VolumeBeforeFrameStepping);
  129.  
  130.         int col = (i - 1) % cols;
  131.         int row = (i - 1) / cols;
  132.  
  133.         CSize siz((width - margin * 2) / cols, (height - margin * 2 - infoheight) / rows);
  134.         CPoint p(margin + col * siz.cx, margin + row * siz.cy + infoheight);
  135.         CRect r(p, siz);
  136.         r.DeflateRect(margin, margin);
  137.  
  138.         CRenderedTextSubtitle rts(&csSubLock);
  139.         rts.CreateDefaultStyle(0);
  140.         rts.m_dstScreenSize.SetSize(width, height);
  141.         STSStyle* style = DNew STSStyle();
  142.         style->marginRect.SetRectEmpty();
  143.         rts.AddStyle(_T("thumbs"), style);
  144.  
  145.         CStringW str;
  146.         str.Format(L"{\\an7\\1c&Hffffff&\\4a&Hb0&\\bord1\\shad4\\be1}{\\p1}m %d %d l %d %d %d %d %d %d{\\p}",
  147.                    r.left, r.top, r.right, r.top, r.right, r.bottom, r.left, r.bottom);
  148.         rts.Add(str, true, 0, 1, _T("thumbs"));
  149.         str.Format(L"{\\an3\\1c&Hffffff&\\3c&H000000&\\alpha&H80&\\fs16\\b1\\bord2\\shad0\\pos(%d,%d)}%02d:%02d:%02d",
  150.                    r.right - 5, r.bottom - 3, hmsf.bHours, hmsf.bMinutes, hmsf.bSeconds);
  151.         rts.Add(str, true, 1, 2, _T("thumbs"));
  152.  
  153.         rts.Render(spd, 0, 25, bbox);
  154.  
  155.         BYTE* pData = NULL;
  156.         long size = 0;
  157.         if (!GetDIB(&pData, size)) {
  158.             return;
  159.         }
  160.  
  161.         BITMAPINFO* bi = (BITMAPINFO*)pData;
  162.  
  163.         if (bi->bmiHeader.biBitCount != 32) {
  164.             delete [] pData;
  165.             CString strTemp;
  166.             strTemp.Format(IDS_MAINFRM_57, bi->bmiHeader.biBitCount);
  167.             AfxMessageBox(strTemp);
  168.             return;
  169.         }
  170.  
  171.         int sw = bi->bmiHeader.biWidth;
  172.         int sh = abs(bi->bmiHeader.biHeight);
  173.         int sp = sw * 4;
  174.         const BYTE* src = pData + sizeof(bi->bmiHeader);
  175.         if (bi->bmiHeader.biHeight >= 0) {
  176.             src += sp * (sh - 1);
  177.             sp = -sp;
  178.         }
  179.  
  180.         int dp = spd.pitch;
  181.         BYTE* dst = (BYTE*)spd.bits + spd.pitch * r.top + r.left * 4;
  182.  
  183.         for (DWORD h = r.bottom - r.top, y = 0, yd = (sh << 8) / h; h > 0; y += yd, h--) {
  184.             DWORD yf = y & 0xff;
  185.             DWORD yi = y >> 8;
  186.  
  187.             DWORD* s0 = (DWORD*)(src + (int)yi * sp);
  188.             DWORD* s1 = (DWORD*)(src + (int)yi * sp + sp);
  189.             DWORD* d = (DWORD*)dst;
  190.  
  191.             for (DWORD w = r.right - r.left, x = 0, xd = (sw << 8) / w; w > 0; x += xd, w--) {
  192.                 DWORD xf = x & 0xff;
  193.                 DWORD xi = x >> 8;
  194.  
  195.                 DWORD c0 = s0[xi];
  196.                 DWORD c1 = s0[xi + 1];
  197.                 DWORD c2 = s1[xi];
  198.                 DWORD c3 = s1[xi + 1];
  199.  
  200.                 c0 = ((c0 & 0xff00ff) + ((((c1 & 0xff00ff) - (c0 & 0xff00ff)) * xf) >> 8)) & 0xff00ff
  201.                      | ((c0 & 0x00ff00) + ((((c1 & 0x00ff00) - (c0 & 0x00ff00)) * xf) >> 8)) & 0x00ff00;
  202.  
  203.                 c2 = ((c2 & 0xff00ff) + ((((c3 & 0xff00ff) - (c2 & 0xff00ff)) * xf) >> 8)) & 0xff00ff
  204.                      | ((c2 & 0x00ff00) + ((((c3 & 0x00ff00) - (c2 & 0x00ff00)) * xf) >> 8)) & 0x00ff00;
  205.  
  206.                 c0 = ((c0 & 0xff00ff) + ((((c2 & 0xff00ff) - (c0 & 0xff00ff)) * yf) >> 8)) & 0xff00ff
  207.                      | ((c0 & 0x00ff00) + ((((c2 & 0x00ff00) - (c0 & 0x00ff00)) * yf) >> 8)) & 0x00ff00;
  208.  
  209.                 *d++ = c0;
  210.             }
  211.  
  212.             dst += dp;
  213.         }
  214.  
  215.         rts.Render(spd, 10000, 25, bbox);
  216.  
  217.         delete [] pData;
  218.     }
  219.  
  220.     {
  221.         CRenderedTextSubtitle rts(&csSubLock);
  222.         rts.CreateDefaultStyle(0);
  223.         rts.m_dstScreenSize.SetSize(width, height);
  224.         STSStyle* style = DNew STSStyle();
  225.         style->marginRect.SetRect(margin * 2, margin * 2, margin * 2, height - infoheight - margin);
  226.         rts.AddStyle(_T("thumbs"), style);
  227.  
  228.         CStringW str;
  229.         str.Format(L"{\\an9\\fs%d\\b1\\bord0\\shad0\\1c&Hffffff&}%s", infoheight - 10, width >= 550 ? L"Media Player Classic" : L"MPC");
  230.  
  231.         rts.Add(str, true, 0, 1, _T("thumbs"), _T(""), _T(""), CRect(0, 0, 0, 0), -1);
  232.  
  233.         DVD_HMSF_TIMECODE hmsf = RT2HMS_r(rtDur);
  234.  
  235.         CPath path(m_wndPlaylistBar.GetCurFileName());
  236.         path.StripPath();
  237.         CStringW fnp = (LPCTSTR)path;
  238.  
  239.         CStringW fs;
  240.         WIN32_FIND_DATA wfd;
  241.         HANDLE hFind = FindFirstFile(m_wndPlaylistBar.GetCurFileName(), &wfd);
  242.         if (hFind != INVALID_HANDLE_VALUE) {
  243.             FindClose(hFind);
  244.  
  245.             __int64 size = (__int64(wfd.nFileSizeHigh) << 32) | wfd.nFileSizeLow;
  246.             const int MAX_FILE_SIZE_BUFFER = 65;
  247.             WCHAR szFileSize[MAX_FILE_SIZE_BUFFER];
  248.             StrFormatByteSizeW(size, szFileSize, MAX_FILE_SIZE_BUFFER);
  249.             CString szByteSize;
  250.             szByteSize.Format(_T("%I64d"), size);
  251.             fs.Format(IDS_MAINFRM_58, szFileSize, FormatNumber(szByteSize));
  252.         }
  253.  
  254.         CStringW ar;
  255.         if (arxy.cx > 0 && arxy.cy > 0 && arxy.cx != wh.cx && arxy.cy != wh.cy) {
  256.             ar.Format(L"(%d:%d)", arxy.cx, arxy.cy);
  257.         }
  258.  
  259.         str.Format(IDS_MAINFRM_59,
  260.                    fnp, fs, wh.cx, wh.cy, ar, hmsf.bHours, hmsf.bMinutes, hmsf.bSeconds);
  261.         rts.Add(str, true, 0, 1, _T("thumbs"));
  262.  
  263.         rts.Render(spd, 0, 25, bbox);
  264.     }
  265.  
  266.     SaveDIB(fn, (BYTE*)dib, dibsize);
  267.  
  268.     SeekTo(rtPos);
  269.  
  270.     m_OSD.DisplayMessage(OSD_TOPLEFT, ResStr(IDS_OSD_THUMBS_SAVED), 3000);
  271. }
Advertisement
Add Comment
Please, Sign In to add comment