📄 chxphook.cpp
字号:
BOOL bRecordable = FALSE; CHXHeader* pHeader = NULL; CHXBuffer* pPropValueSource = NULL; CHXBuffer* pPropValueTarget = NULL; IHXStream* pStream = NULL; // retrieve the stream info pSource->GetStream(j, (IUnknown*&)pStream); pHeader = (CHXHeader*)pStream->GetHeader(); // make a copy of this stream header // XXX HP: this could be wrapped up into one method in CHXHeader pStreamHeader = new CHXHeader(); pStreamHeader->AddRef(); // copy all the ULONG32 attributes if (HXR_OK == pHeader->GetFirstPropertyULONG32(pszPropName, ulPropValue)) { pStreamHeader->SetPropertyULONG32(pszPropName, ulPropValue); while (HXR_OK == pHeader->GetNextPropertyULONG32(pszPropName, ulPropValue)) { pStreamHeader->SetPropertyULONG32(pszPropName, ulPropValue); } } // copy all the buffer attributes if (HXR_OK == pHeader->GetFirstPropertyBuffer(pszPropName, (IHXBuffer*&)pPropValueSource)) { pPropValueTarget = new CHXBuffer(); pPropValueTarget->AddRef(); pPropValueTarget->Set(pPropValueSource->GetBuffer(), pPropValueSource->GetSize()); pStreamHeader->SetPropertyBuffer(pszPropName, pPropValueTarget); HX_RELEASE(pPropValueTarget); HX_RELEASE(pPropValueSource); while (HXR_OK == pHeader->GetNextPropertyBuffer(pszPropName, (IHXBuffer*&)pPropValueSource)) { pPropValueTarget = new CHXBuffer(); pPropValueTarget->AddRef(); pPropValueTarget->Set(pPropValueSource->GetBuffer(), pPropValueSource->GetSize()); pStreamHeader->SetPropertyBuffer(pszPropName, pPropValueTarget); HX_RELEASE(pPropValueTarget); HX_RELEASE(pPropValueSource); } } // copy all the CString attributes if (HXR_OK == pHeader->GetFirstPropertyCString(pszPropName, (IHXBuffer*&)pPropValueSource)) { pPropValueTarget = new CHXBuffer(); pPropValueTarget->AddRef(); pPropValueTarget->Set(pPropValueSource->GetBuffer(), pPropValueSource->GetSize()); pStreamHeader->SetPropertyCString(pszPropName, pPropValueTarget); HX_RELEASE(pPropValueTarget); HX_RELEASE(pPropValueSource); while (HXR_OK == pHeader->GetNextPropertyCString(pszPropName, (IHXBuffer*&)pPropValueSource)) { pPropValueTarget = new CHXBuffer(); pPropValueTarget->AddRef(); pPropValueTarget->Set(pPropValueSource->GetBuffer(), pPropValueSource->GetSize()); pStreamHeader->SetPropertyCString(pszPropName, pPropValueTarget); HX_RELEASE(pPropValueTarget); HX_RELEASE(pPropValueSource); } } HX_RELEASE(pHeader); // modify some values pStreamHeader->SetPropertyULONG32("StreamNumber", ulStreamIndex); // the stream is recordable as long as there is one renderer supports // IHXPacketHookHelper. Multiple renderers can serve the packets with // the same stream number on it, One solution for this is to choose the // first renderer which supports IHXPacketHookHelper as the only source ulRenderers = pStream->GetRendererCount(); for (k = 0; k < ulRenderers; k++) { IUnknown* pUnknown = NULL; IHXPacketHookHelper* pPacketHookHelper = NULL; pStream->GetRenderer(k, pUnknown); if (HXR_OK == pUnknown->QueryInterface(IID_IHXPacketHookHelper, (void**)&pPacketHookHelper)) { bRecordable = TRUE; pPacketHookHelper->StartHook(ulStreamIndex, 0, new PacketHookHelperResponse(this, ulStreamIndex)); } HX_RELEASE(pPacketHookHelper); HX_RELEASE(pUnknown); } if (bRecordable) { m_ulRecordableStreams++; } pStreamHeader->SetPropertyULONG32("Recordable", (ULONG32)bRecordable); /* * It's possible that StartHook will cause the m_pPacketHook to * be released */ if (!m_pPacketHook) { hr = HXR_UNEXPECTED; goto cleanup; } // send stream header to its top level client hr = m_pPacketHook->OnStreamHeader(pStreamHeader); if (hr != HXR_OK) { HX_RELEASE(m_pPacketHook); goto cleanup; } ulStreamIndex++; HX_RELEASE(pStreamHeader); HX_RELEASE(pStream); } HX_RELEASE(pSource); HX_RELEASE(pUnknown); } cleanup: HX_RELEASE(pTitle); HX_RELEASE(pAuthor); HX_RELEASE(pCopyright); HX_RELEASE(pFileHeader); return hr;} /************************************************************************ * Method: * IHXPacketHookManager::StopHook * Purpose: * called by the top level client to stop recording */STDMETHODIMP PacketHookManager::StopHook (){ HX_RESULT hr = HXR_OK; UINT16 i = 0; UINT16 j = 0; UINT16 k = 0; UINT16 ulSources = 0; UINT16 ulStreams = 0; IUnknown* pUnknown = NULL; IHXStreamSource* pSource = NULL; IHXInfoLogger* pInfoLogger = NULL; if (!m_pPlayer || !m_pPacketHook) { hr = HXR_FAILED; goto cleanup; } // prepare the stream headers ulSources = m_pPlayer->GetSourceCount(); for (i = 0; i < ulSources; i++) { if (m_pPlayer->GetSource(i, pUnknown) != HXR_OK) continue; if (HXR_OK != pUnknown->QueryInterface(IID_IHXStreamSource, (void**)&pSource)) { break; } if (HXR_OK == pUnknown->QueryInterface(IID_IHXInfoLogger, (void**)&pInfoLogger)) { pInfoLogger->LogInformation("RECEND", NULL); } HX_RELEASE(pInfoLogger); ulStreams = pSource->GetStreamCount(); for (j = 0; j < ulStreams; j++) { UINT16 ulRenderers = 0; IHXStream* pStream = NULL; // retrieve the stream info pSource->GetStream(j, (IUnknown*&)pStream); ulRenderers = pStream->GetRendererCount(); for (k = 0; k < ulRenderers; k++) { IHXRenderer* pRenderer = NULL; IHXPacketHookHelper* pPacketHookHelper = NULL; IHXPacketHookSink* pSink = NULL; pStream->GetRenderer(k, (IUnknown*&)pRenderer); if (HXR_OK == pRenderer->QueryInterface(IID_IHXPacketHookSink, (void**)&pSink)) { pSink->StopSink(); HX_RELEASE(pSink); } if (HXR_OK == pRenderer->QueryInterface(IID_IHXPacketHookHelper, (void**)&pPacketHookHelper)) { pPacketHookHelper->StopHook(); } HX_RELEASE(pSink); HX_RELEASE(pPacketHookHelper); HX_RELEASE(pRenderer); } HX_RELEASE(pStream); } HX_RELEASE(pSource); HX_RELEASE(pUnknown); }cleanup: return hr;}STDMETHODIMP PacketHookManager::OnPacket (IHXPacket* pPacket){ HX_RESULT hr = HXR_OK; if (!m_pPacketHook) { hr = HXR_FAILED; goto cleanup; } // pass packet back to the top-level client hr = m_pPacketHook->OnPacket(pPacket); if (hr != HXR_OK) { HX_RELEASE(m_pPacketHook); }cleanup: return hr;}STDMETHODIMP PacketHookManager::OnEndOfPackets (ULONG32 ulStreamID){ HX_RESULT hr = HXR_OK; if (!m_pPacketHook) { hr = HXR_FAILED; goto cleanup; } // this is the last stream if (!--m_ulRecordableStreams) { m_pPacketHook->OnEnd(); HX_RELEASE(m_pPacketHook); }cleanup: return hr;}PacketHookHelperResponse::PacketHookHelperResponse(PacketHookManager* pPacketHookManager, ULONG32 ulStreamID) : m_lRefCount (0) , m_pPacketHookManager (NULL) , m_ulStreamID (0){ m_pPacketHookManager = pPacketHookManager; m_pPacketHookManager->AddRef(); m_ulStreamID = ulStreamID;}PacketHookHelperResponse::~PacketHookHelperResponse(){ HX_RELEASE(m_pPacketHookManager);}/////////////////////////////////////////////////////////////////////////// Method:// IUnknown::QueryInterface// Purpose:// Implement this to export the interfaces supported by your // object.//STDMETHODIMP PacketHookHelperResponse::QueryInterface(REFIID riid, void** ppvObj){ QInterfaceList qiList[] = { { GET_IIDHANDLE(IID_IHXPacketHookHelperResponse), (IHXPacketHookHelperResponse*)this }, { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXPacketHookHelperResponse*)this }, }; return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);}/////////////////////////////////////////////////////////////////////////// Method:// IUnknown::AddRef// Purpose:// Everyone usually implements this the same... feel free to use// this implementation.//STDMETHODIMP_(ULONG32) PacketHookHelperResponse::AddRef(){ return InterlockedIncrement(&m_lRefCount);}/////////////////////////////////////////////////////////////////////////// Method:// IUnknown::Release// Purpose:// Everyone usually implements this the same... feel free to use// this implementation.//STDMETHODIMP_(ULONG32) PacketHookHelperResponse::Release(){ if (InterlockedDecrement(&m_lRefCount) > 0) { return m_lRefCount; } delete this; return 0;}/* * IHXPacketHookHelperResponse methods *//************************************************************************ * Method: * IHXPacketHookHelperResponse::OnPacket * Purpose: * called by the renderer to pass the packet for recording */STDMETHODIMP PacketHookHelperResponse::OnPacket (IHXPacket* pPacket){ HX_RESULT hr = HXR_OK; if (!m_pPacketHookManager) { hr = HXR_FAILED; goto cleanup; } // pass packet back to the top-level client hr = m_pPacketHookManager->OnPacket(pPacket); if (hr != HXR_OK) { HX_RELEASE(m_pPacketHookManager); }cleanup: return hr;}/************************************************************************ * Method: * IHXPacketHookManager::OnEndOfPackets * Purpose: * called by the renderer to notify the end of this stream */STDMETHODIMP PacketHookHelperResponse::OnEndOfPackets (){ HX_RESULT hr = HXR_OK; if (!m_pPacketHookManager) { hr = HXR_FAILED; goto cleanup; } m_pPacketHookManager->OnEndOfPackets(m_ulStreamID);cleanup: return hr;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -