qtffplin.cpp

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

CPP
2,308
字号
		    if (!m_pPacketCache[unStreamNumber].bPending)
		    {
			m_pPacketCache[unStreamNumber].bPending = TRUE;
			return HXR_OK;
		    }
		    else
		    {
			retVal = HXR_UNEXPECTED;
		    }
		}
		else
		{
		    retVal = m_pFFResponse->StreamDone(unStreamNumber);
		}
	    }
	    else
	    {
		// Packet Cache not primed - start priming

		// To save memory, release streams not used
		m_TrackManager.RemoveInactiveStreams(TRUE);

		m_State = QTFF_PrimeCache;
		m_pPacketCache = new 
		    CPacketCache[m_TrackManager.GetNumStreams()];
		if (m_pPacketCache)
		{
		    m_pPacketCache[unStreamNumber].bPending = TRUE;

		    if (m_TrackManager.IsStreamTrackActive(0))
		    {
			return m_TrackManager.GetStreamTrack(0)->
				    GetPacket(0);
		    }
		    else
		    {
			return PacketReady(0, 
					   HXR_STREAM_DONE,
					   NULL);
		    }
		}
		else
		{
		    retVal = HXR_OUTOFMEMORY;
		    m_State = QTFF_Error;
		}
	    }
	    break;

	case QTFF_GetPacket:
	case QTFF_PrimeCache:
	    // Delay processing packet for stream until Ready
	    HX_ASSERT(m_pPacketCache);

	    if (!m_pPacketCache[unStreamNumber].bStreamDone)
	    {
		if (!m_pPacketCache[unStreamNumber].bPending)
		{
		    m_pPacketCache[unStreamNumber].bPending = TRUE;
		    return HXR_OK;
		}
		else
		{
		    retVal = HXR_UNEXPECTED;
		}
	    }
	    else
	    {
		retVal = m_pFFResponse->StreamDone(unStreamNumber);
	    }
	    break;

	default:
	    retVal = HXR_UNEXPECTED;
	    break;
	}
    }
    else
    {
	retVal = HXR_INVALID_PARAMETER;
    }

    return retVal;
}

/************************************************************************
 *  Seek
 *  Purpose:
 *	Called by controller to tell the file format to seek to the 
 *	nearest packet to the requested offset. The file format should 
 *	call IHXFileFormatResponse::SeekDone() for the IHXFileFormat-
 *	Session object that was passed in during initialization, when 
 *	the seek has completed.
 */
STDMETHODIMP CQTFileFormat::Seek(ULONG32 ulOffset)
{
    UINT16 uStreamNum;
    HX_RESULT retVal = HXR_OK;

    switch (m_State)
    {
    case QTFF_Ready:
	for (uStreamNum = 0;
	     uStreamNum < m_TrackManager.GetNumStreams();
	     uStreamNum++)
	{
	    if (m_TrackManager.IsStreamTrackActive(uStreamNum))
	    {
		m_TrackManager.GetStreamTrack(uStreamNum)->Seek(ulOffset);
	    }
	}

	m_uNextPacketStreamNum = NO_STREAM_SET;
	HX_VECTOR_DELETE(m_pPacketCache);

	retVal = m_pFFResponse->SeekDone(HXR_OK);
	break;

    case QTFF_GetPacket:
    case QTFF_PrimeCache:
    case QTFF_SeekPending:
	m_State = QTFF_SeekPending;
	m_ulPendingSeekTime = ulOffset;
	break;

    default:
	retVal = HXR_UNEXPECTED;
	break;
    }

    return retVal;
}

/************************************************************************
 *  WriteDone
 *  Purpose:
 *	Notification interface provided by users of the IHXFileObject
 *	interface. This method is called by the IHXFileObject when the
 *	last write to the file is complete.
 */
STDMETHODIMP CQTFileFormat::WriteDone(HX_RESULT status)
{
    return HXR_UNEXPECTED;
}

