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

📄 mp3rend.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//  This routine is called by the RMA core to inform the Renderer that 
//  playback has just begun or has been resumed. The stream's time value just
//  after resuming the playback is provided.
//
STDMETHODIMP
CRnMp3Ren::OnBegin(UINT32 timeAfterBegin)
{
    #ifdef _WIN32
    #ifdef _DEBUG
    TCHAR szTmp[128];
    wsprintf(szTmp, TEXT("OnBegin timeAfter %ld\n"),timeAfterBegin);
    OutputDebugString(szTmp);
    #endif
    #endif

    if(m_pPacketParser)
    {
        m_pPacketParser->Begin(timeAfterBegin);
    }

    return HXR_OK;
}

///////////////////////////////////////////////////////////////////////////////
//  IHXRenderer::GetDisplayType                             ref:  hxrendr.h
//
//  This routine returns the preferred display type of the Renderer. Any
//  other additional information necessary for the display can also be
//  provided. This method is called by the RMA core when the plug-in is being
//  initialized.
//
STDMETHODIMP
CRnMp3Ren::GetDisplayType(REF(HX_DISPLAY_TYPE) displayType,
                          REF(IHXBuffer*) pDisplayInfo)
{
    displayType = HX_DISPLAY_NONE;

	return HXR_OK;
}

///////////////////////////////////////////////////////////////////////////////
//  IHXRenderer::OnPacket                                   ref:  hxrendr.h
//
//  This routine is passed the packet object streamed by the associated
//  file format plug-in. It is called by the RMA core when a packet is due
//  to be delivered. In most cases, the actual rendering of the packet is
//  done in this method. The stream's time offset with respect to the master
//  timeline is provided.
//
STDMETHODIMP
CRnMp3Ren::OnPacket(IHXPacket* pPacketObj,
                    INT32 streamOffsetTime)
{
    if (m_bInSeekMode)
        return HXR_OK;
    
    if(!m_pPacketParser)
       return HXR_NOT_INITIALIZED;

    if (!pPacketObj)
        return HXR_INVALID_PARAMETER;
    
    #ifdef _DEBUG
    ++m_ulPacketsDecoded;
    #endif

    m_lTimeLineOffset = streamOffsetTime;

    HX_RESULT res = m_pPacketParser->AddPacket(pPacketObj, 0);

    if(FAILED(res))
    {            
        return HXR_OK;
    }

    if(m_pDefaultPacketHookHelper)
	m_pDefaultPacketHookHelper->OnPacket(pPacketObj);
#if 0
#ifdef HELIX_CONFIG_ONLY_DECODE_IF_DRY
    // Only decode audio if audio device is low
    // IMPORTANT NOTE: since the implementation of AddPacket in the parser
    // does not have a queue, in general if we return here and we do NOT get
    // an OnDryNotification, the next time OnPacket is called, it will clobber
    // an undecoded packet. As it turns out, this doesn't seem to happen in
    // testing to date, but this is a TBD.
    // Testing without this code seems to show that we can get the same results
    // without it. Nevertheless, we are going to leave this code here until an
    // absolute final decision can be made on the best solution.
    UINT32 ulBytesInAudioDevice = 0;
    m_pAudioPushdown2->GetCurrentAudioDevicePushdown( ulBytesInAudioDevice );
    if( ulBytesInAudioDevice >= OPTIMAL_AUDIO_PUSHDOWN )
    {
       return HXR_OK;
    }
#endif // HELIX_CONFIG_ONLY_DECODE_IF_DRY
#endif // 0

    // Decode and render all frames available
    HX_RESULT theErr = m_pPacketParser->RenderAll();
    if( theErr == HXR_OUTOFMEMORY )
    {
        return theErr;
    }

    // Handle rebuffering
    if (m_bStarving)
    {
        // Waiting for more packets
        if (++m_ulNumPackets < m_nPacketsNeeded)
        {
            m_pStream->ReportRebufferStatus(m_nPacketsNeeded, (UINT8)m_ulNumPackets);
            return HXR_OK;
        }

        #ifdef _WIN32
        #ifdef _DEBUG
        OutputDebugString(TEXT("Rebuffer Complete\n"));
        #endif
        #endif

        m_pStream->ReportRebufferStatus(m_nPacketsNeeded, m_nPacketsNeeded);
        m_bStarving = FALSE;
    }

    return HXR_OK;
}

