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

📄 hxaudstr_new.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	audioData.pData = m_piPendingAudioData ;
	audioData.pData->AddRef() ;

	// use time of incoming packet -- one sample frame is below the
	// ms resolution of time stamps.
	audioData.ulAudioTime = pInData->ulAudioTime;
	// stream type is incoming stream type
	audioData.uAudioStreamType = pInData->uAudioStreamType;
	theErr = Write2(&audioData) ;
	audioData.pData->Release() ;

	m_ulPendingAudioBytes = 0 ;

	// release the slush buffer
	HX_RELEASE(m_piPendingAudioData) ;

	if (FAILED(theErr))
	    return theErr ;
    }

    // put partial sample frames from the end of the incoming buffer
    // into the slush buffer.

    if (ulInBytes % m_ulSampleFrameSize)
    {
	// the slush buffer should be empty here.
	HX_ASSERT(m_ulPendingAudioBytes == 0);
	HX_ASSERT(m_piPendingAudioData == 0) ;

	// reserve a new slush buffer
	theErr = CreateInstance(IID_IHXBuffer, (void**)&m_piPendingAudioData);

	if (SUCCEEDED(theErr))
	    theErr = m_piPendingAudioData->SetSize(m_ulSampleFrameSize) ;

	if (SUCCEEDED(theErr))
	{
	    m_ulPendingAudioBytes = ulInBytes % m_ulSampleFrameSize ;
	    ulInBytes -= m_ulPendingAudioBytes ;

	    memcpy(m_piPendingAudioData->GetBuffer(),
		   pInData->pData->GetBuffer() + ulCutoffBytes + ulInBytes,
		   m_ulPendingAudioBytes) ;
	}

	if (FAILED(theErr))
	    return theErr ;
    }

    // send any leftover fragment of the incoming buffer.

    if (ulInBytes == pInData->pData->GetSize() && !ulCutoffBytes)
    /* this is the entire buffer, not a fragment. 
     * This is the normal case -- let's handle it efficiently. */
    {
	theErr = Write2(pInData) ;
    }
    else if (ulInBytes)
    /* if anything left in buffer, send it in a fragment */
    {
	HXAudioData audioData ;
	CHXBufferFragment* pFragment = new CHXBufferFragment(
	    pInData->pData,
	    pInData->pData->GetBuffer() + ulCutoffBytes,
	    ulInBytes);

	theErr = pFragment->QueryInterface(IID_IUnknown, (void**)&audioData.pData) ;

	// this must always succeed, since we know it exports a IHXBuffer
	HX_ASSERT(SUCCEEDED(theErr)) ;

	// use time of incoming packet -- one sample frame is below the
	// ms resolution of time stamps.
	audioData.ulAudioTime = pInData->ulAudioTime;
	// stream type is incoming stream type if we did not cut anything away,
	// and STREAMED_AUDIO if we did (because in that case this is a continuation)
	audioData.uAudioStreamType = ulCutoffBytes ? STREAMING_AUDIO : pInData->uAudioStreamType ;
	theErr = Write2(&audioData) ;
	// we release our hold on pFragment here. When MixIntoBuffer() is done with
	// this fragment, it will also release its hold, and the fragment gets
	// deleted.
	audioData.pData->Release() ;
    }
#else
    theErr = Write2(pInData) ;
#endif /* HELIX_FEATURE_AUDIO_INCOMPLETESAMPLE */

    return theErr;
}

/************************************************************************
 *  Method:
 *		IHXAudioStream::Write2
 *  Purpose:
 *      Write audio data to Audio Services. This is a companion/backend
 *      function to IHXAudioStream::Write
 *
 */
HX_RESULT CHXAudioStream::Write2(HXAudioData* pInData)
{
    HX_RESULT theErr = HXR_OK;

    // Process any "hooks"; Add the data to the data list.
    /* If buffer is NULL, it means that the user just 
     * wants to know what timestamp should be placed in the next 
     * STREAMED/TIMED audio data
     */
    if ( !m_bGotHooks || !pInData->pData)
    {
	theErr = AddData( pInData );
    }
    else
    {
 	HXAudioData outData;
	
	outData.pData	    = 0;
	outData.ulAudioTime = 0;

	theErr = ProcessHooks( pInData, &outData );
	if (!theErr && !m_bDisableWrite )
	{
	    theErr = AddData( &outData );
	}

	if (outData.pData)
	{
	    outData.pData->Release();
	}
    }
    
    return theErr;
}

/************************************************************************
 *  Method:
 *		IHXAudioStream::AddPreMixHook
 *	Purpose:
 *      Use this method to add a pre-mix audio data hook.
 */