/************************************************************************
 *  SeekDone
 *  Purpose:
 *	Notification interface provided by users of the IHXFileObject
 *	interface. This method is called by the IHXFileObject when the
 *	last seek in the file is complete.
 */
STDMETHODIMP CQTFileFormat::SeekDone(HX_RESULT status)
{
    return HXR_UNEXPECTED;
}

/************************************************************************
 *  Close
 */
STDMETHODIMP CQTFileFormat::Close()
{
    m_State = QTFF_Error;

    HX_RELEASE(m_pContext);
    HX_RELEASE(m_pRequest);
    HX_RELEASE(m_pFFResponse);
    HX_RELEASE(m_pClassFactory);
    HX_RELEASE(m_pScheduler);
    HX_RELEASE(m_pErrorMessages);
    if (m_pFileSwitcher)
    {
	m_pFileSwitcher->Close(this);
	m_pFileSwitcher->Release();
	m_pFileSwitcher = NULL;
    }
    if (m_pAtomizer)
    {
	m_pAtomizer->Close();
	m_pAtomizer->Release();
	m_pAtomizer = NULL;
    }
    HX_RELEASE(m_pPacketAssembler);
#ifdef QTCONFIG_BFRAG_FACTORY
    HX_RELEASE(m_pBufferFragmentFactory);
#endif	// QTCONFIG_BFRAG_FACTORY
    HX_VECTOR_DELETE(m_pPacketCache);

    m_TrackManager.CloseTracks();

    return HXR_OK;
}

/************************************************************************
 *  IHXFileResponse
 */
/************************************************************************
 *  InitDone
 *  Purpose:
 *    Notification interface provided by users of the IHXFileObject
 *    interface. This method is called by the IHXFileObject when the
 *    initialization of the file is complete, and the Mime type is
 *    available for the request file. If the URL is not valid for the
 *    file system, the status HXR_FAILED should be returned,
 *    with a mime type of NULL. If the URL is valid but the mime type
 *    is unknown, then the status HXR_OK should be returned with
 *    a mime type of NULL.
 */
STDMETHODIMP CQTFileFormat::InitDone(HX_RESULT status)
{
    HX_RESULT retVal = HXR_OK;

    switch (m_State)
    {
    case QTFF_Init:
	if (SUCCEEDED(status))
	{
	    status = m_pAtomizer->Init((IUnknown*)(IHXFileSwitcher*) m_pFileSwitcher,
				       (IUnknown*)(IHXAtomizerResponse*) this,
				       (IUnknown*)(IHXAtomizationCommander*) this);
	}
	
	m_State = SUCCEEDED(status) ? QTFF_Ready : QTFF_Error;

	retVal = m_pFFResponse->InitDone(status);
	break;

    default:
	retVal = HXR_UNEXPECTED;
	break;
    }

    return retVal;
}


/************************************************************************
 *  CloseDone
 *  Purpose:
 *	Notification interface provided by users of the IHXFileObject
 *	interface. This method is called by the IHXFileObject when the
 *	close of the file is complete.
 */
STDMETHODIMP CQTFileFormat::CloseDone(HX_RESULT status)
{
    // nothing to do
    return HXR_OK;
}

/************************************************************************
 *  ReadDone
 *  Purpose:
 *	Notification interface provided by users of the IHXFileObject
 *	interface. This method is called by the IHXFileObject when the
 *	last read from the file is complete and a buffer is available.
 */
STDMETHODIMP CQTFileFormat::ReadDone(HX_RESULT status,
					    IHXBuffer* pBuffer)
{
    return HXR_UNEXPECTED;
}

/************************************************************************
 *  IHXAtomizationCommander
 */
/************************************************************************
 *  GetAtomCommand
 */
