qtffplin.cpp

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

CPP
2,308
字号
			ulGroupBitrate = 0;
		    }

		    status = m_TrackManager.AddStreamToGroup(
			uStrmIdx,
			(UINT16) ulGroupID,
			ulGroupBitrate);
		}
						   
		HX_RELEASE(pGroupInfo);

		if (FAILED(status))
		{
		    break;
		}
	    }
	}
    }

    // Make Default subscriptions
    if (SUCCEEDED(status))
    {
	status = m_TrackManager.SubscribeDefault();
    }

    // If we are running in player, eliminate inactive stream tracks
    if (SUCCEEDED(status))
    {
	IHXClientEngine *pPlayer = NULL;

	if (SUCCEEDED(m_pContext->QueryInterface(IID_IHXClientEngine, 
						 (void**) &pPlayer)))
	{
	    // Running in player
	    status = m_TrackManager.RemoveInactiveStreams();
	}

	HX_RELEASE(pPlayer);
    }
#endif	// QTCONFIG_ALTERNATE_STREAMS

    // Set General properties, Stream Count and duration
    if (SUCCEEDED(status))
    {
	pHeader->SetPropertyULONG32("IsRealDataType", 0);
	pHeader->SetPropertyULONG32("StreamCount",  
				    m_TrackManager.GetNumStreams());
	pHeader->SetPropertyULONG32("Duration",
	    (ULONG32) ((1000.0 * ((double) m_MovieInfo.GetMovieDuration())) /
	               m_MovieInfo.GetMovieTimeScale()));
    }

    // Set the licensing information: Basically this information is used by the
    // Broadcast Receiver plug-in to check and see if the RealServer is actually
    // licensed to receive this content
#ifdef QTCONFIG_SERVER
    if(SUCCEEDED(status) && (!m_bViewSourceRequest))
    {
        switch(m_TrackManager.GetFType())
        {
            case QT_FTYPE_QT:
            case QT_FTYPE_UNKNOWN:
            {
                IHXBuffer* pFileTypeBuf = NULL;
                IHXBuffer* pLicenseKeyBuf = NULL;
                m_pClassFactory->CreateInstance(CLSID_IHXBuffer, (void**)&pFileTypeBuf);
                m_pClassFactory->CreateInstance(CLSID_IHXBuffer, (void**)&pLicenseKeyBuf);
                pFileTypeBuf->Set((const BYTE*)"QuickTime", strlen("QuickTime") + 1);
                pLicenseKeyBuf->Set((const BYTE*)REGISTRY_QUICKTIME_ENABLED, strlen(REGISTRY_QUICKTIME_ENABLED) + 1);

                pHeader->SetPropertyCString("FileType", pFileTypeBuf);
                pHeader->SetPropertyCString("LicenseKey", pLicenseKeyBuf);
                pHeader->SetPropertyULONG32("DefaultLicenseValue", LICENSE_QUICKTIME_ENABLED);
                HX_RELEASE(pFileTypeBuf);
                HX_RELEASE(pLicenseKeyBuf);
                break;
            }
            case QT_FTYPE_MP4:
            {
                IHXBuffer* pFileTypeBuf = NULL;
                IHXBuffer* pLicenseKeyBuf = NULL;
                m_pClassFactory->CreateInstance(CLSID_IHXBuffer, (void**)&pFileTypeBuf);
                m_pClassFactory->CreateInstance(CLSID_IHXBuffer, (void**)&pLicenseKeyBuf);
                pFileTypeBuf->Set((const BYTE*)"MPEG4", strlen("MPEG4") + 1);
                pLicenseKeyBuf->Set((const BYTE*)REGISTRY_REALMP4_ENABLED, strlen(REGISTRY_REALMP4_ENABLED) + 1);

                pHeader->SetPropertyCString("FileType", pFileTypeBuf);
                pHeader->SetPropertyCString("LicenseKey", pLicenseKeyBuf);
                pHeader->SetPropertyULONG32("DefaultLicenseValue", LICENSE_REALMP4_ENABLED);
                HX_RELEASE(pFileTypeBuf);
                HX_RELEASE(pLicenseKeyBuf);
                break;
            }
        }
    }
