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

📄 mp3rend.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* ***** BEGIN LICENSE BLOCK ***** 
 * Version: RCSL 1.0/RPSL 1.0 
 *  
 * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
 *      
 * The contents of this file, and the files included with this file, are 
 * subject to the current version of the RealNetworks Public Source License 
 * Version 1.0 (the "RPSL") available at 
 * http://www.helixcommunity.org/content/rpsl unless you have licensed 
 * the file under the RealNetworks Community Source License Version 1.0 
 * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
 * in which case the RCSL will apply. You may also obtain the license terms 
 * directly from RealNetworks.  You may not use this file except in 
 * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
 * applicable to this file, the RCSL.  Please see the applicable RPSL or 
 * RCSL for the rights, obligations and limitations governing use of the 
 * contents of the file.  
 *  
 * This file is part of the Helix DNA Technology. RealNetworks is the 
 * developer of the Original Code and owns the copyrights in the portions 
 * it created. 
 *  
 * This file, and the files included with this file, is distributed and made 
 * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
 * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
 * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
 * 
 * Technology Compatibility Kit Test Suite(s) Location: 
 *    http://www.helixcommunity.org/content/tck 
 * 
 * Contributor(s): 
 *  
 * ***** END LICENSE BLOCK ***** */ 

// system
#include "hlxclib/stdio.h"
// include
#include "hxcom.h"              // IUnknown
#include "hxcomm.h"            // IHXCommonClassFactory
#include "ihxpckts.h"           // IHXBuffer, IHXPacket, IHXValues
#include "hxplugn.h"           // IHXPlugin
#include "hxrendr.h"           // IHXRenderer
#include "hxengin.h"           // IHXInterruptSafe
#include "hxcore.h"            // IHXStream
#include "hxausvc.h"           // Audio Services
#include "hxmon.h"             // IHXStatistics
#include "hxupgrd.h"           // IHXUpgradeCollection
#include "rmfftype.h"		// AudioTypeSpecificData
#include "hxprefs.h"
#include "hxcore.h"		// IHXUpdateProperties
#include "hxver.h"
// pnmisc
#include "hxstrutl.h"           // strcasecmp()
// rmpadec
#include "mpadecobj.h"          // MPEG Audio Decoder (selects fixed-pt or floating-pt based on HELIX_CONFIG_FIXEDPOINT)
// rmp3lib
#include "mp3format.h"          // MP3 formatter
// mpgcommon
#ifdef DEMUXER
#include "xmddemuxer.h"         // Demuxer
#include "xmdtypes.h"
#endif
#include "addupcol.h"
// mp3rend
#include "mp3rend.h"           // CRnMp3Ren
#include "pktparse.h"           // CPacketParser
#if defined (MPA_FMT_RAW)
#include "mpapktparse.h"        // CMpaPacketParser, C2250PacketParser
#endif /* #if defined (MPA_FMT_RAW) */
#if defined(MPA_FMT_DRAFT00)
#include "fmtpktparse.h"        // CFmtPacketParser
#endif /* #if defined(MPA_FMT_DRAFT00) */
#if defined(MPA_FMT_RFC3119)
#include "robpktparse.h"        // CRobustPacketParser
#endif /* #if defined(MPA_FMT_RFC3119) */
#include "hxdefpackethookhlp.h"

#include "adjtime.h"

// The value below is derived from trial and error as the lowest we can
// get away with on the platforms tested. Feel free to experiment with
// different values on your platform.
#define OPTIMAL_AUDIO_PUSHDOWN 160
#ifdef PCM_CAPTURE
#include <stdio.h>
#include "wavep.h"

static UINT32 g_dwTotalPcmBytes = 0;
static FILE  *fpOut = NULL;
#endif // PCM_CAPTURE


#if defined(HELIX_FEATURE_MIN_HEAP)
#define MAXIMUM_MP3_PREROLL 3000
#else
#define MAXIMUM_MP3_PREROLL 15000
#endif

///////////////////////////////////////////////////////////////////////////////
//  CRnMp3Ren static variables                      ref:  ff1rendr.h
//
//  These variables are passed to the RMA core to provide information about
//  this plug-in. They are required to be static in order to remain valid
//  for the lifetime of the plug-in.
//
const char* const CRnMp3Ren::zm_pDescription = MY_DESCRIPTION;
const char* const CRnMp3Ren::zm_pCopyright   = HXVER_COPYRIGHT;
const char* const CRnMp3Ren::zm_pMoreInfoURL = HXVER_MOREINFO;
const char* const CRnMp3Ren::zm_pStreamMimeTypes[] = MY_STREAM_MIME_TYPES;