///////////////////////////////////////////////////////////////////////////////
//  IHXRenderer::OnTimeSync                                 ref:  hxrendr.h
//
//  This routine is called by the RMA core periodically passing the current
//  playback time. The Renderer should use this time value to synchronize the
//  playback of various streams.
//
STDMETHODIMP
CRnMp3Ren::OnTimeSync(UINT32 currentPlayBackTime)
{
#if 0
    #ifdef _DEBUG
    #ifdef _WIN32
    if (!m_bStarted)
    {
        TCHAR szTmp[128];
        wsprintf(szTmp, TEXT("OnTimeSync %ld Preroll %ld\n"),
                         currentPlayBackTime, m_ulPacketsDecoded*m_dFrameTime);
        OutputDebugString(szTmp);

        m_bStarted = 1;
    }
    #endif
    #endif
#endif

    return HXR_OK;
}

///////////////////////////////////////////////////////////////////////////////
//  IHXRenderer::OnPreSeek                                  ref:  hxrendr.h
//
//  This routine is called by the RMA core before a seek is about to occur.
//  The stream's time value just before the seek, and the time value just
//  after the seek are provided.
//
STDMETHODIMP
CRnMp3Ren::OnPreSeek(UINT32 timeBeforeSeek,
                     UINT32 timeAfterSeek)
{
    #ifdef _WIN32
    #ifdef _DEBUG
    TCHAR szTmp[128];
    wsprintf(szTmp, TEXT("OnPreSeek timeb4 %ld timeAfter %ld\n"), timeBeforeSeek, timeAfterSeek);
    OutputDebugString(szTmp);
    m_ulPacketsDecoded = 0;
    m_ulFramesDecoded = 0;
    m_bStarted = 0;
    #endif
    #endif

    // Wait for decode thread to become idle and
    // release all buffered packets
    m_bInSeekMode = TRUE;
    m_bDiscontinuity = TRUE;

    if(m_pPacketParser)
    {
        m_pPacketParser->PreSeek();
    }

#ifdef DEMUXER
    if (m_pRegistry) m_pRegistry->SetIntByName("FirstPts", -1);
#endif

    return HXR_OK;
}


///////////////////////////////////////////////////////////////////////////////
//  IHXRenderer::OnPostSeek                                 ref:  hxrendr.h
//
//  This routine is called by the RMA core just after a seek has occured.
//  The stream's time value just before the seek, and the time value just
//  after the seek are provided.
//
STDMETHODIMP
CRnMp3Ren::OnPostSeek(UINT32 timeBeforeSeek,
                      UINT32 timeAfterSeek)
{
    #ifdef _WIN32
    #ifdef _DEBUG
    TCHAR szTmp[128];
    wsprintf(szTmp, TEXT("OnPostSeek timeb4 %ld timeAfter %ld\n"), timeBeforeSeek, timeAfterSeek);
    OutputDebugString(szTmp);
    #endif
    #endif

    m_bInSeekMode = FALSE;

    if(m_pPacketParser)
    {
        m_pPacketParser->PostSeek(timeAfterSeek);
    }
    return HXR_OK;
}

///////////////////////////////////////////////////////////////////////////////
//  IHXRenderer::OnPause                                    ref:  hxrendr.h
//
//  This routine is called by the RMA core just after a pause has occured.
//  The stream's time value just before pausing is provided.
//
STDMETHODIMP
CRnMp3Ren::OnPause(UINT32 timeBeforePause)
{
    #ifdef _WIN32
    #ifdef _DEBUG
    TCHAR szTmp[128];
    wsprintf(szTmp, TEXT("OnPause timeb4 %ld\n"), timeBeforePause);
    OutputDebugString(szTmp);
    #endif
    #endif

    return HXR_OK;
}