#endif	// QTCONFIG_SERVER

    // Set Requested Meta Information
    if (SUCCEEDED(status))
    {
	IHXValues* pHeaders = NULL;
	IHXBuffer* pBuffer = NULL;
	
	if (m_pRequest &&
	    (m_pRequest->GetRequestHeaders(pHeaders) == HXR_OK) &&
	    pHeaders)
	{	    
	    pHeaders->Release();
	}

	status = AddMetaInfo(pHeader);
	
	// We no longer need the request so release it
	HX_RELEASE(m_pRequest);
    }

    // Set View Source specific information
#ifdef HELIX_FEATURE_VIEWSOURCE
    if (SUCCEEDED(status) && m_bViewSourceRequest)
    {
	IHXBuffer* pCStringBuffer = NULL;

	status = m_pClassFactory->CreateInstance(CLSID_IHXBuffer,
						 (void**) &pCStringBuffer);
	if (SUCCEEDED(status))
	{
	    const char* pString = "Not Hinted";

	    if (m_TrackManager.IsHinted())
	    {
		pString = "Hinted";
	    }

	    status = pCStringBuffer->Set((UINT8*) pString, strlen(pString) + 1);
	}

	if (SUCCEEDED(status))
	{
	    status = pHeader->SetPropertyCString("Characteristic", pCStringBuffer);
	}

	HX_RELEASE(pCStringBuffer);

	if (SUCCEEDED(status))
	{
	    status = pHeader->SetPropertyULONG32("ViewSourceInfoHeaders", 1);
	}
    }
#endif	// HELIX_FEATURE_VIEWSOURCE

    if (FAILED(status))
    {
	HX_RELEASE(pHeader);
    }

    retVal = m_pFFResponse->FileHeaderReady(status, pHeader);

    HX_RELEASE(pHeader);

    return retVal;
}

HX_RESULT CQTFileFormat::ObtainStreamHeader(UINT16 unStreamNumber,
					    IHXValues* &pHeader)
{
    HX_RESULT retVal = HXR_OK;
    CQTTrack* pTrack = NULL;
    
    pHeader = NULL;

    // Check Entry requirements
    if (m_State != QTFF_Ready)
    {
	retVal = HXR_UNEXPECTED;
    }

    if (SUCCEEDED(retVal))
    {
	retVal = HXR_INVALID_PARAMETER;
	if (unStreamNumber < m_TrackManager.GetNumStreams())
	{
	    retVal = HXR_OK;
	}
    }

    // See if made header is already available
    if (SUCCEEDED(retVal))
    {
	pTrack = m_TrackManager.GetStreamTrack(unStreamNumber);
	if (pTrack->m_TrackInfo.GetHeader(pHeader) != HXR_OK)
	{
	    retVal = BuildStreamHeader(pHeader,
				       pTrack,
				       &pTrack->m_TrackInfo,
				       &m_MovieInfo,
				       &m_TrackManager,
				       m_pClassFactory);
	}
    }

    if (SUCCEEDED(retVal))
    {
	HX_ASSERT(pHeader);
	pHeader->SetPropertyULONG32("StreamNumber", unStreamNumber);
    }

    return retVal;
}

