mp3rend.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:42k
源码类别:

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. // system
  36. #include "hlxclib/stdio.h"
  37. // include
  38. #include "hxcom.h"              // IUnknown
  39. #include "hxcomm.h"            // IHXCommonClassFactory
  40. #include "ihxpckts.h"           // IHXBuffer, IHXPacket, IHXValues
  41. #include "hxplugn.h"           // IHXPlugin
  42. #include "hxrendr.h"           // IHXRenderer
  43. #include "hxengin.h"           // IHXInterruptSafe
  44. #include "hxcore.h"            // IHXStream
  45. #include "hxausvc.h"           // Audio Services
  46. #include "hxmon.h"             // IHXStatistics
  47. #include "hxupgrd.h"           // IHXUpgradeCollection
  48. #include "rmfftype.h" // AudioTypeSpecificData
  49. #include "hxprefs.h"
  50. #include "hxcore.h" // IHXUpdateProperties
  51. #include "hxver.h"
  52. // pnmisc
  53. #include "hxstrutl.h"           // strcasecmp()
  54. // rmpadec
  55. #include "mpadecobj.h"          // MPEG Audio Decoder (selects fixed-pt or floating-pt based on HELIX_CONFIG_FIXEDPOINT)
  56. // rmp3lib
  57. #include "mp3format.h"          // MP3 formatter
  58. // mpgcommon
  59. #ifdef DEMUXER
  60. #include "xmddemuxer.h"         // Demuxer
  61. #include "xmdtypes.h"
  62. #endif
  63. #include "addupcol.h"
  64. // mp3rend
  65. #include "mp3rend.h"           // CRnMp3Ren
  66. #include "pktparse.h"           // CPacketParser
  67. #if defined (MPA_FMT_RAW) || defined (MPA_FMT_RFC2250) || defined (MPA_FMT_SYSTEM) || defined (MPA_FMT_RFC2250_SYSTEM)
  68. #include "mpapktparse.h"        // CMpaPacketParser, C2250PacketParser
  69. #endif /* #if defined (MPA_FMT_RAW) */
  70. #if defined(MPA_FMT_DRAFT00)
  71. #include "fmtpktparse.h"        // CFmtPacketParser
  72. #endif /* #if defined(MPA_FMT_DRAFT00) */
  73. #if defined(MPA_FMT_RFC3119)
  74. #include "robpktparse.h"        // CRobustPacketParser
  75. #endif /* #if defined(MPA_FMT_RFC3119) */
  76. #include "hxdefpackethookhlp.h"
  77. #include "adjtime.h"
  78. // The value below is derived from trial and error as the lowest we can
  79. // get away with on the platforms tested. Feel free to experiment with
  80. // different values on your platform.
  81. #define OPTIMAL_AUDIO_PUSHDOWN 160
  82. #ifdef PCM_CAPTURE
  83. #include <stdio.h>
  84. #include "wavep.h"
  85. static UINT32 g_dwTotalPcmBytes = 0;
  86. static FILE  *fpOut = NULL;
  87. #endif // PCM_CAPTURE
  88. #if defined(HELIX_FEATURE_MIN_HEAP)
  89. #define MAXIMUM_MP3_PREROLL 3000
  90. #else
  91. #define MAXIMUM_MP3_PREROLL 15000
  92. #endif
  93. ///////////////////////////////////////////////////////////////////////////////
  94. //  CRnMp3Ren static variables                      ref:  ff1rendr.h
  95. //
  96. //  These variables are passed to the RMA core to provide information about
  97. //  this plug-in. They are required to be static in order to remain valid
  98. //  for the lifetime of the plug-in.
  99. //
  100. const char* const CRnMp3Ren::zm_pDescription = MY_DESCRIPTION;
  101. const char* const CRnMp3Ren::zm_pCopyright   = HXVER_COPYRIGHT;
  102. const char* const CRnMp3Ren::zm_pMoreInfoURL = HXVER_MOREINFO;
  103. const char* const CRnMp3Ren::zm_pStreamMimeTypes[] = MY_STREAM_MIME_TYPES;
  104. ///////////////////////////////////////////////////////////////////////////////
  105. //  CRnMp3Ren::CRnMp3Ren                   ref:  ff1rendr.h
  106. //
  107. //  Constructor
  108. //
  109. CRnMp3Ren::CRnMp3Ren(void)
  110. : m_RefCount        (0),
  111.   m_pContext        (NULL),
  112.       m_pClassFactory   (NULL),
  113.       m_pStream         (NULL),
  114.       m_pAudioPlayer    (NULL),
  115.       m_pAudioStream    (NULL),
  116.       m_pAudioPushdown2 (NULL),
  117.       m_pDefAudStream   (NULL),
  118.       m_pHeader         (NULL),      
  119.       m_pPacketParser   (NULL),
  120.       m_bInSeekMode     (FALSE),
  121.       m_bDiscontinuity  (TRUE),
  122.       m_wAudStream      (0),
  123.       m_nPacketsNeeded  (0),
  124.       m_bStarving       (0),
  125.       m_bEndOfPackets   (0),
  126.       m_ulNumPackets    (0),      
  127.       m_pRegistry       (NULL),      
  128.       m_ulPreroll       (0),
  129.       m_ulRegistryID    (0),
  130.       m_ulDelay         (0),
  131.       m_lTimeLineOffset (0),
  132.       m_ulChannelsRegID (0),
  133.       m_ulCodecRegID    (0),
  134.       m_ulPacketsDecoded(0),
  135.       m_ulFramesDecoded (0),
  136.       m_ulBadPackets    (0),
  137.       m_bStarted        (0),
  138.       m_bTrustPackets(FALSE),
  139.       m_pDefaultPacketHookHelper(NULL)
  140. {
  141.     memset(m_aAudStreamList, 0, sizeof(m_aAudStreamList));
  142. }
  143. ///////////////////////////////////////////////////////////////////////////////
  144. //  IHXPlugin::GetPluginInfo                                ref:  hxplugn.h
  145. //
  146. //  This routine returns descriptive information about the plug-in, most
  147. //  of which is used in the About box of the user interface. It is called
  148. //  when the RMA core application is launched.
  149. //
  150. STDMETHODIMP
  151. CRnMp3Ren::GetPluginInfo(REF(int) bLoadMultiple,
  152.                          REF(const char*) pDescription,
  153.                          REF(const char*) pCopyright,
  154.                          REF(const char*) pMoreInfoURL,
  155.                          REF(UINT32) versionNumber)
  156. {
  157. bLoadMultiple = TRUE;
  158. pDescription  = zm_pDescription;
  159. pCopyright    = zm_pCopyright;
  160. pMoreInfoURL  = zm_pMoreInfoURL;
  161. versionNumber = MY_PLUGIN_VERSION;
  162.     return HXR_OK;
  163. }
  164. ///////////////////////////////////////////////////////////////////////////////
  165. //  IHXRenderer::GetRendererInfo                            ref:  hxrendr.h
  166. //
  167. //  This routine returns crucial information required to associate this
  168. //  plug-in with a given stream MIME type. This information tells the HX
  169. //  core which Renderer to use to display a particular type of stream. This
  170. //  method is called when the RMA core application is launched.
  171. //
  172. STDMETHODIMP
  173. CRnMp3Ren::GetRendererInfo(REF(const char**) pStreamMimeTypes,
  174.                            REF(UINT32) initialGranularity)
  175. {
  176. // Associate this Renderer with a given stream MIME type
  177. pStreamMimeTypes = (const char**) zm_pStreamMimeTypes;
  178. // Set frequency of OnTimeSync() updates
  179. initialGranularity = 50;
  180.     return HXR_OK;
  181. }
  182. ///////////////////////////////////////////////////////////////////////////////
  183. //  IHXPlugin::InitPlugin                                   ref:  hxplugn.h
  184. //
  185. //  This routine performs initialization steps such as determining if
  186. //  required interfaces are available. It is called when the RMA core 
  187. //  application is launched, and whenever a stream associated with this
  188. //  plug-in needs to be rendered.
  189. //
  190. STDMETHODIMP
  191. CRnMp3Ren::InitPlugin(IUnknown* pHXCore)
  192. {
  193.     m_pContext = pHXCore;
  194.     m_pContext->AddRef();
  195.     
  196.     // Store a reference to the IHXCommonClassFactory interface which is
  197.     // used to create commonly used HX objects such as IHXPacket, 
  198.     // IHXValues, and IHXBuffers.
  199. pHXCore->QueryInterface(IID_IHXCommonClassFactory, 
  200.                         (void**)&m_pClassFactory);
  201. if (!m_pClassFactory)
  202. return HXR_NOTIMPL;
  203.     pHXCore->QueryInterface(IID_IHXRegistry, (void**)&m_pRegistry);
  204. #ifdef DEMUXER
  205.     if (m_pRegistry) m_pRegistry->AddInt("FirstPts", -1);
  206. #endif
  207.     
  208.     return HXR_OK;
  209. }
  210. ///////////////////////////////////////////////////////////////////////////////
  211. //  IHXRenderer::StartStream                                ref:  hxrendr.h
  212. //
  213. //  The RMA core calls this routine to provide access to the stream and
  214. //  player. It is called when the plug-in is being initialized.
  215. //
  216. STDMETHODIMP
  217. CRnMp3Ren::StartStream(IHXStream *pStream,
  218.                        IHXPlayer *pPlayer)
  219. {
  220.     m_bEndOfPackets = FALSE;
  221.     m_pStream = pStream;
  222.     m_pStream->AddRef();
  223.     // Get interface to audio player
  224.     if (HXR_OK != pPlayer->QueryInterface(IID_IHXAudioPlayer, (void**) &m_pAudioPlayer))
  225.         return !HXR_OK;
  226.     pPlayer->QueryInterface(IID_IHXAudioPushdown2, (void**) &m_pAudioPushdown2);
  227. #ifdef HELIX_CONFIG_MIN_PCM_PUSHDOWN_BYTES
  228.     m_pAudioPushdown2->SetAudioPushdown( OPTIMAL_AUDIO_PUSHDOWN );
  229. #endif // HELIX_CONFIG_MIN_PUSHDOWN_BYTES
  230.     return HXR_OK;
  231. }
  232. ///////////////////////////////////////////////////////////////////////////////
  233. //  IHXRenderer::OnHeader                                   ref:  hxrendr.h
  234. //
  235. //  This routine is passed the stream header object created by the associated
  236. //  file format plug-in. Use the methods defined in the IHXValues interface
  237. //  to access the stream header data. This method is called from the HX
  238. //  core when the plug-in is being initialized.
  239. //
  240. STDMETHODIMP
  241. CRnMp3Ren::OnHeader(IHXValues* pStreamHeaderObj)
  242. {
  243.     UINT32  ulAvgBitRate = 0,
  244.             ulAvgPacketSize = 0,
  245.             ulStreaming = 0,
  246.             ulSampRate = 0,
  247.             ulChannels = 0;
  248.     HX_RESULT  pr;
  249.     pr = CheckStreamVersions(pStreamHeaderObj);
  250.     
  251.     if (HXR_OK != pr)
  252.         return pr;
  253.         
  254.     m_pHeader = pStreamHeaderObj;
  255.     m_pHeader->AddRef();
  256.     pStreamHeaderObj->GetPropertyULONG32("AvgBitRate",      ulAvgBitRate);
  257.     pStreamHeaderObj->GetPropertyULONG32("AvgPacketSize",   ulAvgPacketSize);
  258.     pStreamHeaderObj->GetPropertyULONG32("SampleRate",      ulSampRate);
  259.     pStreamHeaderObj->GetPropertyULONG32("NumChannels",     ulChannels);
  260.     pStreamHeaderObj->GetPropertyULONG32("Delay",           m_ulDelay);
  261.     pStreamHeaderObj->SetPropertyULONG32("IsAudioStream",   1);
  262.     // Setup preroll
  263.     // Set to default value if not set in stream header.
  264.     m_ulPreroll = 0;
  265.     pStreamHeaderObj->GetPropertyULONG32("Preroll", m_ulPreroll);
  266.     if (m_ulPreroll == 0)
  267.     {
  268. // Preroll is not set for this stream - assume default
  269. m_ulPreroll = MY_DFLT_PREROLL;
  270.         pStreamHeaderObj->SetPropertyULONG32("Preroll", m_ulPreroll);
  271.     }
  272.     // Check that stream header value is not over our max.
  273.     else if( m_ulPreroll > MAXIMUM_MP3_PREROLL )
  274.     {
  275.         m_ulPreroll = MAXIMUM_MP3_PREROLL;
  276.         pStreamHeaderObj->SetPropertyULONG32("Preroll", m_ulPreroll);
  277.     }
  278.     
  279.     // Check standard stream properties if custom properties fail
  280.     if (!ulSampRate)
  281.         pStreamHeaderObj->GetPropertyULONG32("SamplesPerSecond", ulSampRate);
  282.     if (!ulChannels)
  283.         pStreamHeaderObj->GetPropertyULONG32("Channels", ulChannels);
  284.     // Try Opaque Data for SampleRate and/or channels
  285.     if (!ulSampRate || !ulChannels)
  286.     {
  287.      IHXBuffer* pOpaqueData = NULL;
  288. if (SUCCEEDED(pStreamHeaderObj->GetPropertyBuffer("OpaqueData", 
  289.   pOpaqueData)) &&
  290.     pOpaqueData)
  291. {
  292.     AudioTypeSpecificData audioData;
  293.     memset(&audioData, 0, sizeof(audioData));
  294.     
  295.     audioData.unpack(pOpaqueData->GetBuffer(), 
  296.      pOpaqueData->GetSize());
  297.     
  298.     if (audioData.numChannels)
  299.     {
  300. ulChannels = audioData.numChannels;
  301.     }
  302.     if (audioData.sampleRate)
  303.     {
  304. ulSampRate = audioData.sampleRate;
  305.     }
  306. }
  307. HX_RELEASE(pOpaqueData);
  308.     }
  309.     
  310.     // Check MIME type
  311.     IHXBuffer* pStringObj = NULL;
  312.     m_pClassFactory->CreateInstance(CLSID_IHXBuffer,
  313.                                      (void**)&pStringObj);
  314.     if (pStringObj)
  315.     {
  316.         pStreamHeaderObj->GetPropertyCString("MimeType", pStringObj);
  317.         SetPacketFormat((const char*)(pStringObj->GetBuffer()));
  318.         // Check if we know these packets can be trusted. These
  319.         // are the mime types that we *know* came from our file format
  320.         const char* pszMimeType = (const char*) pStringObj->GetBuffer();
  321.         if (!strcmp(pszMimeType, "audio/MPEG-ELEMENTARY")    ||
  322.             !strcmp(pszMimeType, "audio/MPEG-ELEMENTARY-RN") ||
  323.             !strcmp(pszMimeType, "audio/X-MP3-draft-00")     ||
  324.             !strcmp(pszMimeType, "audio/X-MP3-draft-00-RN"))
  325.         {
  326.             m_bTrustPackets = TRUE;
  327.         }
  328.         // Set this in the packet parser
  329.         m_pPacketParser->SetTrustPackets(m_bTrustPackets);
  330.         
  331.         HX_RELEASE(pStringObj);
  332.     }
  333.     
  334.     if(m_pPacketParser)
  335.     {
  336.         m_pPacketParser->Init(this, m_pClassFactory);
  337.     }
  338.     if (!ulAvgPacketSize)
  339.         ulAvgPacketSize = 1200;
  340.     UINT32 dwAudBytes = m_ulPreroll * ulAvgBitRate / 8000;
  341.     m_nPacketsNeeded = (UINT8)(dwAudBytes / ulAvgPacketSize);
  342.     
  343.     if (!m_pAudioStream && ulChannels && ulSampRate)
  344.     {        
  345.         // Create our audio stream
  346.         m_pAudioPlayer->CreateAudioStream(&m_aAudStreamList[m_wAudStream]);
  347.         m_pAudioStream = m_aAudStreamList[m_wAudStream];
  348.         if (!m_pAudioStream)
  349.             return HXR_OK;
  350.         // Let's override the default class factory and use the one in
  351.         // client/audiosvc that caches our pcm buffers and avoids 
  352.         // unnecessary heap fragmentation.
  353.         IHXCommonClassFactory* pCommonClassFactory;
  354.         if (HXR_OK == m_pAudioStream->QueryInterface(IID_IHXCommonClassFactory, 
  355. (void**)&pCommonClassFactory))
  356.         {
  357.     if( m_pPacketParser )
  358.        m_pPacketParser->OverrideFactory(pCommonClassFactory);
  359.     pCommonClassFactory->Release();
  360.         }
  361.         // Init PCM device
  362.         HXAudioFormat audioFmt;
  363.         audioFmt.uChannels = (unsigned short)ulChannels;
  364.         audioFmt.uBitsPerSample = 16;
  365.         audioFmt.ulSamplesPerSec = ulSampRate;
  366.         audioFmt.uMaxBlockSize = (unsigned short)(1152 *
  367.                                  (audioFmt.uBitsPerSample>>3) *
  368.                                  audioFmt.uChannels);
  369.         m_pAudioStream->Init(&audioFmt, m_pHeader);
  370.         m_pAudioStream->AddDryNotification(this);
  371.         m_bDiscontinuity = TRUE;
  372.     }
  373.     
  374. #if 0
  375.     // Create a default stream to prevent rebuffering
  376.     else
  377.     {
  378.         // If the server does not send these properties
  379.         if (!ulSampRate)
  380.             ulSampRate = 44100;
  381.         if (!ulChannels)
  382.             ulChannels = 2;
  383.         ulSampRate = min(ulSampRate, 44100);
  384.         ulChannels = min(ulChannels, 2);
  385.         // Create our audio stream
  386.         m_pAudioPlayer->CreateAudioStream(&m_pDefAudStream);
  387.         if (!m_pDefAudStream)
  388.             return HXR_OK;
  389.         // Init PCM device
  390.         HXAudioFormat audioFmt;
  391.         audioFmt.uChannels = (unsigned short)ulChannels;
  392.         audioFmt.uBitsPerSample = 16;
  393.         audioFmt.ulSamplesPerSec = ulSampRate;
  394.         audioFmt.uMaxBlockSize = (unsigned short)(1152 *
  395.                                  (audioFmt.uBitsPerSample>>3) *
  396.                                  audioFmt.uChannels);
  397.         m_pDefAudStream->Init(&audioFmt, m_pHeader);
  398.     }
  399. #endif
  400.     return HXR_OK;
  401. }
  402. ///////////////////////////////////////////////////////////////////////////////
  403. //  IHXRenderer::OnBegin                                   ref:  hxrendr.h
  404. //
  405. //  This routine is called by the RMA core to inform the Renderer that 
  406. //  playback has just begun or has been resumed. The stream's time value just
  407. //  after resuming the playback is provided.
  408. //
  409. STDMETHODIMP
  410. CRnMp3Ren::OnBegin(UINT32 timeAfterBegin)
  411. {
  412.     #ifdef _WIN32
  413.     #ifdef _DEBUG
  414.     TCHAR szTmp[128];
  415.     wsprintf(szTmp, TEXT("OnBegin timeAfter %ldn"),timeAfterBegin);
  416.     OutputDebugString(szTmp);
  417.     #endif
  418.     #endif
  419.     if(m_pPacketParser)
  420.     {
  421.         m_pPacketParser->Begin(timeAfterBegin);
  422.     }
  423.     return HXR_OK;
  424. }
  425. ///////////////////////////////////////////////////////////////////////////////
  426. //  IHXRenderer::GetDisplayType                             ref:  hxrendr.h
  427. //
  428. //  This routine returns the preferred display type of the Renderer. Any
  429. //  other additional information necessary for the display can also be
  430. //  provided. This method is called by the RMA core when the plug-in is being
  431. //  initialized.
  432. //
  433. STDMETHODIMP
  434. CRnMp3Ren::GetDisplayType(REF(HX_DISPLAY_TYPE) displayType,
  435.                           REF(IHXBuffer*) pDisplayInfo)
  436. {
  437.     displayType = HX_DISPLAY_NONE;
  438. return HXR_OK;
  439. }
  440. ///////////////////////////////////////////////////////////////////////////////
  441. //  IHXRenderer::OnPacket                                   ref:  hxrendr.h
  442. //
  443. //  This routine is passed the packet object streamed by the associated
  444. //  file format plug-in. It is called by the RMA core when a packet is due
  445. //  to be delivered. In most cases, the actual rendering of the packet is
  446. //  done in this method. The stream's time offset with respect to the master
  447. //  timeline is provided.
  448. //
  449. STDMETHODIMP
  450. CRnMp3Ren::OnPacket(IHXPacket* pPacketObj,
  451.                     INT32 streamOffsetTime)
  452. {
  453.     if (m_bInSeekMode)
  454.         return HXR_OK;
  455.     
  456.     if(!m_pPacketParser)
  457.        return HXR_NOT_INITIALIZED;
  458.     if (!pPacketObj)
  459.         return HXR_INVALID_PARAMETER;
  460.     
  461.     #ifdef _DEBUG
  462.     ++m_ulPacketsDecoded;
  463.     #endif
  464.     m_lTimeLineOffset = streamOffsetTime;
  465.     HX_RESULT res = m_pPacketParser->AddPacket(pPacketObj, 0);
  466.     if(FAILED(res))
  467.     {            
  468.         return HXR_OK;
  469.     }
  470.     if(m_pDefaultPacketHookHelper)
  471. m_pDefaultPacketHookHelper->OnPacket(pPacketObj);
  472. #if 0
  473. #ifdef HELIX_CONFIG_ONLY_DECODE_IF_DRY
  474.     // Only decode audio if audio device is low
  475.     // IMPORTANT NOTE: since the implementation of AddPacket in the parser
  476.     // does not have a queue, in general if we return here and we do NOT get
  477.     // an OnDryNotification, the next time OnPacket is called, it will clobber
  478.     // an undecoded packet. As it turns out, this doesn't seem to happen in
  479.     // testing to date, but this is a TBD.
  480.     // Testing without this code seems to show that we can get the same results
  481.     // without it. Nevertheless, we are going to leave this code here until an
  482.     // absolute final decision can be made on the best solution.
  483.     UINT32 ulBytesInAudioDevice = 0;
  484.     m_pAudioPushdown2->GetCurrentAudioDevicePushdown( ulBytesInAudioDevice );
  485.     if( ulBytesInAudioDevice >= OPTIMAL_AUDIO_PUSHDOWN )
  486.     {
  487.        return HXR_OK;
  488.     }
  489. #endif // HELIX_CONFIG_ONLY_DECODE_IF_DRY
  490. #endif // 0
  491.     // Decode and render all frames available
  492.     HX_RESULT theErr = m_pPacketParser->RenderAll();
  493.     if( theErr == HXR_OUTOFMEMORY )
  494.     {
  495.         return theErr;
  496.     }
  497.     // Handle rebuffering
  498.     if (m_bStarving)
  499.     {
  500.         // Waiting for more packets
  501.         if (++m_ulNumPackets < m_nPacketsNeeded)
  502.         {
  503.             m_pStream->ReportRebufferStatus(m_nPacketsNeeded, (UINT8)m_ulNumPackets);
  504.             return HXR_OK;
  505.         }
  506.         #ifdef _WIN32
  507.         #ifdef _DEBUG
  508.         OutputDebugString(TEXT("Rebuffer Completen"));
  509.         #endif
  510.         #endif
  511.         m_pStream->ReportRebufferStatus(m_nPacketsNeeded, m_nPacketsNeeded);
  512.         m_bStarving = FALSE;
  513.     }
  514.     return HXR_OK;
  515. }
  516. ///////////////////////////////////////////////////////////////////////////////
  517. //  IHXRenderer::OnTimeSync                                 ref:  hxrendr.h
  518. //
  519. //  This routine is called by the RMA core periodically passing the current
  520. //  playback time. The Renderer should use this time value to synchronize the
  521. //  playback of various streams.
  522. //
  523. STDMETHODIMP
  524. CRnMp3Ren::OnTimeSync(UINT32 currentPlayBackTime)
  525. {
  526. #if 0
  527.     #ifdef _DEBUG
  528.     #ifdef _WIN32
  529.     if (!m_bStarted)
  530.     {
  531.         TCHAR szTmp[128];
  532.         wsprintf(szTmp, TEXT("OnTimeSync %ld Preroll %ldn"),
  533.                          currentPlayBackTime, m_ulPacketsDecoded*m_dFrameTime);
  534.         OutputDebugString(szTmp);
  535.         m_bStarted = 1;
  536.     }
  537.     #endif
  538.     #endif
  539. #endif
  540.     return HXR_OK;
  541. }
  542. ///////////////////////////////////////////////////////////////////////////////
  543. //  IHXRenderer::OnPreSeek                                  ref:  hxrendr.h
  544. //
  545. //  This routine is called by the RMA core before a seek is about to occur.
  546. //  The stream's time value just before the seek, and the time value just
  547. //  after the seek are provided.
  548. //
  549. STDMETHODIMP
  550. CRnMp3Ren::OnPreSeek(UINT32 timeBeforeSeek,
  551.                      UINT32 timeAfterSeek)
  552. {
  553.     #ifdef _WIN32
  554.     #ifdef _DEBUG
  555.     TCHAR szTmp[128];
  556.     wsprintf(szTmp, TEXT("OnPreSeek timeb4 %ld timeAfter %ldn"), timeBeforeSeek, timeAfterSeek);
  557.     OutputDebugString(szTmp);
  558.     m_ulPacketsDecoded = 0;
  559.     m_ulFramesDecoded = 0;
  560.     m_bStarted = 0;
  561.     #endif
  562.     #endif
  563.     // Wait for decode thread to become idle and
  564.     // release all buffered packets
  565.     m_bInSeekMode = TRUE;
  566.     m_bDiscontinuity = TRUE;
  567.     if(m_pPacketParser)
  568.     {
  569.         m_pPacketParser->PreSeek();
  570.     }
  571. #ifdef DEMUXER
  572.     if (m_pRegistry) m_pRegistry->SetIntByName("FirstPts", -1);
  573. #endif
  574.     return HXR_OK;
  575. }
  576. ///////////////////////////////////////////////////////////////////////////////
  577. //  IHXRenderer::OnPostSeek                                 ref:  hxrendr.h
  578. //
  579. //  This routine is called by the RMA core just after a seek has occured.
  580. //  The stream's time value just before the seek, and the time value just
  581. //  after the seek are provided.
  582. //
  583. STDMETHODIMP
  584. CRnMp3Ren::OnPostSeek(UINT32 timeBeforeSeek,
  585.                       UINT32 timeAfterSeek)
  586. {
  587.     #ifdef _WIN32
  588.     #ifdef _DEBUG
  589.     TCHAR szTmp[128];
  590.     wsprintf(szTmp, TEXT("OnPostSeek timeb4 %ld timeAfter %ldn"), timeBeforeSeek, timeAfterSeek);
  591.     OutputDebugString(szTmp);
  592.     #endif
  593.     #endif
  594.     m_bInSeekMode = FALSE;
  595.     if(m_pPacketParser)
  596.     {
  597.         m_pPacketParser->PostSeek(timeAfterSeek);
  598.     }
  599.     return HXR_OK;
  600. }
  601. ///////////////////////////////////////////////////////////////////////////////
  602. //  IHXRenderer::OnPause                                    ref:  hxrendr.h
  603. //
  604. //  This routine is called by the RMA core just after a pause has occured.
  605. //  The stream's time value just before pausing is provided.
  606. //
  607. STDMETHODIMP
  608. CRnMp3Ren::OnPause(UINT32 timeBeforePause)
  609. {
  610.     #ifdef _WIN32
  611.     #ifdef _DEBUG
  612.     TCHAR szTmp[128];
  613.     wsprintf(szTmp, TEXT("OnPause timeb4 %ldn"), timeBeforePause);
  614.     OutputDebugString(szTmp);
  615.     #endif
  616.     #endif
  617.     return HXR_OK;
  618. }
  619. ///////////////////////////////////////////////////////////////////////////////
  620. //  IHXRenderer::OnBuffering                                ref:  hxrendr.h
  621. //
  622. //  This routine is called by the RMA core to inform the Renderer that
  623. //  buffering of data is occuring. The reason for buffering (e.g. start-up
  624. //  of stream, seek has occured, network congestion, etc.), as well as the
  625. //  percentage of the buffering process complete are provided.
  626. //
  627. STDMETHODIMP
  628. CRnMp3Ren::OnBuffering(UINT32 reason,
  629.                        UINT16 percentComplete)
  630. {
  631.     #ifdef _WIN32
  632.     #ifdef _DEBUG
  633.     TCHAR szTmp[128];
  634.     wsprintf(szTmp, TEXT("OnBuffer percent %dn"), percentComplete);
  635.     OutputDebugString(szTmp);
  636.     #endif
  637.     #endif
  638.     return HXR_OK;
  639. }
  640. ///////////////////////////////////////////////////////////////////////////////
  641. //  IHXRenderer::OnEndofPackets                             ref:  hxrendr.h
  642. //
  643. //  Called by client engine to inform the renderer that all the
  644. //  packets have been delivered. However, if the user seeks before
  645. //  EndStream() is called, renderer may start getting packets again
  646. //  and the client engine will eventually call this function again.
  647. //
  648. STDMETHODIMP
  649. CRnMp3Ren::OnEndofPackets(void)
  650. {
  651.     m_bEndOfPackets = TRUE;
  652.     if (m_bStarving)
  653.     {
  654.         m_bStarving = FALSE;
  655.         m_pStream->ReportRebufferStatus(m_nPacketsNeeded, m_nPacketsNeeded);
  656.     }
  657.     if(m_pPacketParser)
  658.     {
  659.         m_pPacketParser->EndOfPackets();
  660.     }
  661.     if(m_pDefaultPacketHookHelper)
  662. m_pDefaultPacketHookHelper->OnEndOfPackets();
  663.     return HXR_OK;
  664. }
  665. ///////////////////////////////////////////////////////////////////////////////
  666. //  IHXRenderer::EndStream                                  ref:  hxrendr.h
  667. //
  668. //  This routine is called by the RMA core when the rendering of the stream
  669. //  has completed. Deallocation of any resources should be done here.
  670. //
  671. STDMETHODIMP
  672. CRnMp3Ren::EndStream(void)
  673. {
  674.     HX_RELEASE(m_pContext);
  675.     HX_RELEASE(m_pClassFactory);
  676.     HX_DELETE(m_pPacketParser);
  677.     if(m_pDefaultPacketHookHelper)
  678.     {
  679. m_pDefaultPacketHookHelper->Terminate();
  680. HX_RELEASE(m_pDefaultPacketHookHelper);
  681.     }
  682. #ifdef DEMUXER
  683.     if (m_pRegistry)
  684.         m_pRegistry->DeleteByName("FirstPts");
  685. #endif
  686.     for (int i=0; i<=m_wAudStream; i++)
  687.         HX_RELEASE(m_aAudStreamList[i]);
  688.     HX_RELEASE(m_pDefAudStream);
  689.     HX_RELEASE(m_pStream);
  690.     HX_RELEASE(m_pHeader);
  691.     HX_RELEASE(m_pAudioPlayer);
  692.     HX_RELEASE(m_pAudioPushdown2);
  693.     HX_RELEASE(m_pRegistry);
  694.     #ifdef PCM_CAPTURE
  695.     if (fpOut)
  696.     {
  697.         write_pcm_tailer_wave(fpOut, g_dwTotalPcmBytes);
  698.         fclose(fpOut);
  699.         fpOut = NULL;
  700.     }
  701.     #endif //PCM_CAPTURE
  702.     return HXR_OK;
  703. }
  704. ///////////////////////////////////////////////////////////////////////////////
  705. //  IHXDryNotification::OnDryNotification                   ref:  hxausvc.h
  706. //
  707. //  This function is called when it is time to write to audio device 
  708. //  and there is not enough data in the audio stream. The renderer can
  709. //  then decide to add more data to the audio stream. This should be 
  710. //  done synchronously within the call to this function.
  711. //  It is OK to not write any data. Silence will be played instead.
  712. //
  713. STDMETHODIMP
  714. CRnMp3Ren::OnDryNotification(UINT32 /*IN*/ ulCurrentStreamTime,
  715.                              UINT32 /*IN*/ ulMinimumDurationRequired)
  716. {
  717.     // We do not set our rebuffer flag at the end of a stream
  718.     if (m_bEndOfPackets || !m_pStream)
  719.         return HXR_OK;
  720.     #ifdef _DEBUG
  721.         #ifdef _WIN32
  722.         TCHAR szTmp[128];
  723.         wsprintf(szTmp, TEXT("DryNot: dur %ldn"), ulMinimumDurationRequired);
  724.         OutputDebugString(szTmp);
  725.         #endif
  726.     #endif
  727.     // NOTE: We still need to scrutinize this low-heap solution because it
  728.     // skips the rebuffering call. XXXJHHB
  729. #if defined(HELIX_CONFIG_ONLY_DECODE_IF_DRY)
  730.     HX_RESULT theErr = m_pPacketParser->RenderAll();
  731.     if( theErr == HXR_OUTOFMEMORY )
  732.     {
  733.         return theErr;
  734.     }
  735. #else
  736.     // Rebuffer if we are late
  737.     if (ulCurrentStreamTime+m_ulPreroll > m_ulDelay)
  738.     {
  739.         m_ulNumPackets = 0;
  740.         m_bStarving = TRUE;
  741.         
  742.         if(m_pPacketParser)
  743.         {
  744.             m_nPacketsNeeded = (UINT8)(ulMinimumDurationRequired / 
  745.                                 m_pPacketParser->GetTimePerPkt() + 1);
  746.         }
  747.         m_pStream->ReportRebufferStatus(m_nPacketsNeeded, 0);
  748.     }
  749. #endif
  750.     return HXR_OK;
  751. }
  752. STDMETHODIMP
  753. CRnMp3Ren::InitializeStatistics(UINT32 ulRegistryID)
  754. {
  755. #if defined(HELIX_FEATURE_STATS)
  756.     m_ulRegistryID = ulRegistryID;
  757.     m_ulChannelsRegID = 0;
  758.     m_ulCodecRegID = 0;
  759.     return HXR_OK;
  760. #else
  761.     return HXR_NOTIMPL;
  762. #endif /* HELIX_FEATURE_STATS */
  763. }
  764. STDMETHODIMP
  765. CRnMp3Ren::UpdateStatistics()
  766. {
  767. #if defined(HELIX_FEATURE_STATS)
  768.     if (m_pRegistry)
  769.     {
  770.         char szRegistryEntry[MAX_DISPLAY_NAME] = "0"; /* Flawfinder: ignore */
  771.         // Get the registry name for the specified id
  772.         IHXBuffer* pszRegistryName = NULL;
  773.         UINT32 ulChannels = m_pPacketParser ? m_pPacketParser->GetChannels() : 0;
  774.         if (!m_ulChannelsRegID && HXR_OK == m_pRegistry->GetPropName(m_ulRegistryID, pszRegistryName))
  775.         {
  776.             // Get the channel registry and set the value
  777.             SafeSprintf(szRegistryEntry, MAX_DISPLAY_NAME, "%s.Channels", pszRegistryName->GetBuffer());        
  778.             m_ulChannelsRegID = m_pRegistry->AddInt (szRegistryEntry, ulChannels);
  779.             HX_RELEASE(pszRegistryName);
  780.         }
  781.         // Set the channels value based on id
  782.         else
  783.             m_pRegistry->SetIntById(m_ulChannelsRegID, ulChannels);
  784.         // Set the codec name in registry
  785.         if (!m_ulCodecRegID)
  786.         {
  787.             // Get the current registry key name
  788.             if (!m_ulCodecRegID && (HXR_OK == m_pRegistry->GetPropName(m_ulRegistryID, pszRegistryName)))
  789.             {
  790.                 SafeSprintf(szRegistryEntry, MAX_DISPLAY_NAME, "%s.Codec", pszRegistryName->GetBuffer());
  791.             
  792.                 IHXBuffer *pValue = NULL;
  793.                 m_pClassFactory->CreateInstance(CLSID_IHXBuffer, (void**) &pValue);
  794.             
  795.                 if (pValue)
  796.                 {
  797.                     UCHAR pCodecName[] = "MPEG Audio";
  798.                     pValue->Set((const UCHAR*)pCodecName, strlen((const char*)pCodecName)+1);
  799.                     m_ulCodecRegID = m_pRegistry->AddStr(szRegistryEntry, pValue);
  800.                     pValue->Release();
  801.                 }
  802.             
  803.                 pszRegistryName->Release();
  804.                 pszRegistryName = NULL;
  805.             }
  806.         }
  807.         else
  808.         {
  809.             IHXBuffer *pValue = NULL;
  810.             m_pClassFactory->CreateInstance(CLSID_IHXBuffer, (void**) &pValue);
  811.         
  812.             if (pValue)
  813.             {
  814.                 UCHAR pCodecName[] = "MPEG Audio";
  815.                 pValue->Set((const UCHAR*)pCodecName, strlen((const char*)pCodecName)+1);
  816.                 m_pRegistry->SetStrById(m_ulCodecRegID, pValue);
  817.                 pValue->Release();
  818.             }
  819.         }
  820.     }
  821.     return HXR_OK;
  822. #else
  823.     return HXR_NOTIMPL;
  824. #endif /* HELIX_FEATURE_STATS */
  825. }
  826. /************************************************************************
  827.  *  IHXUpdateProperties Methods
  828.  */
  829. /************************************************************************
  830.  *  UpdatePacketTimeOffset
  831.  * Call this method to update the timestamp offset of cached packets
  832.  */
  833. STDMETHODIMP CRnMp3Ren::UpdatePacketTimeOffset(INT32 lTimeOffset)
  834. {
  835.     m_lTimeLineOffset -= lTimeOffset;
  836.     return HXR_OK;
  837. }
  838. /************************************************************************
  839.  * Method:
  840.  *     IHXUpdateProperties::UpdatePlayTimes
  841.  * Purpose:
  842.  *     Call this method to update the playtime attributes
  843.  */
  844. STDMETHODIMP CRnMp3Ren::UpdatePlayTimes(IHXValues* pProps)
  845. {
  846.     return HXR_OK;
  847. }
  848. ///////////////////////////////////////////////////////////////////////////////
  849. //  CRnMp3Ren::~CRnMp3Ren                  ref:  ff1rendr.h
  850. //
  851. //  Destructor
  852. //
  853. CRnMp3Ren::~CRnMp3Ren(void)
  854. {
  855.     //--_gbInit;
  856.     EndStream();
  857. }
  858. // IUnknown COM Interface Methods
  859. ///////////////////////////////////////////////////////////////////////////////
  860. //  IUnknown::AddRef                                            ref:  hxcom.h
  861. //
  862. //  This routine increases the object reference count in a thread safe
  863. //  manner. The reference count is used to manage the lifetime of an object.
  864. //  This method must be explicitly called by the user whenever a new
  865. //  reference to an object is used.
  866. //
  867. STDMETHODIMP_(UINT32)
  868. CRnMp3Ren::AddRef(void)
  869. {
  870.     return InterlockedIncrement(&m_RefCount);
  871. }
  872. ///////////////////////////////////////////////////////////////////////////////
  873. //  IUnknown::Release                                           ref:  hxcom.h
  874. //
  875. //  This routine decreases the object reference count in a thread safe
  876. //  manner, and deletes the object if no more references to it exist. It must
  877. //  be called explicitly by the user whenever an object is no longer needed.
  878. //
  879. STDMETHODIMP_(UINT32)
  880. CRnMp3Ren::Release(void)
  881. {
  882.     if (InterlockedDecrement(&m_RefCount) > 0)
  883.     return m_RefCount;
  884.     delete this;
  885.     return 0;
  886. }
  887. ///////////////////////////////////////////////////////////////////////////////
  888. //  IUnknown:]Interface                                    ref:  hxcom.h
  889. //
  890. //  This routine indicates which interfaces this object supports. If a given
  891. //  interface is supported, the object's reference count is incremented, and
  892. //  a reference to that interface is returned. Otherwise a NULL object and
  893. //  error code are returned. This method is called by other objects to
  894. //  discover the functionality of this object.
  895. //
  896. STDMETHODIMP
  897. CRnMp3Ren::QueryInterface(REFIID interfaceID,
  898.                           void** ppInterfaceObj)
  899. {
  900.     // By definition all COM objects support the IUnknown interface
  901.     if (IsEqualIID(interfaceID, IID_IUnknown))
  902.     {
  903.     AddRef();
  904.     *ppInterfaceObj = (IUnknown*)(IHXPlugin*)this;
  905.     return HXR_OK;
  906.     }
  907.     // IHXPlugin interface is supported
  908.     else if (IsEqualIID(interfaceID, IID_IHXPlugin))
  909.     {
  910.     AddRef();
  911.     *ppInterfaceObj = (IHXPlugin*)this;
  912.     return HXR_OK;
  913.     }
  914.     // IHXInterruptSafe interface is supported
  915.     else if (IsEqualIID(interfaceID, IID_IHXInterruptSafe))
  916.     {
  917.         AddRef();
  918.         *ppInterfaceObj = (IHXInterruptSafe*)this;
  919.         return HXR_OK;
  920.     }
  921.     // IHXRenderer interface is supported
  922.     else if (IsEqualIID(interfaceID, IID_IHXRenderer))
  923.     {
  924.     AddRef();
  925.     *ppInterfaceObj = (IHXRenderer*)this;
  926.     return HXR_OK;
  927.     }
  928.     else if (IsEqualIID(interfaceID, IID_IHXDryNotification))
  929.     {
  930.     AddRef();
  931.     *ppInterfaceObj = (IHXDryNotification*)this;
  932.     return HXR_OK;
  933.     }
  934. #if defined(HELIX_FEATURE_STATS)
  935.     else if (IsEqualIID(interfaceID, IID_IHXStatistics))
  936.     {
  937.     AddRef();
  938.     *ppInterfaceObj = (IHXStatistics*)this;
  939.     return HXR_OK;
  940.     }
  941. #endif /* #if defined(HELIX_FEATURE_STATS) */
  942.     else if (IsEqualIID(interfaceID, IID_IHXUpdateProperties))
  943.     {
  944. AddRef();
  945. *ppInterfaceObj = (IHXUpdateProperties*)this;
  946. return HXR_OK;
  947.     }
  948.     else if (IsEqualIID(interfaceID, IID_IHXPacketHookHelper))
  949.     {
  950. if(!m_pDefaultPacketHookHelper)
  951. {
  952.     m_pDefaultPacketHookHelper = new CHXDefaultPacketHookHelper;
  953.     if(m_pDefaultPacketHookHelper)
  954.     {
  955. m_pDefaultPacketHookHelper->AddRef();
  956. m_pDefaultPacketHookHelper->Initialize(m_pContext);
  957.     }
  958. }
  959. if(m_pDefaultPacketHookHelper)
  960.     return m_pDefaultPacketHookHelper->QueryInterface(interfaceID, ppInterfaceObj);
  961.     }
  962.     // No other interfaces are supported
  963.     *ppInterfaceObj = NULL;
  964.     return HXR_NOINTERFACE;
  965. }
  966. STDMETHODIMP
  967. CRnMp3Ren::CheckStreamVersions(IHXValues* pHeader)
  968. {
  969.     // check stream and content versions so an upgrade can
  970.     // be called if necessary...
  971.     HX_RESULT pnr = HXR_OK;
  972.     BOOL bVersionOK = TRUE;
  973.     UINT32 ulStreamVersion = 0;
  974.     UINT32 ulContentVersion = 0;
  975.     if(HXR_OK == pHeader->GetPropertyULONG32("StreamVersion", 
  976.                                          ulStreamVersion))
  977.     {
  978.     UINT32 ulMajorVersion = HX_GET_MAJOR_VERSION(ulStreamVersion);
  979.     UINT32 ulMinorVersion = HX_GET_MINOR_VERSION(ulStreamVersion);
  980.     if((ulMajorVersion > STREAM_MAJOR_VERSION) ||
  981.        (ulMinorVersion > STREAM_MINOR_VERSION &&
  982.     ulMajorVersion == STREAM_MAJOR_VERSION))
  983.     {
  984.     bVersionOK = FALSE;
  985.     }
  986.     }
  987.     if(bVersionOK &&
  988.        HXR_OK == pHeader->GetPropertyULONG32("ContentVersion",
  989.                                              ulContentVersion))
  990.     {
  991.     UINT32 ulMajorVersion = HX_GET_MAJOR_VERSION(ulContentVersion);
  992.     UINT32 ulMinorVersion = HX_GET_MINOR_VERSION(ulContentVersion);
  993.     if((ulMajorVersion > CONTENT_MAJOR_VERSION) ||
  994.        (ulMinorVersion > CONTENT_MINOR_VERSION &&
  995.     ulMajorVersion == CONTENT_MAJOR_VERSION))
  996.     {
  997.     bVersionOK = FALSE;
  998.     }
  999.     }
  1000.     if(!bVersionOK)
  1001.     {
  1002.         AddToAutoUpgradeCollection(zm_pStreamMimeTypes[0], m_pContext);
  1003.      pnr = HXR_FAIL;
  1004.     }
  1005.     return pnr;
  1006. }
  1007. BOOL
  1008. CRnMp3Ren::InitAudioStream(HXAudioFormat audioFmt)
  1009. {
  1010.     if(m_pAudioStream)
  1011.     {
  1012.         // if already inited, don't do anything
  1013.         return TRUE;
  1014.     }
  1015.     // If we could not create the stream in OnHeader
  1016.     // Create our audio stream
  1017.     m_pAudioPlayer->CreateAudioStream(&m_pAudioStream);
  1018.     if (!m_pAudioStream)
  1019.         return FALSE;
  1020.     m_pAudioStream->Init(&audioFmt, m_pHeader);
  1021.     #ifdef PCM_CAPTURE
  1022.     #ifdef _WIN32
  1023.     char                    szFile[64] = "c:\temp.wav"; /* Flawfinder: ignore */
  1024.     #elif _MACINTOSH
  1025.     char                    szFile[64] = "temp.wav"; /* Flawfinder: ignore */
  1026.     #endif
  1027.     fpOut = fopen(szFile, "wb");
  1028.     write_pcm_header_wave(fpOut,
  1029.                           lPCMSampRate,
  1030.                           nPCMChannels,
  1031.                           nBitsPerSample,
  1032.                           0);
  1033.     g_dwTotalPcmBytes = 0;
  1034.     
  1035.     #endif // PCM_CAPTURE
  1036.     
  1037.     m_pAudioStream->AddDryNotification(this);
  1038.     m_bDiscontinuity = TRUE;
  1039.     return TRUE;
  1040. }
  1041. BOOL
  1042. CRnMp3Ren::ReInitAudioStream(HXAudioFormat audioFmt)
  1043. {
  1044.     #if defined _DEBUG && defined _WIN32
  1045.     OutputDebugString(TEXT("Dynamic audio src changen"));
  1046.     #endif
  1047.     IHXAudioStream2 *pStream = NULL;
  1048.     m_pAudioStream->QueryInterface(IID_IHXAudioStream2, (void**)&pStream);
  1049.     if (pStream)
  1050.     {
  1051.         pStream->RemoveDryNotification((IHXDryNotification*)this);
  1052.         pStream->Release();
  1053.     }
  1054.     
  1055.     m_pAudioStream = m_aAudStreamList[++m_wAudStream];
  1056.     return InitAudioStream(audioFmt);
  1057. }
  1058. void CRnMp3Ren::Render(IHXBuffer* pPCMBuffer, double dTime)
  1059. {
  1060.     #ifdef PCM_CAPTURE
  1061.     if (fpOut)
  1062.     {
  1063.         fwrite(pPCMBuffer->GetBuffer(), dwPCM, 1, fpOut);
  1064.         g_dwTotalPcmBytes += dwPCM;
  1065.     }
  1066.     #endif //PCM_CAPTURE
  1067.     // Write to Audio Services
  1068.     HXAudioData  audioData;
  1069.     audioData.pData = pPCMBuffer;
  1070.     audioData.ulAudioTime = (UINT32)dTime;
  1071.     #ifdef _DEBUG
  1072.     ++m_ulFramesDecoded;
  1073.     #endif
  1074.     
  1075.     #if defined _DEBUG && defined _WIN32
  1076.     //wsprintf(szTmp, "Audio Pts %ldn", audioData.ulAudioTime);
  1077.     //OutputDebugString(szTmp);
  1078.     #endif
  1079.     if (m_bDiscontinuity)
  1080.     {
  1081.         audioData.uAudioStreamType = TIMED_AUDIO;
  1082.         m_bDiscontinuity = FALSE;
  1083.     }
  1084.     else
  1085.         audioData.uAudioStreamType = STREAMING_AUDIO;
  1086.     audioData.ulAudioTime = AdjustTimestamp( (ULONG32) dTime, m_lTimeLineOffset );
  1087.     m_pAudioStream->Write(&audioData);
  1088. }
  1089. void
  1090. CRnMp3Ren::SetPacketFormat(const char* szMimeType)
  1091. {
  1092.     if(!szMimeType)
  1093.     {
  1094.         return;
  1095.     }
  1096.     int i, j;
  1097.     for (i=0; zm_pStreamMimeTypes[i] != NULL; i++)
  1098.         if (!strcasecmp(szMimeType, zm_pStreamMimeTypes[i]))
  1099.             break;
  1100.     if(zm_pStreamMimeTypes[i] == NULL)
  1101.     {
  1102.         return;
  1103.     }
  1104.     for (j=0; MIME_FMT_BASIC[j] != -1; j++)
  1105.     {
  1106.         if(MIME_FMT_BASIC[j] == i)
  1107.         {
  1108. #if defined (MPA_FMT_DRAFT00)
  1109.             m_pPacketParser = new CFmtPacketParser();
  1110. #if defined(HELIX_FEATURE_MIN_HEAP)
  1111.             m_ulPreroll = 0;
  1112.             m_pHeader->SetPropertyULONG32("Preroll", m_ulPreroll);
  1113. #endif
  1114. #endif //MPA_FMT_DRAFT00
  1115.             return;
  1116.         }
  1117.     }
  1118.     for (j=0; MIME_MPA_BASIC[j] != -1; j++)
  1119.     {
  1120.         if(MIME_MPA_BASIC[j] == i)
  1121.         {    
  1122. #if defined (MPA_FMT_RAW)         
  1123.             m_pPacketParser = new CMpaPacketParser();
  1124. #if defined(HELIX_FEATURE_MIN_HEAP)
  1125.             m_ulPreroll = 0;
  1126.             m_pHeader->SetPropertyULONG32("Preroll", m_ulPreroll);
  1127. #endif
  1128. #endif //MPA_FMT_RAW
  1129.             return;
  1130.         }
  1131.     }
  1132.     for (j=0; MIME_FMT_3119[j] != -1; j++)
  1133.     {
  1134.         if(MIME_FMT_3119[j] == i)
  1135.         {
  1136. #if defined (MPA_FMT_RFC3119)
  1137.             m_pPacketParser = new CRobustPacketParser();
  1138. #endif //MPA_FMT_RFC3119
  1139.             return;
  1140.         }
  1141.     }
  1142.     for (j=0; MIME_MPA_2250[j] != -1; j++)
  1143.     {
  1144.         if(MIME_MPA_2250[j] == i)
  1145.         {
  1146. #if defined (MPA_FMT_RFC2250)
  1147.             m_pPacketParser = new C2250PacketParser();
  1148. #if defined(HELIX_FEATURE_MIN_HEAP)
  1149.             m_ulPreroll = 0;
  1150.             m_pHeader->SetPropertyULONG32("Preroll", m_ulPreroll);
  1151. #endif
  1152. #endif //MPA_FMT_RFC2250
  1153.             return;
  1154.         }
  1155.     }
  1156. #ifdef DEMUXER
  1157.     for (j=0; MIME_MPG1_2250[j] != -1; j++)
  1158.     {
  1159.         if(MIME_MPG1_2250[j] == i)
  1160.         {
  1161. #if defined (MPA_FMT_RFC2250_SYSTEM)
  1162.             m_pPacketParser = (CPacketParser*)(CSysPacketParser*)
  1163.                               (new C2250SysPacketParser(FALSE, m_pRegistry));
  1164. #if defined(HELIX_FEATURE_MIN_HEAP)
  1165.             m_ulPreroll = 0;
  1166.             m_pHeader->SetPropertyULONG32("Preroll", m_ulPreroll);
  1167. #endif
  1168. #endif //MPA_FMT_RFC2250_SYSTEM
  1169.             return;
  1170.         }
  1171.     }
  1172.     for (j=0; MIME_MPG2_2250[j] != -1; j++)
  1173.     {
  1174.         if(MIME_MPG2_2250[j] == i)
  1175.         {
  1176. #if defined (MPA_FMT_RFC2250_SYSTEM)
  1177.             m_pPacketParser = (CPacketParser*)(CSysPacketParser*)
  1178.                               (new C2250SysPacketParser(TRUE, m_pRegistry));
  1179. #if defined(HELIX_FEATURE_MIN_HEAP)
  1180.             m_ulPreroll = 0;
  1181.             m_pHeader->SetPropertyULONG32("Preroll", m_ulPreroll);
  1182. #endif
  1183. #endif //MPA_FMT_RFC2250_SYSTEM
  1184.             return;
  1185.         }
  1186.     }
  1187.     for (j=0; MIME_MPG1_SYS[j] != -1; j++)
  1188.     {
  1189.         if(MIME_MPG1_SYS[j] == i)
  1190.         {
  1191. #if defined (MPA_FMT_SYSTEM)
  1192.             m_pPacketParser = new CSysPacketParser(FALSE, m_pRegistry);
  1193. #endif //MPA_FMT_SYSTEM
  1194.             return;
  1195.         }
  1196.     }
  1197.     for (j=0; MIME_MPG2_SYS[j] != -1; j++)
  1198.     {
  1199.         if(MIME_MPG2_SYS[j] == i)
  1200.         {
  1201. #if defined (MPA_FMT_SYSTEM)
  1202.             m_pPacketParser = new CSysPacketParser(TRUE, m_pRegistry);
  1203. #endif //MPA_FMT_SYSTEM
  1204.             return;
  1205.         }
  1206.     }
  1207. #endif // DEMUXER
  1208. }