///////////////////////////////////////////////////////////////////////////////
//  IHXRenderer::OnBuffering                                ref:  hxrendr.h
//
//  This routine is called by the RMA core to inform the Renderer that
//  buffering of data is occuring. The reason for buffering (e.g. start-up
//  of stream, seek has occured, network congestion, etc.), as well as the
//  percentage of the buffering process complete are provided.
//
STDMETHODIMP
CRnMp3Ren::OnBuffering(UINT32 reason,
                       UINT16 percentComplete)
{
    #ifdef _WIN32
    #ifdef _DEBUG
    TCHAR szTmp[128];
    wsprintf(szTmp, TEXT("OnBuffer percent %d\n"), percentComplete);
    OutputDebugString(szTmp);
    #endif
    #endif
    return HXR_OK;
}

///////////////////////////////////////////////////////////////////////////////
//  IHXRenderer::OnEndofPackets                             ref:  hxrendr.h
//
//  Called by client engine to inform the renderer that all the
//  packets have been delivered. However, if the user seeks before
//  EndStream() is called, renderer may start getting packets again
//  and the client engine will eventually call this function again.
//
STDMETHODIMP
CRnMp3Ren::OnEndofPackets(void)
{
    m_bEndOfPackets = TRUE;
    if (m_bStarving)
    {
        m_bStarving = FALSE;
        m_pStream->ReportRebufferStatus(m_nPacketsNeeded, m_nPacketsNeeded);
    }

    if(m_pPacketParser)
    {
        m_pPacketParser->EndOfPackets();
    }

    if(m_pDefaultPacketHookHelper)
	m_pDefaultPacketHookHelper->OnEndOfPackets();

    return HXR_OK;
}


///////////////////////////////////////////////////////////////////////////////
//  IHXRenderer::EndStream                                  ref:  hxrendr.h
//
//  This routine is called by the RMA core when the rendering of the stream
//  has completed. Deallocation of any resources should be done here.
//
STDMETHODIMP
CRnMp3Ren::EndStream(void)
{
    HX_RELEASE(m_pContext);
    HX_RELEASE(m_pClassFactory);

    HX_DELETE(m_pPacketParser);

    if(m_pDefaultPacketHookHelper)
    {
	m_pDefaultPacketHookHelper->Terminate();
	HX_RELEASE(m_pDefaultPacketHookHelper);
    }

#ifdef DEMUXER
    if (m_pRegistry)
        m_pRegistry->DeleteByName("FirstPts");
#endif

    for (int i=0; i<=m_wAudStream; i++)
        HX_RELEASE(m_aAudStreamList[i]);

    HX_RELEASE(m_pDefAudStream);
    HX_RELEASE(m_pStream);
    HX_RELEASE(m_pHeader);
    HX_RELEASE(m_pAudioPlayer);
    HX_RELEASE(m_pAudioPushdown2);
    HX_RELEASE(m_pRegistry);

    #ifdef PCM_CAPTURE
    if (fpOut)
    {
        write_pcm_tailer_wave(fpOut, g_dwTotalPcmBytes);
        fclose(fpOut);
        fpOut = NULL;
    }
    #endif //PCM_CAPTURE

    return HXR_OK;
}

