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

📄 hxaudses.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
            }

	    pSessionBuf = m_pSessionBuf->GetBuffer();

	    // Zero session buffer.
	    //memset(pSessionBuf, 0, HX_SAFESIZE_T(m_ulBytesPerGran));

	    // Get each player
	    pPlayer = 0;
	    CHXSimpleList::Iterator lIter = m_pPlayerList->Begin();
	    for (; lIter != m_pPlayerList->End(); ++lIter)
	    {
		BOOL bStalled = FALSE;
		pPlayer = (CHXAudioPlayer*) (*lIter);
		if (pPlayer->GetStreamCount() == 0 ||
		    pPlayer->IsDonePlayback() ||
		    pPlayer->GetState() != E_PLAYING)
		{
		    continue;
		}

		bAtLeastOnePlayerActive = TRUE;

		if (m_pPlayerList->GetCount() == 1)
		{
		    pMixIHXBuffer = m_pSessionBuf;
		    bufType = BUFFER_SESSION;
		}
		else
		{
		    if (!m_pPlayerBuf)
		    {
			m_pPlayerBuf = new CHXBuffer;
			m_pPlayerBuf->AddRef();
		    }

		    m_pPlayerBuf->SetSize(m_ulBytesPerGran);

		    pPlayerBuf = m_pPlayerBuf->GetBuffer();
		    // Zero play buffer.
//		    memset(pPlayerBuf, 0, HX_SAFESIZE_T(m_ulBytesPerGran));
		    pMixIHXBuffer = m_pPlayerBuf;
		    bufType = BUFFER_PLAYER;
		}

		pMixBuffer = pMixIHXBuffer->GetBuffer();
		BOOL bIsMixBufferDirty = FALSE;
		BOOL bMayNeedToRollbackTimestamp = FALSE;

		if (pPlayer->GetState() == E_PLAYING)
		{
		    UINT32  ulBufTime = 0;
		    // Get each stream associated with this player
		    pStreamList = pPlayer->GetStreamList();
		    CHXSimpleList::Iterator lIter = pStreamList->Begin();
		    for (; lIter != pStreamList->End(); ++lIter)
		    {
		    	pStream = (CHXAudioStream*) (*lIter);
			pStream->m_bMayNeedToRollbackTimestamp = FALSE;

			// don't mix paused audio streams
			if (pStream->GetState() != E_PAUSED)
			{
			    theErr = pStream->MixIntoBuffer( pMixBuffer, m_ulBytesPerGran, ulBufTime, bIsMixBufferDirty);

			    // so as not to trigger ReallyNeedData
			    // since one of the streams internal m_llLastwritetime
			    // has been updated even though this flag is set to FALSE.
#if 0
                            if (!bIsMixBufferDirty &&
                                (theErr == HXR_OK || theErr == HXR_NO_DATA))
                            {
                                bIsMixBufferDirty = TRUE;
                                ::memset(pMixBuffer, 0, HX_SAFESIZE_T(m_ulBytesPerGran));
                            }
#endif

                            if (theErr == HXR_NO_DATA)
                            {
                                pStream->m_bMayNeedToRollbackTimestamp = TRUE;
                                bMayNeedToRollbackTimestamp = TRUE;
                                theErr = HXR_OK;
                                continue;
                            }

                            if (theErr == HXR_FAIL)
                            {
                                theErr = HXR_OK;
                                goto exit;
                            }

                            if (theErr == HXR_OUTOFMEMORY)
                            {
                                goto exit;
                            }

                            if (theErr == HXR_WOULD_BLOCK)
                            {
#ifdef _RAHULDEBUG
                                {
                                    char str[255]; /* Flawfinder: ignore */
                                    ::sprintf(str, "Num to be pushed remaining: %lu\n", m_uNumToBePushed); /* Flawfinder: ignore */
                                    OutputDebugString(str);
                                }
#endif

                                if (bMayNeedToRollbackTimestamp)
                                {
                                    bMayNeedToRollbackTimestamp = FALSE;
                                    lIter = pStreamList->Begin();
                                    for (; lIter != pStreamList->End(); ++lIter)
                                    {
                                        pStream = (CHXAudioStream*) (*lIter);
                                        if (pStream->m_bMayNeedToRollbackTimestamp)
                                        {
                                            pStream->m_bMayNeedToRollbackTimestamp = FALSE;
                                            pStream->RollBackTimestamp();
                                        }
                                    }
                                }

                                goto handlewouldblock;
                            }
                        }

                        if (pPlayer->GetState() != E_PLAYING)
                        {
                            /* We should keep the last buffer around and the last stream
                             * to be mixed again...TBD XXX Rahul
                             */
                            //pPlayer->SetLastMixedBuffer(pMixBuffer, pStream);
                            bStalled = TRUE;
                            break;
                        }
                    }

                    /* This pause may have happended due to ondrynotification */
                    if (m_bPaused || m_bStoppedDuringPause)
                    {
                        /* This would happen ONLY IF THERE IS ONE AUDIO PLAYER
                         * and that has been paused. So simply break
                         */
                        goto exit;
                        //break;
                    }

                    /* hmmm... looks like there are more than one audio player.
                     * continue with the next one
                     */
                    if (bStalled)
                    {
                        continue;
                    }

                    /* If the mixer buffer was not used, make sure it is initialized
                     * to silence since we pass it to post process hooks
                     */
                    if (!bIsMixBufferDirty)
                    {
//{FILE* f1 = ::fopen("e:\\audioses.txt", "a+"); ::fprintf(f1, "%lu\t%p\tsilence in mix buffer\n", HX_GET_BETTERTICKCOUNT(), this);::fclose(f1);}
                        ::memset(pMixBuffer, 0, HX_SAFESIZE_T(m_ulBytesPerGran));
                    }

#if defined(HELIX_FEATURE_VOLUME) && defined(HELIX_FEATURE_MIXER)
                    // Apply Player volume to buffer; do this before we call
                    // the post mix hooks.
                    uPlayerVolume = pPlayer->GetVolume();

                    if (uPlayerVolume != 100 && bIsMixBufferDirty)
                    {
                        CHXMixer::ApplyVolume(pMixBuffer, m_ulBytesPerGran, uPlayerVolume, m_DeviceFmt.uBitsPerSample);
                    }
#endif /* HELIX_FEATURE_VOLUME && HELIX_FEATURE_MIXER */

                    // Give data to this AudioPlayer's post mix hooks
                    // (do they want 8 or 16 bit?)
                    BOOL bChanged = FALSE;
                    ProcessPostMixHooks(pPlayer, pMixIHXBuffer, &bDisableWrite, ulBufTime, bChanged);

                    /*
                     * If the mixer buffer changed (because of a post mix hook)
                     * make sure to point the player/session buffer to this
                     * modified buffer
                     */
                    if (bChanged)
                    {
                        pMixBuffer = pMixIHXBuffer->GetBuffer();

                        if (bufType == BUFFER_PLAYER)
                        {
                            m_pPlayerBuf = pMixIHXBuffer;
                            pPlayerBuf = pMixIHXBuffer->GetBuffer();
                        }
                        else
                        {
                            m_pSessionBuf = pMixIHXBuffer;
                            pSessionBuf = pMixIHXBuffer->GetBuffer();
                        }
                    }
                }

#if defined(HELIX_FEATURE_MIXER)
                // Don't mix if volume is 0.
                // Don't mix if this player has disabled device write.
                // Don't mix if there is only one player since we would have
                // written data into session buf instead of player buffer
                if (m_pPlayerList->GetCount() > 1 && uPlayerVolume > 0 && !bDisableWrite)
                {
                    /* We always set a volume of 100 since we have already applied volume
                     * to player buffer
                     */
                    CHXMixer::MixBuffer( pPlayerBuf, pSessionBuf,
                                m_ulBytesPerGran, FALSE, 100, m_DeviceFmt.uBitsPerSample, m_bSessionBufferDirty);
                }
#endif /* HELIX_FEATURE_MIXER */

                pPlayer->UpdateLastWriteTime(m_ulGranularity);
            }

            if (!bAtLeastOnePlayerActive)
            {
                goto exit;
            }

            /* did we ever write to the session buffer ? */
            if (m_pPlayerList->GetCount() > 1 && !m_bSessionBufferDirty)
            {
//{FILE* f1 = ::fopen("e:\\audioses.txt", "a+"); ::fprintf(f1, "%lu\t%p\tsilence in session buffer\n", HX_GET_BETTERTICKCOUNT(), this);::fclose(f1);}
                ::memset(pSessionBuf, 0, HX_SAFESIZE_T(m_ulBytesPerGran));
            }

            // This increments with each buffered played.
            m_dBufEndTime   += m_dGranularity;

            // Set the session buffer to the IRMA buffer.
            audioData.pData       = m_pSessionBuf;
            audioData.ulAudioTime = (ULONG32)m_dBufEndTime;

            if (m_pAudioDev && !m_bDisableWrite)
            {
                /* are we dealing with a f*%$'ed up sound card */
                if ((m_BeforeHookDeviceFmt.uChannels == 1 && m_DeviceFmt.uChannels == 2)||
                    m_BeforeHookDeviceFmt.uBitsPerSample == 8)
                {
                    ConvertTo8BitAndOrMono(&audioData);
                }

                if (m_pFinalHook && m_bUseFinalHook)
                {
                    if (HXR_OK == ProcessAudioHook(ACTION_CHECK, m_pFinalHook))
                    {
                        m_pOutDataPtr->pData        = NULL;
                        m_pOutDataPtr->ulAudioTime          = audioData.ulAudioTime;
                        m_pOutDataPtr->uAudioStreamType = audioData.uAudioStreamType;

                        m_pFinalHook->OnBuffer(&audioData, m_pOutDataPtr);

                        HX_ASSERT(m_pOutDataPtr->pData);
                        if (m_pOutDataPtr->pData)
                        {
                            HX_RELEASE(audioData.pData);
                            m_pSessionBuf = audioData.pData = m_pOutDataPtr->pData;
                        }
                        else
                        {
                            /* This is a screwed up Hook. Disable it */
                            m_bUseFinalHook = FALSE;
                        }
                    }
                }

                if (m_pHookList)
                {
                    ProcessHooks(&audioData);
                }

                ulNumBytesWritten    = audioData.pData->GetSize();
                if (HXR_OK == ProcessAudioDevice(ACTION_CHECK, m_pAudioDev))
                {
                    // Write session audio data to device.
                    theErr = m_pAudioDev->Write(&audioData);
                    if( theErr == HXR_OUTOFMEMORY )
                    {
                        goto exit;
                    }
                }

                if (theErr == HXR_WOULD_BLOCK)
                {
                    HXAudioData* pAudioData     = new HXAudioData;
                    pAudioData->pData           = audioData.pData;
                    pAudioData->pData->AddRef();
                    pAudioData->ulAudioTime     = audioData.ulAudioTime;
                    pAudioData->uAudioStreamType= audioData.uAudioStreamType;

                    // Create auxiliary buffer list, if one is not already created
                    if (!m_pAuxiliaryAudioBuffers)
                    {
                        m_pAuxiliaryAudioBuffers = new CHXSimpleList;
                    }
                    if( NULL == m_pAuxiliaryAudioBuffers->AddTail(pAudioData) )
                    {
                        theErr = HXR_OUTOFMEMORY;
                        goto exit;
                    }

                    HX_RELEASE(m_pSessionBuf);
                }
                /* Any error from audio device other than memory error is
                 * returned as HXR_AUDIO_DRIVER
                 */
                if (theErr != HXR_OK && theErr != HXR_WOULD_BLOCK &&
                    theErr != HXR_OUTOFMEMORY)
                {
                    theErr = HXR_AUDIO_DRIVER;
                }
            }

            if (!theErr)
            {
                m_ulBlocksWritten++;
                m_dNumBytesWritten  += ulNumBytesWritten;
            }

            // So this function is good in theory, but in practice we find in
            // heap-optimized mode it is not necessary, and it leads to
            // unnecessary heap fragmentation.
