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

📄 hxaudstr_new.cpp

📁 linux下的一款播放器
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    HX_DELETE(m_pAvailableBuffers);    // Delete all entries in the audio data list    FlushBuffers();    HX_DELETE(m_pDataList);    HX_DELETE(m_pInstantaneousList);    CleanupRAByToTs();    HX_DELETE(m_pRAByToTsInList);    HX_DELETE(m_pRAByToTsAdjustedList);    HX_DELETE(m_pMixEngine);    m_bGotHooks = FALSE;    m_llLastWriteTime = 0;    m_ulTSRollOver = 0;    HX_RELEASE(m_pValues);#if defined(HELIX_FEATURE_AUDIO_PREMIXHOOK)    // Delete all entries in the pre-mix hook list.    if ( m_PreMixHookMap.GetCount() > 0)    {        HXAudioHookInfo* h = 0;        CHXMapPtrToPtr::Iterator lIter = m_PreMixHookMap.Begin();        for (; lIter != m_PreMixHookMap.End(); ++lIter)        {            h = (HXAudioHookInfo*) (*lIter);	    ProcessAudioHook(ACTION_REMOVE, h->pHook);            h->pHook->Release();            delete h;        }		m_PreMixHookMap.RemoveAll();    }#endif /* HELIX_FEATURE_AUDIO_PREMIXHOOK */#ifdef HELIX_FEATURE_VOLUME    if( m_pStreamVolume )    {        m_pStreamVolume->RemoveAdviseSink(this);        m_pStreamVolume->Release();        m_pStreamVolume=NULL;    }#endif            HX_DELETE(m_pInDataPtr);    HX_DELETE(m_pOutDataPtr);    if (m_DryNotificationMap && m_DryNotificationMap->GetCount() > 0)    {        IHXDryNotification* pDryNotification = 0;        CHXMapPtrToPtr::Iterator lIter = m_DryNotificationMap->Begin();        for (; lIter != m_DryNotificationMap->End(); ++lIter)        {            pDryNotification = (IHXDryNotification*) (*lIter);            pDryNotification->Release();        }		m_DryNotificationMap->RemoveAll();    }    HX_RELEASE(m_pCrossFadeStream);    HX_RELEASE(m_pCommonClassFactory);#if defined(HELIX_FEATURE_PREFERENCES)    HX_RELEASE(m_pPreferences);#endif /* HELIX_FEATURE_PREFERENCES */    HX_RELEASE(m_Owner);    return;}HX_RESULTCHXAudioStream::ProcessAudioHook(PROCESS_ACTION action, 				 IHXAudioHook* pAudioHook){    return HXR_OK;}/************************************************************************ *  Method: *		IHXAudioStream::InitHooks *	Purpose: *	Init any pre-mix hooks. Return TRUE if hooks exist else return *	FALSE. */void CHXAudioStream::InitHooks(){#if defined(HELIX_FEATURE_AUDIO_PREMIXHOOK)    /* Iterate thru the hook list and call the hook's OnInit().     * If any of the hooks have disabled write set to TRUE, then     * we will let this override any set to FALSE.     */    if ( m_PreMixHookMap.GetCount() > 0 )    {	HXAudioHookInfo* h = 0;	CHXMapPtrToPtr::Iterator lIter = m_PreMixHookMap.Begin();	for (; lIter != m_PreMixHookMap.End(); ++lIter)	{	    h = (HXAudioHookInfo*) (*lIter);	    if (h->bIgnoreAudioData ||		HXR_OK == ProcessAudioHook(ACTION_CHECK, h->pHook))	    {		h->pHook->OnInit( &m_AudioFmt );	    }	}    }#endif /* HELIX_FEATURE_AUDIO_PREMIXHOOK */    m_bHooksInitialized = TRUE;}/************************************************************************ *  Method: *		IHXAudioStream::ProcessHooks *	Purpose: */HX_RESULT CHXAudioStream::ProcessHooks(     HXAudioData*	pInData,    HXAudioData*	pOutData){    HX_RESULT theErr = HXR_OK;#if defined(HELIX_FEATURE_AUDIO_PREMIXHOOK)    m_pInDataPtr->pData		= pInData->pData;    m_pInDataPtr->pData->AddRef();    m_pInDataPtr->ulAudioTime	= pInData->ulAudioTime;        m_pOutDataPtr->pData	= NULL;    m_pOutDataPtr->ulAudioTime	= pInData->ulAudioTime;    m_pInDataPtr->uAudioStreamType    = pInData->uAudioStreamType;    m_pOutDataPtr->uAudioStreamType   = pInData->uAudioStreamType;    if ( m_PreMixHookMap.GetCount() > 0 )    {	HXAudioHookInfo* pPreMixHookInfo = 0;	CHXMapPtrToPtr::Iterator lIter = m_PreMixHookMap.Begin();	for (; !theErr && lIter != m_PreMixHookMap.End(); ++lIter)	{	    pPreMixHookInfo = (HXAudioHookInfo*) (*lIter);	    if (HXR_OK == ProcessAudioHook(ACTION_CHECK, pPreMixHookInfo->pHook))	    {                // XXXHP, disable hooks when it doesn't support multi-channel                if (m_AudioFmt.uChannels <= 2 || pPreMixHookInfo->bMultiChannelSupport)                {		    theErr = pPreMixHookInfo->pHook->OnBuffer( m_pInDataPtr, m_pOutDataPtr);		    /* Check to see if renderer changed the buffer. If so, then		     * make this output as input to the next Hook.		     */		    if (!theErr && m_pOutDataPtr->pData)		    {		        m_pInDataPtr->pData->Release();		        m_pInDataPtr->pData	    = m_pOutDataPtr->pData;		        m_pInDataPtr->ulAudioTime   = m_pOutDataPtr->ulAudioTime;		        m_pOutDataPtr->pData	= 0;		    }                }	    }	    else if (pPreMixHookInfo->bIgnoreAudioData)	    {		IHXBuffer* pTempBuf = m_pInDataPtr->pData;		m_pInDataPtr->pData = NULL;		theErr = pPreMixHookInfo->pHook->OnBuffer( m_pInDataPtr, m_pOutDataPtr);		m_pInDataPtr->pData = pTempBuf;	    }	}    }    /* Final output is always in InDataPtr*/    pOutData->pData		= m_pInDataPtr->pData;    pOutData->ulAudioTime	= m_pInDataPtr->ulAudioTime;    pOutData->uAudioStreamType  = m_pInDataPtr->uAudioStreamType;#endif /* HELIX_FEATURE_AUDIO_PREMIXHOOK */    return theErr;}/************************************************************************ *  Method: *	CHXAudioStream::MixIntoBuffer *  Purpose: *	Mix stream data into this pPlayerBuf. * */HX_RESULT CHXAudioStream::MixIntoBuffer(    UCHAR*   pPlayerBuf,    ULONG32  ulBufSize,    ULONG32& ulBufTime,    BOOL&    bIsMixBufferDirty,    BOOL     bGetCrossFadeData){    HX_RESULT res = HXR_OK ;    if (!m_bInited)    {	return HXR_NOT_INITIALIZED;    }    // bGetCrossFadeData should now be a thing of the past.    HX_ASSERT(!bGetCrossFadeData) ;//{FILE* f1 = ::fopen("c:\\temp\\rasync.txt", "a+"); ::fprintf(f1, "Call MixIntoBuffer: %lu\n", m_ulLastWriteTime);::fclose(f1);}    /* If this is a *FROM* stream, we may have already mixed     * data during cross-fade with *TO* stream     */    // update the outside world's sense of time.    // XXX wschildbach: how to account for rollover?    INT64 llNextMixTime = m_pMixEngine->GetNextMixTimeMillis();    UINT32 ulLastWriteTime = INT64_TO_UINT32(llNextMixTime - CAST_TO_INT64(m_ulTSRollOver) * CAST_TO_INT64(MAX_UINT32));    // In a surestream situation, ulBufTime is 0 on the first stream, and a time corresponding    // to the granularity in the second stream. I don't know what this code tries to do.    // XXX wschildbach    if (ulBufTime < ulLastWriteTime)    {	ulBufTime = ulLastWriteTime;    }    /* If there are any DryNotifications and the data list is empty     * we need to notify them so that they can write more data.     *     * If EnoughDataAvailable() returns FALSE, it will have updated     * the input values to point at where the buffer needs to be filled.     */    INT64  llStartMix, llEndMix;    m_pMixEngine->GetMixRange(ulBufSize, llStartMix, llEndMix) ;    UINT32 nSamplesNeeded = INT64_TO_UINT32(llEndMix - llStartMix) ; // always fits into UINT32    if (!EnoughDataAvailable(llStartMix, nSamplesNeeded))    {        // Check if the audio device is really empty ("ReallyNeedData") or if we are        // just over-eagerly filling up the pre-roll. If the latter is the case,        // return HXR_WOULD_BLOCK	if (!bIsMixBufferDirty && !m_Owner->m_Owner->ReallyNeedData())	{	    return HXR_WOULD_BLOCK;	}        // renderer might pause playback if has no packets	if (m_DryNotificationMap->GetCount() > 0)	{	    IHXDryNotification* pDryNotification = 0;	    CHXMapPtrToPtr::Iterator lIter = m_DryNotificationMap->Begin();	    for (; lIter != m_DryNotificationMap->End(); ++lIter)	    {		pDryNotification = (IHXDryNotification*) (*lIter);                UINT64 streamTime = Samples2Ms(llStartMix, &m_AudioFmt) -                    CAST_TO_INT64(m_ulTSRollOver)*CAST_TO_INT64(MAX_UINT32);		HX_RESULT theErr = pDryNotification->OnDryNotification( INT64_TO_UINT32(streamTime),                                                     INT64_TO_UINT32(Samples2Ms(nSamplesNeeded, &m_AudioFmt))) ;                if( theErr == HXR_OUTOFMEMORY )                {                    return theErr;                }	    }	    if (m_Owner->GetState() != E_PLAYING)	    {		return HXR_OK;	    }	}    }    // XXX wschildbach what does this do?    m_Owner->DataInAudioDevice(TRUE);    /*    {FILE *f1 = fopen("c:\\temp\\mix.txt","a+");     fprintf(f1,"\ncall MixIntoBuffer(%I64d, id=%ld)\n",(INT64)mixTimeInSamples,m_pMixEngine - (HXAudioSvcMixEngine*)0xdde198);     fclose(f1);}*/    // this call does all the mixing.    res = m_pMixEngine->MixIntoBuffer(pPlayerBuf, ulBufSize, bIsMixBufferDirty) ;    if( m_wLastError == HXR_OUTOFMEMORY )    {        return m_wLastError;    }     if (FAILED(res))        return res ; #if defined(HELIX_FEATURE_AUDIO_INACCURATESAMPLING)    if( m_bRealAudioStream )        MapFudgedTimestamps();#endif            // update the inside world's sense of time.    m_llLastWriteTime = m_pMixEngine->GetNextMixTimeMillis() ;#if 0    {FILE *f = fopen("c:\\temp\\incoming.txt","a+");    fprintf(f,"mix %ld %I64d\n",ulBufTime,m_llLastWriteTime);fclose(f);}#endif    return HXR_OK;}/* * This is the callback function that m_pMixEngine->MixIntoBuffer() will call to read * new samples. */BOOL CHXAudioStream::ConvertIntoBuffer(tAudioSample* buffer, UINT32 nSamples, INT64 llStartTimeInSamples){    HXAudioInfo*    pInfo           = 0;    LISTPOSITION    lp              = 0;    INT32           nBytesPerSample = m_AudioFmt.uBitsPerSample>>3 ;    BOOL            didMix          = FALSE ; // set to TRUE if we have packets in this time range    BOOL            bPacketsAfterRange = FALSE;    /*    {FILE *f1 = fopen("c:\\temp\\mix.txt","a+");     fprintf(f1," ConvertIntoBuffer(%I64d - %I64d, len=%ld)\n",(INT64)llStartTimeInSamples,(INT64)llStartTimeInSamples+nSamples,nSamples);     fclose(f1);}     */    // there are two lists of packets here: timed audio and instantaneous audio.    // We only look into the list for timed buffers -- Instantaneoue audio is ignored    // (it never properly worked anyway, so support is discontinued).    /* remove old packets. Old packets are packets that have an end time that is before       our current mix time. */    lp = m_pDataList->GetHeadPosition();    while( lp )    {	LISTPOSITION lastlp = lp;	pInfo	= (HXAudioInfo*) m_pDataList->GetNext(lp);	if (pInfo->llEndTimeInSamples < llStartTimeInSamples)	{            /*    {FILE *f1 = fopen("c:\\temp\\mix.txt","a+");     fprintf(f1,"-- reaping packet (%I64d,%I64d)\n",         pInfo->llStartTimeInSamples,pInfo->llEndTimeInSamples);     fclose(f1);}     */	    FreeInfo(pInfo);	    m_pDataList->RemoveAt(lastlp);            if( m_wLastError == HXR_OUTOFMEMORY )            {                return FALSE;            }	}        else // if monotonous and non-overlapping            break ;    }    // now go through the entire list of packets, and look for overlap with the    // convert buffer. Any packet with overlap will be at least partially converted    // into the buffer.    // If packets overlap, one packet will then take precedence over another -- not    // much we can do about that.    lp = m_pDataList->GetHeadPosition();    while( lp )    {	pInfo	= (HXAudioInfo*) m_pDataList->GetNext(lp);	if (pInfo->llStartTimeInSamples < llStartTimeInSamples + nSamples &&            pInfo->llEndTimeInSamples > llStartTimeInSamples)        {            // This packet has some overlap with what we are converting.            // if this is the first packet to be mixed into this buffer,            // silence out the entire buffer. This is inefficient, but safe            if (!didMix)                CAudioSvcSampleConverter::silence(buffer, nSamples) ;            didMix = TRUE ;            INT32 nMixbufferOffset = 0;            INT32 pastPacketStart = INT64_TO_INT32(llStartTimeInSamples - pInfo->llStartTimeInSamples) ;            if (pastPacketStart < 0)            {                nMixbufferOffset = -pastPacketStart;                pastPacketStart = 0 ;            }            INT32 nn = Bytes2Samples(pInfo->pBuffer->GetSize(), &m_AudioFmt) ;            INT32 nSamplesToUse = nn - pastPacketStart;            if (nSamplesToUse > (INT32)(nSamples - nMixbufferOffset))                nSamplesToUse = nSamples - nMixbufferOffset;            const unsigned char *cvtin = pInfo->pBuffer->GetBuffer() + pastPacketStart * nBytesPerSample ;            tAudioSample *cvtout = buffer + nMixbufferOffset ;            /*    {FILE *f1 = fopen("c:\\temp\\mix.txt","a+");     fprintf(f1,"  mix packet (%I64d,%I64d,len=%ld) into buffer(%ld,%ld,len=%ld)\n",         pInfo->llStartTimeInSamples,pInfo->llEndTimeInSamples,         nn,         nMixbufferOffset,nMixbufferOffset+nSamplesToUse,nSamplesToUse);     fprintf(f1,"  pastPacketStart = %I64d, nMixbufferOffset = %ld\n",                pastPacketStart,nMixbufferOffset) ;     fclose(f1);}*/            switch (nBytesPerSample)            {            case 1:                CAudioSvcSampleConverter::cvt8(cvtin, cvtout, nSamplesToUse);                break ;            case 2:                CAudioSvcSampleConverter::cvt16(cvtin, cvtout, nSamplesToUse);                break ;            case 4:                CAudioSvcSampleConverter::cvt32(cvtin, cvtout, nSamplesToUse);                break ;            }        }	else if (pInfo->llStartTimeInSamples >= llStartTimeInSamples + nSamples)	{	    /* We've found audio data that is past the	     * desired range.	     */	    bPacketsAfterRange = TRUE;	}    }    if (!didMix && bPacketsAfterRange)    {	/* We do not have packets for this range, but we	 * do have packets after the range.	 * Create silence data and make it look like we	 * actually had data for this range.	 */	CAudioSvcSampleConverter::silence(buffer, nSamples) ;	didMix = TRUE;    }    return didMix ;

⌨️ 快捷键说明

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