⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hxaudply.cpp

📁 symbian 下的helix player源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/************************************************************************
 *  Method:
 *		CHXAudioPlayer::GetStreamCount
 *	Purpose:
 *		Get the number of streams associated with this player.
 */
UINT16 CHXAudioPlayer::GetStreamCount()
{
    return m_pStreamList->GetCount();
}

/************************************************************************
 *  Method:
 *		CHXAudioPlayer::SetStreamInfoResponse
 *	Purpose:
 *		Add the stream info response interface to our list.
 */
STDMETHODIMP CHXAudioPlayer::SetStreamInfoResponse
(
    IHXAudioStreamInfoResponse*    pResponse
)
{
    if (!pResponse || !m_pStreamRespList)
    {
	return HXR_FAILED;
    }

    /* Add to the stream response list */
    LISTPOSITION lPos = m_pStreamRespList->Find(pResponse);
    if (lPos)
    {
	return HXR_FAILED;
    }

    m_pStreamRespList->AddTail((void*) pResponse);
    pResponse->AddRef();         // Released in destructor
    return HXR_OK;
}

/************************************************************************
 *  Method:
 *  CHXAudioPlayer::RemoveStreamInfoResponse
 *  Purpose:
 *  Remove stream info response that was added earlier
 */
STDMETHODIMP CHXAudioPlayer::RemoveStreamInfoResponse
(
    IHXAudioStreamInfoResponse*    pResponse
)
{
    /* Add to the stream response list */
    if (pResponse && m_pStreamRespList)
    {
	LISTPOSITION lPos = m_pStreamRespList->Find(pResponse);
	if (lPos)
	{
	    m_pStreamRespList->RemoveAt(lPos);
	    pResponse->Release();         // Released in destructor
	    return HXR_OK;
	}
    }

    return HXR_FAILED;
}

UINT16
CHXAudioPlayer::NumberOfResumedStreams(void)
{
    UINT16 uNumActive = 0;
    if (m_pStreamList && m_pStreamList->GetCount() > 0)
    {
	CHXAudioStream* pStream = 0;
	CHXSimpleList::Iterator lIter = m_pStreamList->Begin();
	for (; lIter != m_pStreamList->End(); ++lIter)
	{
	    pStream = (CHXAudioStream*) (*lIter);
	    if (pStream->GetState() == E_PLAYING)
	    {
		uNumActive++;
	    }
	}
    }

    return uNumActive;
}

void CHXAudioPlayer::StreamInitialized(CHXAudioStream* pAudioStream)
{
    /* If we are already initialized, it means this stream was added mid-
     * presentation and gogt initialized later. In this case, report arrival
     * of this stream to all StreamInfoResponse objects registered with the
     * player
     */

    if (m_pStreamRespList && m_bInited)
    {
	IHXAudioStreamInfoResponse* pAudioStreamInfoResponse = 0;
	CHXSimpleList::Iterator lIter = m_pStreamRespList->Begin();
	for (; lIter != m_pStreamRespList->End(); ++lIter)
 	{
	    pAudioStreamInfoResponse = (IHXAudioStreamInfoResponse*) (*lIter);
	    pAudioStreamInfoResponse->OnStream(pAudioStream);
	}
    }

    m_bHasStreams = TRUE;
}

ULONG32	CHXAudioPlayer::GetInitialPushdown(BOOL bAtStart /* = FALSE*/)
{
    /* If there are any audio streams, initial pushdown is session's
     * initial pushdown
     */
    if (m_pStreamList->GetCount() > 0)
    {
        ULONG32 ulRet = 
            m_Owner->GetInitialPushdown(bAtStart) + m_ulGranularity;

#ifdef HELIX_FEATURE_MIN_HEAP
        // The MIN_HEAP code seems to need 1 extra block's worth
        // of data to avoid rebuffers during playback. This
        // is a low impact temporary solution that fixes the problem.
        ulRet += m_ulGranularity;
#endif /* HELIX_FEATURE_MIN_HEAP */

        return ulRet;
    }
    else
    {
	return 0;
    }
}

/************************************************************************
 *  Method:
 *      CHXAudioPlayer::OnTimerCallback
 *  Purpose:
 *      Timer callback when implementing fake timeline.
 */