///////////////////////////////////////////////////////////////////////////////
//  CRnMp3Ren::CRnMp3Ren                   ref:  ff1rendr.h
//
//  Constructor
//
CRnMp3Ren::CRnMp3Ren(void)
	: m_RefCount        (0),
	  m_pContext        (NULL),
      m_pClassFactory   (NULL),
      m_pStream         (NULL),
      m_pAudioPlayer    (NULL),
      m_pAudioStream    (NULL),
      m_pAudioPushdown2 (NULL),
      m_pDefAudStream   (NULL),
      m_pHeader         (NULL),      
      m_pPacketParser   (NULL),
      m_bInSeekMode     (FALSE),
      m_bDiscontinuity  (TRUE),
      m_wAudStream      (0),
      m_nPacketsNeeded  (0),
      m_bStarving       (0),
      m_bEndOfPackets   (0),
      m_ulNumPackets    (0),      
      m_pRegistry       (NULL),      
      m_ulPreroll       (0),
      m_ulRegistryID    (0),
      m_ulDelay         (0),
      m_lTimeLineOffset	(0),
      m_ulChannelsRegID (0),
      m_ulCodecRegID    (0),

      m_ulPacketsDecoded(0),
      m_ulFramesDecoded (0),
      m_ulBadPackets    (0),
      m_bStarted        (0),
      m_bTrustPackets(FALSE),

      m_pDefaultPacketHookHelper(NULL)
{

    memset(m_aAudStreamList, 0, sizeof(m_aAudStreamList));
}


///////////////////////////////////////////////////////////////////////////////
//  IHXPlugin::GetPluginInfo                                ref:  hxplugn.h
//
//  This routine returns descriptive information about the plug-in, most
//  of which is used in the About box of the user interface. It is called
//  when the RMA core application is launched.
//
STDMETHODIMP
CRnMp3Ren::GetPluginInfo(REF(int) bLoadMultiple,
                         REF(const char*) pDescription,
                         REF(const char*) pCopyright,
                         REF(const char*) pMoreInfoURL,
                         REF(UINT32) versionNumber)
{
	bLoadMultiple = TRUE;
	pDescription  = zm_pDescription;
	pCopyright    = zm_pCopyright;
	pMoreInfoURL  = zm_pMoreInfoURL;
	versionNumber = MY_PLUGIN_VERSION;
	
    return HXR_OK;
}

///////////////////////////////////////////////////////////////////////////////
//  IHXRenderer::GetRendererInfo                            ref:  hxrendr.h
//
//  This routine returns crucial information required to associate this
//  plug-in with a given stream MIME type. This information tells the HX
//  core which Renderer to use to display a particular type of stream. This
//  method is called when the RMA core application is launched.
//
STDMETHODIMP
CRnMp3Ren::GetRendererInfo(REF(const char**) pStreamMimeTypes,
                           REF(UINT32) initialGranularity)
{
	// Associate this Renderer with a given stream MIME type
	pStreamMimeTypes = (const char**) zm_pStreamMimeTypes;

	// Set frequency of OnTimeSync() updates
	initialGranularity = 50;
	
    return HXR_OK;
}


///////////////////////////////////////////////////////////////////////////////
//  IHXPlugin::InitPlugin                                   ref:  hxplugn.h
//
//  This routine performs initialization steps such as determining if
//  required interfaces are available. It is called when the RMA core 
//  application is launched, and whenever a stream associated with this
//  plug-in needs to be rendered.
//
STDMETHODIMP
CRnMp3Ren::InitPlugin(IUnknown* pHXCore)
{
    m_pContext = pHXCore;
    m_pContext->AddRef();
    
    // Store a reference to the IHXCommonClassFactory interface which is
    // used to create commonly used HX objects such as IHXPacket, 
    // IHXValues, and IHXBuffers.
	pHXCore->QueryInterface(IID_IHXCommonClassFactory, 
	                        (void**)&m_pClassFactory);
	if (!m_pClassFactory)
		return HXR_NOTIMPL;
	
    pHXCore->QueryInterface(IID_IHXRegistry, (void**)&m_pRegistry);

#ifdef DEMUXER
    if (m_pRegistry) m_pRegistry->AddInt("FirstPts", -1);
#endif
    
    return HXR_OK;
}


