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

📄 hxaudstr.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        if (HXR_OK == m_Owner->m_pContext->QueryInterface(IID_IHXErrorMessages, (void**)&pErrMsg))
        {
            DEBUG_OUT(pErrMsg, DOL_GENERIC, (s,"AudioFormatIn: %lu channels %lu SamplesPerSec", m_AudioFmt.uChannels, m_AudioFmt.ulSamplesPerSec));
            DEBUG_OUT(pErrMsg, DOL_GENERIC, (s,"AudioFormatOut: %lu channels %lu SamplesPerSec", m_DeviceFmt.uChannels, m_DeviceFmt.ulSamplesPerSec));
        }
        HX_RELEASE(pErrMsg);

        if (m_bIsLive)
        {
            m_Owner->UpdateStreamLastWriteTime();
            UpdateStreamLastWriteTime(TRUE);
        }
    }
//{FILE* f1 = ::fopen("c:\\temp\\audio.txt", "a+"); ::fprintf(f1, "%lu\tAddData\t%p\t%lu\n", HX_GET_BETTERTICKCOUNT(), this, pAudioData->ulAudioTime);::fclose(f1);}
//    ::fwrite(pAudioData->pData->GetBuffer(), pAudioData->pData->GetSize(), 1, fdin);

    UINT32 ulDataTime = CalcMs(pAudioData->pData->GetSize());
    UINT32 ulEndTime = pAudioData->ulAudioTime + ulDataTime;

    if (m_pAvailableBuffers && !m_bDeterminedInitialCacheSize && ulDataTime > 0)
    {
        m_bDeterminedInitialCacheSize = TRUE;
        m_uCacheSize = (UINT16) (m_ulGranularity*2/ulDataTime) + 1;
        /* make sure it is atleast CACHE_INCREMENT_SIZE to begin with */
        m_uCacheSize = m_uCacheSize < CACHE_INCREMENT_SIZE ? 
                            CACHE_INCREMENT_SIZE : m_uCacheSize;
    }

    if (m_ulLastInputStartTime > pAudioData->ulAudioTime &&
        ((m_ulLastInputStartTime - pAudioData->ulAudioTime) > MAX_TIMESTAMP_GAP))
    {
        bInTSRollOver = TRUE;
        m_ulTSRollOver++;
    }

    m_ulLastInputStartTime  = pAudioData->ulAudioTime;
    m_ulLastInputEndTime    = ulEndTime;

    /* even in STREAMING_AUDIO case, it might happen, that the packets
     * written are late. e.g. packets received late on the network 
     */
    INT64 llActualTimestamp = CAST_TO_INT64 (pAudioData->ulAudioTime) + CAST_TO_INT64 m_ulTSRollOver * CAST_TO_INT64 MAX_UINT32;
    INT64 llActualEndTime = CAST_TO_INT64 (pAudioData->ulAudioTime) + CAST_TO_INT64 (ulDataTime) +
                            CAST_TO_INT64 m_ulTSRollOver * CAST_TO_INT64 MAX_UINT32;

    if ((pAudioData->uAudioStreamType == STREAMING_AUDIO ||
         pAudioData->uAudioStreamType == TIMED_AUDIO) &&
       !(llActualTimestamp >= m_llLastWriteTime ||
         llActualEndTime > m_llLastWriteTime)) 
    {
        /* Too late*/
        m_bTobeTimed    = TRUE;
//{FILE* f1 = ::fopen("e:\\audio.txt", "a+"); ::fprintf(f1, "%lu\t%p\t%d\t%lu\t%lu\tLATE\n", HX_GET_BETTERTICKCOUNT(), this, m_pDataList->GetCount(), pAudioData->ulAudioTime, (INT32)m_llLastWriteTime);::fclose(f1);}
        return HXR_LATE_PACKET; 
    }

    pAinfo = new HXAudioInfo;
    if(!pAinfo)
    {
        theErr = HXR_OUTOFMEMORY;
        goto exit;
    }

    pAudioData->pData->AddRef();
    pAinfo->pBuffer             = pAudioData->pData;
    pAinfo->ulStartTime         = pAudioData->ulAudioTime;
    pAinfo->pOffset             = pAudioData->pData->GetBuffer();  
    pAinfo->ulBytesLeft         = pAudioData->pData->GetSize();  
    pAinfo->uAudioStreamType    = pAudioData->uAudioStreamType;

    if (m_bTobeTimed && pAudioData->uAudioStreamType == STREAMING_AUDIO)
    {
        pAinfo->uAudioStreamType = TIMED_AUDIO;
        m_bTobeTimed             = FALSE;
    }
    else if (m_bTobeTimed && pAudioData->uAudioStreamType == TIMED_AUDIO)
    {
        m_bTobeTimed    = FALSE;
    }

