qttrack.cpp

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

CPP
894
字号
/****************************************************************************
 *  IsThreadSafe
 */
STDMETHODIMP_(UINT32)
CQTTrack::IsThreadSafe()
{
    return HX_THREADSAFE_METHOD_FF_GETPACKET | HX_THREADSAFE_METHOD_FSR_READDONE;
}


/****************************************************************************
 *  Protected Functions
 */
/****************************************************************************
 *  InitPacketizer
 */
HX_RESULT CQTTrack::InitPacketizer(IHXPayloadFormatObject* &pPacketizer,
				   CQTPacketizerFactory* pPacketizerFactory,
				   const char* pProtocol,
				   CQT_TrackInfo_Manager* pTrackInfo,
				   CQT_MovieInfo_Manager* pMovieInfo,
				   CQTTrackManager* pTrackManager,
				   CQTTrack* pTrack,
				   IUnknown* pContext)
{
    HX_RESULT retVal = HXR_OK;

#ifdef QTCONFIG_PACKETIZER_FACTORY
    if (pPacketizerFactory)
    {
	retVal = pPacketizerFactory->Construct(pPacketizer,
					       pProtocol,
					       pTrackInfo,
					       pMovieInfo,
					       pTrackManager,
					       pTrack,
					       pContext);

	if (retVal == HXR_NO_DATA)
	{
	    retVal = HXR_OK;
	}
    }

    if (SUCCEEDED(retVal))
    {
	if (pPacketizer)
	{
	    IHXValues* pHeader = NULL;

	    retVal = pPacketizer->Init(pContext, TRUE);

	    if (SUCCEEDED(retVal))
	    {
		retVal = m_pFileFormat->BuildStreamHeader(pHeader,
							  this,
							  pTrackInfo,
							  pMovieInfo,
							  pTrackManager,
							  m_pClassFactory);
	    }

	    if (SUCCEEDED(retVal))
	    {
		retVal = pPacketizer->SetStreamHeader(pHeader);
	    }

	    HX_RELEASE(pHeader);

	    if (SUCCEEDED(retVal))
	    {
		retVal = pPacketizer->GetStreamHeader(pHeader);
	    }

	    if (SUCCEEDED(retVal))
	    {
		pTrackInfo->SetHeader(pHeader);
	    }

	    HX_RELEASE(pHeader);
	}
    }
#endif	// QTCONFIG_PACKETIZER_FACTORY

    return retVal;
}

/****************************************************************************
 *  LoadData
 */
HX_RESULT CQTTrack::LoadData(IHXBuffer* pFileName,
			    ULONG32 ulOffset,
			    ULONG32 ulSize)
{
    HX_RELEASE(m_pReadFileNameBuffer);
    m_pReadFileName = NULL;

#ifdef _LOG_DATA_ACCESS
    FILE* pf = fopen("C:\\qt_access.txt", "a");
    fprintf(pf, "%d %d %d\n", m_ulTrackID, ulOffset, ulSize);
    fclose(pf);
#endif // _LOG_DATA_ACCESS

#ifdef QTCONFIG_TRACK_CACHE
    m_TrackCache.ReleasePage();
#endif	// QTCONFIG_TRACK_CACHE

    m_ulReadSize = ulSize;
    m_ulReadPageSize = ulSize;
    m_ulReadPageOffset = ulOffset;
    
    if (pFileName)
    {
	m_pReadFileNameBuffer = pFileName;
	pFileName->AddRef();
	m_pReadFileName = (char *) pFileName->GetBuffer();
    }
#ifdef QTCONFIG_TRACK_CACHE
    else if (m_TrackCache.IsEnabled() && (ulSize < QTTRACKCACHE_PAGE_SIZE))
    {
	m_ulReadPageSize = QTTRACKCACHE_PAGE_SIZE;
    }
#endif	// QTCONFIG_TRACK_CACHE

    return m_pFileSwitcher->Seek(   ulOffset,
				    FALSE,
				    (IHXFileResponse*) this,
				    m_pReadFileName);
}

/****************************************************************************
 *  DataReady
 */
