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

📄 hxaudses.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        /* If the audio device is busy, check if we have
         * anything other than audio in the presentation.
         * If TRUE, play silence so that the rest of the
         * presentation can be played.
         */
        if (theErr == HXR_AUDIO_DRIVER && !m_bDisableWrite)
        {
            if (!IsAudioOnlyTrue())
            {
                m_bDisableWrite = TRUE;
                m_pAudioDev         = 0;
                theErr      = HXR_OK;
            }
        }
    }

    m_bInited = (!theErr) ? TRUE : FALSE;

    if (!theErr && m_pAudioDev && m_pHookList)
    {
        InitHooks();
    }

    if (!theErr && m_pAudioDev && m_pFinalHook)
    {
        ProcessAudioHook(ACTION_ADD, m_pFinalHook);
    }

    if(m_pContext)
    {
        HX_RELEASE(m_pMPPSupport);
        m_pContext->QueryInterface(IID_IHXMultiPlayPauseSupport, (void**)&m_pMPPSupport);
    }

    return theErr;
}

HX_RESULT
CHXAudioSession::OpenDevice()
{
    HX_RESULT       theErr = HXR_OK;
    HXAudioFormat  audioFormat;

    if (m_pFinalHook)
    {
        m_bUseFinalHook = TRUE;

        if (HXR_OK != ProcessAudioHook(ACTION_CHECK, m_pFinalHook))
        {
            m_bUseFinalHook = FALSE;
        }

        if (m_bUseFinalHook)
        {
            memcpy( &audioFormat, &m_ActualDeviceFmt, sizeof(HXAudioFormat));
            theErr = m_pFinalHook->OnInit(&audioFormat);
        }
    }

    if (!theErr && m_pFinalHook && m_bUseFinalHook)
    {
        m_bUseFinalHook = TRUE;
        /* Did the hook change the data format? */
        if( 0!=memcmp(&audioFormat, &m_ActualDeviceFmt, sizeof(HXAudioFormat)))
        {
            memcpy( &m_BeforeHookDeviceFmt, &m_ActualDeviceFmt, sizeof(HXAudioFormat));
            memcpy( &m_ActualDeviceFmt, &audioFormat, sizeof(HXAudioFormat));
        }
    }
    else
    {
        m_bUseFinalHook = FALSE;
    }

    theErr = OpenAudio();

    if (theErr && m_pFinalHook && m_bUseFinalHook)
    {
        /* Looks like the audio device does not support the format
         * specified by the final Hook
         * Revert back to the original format and try again
         */
        memcpy( &m_ActualDeviceFmt, &m_BeforeHookDeviceFmt, sizeof(HXAudioFormat));
        m_bUseFinalHook         = FALSE;
        theErr = OpenAudio();
    }

    return theErr;
}


/* ***********************************************************************
 *  Method:
 *              CHXAudioSession::GetDeviceFormat
 *      Purpose:
 *              Determine the device format for this session.
 *              The session object needs to resolve the device format
 *              among multiple players.
 */