//{FILE* f1 = ::fopen("c:\\temp\\audio.txt", "a+"); ::fprintf(f1, "AddData ulAudioTime: %lu\n", pAudioData->ulAudioTime);::fclose(f1);}

    if (pAinfo->uAudioStreamType == INSTANTANEOUS_AUDIO)
    {
	CHXSimpleList* pList = new CHXSimpleList;
        if(!pList)
        {
            theErr = HXR_OUTOFMEMORY;
            goto exit;
        }
	pList->AddHead((void*) pAinfo);
	m_pInstantaneousList->AddTail((void*) pList);
	m_Owner->m_Owner->ToBeRewound();
    }
    else if (pAinfo->uAudioStreamType == STREAMING_INSTANTANEOUS_AUDIO)
    {
	HX_ASSERT(m_pInstantaneousList && m_pInstantaneousList->GetCount() > 0);
	CHXSimpleList* pList = NULL;
	if (m_pInstantaneousList->GetCount() == 0)
	{
	    pList = new CHXSimpleList;
            if(!pList)
            {
                theErr = HXR_OUTOFMEMORY;
                goto exit;
            }
	    m_pInstantaneousList->AddTail((void*) pList);

	    // fix for naive users!
	    pAinfo->uAudioStreamType = INSTANTANEOUS_AUDIO;
	    m_Owner->m_Owner->ToBeRewound();
	}

        pList = (CHXSimpleList*) m_pInstantaneousList->GetTail();
        pList->AddTail(pAinfo);
    }
    else if (m_pDataList->IsEmpty())
    {
        m_pDataList->AddTail((void*) pAinfo);
    }
    else
    {
        HXAudioInfo* pInfo = (HXAudioInfo*) m_pDataList->GetTail();

        UINT32  ulActualTSRollOver = m_ulTSRollOver;

        if (bInTSRollOver && ulActualTSRollOver)
        {
            ulActualTSRollOver--;
        }

        INT64 llActualLastEndTime = CAST_TO_INT64 (pInfo->ulStartTime) + CAST_TO_INT64 (CalcMs(pInfo->pBuffer->GetSize())) +
                                    CAST_TO_INT64 ulActualTSRollOver * CAST_TO_INT64 MAX_UINT32;
        INT64 llActualLastStartTime = CAST_TO_INT64 (pInfo->ulStartTime) + CAST_TO_INT64 ulActualTSRollOver * CAST_TO_INT64 MAX_UINT32;
        
        if (llActualTimestamp < llActualLastStartTime)
        {
            /* Not allowed */
            theErr = HXR_OUTOFORDER_PACKET; 
            /* something is fu*#$#up... figure out what?*/

            HX_ASSERT(!("Packets written out of order"));
            goto exit;
        }

        if (pAinfo->uAudioStreamType == STREAMING_AUDIO)
        {
            /* is it a resonable packet to add to the list */
            if ((llActualTimestamp <= llActualLastEndTime               &&
                 llActualLastEndTime - llActualTimestamp <= m_ulFudge)  || 
                (llActualTimestamp >= llActualLastEndTime               &&
                 llActualTimestamp - llActualLastEndTime <= m_ulFudge))
            {
                m_pDataList->AddTail((void*) pAinfo);
            }
            else
            {
                theErr = HXR_NONCONTIGUOUS_PACKET; //HX_LATE_PACKET;
                /* something is fu*#$#up... figure out what?*/
                HX_ASSERT(!("Streaming Audio: Non-Contigous Write"));
                m_bTobeTimed    = TRUE;
                goto exit;
            }
        }
        else
        {
            /* see if there is any overlap.. we do not allow any overlap */
            if (llActualTimestamp < llActualLastEndTime &&
                llActualLastEndTime - llActualTimestamp > m_ulFudge)
            {
                /* hmmm an overlapped packet */
                theErr = HXR_OVERLAPPED_PACKET;
                /* something is fu*#$#up... figure out what?*/
                HX_ASSERT(!("Timed Audio: Overlapping write"));
                m_bTobeTimed    = TRUE;
                goto exit;
            }
            else
            {
                m_pDataList->AddTail((void*) pAinfo);
            }
        }
    }

