home *** CD-ROM | disk | FTP | other *** search
- //------------------------------------------------------------------------------
- // File: Demonstration.CPP
- //
- // Desc: DirectShow sample code
- // Implementation of CDemonstration,
- // "special effects" module to represent capabilities of VMR.
- // This class is called from CVMRMixDlg by "Play" button.
- // CDemonstration contains CVMRCore member (VMR engine) through which
- // it performs initialization of the graph builder and presentation.
- //
- // Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved.
- //------------------------------------------------------------------------------
-
- #include "stdafx.h"
- #include "Demonstration.h"
- #include <math.h>
-
- #define DO_NOT_RUN_YET true
-
- //------------------------------------------------------------------------------
- // Perform
- // Desc: Performs presentation. Just call it from the 'parent' dialog
- // Return HRESULT
- //------------------------------------------------------------------------------
- HRESULT CDemonstration::Perform()
- {
- HRESULT hr = S_OK;
- clock_t tStart;
- clock_t tCurrent;
- clock_t tUpdate;
-
- if( false == m_bInitialized )
- {
- hr = Initialize();
- }
- if( FAILED(hr) )
- {
- return hr;
- }
-
- try
- {
- hr = m_pCore->Play();
- if( FAILED(hr) )
- {
- sprintf( m_szMsg, "Failed to run VMR, method returned %s\n", hresultNameLookup(hr));
- OutputDebugString(m_szMsg);
- return hr;
- }
- }
- catch(...)
- {
- OutputDebugString("Unhandled exception in CDemonstration::Perform()\n");
- ShellAbort(m_pCore);
- return E_POINTER;
- }
-
- tStart = clock();
- tCurrent = clock();
- tUpdate = clock();
-
-
- // presentation loop: wait until presentation is over
- // or user closed the window and VMRCore is inactive
- while( (tCurrent - tStart) / CLOCKS_PER_SEC < m_MList.GetAvgDuration() / 10000000L &&
- m_pCore->IsActive() )
- {
- Sleep(10);
- UpdateStreams(tStart);
- tCurrent = clock();
- }// while
-
- return S_OK;
- }
-
- //------------------------------------------------------------------------------
- // Initialize()
- // Desc: Initializes demonstration; fills start parameters,
- // creates the graph for VMR; renders files
- // Return: HRESULT
- //------------------------------------------------------------------------------
- HRESULT CDemonstration::Initialize()
- {
- HRESULT hr = S_OK;
- LONGLONG llCurrent = 0L;
- LONGLONG llStop = 0L;
- LONGLONG llDelay = 0L;
- clock_t tStart;
-
- // calculate playback time
- m_MList.AdjustDuration();
-
- m_MList.SetInitialParameters();
-
- // create VMRCore
- m_pCore = new CVMRCore(m_pDlg, &m_MList );
-
- tStart = clock();
-
- if( !m_pCore)
- {
- return E_OUTOFMEMORY;
- }
-
- // here, VMRCore creates the graph and if successfully, runs IMediaControl
- // for the first file from the media list
- hr = m_pCore->Play(DO_NOT_RUN_YET);
- if(FAILED(hr))
- {
- return hr;
- }
-
- // if user selected "show bitmap" option, load the bitmap
- // from the resource and apply color key
- if( m_pDlg->IsBitmapToUse())
- {
- hr = SetAlphaBitmapColorKey(IDB_BITMAP_LOGO);
-
- if(FAILED(hr))
- {
- OutputDebugString("Failed to SetAlphaBitmapColorKey() in CDemonstration::Initialize()\n");
- return E_INVALIDARG;
- }
- }
-
- m_bInitialized = true;
-
- return S_OK;
- }
-
- //------------------------------------------------------------------------------
- // SetAlphaBitmapColorKey
- // Desc: initializes proper members of VMRALPHABITMAP for solor key support
- // Parameters: [in] UINT ImageID - resource ID
- // Return: HRESULT
- //------------------------------------------------------------------------------
- HRESULT CDemonstration::SetAlphaBitmapColorKey(UINT ImageID)
- {
- HRESULT hr;
-
- if( ! m_pCore )
- {
- OutputDebugString("Function SetAlphaBitmapColorKey() is called before initializing m_pCore\n");
- return E_INVALIDARG;
- }
- // prepare the valid default bitmap
- if (GetValidVMRBitmap(ImageID) != FNS_PASS)
- {
- OutputDebugString("Unable to get a valid VMRALPHABITMAP\n");
- return E_INVALIDARG;
- }
-
- m_sBmpParams.fAlpha = 1.0f;
- m_sBmpParams.clrSrcKey = RGB(255,255,255);
- m_sBmpParams.dwFlags |= VMRBITMAP_SRCCOLORKEY;
-
- try
- {
- hr = m_pCore->GetMixerBitmap()->SetAlphaBitmap(&m_sBmpParams);
-
- if( FAILED(hr) )
- {
- return hr;
- }
- } // try
- catch(...)
- {
- return ShellAbort(m_pCore);
- }
- return S_OK;
- }
-
- //------------------------------------------------------------------------------
- // GetValidVMRBitmap
- // Desc: creates bitmap compatible with VMR
- // Parameters: [in] UINT ImageID - resource ID
- // [out] VMRALPHABITMAP * vmrBmp - what IVMRMixerBitmap uses
- // Return: HRESULT
- //------------------------------------------------------------------------------
- HRESULT CDemonstration::GetValidVMRBitmap(UINT ImageID)
- {
- HRESULT hr = S_OK;
- long cx, cy;
- HDC hdc;
- HBITMAP hbmpVmr;
- BITMAP bmp;
-
- hr = m_pCore->GetVMRWndless()->GetNativeVideoSize(&cx, &cy, NULL, NULL);
- if( FAILED(hr) )
- {
- OutputDebugString("Failed in GetNativeVideoSize()\n");
- return hr;
- }
-
- // get compatible DC
- hdc = GetDC(m_pCore->GetClientHwnd());
-
- m_hbmp = CreateCompatibleBitmap(hdc, cx, cy); /*** RELEASE ***/
-
- hbmpVmr = (HBITMAP)LoadImage(AfxGetInstanceHandle(),MAKEINTRESOURCE(ImageID),IMAGE_BITMAP,0,0,/*LR_LOADFROMFILE|*/LR_CREATEDIBSECTION);
- if( !hbmpVmr )
- {
- OutputDebugString("Failed to load resource\n");
- DeleteObject(m_hbmp);
- return E_INVALIDARG;
- }
-
- // Get size of the bitmap
- GetObject( hbmpVmr, sizeof(bmp), &bmp );
-
- HDC hdcBmp = CreateCompatibleDC(hdc); /*** RELEASE ***/
- HDC hdcVMR = CreateCompatibleDC(hdc);
-
- ReleaseDC(m_pCore->GetClientHwnd(), hdc);
-
- HBITMAP hbmpold = (HBITMAP)SelectObject(hdcBmp, m_hbmp);// in hdcBmp, select hbmp
- hbmpVmr = (HBITMAP)SelectObject(hdcVMR, hbmpVmr);// in hdcVmr, select hbmpVmr (the pic we loaded)
-
- BitBlt(hdcBmp, 0, 0, bmp.bmWidth, bmp.bmHeight, hdcVMR, 0, 0, SRCPAINT);// put loaded pic from hdcVmr to hdcBmp
- DeleteObject(SelectObject(hdcVMR, hbmpVmr));// ok, we do not need hbmpVmr any more
- DeleteDC(hdcVMR);
-
- RECT rc;
-
- ZeroMemory(&m_sBmpParams, sizeof(VMRALPHABITMAP) );
- m_sBmpParams.dwFlags = VMRBITMAP_HDC;
- m_sBmpParams.hdc = hdcBmp;
-
- // set source rectangle (entire original bitmap)
- SetRect(&rc, 0, 0, bmp.bmWidth, bmp.bmHeight);
- m_sBmpParams.rSrc = rc;
-
- float fCoeff = 0.2f + 1.7f * (float)rand()/RAND_MAX;
- // set destination rectangle (keeping aspect ratio of the original image)
- // please note that normalized rect is always in [0.0, 1.0] range for
- // all its members
- m_sBmpParams.rDest.left = 0.f;
- m_sBmpParams.rDest.top = 0.f;
- m_sBmpParams.rDest.right = 0.9f*(float)bmp.bmWidth / (float)cx;
- m_sBmpParams.rDest.bottom = 0.9f*(float)bmp.bmHeight / (float)cy;
- m_sBmpParams.fAlpha = 0.5f;
-
- // quite important, otherwise VMR would give error
- m_sBmpParams.pDDS = NULL;
-
- // Note: this demo uses bitmap directly, but often it is better to create
- // DirectDrawSurface of appropriate format and set m_sBmpParams.pDDS to it
- // (especially if you experience performance issues)
-
- return S_OK;
- }
-
-
- //------------------------------------------------------------------------------
- // UpdateStreams
- // Desc: updates presentation parameters (destination rectangles and alpha level)
- // for each media file
- // Parameters: clock_t tStart -- presentation start; used as a 'time' variable
- // in calculations
- // Return: HRESULT
- //------------------------------------------------------------------------------
- HRESULT CDemonstration::UpdateStreams(clock_t tStart)
- {
- HRESULT hr = S_OK;
- int i;
- clock_t tCurrent;
- NORMALIZEDRECT rectD0;
- NORMALIZEDRECT rectD;
- NORMALIZEDRECT rectDRes;
- double Alpha0;
- double Alpha;
-
- ASSERT( tStart >0 );
-
- for( i=0; i< this->m_MList.Size(); i++)
- {
- if( false == m_MList.GetItem(i)->m_bInUse)
- continue;
-
- tCurrent = clock() - tStart;
-
- rectD0 = m_MList.GetItem(i)->m_rD;
- Alpha0 = m_MList.GetItem(i)->m_fAlpha;
-
- Alpha = 1.f;
- rectD.left = rectD.top = 0.f;
- rectD.right = rectD.bottom = 1.f;
-
- FountainPath( tCurrent,
- (long)(m_MList.GetAvgDuration() / 10000000 * CLOCKS_PER_SEC),
- i,
- rectD0,
- Alpha0,
- &rectD,
- &Alpha);
-
- hr = m_pCore->GetMixerControl()->SetAlpha(i, (float)Alpha);
- if( !SUCCEEDED(hr))
- {
- sprintf( m_szMsg, "Failure in CDemonstration::UpdateStreams, GetMixerControl()->SetAlpha, method returned %s\n",
- hresultNameLookup(hr));
- OutputDebugString(m_szMsg);
- }
- hr = m_pCore->GetMixerControl()->SetOutputRect(i, &rectD);
- if( !SUCCEEDED(hr))
- {
- sprintf( m_szMsg, "Failure in CDemonstration::UpdateStreams, GetMixerControl()->SetOutputRect, method returned %s\n",
- hresultNameLookup(hr));
- OutputDebugString(m_szMsg);
- }
-
- hr = m_pCore->GetMixerControl()->GetOutputRect(i, &rectDRes);
- if( !SUCCEEDED(hr))
- {
- sprintf( m_szMsg, "Failure in CDemonstration::UpdateStreams, GetMixerControl()->GetOutputRect, method returned %s\n",
- hresultNameLookup(hr));
- OutputDebugString(m_szMsg);
- }
- else
- {
- if( fabs(rectD.top - rectDRes.top) > 0.01 ||
- fabs(rectD.bottom - rectDRes.bottom) > 0.01 ||
- fabs(rectD.left - rectDRes.left) > 0.01 ||
- fabs(rectD.right - rectDRes.right) > 0.01 )
- {
- sprintf( m_szMsg, "Failed invalidation of SetOutputRect(): required [l,t,r,b] = [%f,%f,%f,%f] and returned [%f,%f,%f,%f]\n",
- rectD.left, rectD.top, rectD.right, rectD.bottom,
- rectDRes.left, rectDRes.top, rectDRes.right, rectDRes.bottom );
- OutputDebugString(m_szMsg);
- }
- }// else
-
- }// for
-
- return hr;
- }
-
-
- //------------------------------------------------------------------------------
- // Name: FountainPath
- // Purpose: creates 'movie fountain' effect; for each stream, center point
- // moves by a random ellipse around the center of a playback window;
- // size and alpha-level of stream's output rect changes by cosine with
- // some random initial delay (to desynchronize streams)
- // Parameters:
- // [IN] long t - current timestamp (any units, we use relative time)
- // [IN] long T - expected total playback time (in the same units as t)
- // [IN] int n - id of particular stream we want to set
- // [IN] NORMALIZEDRECT r0 - original OutputRect of the stream
- // [IN] double A0 - original alpha level (used as a parameter for smoothly
- // changing alpha level)
- // [OUT] NORMALIZEDRECT * pR - dest. part of playback window
- // [OUT] double * pA - new alpha level
- //------------------------------------------------------------------------------
- void CDemonstration::FountainPath( long t,
- long T,
- int n,
- NORMALIZEDRECT r0,
- double A0,
- NORMALIZEDRECT * pR,
- double * pA)
- {
- double cx0; // original center of the output rect, in normalized coordinates
- double cy0;
- double cx; // new center of the output rect, in normalized coordinates
- double cy;
- double cx1; // auxiliary center of the output rect, in normalized coordinates
- double cy1;
- double L0; // original half-diagonal measure of the rectangle
- double w; // orig. rect width
- double h; // orig. rect height
- double beta; // shift in cosine for L(t). see below
- double L; // new half-diagonal measure of the rectangle
- double tau; // time in relative units
- double gamma; // shift in sine for A(t). see below
- double coeff; // coefficient that is used to create 'mirror-flip' effect
- double dx; // new half-width
- double dy; // new half-heights
-
- // relative time, to have about 3 periods over the total playtime
- tau = 18.0 * (double)t / T;
-
- // alpha level, A = 0.2 + 0.8 sin( tau + gamma) where gamma is such that A(0)=A0
- gamma = (A0 - 0.2)/0.8;
- gamma = (gamma < -1.) ? -1. : gamma;
- gamma = (gamma > 1. ) ? 1. : gamma;
- gamma = asin( gamma);
- *pA = 0.6 + 0.4 * sin(tau + gamma + A0);
-
- cx0 = (r0.left + r0.right)/2.;
- cy0 = (r0.top + r0.bottom)/2.;
- w = r0.right - r0.left;
- h = r0.bottom - r0.top;
- L0 = 0.5 * sqrt(w*w + h*h);
-
- L0 = (L0 < 0.0001) ? 0.1 : L0;
- // now rectangle. Its half-diagonal measure L = 0.1 + 0.7 cos( tau + beta)
- // where beta is such that L(0) = LO;
- beta = (L0 - 0.1)/0.7;
- beta = (beta < -1.) ? -1. : beta;
- beta = (beta > 1.) ? 1. : beta;
- beta = acos( beta);
- L = 0.35 + 0.45 * cos( tau + beta + 3.*A0);
-
- // center of the rectangle is moving by ellips
- // cx = cx0 + (-1)^n 0.1 sin(tau);
- // cy = cy0 - 0.2 + 0.2 cos( tau);
- // and turn it buy... say, theta = 7.85 A0 - 1.57;
- coeff = (n%2) ? -1. : 1.;
- cx1 = cx0 + coeff * 0.2 * sin(tau + A0);
- cy1 = cy0 - 0.05 + 0.2 * cos( tau + A0);
-
- // the lines below are unnecessary, but we could want some
- // additional transformation here, like turn trajectory ellipse
- // by some angle
- cx = cx1;
- cy = cy1;
-
- dx = L * w / L0;
- dy = L * h / L0;
-
- pR->left = (float)(cx - dx);
- pR->right = (float)(cx + dx);
- pR->top = (float)(cy - dy);
- pR->bottom = (float)(cy + dy);
- }
-
-
-