void	CHXAudioPlayer::OnTimerCallback()
{
    ULONG32 ulCurrentTime	= HX_GET_TICKCOUNT();

    m_ulIncreasingTimer		+= CALCULATE_ELAPSED_TICKS(m_ulLastFakeCallbackTime, ulCurrentTime);
    m_ulLastFakeCallbackTime    = ulCurrentTime;

    OnTimeSync(m_ulIncreasingTimer);

    /* A call to timesync may result in stopping
     * playback and we do not want to have any more
     * time syncs.
     */
    /* Put this back in the scheduler.
     */
    if (m_bInited && m_eState == E_PLAYING && !m_ulCallbackID)
    {
	*m_pFakeAudioCBTime += (int) (m_ulGranularity*1000);
	m_ulCallbackID = m_pScheduler->AbsoluteEnter( this,
                                                      *((HXTimeval*)m_pFakeAudioCBTime));
    }
}


void
CHXAudioPlayer::SetLive(BOOL bIsLive)
{
    m_bIsLive = bIsLive;
    CHXAudioStream* s = 0;
    CHXSimpleList::Iterator lIter = m_pStreamList->Begin();
    for (; lIter != m_pStreamList->End(); ++lIter)
    {
	s = (CHXAudioStream*) (*lIter);
	s->SetLive(m_bIsLive);
    }
}

void
CHXAudioPlayer::AudioFormatNowKnown(void)
{
    HX_ASSERT(m_bInited);

    /* When : More than one audio stream created after initialization
     * and one of them already called this function earlier
     */
    if (m_bHasStreams)
    {
	return;
    }

    m_bHasStreams   = TRUE;
    m_bInited	= FALSE;
    /* internal setup */
    HX_RESULT theErr = Setup(m_ulGranularity);
    if (theErr != HXR_OK)
    {
	IHXErrorMessages* pErrorMessage = NULL;
	m_pContext->QueryInterface(IID_IHXErrorMessages, (void**) &pErrorMessage);
	if (pErrorMessage)
	{
	    pErrorMessage->Report(HXLOG_ERR, theErr, 0, NULL, NULL);
	    pErrorMessage->Release();
	}

	return;
    }

    HX_ASSERT(m_bInited);

    /* If we have not yet resumed, it is simply setting the audio
     * player from fake timeline mode to audio timeline mode.
     * Instead if we have already been resumed and are acting as a
     * fake timeline, we need to kinda pause from being a fake timeline to
     * an audio timeline, In this process, we may have to seek the audio
     * device to generate right timesyncs.
     */

    /* If we are already resumed, we need to call resume again internally */
    if (m_bIsResumed)
    {
	StopFakeTimeline();
	Seek(m_ulCurrentTime);
	// only resume the owner if we are in a play state...
	// otherwise owner will be resumed when the player gets resumed.
	if (m_eState == E_PLAYING)
	{
	    m_Owner->Resume();
	}
    }
    else
    {
	/* Cool! HXPlayer will call resume later */
    }
}

void
CHXAudioPlayer::RegisterRealAudioStream(CHXAudioStream* pAudioStream)
{
    if (!m_pRealAudioStreamList)
    {
	m_pRealAudioStreamList = new CHXSimpleList;
    }

    m_pRealAudioStreamList->AddTail((void*) pAudioStream);
    m_bAdjustForRealAudio = TRUE;
}

void
CHXAudioPlayer::UnRegisterRealAudioStream(CHXAudioStream* pAudioStream)
{
    if (!m_pRealAudioStreamList)
    {
	return;
    }

    LISTPOSITION posStream = m_pRealAudioStreamList->Find((void*) pAudioStream);
    if (posStream)
    {
	m_pRealAudioStreamList->RemoveAt(posStream);
    }

    /* Check if there are any more RealAudio Streams registered */
    if (m_pRealAudioStreamList->GetCount() == 0)
    {
	m_bAdjustForRealAudio = FALSE;
    }
}

BOOL
CHXAudioPlayer::IsAudioOnlyTrue(void)
{
    BOOL bRetValue = TRUE;
    IHXPlayer* pPlayer = NULL;
    m_pContext->QueryInterface(IID_IHXPlayer, (void**)&pPlayer);

    HX_ASSERT(pPlayer);

    UINT16 uNumSources = pPlayer->GetSourceCount();

    IUnknown*		pUnknown	= NULL;
    IHXStreamSource*	pStreamSource	= NULL;
    IHXStream*		pStream		= NULL;
    for (UINT16 i=0; bRetValue && i < uNumSources; i++)
    {
	pPlayer->GetSource(i, pUnknown);
	pUnknown->QueryInterface(IID_IHXStreamSource,
				 (void**) &pStreamSource);
	HX_RELEASE(pUnknown);
	HX_ASSERT(pStreamSource);

	UINT16 uNumStreams = pStreamSource->GetStreamCount();
	for (UINT16 j=0; bRetValue && j < uNumStreams; j++)
	{
	    pStreamSource->GetStream(j, pUnknown);
	    pUnknown->QueryInterface(IID_IHXStream,
				     (void**) &pStream);
	    HX_RELEASE(pUnknown);
	    HX_ASSERT(pStream);

	    IHXValues* pHeader = pStream->GetHeader();
	    if (pHeader)
	    {
		if (!IsThisAudioStream(pHeader))
		{
		    bRetValue = FALSE;
		}
		pHeader->Release();
	    }

	    pStream->Release();
	}

	HX_RELEASE(pStreamSource);
    }

    HX_RELEASE(pPlayer);

    return bRetValue;
}