HX_RESULT CQTTrack::DataReady(HX_RESULT status, IHXBuffer *pBuffer)
{
#ifdef QTCONFIG_TRACK_CACHE
    if (status == HXR_OK)
    {
	if (m_ulReadPageSize > m_ulReadSize)
	{
	    m_TrackCache.SetPage(m_ulReadPageOffset, pBuffer);
	}
    }
    else
    {
	if (m_TrackCache.IsEnabled())
	{
	    m_TrackCache.Enable(FALSE);
	    return LoadData(m_pReadFileNameBuffer,
			    m_ulReadPageOffset,
			    m_ulReadSize);
	}
    }
#endif	// QTCONFIG_TRACK_CACHE

    switch (m_PendingState)
    {
    case QTT_SegmentRead:
	m_PendingState = QTT_Offline;

	if (m_pPacketAssembler)
	{
	    return m_pPacketAssembler->SegmentReady(status, pBuffer,
						    0, m_ulReadSize);
	}
	break;

    case QTT_SampleRead:
	m_PendingState = QTT_Offline;
	return ReturnPacket(status, pBuffer, 0, m_ulReadSize);
    }

    return HXR_UNEXPECTED;
}

/****************************************************************************
 *  ReturnPacket
 */
HX_RESULT CQTTrack::ReturnPacket(HX_RESULT status, 
				 IHXBuffer *pBuffer)
{
    return ReturnPacket(status,
			pBuffer,
			0,
			pBuffer ? pBuffer->GetSize() : 0);
}

/****************************************************************************
 *  ReturnPacket
 */
HX_RESULT CQTTrack::ReturnPacket(HX_RESULT status, 
				IHXBuffer *pBuffer,
				ULONG32 ulOffset,
				ULONG32 ulSize)
{
    ULONG32 ulTime = (ULONG32) (m_TrackEdit.GetRealTime() + 0.5);
    ULONG32 ulRTPTime = m_TrackEdit.GetMediaTime() + 
			m_TimeToSample.GetCompositionOffset();
    IHXPacket* pPacket = NULL;
    HX_RESULT retVal = HXR_OK;

    if (pBuffer)
    {
#ifdef QTCONFIG_BFRAG
	if ((ulOffset != 0) || (ulSize != pBuffer->GetSize()))
	{
#ifdef QTCONFIG_BFRAG_FACTORY
	    pBuffer = 
		m_pFileFormat->m_pBufferFragmentFactory->WrapFragment(
		    pBuffer, ulOffset, ulSize);
#else	// QTCONFIG_BFRAG_FACTORY
	    pBuffer = new CBufferFragment(pBuffer, ulOffset, ulSize);
	    
	    if (pBuffer)
	    {
		pBuffer->AddRef();
	    }
#endif	// QTCONFIG_BFRAG_FACTORY
	}
	else
#else	// QTCONFIG_BFRAG
	HX_ASSERT((ulOffset == 0) && (ulSize == pBuffer->GetSize()));
#endif	// QTCONFIG_BFRAG
	{
	    pBuffer->AddRef();
	}
    }

    // Form packet
    if (status == HXR_OK)
    {
	status = m_pClassFactory->CreateInstance(CLSID_IHXRTPPacket,
						 (void**) &pPacket);
    }

    if (pBuffer)
    {
	if (status == HXR_OK)
	{
	    status = ((IHXRTPPacket*) pPacket)->SetRTP(
		pBuffer,
		ulTime,
		ulRTPTime,
		m_uStreamNumber,
		m_TimeToSample.IsOnSyncSample() ? 
		    (HX_ASM_SWITCH_ON | HX_ASM_SWITCH_OFF) :
		    HX_ASM_SWITCH_OFF,			    // ASM Flags
		QTASM_MARKER_ON_RULE);
	}

	pBuffer->Release();
	pBuffer = NULL;
    }
    
    if (status == HXR_OK)
    {
	m_ulLastSampleDescIdx = m_SampleToChunk.GetSampleDescIdx();
	m_bTrackDone = !AdvanceSample(m_TrackEdit,
				      m_TimeToSample,
				      m_SampleToChunk);
    }
    else
    {
	m_bTrackDone = TRUE;
    }

    if (m_pPacketizer)
    {
	if (status == HXR_OK)
	{
	    m_pPacketizer->SetPacket(pPacket);
	}

	HX_RELEASE(pPacket);

	if (m_bTrackDone)
	{
	    m_pPacketizer->Flush();
	}

	status = m_pPacketizer->GetPacket(pPacket);

	if (status == HXR_INCOMPLETE)
	{
	    if (!m_bTrackDone)
	    {
		status = GetPacket(m_uStreamNumber);
		if (status == HXR_OK)
		{
		    return status;
		}
	    }
	    else
	    {
		status = HXR_STREAM_DONE;
	    }
	}
    }

    retVal = m_pFileFormat->PacketReady(m_uStreamNumber, status, pPacket);

    HX_RELEASE(pPacket);

    return retVal;
}

