📄 chxphook.cpp
字号:
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 + -