HX_RESULT CHXAudioSession::GetDeviceFormat()
{
    HX_RESULT       theErr          = HXR_OK;
    UINT16          uOrigSampleRate = 0;
    CHXAudioPlayer* p               = NULL;
    UINT16          bAutoUpsampling = FALSE;
    HXAudioFormat   audioFmt;

    // We no longer force audio device in stereo mode.  However we
    // still try to open it in 16-bit mode since all of our processing
    // is done in 16 bit.
    m_DeviceFmt.uBitsPerSample  = 16;

    //Just grab the first players stats to use as maximums.
    LISTPOSITION lp = m_pPlayerList->GetHeadPosition();
    while(lp)
    {
        p = (CHXAudioPlayer*) m_pPlayerList->GetNext(lp);
        if(0!=p->GetStreamCount())
        {
            p->GetFormat( &audioFmt );
            m_DeviceFmt.uChannels       = audioFmt.uChannels;
            m_DeviceFmt.ulSamplesPerSec = audioFmt.ulSamplesPerSec;
            m_DeviceFmt.uMaxBlockSize   = audioFmt.uMaxBlockSize;
            break;
        }
    }

    //Now loop through the rest of the players and find all the
    //maximums.
    while(lp)
    {
        p = (CHXAudioPlayer*) m_pPlayerList->GetNext(lp);
        if( 0 != p->GetStreamCount() )
        {
            p->GetFormat( &audioFmt );
            m_DeviceFmt.uChannels       = max(m_DeviceFmt.uChannels,
                                              audioFmt.uChannels);
            m_DeviceFmt.ulSamplesPerSec = max(m_DeviceFmt.ulSamplesPerSec,
                                              audioFmt.ulSamplesPerSec);
            m_DeviceFmt.uMaxBlockSize   = max(m_DeviceFmt.uMaxBlockSize,
                                              audioFmt.uMaxBlockSize);
        }
    }

    // turn on the default upsampling to 44K only on IX86 platforms
    // which support MMX
    // XXXgfw this also uses more memory for each block we push down
    // XXXgfw to the audio device. You might not want it on MIN_HEAP
    // XXXgfw kind of MMX devices, if there are any.
#if defined(_M_IX86)
    ReadPrefINT16(m_pPreferences, "AutoAudioUpsampling", bAutoUpsampling );
#endif
    if(bAutoUpsampling)
    {
        //force 44khz as our first attempt to open audio device
        uOrigSampleRate = (UINT16)m_DeviceFmt.ulSamplesPerSec;
        m_DeviceFmt.ulSamplesPerSec = 44100;
    }
#if defined(HELIX_FEATURE_PREFERENCES)
    else
    {
        UINT16 ulSamplesPerSecPreference = 0;
    	ReadPrefINT16(m_pPreferences, "AudioDeviceSamplesPerSec", ulSamplesPerSecPreference );
        if(ulSamplesPerSecPreference)
        {
            uOrigSampleRate = (UINT16)m_DeviceFmt.ulSamplesPerSec;
            m_DeviceFmt.ulSamplesPerSec = ulSamplesPerSecPreference;
        }
    }
#endif /* HELIX_FEATURE_PREFERENCES */

    //Start negotiating with the device. Generate a table that will
    //drive the different formats we want to try.  Start with the
    //native rate (and any mods from the pref stuff above) and go up
    //in samplerate. If that fails, go down in sample rate.
    const int nNumberOfRates = sizeof(z_anValidSampleRates)/sizeof(z_anValidSampleRates[0]);
    //Total number of table entries per sample rate will be:
    //nNumberOfRates*4 (mono/16, mono/8, stereo/16, stereo/8) plus
    //native format + user defined samplerate entry.
    const int      nTmp       = nNumberOfRates*4+2;
    unsigned short nTableSize = 0;
    tableEntry* table = new tableEntry[nTmp];

    HX_ASSERT(table);
    if( NULL == table )
        return HXR_OUTOFMEMORY;


    //First entry is always our native format from above with any
    //samplerate changes the user made via prefs.
    table[nTableSize++].set( (UINT16)m_DeviceFmt.ulSamplesPerSec,
                             (UINT8)m_DeviceFmt.uChannels,
                             (UINT8)m_DeviceFmt.uBitsPerSample
                             );

    //Second entry is always the above with the clip's original
    //sample rate, if we changed it.
    if( uOrigSampleRate )
        table[nTableSize++].set(uOrigSampleRate,
                                (UINT8)m_DeviceFmt.uChannels,
                                (UINT8)m_DeviceFmt.uBitsPerSample
                                );

    //Now generate the rest of the format table....
    const UINT8 usNativeChannel = (UINT8)m_DeviceFmt.uChannels;
    const UINT8 usAltChannel    = (2==m_DeviceFmt.uChannels)?1:2;
    const UINT8 usNativeBits    = (UINT8)m_DeviceFmt.uBitsPerSample;
    const UINT8 usAltBits       = (8==m_DeviceFmt.uBitsPerSample)?16:8;

    //First use all equal or higher sample rates.
    short nIdx = 0;
    while( nIdx<nNumberOfRates )
    {
        UINT16 usRate = z_anValidSampleRates[nIdx];
        if( usRate >= m_DeviceFmt.ulSamplesPerSec )
        {
            table[nTableSize++].set(usRate, usNativeChannel, usNativeBits );
            table[nTableSize++].set(usRate, usAltChannel,    usNativeBits );
            table[nTableSize++].set(usRate, usNativeChannel, usAltBits  );
            table[nTableSize++].set(usRate, usAltChannel,    usAltBits  );
        }
        nIdx++;
    }
    //Now all the samle rates lower then the native rate.
    nIdx = nNumberOfRates-1;
    while( nIdx>=0)
    {
        UINT16 usRate = z_anValidSampleRates[nIdx];
        if( usRate < m_DeviceFmt.ulSamplesPerSec )
        {
            table[nTableSize++].set(usRate, usNativeChannel, usNativeBits );
            table[nTableSize++].set(usRate, usAltChannel,    usNativeBits );
            table[nTableSize++].set(usRate, usNativeChannel, usAltBits  );
            table[nTableSize++].set(usRate, usAltChannel,    usAltBits  );
        }
        nIdx--;
    }

    //Now loop through our table and find a supported format.
    nIdx = 0;
    theErr = HXR_FAIL;
    while( FAILED(theErr) && nIdx<nTableSize)
    {
        m_DeviceFmt.ulSamplesPerSec = table[nIdx].usSampleRate;
        m_DeviceFmt.uChannels       = table[nIdx].usChannels;
        m_DeviceFmt.uBitsPerSample  = table[nIdx].usBits;
        theErr = CheckAudioFormat(&m_DeviceFmt);
        nIdx++;
    }

    //We still need to create playback buffers since we will use the
    //fake timeline if the presentation has atleast one media type
    //other than audio
    //XXXgfw this code below needs to be looked at. I Don't want to
    //touch it now for fear of breaking something that will take
    //a long time to fix.
    if (!theErr || theErr == HXR_AUDIO_DRIVER)
    {
        m_ActualDeviceFmt = m_DeviceFmt;

        //All the calculations are done for 16 bit stereo. There are
        //VERY FEW sound cards out there which do not support 16 bit
        //stereo. They will incur a high performace hit because of
        //possible unnecessary up/down conversion. For now we will
        //live with that.
        //XXXgfw wrong. lots of handhelds/phones don't do 16bit-2
        //channel output.
        m_DeviceFmt.uBitsPerSample  = 16;

        m_BeforeHookDeviceFmt = m_ActualDeviceFmt;
    }

    HX_VECTOR_DELETE(table);
    return theErr;
}


