qtffplin.cpp

来自「symbian 下的helix player源代码」· C++ 代码 · 共 2,308 行 · 第 1/4 页

CPP
2,308
字号
	return retVal;

    case QTFF_PrimeCache:
	if (status == HXR_OK)
	{
	    HX_ASSERT(pPacket);

	    m_pPacketCache[uStreamNum].pPacket = pPacket;
	    pPacket->AddRef();
	}
	else
	{
	    m_pPacketCache[uStreamNum].pPacket = NULL;
	    m_pPacketCache[uStreamNum].bStreamDone = TRUE;
	    if (status == HXR_STREAM_DONE)
	    {
		if (m_pPacketCache[uStreamNum].bPending)
		{
		    AddRef();   // Make sure we do not die

		    m_pPacketCache[uStreamNum].bPending = FALSE;
		    retVal = m_pFFResponse->StreamDone(uStreamNum);

		    if (m_State != QTFF_PrimeCache)
		    {
			// StreamDone must have closed us
			Release();

			break;
		    }

		    Release();
		}
	    }
	    else
	    {
		// Fatal failure
		retVal = HandleFailure(status);

		break;
	    }
	}

	uStreamNum++;
	if (uStreamNum < m_TrackManager.GetNumStreams())
	{
	    // we still have stream packets to prime
	    if (m_TrackManager.IsStreamTrackActive(uStreamNum))
	    {
		retVal = m_TrackManager.GetStreamTrack(uStreamNum)->
			    GetPacket(uStreamNum);
	    }
	    else
	    {
		retVal = PacketReady(uStreamNum, 
				     HXR_STREAM_DONE,
				     NULL);
	    }
	}
	else
	{
	    // we are done priming the packets
	    retVal = HXR_OK;
	    m_State = QTFF_Ready;

	    // see if a pending request needs to be fullfilled
	    m_uNextPacketStreamNum = GetNextPacketStreamNum();
	    if ((m_uNextPacketStreamNum != NO_STREAM_SET) &&
		m_pPacketCache[m_uNextPacketStreamNum].bPending)
	    {
		m_State = QTFF_GetPacket;
		retVal = m_TrackManager.
			    GetStreamTrack(m_uNextPacketStreamNum)->
				GetPacket(m_uNextPacketStreamNum);
	    }
	}
	break;

    case QTFF_SeekPending:
	HX_VECTOR_DELETE(m_pPacketCache);
	m_uNextPacketStreamNum = NO_STREAM_SET;
	m_State = QTFF_Ready;

	retVal = Seek(m_ulPendingSeekTime);
	break;

    default:
	retVal = HXR_UNEXPECTED;
	break;
    }

    return retVal;
}


/************************************************************************
 *  Protected Methods
 */
CQTPacketizerFactory* CQTFileFormat::BuildPacketizerFactory(void)
{
#ifdef QTCONFIG_PACKETIZER_FACTORY
    return new CQTPacketizerFactory();
#else	// QTCONFIG_PACKETIZER_FACTORY
    return NULL;
#endif	// QTCONFIG_PACKETIZER_FACTORY
}

/************************************************************************
 *  Private Methods
 */
/************************************************************************
 *  GetNextPacketStreamNum
 */
inline UINT16 CQTFileFormat::GetNextPacketStreamNum(void)
{
    UINT16 uStreamNum;
    ULONG32 ulLowestTime = 0xFFFFFFFF;
    UINT16 uNextPacketStream = NO_STREAM_SET;

    HX_ASSERT(m_pPacketCache);

    for (uStreamNum = 0;
	 uStreamNum < m_TrackManager.GetNumStreams();
	 uStreamNum++)
    {
	if (!m_pPacketCache[uStreamNum].bStreamDone)
	{
	    HX_ASSERT(m_pPacketCache[uStreamNum].pPacket);

	    if (ulLowestTime >
		m_pPacketCache[uStreamNum].pPacket->GetTime())
	    {
		uNextPacketStream = uStreamNum;
		ulLowestTime = m_pPacketCache[uStreamNum].
				    pPacket->GetTime();
	    }
	}
    }

    return uNextPacketStream;
}

/************************************************************************
 *  HandleFailure
 */
HX_RESULT CQTFileFormat::HandleFailure(HX_RESULT status)
{
    HX_RESULT retVal = HXR_OK;

    HX_ASSERT(FAILED(status));

    switch (m_State)
    {
    case QTFF_PrimeCache:
	{
	    UINT16 uStreamNum = 0;
	    m_State = QTFF_Error;
	    
	    AddRef();

	    while (m_pPacketCache &&
		   (uStreamNum < m_TrackManager.GetNumStreams()))
	    {
		if (m_pPacketCache[uStreamNum].bPending)
		{
		    m_pPacketCache[uStreamNum].bPending = FALSE;
		    m_pFFResponse->PacketReady(status, NULL);
		}
		uStreamNum++;
	    }

	    Release();
	}
	break;

    default:
	retVal = HXR_UNEXPECTED;
	break;
    }

    return retVal;
}