///////////////////////////////////////////////////////////////////////////////
//  IHXRenderer::StartStream                                ref:  hxrendr.h
//
//  The RMA core calls this routine to provide access to the stream and
//  player. It is called when the plug-in is being initialized.
//
STDMETHODIMP
CRnMp3Ren::StartStream(IHXStream *pStream,
                       IHXPlayer *pPlayer)
{
    m_bEndOfPackets = FALSE;

    m_pStream = pStream;
    m_pStream->AddRef();

    // Get interface to audio player
    if (HXR_OK != pPlayer->QueryInterface(IID_IHXAudioPlayer, (void**) &m_pAudioPlayer))
        return !HXR_OK;

    pPlayer->QueryInterface(IID_IHXAudioPushdown2, (void**) &m_pAudioPushdown2);
#ifdef HELIX_CONFIG_MIN_PCM_PUSHDOWN_BYTES
    m_pAudioPushdown2->SetAudioPushdown( OPTIMAL_AUDIO_PUSHDOWN );
#endif // HELIX_CONFIG_MIN_PUSHDOWN_BYTES

    return HXR_OK;
}

///////////////////////////////////////////////////////////////////////////////
//  IHXRenderer::OnHeader                                   ref:  hxrendr.h
//
//  This routine is passed the stream header object created by the associated
//  file format plug-in. Use the methods defined in the IHXValues interface
//  to access the stream header data. This method is called from the HX
//  core when the plug-in is being initialized.
//
STDMETHODIMP
CRnMp3Ren::OnHeader(IHXValues* pStreamHeaderObj)
{
    UINT32  ulAvgBitRate = 0,
            ulAvgPacketSize = 0,
            ulStreaming = 0,
            ulSampRate = 0,
            ulChannels = 0;

    HX_RESULT  pr;
    pr = CheckStreamVersions(pStreamHeaderObj);
    
    if (HXR_OK != pr)
        return pr;
        
    m_pHeader = pStreamHeaderObj;
    m_pHeader->AddRef();

    pStreamHeaderObj->GetPropertyULONG32("AvgBitRate",      ulAvgBitRate);
    pStreamHeaderObj->GetPropertyULONG32("AvgPacketSize",   ulAvgPacketSize);
    pStreamHeaderObj->GetPropertyULONG32("SampleRate",      ulSampRate);
    pStreamHeaderObj->GetPropertyULONG32("NumChannels",     ulChannels);
    pStreamHeaderObj->GetPropertyULONG32("Delay",           m_ulDelay);

    pStreamHeaderObj->SetPropertyULONG32("IsAudioStream",   1);

    // Setup preroll
    // Set to default value if not set in stream header.
    m_ulPreroll = 0;
    pStreamHeaderObj->GetPropertyULONG32("Preroll", m_ulPreroll);
    if (m_ulPreroll == 0)
    {
	// Preroll is not set for this stream - assume default
	m_ulPreroll = MY_DFLT_PREROLL;
        pStreamHeaderObj->SetPropertyULONG32("Preroll", m_ulPreroll);
    }
    // Check that stream header value is not over our max.
    else if( m_ulPreroll > MAXIMUM_MP3_PREROLL )
    {
        m_ulPreroll = MAXIMUM_MP3_PREROLL;
        pStreamHeaderObj->SetPropertyULONG32("Preroll", m_ulPreroll);
    }
    
    // Check standard stream properties if custom properties fail
    if (!ulSampRate)
        pStreamHeaderObj->GetPropertyULONG32("SamplesPerSecond", ulSampRate);

    if (!ulChannels)
        pStreamHeaderObj->GetPropertyULONG32("Channels", ulChannels);

    // Try Opaque Data for SampleRate and/or channels
    if (!ulSampRate || !ulChannels)
    {
    	IHXBuffer* pOpaqueData = NULL;

	if (SUCCEEDED(pStreamHeaderObj->GetPropertyBuffer("OpaqueData", 
							  pOpaqueData)) &&
	    pOpaqueData)
	{
	    AudioTypeSpecificData audioData;

	    memset(&audioData, 0, sizeof(audioData));
		    
	    audioData.unpack(pOpaqueData->GetBuffer(), 
			     pOpaqueData->GetSize());
		    
	    if (audioData.numChannels)
	    {
		ulChannels = audioData.numChannels;
	    }

	    if (audioData.sampleRate)
	    {
		ulSampRate = audioData.sampleRate;
	    }
	}

	HX_RELEASE(pOpaqueData);
    }
    
    // Check MIME type
    IHXBuffer* pStringObj = NULL;
    m_pClassFactory->CreateInstance(CLSID_IHXBuffer,
                                     (void**)&pStringObj);
    if (pStringObj)
    {
        pStreamHeaderObj->GetPropertyCString("MimeType", pStringObj);
        SetPacketFormat((const char*)(pStringObj->GetBuffer()));

        // Check if we know these packets can be trusted. These
        // are the mime types that we *know* came from our file format
        const char* pszMimeType = (const char*) pStringObj->GetBuffer();
        if (!strcmp(pszMimeType, "audio/MPEG-ELEMENTARY")    ||
            !strcmp(pszMimeType, "audio/MPEG-ELEMENTARY-RN") ||
            !strcmp(pszMimeType, "audio/X-MP3-draft-00")     ||
            !strcmp(pszMimeType, "audio/X-MP3-draft-00-RN"))
        {
            m_bTrustPackets = TRUE;
        }
        // Set this in the packet parser
        m_pPacketParser->SetTrustPackets(m_bTrustPackets);
        
        HX_RELEASE(pStringObj);
    }
    
    if(m_pPacketParser)
    {
        m_pPacketParser->Init(this, m_pClassFactory);
    }

    if (!ulAvgPacketSize)
        ulAvgPacketSize = 1200;

    UINT32 dwAudBytes = m_ulPreroll * ulAvgBitRate / 8000;
    m_nPacketsNeeded = (UINT8)(dwAudBytes / ulAvgPacketSize);
    
    if (!m_pAudioStream && ulChannels && ulSampRate)
    {        
        // Create our audio stream
        m_pAudioPlayer->CreateAudioStream(&m_aAudStreamList[m_wAudStream]);
        m_pAudioStream = m_aAudStreamList[m_wAudStream];

        if (!m_pAudioStream)
            return HXR_OK;
        // Let's override the default class factory and use the one in
        // client/audiosvc that caches our pcm buffers and avoids 
        // unnecessary heap fragmentation.

        IHXCommonClassFactory* pCommonClassFactory;
        if (HXR_OK == m_pAudioStream->QueryInterface(IID_IHXCommonClassFactory, 
				(void**)&pCommonClassFactory))
        {
	    if( m_pPacketParser )
	       m_pPacketParser->OverrideFactory(pCommonClassFactory);
	    pCommonClassFactory->Release();
        }

        // Init PCM device
        HXAudioFormat audioFmt;
        audioFmt.uChannels = (unsigned short)ulChannels;
        audioFmt.uBitsPerSample	= 16;
        audioFmt.ulSamplesPerSec = ulSampRate;
        audioFmt.uMaxBlockSize = (unsigned short)(1152 *
                                 (audioFmt.uBitsPerSample>>3) *
                                 audioFmt.uChannels);

        m_pAudioStream->Init(&audioFmt, m_pHeader);

        m_pAudioStream->AddDryNotification(this);
        m_bDiscontinuity = TRUE;
    }
    
#if 0
    // Create a default stream to prevent rebuffering
    else
    {
        // If the server does not send these properties
        if (!ulSampRate)
            ulSampRate = 44100;

        if (!ulChannels)
            ulChannels = 2;

        ulSampRate = min(ulSampRate, 44100);
        ulChannels = min(ulChannels, 2);

        // Create our audio stream
        m_pAudioPlayer->CreateAudioStream(&m_pDefAudStream);

        if (!m_pDefAudStream)
            return HXR_OK;

        // Init PCM device
        HXAudioFormat audioFmt;
        audioFmt.uChannels = (unsigned short)ulChannels;
        audioFmt.uBitsPerSample	= 16;
        audioFmt.ulSamplesPerSec = ulSampRate;
        audioFmt.uMaxBlockSize = (unsigned short)(1152 *
                                 (audioFmt.uBitsPerSample>>3) *
                                 audioFmt.uChannels);

        m_pDefAudStream->Init(&audioFmt, m_pHeader);
    }
#endif


    return HXR_OK;
}


///////////////////////////////////////////////////////////////////////////////
//  IHXRenderer::OnBegin                                   ref:  hxrendr.h
//

⌨️ 快捷键说明

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