/************************************************************************
 *  Method:
 *              CHXAudioSession::CheckAudioFormat
 *      Purpose:
 *       The audio player calls this to check its audio format with the
 *       the audio device.
 */
HX_RESULT CHXAudioSession::CheckAudioFormat
(
    HXAudioFormat*    pAudioFormat
)
{
    HX_RESULT theErr = HXR_OK;

    if (!m_pAudioDev)
    {
        CreateAudioDevice();
        m_pAudioDev = m_pCurrentAudioDev;
    }

    if (m_pAudioDev)
    {
        theErr = m_pAudioDev->CheckFormat(pAudioFormat);
        /* Any error from audio device other than memory error is
         * returned as HXR_AUDIO_DRIVER
         */
        if (theErr != HXR_OK && theErr != HXR_OUTOFMEMORY)
        {
            theErr = HXR_AUDIO_DRIVER;
        }
    }

    return theErr;
}

/************************************************************************
 *  Method:
 *              CHXAudioSession::PlayAudio
 *      Purpose:
 *       The player object call this to play audio. This method is called
 *       again in the playback response function.
 */
HX_RESULT CHXAudioSession::PlayAudio(UINT16 uNumBlocks)
{
    HX_RESULT theErr        = HXR_OK;
    BOOL      bDisableWrite = FALSE;

    if ( !m_bInited )
        return theErr;

    if (m_bInPlayAudio)
    {
        return HXR_OK;
    }

    m_pMutex->Lock();

    if (m_bToBeRewound)
    {
        theErr = Rewind();
        goto exit;
    }

    m_bInPlayAudio = TRUE;

    if (m_pAuxiliaryAudioBuffers &&
        m_pAuxiliaryAudioBuffers->GetCount() > 0 && m_pAudioDev && !m_bDisableWrite)
    {
        if (HXR_OK == ProcessAudioDevice(ACTION_CHECK, m_pAudioDev))
        {
            /* Try to stuff in as much backlog as possible */
            while (!theErr && m_pAuxiliaryAudioBuffers->GetCount() > 0)
            {
                HXAudioData* pAudioData =
                    (HXAudioData*) m_pAuxiliaryAudioBuffers->GetHead();

                // Write session audio data to device.
                theErr = m_pAudioDev->Write(pAudioData);
                if( theErr == HXR_OUTOFMEMORY )
                {
                    goto exit;
                }

                if (!theErr)
                {
                    m_ulBlocksWritten++;
                    m_dNumBytesWritten  += pAudioData->pData->GetSize();

                    m_pAuxiliaryAudioBuffers->RemoveHead();
                    pAudioData->pData->Release();
                    delete pAudioData;
                }
                /*All other error codes are translated into audio driver error*/
                else if (theErr != HXR_OUTOFMEMORY && theErr != HXR_WOULD_BLOCK)
                {
                    theErr = HXR_AUDIO_DRIVER;
                }
            }
        }
    }

    // If we have audio streams then play audio.
    if (!theErr && m_bHasStreams)
    {
	// Push down at least 3 secs of audio.
	UINT16 uPush = uNumBlocks;
	if (m_bFirstPlayAudio)
	{
	    uPush = (UINT16) m_ulMinBlocksTobeQueued;
    	}

	HXAudioData audioData;
	CHXAudioPlayer* pPlayer = 0;
	CHXAudioStream* pStream = 0;
	CHXSimpleList*  pStreamList = 0;
#if defined(HELIX_FEATURE_VOLUME) || defined(HELIX_FEATURE_MIXER)
	UINT16  uPlayerVolume = HX_INIT_VOLUME;
#endif
	UCHAR*  pMixBuffer = 0;
	UCHAR*  pPlayerBuf = NULL;
	UCHAR*  pSessionBuf = NULL;
	IHXBuffer* pMixIHXBuffer = NULL;
	BufType	bufType = BUFFER_NONE;

	for (UINT16 i = 0; !theErr && i < uPush; i++ )
	{
	    m_uNumToBePushed = uPush - i;
	    m_bSessionBufferDirty = FALSE; // only used for multi-player case

	    UINT32  ulNumBytesWritten = m_ulBytesPerGran;
	    BOOL    bAtLeastOnePlayerActive = FALSE;

	    theErr = m_pSessionBuf->SetSize(m_ulBytesPerGran);
            if( theErr == HXR_OUTOFMEMORY )
            {
                theErr = HXR_OUTOFMEMORY;
                goto exit;

⌨️ 快捷键说明

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