BOOL
CHXAudioPlayer::IsThisAudioStream(IHXValues* pHeader)
{
    CHXSimpleList::Iterator ndxStream = m_pStreamList->Begin();
    for(; ndxStream != m_pStreamList->End(); ++ndxStream)
    {
	CHXAudioStream* pAudioStream = (CHXAudioStream*) (*ndxStream);
	IHXValues* pAudioHeader = pAudioStream->GetStreamInfo();
	if (pAudioHeader == pHeader)
	{
	    HX_RELEASE(pAudioHeader);
	    return TRUE;
	}

	HX_RELEASE(pAudioHeader);
    }

    return FALSE;
}

void
CHXAudioPlayer::AdjustForRealAudio()
{
    UINT32 ulCurrentDeviceTime = m_ulCurrentTime;

#if defined(HELIX_FEATURE_AUDIO_INACCURATESAMPLING)
    if (m_bAdjustForRealAudio)
    {
	CHXAudioStream* pAudioStream = NULL;

        // Only use a playing audio stream for time adjustment:
        for (CHXSimpleList::Iterator streamIterator = m_pRealAudioStreamList->Begin();
             streamIterator != m_pRealAudioStreamList->End();
             ++streamIterator)
        {
            if ( ((CHXAudioStream*) (*streamIterator))->GetState() == E_PLAYING)
            {
                pAudioStream = (CHXAudioStream*) *streamIterator;
                break;
            }
        }

        if (pAudioStream)
        {
            UINT32 ulAdjustedTime = 0L;

            double dBytesPlayed = m_Owner->GetNumBytesPlayed();
            if (HXR_OK == pAudioStream->ConvertCurrentTime( dBytesPlayed,
                                                            m_ulCurrentTime,
                                                            ulAdjustedTime))
            {
                UINT32 ulTickCount = HX_GET_TICKCOUNT();
                /* This is to avoid stall at end of the presentation */
                /* The RA stream may have a duration of say 30 seconds
                 * but the actual data may be only for 29.9
                 * seconds. In this case, audio stream will never
                 * return time more than 29.9 seconds and we will get
                 * stalled.  To avoid this, we wait for atmost
                 * MAX_WAIT_AT_SAME_TIME (== max granularity+50 ms) at
                 * the same timestamp. If we find that we are pushing
                 * more data in the audio device but the audio stream
                 * is reporting the same time for the past
                 * MAX_WAIT_AT_SAME_TIME, we increment our timestamp
                 * by the real time elapsed since the last update.
                 * This code will only trigger when we are near the
                 * end of presentation.
                 */
                if (m_bTimeReturned &&
                    ulAdjustedTime <= m_ulLastCurrentTimeReturned &&
                    ulCurrentDeviceTime > m_ulLastDeviceTimeAdjusted &&
                    ulCurrentDeviceTime - m_ulLastDeviceTimeAdjusted > MAX_WAIT_AT_SAME_TIME)
                {
                    UINT32 ulElapsedTime = CALCULATE_ELAPSED_TICKS(m_ulTimeAdjustDoneAt,
                                                                   ulTickCount);
                    if (ulElapsedTime >= MAX_WAIT_AT_SAME_TIME)
                    {
                        m_ulCurrentTime = m_ulLastCurrentTimeReturned + ulElapsedTime;
                        m_ulTimeAdjustDoneAt	    = ulTickCount;
                        m_ulLastDeviceTimeAdjusted  = ulCurrentDeviceTime;
                    }
                    else
                    {
                        m_ulCurrentTime = ulAdjustedTime;
                    }
                }
                else
                {
                    m_ulTimeAdjustDoneAt = ulTickCount;
                    m_ulCurrentTime      = ulAdjustedTime;
                }
            }
        }
    }
#endif /* HELIX_FEATURE_AUDIO_INACCURATESAMPLING */

    /* Never go back in time */
    if (!m_bTimeReturned)
    {
	m_bTimeReturned		    = TRUE;
	m_ulLastCurrentTimeReturned = m_ulCurrentTime;
	m_ulTimeAdjustDoneAt	    = HX_GET_TICKCOUNT();
	m_ulLastDeviceTimeAdjusted  = ulCurrentDeviceTime;
    }
    else if (m_ulCurrentTime <= m_ulLastCurrentTimeReturned)
    {
	m_ulCurrentTime = m_ulLastCurrentTimeReturned;
    }
    else
    {
	m_ulLastDeviceTimeAdjusted  = ulCurrentDeviceTime;
	m_ulLastCurrentTimeReturned = m_ulCurrentTime;
    }

}