/************************************************************************
 *  a standard way of pulling a error string out of a resource file in a 
 *  localization friendly manner :)
 */
void 
CQTFileFormat::ReportError(UINT32 ulErrorID, HX_RESULT retVal)
{
    // Try to get the string from the resource manager
    CHXString cErrStr;
    HX_RESULT errRet = GetResourceErrorString(ulErrorID, cErrStr);
    if (errRet != HXR_OK)
    {
        switch (ulErrorID)
        {
            case IDS_ERR_QT_NOTLICENSED:
                cErrStr = ERRSTR_QT_NOTLICENSED;
                break;
            default:
                cErrStr = ERRSTR_QT_GENERALERROR;
                break;
        }
    }
 
    if (m_pErrorMessages)
    {
        m_pErrorMessages->Report(HXLOG_CRIT, retVal, 0, (const char*) cErrStr,  NULL);
    }
}

HX_RESULT 
CQTFileFormat::GetResourceErrorString(UINT32 ulErrorID, CHXString& rErrorStr)
{
    IHXExternalResourceManager* pResMgr = NULL;
    HX_RESULT retVal = m_pContext->QueryInterface(IID_IHXExternalResourceManager, (void**) &pResMgr);
    if (retVal != HXR_OK)
    {
        return retVal;
    }

	IHXExternalResourceReader* pResRdr = NULL;
    retVal = pResMgr->CreateExternalResourceReader(CORE_RESOURCE_SHORT_NAME, pResRdr);
    if (retVal != HXR_OK)
    {
        HX_RELEASE(pResMgr);
        return retVal;
    }

    IHXXResource* pRes = pResRdr->GetResource(HX_RT_STRING, ulErrorID);
    if(!pRes)
    {
        HX_RELEASE(pResRdr);
        HX_RELEASE(pResMgr);
        return HXR_FAIL;
    }

    // Assign the error string to the out parameter
    rErrorStr = (const char*) pRes->ResourceData();

    // Release all references
    HX_RELEASE(pRes);
    HX_RELEASE(pResRdr);
    HX_RELEASE(pResMgr);

    return HXR_OK;
}

/************************************************************************
 *  AddMetaInfo
 */
HX_RESULT CQTFileFormat::AddMetaInfo(IHXValues* pHeader)
{
    BOOL bAddAll;

    ULONG32 ulPresentationWidth = 0;
    ULONG32 ulPresentationHeight = 0;
    
    HX_ASSERT(pHeader);

    if ((m_TrackManager.GetEType() == QT_ETYPE_CLIENT) || 
	(m_ulStreamMetaInfoMask & META_INFO_ALL) ||
	(m_ulStreamMetaInfoMask & META_INFO_WIDTH) ||
	(m_ulStreamMetaInfoMask & META_INFO_HEIGHT))
    {
	UINT16 uStreamCount;
	CQTTrack* pTrack;

	// Collect Meta Info
	for (uStreamCount = m_TrackManager.GetNumStreams();
	     uStreamCount != 0;
	     uStreamCount--)
	{
	    pTrack = m_TrackManager.GetStreamTrack(uStreamCount - 1);
	
	    ulPresentationWidth += pTrack->m_TrackInfo.GetTrackWidth();
	    ulPresentationHeight += pTrack->m_TrackInfo.GetTrackHeight();
	}
    }

    bAddAll = ((m_TrackManager.GetEType() == QT_ETYPE_CLIENT) || 
	       (m_ulStreamMetaInfoMask & META_INFO_ALL));

    if (bAddAll)
    {
	if (ulPresentationWidth > 0)
	{
	    pHeader->SetPropertyULONG32(WIDTH_METANAME, 
					ulPresentationWidth);
	}
	if (ulPresentationHeight > 0)
	{
	    pHeader->SetPropertyULONG32(HEIGHT_METANAME, 
					ulPresentationHeight);
	}
    }
#ifdef QTCONFIG_SERVER
    else if((m_ulStreamMetaInfoMask & META_INFO_ALL) ||
	(m_ulStreamMetaInfoMask & META_INFO_WIDTH) ||
	(m_ulStreamMetaInfoMask & META_INFO_HEIGHT))
    {	    
	if (ulPresentationWidth > 0 &&
	    ((m_ulStreamMetaInfoMask & META_INFO_ALL) ||
	    (m_ulStreamMetaInfoMask & META_INFO_WIDTH)))
	{
	    pHeader->SetPropertyULONG32(WIDTH_METANAME, 
					ulPresentationWidth);
	}

	if (ulPresentationHeight > 0 &&
	    ((m_ulStreamMetaInfoMask & META_INFO_ALL) ||
	    (m_ulStreamMetaInfoMask & META_INFO_HEIGHT)))
	{
	    pHeader->SetPropertyULONG32(HEIGHT_METANAME, 
					ulPresentationHeight);
	}
    } 
#endif	// QTCONFIG_SERVER

    return HXR_OK;
}