///////////////////////////////////////////////////////////////////////////////
//  IHXDryNotification::OnDryNotification                   ref:  hxausvc.h
//
//  This function is called when it is time to write to audio device 
//  and there is not enough data in the audio stream. The renderer can
//  then decide to add more data to the audio stream. This should be 
//  done synchronously within the call to this function.
//  It is OK to not write any data. Silence will be played instead.
//
STDMETHODIMP
CRnMp3Ren::OnDryNotification(UINT32 /*IN*/ ulCurrentStreamTime,
                             UINT32 /*IN*/ ulMinimumDurationRequired)
{
    // We do not set our rebuffer flag at the end of a stream
    if (m_bEndOfPackets || !m_pStream)
        return HXR_OK;

    #ifdef _DEBUG
        #ifdef _WIN32
        TCHAR szTmp[128];
        wsprintf(szTmp, TEXT("DryNot: dur %ld\n"), ulMinimumDurationRequired);
        OutputDebugString(szTmp);
        #endif
    #endif

    // NOTE: We still need to scrutinize this low-heap solution because it
    // skips the rebuffering call. XXXJHHB
#if defined(HELIX_CONFIG_ONLY_DECODE_IF_DRY)
    HX_RESULT theErr = m_pPacketParser->RenderAll();
    if( theErr == HXR_OUTOFMEMORY )
    {
        return theErr;
    }
#else
    // Rebuffer if we are late
    if (ulCurrentStreamTime+m_ulPreroll > m_ulDelay)
    {
        m_ulNumPackets = 0;
        m_bStarving = TRUE;
        
        if(m_pPacketParser)
        {
            m_nPacketsNeeded = (UINT8)(ulMinimumDurationRequired / 
                                m_pPacketParser->GetTimePerPkt() + 1);
        }
        m_pStream->ReportRebufferStatus(m_nPacketsNeeded, 0);
    }
#endif

    return HXR_OK;
}

STDMETHODIMP
CRnMp3Ren::InitializeStatistics(UINT32 ulRegistryID)
{
#if defined(HELIX_FEATURE_STATS)
    m_ulRegistryID = ulRegistryID;
    m_ulChannelsRegID = 0;

    m_ulCodecRegID = 0;

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

STDMETHODIMP
CRnMp3Ren::UpdateStatistics()
{
#if defined(HELIX_FEATURE_STATS)
    if (m_pRegistry)
    {
        char szRegistryEntry[MAX_DISPLAY_NAME] = "0"; /* Flawfinder: ignore */

        // Get the registry name for the specified id
        IHXBuffer* pszRegistryName = NULL;
        UINT32 ulChannels = m_pPacketParser ? m_pPacketParser->GetChannels() : 0;
        if (!m_ulChannelsRegID && HXR_OK == m_pRegistry->GetPropName(m_ulRegistryID, pszRegistryName))
        {
            // Get the channel registry and set the value
            SafeSprintf(szRegistryEntry, MAX_DISPLAY_NAME, "%s.Channels", pszRegistryName->GetBuffer());        
            m_ulChannelsRegID = m_pRegistry->AddInt (szRegistryEntry, ulChannels);
            HX_RELEASE(pszRegistryName);
        }
        // Set the channels value based on id
        else
            m_pRegistry->SetIntById(m_ulChannelsRegID, ulChannels);

        // Set the codec name in registry
        if (!m_ulCodecRegID)
        {
            // Get the current registry key name
            if (!m_ulCodecRegID && (HXR_OK == m_pRegistry->GetPropName(m_ulRegistryID, pszRegistryName)))
            {
                SafeSprintf(szRegistryEntry, MAX_DISPLAY_NAME, "%s.Codec", pszRegistryName->GetBuffer());
            
                IHXBuffer *pValue = NULL;
                m_pClassFactory->CreateInstance(CLSID_IHXBuffer, (void**) &pValue);
            
                if (pValue)
                {
                    UCHAR pCodecName[] = "MPEG Audio";

                    pValue->Set((const UCHAR*)pCodecName, strlen((const char*)pCodecName)+1);
                    m_ulCodecRegID = m_pRegistry->AddStr(szRegistryEntry, pValue);

                    pValue->Release();
                }
            
                pszRegistryName->Release();
                pszRegistryName = NULL;
            }
        }
        else
        {
            IHXBuffer *pValue = NULL;

⌨️ 快捷键说明

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