exit:
    if (theErr != HXR_OK && pAinfo)
    {
        pAinfo->pBuffer->Release();
        delete pAinfo;
    }

    /* Make sure to discard any data that is prior to cross-fade time */
    if (!theErr && m_bCrossFadingToBeDone && m_bFadeToThisStream)
    {
        RemoveExcessCrossFadeData();
    }

//{FILE* f1 = ::fopen("e:\\audio.txt", "a+"); ::fprintf(f1, "%lu\t%p\t%d\t%lu\t%lu\n", HX_GET_BETTERTICKCOUNT(), this, m_pDataList->GetCount(), pAudioData->ulAudioTime, (UINT32)m_llLastWriteTime);::fclose(f1);}
    
    return theErr;
}

HX_RESULT CHXAudioStream::ProcessInfo(void)
{
    HX_RESULT theErr = HXR_OK;

    // Calculate the number of bytes per granularity.
    m_ulInputBytesPerGran = (ULONG32) 
                (((m_AudioFmt.uChannels * ((m_AudioFmt.uBitsPerSample==8)?1:2) *  m_AudioFmt.ulSamplesPerSec) 
                                / 1000.0) * m_ulGranularity);

    m_ulOutputBytesPerGran  = (ULONG32) 
                (((m_DeviceFmt.uChannels * ((m_DeviceFmt.uBitsPerSample==8)?1:2) *  m_DeviceFmt.ulSamplesPerSec) 
                                / 1000.0) * m_ulGranularity);

    /* Number of samples required at output should be a multiple of 8 if 
     * sampling rate is 8K/16K/32K...or a multiple of 11 for 11K/22K...
     * This is needed since the resamplerequires works reliably ONLY if
     * this condition is true. Ken is working on this problem. This is 
     * an interim fix 
     */
    ULONG32 ulExtraGranularity = 1;
    if (m_DeviceFmt.ulSamplesPerSec % 8 == 0)
    {
        ulExtraGranularity = 8;
    }
    else
    {
        ulExtraGranularity = 11;
    }

    // Make sure that number of bytes per granularity is an even number.
    if (m_ulInputBytesPerGran % (2*m_AudioFmt.uChannels*ulExtraGranularity) != 0)
    {
        m_ulInputBytesPerGran -= m_ulInputBytesPerGran % (2*m_AudioFmt.uChannels*ulExtraGranularity);
    }

    if (m_ulOutputBytesPerGran % (2*m_DeviceFmt.uChannels*ulExtraGranularity) != 0)
    {
        m_ulOutputBytesPerGran -= m_ulOutputBytesPerGran % (2*m_DeviceFmt.uChannels*ulExtraGranularity);
    }


    if (!theErr)
    {
        // Setup the resampler
        theErr = SetupResampler();
    }

    if (!theErr)
    {
        m_bInited = TRUE;
        
        if (m_eState == E_STOPPED)
        {
            m_eState = E_INITIALIZED;
        } 
    }

    if (!theErr && m_bInited && m_bCrossFadingToBeDone && 
        m_bFadeToThisStream)
    {
        InitializeCrossFader();
    }

    /* Get the current player time to set the last write audio time 
     * If someone creates a stream mid presentation, we ask the player 
     * object for the current write time.
     */
    // set last write time to be the current playback time since
    // this is what other system components(i.e. renderers) based on 
    // fixed b#69847 - loss of push-down-worth of data =
    // m_Owner->GetLastAudioWriteTime() - m_Owner->GetCurrentPlayBackTime()
//    m_llLastWriteTime = m_Owner->GetCurrentPlayBackTime();

    // XXXRA: It is necessary to use last audio write time for any delayed
    // audio streams to work that do not involve any Pause/Rewind logic.
    // To cover the case where a source (and an audio stream) has been added
    // mid-playback by SMIL renderer which has a delay equivalent to the 
    // current playback time, it should result in a player rewind which should 
    // reset the lastaudiowrite time accordingly...so we should be able
    // to use m_Owner->GetLastAudioWriteTime() value in such a use case as well.
    // this change is required to fix PR 79161 and PR 69780.
    // Henry, PR 69847 (the reason for the earlier change) is still busted. 
    // so I am reverting this code to the original code. you will have 
    // to come up with a different fix for PR 69847 since this was clearly not 
    // the correct fix.
    m_llLastWriteTime = m_Owner->GetLastAudioWriteTime();

    if (!theErr && m_bInited)
    {
        m_Owner->StreamInitialized(this);
    }

    return theErr;
}