STDMETHODIMP CHXAudioStream::AddPreMixHook
( 
	  IHXAudioHook*    pHook,
    const BOOL              bDisableWrite
)
{
#if defined(HELIX_FEATURE_AUDIO_PREMIXHOOK)
    void* pTmp = 0;
    
    /* Does one already exists */
    if (m_PreMixHookMap.Lookup((void*)pHook, pTmp))
    {
	return HXR_INVALID_PARAMETER;
    }

    HXAudioHookInfo* pPreMixHookInfo = (HXAudioHookInfo*) new HXAudioHookInfo;
    pPreMixHookInfo->pHook   	    = pHook;
    pPreMixHookInfo->bDisableWrite  = bDisableWrite;
    pPreMixHookInfo->bFinal = FALSE;
    pPreMixHookInfo->bIgnoreAudioData = FALSE;
    pPreMixHookInfo->bMultiChannelSupport = FALSE;

    IHXValues* pValues = NULL;
    if (pHook && pHook->QueryInterface(IID_IHXValues, (void**) &pValues) == HXR_OK)
    {
	UINT32 ulValue = 0;
	pValues->GetPropertyULONG32("IgnoreAudioData", ulValue);
	pPreMixHookInfo->bIgnoreAudioData = (ulValue == 1);
	HX_RELEASE(pValues);
    }

    pHook->AddRef();		// Released in destructor

    IHXAudioMultiChannel* pMultiChannel = NULL;
    if (pHook && HXR_OK == pHook->QueryInterface(IID_IHXAudioMultiChannel, (void**) &pMultiChannel))
    {
        pPreMixHookInfo->bMultiChannelSupport = pMultiChannel->GetMultiChannelSupport();
    }
    HX_RELEASE(pMultiChannel);

    m_PreMixHookMap.SetAt(pHook, pPreMixHookInfo);

    m_bGotHooks	= TRUE;

    /* If any one of them is Disabled, we do not write */
    if (bDisableWrite)
    {
	m_bDisableWrite = TRUE;
    }

    ProcessAudioHook(ACTION_ADD, pHook);

    /* If we are already initialized, send the audio format */
    if (m_bHooksInitialized)
    {
	if (pPreMixHookInfo->bIgnoreAudioData ||
	    HXR_OK == ProcessAudioHook(ACTION_CHECK, pHook))
	{
	    pHook->OnInit( &m_AudioFmt );
	}
    }

    return HXR_OK;
#else
    return HXR_NOTIMPL;
#endif /* HELIX_FEATURE_AUDIO_PREMIXHOOK */
}

/************************************************************************
 *  Method:
 *		IHXAudioStream::RemovePreMixHook
 *	Purpose:
 *      Use this method to remove a pre-mix audio data hook.
 */
STDMETHODIMP CHXAudioStream::RemovePreMixHook
( 
      IHXAudioHook*    pHook
)
{
#if defined(HELIX_FEATURE_AUDIO_PREMIXHOOK)
    HXAudioHookInfo* pPreMixHookInfo = 0;
    BOOL bCheckForDisableWrite	      = FALSE;

    if (!m_PreMixHookMap.Lookup((void*)pHook, (void*&) pPreMixHookInfo))
    {
	return HXR_INVALID_PARAMETER;
    }

    m_PreMixHookMap.RemoveKey(pHook);

    /* If we are removing a hook which had disable write, 
     * we need to re-determine if any of the remaining hooks
     * has DisableWrite set to TRUE
     */
    if (pPreMixHookInfo->bDisableWrite)
    {
	bCheckForDisableWrite = TRUE;
	m_bDisableWrite	      = FALSE;
    }

    ProcessAudioHook(ACTION_REMOVE, pHook);

    pPreMixHookInfo->pHook->Release();
    delete pPreMixHookInfo;

    if (m_PreMixHookMap.GetCount() == 0)
    {
	m_bGotHooks	= FALSE;
	m_bDisableWrite = FALSE;
    }
    else if (bCheckForDisableWrite)
    {
	CHXMapPtrToPtr::Iterator lIter = m_PreMixHookMap.Begin();
	for (; lIter != m_PreMixHookMap.End(); ++lIter)
	{
	    HXAudioHookInfo* pPreMixHook = (HXAudioHookInfo*) (*lIter);
	    
	    /* atleast one has Disable Write ON */
	    if (pPreMixHook->bDisableWrite)
	    {
		m_bDisableWrite = TRUE;
		break;
	    }
	}
    }
#endif /* HELIX_FEATURE_AUDIO_PREMIXHOOK */

    return HXR_OK;
}