#ifdef QTCONFIG_SERVER
/************************************************************************
 *  CheckLicense
 */
HX_RESULT CQTFileFormat::CheckLicense(void)
{
    HX_ASSERT(m_pContext);
    
    IHXClientEngine* pPlayer = NULL;
    IHXRemoteBroadcastServices* pRBServices = NULL;
    if (SUCCEEDED(m_pContext->QueryInterface(IID_IHXClientEngine, (void**)&pPlayer))
        || SUCCEEDED(m_pContext->QueryInterface(IID_IHXRemoteBroadcastServices, (void**)&pRBServices)))
    {
        // Data types are always licensed on the Player and iqslta
        m_bQTLicensed = TRUE;
	m_bMP4Licensed = TRUE;
    }
    else
    {    
        // On the Server, check the license section of the registry
        IHXRegistry* pRegistry = NULL;        
	if (HXR_OK != m_pContext->QueryInterface(IID_IHXRegistry, 
				(void**)&pRegistry))
	{
	    return HXR_UNEXPECTED;
	}

        INT32 nLicensed = 0;
        if (!SUCCEEDED(pRegistry->GetIntByName(REGISTRY_QUICKTIME_ENABLED, 
            nLicensed)))
        {
            /* take default */
            nLicensed = LICENSE_QUICKTIME_ENABLED;
        }
        m_bQTLicensed = (nLicensed) ? (TRUE) : (FALSE);

        if (!SUCCEEDED(pRegistry->GetIntByName(REGISTRY_REALMP4_ENABLED, 
            nLicensed)))
        {
            /* take default */
            nLicensed = LICENSE_REALMP4_ENABLED;
        }
        m_bMP4Licensed = (nLicensed) ? (TRUE) : (FALSE);

        HX_RELEASE(pRegistry);
    }
    HX_RELEASE(pPlayer);
    HX_RELEASE(pRBServices);

    return HXR_OK;
}

/************************************************************************
 *  WarnIfNotHinted
 */
void CQTFileFormat::WarnIfNotHinted(HX_RESULT status, BOOL bIgnoreHintTracks)
{    
    /*
     * log what's going on...
     */    
    if ((m_TrackManager.GetEType() == QT_ETYPE_SERVER) && m_pErrorMessages
	&& HXR_OK == status)
    {
        /*
         * Check the registry to see if warnings are disabled.
         */
        INT32 nWarningDisabled = 0;
        IHXRegistry* pRegistry = NULL;
        if (m_pContext &&
            (HXR_OK == m_pContext->QueryInterface(IID_IHXRegistry, 
                                                 (void**)&pRegistry)))
        {
            pRegistry->GetIntByName("config.DisableHintingWarning",
                                    nWarningDisabled);
        }
        HX_RELEASE(pRegistry);

        if (nWarningDisabled)
        {
            return;
        }

	const char* pszIgnore = 
	    "Handling HINTED content - ignoring Hint Tracks (URL: /%s)\n";
	const char* pszHint = 
	    "Handling HINTED content - using Hint Tracks (URL: /%s)\n";
	const char* pszNotHinted = 
	    "Handling UNHINTED content (URL: /%s)\n";
	const char* pszMsg;
	
	if (bIgnoreHintTracks)
	{	
	    pszMsg = pszIgnore;
	}
	else if (m_TrackManager.IsHinted())
	{
	    pszMsg = pszHint;
	    HX_ASSERT(HXR_NOT_LICENSED != status); // can't ever be this error
	}
	else
	{
	    pszMsg = pszNotHinted;
	}

        const char* pReqURL = NULL;        
        UINT32 ulMaxURLLen = 1024 * 2;
        UINT32 ulBuffLen = ulMaxURLLen + strlen(pszMsg) + 1;

        HX_RESULT status = HXR_OK;
        if (m_pRequest)
        {
            status = m_pRequest->GetURL(pReqURL);
        }

        if (SUCCEEDED(status) && pReqURL)
        {
            UINT32 ulURLLen = strlen(pReqURL);
            if (ulURLLen >  ulMaxURLLen)
            {
                pReqURL += ulURLLen - ulMaxURLLen;  
            }
        }
        else 
        {
            pReqURL = " ";
        }

        NEW_FAST_TEMP_STR(pszTmpStr, 4096, ulBuffLen);
        snprintf(pszTmpStr, ulBuffLen, pszMsg, pReqURL); 
        m_pErrorMessages->Report(HXLOG_WARNING, HXR_OK, 0, pszTmpStr, NULL);
        DELETE_FAST_TEMP_STR(pszTmpStr);
    }
}
#else	// QTCONFIG_SERVER
HX_RESULT CQTFileFormat::CheckLicense(void)
{
    return HXR_OK;
}