/************************************************************************
 *  Method:
 *              IHXAudioStream::SetupResampler
 *      Purpose:
 */
HX_RESULT CHXAudioStream::SetupResampler()
{
    HX_RESULT theErr = HXR_OK;

#if defined(HELIX_FEATURE_RESAMPLER)
    // Create a resampler for this stream if we need one.
    // Current resampler code resamples these sampling rates:
    // 8000,11025,16000,22050,32000,44100.  The resample also
    // converts 8-bit to 16-bit. NOTE: We convert all 8-bit samples
    // to 16-bit before input into the resampler or mixer.

    /* Resampler does the following tasks:
     * 1. Conversion for sampling rates
     * 2. Conversion from 8->16 and will also do 16->8 (XXX TBD)
     * 3. Conversion from stereo to mono

     * We do not use resampler for conversion from mono to stereo. This
     * takes place in the Mixer.
     */

/*
    fprintf(fdbeforetxt, "Samples: %lu, Channels: %lu, Bits/Sample: %lu\n",
         m_AudioFmt.ulSamplesPerSec, m_AudioFmt.uChannels, m_AudioFmt.uBitsPerSample);

    fprintf(fdaftertxt, "Samples: %lu, Channels: %lu, Bits/Sample: %lu\n",
         m_DeviceFmt.ulSamplesPerSec, m_DeviceFmt.uChannels, m_DeviceFmt.uBitsPerSample);
*/

    if ((m_AudioFmt.ulSamplesPerSec != m_DeviceFmt.ulSamplesPerSec) ||
        (m_AudioFmt.uBitsPerSample != m_DeviceFmt.uBitsPerSample)   ||
        (m_AudioFmt.uChannels == 2 && m_DeviceFmt.uChannels == 1))
    {
	m_AudioFmt.uMaxBlockSize = (UINT16) (m_ulInputBytesPerGran*1.5);

        if (HXR_OK == m_Owner->GetOwner()->CreateResampler(m_AudioFmt, 
                                                           m_DeviceFmt, 
                                                           m_pResampler))
        {                               
            /* times 2 since resampler always returns data in 16 bit.
             * times 2 if i/p or o/p is stereo
             * May change in future when we do 16->8 conversion in resampler
             */
            m_ulMaxBlockSize = (ULONG32) m_DeviceFmt.uMaxBlockSize * 2 * 2;

            /* This may be TRUE in downsampling */
            if (m_ulMaxBlockSize < (ULONG32) (m_ulInputBytesPerGran*1.5))
            {
                m_ulMaxBlockSize = (ULONG32) (m_ulInputBytesPerGran*1.5);
            }
        }
        else
        {
            HX_RELEASE(m_pResampler);
            theErr = HX_RESAMPLER_ERROR;
        }

        if ( !theErr )
        {
            m_pResampleBuf = (UCHAR*) new char [ m_ulMaxBlockSize ];
            m_pTmpResBuf = (UCHAR*) new char [ m_ulMaxBlockSize ];

            if (!m_pResampleBuf || !m_pTmpResBuf)
            {
                theErr = HXR_OUTOFMEMORY;
            }
        }

    }
    else
    {
        m_ulMaxBlockSize =  m_DeviceFmt.uMaxBlockSize;
    }

    /* Do not rely on max block size specified by the user */
    if (!theErr)
    {
        m_AudioFmt.uMaxBlockSize = (UINT16) m_ulMaxBlockSize;
    }

    m_bChannelConvert = (m_AudioFmt.uChannels == 1 && m_DeviceFmt.uChannels == 2);
#endif /* HELIX_FEATURE_RESAMPLER */

    // Create the resampler output buffer. Size it to the largest needed.
    return theErr;
}

/************************************************************************
 *  Method:
 *              IHXAudioStream::GetFormat
 *      Purpose:
 *      Return the stream's audio format.
 */
HX_RESULT CHXAudioStream::GetFormat
( 
    HXAudioFormat*      pAudioFormat
)
{
    if (!m_bAudioFormatKnown)
    {
        return HXR_NOT_INITIALIZED;
    }

⌨️ 快捷键说明

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