/****************************************************************************
 *  SequenceToTime
 */
BOOL CQTTrack::SequenceToTime(CQT_TrackEdit_Manager &TrackEdit,
			     CQT_TimeToSample_Manager &TimeToSample,
			     CQT_SampleToChunk_Manager &SampleToChunk,
			     BOOL bUseNonKeyFrames)
{
    BOOL bOverSeek;

    do
    {
	bOverSeek = !(	bUseNonKeyFrames ?
			TimeToSample.EstablishByMediaTime(
			    TrackEdit.GetMediaTime()) :
			TimeToSample.EstablishAtKeyByMediaTime(
			    TrackEdit.GetMediaTime()));
    } while ((!bOverSeek) &&
	     TrackEdit.AdvanceByMediaTime(
		TimeToSample.GetLastMediaSyncTime(), bOverSeek) &&
	     (!bOverSeek));

    if (!bOverSeek)
    {
	bOverSeek = !SampleToChunk.EstablishBySample(
	    TimeToSample.GetSampleNumber());
    }

    return !bOverSeek;
}

/****************************************************************************
 *  AdvanceSample
 */
BOOL CQTTrack::AdvanceSample(CQT_TrackEdit_Manager &TrackEdit,
			    CQT_TimeToSample_Manager &TimeToSample,
			    CQT_SampleToChunk_Manager &SampleToChunk)
{
    BOOL bStreamDone;

    if (TrackEdit.AdvanceByMediaTime(
	    TimeToSample.GetSampleDuration(),
	    bStreamDone))
    {
	// Advancement in time caused change in edit segment
	if (!bStreamDone)
	{
	    bStreamDone = !SequenceToTime(TrackEdit,
					  TimeToSample,
					  SampleToChunk,
					  QTTRK_USE_ANY_FRAME);
	}
    }
    else
    {
	bStreamDone = ((!TimeToSample.AdvanceBySample()) ||
		       (!SampleToChunk.AdvanceBySample()));
    }

    return !bStreamDone;
}

/****************************************************************************
 *  IHXFileResponse methods 
 */
/****************************************************************************
 *  ReadDone
 */
STDMETHODIMP CQTTrack::ReadDone(HX_RESULT status,
				IHXBuffer* pBuffer)
{
    return DataReady(status, pBuffer);
}

/****************************************************************************
 *  SeekDone
 */
STDMETHODIMP CQTTrack::SeekDone(HX_RESULT status)
{
    if (SUCCEEDED(status))
    {
	return m_pFileSwitcher->Read(	m_ulReadPageSize,
					(IHXFileResponse*) this,
					m_pReadFileName);
    }

    return DataReady(status, NULL);
}

/****************************************************************************
 *  IUnknown methods
 */
/////////////////////////////////////////////////////////////////////////
//  Method:
//	IUnknown::QueryInterface
//
STDMETHODIMP CQTTrack::QueryInterface(REFIID riid, void** ppvObj)
{
    if (IsEqualIID(riid, IID_IHXThreadSafeMethods))
    {
	AddRef();
	*ppvObj = (IHXThreadSafeMethods*) this;
	return HXR_OK;
    }
    else if (IsEqualIID(riid, IID_IUnknown))
    {
	AddRef();
	*ppvObj = this;
	return HXR_OK;
    }

    *ppvObj = NULL;

    return HXR_NOINTERFACE;
}

/////////////////////////////////////////////////////////////////////////
//  Method:
//	IUnknown::AddRef
//
STDMETHODIMP_(ULONG32) CQTTrack::AddRef()
{
    return InterlockedIncrement(&m_lRefCount);
}

/////////////////////////////////////////////////////////////////////////
//  Method:
//	IUnknown::Release
//
STDMETHODIMP_(ULONG32) CQTTrack::Release()
{
    if (InterlockedDecrement(&m_lRefCount) > 0)
    {
        return m_lRefCount;
    }

    delete this;
    return 0;
}

⌨️ 快捷键说明

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