HX_RESULT CQTFileFormat::BuildStreamHeader(IHXValues* &pHeader,
					   CQTTrack* pTrack,
					   CQT_TrackInfo_Manager* pTrackInfo,
					   CQT_MovieInfo_Manager* pMovieInfo,
					   CQTTrackManager* pTrackManager,
					   IHXCommonClassFactory* pClassFactory)
{
    IHXBuffer* pName = NULL;
    IHXBuffer* pASMRuleBook = NULL;
    IHXBuffer* pMimeType = NULL;
    ULONG32 ulPayloadType = QT_BAD_PAYLOAD;
    ULONG32 ulAvgBitRate = 0;
    ULONG32 ulMaxBitRate = 0;
    ULONG32 ulPreroll = 0;
    ULONG32 ulPredata = 0;
    ULONG32 ulWidth = 0;
    ULONG32 ulHeight = 0;
    ULONG32 ulChannels = 0;
    HX_RESULT retVal = HXR_OK;

    // Create needed buffers
    if (!pHeader)
    {
	retVal = pClassFactory->CreateInstance(CLSID_IHXValues,
						 (void**) &pHeader);
    }

    if (SUCCEEDED(retVal))
    {
	retVal = pClassFactory->CreateInstance(CLSID_IHXBuffer,
						 (void**) &pName);
    }

    if (SUCCEEDED(retVal))
    {
	retVal = pClassFactory->CreateInstance(CLSID_IHXBuffer,
						 (void**) &pASMRuleBook);
    }

    // Set Stream Name
    if (SUCCEEDED(retVal) && (pTrackInfo->GetNameLength() > 0))
    {
	UCHAR* pNameMem;
	ULONG32 ulNameMemLength = 0;
	
	retVal = pName->SetSize(pTrackInfo->GetNameLength() + 1);
	if (SUCCEEDED(retVal))
	{
	    pName->Get(pNameMem, ulNameMemLength);
	    memcpy(pNameMem, pTrackInfo->GetName(), /* Flawfinder: ignore */
		   ulNameMemLength - 1);
	    pNameMem[ulNameMemLength - 1] = '\0';

	    pHeader->SetPropertyCString("StreamName", pName);
	}
    }

    HX_RELEASE(pName);

    // Set Opaque Data - if any
    if (SUCCEEDED(retVal) && (pTrackInfo->GetOpaqueDataLength() > 0))
    {
	IHXBuffer* pOpaqueData = NULL;

	retVal = pClassFactory->CreateInstance(CLSID_IHXBuffer,
					       (void**) &pOpaqueData);

	if (SUCCEEDED(retVal))
	{
	    UCHAR* pOpaqueDataMem;
	    ULONG32 ulOpaqueDataLength = 0;
	
	    retVal = pOpaqueData->SetSize(pTrackInfo->GetOpaqueDataLength());
	    if (SUCCEEDED(retVal))
	    {
		pOpaqueData->Get(pOpaqueDataMem, ulOpaqueDataLength);
		memcpy(pOpaqueDataMem, /* Flawfinder: ignore */
		       pTrackInfo->GetOpaqueData(),
		       ulOpaqueDataLength);
		pHeader->SetPropertyBuffer("OpaqueData", pOpaqueData);
	    }
	}

	HX_RELEASE(pOpaqueData);
    }

    if (SUCCEEDED(retVal))
    {
	retVal = GetPayloadIdentity(pHeader, pTrack, pTrackInfo);
    }
    
    // Set Duration, AvgBitRate and Preroll
    if (SUCCEEDED(retVal))
    {
	ULONG32 ulDuration;
	
	ulDuration = (ULONG32) ((pTrackInfo->GetTrackDuration()
				 * 1000.0)
				/ pMovieInfo->GetMovieTimeScale());

	ulAvgBitRate = pTrackInfo->GetAvgBitrate();

	ulMaxBitRate = pTrackInfo->GetMaxBitrate();

	ulPreroll = pTrackInfo->GetPreroll();
	ulPredata = pTrackInfo->GetPredata();

	ulWidth = pTrackInfo->GetTrackWidth();
	ulHeight= pTrackInfo->GetTrackHeight();

	if ((ulAvgBitRate == 0) && (ulDuration > 0))
	{
	    ULONG32 ulTrackSize = pTrackInfo->GetTrackSize();

	    if (ulTrackSize == 0)
	    {
		    pTrack->ComputeTrackSize(ulTrackSize);
		}

	    ulAvgBitRate = (ULONG32) ((((double) ulTrackSize) * 8000.0) 
				      / ulDuration + 0.5);
	}

	if (ulAvgBitRate == 0)
	{
	    ulAvgBitRate = SDPMapPayloadToBitrate(ulPayloadType);
	}

	pHeader->SetPropertyULONG32("Duration", ulDuration);

	if (ulAvgBitRate != 0)
	{
	    pHeader->SetPropertyULONG32("AvgBitRate", ulAvgBitRate);
	}

	if (ulMaxBitRate != 0)
	{
	    pHeader->SetPropertyULONG32("MaxBitRate", ulMaxBitRate);
	}

	if (ulPreroll != 0)
	{
	    pHeader->SetPropertyULONG32("Preroll", ulPreroll);
	}

	if (ulPredata != 0)
	{
	    pHeader->SetPropertyULONG32("Predata", ulPredata);
	}

	if(ulWidth != 0)
	{
	    pHeader->SetPropertyULONG32(WIDTH_METANAME, ulWidth);
	}

	if(ulHeight != 0)
	{
	    pHeader->SetPropertyULONG32(HEIGHT_METANAME, ulHeight);
	}
    }

    if (SUCCEEDED(retVal))
    {
	// .mp4 and .mov files may produce streams with out-of-order time stamps
	// Client core does not normally expect this in RDT protocol so set this
	// property to alert client core of this fact.
	pHeader->SetPropertyULONG32("HasOutOfOrderTS", 1);
    }

    // Set ASM Rule Book
    if (SUCCEEDED(retVal))
    {
	char pRuleBook[128]; /* Flawfinder: ignore */

#ifdef QTCONFIG_SERVER
	pHeader->GetPropertyULONG32("RTPPayloadType", ulPayloadType);

	if (pTrackManager->GetEType() != QT_ETYPE_CLIENT)
	{
	    // Server Side
	    retVal = HXR_FAIL;
	    if (ulPayloadType != QT_BAD_PAYLOAD)
	    {
		retVal = HXR_OK;
	    }

	    if (SUCCEEDED(retVal))
	    {
		BOOL bSupportedPayload = SDPIsKnownPayload(ulPayloadType);

		pHeader->GetPropertyCString("MimeType", pMimeType);

		// This is not a standard payload - 
		// but maybe the encoding is standard
		if (!bSupportedPayload && pMimeType)
		{
		    bSupportedPayload = (SDPMapMimeToPayload(pMimeType, 
							     ulPayloadType)
					 == HXR_OK);
		}

		// Set the ASM rule book
		if ((ulAvgBitRate > 0)
#ifndef QTFORCE_AVG_BITRATE_DELIVERY
		    && bSupportedPayload
		    && SDPIsFixedRatePayload(ulPayloadType)
#endif	// QTFORCE_AVG_BITRATE_DELIVERY
		   )
		{
		    // divide avg bitrate
		    UINT32 ulAvgBandwidth = ulAvgBitRate / 2;

		    SafeSprintf(pRuleBook, 128, 
			    "Marker=%d,AverageBandwidth=%d;"
			    "Marker=%d,AverageBandwidth=%d;",
			    (QTASM_MARKER_ON_RULE == 0) ? 1 : 0,
			    ulAvgBitRate - ulAvgBandwidth,
			    (QTASM_MARKER_ON_RULE == 0) ? 0 : 1,
			    ulAvgBandwidth);
		}
		else
		{
		    if (ulAvgBitRate > 0)
		    {
			SafeSprintf(pRuleBook, 128, "Marker=%d,AverageBandwidth=%d,TimeStampDelivery=TRUE;"
					   "Marker=%d,AverageBandwidth=0,TimeStampDelivery=TRUE;",
			        (QTASM_MARKER_ON_RULE == 0) ? 1 : 0,
				ulAvgBitRate,
				(QTASM_MARKER_ON_RULE == 0) ? 0 : 1);
		    }
		    else
		    {
			SafeSprintf(pRuleBook, 128, "Marker=%d,TimeStampDelivery=TRUE;"
					   "Marker=%d,TimeStampDelivery=TRUE;",
			        (QTASM_MARKER_ON_RULE == 0) ? 1 : 0,
				(QTASM_MARKER_ON_RULE == 0) ? 0 : 1);
		    }
		}
	    }
	}
	else
#endif	// QTCONFIG_SERVER
	{
	    // Player Side
	    SafeSprintf(pRuleBook, 128, "Marker=%d;Marker=%d;",
		(QTASM_MARKER_ON_RULE == 0) ? 1 : 0,
		(QTASM_MARKER_ON_RULE == 0) ? 0 : 1);
	}


	if (SUCCEEDED(retVal))
	{
	    retVal = pASMRuleBook->Set((UCHAR*) pRuleBook, strlen(pRuleBook) + 1);
	}

	if (SUCCEEDED(retVal))
	{
	    pHeader->SetPropertyCString("ASMRuleBook", pASMRuleBook);
	}
    }

    HX_RELEASE(pASMRuleBook);
    HX_RELEASE(pMimeType);

    return retVal;
}