#if !defined(HELIX_CONFIG_MIN_HEAP_FRAG)
            theErr = CheckForBufferReuse();
#endif
        }  // for loop
    }     //  end if we have audio streams

handlewouldblock:
    // mask this error
    if (theErr == HXR_WOULD_BLOCK)
    {
        theErr = HXR_OK;
    }

    // If we do not have audio.. OR  if we do have audio but
    // we have disabled writing to the device, then we need to
    // fake the timeline.
    if (!theErr && !m_ulCallbackID && (!m_bHasStreams || m_bDisableWrite))
    {
        if (m_bFirstPlayAudio)
        {
            // First time thru, we initialize callback time.
            HXTimeval lTime = m_pScheduler->GetCurrentSchedulerTime();
            m_pFakeAudioCBTime->tv_sec = lTime.tv_sec;
            m_pFakeAudioCBTime->tv_usec = lTime.tv_usec;

            m_ulIncreasingTimer = 0;
            m_ulLastFakeCallbackTime    = HX_GET_TICKCOUNT();

            *m_pFakeAudioCBTime += (int) (m_ulGranularity*1000);
        }
        m_bFakeAudioTimeline =  TRUE;
        m_ulCallbackID = m_pScheduler->RelativeEnter( this, m_ulGranularity);
        if (m_bFirstPlayAudio)
        {
            OnTimeSync(m_ulIncreasingTimer);
        }
    }
    else if (!theErr && !m_ulCallbackID && m_bHasStreams && !m_bDisableWrite)
    {
        m_bFakeAudioTimeline =  FALSE;
        m_ulCallbackID = m_pScheduler->RelativeEnter(this, m_ulGranularity*9/10);

#if 0	// XXX HP don't send OnTimeSync() untill we resume the audio device
	// the following logic caused OnTimeSync() sent to video renderer before the audio
	// timeline is started after seeking, as a consequence, the A/V could be out of
	// sync, video could be frozen for short period time in order to wait the audio
	// timeline to catch up
        if (m_bFirstPlayAudio)
        {
            OnTimeSync(m_ulIncreasingTimer);
        }
#endif
    }

exit:
    m_bInPlayAudio      = FALSE;

    // can only happen in multi-player pause/resume/stop case
    if (m_bDeferActualResume && theErr != HXR_OUTOFMEMORY)
    {
        m_bDeferActualResume = FALSE;
        theErr = ActualResume();
    }

    m_bFirstPlayAudio   = FALSE;

    m_pMutex->Unlock();

    return theErr;
}

HX_RESULT
CHXAudioSession::CheckForBufferReuse()
{
    if (m_pSessionBuf)
    {
        m_pSessionBuf->AddRef();
        if (m_pSessionBuf->Release() > 1)
        {
            /*
             * Cannot use this buffer the next time
             * release our reference and  create a new one
             */
            m_pSessionBuf->Release();

            m_pSessionBuf = (IHXBuffer*) new CHXBuffer;
            if( m_pSessionBuf )

⌨️ 快捷键说明

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