// This code and information is provided "as is" without warranty of // any kind, either expressed or implied, including but not limited to // the implied warranties of merchantability and/or fitness for a // particular purpose. // Copyright (C) 1996 - 1998 Intel corporation. All rights reserved. // IPlaydoc.cpp : implementation of the CIPlayDoc class // #include "stdafx.h" #include "IPlay.h" #include "IPlaydoc.h" #include // OLE (Quartz) initialization #include "ax_spec.h" #ifdef _DEBUG #undef THIS_FILE static char BASED_CODE THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CIPlayDoc IMPLEMENT_DYNCREATE(CIPlayDoc, CDocument) #define new DEBUG_NEW //Checking for mem leaks in debug mode BEGIN_MESSAGE_MAP(CIPlayDoc, CDocument) //{{AFX_MSG_MAP(CIPlayDoc) ON_COMMAND(ID_MEDIA_LOOP, OnMediaLoop) ON_COMMAND(ID_MEDIA_PAUSE, OnMediaPause) ON_COMMAND(ID_MEDIA_ZOOMX2, OnMediaZoomx2) ON_UPDATE_COMMAND_UI(ID_MEDIA_PAUSE, OnUpdateMediaPause) ON_UPDATE_COMMAND_UI(ID_MEDIA_PLAY, OnUpdateMediaPlay) ON_UPDATE_COMMAND_UI(ID_MEDIA_STOP, OnUpdateMediaStop) ON_UPDATE_COMMAND_UI(ID_MEDIA_ZOOMX2, OnUpdateMediaZoomx2) ON_UPDATE_COMMAND_UI(ID_MEDIA_LOOP, OnUpdateMediaLoop) ON_COMMAND(ID_MEDIA_PLAY, OnMediaPlay) ON_COMMAND(ID_MEDIA_STOP, OnMediaStop) //}}AFX_MSG_MAP END_MESSAGE_MAP() R4_DEC_SEQ_DATA m_r4SeqData; // Indeo data structures R4_DEC_FRAME_DATA m_r4FrameData; ///////////////////////////////////////////////////////////////////////////// // CIPlayDoc construction/destruction CIPlayDoc::CIPlayDoc() { m_pGraph = NULL; m_hGraphEvent = NULL; m_pIndeo = NULL; m_lpstrPath[0] = '\0'; m_bLoop = FALSE; m_bZoom = FALSE; m_lWidth = 0; m_lHeight = 0; m_State = Uninitialized; // Initialize the headers for the Indeo data structures // This stuff never changes (except for dwFlags) m_r4FrameData.dwSize = sizeof(R4_DEC_FRAME_DATA); m_r4FrameData.dwFourCC = FOURCC_IV41; m_r4FrameData.dwVersion = SPECIFIC_INTERFACE_VERSION; m_r4FrameData.oeEnvironment = OE_32; m_r4FrameData.dwFlags = 0; m_r4SeqData.dwSize = sizeof(R4_DEC_SEQ_DATA); m_r4SeqData.dwFourCC = FOURCC_IV41; m_r4SeqData.dwVersion = SPECIFIC_INTERFACE_VERSION; m_r4SeqData.oeEnvironment = OE_32; m_r4SeqData.dwFlags = 0; ((CIPlayApp *) AfxGetApp())->OnDocumentCreated( this ); } CIPlayDoc::~CIPlayDoc() { DeleteContents(); ((CIPlayApp *) AfxGetApp())->OnDocumentDestroyed( this ); } ///////////////////////////////////////////////////////////////////////////// // CIPlayDoc diagnostics #ifdef _DEBUG void CIPlayDoc::AssertValid() const { CDocument::AssertValid(); } void CIPlayDoc::Dump(CDumpContext& dc) const { CDocument::Dump(dc); } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CIPlayDoc Message Handlers BOOL CIPlayDoc::OnOpenDocument(LPCTSTR lpszPathName) { WCHAR wPath[MAX_PATH]; char szDrive[ _MAX_DRIVE ] ; char szDir[ _MAX_DIR ]; char szFname[ _MAX_FNAME ]; char szExt[ _MAX_EXT ]; IBaseFilter *pFilter; // EnumFilters vars IEnumFilters *pEnum; ULONG pcFetched; HRESULT hr; // HWND hVidWin; void *pIF; // generic interface to graph object // Get rid of any previously opened graph. DeleteContents(); // Create a new filter graph object. if ( !CreateFilterGraph() ) { AfxMessageBox(IDS_CANT_INIT_QUARTZ); return FALSE; } // Render the file using the new filter graph. // This will add the necessary filters to the // graph (which up til now was empty). strcpy(m_lpstrPath, lpszPathName); MultiByteToWideChar( CP_ACP, 0, lpszPathName, -1, wPath, MAX_PATH ); hr = m_pGraph->QueryInterface(IID_IGraphBuilder, &pIF); if (FAILED( ((IGraphBuilder *)pIF)->RenderFile(wPath, NULL) )) { AfxMessageBox(IDS_CANT_RENDER_FILE); return FALSE; } ((IGraphBuilder *)pIF)->Release(); // Position and set the title of the video window. _splitpath( lpszPathName, szDrive, szDir, szFname, szExt ); MultiByteToWideChar( CP_ACP, 0, CString(szFname) + szExt,-1, wPath, _MAX_FNAME + _MAX_EXT); SetWindow((BSTR)wPath); // Get and save the native video size -- used for // zoom by 2. hr = m_pGraph->QueryInterface(IID_IBasicVideo, &pIF); if( SUCCEEDED(hr) ){ ((IBasicVideo *)pIF)->GetVideoSize(&m_lWidth, &m_lHeight); ((IBasicVideo *)pIF)->Release(); } // Call the stop function to queue up the first // frame of the clip. Have to set the state first // to Paused so we can transistion to Stopped. m_State = Paused; OnMediaStop(); // See if the Indeo codec filter is in the graph. hr = m_pGraph->EnumFilters(&pEnum); if (FAILED(hr)) return TRUE; while ((hr = pEnum->Next(1, &pFilter, &pcFetched)) == S_OK) { hr = pFilter->QueryInterface(IID_IIndeoDecode, &m_pIndeo); pFilter->Release(); if (hr == S_OK) break; } // This interface needs to be released, even though // it was not obtained in the usual way with QueryInterface. pEnum->Release(); // Someday, the following line can replace the above section of code // that enumerates the filters in the graph to find the // IIndeoDecode interface, but apparently that someday is not today. //hr = m_pGraph->QueryInterface(IID_IIndeoDecode, &m_pIndeo); return TRUE; } void CIPlayDoc::OnGraphNotify(void) { IMediaEvent *pME; long lEventCode, lParam1, lParam2; ASSERT( m_hGraphEvent != NULL ); if( SUCCEEDED(m_pGraph->QueryInterface(IID_IMediaEvent, (void **) &pME))){ if( SUCCEEDED(pME->GetEvent(&lEventCode, &lParam1, &lParam2, 0)) ) { switch (lEventCode) { case EC_COMPLETE: OnMediaStop(); if (m_bLoop) OnMediaPlay(); break; case EC_USERABORT: case EC_ERRORABORT: OnMediaStop(); } } pME->Release(); } // Send a message so toolbar gets updated PostMessage( AfxGetMainWnd()->m_hWnd, WM_USER, 0, 0 ); } void CIPlayDoc::OnMediaLoop() { m_bLoop = !m_bLoop; } void CIPlayDoc::OnMediaPause() { if( CanPause() ){ HRESULT hr; IMediaControl *pMC; // Obtain the interface to our filter graph hr = m_pGraph->QueryInterface(IID_IMediaControl, (void **) &pMC); if( SUCCEEDED(hr) ){ // Ask the filter graph to pause and release the interface hr = pMC->Pause(); pMC->Release(); if( SUCCEEDED(hr) ){ m_State = Paused; return; } } } } void CIPlayDoc::OnMediaPlay() { if( CanPlay() ){ HRESULT hr; IMediaControl *pMC; // Obtain the interface to our filter graph hr = m_pGraph->QueryInterface(IID_IMediaControl, (void **) &pMC); if( SUCCEEDED(hr) ){ // Ask the filter graph to play and release the interface hr = pMC->Run(); pMC->Release(); if( SUCCEEDED(hr) ){ m_State=Playing; // Let Indeo view object know the state changed UpdateAllViews(NULL); return; } } } } void CIPlayDoc::OnMediaStop() { if( CanStop() ){ HRESULT hr; IMediaControl *pMC; IMediaPosition *pMP; OAFilterState fstate; // Obtain the interface to our filter graph hr = m_pGraph->QueryInterface(IID_IMediaControl, (void **) &pMC); if( SUCCEEDED(hr) ){ // Ask the filter graph to stop and release the interface // put graph in stopped state hr = pMC->Stop(); // Rewind the stream hr = m_pGraph->QueryInterface(IID_IMediaPosition, (void **) &pMP); hr = pMP->put_CurrentPosition(0); hr = pMP->Release(); // Flush the graph hr = pMC->Pause(); // Wait for state transition to complete hr = pMC->GetState(5000, &fstate); // Now back to stopped state hr = pMC->Stop(); pMC->Release(); if( SUCCEEDED(hr) ){ m_State = Stopped; // Let Indeo view object know the state changed UpdateAllViews(NULL); return; } } } } void CIPlayDoc::OnMediaZoomx2() { // This function doubles the width & height of the original video // size -- depending on the hardware, this may result in a // better quality video than a random stretch of the video window. // Subsequent calls toggle the video size between the original size // and the "x2" size, ignoring the fact that the user may have // resized the window using the window frame. The function attempts to // keep the video window's center in place (zooms/unzooms from top, // bottom, right and left). HRESULT hr; void *pIF; long x,y,width,height,width2,height2; m_bZoom = !m_bZoom; hr = m_pGraph->QueryInterface(IID_IVideoWindow, &pIF); if( SUCCEEDED(hr) ){ if (m_bZoom) { // Set the width & height to twice the native video size // Allow for the window frame -- we really want to just // double the size of the client area. width2 = (m_lWidth * 2) + (m_lWinWidth - m_lWidth); height2 = (m_lHeight * 2) + (m_lWinHeight - m_lHeight); ((IVideoWindow *)pIF)->GetWindowPosition(&x, &y, &width, &height); ((IVideoWindow *)pIF)->SetWindowPosition(x + (width - width2)/2, y + (height - height2)/2, width2, height2); } else { // Restore original size ((IVideoWindow *)pIF)->GetWindowPosition(&x, &y, &width, &height); ((IVideoWindow *)pIF)->SetWindowPosition(x + (width - m_lWinWidth)/2, y + (height - m_lWinHeight)/2, m_lWinWidth, m_lWinHeight); } ((IVideoWindow *)pIF)->Release(); } } void CIPlayDoc::OnUpdateMediaPause(CCmdUI* pCmdUI) { pCmdUI->Enable( CanPause() ); } void CIPlayDoc::OnUpdateMediaPlay(CCmdUI* pCmdUI) { pCmdUI->Enable( CanPlay() ); } void CIPlayDoc::OnUpdateMediaStop(CCmdUI* pCmdUI) { pCmdUI->Enable( CanStop() ); } void CIPlayDoc::OnUpdateMediaLoop(CCmdUI* pCmdUI) { pCmdUI->Enable( IsInitialized() ); pCmdUI->SetCheck( m_bLoop ); } void CIPlayDoc::OnUpdateMediaZoomx2(CCmdUI* pCmdUI) { pCmdUI->Enable( IsInitialized() ); pCmdUI->SetCheck( m_bZoom ); } ///////////////////////////////////////////////////////////////////////////// // CIPlayDoc Commands BOOL CIPlayDoc::IsIndeo() { return (m_pIndeo != NULL); } void CIPlayDoc::GetTransFillRGB(int& red, int& green, int& blue) { HRESULT hr; m_r4FrameData.mtType = MT_DECODE_FRAME_VALUE; m_r4FrameData.dwFlags = DECFRAME_FILL_COLOR | DECFRAME_VALID; m_r4FrameData.dwFillColor = DECFRAME_FILL_UNDEFINED; hr = ((IIndeoDecode *)m_pIndeo)->get_DecodeFrame(&m_r4FrameData); if (FAILED( hr )) { AfxMessageBox(IDS_CANT_GET_FRAME_DATA); return; } if (m_r4FrameData.dwFillColor & DECFRAME_FILL_UNDEFINED) { red = 0; green = 0; blue = 0; } else { // Fill color is valid red = (m_r4FrameData.dwFillColor&0x00FF0000)>>16; green = (m_r4FrameData.dwFillColor&0x0000FF00)>>8; blue = (m_r4FrameData.dwFillColor&0x000000FF); } return; } void CIPlayDoc::GetBCS(int& b, int& c, int& s) { HRESULT hr; m_r4FrameData.mtType = MT_DECODE_FRAME_VALUE; m_r4FrameData.dwFlags = DECFRAME_BRIGHTNESS | DECFRAME_CONTRAST | DECFRAME_SATURATION | DECFRAME_VALID; hr = ((IIndeoDecode *)m_pIndeo)->get_DecodeFrame(&m_r4FrameData); if (FAILED( hr )) { AfxMessageBox(IDS_CANT_GET_FRAME_DATA); return; } b = LOWORD(m_r4FrameData.lBrightness); c = LOWORD(m_r4FrameData.lContrast); s = LOWORD(m_r4FrameData.lSaturation); return; } void CIPlayDoc::GetDecodeTime(DWORD& time) { HRESULT hr; m_r4FrameData.mtType = MT_DECODE_FRAME_VALUE; m_r4FrameData.dwFlags = DECFRAME_TIME_LIMIT | DECFRAME_VALID; hr = ((IIndeoDecode *)m_pIndeo)->get_DecodeFrame(&m_r4FrameData); if (FAILED( hr )) { AfxMessageBox(IDS_CANT_SET_FRAME_DATA); return; } time = m_r4FrameData.dwTimeLimit; return; } void CIPlayDoc::GetDecodeRect(DWORD& x, DWORD& y, DWORD& width, DWORD& height) { HRESULT hr; m_r4FrameData.mtType = MT_DECODE_FRAME_VALUE; m_r4FrameData.dwFlags = DECFRAME_DECODE_RECT | DECFRAME_VALID; hr = ((IIndeoDecode *)m_pIndeo)->get_DecodeFrame(&m_r4FrameData); if (FAILED( hr )) { AfxMessageBox(IDS_CANT_GET_FRAME_DATA); return; } x = m_r4FrameData.rDecodeRect.dwX; y = m_r4FrameData.rDecodeRect.dwY; width = m_r4FrameData.rDecodeRect.dwWidth; height = m_r4FrameData.rDecodeRect.dwHeight; return; } void CIPlayDoc::GetViewRect(DWORD& x, DWORD& y, DWORD& width, DWORD& height) { HRESULT hr; m_r4FrameData.mtType = MT_DECODE_FRAME_VALUE; m_r4FrameData.dwFlags = DECFRAME_VIEW_RECT | DECFRAME_VALID; hr = ((IIndeoDecode *)m_pIndeo)->get_DecodeFrame(&m_r4FrameData); if (FAILED( hr )) { AfxMessageBox(IDS_CANT_GET_FRAME_DATA); return; } x = m_r4FrameData.rViewRect.dwX; y = m_r4FrameData.rViewRect.dwY; width = m_r4FrameData.rViewRect.dwWidth; height = m_r4FrameData.rViewRect.dwHeight; return; } void CIPlayDoc::GetSequenceOptions(BOOL& altline, BOOL& ddframes, BOOL& ddquality, BOOL& trans, BOOL& usekey, DWORD& key) { HRESULT hr; m_r4SeqData.mtType = MT_DECODE_SEQ_VALUE; m_r4SeqData.dwFlags = DECSEQ_KEY | DECSEQ_SCALABILITY | DECSEQ_FILL_TRANSPARENT | DECSEQ_ALT_LINE | DECSEQ_VALID; hr = ((IIndeoDecode *)m_pIndeo)->get_DecodeSequence(&m_r4SeqData); if (FAILED( hr )) { AfxMessageBox(IDS_CANT_GET_SEQ_DATA); return; } altline = m_r4SeqData.fAltLine; switch (m_r4SeqData.eScalability) { case SC_ON: ddframes = ddquality = FALSE; break; case SC_OFF: ddframes = ddquality = TRUE; break; case SC_DONT_DROP_FRAMES: ddframes = TRUE; ddquality = FALSE; break; case SC_DONT_DROP_QUALITY: ddframes = FALSE; ddquality = TRUE; break; } trans = m_r4SeqData.fFillTransparentPixels; usekey = m_r4SeqData.fEnabledKey; key = m_r4SeqData.dwKey; return; } void CIPlayDoc::SetTransFillRGB(DWORD rgb) { HRESULT hr; m_r4FrameData.mtType = MT_DECODE_FRAME_VALUE; m_r4FrameData.dwFlags = DECFRAME_VALID | DECFRAME_FILL_COLOR; m_r4FrameData.dwFillColor = rgb; hr = ((IIndeoDecode *)m_pIndeo)->set_DecodeFrame(&m_r4FrameData); if (FAILED( hr )) AfxMessageBox(IDS_CANT_SET_FRAME_DATA); return; } void CIPlayDoc::SetBCS(int b, int c, int s) { HRESULT hr; m_r4FrameData.mtType = MT_DECODE_FRAME_VALUE; m_r4FrameData.dwFlags = DECFRAME_BRIGHTNESS | DECFRAME_CONTRAST | DECFRAME_SATURATION | DECFRAME_VALID; m_r4FrameData.lBrightness = b; m_r4FrameData.lContrast = c; m_r4FrameData.lSaturation = s; hr = ((IIndeoDecode *)m_pIndeo)->set_DecodeFrame(&m_r4FrameData); if (FAILED( hr )) AfxMessageBox(IDS_CANT_SET_FRAME_DATA); return; } void CIPlayDoc::SetDecodeTime(DWORD time) { HRESULT hr; m_r4FrameData.mtType = MT_DECODE_FRAME_VALUE; m_r4FrameData.dwFlags = DECFRAME_TIME_LIMIT | DECFRAME_VALID; m_r4FrameData.dwTimeLimit = time; hr = ((IIndeoDecode *)m_pIndeo)->set_DecodeFrame(&m_r4FrameData); if (FAILED( hr )) AfxMessageBox(IDS_CANT_SET_FRAME_DATA); return; } void CIPlayDoc::SetDecodeRect(DWORD x, DWORD y, DWORD width, DWORD height) { HRESULT hr; m_r4FrameData.mtType = MT_DECODE_FRAME_VALUE; m_r4FrameData.dwFlags = DECFRAME_DECODE_RECT | DECFRAME_VALID; m_r4FrameData.rDecodeRect.dwX = x; m_r4FrameData.rDecodeRect.dwY = y; m_r4FrameData.rDecodeRect.dwWidth = width; m_r4FrameData.rDecodeRect.dwHeight = height; m_r4FrameData.rDecodeRect.dwX = x; m_r4FrameData.rDecodeRect.dwY = y; m_r4FrameData.rDecodeRect.dwWidth = width; m_r4FrameData.rDecodeRect.dwHeight = height; hr = ((IIndeoDecode *)m_pIndeo)->set_DecodeFrame(&m_r4FrameData); if (FAILED( hr )) AfxMessageBox(IDS_CANT_SET_FRAME_DATA); return; } void CIPlayDoc::SetViewRect(BOOL view ,DWORD x, DWORD y, DWORD width, DWORD height) { HRESULT hr; m_r4FrameData.mtType = MT_DECODE_FRAME_VALUE; m_r4FrameData.dwFlags = DECFRAME_VIEW_RECT | DECFRAME_VIEW_RECT_ORIGIN | DECFRAME_VALID; m_r4FrameData.fViewRectOrigin = view; m_r4FrameData.rViewRect.dwX = x; m_r4FrameData.rViewRect.dwY = y; m_r4FrameData.rViewRect.dwWidth = width; m_r4FrameData.rViewRect.dwHeight = height; hr = ((IIndeoDecode *)m_pIndeo)->set_DecodeFrame(&m_r4FrameData); if (FAILED( hr )) AfxMessageBox(IDS_CANT_SET_FRAME_DATA); return; } void CIPlayDoc::SetSequenceOptions(BOOL altline, LONG scal, BOOL fill, BOOL usekey, DWORD key) { HRESULT hr; m_r4SeqData.mtType = MT_DECODE_SEQ_VALUE; m_r4SeqData.dwFlags = DECSEQ_KEY | DECSEQ_SCALABILITY | DECSEQ_FILL_TRANSPARENT | DECSEQ_ALT_LINE | DECSEQ_VALID; m_r4SeqData.fAltLine = altline; m_r4SeqData.eScalability = scal; m_r4SeqData.fFillTransparentPixels = fill; m_r4SeqData.fEnabledKey = usekey; m_r4SeqData.dwKey = key; hr = ((IIndeoDecode *)m_pIndeo)->set_DecodeSequence(&m_r4SeqData); if (FAILED( hr )) AfxMessageBox(IDS_CANT_SET_SEQ_DATA); return; } void CIPlayDoc::GetFrameDefaults(int& b, int& c, int& s, DWORD& time, DWORD& dx, DWORD& dy, DWORD& dWidth, DWORD& dHeight, DWORD& vx, DWORD& vy, DWORD& vWidth, DWORD& vHeight) { HRESULT hr; m_r4FrameData.mtType = MT_DECODE_FRAME_DEFAULT; m_r4FrameData.dwFlags = DECFRAME_BRIGHTNESS | DECFRAME_CONTRAST | DECFRAME_SATURATION | DECFRAME_TIME_LIMIT | DECFRAME_DECODE_RECT | DECFRAME_VIEW_RECT | DECFRAME_VIEW_RECT_ORIGIN | DECFRAME_VALID; hr = ((IIndeoDecode *)m_pIndeo)->get_DecodeFrame(&m_r4FrameData); if (FAILED( hr )) { AfxMessageBox(IDS_CANT_GET_FRAME_DATA); return; } b = LOWORD(m_r4FrameData.lBrightness); c = LOWORD(m_r4FrameData.lContrast); s = LOWORD(m_r4FrameData.lSaturation); time = m_r4FrameData.dwTimeLimit; dx = m_r4FrameData.rDecodeRect.dwX; dy = m_r4FrameData.rDecodeRect.dwY; dWidth = m_r4FrameData.rDecodeRect.dwWidth; dHeight = m_r4FrameData.rDecodeRect.dwHeight; vx = m_r4FrameData.rViewRect.dwX; vy = m_r4FrameData.rViewRect.dwY; vWidth = m_r4FrameData.rViewRect.dwWidth; vHeight = m_r4FrameData.rViewRect.dwHeight; return; } void CIPlayDoc::GetSeqDefaults(BOOL& altline, BOOL& ddframes, BOOL& ddquality, BOOL& trans, BOOL& usekey, DWORD& key) { HRESULT hr; m_r4SeqData.mtType = MT_DECODE_SEQ_DEFAULT; m_r4SeqData.dwFlags = DECSEQ_KEY | DECSEQ_SCALABILITY | DECSEQ_FILL_TRANSPARENT | DECSEQ_ALT_LINE | DECSEQ_VALID; hr = ((IIndeoDecode *)m_pIndeo)->get_DecodeSequence(&m_r4SeqData); if (FAILED( hr )) { AfxMessageBox(IDS_CANT_GET_SEQ_DATA); return; } altline = m_r4SeqData.fAltLine; switch (m_r4SeqData.eScalability) { case SC_ON: ddframes = ddquality = FALSE; break; case SC_OFF: ddframes = ddquality = TRUE; break; case SC_DONT_DROP_FRAMES: ddframes = TRUE; ddquality = FALSE; break; case SC_DONT_DROP_QUALITY: ddframes = FALSE; ddquality = TRUE; break; } trans = m_r4SeqData.fFillTransparentPixels; usekey = m_r4SeqData.fEnabledKey; key = m_r4SeqData.dwKey; } ULONG CIPlayDoc::VideoWidth() { HRESULT hr; IBasicVideo *pIF; long width; hr = m_pGraph->QueryInterface(IID_IBasicVideo, (void **)&pIF); if( FAILED(hr) ) { AfxMessageBox(IDS_CANT_GET_VIDEO_INTERFACE); return 0; } pIF->get_DestinationWidth(&width); pIF->Release(); return width; } ULONG CIPlayDoc::VideoHeight() { HRESULT hr; IBasicVideo *pIF; long height; hr = m_pGraph->QueryInterface(IID_IBasicVideo, (void **)&pIF); if( FAILED(hr) ) { AfxMessageBox(IDS_CANT_GET_VIDEO_INTERFACE); return 0; } pIF->get_DestinationHeight(&height); pIF->Release(); return height; } ///////////////////////////////////////////////////////////////////////////// // CIPlayDoc protected funtions BOOL CIPlayDoc::CreateFilterGraph(void) { HRESULT hr; // return code ASSERT(m_pGraph == NULL); // Create this document's filter graph object hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IFilterGraph, (void **) &m_pGraph); if (FAILED(hr)){ m_pGraph = NULL; return FALSE; } // get media event handle IMediaEvent *pME; hr = m_pGraph->QueryInterface(IID_IMediaEvent, (void **) &pME); if (FAILED(hr)) { DeleteContents(); return FALSE; } hr = pME->GetEventHandle((OAEVENT*) &m_hGraphEvent); pME->Release(); if (FAILED(hr)) { DeleteContents(); return FALSE; } return TRUE; } void CIPlayDoc::DeleteContents() { // Release all interfaces to graph // and filters. if (m_pIndeo != NULL) { ((IIndeoDecode *)m_pIndeo)->Release(); m_pIndeo = NULL; } if (m_pGraph != NULL) { m_pGraph->Release(); m_pGraph = NULL; } m_hGraphEvent = NULL; m_State = Uninitialized; } void CIPlayDoc::SetWindow(BSTR wPath) { HRESULT hr; IVideoWindow *pVidWin; RECT rDeskTop; int x, y; hr = m_pGraph->QueryInterface(IID_IVideoWindow, (void **)&pVidWin); if( FAILED(hr) ) { AfxMessageBox(IDS_CANT_GET_WINDOW_INTERFACE); return; } // Set the caption of the video window pVidWin->put_Caption(wPath); // Save the original size for zoom x 2 pVidWin->get_Width(&m_lWinWidth); pVidWin->get_Height(&m_lWinHeight); // Center the window on the screen GetWindowRect(GetDesktopWindow(), &rDeskTop); if ( m_lWinWidth < (rDeskTop.right - rDeskTop.left) ) x = ((rDeskTop.right - rDeskTop.left) - m_lWinWidth) / 2; else x = rDeskTop.left; if ( m_lWinHeight < (rDeskTop.bottom - rDeskTop.top) ) y = ((rDeskTop.bottom - rDeskTop.top) - m_lWinHeight) / 2; else y = rDeskTop.top; pVidWin->SetWindowPosition(x, y, m_lWinWidth, m_lWinHeight); pVidWin->Release(); }