HX_RESULT CQTFileFormat::GetSessionIdentity(IHXValues* pHeader,
					    CQT_MovieInfo_Manager* pMovieInfo)
{
    return HXR_OK;
}

HX_RESULT CQTFileFormat::GetPayloadIdentity(IHXValues* pHeader,
					    CQTTrack* pTrack,
					    CQT_TrackInfo_Manager* pTrackInfo)
{
    HX_RESULT retVal = HXR_OK;

    if (SUCCEEDED(retVal))
    {
	const char* pMimeType = pTrackInfo->GetMimeType();
	retVal = HXR_FAIL;
	if (pMimeType)
	{
	    IHXBuffer* pMimeTypeBuffer = NULL;
	    UINT32 ulMimeTypeLength = strlen(pMimeType);
	    retVal = m_pClassFactory->CreateInstance(CLSID_IHXBuffer,
						     (void**) &pMimeTypeBuffer);

	    if (SUCCEEDED(retVal))
	    {	
		retVal = pMimeTypeBuffer->SetSize(ulMimeTypeLength + 1);
	    }

	    if (SUCCEEDED(retVal))
	    {
		memcpy(pMimeTypeBuffer->GetBuffer(), /* Flawfinder: ignore */
		       pMimeType,
		       ulMimeTypeLength + 1);
		retVal = pHeader->SetPropertyCString("MimeType", pMimeTypeBuffer);
	    }

	    HX_RELEASE(pMimeTypeBuffer);
	}
    }

    if (SUCCEEDED(retVal))
    {
	ULONG32 ulTimeScale = pTrackInfo->GetMediaTimeScale();

	retVal = HXR_FAIL;
	if (ulTimeScale != 0)
	{
	    retVal = pHeader->SetPropertyULONG32("SamplesPerSecond", ulTimeScale);
	}
    }

    if (SUCCEEDED(retVal))
    {
	ULONG32 ulPayloadType = pTrackInfo->GetPayloadType();

	retVal = HXR_FAIL;
	if (ulPayloadType != QT_BAD_PAYLOAD)
	{
	    retVal = pHeader->SetPropertyULONG32("RTPPayloadType", ulPayloadType);
	}
    }

    return retVal;
}


/************************************************************************
 *  GetPacket
 *  Method:
 *	IHXFileFormatObject::GetPacket
 *  Purpose:
 *	Called by controller to ask the file format for the next packet
 *	for a particular stream in the file. The file format should call
 *	IHXFileFormatResponse::Data*() for the IHXFileFormatResponse
 *	object that was passed in during initialization, when the packet
 *	is available.
 */
STDMETHODIMP CQTFileFormat::GetPacket(UINT16 unStreamNumber)
{
    HX_RESULT retVal;

    if (unStreamNumber < m_TrackManager.GetNumStreams())
    {
	switch (m_State)
	{
	case QTFF_Ready:
	    if (unStreamNumber == m_uNextPacketStreamNum)
	    {
		// Process this packet request
		// - but replace stream's cache first
		HX_ASSERT(m_pPacketCache);

		m_State = QTFF_GetPacket;
		return m_TrackManager.GetStreamTrack(unStreamNumber)->
				GetPacket(unStreamNumber);
	    }
	    else if (m_pPacketCache)
	    {
		// Delay processing packet for stream until its turn
		if (!m_pPacketCache[unStreamNumber].bStreamDone)
		{

⌨️ 快捷键说明

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