// // COutputQueuee Destructor : // // Free all resources - // // Thread, // Batched samples // COutputQueue::~COutputQueue() { DbgLog((LOG_TRACE, 3, TEXT("COutputQueue::~COutputQueue"))); /* Free our pointer */ if (m_pInputPin != NULL) { m_pInputPin->Release(); } if (m_hThread != NULL) { { CAutoLock lck(this); m_bTerminate = TRUE; m_hr = S_FALSE; NotifyThread(); } DbgWaitForSingleObject(m_hThread); EXECUTE_ASSERT(CloseHandle(m_hThread)); // The thread frees the samples when asked to terminate ASSERT(m_List->GetCount() == 0); delete m_List; } else { FreeSamples(); } if (m_hSem != NULL) { EXECUTE_ASSERT(CloseHandle(m_hSem)); } delete [] m_ppSamples; }
// destructor for CAkMsgThread - cleans up any messages left in the // queue when the thread exited CAkMsgThread::~CAkMsgThread() { #ifdef __Win32__ if(m_hThread != NULL) { WaitForSingleObject(m_hThread, INFINITE); EXECUTE_ASSERT(CloseHandle(m_hThread)); m_hThread =NULL; } while (false == m_ThreadQueue.empty()) { CMsg *pMsg = m_ThreadQueue.front(); delete pMsg; m_ThreadQueue.pop(); } if(m_hSem != NULL) { EXECUTE_ASSERT(CloseHandle(m_hSem)); } if(m_hQueueLenSem != NULL) { EXECUTE_ASSERT(CloseHandle(m_hQueueLenSem)); } #else //pthread_join(m_threadId, &status); if(m_threadId != 0) { int nret = 0; void *status = NULL; nret = pthread_join(m_threadId, &status); //GetExitCodeThread(m_hThread, lpdwExitCode); if(0 != nret) { fprintf(stderr, "pthread join thread %lu error\n", m_threadId); } //fprintf(stderr, "akmsgthread pthread_join thread 0x%lu\n", m_threadId); m_threadId = 0; } while (true != m_ThreadQueue.empty()) { CMsg *pMsg = m_ThreadQueue.front(); delete pMsg; m_ThreadQueue.pop(); } sem_destroy(&m_hSem); sem_destroy(&m_hQueueLenSem); #endif }
CBaseReferenceClock::~CBaseReferenceClock() { if(m_TimerResolution) timeEndPeriod(m_TimerResolution); m_pSchedule->DumpLinkedList(); if(m_hThread) { m_bAbort = TRUE; TriggerThread(); WaitForSingleObject(m_hThread, INFINITE); EXECUTE_ASSERT(CloseHandle(m_hThread)); m_hThread = 0; EXECUTE_ASSERT(CloseHandle(m_pSchedule->GetEvent())); delete m_pSchedule; } }
// // GetClassWindowStyles // // When we call PrepareWindow in our constructor it will call this method as // it is going to create the window to get our window and class styles. The // return code is the class name and must be allocated in static storage. We // specify a normal window during creation although the window styles as well // as the extended styles may be changed by the application via IVideoWindow // LPTSTR CVideoText::GetClassWindowStyles(DWORD *pClassStyles, DWORD *pWindowStyles, DWORD *pWindowStylesEx) { CheckPointer(pClassStyles,NULL); CheckPointer(pWindowStyles,NULL); CheckPointer(pWindowStylesEx,NULL); OSVERSIONINFO VersionInfo; VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); EXECUTE_ASSERT(GetVersionEx(&VersionInfo)); // Default styles for Windows NT systems *pClassStyles = CS_HREDRAW | CS_VREDRAW | CS_BYTEALIGNCLIENT; *pWindowStyles = WS_POPUP | WS_CLIPCHILDREN; *pWindowStylesEx = (DWORD) 0; // Make a normal window on Win95 systems if ((VersionInfo.dwPlatformId & VER_PLATFORM_WIN32_NT) == 0) *pWindowStyles = WS_POPUP | WS_CAPTION | WS_CLIPCHILDREN; return TEXT("VideoTextRenderer\0"); } // GetClassWindowStyles
void WINAPI DbgInitLogTo( HKEY hKey) { LONG lReturn; DWORD dwKeyType; DWORD dwKeySize; TCHAR szFile[MAX_PATH] = {0}; static const TCHAR cszKey[] = TEXT("LogToFile"); dwKeySize = MAX_PATH; lReturn = RegQueryValueEx(hKey, // Handle to an open key cszKey, // Subkey name derivation NULL, // Reserved field &dwKeyType, // Returns the field type (LPBYTE) szFile, // Returns the field's value &dwKeySize); // Number of bytes transferred // create an empty key if it does not already exist // if(lReturn != ERROR_SUCCESS || dwKeyType != REG_SZ) { dwKeySize = sizeof(TCHAR); lReturn = RegSetValueEx(hKey, // Handle of an open key cszKey, // Address of subkey name (DWORD) 0, // Reserved field REG_SZ, // Type of the key field (PBYTE)szFile, // Value for the field dwKeySize); // Size of the field buffer } // if an output-to was specified. try to open it. // if(m_hOutput != INVALID_HANDLE_VALUE) { EXECUTE_ASSERT(CloseHandle(m_hOutput)); m_hOutput = INVALID_HANDLE_VALUE; } if(szFile[0] != 0) { if(!lstrcmpi(szFile, TEXT("Console"))) { m_hOutput = GetStdHandle(STD_OUTPUT_HANDLE); if(m_hOutput == INVALID_HANDLE_VALUE) { AllocConsole(); m_hOutput = GetStdHandle(STD_OUTPUT_HANDLE); } SetConsoleTitle(TEXT("ActiveX Debug Output")); } else if(szFile[0] && lstrcmpi(szFile, TEXT("Debug")) && lstrcmpi(szFile, TEXT("Debugger")) && lstrcmpi(szFile, TEXT("Deb"))) { m_hOutput = CreateFile(szFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if(INVALID_HANDLE_VALUE != m_hOutput) { static const TCHAR cszBar[] = TEXT("\r\n\r\n=====DbgInitialize()=====\r\n\r\n"); SetFilePointer(m_hOutput, 0, NULL, FILE_END); DbgOutString(cszBar); } } } }
//------------------------------------------------------------------------------ // ReallyFree // called from the destructor (and from Alloc if changing size/count) to // actually free up the memory void CCustomAllocator::ReallyFree(void) { /* Should never be deleting this unless all buffers are freed */ ASSERT(m_lAllocated == m_lFree.GetCount()); ASSERT(0 == m_lDeliver.GetCount()); /* Free up all the CMediaSamples */ CMediaSample* pSample = m_lFree.RemoveHead(); while (pSample) { delete pSample; pSample = m_lFree.RemoveHead(); } m_lBuffers.RemoveAll(); m_lAllocated = 0; // free the block of buffer memory if (m_pBuffer) { EXECUTE_ASSERT(VirtualFree(m_pBuffer, 0, MEM_RELEASE)); m_pBuffer = NULL; } return; }
// destructor for CMsgThread - cleans up any messages left in the // queue when the thread exited CMsgThread::~CMsgThread() { if(m_hThread != NULL) { WaitForSingleObject(m_hThread, INFINITE); EXECUTE_ASSERT(CloseHandle(m_hThread)); } POSITION pos = m_ThreadQueue.GetHeadPosition(); while(pos) { CMsg * pMsg = m_ThreadQueue.GetNext(pos); delete pMsg; } m_ThreadQueue.RemoveAll(); if(m_hSem != NULL) { EXECUTE_ASSERT(CloseHandle(m_hSem)); } }
void WINAPI DbgTerminate() { if(m_hOutput != INVALID_HANDLE_VALUE) { EXECUTE_ASSERT(CloseHandle(m_hOutput)); m_hOutput = INVALID_HANDLE_VALUE; } DeleteCriticalSection(&m_CSDebug); m_bInit = FALSE; }
CWebServer::~CWebServer() { if(m_hThread != NULL) { PostThreadMessage(m_ThreadId, WM_QUIT, 0, 0); WaitForSingleObject(m_hThread, 10000); EXECUTE_ASSERT(CloseHandle(m_hThread)); } }
// A derived class may supply a hThreadEvent if it has its own thread that will take care // of calling the schedulers Advise method. (Refere to CBaseReferenceClock::AdviseThread() // to see what such a thread has to do.) CBaseReferenceClock::CBaseReferenceClock( TCHAR *pName, LPUNKNOWN pUnk, HRESULT *phr, CAMSchedule * pShed ) : CUnknown( pName, pUnk ) , m_rtLastGotTime(0) , m_TimerResolution(0) , m_bAbort( FALSE ) , m_pSchedule( pShed ? pShed : new CAMSchedule(CreateEvent(NULL, FALSE, FALSE, NULL)) ) , m_hThread(0) { ASSERT(m_pSchedule); if (!m_pSchedule) { *phr = E_OUTOFMEMORY; } else { // Set up the highest resolution timer we can manage TIMECAPS tc; m_TimerResolution = (TIMERR_NOERROR == timeGetDevCaps(&tc, sizeof(tc))) ? tc.wPeriodMin : 1; timeBeginPeriod(m_TimerResolution); /* Initialise our system times - the derived clock should set the right values */ m_dwPrevSystemTime = timeGetTime(); m_rtPrivateTime = (UNITS / MILLISECONDS) * m_dwPrevSystemTime; #ifdef PERF m_idGetSystemTime = MSR_REGISTER(TEXT("CBaseReferenceClock::GetTime")); #endif if ( !pShed ) { DWORD ThreadID; m_hThread = ::CreateThread(NULL, // Security attributes (DWORD) 0, // Initial stack size AdviseThreadFunction, // Thread start address (LPVOID) this, // Thread parameter (DWORD) 0, // Creation flags &ThreadID); // Thread identifier if (m_hThread) { SetThreadPriority( m_hThread, THREAD_PRIORITY_TIME_CRITICAL ); } else { *phr = E_FAIL; EXECUTE_ASSERT( CloseHandle(m_pSchedule->GetEvent()) ); delete m_pSchedule; } } } }
CWebServer::~CWebServer() { if (m_hThread != NULL) { PostThreadMessage(m_ThreadId, WM_QUIT, 0, 0); if (WaitForSingleObject(m_hThread, 10000) == WAIT_TIMEOUT) { TerminateThread(m_hThread, 0xDEAD); } EXECUTE_ASSERT(CloseHandle(m_hThread)); } }
//------------------------------------------------------------------------------ // Destructor // CCustomAllocator::~CCustomAllocator(void) { Decommit(); ReallyFree(); if (m_hSemFree) { EXECUTE_ASSERT(CloseHandle(m_hSemFree)); } }
// // OnPaint // // This is called when the window thread receives a WM_PAINT message // BOOL CTextOutFilter::OnPaint(COLORREF WindowColor) { CAutoLock cAutoLock(&m_RendererLock); RECT ClientRect; PAINTSTRUCT ps; BeginPaint(m_TextWindow.GetWindowHWND(),&ps); EndPaint(m_TextWindow.GetWindowHWND(),&ps); // Display the text if we have a sample if (m_pMediaSample) { DrawText(m_pMediaSample); return TRUE; } // Create a coloured brush to paint the window HBRUSH hBrush = CreateSolidBrush(WindowColor); EXECUTE_ASSERT(GetClientRect(m_TextWindow.GetWindowHWND(),&ClientRect)); EXECUTE_ASSERT(FillRect(m_TextWindow.GetWindowHDC(),&ClientRect,hBrush)); EXECUTE_ASSERT(DeleteObject(hBrush)); return TRUE; } // OnPaint
STDMETHODIMP CRenderedInputPin::EndOfStream() { HRESULT hr = CheckStreaming(); // Do EC_COMPLETE handling for rendered pins if (S_OK == hr && !m_bAtEndOfStream) { m_bAtEndOfStream = TRUE; FILTER_STATE fs; EXECUTE_ASSERT(SUCCEEDED(m_pFilter->GetState(0, &fs))); if (fs == State_Running) { DoCompleteHandling(); } } return hr; }
CBaseReferenceClock::~CBaseReferenceClock() { #ifdef DXMPERF PERFLOG_DTOR( L"CBaseReferenceClock", (IReferenceClock *) this ); #endif // DXMPERF if (m_TimerResolution) timeEndPeriod(m_TimerResolution); if (m_pSchedule) { m_pSchedule->DumpLinkedList(); } if (m_hThread) { m_bAbort = TRUE; TriggerThread(); WaitForSingleObject( m_hThread, INFINITE ); EXECUTE_ASSERT( CloseHandle(m_hThread) ); m_hThread = 0; EXECUTE_ASSERT( CloseHandle(m_pSchedule->GetEvent()) ); delete m_pSchedule; } }
STDMETHODIMP CBasePin::Connect( IPin * pReceivePin, const AM_MEDIA_TYPE *pmt // optional media type ) { CheckPointer(pReceivePin,E_POINTER); ValidateReadPtr(pReceivePin,sizeof(IPin)); CComAutoLock cObjectLock(m_pLock); DisplayPinInfo(pReceivePin); /* See if we are already connected */ if (m_Connected) { DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("Already connected"))); return VFW_E_ALREADY_CONNECTED; } /* See if the filter is active */ if (!IsStopped() && !m_bCanReconnectWhenActive) { return VFW_E_NOT_STOPPED; } // Find a mutually agreeable media type - // Pass in the template media type. If this is partially specified, // each of the enumerated media types will need to be checked against // it. If it is non-null and fully specified, we will just try to connect // with this. const CMediaType * ptype = (CMediaType*)pmt; HRESULT hr = AgreeMediaType(pReceivePin, ptype); if (FAILED(hr)) { DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("Failed to agree type"))); // Since the procedure is already returning an error code, there // is nothing else this function can do to report the error. EXECUTE_ASSERT( SUCCEEDED( BreakConnect() ) ); return hr; } DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("Connection succeeded"))); return NOERROR; }
BOOL CMpcAudioRenderer::ScheduleSample(IMediaSample *pMediaSample) { REFERENCE_TIME StartSample; REFERENCE_TIME EndSample; // Is someone pulling our leg if (pMediaSample == NULL) { return FALSE; } // Get the next sample due up for rendering. If there aren't any ready // then GetNextSampleTimes returns an error. If there is one to be done // then it succeeds and yields the sample times. If it is due now then // it returns S_OK other if it's to be done when due it returns S_FALSE HRESULT hr = GetSampleTimes(pMediaSample, &StartSample, &EndSample); if (FAILED(hr)) { return FALSE; } // If we don't have a reference clock then we cannot set up the advise // time so we simply set the event indicating an image to render. This // will cause us to run flat out without any timing or synchronisation if (hr == S_OK) { EXECUTE_ASSERT(SetEvent((HANDLE) m_RenderEvent)); return TRUE; } if (m_dRate <= 1.1) { ASSERT(m_dwAdvise == 0); ASSERT(m_pClock); WaitForSingleObject((HANDLE)m_RenderEvent,0); hr = m_pClock->AdviseTime( (REFERENCE_TIME) m_tStart, StartSample, (HEVENT)(HANDLE) m_RenderEvent, &m_dwAdvise); if (SUCCEEDED(hr)) { return TRUE; } } else { hr = DoRenderSample (pMediaSample); } // We could not schedule the next sample for rendering despite the fact // we have a valid sample here. This is a fair indication that either // the system clock is wrong or the time stamp for the sample is duff ASSERT(m_dwAdvise == 0); return FALSE; }
Definition* Definition::SetChildAsValue(CStringW path, status_t s, CStringW v, CStringW u) { Definition* pDef = this; Split split('.', path); for(size_t i = 0, j = split - 1; i <= j; i++) { CStringW type = split[i]; if(pDef->m_nodes.IsEmpty() || !dynamic_cast<Reference*>(pDef->m_nodes.GetTail())) { EXECUTE_ASSERT(m_pnf->CreateRef(pDef) != NULL); } if(Reference* pRef = dynamic_cast<Reference*>(pDef->m_nodes.GetTail())) { pDef = NULL; POSITION pos = pRef->m_nodes.GetTailPosition(); while(pos) { Definition* pChildDef = dynamic_cast<Definition*>(pRef->m_nodes.GetPrev(pos)); if(pChildDef->IsType(type)) { if(pChildDef->IsNameUnknown()) pDef = pChildDef; break; } } if(!pDef) { pDef = m_pnf->CreateDef(pRef, type); } if(i == j) { pDef->SetAsValue(s, v, u); return pDef; } } } return NULL; }
REFERENCE_TIME CAMSchedule::Advise( const REFERENCE_TIME & rtTime ) { REFERENCE_TIME rtNextTime; CAdvisePacket * pAdvise; DbgLog((LOG_TIMING, 2, TEXT("CAMSchedule::Advise( %lu ms )"), ULONG(rtTime / (UNITS / MILLISECONDS)))); CAutoLock lck(&m_Serialize); #ifdef DEBUG if (DbgCheckModuleLevel(LOG_TIMING, 4)) DumpLinkedList(); #endif // Note - DON'T cache the difference, it might overflow while ( rtTime >= (rtNextTime = (pAdvise=head.m_next)->m_rtEventTime) && !pAdvise->IsZ() ) { ASSERT(pAdvise->m_dwAdviseCookie); // If this is zero, its the head or the tail!! ASSERT(pAdvise->m_hNotify != INVALID_HANDLE_VALUE); if (pAdvise->m_bPeriodic == TRUE) { ReleaseSemaphore(pAdvise->m_hNotify,1,NULL); pAdvise->m_rtEventTime += pAdvise->m_rtPeriod; ShuntHead(); } else { ASSERT( pAdvise->m_bPeriodic == FALSE ); EXECUTE_ASSERT(SetEvent(pAdvise->m_hNotify)); --m_dwAdviseCount; Delete( head.RemoveNext() ); } } DbgLog((LOG_TIMING, 3, TEXT("CAMSchedule::Advise() Next time stamp: %lu ms, for advise %lu."), DWORD(rtNextTime / (UNITS / MILLISECONDS)), pAdvise->m_dwAdviseCookie )); return rtNextTime; }
// // Select an input // HRESULT CCrossbar::SetInputIndex ( LONG Index) { HRESULT hr = E_FAIL; if (!m_RoutingList) return E_POINTER; CRouting *pCurrent = m_RoutingList->GetHead(); int j; if (Index >= m_RoutingList->GetCount()) return hr; POSITION pos = m_RoutingList->GetHeadPosition(); for (j = 0; j <= Index; j++) { pCurrent = m_RoutingList->GetNext(pos); } ASSERT (pCurrent != NULL); int Depth= pCurrent->Depth + 1; for (j = 0; j < Depth; j++) { hr = pCurrent->pXbar->Route (pCurrent->VideoOutputIndex, pCurrent->VideoInputIndex); ASSERT (S_OK == hr); if ((pCurrent->AudioOutputIndex != -1) && (pCurrent->AudioInputIndex != -1)) { EXECUTE_ASSERT (S_OK == pCurrent->pXbar->Route (pCurrent->AudioOutputIndex, pCurrent->AudioInputIndex)); } DbgLog((LOG_TRACE,3,TEXT("CCrossbar::Routing, VideoOutIndex=%d VideoInIndex=%d"), pCurrent->VideoOutputIndex, pCurrent->VideoInputIndex)); pCurrent++; } m_CurrentRoutingIndex = Index; return hr; }
HRESULT CSynthStream::BreakConnect(void) { // This lock must be held because this function uses // m_hPCMToMSADPCMConversionStream and m_dwTempPCMBufferSize. CAutoLock lShared(&m_cSharedState); HRESULT hr = CDynamicSourceStream::BreakConnect(); if(FAILED(hr)) { return hr; } if(NULL != m_hPCMToMSADPCMConversionStream) { // acmStreamClose() should never fail because m_hPCMToMSADPCMConversionStream // holds a valid ACM stream handle and all operations using the handle are // synchronous. EXECUTE_ASSERT(0 == acmStreamClose(m_hPCMToMSADPCMConversionStream, 0)); m_hPCMToMSADPCMConversionStream = NULL; m_dwTempPCMBufferSize = 0; } return S_OK; }
HRESULT CWavDestFilter::Transform(IMediaSample* pIn, IMediaSample* pOut) { REFERENCE_TIME rtStart, rtEnd; HRESULT hr = Copy(pIn, pOut); if (FAILED(hr)) { return hr; } // Prepare it for writing LONG lActual = pOut->GetActualDataLength(); if (m_cbWavData + m_cbHeader + lActual < m_cbWavData + m_cbHeader) { // overflow return E_FAIL; } rtStart = m_cbWavData + m_cbHeader; rtEnd = rtStart + lActual; m_cbWavData += lActual; EXECUTE_ASSERT(pOut->SetTime(&rtStart, &rtEnd) == S_OK); return S_OK; }
CAMEvent::~CAMEvent() { if (m_hEvent) { EXECUTE_ASSERT(CloseHandle(m_hEvent)); } }
enum CBaseStreamControl::StreamControlState CBaseStreamControl::CheckStreamState( IMediaSample * pSample ) { REFERENCE_TIME rtBufferStart, rtBufferStop; const BOOL bNoBufferTimes = pSample == NULL || FAILED(pSample->GetTime(&rtBufferStart, &rtBufferStop)); StreamControlState state; LONG lWait; do { // something has to break out of the blocking if (m_bIsFlushing || m_FilterState == State_Stopped) return STREAM_DISCARDING; if (bNoBufferTimes) { // Can't do anything until we get a time stamp state = m_StreamState; break; } else { state = CheckSampleTimes( &rtBufferStart, &rtBufferStop ); if (state == STREAM_FLOWING) break; // we aren't supposed to send this, but we've been // told to send one more than we were supposed to // (and the stop isn't still pending and we're streaming) if (m_bStopSendExtra && !m_bStopExtraSent && m_tStopTime == MAX_TIME && m_FilterState != State_Stopped) { m_bStopExtraSent = TRUE; DbgLog((LOG_TRACE,2,TEXT("%d sending an EXTRA frame"), m_dwStopCookie)); state = STREAM_FLOWING; break; } } // We're in discarding mode // If we've no clock, discard as fast as we can if (!m_pRefClock) { break; // If we're paused, we can't discard in a timely manner because // there's no such thing as stream times. We must block until // we run or stop, or we'll end up throwing the whole stream away // as quickly as possible } else if (m_FilterState == State_Paused) { lWait = INFINITE; } else { // wait until it's time for the sample until we say "discard" // ("discard in a timely fashion") REFERENCE_TIME rtNow; EXECUTE_ASSERT(SUCCEEDED(m_pRefClock->GetTime(&rtNow))); rtNow -= m_tRunStart; // Into relative ref-time lWait = LONG((rtBufferStart - rtNow)/10000); // 100ns -> ms if (lWait < 10) break; // Not worth waiting - discard early } } while(WaitForSingleObject(GetStreamEventHandle(), lWait) != WAIT_TIMEOUT); return state; }
HRESULT CSynthStream::CompleteConnect(IPin *pReceivePin) { // This lock must be held because this function uses // m_hPCMToMSADPCMConversionStream, m_fFirstSampleDelivered // and m_llSampleMediaTimeStart. CAutoLock lShared(&m_cSharedState); HRESULT hr; WAVEFORMATEX *pwfexCurrent = (WAVEFORMATEX*)m_mt.Format(); if(WAVE_FORMAT_PCM == pwfexCurrent->wFormatTag) { hr = m_Synth->AllocWaveCache(*pwfexCurrent); if(FAILED(hr)) { return hr; } } else if(WAVE_FORMAT_ADPCM == pwfexCurrent->wFormatTag) { WAVEFORMATEX wfexSourceFormat; DerivePCMFormatFromADPCMFormatStructure(*pwfexCurrent, &wfexSourceFormat); hr = m_Synth->AllocWaveCache(wfexSourceFormat); if(FAILED(hr)) { return hr; } MMRESULT mmr = acmStreamOpen(&m_hPCMToMSADPCMConversionStream, NULL, &wfexSourceFormat, pwfexCurrent, NULL, 0, 0, ACM_STREAMOPENF_NONREALTIME); // acmStreamOpen() returns 0 if an no errors occur. if(mmr != 0) { return E_FAIL; } } else { ASSERT(NULL == m_hPCMToMSADPCMConversionStream); } hr = CDynamicSourceStream::CompleteConnect(pReceivePin); if(FAILED(hr)) { if(WAVE_FORMAT_ADPCM == pwfexCurrent->wFormatTag) { // acmStreamClose() should never fail because m_hPCMToMSADPCMConversionStream // holds a valid ACM stream handle and all operations using the handle are // synchronous. EXECUTE_ASSERT(0 == acmStreamClose(m_hPCMToMSADPCMConversionStream, 0)); m_hPCMToMSADPCMConversionStream = NULL; } return hr; } m_fFirstSampleDelivered = FALSE; m_llSampleMediaTimeStart = 0; return S_OK; }
// // InitWindowRegion // // We display the video in a window that has a region selected into it that // matches the word we are passed in. By doing this we let Windows manage // all the clipping and mouse technology. The trick is in creating a region // that matches the word, which is done by using paths. We create a path for // a temporary HDC, draw the word and then end the path. After that, we can then // ask Windows for a region that describes that path. That gives us a region // for the outside of the word, so we bitwise "not" it to get the word region. // HRESULT CVideoText::InitWindowRegion(TCHAR *pStringName) { ASSERT(pStringName); OSVERSIONINFO VersionInfo; VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); EXECUTE_ASSERT(GetVersionEx(&VersionInfo)); // Set a window region according to the OS capabilities if ((VersionInfo.dwPlatformId & VER_PLATFORM_WIN32_NT) == 0) { m_Size.cx = 320; m_Size.cy = 240; return NOERROR; } // Get the text extents the word passed in will require based on the // font and bitmap selected in the current device context. For it to // be displayed in a different font it must be selected into the HDC HDC hdc = CreateCompatibleDC(m_hdc); HFONT hFont = CreateVideoFont(); SelectObject(hdc,hFont); GetTextExtentPoint32((HDC) hdc, // The output device context pStringName, // The string we'll be using lstrlen(pStringName), // Number of characters in it (LPSIZE) &m_Size); // Filled in with the extents // Create a bitmap that matches the current format HBITMAP hMaskBitmap = CreateCompatibleBitmap(hdc,m_Size.cx,m_Size.cy); if (hMaskBitmap == NULL) { ASSERT(hMaskBitmap); return E_UNEXPECTED; } // Select the monochrome bitmap into the device context HBITMAP hBitmap = (HBITMAP) SelectObject(hdc,hMaskBitmap); EXECUTE_ASSERT(BeginPath(hdc)); // Draw the string into the monochrome bitmap ExtTextOut((HDC) hdc, // Target device context (int) 0, // x coordinate reference (int) 0, // Likewise y coordinate (DWORD) 0, // No special flags to set NULL, // No clipping rectangle pStringName, // Pointer to text words lstrlen(pStringName), // Number of characters NULL); // Intercharacter spacing EXECUTE_ASSERT(EndPath(hdc)); HRGN hOutside = PathToRegion(hdc); HRGN hFullWindow = CreateRectRgn(0,0,m_Size.cx,m_Size.cy); HRGN hWordRegion = CreateRectRgn(0,0,1,1); CombineRgn(hWordRegion,hFullWindow,hOutside,RGN_DIFF); SetWindowRgn(m_hwnd,hWordRegion,TRUE); // Clear up the regions we created DeleteObject(hWordRegion); DeleteObject(hOutside); DeleteObject(hFullWindow); // Delete the HDC and text bitmap SelectObject(hdc,hBitmap); HFONT hDefault = (HFONT) GetStockObject(SYSTEM_FONT); SelectObject(hdc,hDefault); DeleteObject(hFont); DeleteObject(hMaskBitmap); DeleteDC(hdc); return NOERROR; } // InitWindowRegion
HRESULT CStreamSwitcherInputPin::InitializeOutputSample(IMediaSample* pInSample, IMediaSample** ppOutSample) { if (!pInSample || !ppOutSample) { return E_POINTER; } CStreamSwitcherOutputPin* pOut = (static_cast<CStreamSwitcherFilter*>(m_pFilter))->GetOutputPin(); ASSERT(pOut->GetConnected()); CComPtr<IMediaSample> pOutSample; DWORD dwFlags = m_bSampleSkipped ? AM_GBF_PREVFRAMESKIPPED : 0; if (!(m_SampleProps.dwSampleFlags & AM_SAMPLE_SPLICEPOINT)) { dwFlags |= AM_GBF_NOTASYNCPOINT; } HRESULT hr = pOut->GetDeliveryBuffer(&pOutSample , m_SampleProps.dwSampleFlags & AM_SAMPLE_TIMEVALID ? &m_SampleProps.tStart : nullptr , m_SampleProps.dwSampleFlags & AM_SAMPLE_STOPVALID ? &m_SampleProps.tStop : nullptr , dwFlags); if (FAILED(hr)) { return hr; } if (!pOutSample) { return E_FAIL; } if (CComQIPtr<IMediaSample2> pOutSample2 = pOutSample) { AM_SAMPLE2_PROPERTIES OutProps; EXECUTE_ASSERT(SUCCEEDED(pOutSample2->GetProperties(FIELD_OFFSET(AM_SAMPLE2_PROPERTIES, tStart), (PBYTE)&OutProps))); OutProps.dwTypeSpecificFlags = m_SampleProps.dwTypeSpecificFlags; OutProps.dwSampleFlags = (OutProps.dwSampleFlags & AM_SAMPLE_TYPECHANGED) | (m_SampleProps.dwSampleFlags & ~AM_SAMPLE_TYPECHANGED); OutProps.tStart = m_SampleProps.tStart; OutProps.tStop = m_SampleProps.tStop; OutProps.cbData = FIELD_OFFSET(AM_SAMPLE2_PROPERTIES, dwStreamId); hr = pOutSample2->SetProperties(FIELD_OFFSET(AM_SAMPLE2_PROPERTIES, dwStreamId), (PBYTE)&OutProps); if (m_SampleProps.dwSampleFlags & AM_SAMPLE_DATADISCONTINUITY) { m_bSampleSkipped = FALSE; } } else { if (m_SampleProps.dwSampleFlags & AM_SAMPLE_TIMEVALID) { pOutSample->SetTime(&m_SampleProps.tStart, &m_SampleProps.tStop); } if (m_SampleProps.dwSampleFlags & AM_SAMPLE_SPLICEPOINT) { pOutSample->SetSyncPoint(TRUE); } if (m_SampleProps.dwSampleFlags & AM_SAMPLE_DATADISCONTINUITY) { pOutSample->SetDiscontinuity(TRUE); m_bSampleSkipped = FALSE; } LONGLONG MediaStart, MediaEnd; if (pInSample->GetMediaTime(&MediaStart, &MediaEnd) == NOERROR) { pOutSample->SetMediaTime(&MediaStart, &MediaEnd); } } *ppOutSample = pOutSample.Detach(); return S_OK; }
// // OnReceiveMessage // // This is the derived class window message handler methods // LRESULT CVideoText::OnReceiveMessage(HWND hwnd, // Window handle UINT uMsg, // Message ID WPARAM wParam, // First parameter LPARAM lParam) // Other parameter { IBaseFilter *pFilter = NULL; RECT ClientRect; // Blank out the window background if (uMsg == WM_ERASEBKGND) { EXECUTE_ASSERT(GetClientRect(m_hwnd,&ClientRect)); HBRUSH hBrush = CreateSolidBrush(RGB(0,0,0)); EXECUTE_ASSERT(FillRect(m_hdc,&ClientRect,hBrush)); EXECUTE_ASSERT(DeleteObject(hBrush)); return (LRESULT) 0; } // Handle WM_CLOSE by aborting the playback if (uMsg == WM_CLOSE) { m_pRenderer->NotifyEvent(EC_USERABORT,0,0); DoShowWindow(SW_HIDE); return CBaseWindow::OnClose(); } // We pass on WM_ACTIVATEAPP messages to the filtergraph so that the // IVideoWindow plug in distributor can switch us out of fullscreen // mode where appropriate. These messages may also be used by the // resource manager to keep track of which renderer has the focus if (uMsg == WM_ACTIVATEAPP) { NOTE1("Notification of EC_ACTIVATE (%d)",(BOOL) wParam); m_pRenderer->QueryInterface(IID_IBaseFilter,(void **) &pFilter); if (pFilter) { m_pRenderer->NotifyEvent(EC_ACTIVATE, wParam, (LPARAM) pFilter); pFilter->Release(); } return (LRESULT) 0; } // Treat clicks on text as requests to move window if (uMsg == WM_NCHITTEST) { LRESULT Result = DefWindowProc(hwnd,uMsg,wParam,lParam); if (Result == HTCLIENT) Result = HTCAPTION; return Result; } // The base class that implements IVideoWindow looks after a flag // that says whether or not the cursor should be hidden. If so we // hide the cursor and return (LRESULT) 1. Otherwise we pass to // the DefWindowProc to show the cursor as normal. This is used // when our window is made fullscreen to imitate the Modex filter if (uMsg == WM_SETCURSOR) { if (IsCursorHidden() == TRUE) { SetCursor(NULL); return (LRESULT) 1; } } // When we detect a display change we send an EC_DISPLAY_CHANGED // message along with our input pin. The filtergraph will stop // everyone and reconnect our input pin. When being reconnected // we can then accept the media type that matches the new display // mode since we may no longer be able to draw the current format if (uMsg == WM_DISPLAYCHANGE) { m_pRenderer->m_Display.RefreshDisplayType(NULL); m_pRenderer->OnDisplayChange(); NOTE("Sent EC_DISPLAY_CHANGED event"); return (LRESULT) 0; } return CBaseWindow::OnReceiveMessage(hwnd,uMsg,wParam,lParam); } // OnReceiveMessage
// Set up our output sample HRESULT CTransformFilter::InitializeOutputSample(IMediaSample *pSample, IMediaSample **ppOutSample) { IMediaSample *pOutSample; // default - times are the same AM_SAMPLE2_PROPERTIES * const pProps = m_pInput->SampleProps(); DWORD dwFlags = m_bSampleSkipped ? AM_GBF_PREVFRAMESKIPPED : 0; // This will prevent the image renderer from switching us to DirectDraw // when we can't do it without skipping frames because we're not on a // keyframe. If it really has to switch us, it still will, but then we // will have to wait for the next keyframe if(!(pProps->dwSampleFlags & AM_SAMPLE_SPLICEPOINT)) { dwFlags |= AM_GBF_NOTASYNCPOINT; } ASSERT(m_pOutput->m_pAllocator != NULL); HRESULT hr = m_pOutput->m_pAllocator->GetBuffer(&pOutSample , pProps->dwSampleFlags & AM_SAMPLE_TIMEVALID ? &pProps->tStart : NULL , pProps->dwSampleFlags & AM_SAMPLE_STOPVALID ? &pProps->tStop : NULL , dwFlags); *ppOutSample = pOutSample; if(FAILED(hr)) { return hr; } ASSERT(pOutSample); IMediaSample2 *pOutSample2; if(SUCCEEDED(pOutSample->QueryInterface(IID_IMediaSample2, (void **)&pOutSample2))) { /* Modify it */ AM_SAMPLE2_PROPERTIES OutProps; EXECUTE_ASSERT(SUCCEEDED(pOutSample2->GetProperties(FIELD_OFFSET(AM_SAMPLE2_PROPERTIES, tStart), (PBYTE)&OutProps))); OutProps.dwTypeSpecificFlags = pProps->dwTypeSpecificFlags; OutProps.dwSampleFlags = (OutProps.dwSampleFlags & AM_SAMPLE_TYPECHANGED) | (pProps->dwSampleFlags & ~AM_SAMPLE_TYPECHANGED); OutProps.tStart = pProps->tStart; OutProps.tStop = pProps->tStop; OutProps.cbData = FIELD_OFFSET(AM_SAMPLE2_PROPERTIES, dwStreamId); hr = pOutSample2->SetProperties(FIELD_OFFSET(AM_SAMPLE2_PROPERTIES, dwStreamId), (PBYTE)&OutProps); if(pProps->dwSampleFlags & AM_SAMPLE_DATADISCONTINUITY) { m_bSampleSkipped = FALSE; } pOutSample2->Release(); } else { if(pProps->dwSampleFlags & AM_SAMPLE_TIMEVALID) { pOutSample->SetTime(&pProps->tStart, &pProps->tStop); } if(pProps->dwSampleFlags & AM_SAMPLE_SPLICEPOINT) { pOutSample->SetSyncPoint(TRUE); } if(pProps->dwSampleFlags & AM_SAMPLE_DATADISCONTINUITY) { pOutSample->SetDiscontinuity(TRUE); m_bSampleSkipped = FALSE; } // Copy the media times LONGLONG MediaStart, MediaEnd; if(pSample->GetMediaTime(&MediaStart,&MediaEnd) == NOERROR) { pOutSample->SetMediaTime(&MediaStart,&MediaEnd); } } return S_OK; }
HRESULT CDSMSplitterFilter::CreateOutputs(IAsyncReader* pAsyncReader) { CheckPointer(pAsyncReader, E_POINTER); HRESULT hr = E_FAIL; m_pFile.Free(); m_pFile.Attach(DEBUG_NEW CDSMSplitterFile(pAsyncReader, hr, *this, *this)); if (!m_pFile) { return E_OUTOFMEMORY; } if (FAILED(hr)) { m_pFile.Free(); return hr; } m_rtNewStart = m_rtCurrent = 0; m_rtNewStop = m_rtStop = m_rtDuration = m_pFile->m_rtDuration; CAtlArray<BYTE> ids; POSITION pos = m_pFile->m_mts.GetStartPosition(); while (pos) { BYTE id; CMediaType mt; m_pFile->m_mts.GetNextAssoc(pos, id, mt); ids.Add(id); } qsort(ids.GetData(), ids.GetCount(), sizeof(BYTE), compare_id); for (size_t i = 0; i < ids.GetCount(); i++) { BYTE id = ids[i]; CMediaType& mt = m_pFile->m_mts[id]; CStringW name, lang; name.Format(L"Output %02u", id); CAtlArray<CMediaType> mts; mts.Add(mt); CAutoPtr<CBaseSplitterOutputPin> pPinOut(DEBUG_NEW CBaseSplitterOutputPin(mts, name, this, this, &hr)); name.Empty(); pos = m_pFile->m_sim[id].GetStartPosition(); while (pos) { CStringA key; CStringW value; m_pFile->m_sim[id].GetNextAssoc(pos, key, value); pPinOut->SetProperty(CStringW(key), value); if (key == "NAME") { name = value; } if (key == "LANG") { lang = ISOLang::ISO6392ToLanguage(CStringA(value)); if (lang.IsEmpty()) { lang = value; } } } if (!name.IsEmpty() || !lang.IsEmpty()) { if (!name.IsEmpty()) { if (!lang.IsEmpty()) { name += L" (" + lang + L")"; } } else if (!lang.IsEmpty()) { name = lang; } pPinOut->SetName(name); } EXECUTE_ASSERT(SUCCEEDED(AddOutputPin(id, pPinOut))); } pos = m_pFile->m_fim.GetStartPosition(); while (pos) { CStringA key; CStringW value; m_pFile->m_fim.GetNextAssoc(pos, key, value); SetProperty(CStringW(key), value); } for (size_t i = 0; i < m_resources.GetCount(); i++) { const CDSMResource& r = m_resources[i]; if (r.mime == L"application/x-truetype-font" || r.mime == L"application/x-font-ttf" || r.mime == L"application/vnd.ms-opentype") { //m_fontinst.InstallFont(r.data); m_fontinst.InstallFontMemory(r.data.GetData(), (UINT)r.data.GetCount()); } } return !m_pOutputs.IsEmpty() ? S_OK : E_FAIL; }