QTAtomizerCmd CQTFileFormat::GetAtomCommand(QTAtomType AtomType, CQTAtom* pParent)
{
    QTAtomizerCmd eCmd = ATMZR_CMD_LOAD;

    switch (AtomType)
    {
    case QT_udta:
	if (pParent->GetType() == QT_HXROOT)
	{
	    eCmd = ATMZR_CMD_SKIP;
	}
	break;

    default:
	// do nothing;
	break;
    }

    return eCmd;
}


/************************************************************************
 *  IHXAtomizerResponse
 */
/************************************************************************
 *  AtomReady
 */
HX_RESULT CQTFileFormat::AtomReady(HX_RESULT status, CQTAtom* pRootAtom)
{
    HX_RESULT retVal = HXR_UNEXPECTED;
    CQTPacketizerFactory* pPacketizerFactory = NULL;

    switch (m_State)
    {
    case QTFF_Atomize:
	if (SUCCEEDED(status))
	{
	    HX_ASSERT(pRootAtom);
	    
	    pRootAtom->AddRef();
	    
	    if (m_pAtomizer)
	    {
		m_pAtomizer->Close();
		m_pAtomizer->Release();
		m_pAtomizer = NULL;
	    } 
	}
	else
	{
	    pRootAtom = NULL;
	}
	
	if (SUCCEEDED(status))
	{
	    IHXClientEngine* pPlayer = NULL;
	    if (SUCCEEDED(m_pContext->QueryInterface(IID_IHXClientEngine, 
						     (void**)&pPlayer)))
	    {
		m_TrackManager.SetEType(QT_ETYPE_CLIENT);
	    }
	    else
	    {
		m_TrackManager.SetEType(QT_ETYPE_SERVER);
	    }
	    HX_RELEASE(pPlayer);
	}

	if (SUCCEEDED(status))
	{
	    status = m_TrackManager.ManageTracks(pRootAtom);
	}

#ifdef QTCONFIG_PACKETIZER_FACTORY
	if (SUCCEEDED(status))
	{
	    pPacketizerFactory = BuildPacketizerFactory();
	    if (!pPacketizerFactory)
	    {
		status = HXR_OUTOFMEMORY;
	    }
	}
#endif	// QTCONFIG_PACKETIZER_FACTORY
	
	if (SUCCEEDED(status))
	{
	    BOOL bIgnoreHintTracks = FALSE;
	    while (1)
	    {
		status = m_TrackManager.ReadyTracks(bIgnoreHintTracks, 
	    					    m_bViewSourceRequest);

    	    	if (SUCCEEDED(status))
		{
		    status = m_MovieInfo.Init(pRootAtom->FindPresentChild(QT_moov),
					      &m_TrackManager);
		}

    	    	if (SUCCEEDED(status))
    	    	{    	    	
	    	    /*
	    	    * return some error to indicate try something else
	    	    */
	    	    status = m_TrackManager.InitTracks(this, 
					    	       m_pPacketAssembler,
					    	       pPacketizerFactory);
	    	    	

    		    if ((HXR_NOT_SUPPORTED == status) && 
			(bIgnoreHintTracks = !bIgnoreHintTracks))
		    {
			m_MovieInfo.Clear();
			m_TrackManager.ResetTracks();
		    }
		    else
		    {
		    	/*
	    	    	* Until we add support for unhinted content on the server....
	    	    	* 
	    	    	* Verify that hint tracks are present and log a warning message if
	    	    	* they're missing
	    	    	*/	    	    	
		    	WarnIfNotHinted(status, bIgnoreHintTracks);
    
		    	/*
		     	* XXXGo - Change warning to take into account
		     	* hintrack and license for dynamic pktization
		     	* e.g. force pktization yet not licensed for dynamic pktization...
		     	*/		     
	    	    	
	    	    	if (FAILED(status) && m_bViewSourceRequest)
	    	    	{
		    	    // For view source, proceed attempting to return as much
		    	    // information as possible
		    	    status = HXR_OK;
	    	    	}

			break;
		    }
		}
		else
		{
		    break;
		}
	    }
	}
	
	HX_DELETE(pPacketizerFactory);

#ifdef QTCONFIG_BFRAG_FACTORY
	if (SUCCEEDED(status))
	{
	    HX_RELEASE(m_pBufferFragmentFactory);
	    m_pBufferFragmentFactory = new CBufferFragmentFactory(
		m_TrackManager.GetNumStreams() * QTBUFFERFRAGMENT_POOL_SIZE,
		m_TrackManager.GetNumStreams() * QTBUFFERFRAGMENT_INITIAL_POOL_SIZE);

	    retVal = HXR_OUTOFMEMORY;
	    if (m_pBufferFragmentFactory)
	    {
		m_pBufferFragmentFactory->AddRef();
		retVal = HXR_OK;
	    }
	}
#endif	// QTCONFIG_BFRAG_FACTORY

	HX_RELEASE(pRootAtom);

	m_State = SUCCEEDED(status) ? QTFF_Ready : QTFF_Error;

	retVal = MakeFileHeader(status);
	break;

    default:
	// nothing to do
	break;
    }

    return retVal;
}