HX_RESULT
CHXAudioPlayer::ResumeFakeTimeline(void)
{
    HX_RESULT	rc = HXR_OK;

    HX_ASSERT(!m_bHasStreams);

    HXTimeval lTime = m_pScheduler->GetCurrentSchedulerTime();

    m_pFakeAudioCBTime->tv_sec = lTime.tv_sec;
    m_pFakeAudioCBTime->tv_usec = lTime.tv_usec;

    m_ulIncreasingTimer = m_ulCurrentTime;
    m_ulLastFakeCallbackTime = HX_GET_TICKCOUNT();

    *m_pFakeAudioCBTime += (int) (m_ulGranularity*1000);

    m_ulCallbackID = m_pScheduler->AbsoluteEnter(this,
                                                 *((HXTimeval*) m_pFakeAudioCBTime));

    return rc;
}

HX_RESULT CHXAudioPlayer::Func()
{
    m_ulCallbackID = 0;
    OnTimerCallback();
    return HXR_OK;
}


HX_RESULT CHXAudioPlayer::StopFakeTimeline(void)
{
    HX_RESULT	rc = HXR_OK;

    if(m_ulCallbackID && m_pScheduler)
    {
        m_pScheduler->Remove(m_ulCallbackID);
    }

    return rc;
}

double
CHXAudioPlayer::NumberOfBytesWritten()
{
    return m_Owner->NumberOfBytesWritten();
}

double
CHXAudioPlayer::ConvertMsToBytes(UINT32 ulTime)
{
    return m_Owner->ConvertMsToBytes(ulTime);
}

void
CHXAudioPlayer::UpdateStreamLastWriteTime()
{
    // Make each stream seek, too, since they own the resampling buffers.
    CHXAudioStream* s = 0;
    CHXSimpleList::Iterator lIter = m_pStreamList->Begin();
    for (; lIter != m_pStreamList->End(); ++lIter)
    {
	s = (CHXAudioStream*) (*lIter);
	s->UpdateStreamLastWriteTime();
    }
}

void
CHXAudioPlayer::SaveLastNMilliSeconds(BOOL bSave, UINT32 ulNMilliSeconds)
{
    // Make each stream seek, too, since they own the resampling buffers.
    CHXAudioStream* s = 0;
    CHXSimpleList::Iterator lIter = m_pStreamList->Begin();
    for (; lIter != m_pStreamList->End(); ++lIter)
    {
	s = (CHXAudioStream*) (*lIter);
	s->SaveLastNMilliSeconds(bSave, ulNMilliSeconds);
    }
}

void
CHXAudioPlayer::RewindPlayer(UINT32 ulTimeToRewind)
{
    if (m_pStreamList->GetCount() == 0	|| !m_bCanBeRewound)
    {
	return;
    }

    // Make each stream seek, too, since they own the resampling buffers.
    CHXAudioStream* s = 0;
    CHXSimpleList::Iterator lIter = m_pStreamList->Begin();
    for (; lIter != m_pStreamList->End(); ++lIter)
    {
	s = (CHXAudioStream*) (*lIter);
	s->RewindStream(ulTimeToRewind);
    }

    HX_ASSERT(m_llLastWriteTime >= ulTimeToRewind);
    if (m_llLastWriteTime >= ulTimeToRewind)
    {
	m_llLastWriteTime -= ulTimeToRewind;
    }
}

HX_RESULT
CHXAudioPlayer::ProcessAudioHook(PROCESS_ACTION action,
				 IHXAudioHook* pAudioHook)
{
    return HXR_OK;
}

STDMETHODIMP CHXAudioPlayer::SetError( HX_RESULT theErr )
{
    if (theErr != HXR_OK)
    {
	IHXErrorMessages* pErrorMessage = NULL;
	m_pContext->QueryInterface(IID_IHXErrorMessages, (void**) &pErrorMessage);
	if (pErrorMessage)
	{
	    pErrorMessage->Report(HXLOG_ERR, theErr, 0, NULL, NULL);
	    pErrorMessage->Release();
	}
    }
    return HXR_OK;
}

⌨️ 快捷键说明

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