void CQTFileFormat::WarnIfNotHinted(HX_RESULT status, BOOL bIgnoreHintTracks)
{
    return;
}
#endif	// QTCONFIG_SERVER

/************************************************************************
 *	Method:
 *	    IHXThreadSafeMethods::IsThreadSafe
 */
STDMETHODIMP_(UINT32) CQTFileFormat::IsThreadSafe()
{
    return HX_THREADSAFE_METHOD_FF_GETPACKET |
	   HX_THREADSAFE_METHOD_FSR_READDONE;
}

/************************************************************************
 *  IUnknown methods
 */
STDMETHODIMP CQTFileFormat::QueryInterface(REFIID riid, void** ppvObj)
{
    QInterfaceList qiList[] =
    {
	{ GET_IIDHANDLE(IID_IUnknown), (IUnknown*) (IHXPlugin*) this},
	{ GET_IIDHANDLE(IID_IHXPlugin), (IHXPlugin*) this},
	{ GET_IIDHANDLE(IID_IHXFileFormatObject), (IHXFileFormatObject*) this},
	{ GET_IIDHANDLE(IID_IHXAtomizerResponse), (IHXAtomizerResponse*) this},
	{ GET_IIDHANDLE(IID_IHXAtomizationCommander), (IHXAtomizationCommander*) this},
#ifdef QTCONFIG_ALTERNATE_STREAMS
	{ GET_IIDHANDLE(IID_IHXASMSource), (IHXASMSource*) this},
#endif	// QTCONFIG_ALTERNATE_STREAMS
	{ GET_IIDHANDLE(IID_IHXPacketFormat), (IHXPacketFormat*) this},
	{ GET_IIDHANDLE(IID_IHXFileSwitcher), (IHXFileSwitcher*) m_pFileSwitcher},
	{ GET_IIDHANDLE(IID_IHXCommonClassFactory), m_pClassFactory},
	{ GET_IIDHANDLE(IID_IHXScheduler), m_pScheduler}
    };

    return QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
}

STDMETHODIMP_(ULONG32) CQTFileFormat::AddRef()
{
    return InterlockedIncrement(&m_lRefCount);
}

STDMETHODIMP_(ULONG32) CQTFileFormat::Release()
{
    if (InterlockedDecrement(&m_lRefCount) > 0)
    {
        return m_lRefCount;
    }

    delete this;
    return 0;
}


/************************************************************************
 *  GetFileHeader
 *  Purpose:
 *	Called by controller to ask the file format for the number of
 *	headers in the file. The file format should call the 
 *	IHXFormatResponse::StreamCountReady() for the IHXFileFormat-
 *	Session object that was passed in during initialization, when the
 *	header count is available.
 */
STDMETHODIMP CQTFileFormat::GetFileHeader()
{
    HX_RESULT retVal = HXR_UNEXPECTED;

    if (m_State == QTFF_Ready)
    {
	if (m_pAtomizer)
	{
	    // This must be the first call to GetFileHeader - Atomize
	    m_State = QTFF_Atomize;
	    retVal = m_pAtomizer->Atomize();
	}
	else
	{
	    retVal = MakeFileHeader(HXR_OK);
	}
    }
    
    return retVal;
}


/************************************************************************
 *  GetStreamHeader
 *  Purpose:
 *	Called by controller to ask the file format for the header for
 *	a particular stream in the file. The file format should call 
 *	IHXFileFormatResponse::HeaderReady() for the IHXFileFormatResponse
 *	object that was passed in during initialization, when the header
 *	is available.
 */
STDMETHODIMP CQTFileFormat::GetStreamHeader(UINT16 unStreamNumber)
{
    HX_RESULT retVal;
    IHXValues* pHeader;

    retVal = ObtainStreamHeader(unStreamNumber, pHeader);

    if (SUCCEEDED(retVal))
    {
	retVal = m_pFFResponse->StreamHeaderReady(retVal, pHeader);
    }

    HX_RELEASE(pHeader);

    return retVal;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?