/************************************************************************
 *  IHXASMSource
 */
/************************************************************************
 *  Subscribe
 */
STDMETHODIMP CQTFileFormat::Subscribe(UINT16 uStreamNum,
				      UINT16 uRuleNumber)
{
    return m_TrackManager.Subscribe(uStreamNum);
}

/************************************************************************
 *  Unsubscribe
 */
STDMETHODIMP CQTFileFormat::Unsubscribe(UINT16 uStreamNum,
					UINT16 uRuleNumber)
{
    return m_TrackManager.Unsubscribe(uStreamNum);
}


/************************************************************************
 *      Method:
 *          IHXPacketFormat::GetSupportedPacketFormats
 *      Purpose:
 *          Obtains a list of packet formats supported by this file format
 */
STDMETHODIMP CQTFileFormat::GetSupportedPacketFormats
(
    REF(const char**) /*OUT*/ pPacketFormats
)
{
    pPacketFormats = (const char**) zm_pPacketFormats;
    return HXR_OK;
}

/************************************************************************
 *      Method:
 *          IHXPacketFormat::SetPacketFormat
 *      Purpose:
 *          Sets the packet type for this file format
 */
STDMETHODIMP CQTFileFormat::SetPacketFormat
(
    const char* pPacketFormat
)
{
    if (strcasecmp(pPacketFormat, "rtp") == 0)
    {
        m_ulPacketFormat = QTFF_RTP_FORMAT;
    }
    else
    {
        m_ulPacketFormat = QTFF_RDT_FORMAT;
    }
    return HXR_OK;
}


/************************************************************************
 *  Main Interface
 */
/************************************************************************
 *  PacketReady
 */
HX_RESULT CQTFileFormat::PacketReady(UINT16 uStreamNum, 
				     HX_RESULT status, 
				     IHXPacket* pPacket)
{
    HX_RESULT retVal;
    IHXPacket *pPacketToSend;

    switch (m_State)
    {
    case QTFF_GetPacket:
	pPacketToSend = m_pPacketCache[uStreamNum].pPacket;

	HX_ASSERT(pPacketToSend);

	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)
	    {
		status = HXR_OK;
	    }
	}

	AddRef();   // Make Sure we do not die as a result of PacketReady

	m_pPacketCache[uStreamNum].bPending = FALSE;
	retVal = m_pFFResponse->PacketReady(status, pPacketToSend);

	if (pPacketToSend)
	{
	    pPacketToSend->Release();
	}

	// Make sure the state did not change as result of PacketReady()
	// The possible change is due to invocation of Close on PacketReady
	if (m_State == QTFF_GetPacket)
	{
	    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);
	    }
	}

	Release();

⌨️ 快捷键说明

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