/************************************************************************ * 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; }
/************************************************************************ * Method: * IHXPacketHookManager::InitHook * Purpose: * called by the top level client to pass the IHXPacketHook object */ STDMETHODIMP PacketHookManager::InitHook (IHXPacketHook* pPacketHook) { HX_RESULT hr = HXR_OK; if (!m_pPlayer || !pPacketHook) { return HXR_FAILED; } m_pPacketHook = pPacketHook; m_pPacketHook->AddRef(); HXBOOL bRecordAllowed = FALSE; UINT16 ulSources = 0; UINT16 ulStreams = 0; IUnknown* pUnknown = NULL; IHXStreamSource* pSource = NULL; IHXPrivateStreamSource *pPrivateSource = NULL; // for IsSaveAllowed, take this out; XXXCP // caculate the total number of streams + TAC info. if (!(ulSources = m_pPlayer->GetSourceCount())) { return HXR_FAILED; } for (UINT16 i = 0; i < ulSources; i++) { if (m_pPlayer->GetSource(i, pUnknown) != HXR_OK) { continue; } HXBOOL bIsSaveAllowed = FALSE; if (pUnknown->QueryInterface(IID_IHXPrivateStreamSource, (void**)&pPrivateSource) == HXR_OK) { bIsSaveAllowed = pPrivateSource->IsSaveAllowed(); HX_RELEASE(pPrivateSource); if (!bIsSaveAllowed) { HX_RELEASE(pUnknown); continue; } } if(bIsSaveAllowed) bRecordAllowed = TRUE; hr = pUnknown->QueryInterface(IID_IHXStreamSource, (void**)&pSource); HX_RELEASE(pUnknown); if (hr != HXR_OK) { break; } ulStreams = pSource->GetStreamCount(); for (UINT16 j = 0; j < ulStreams; j++) { IHXStream* pStream = NULL; pSource->GetStream(j, (IUnknown*&)pStream); UINT16 ulRenderers = pStream->GetRendererCount(); for (UINT16 k = 0; k < ulRenderers; k++) { IHXRenderer* pRenderer = NULL; IHXPacketHookSink* pSink = NULL; pStream->GetRenderer(k, (IUnknown*&)pRenderer); if (HXR_OK == pRenderer->QueryInterface(IID_IHXPacketHookSink, (void**)&pSink)) { pSink->StartSink(); HX_RELEASE(pSink); } HX_RELEASE(pRenderer); } HX_RELEASE(pStream); } HX_RELEASE(pSource); } if (!bRecordAllowed) { hr = HXR_NO_DATA; } return hr; }
/************************************************************************ * Method: * IHXPacketHookManager::StartHook * Purpose: * called by the top level client to start recording */ STDMETHODIMP PacketHookManager::StartHook () { HX_RESULT hr = HXR_OK; UINT16 i = 0; UINT16 j = 0; UINT16 k = 0; UINT16 ulSources = 0; UINT16 ulStreams = 0; UINT16 ulStreamIndex = 0; IHXBuffer* pTitle = NULL; IHXBuffer* pAuthor = NULL; IHXBuffer* pCopyright = NULL; IHXValues* pFileHeader = NULL; IHXValues* pStreamHeader = NULL; IUnknown* pUnknown = NULL; IHXPrivateStreamSource *pPrivateSource = NULL; // for IsSaveAllowed, take this out; XXXCP IHXStreamSource* pSource = NULL; IHXInfoLogger* pInfoLogger = NULL; // make sure everything has been initialized if (!m_pPlayer || !m_pPacketHook) { hr = HXR_FAILED; goto cleanup; } // caculate the total number of streams + TAC info. if (!(ulSources = m_pPlayer->GetSourceCount())) { hr = HXR_FAILED; goto cleanup; } m_ulTotalStreams = 0; for (i = 0; i < ulSources; i++) { if (HXR_OK != m_pPlayer->GetSource(i, pUnknown)) { continue; } if (HXR_OK != pUnknown->QueryInterface(IID_IHXStreamSource, (void**)&pSource)) { HX_RELEASE(pUnknown); continue; } if (HXR_OK == pUnknown->QueryInterface(IID_IHXPrivateStreamSource, (void**)&pPrivateSource)) { if (!(pPrivateSource->IsSaveAllowed())) { pPrivateSource->Release(); continue; } pPrivateSource->Release(); } m_ulTotalStreams += pSource->GetStreamCount(); HX_RELEASE(pSource); HX_RELEASE(pUnknown); } if (!m_ulTotalStreams) { hr = HXR_FAILED; goto cleanup; } // prepare the file header CreateBufferCCF(pTitle, m_pPlayer); CreateBufferCCF(pAuthor, m_pPlayer); CreateBufferCCF(pCopyright, m_pPlayer); // XXX HP: find better way to collect TAC info #define szTitle "title" #define szAuthor "author" #define szCopyright "copyright" pTitle->Set((const unsigned char*)szTitle, strlen(szTitle)+1); pAuthor->Set((const unsigned char*)szAuthor, strlen(szAuthor)+1); pCopyright->Set((const unsigned char*)szCopyright, strlen(szCopyright)+1); if (HXR_OK == CreateValuesCCF(pFileHeader, m_pPlayer)) { // set attributes(i.e. num. of streams + TAC) pFileHeader->SetPropertyBuffer("Title", pTitle); pFileHeader->SetPropertyBuffer("Author", pAuthor); pFileHeader->SetPropertyBuffer("Copyright", pCopyright); pFileHeader->SetPropertyULONG32("StreamCount", m_ulTotalStreams); } // signal the top level client of upcoming content m_pPacketHook->OnStart(); // send file header to its top level client hr = m_pPacketHook->OnFileHeader(pFileHeader); if (hr != HXR_OK) { HX_RELEASE(m_pPacketHook); goto cleanup; } // prepare the stream headers m_ulRecordableStreams = 0; ulStreamIndex = 0; for (i = 0; i < ulSources; i++) { if (HXR_OK != m_pPlayer->GetSource(i, pUnknown)) { HX_RELEASE(pUnknown); continue; } if (HXR_OK != pUnknown->QueryInterface(IID_IHXStreamSource, (void**)&pSource)) { HX_RELEASE(pSource); continue; } if (HXR_OK == pUnknown->QueryInterface(IID_IHXPrivateStreamSource, (void**)&pPrivateSource)) { if (!(pPrivateSource->IsSaveAllowed())) { pPrivateSource->Release(); continue; } pPrivateSource->Release(); } if (HXR_OK == pUnknown->QueryInterface(IID_IHXInfoLogger, (void**)&pInfoLogger)) { pInfoLogger->LogInformation("RECSTART", NULL); } HX_RELEASE(pInfoLogger); ulStreams = pSource->GetStreamCount(); for (j = 0; j < ulStreams; j++) { const char* pszPropName = NULL; UINT16 ulRenderers = 0; ULONG32 ulPropValue = 0; HXBOOL bRecordable = FALSE; IHXValues* pHeader = NULL; IHXBuffer* pPropValueSource = NULL; IHXBuffer* pPropValueTarget = NULL; IHXStream* pStream = NULL; // retrieve the stream info pSource->GetStream(j, (IUnknown*&)pStream); pHeader = pStream->GetHeader(); // make a copy of this stream header // XXX HP: this could be wrapped up into one method in CHXHeader CreateValuesCCF(pStreamHeader, m_pPlayer); // 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)) { if (HXR_OK == CreateAndSetBufferCCF(pPropValueTarget, pPropValueSource->GetBuffer(), pPropValueSource->GetSize(), m_pPlayer)) { pStreamHeader->SetPropertyBuffer(pszPropName, pPropValueTarget); HX_RELEASE(pPropValueTarget); } HX_RELEASE(pPropValueSource); while (HXR_OK == pHeader->GetNextPropertyBuffer(pszPropName, (IHXBuffer*&)pPropValueSource)) { if (HXR_OK == CreateAndSetBufferCCF(pPropValueTarget, pPropValueSource->GetBuffer(), pPropValueSource->GetSize(), m_pPlayer)) { pStreamHeader->SetPropertyBuffer(pszPropName, pPropValueTarget); HX_RELEASE(pPropValueTarget); } HX_RELEASE(pPropValueSource); } } // copy all the CString attributes if (HXR_OK == pHeader->GetFirstPropertyCString(pszPropName, (IHXBuffer*&)pPropValueSource)) { if (HXR_OK == CreateAndSetBufferCCF(pPropValueTarget, pPropValueSource->GetBuffer(), pPropValueSource->GetSize(), m_pPlayer)) { pStreamHeader->SetPropertyCString(pszPropName, pPropValueTarget); HX_RELEASE(pPropValueTarget); } HX_RELEASE(pPropValueSource); while (HXR_OK == pHeader->GetNextPropertyCString(pszPropName, (IHXBuffer*&)pPropValueSource)) { if (HXR_OK == CreateAndSetBufferCCF(pPropValueTarget, pPropValueSource->GetBuffer(), pPropValueSource->GetSize(), m_pPlayer)) { 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; }
void WebkitClientAdviseSink::GetClipInfo() { // Get HXSource and try to get clip infor. UINT32 sourceCount = m_pPlayer->GetSourceCount(); for (UINT32 sourceID = 0; sourceID < sourceCount; sourceID ++) { // get HXSource IUnknown* pUnkSource = NULL; IHXStreamSource* pStreamSrc = NULL; if (HXR_OK != m_pPlayer->GetSource (sourceID, pUnkSource)) { continue; } IHXValues* pFileHeader = NULL; if ( HXR_OK == pUnkSource->QueryInterface( IID_IHXValues, ( void ** )&pFileHeader ) ) { /* IHXBuffer* pAutoLoopingBuf = NULL; if ( HXR_OK == pFileHeader->GetPropertyBuffer( "Webkit_LOOP", pAutoLoopingBuf ) ) { if ( 0 == strcmp( pAutoLoopingBuf->GetBuffer(), "true" ) ) { m_pWebkitContext->SetAutoLooping( TRUE ); } } HX_RELEASE( pAutoLoopingBuf ); */ static const char * PROPERTY_NAMES[] = { "LiveStream", "HttpLiveStream", "AdaptiveHTTP" }; UINT32 ulTmp = 0; for (int i = 0; i < sizeof(PROPERTY_NAMES)/sizeof(const char *); ++i) { pFileHeader->GetPropertyULONG32(PROPERTY_NAMES[i], ulTmp); if (ulTmp) { m_bIsLiveOrAdaptiveHTTP = TRUE; break; } } } HX_RELEASE( pFileHeader ); pUnkSource->QueryInterface(IID_IHXStreamSource, (void **)&pStreamSrc); HX_RELEASE(pUnkSource); if (!pStreamSrc) { continue; } UINT32 num_streams = pStreamSrc->GetStreamCount(); // get information from Streams for (UINT32 streamID = 0; streamID < num_streams ; streamID++) { IUnknown* pUnkStream = NULL; if (HXR_OK == pStreamSrc->GetStream(streamID, pUnkStream)) { IHXStream* pStream = NULL; if (HXR_OK == pUnkStream->QueryInterface(IID_IHXStream, (void**)&pStream)) { IHXValues* pStreamHdr = pStream->GetHeader(); if (pStreamHdr) { SendClipProperties(pStreamHdr); } HX_RELEASE(pStreamHdr); } HX_RELEASE(pStream); } HX_RELEASE(pUnkStream); } HX_RELEASE(pStreamSrc); } }