/************************************************************************
*  Method:
*	IHXAudioStream::AddDryNotification
*  Purpose:
*	Use this to add a notification response object to get notifications
*	when audio stream is running dry.
*/
STDMETHODIMP CHXAudioStream::AddDryNotification
			(
			    IHXDryNotification* /*IN*/ pNotification
			)
{
    if (!pNotification)
    {
	return HXR_INVALID_PARAMETER;
    }

    void* pTmp = 0;
    
    /* Does one already exists */
    if (m_DryNotificationMap->Lookup((void*)pNotification, pTmp))
    {
	return HXR_INVALID_PARAMETER;
    }

    pNotification->AddRef();

    m_DryNotificationMap->SetAt((void*)pNotification, (void*)pNotification);

    return HXR_OK;
}


/************************************************************************
*  Method:
*      IHXAudioStream2::RemoveDryNotification
*  Purpose:
*	    Use this to remove itself from the notification response object
*	    during the stream switching.
*/
STDMETHODIMP CHXAudioStream::RemoveDryNotification   
			    (
				IHXDryNotification* /*IN*/ pNotification
			    )
{
    HX_RESULT	hr = HXR_OK;

    void* pTmp = 0;

    if (!pNotification)
    {
	hr = HXR_INVALID_PARAMETER;
	goto cleanup;
    }

    // remove only if it is exists
    if (m_DryNotificationMap->Lookup((void*)pNotification, pTmp))
    {
	m_DryNotificationMap->RemoveKey((void*)pNotification);
	HX_RELEASE(pNotification);
    }
    else
    {
	hr = HXR_INVALID_PARAMETER;
	goto cleanup;
    }

cleanup:

    return hr;
}

/************************************************************************
*  Method:
*      IHXAudioStream2::GetAudioFormat
*  Purpose:
*	    Returns the input audio format of the data written by the 
*	    renderer. This function will fill in the pre-allocated 
*	    HXAudioFormat structure passed in.
*/
STDMETHODIMP
CHXAudioStream::GetAudioFormat(HXAudioFormat*	/*IN/OUT*/pAudioFormat)
{
    HX_ASSERT(pAudioFormat);
    if (!pAudioFormat)
    {
	return HXR_INVALID_PARAMETER;
    }

    if (!m_bInited)
    {
	return HXR_UNEXPECTED;
    }

    pAudioFormat->uChannels	    = m_AudioFmt.uChannels;
    pAudioFormat->uBitsPerSample    = m_AudioFmt.uBitsPerSample;
    pAudioFormat->ulSamplesPerSec   = m_AudioFmt.ulSamplesPerSec;
    pAudioFormat->uMaxBlockSize	    = m_AudioFmt.uMaxBlockSize;

    return HXR_OK;
}


 
/************************************************************************
 *  Method:
 *              IHXAudioStream::GetAudioVolume
 *      Purpose:
 *              Return this stream's IRMA volume interface.
 */
STDMETHODIMP_(IHXVolume*) CHXAudioStream::GetAudioVolume()
{
    IHXVolume* pRet = NULL;
    
#ifdef HELIX_FEATURE_VOLUME    
    if( m_pStreamVolume )
    {
        m_pStreamVolume->AddRef();
        pRet = m_pStreamVolume;
    }
#endif 
   
    return pRet;
}

#if defined(HELIX_FEATURE_VOLUME)
//
// IHXVolume methods
//
STDMETHODIMP CHXAudioStream::OnVolumeChange(const UINT16 uVolume)
{
    m_uVolume = uVolume;
#ifdef HELIX_FEATURE_GAINTOOL
    if (m_pMixEngine)
        m_pMixEngine->SetVolume(m_pMixEngine->HXVolume2TenthOfDB(m_uVolume)) ; 
#endif
    return HXR_OK;
}

STDMETHODIMP CHXAudioStream::OnMuteChange(const BOOL bMute)
{
    m_bMute = bMute;
#ifdef HELIX_FEATURE_GAINTOOL
    if (m_pMixEngine)
        m_pMixEngine->SetVolume(m_pMixEngine->HXVolume2TenthOfDB(bMute ? HX_MIN_VOLUME : m_uVolume)) ;
#endif
    return HXR_OK;
}

#endif /* HELIX_FEATURE_VOLUME */





/************************************************************************
 *  Method:
 *		IHXAudioStream::AddData
 *	Purpose:
 *		Add audio data to list.
 *	NOTE: Mark Streamed data also as Timed data IF we don't write a streamed packet
 *	 since it was LATE!!!
 */
HX_RESULT CHXAudioStream::AddData
(
    HXAudioData* pAudioData
)

⌨️ 快捷键说明

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