mp3draft.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:12k
源码类别:

Symbian

开发平台:

C/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. #include "hxtypes.h"
  36. #include "hxwintyp.h"
  37. #include "hxcom.h"
  38. #include "hxcomm.h"
  39. #include "hxassert.h"
  40. #include "hxslist.h"
  41. #include "hxmarsh.h"
  42. #include "hxcomm.h"
  43. #include "ihxpckts.h"
  44. #include "hxformt.h"
  45. #include "hxrendr.h"
  46. #include "hxformt.h"
  47. #include "hxengin.h"
  48. #include "ringbuf.h"
  49. #include "mp3format.h"  // CMp3Format
  50. #include "mp3draft.h"
  51. MP3DraftPayloadFormat::MP3DraftPayloadFormat()
  52.     : m_lRefCount     (0)
  53.     , m_pContext     (NULL)
  54.     , m_pClassFactory     (NULL)
  55.     , m_pStreamHeader     (NULL)
  56.     , m_ulStreamNum     (0)
  57.     , m_bPacketizing     (FALSE)
  58.     , m_bFlushed     (FALSE)
  59.     , m_pFmtBuf     (NULL)
  60.     , m_pMp3Fmt     (NULL)
  61.     , m_bPacketReceived     (FALSE)
  62.     , m_bHeaderParsed     (FALSE)
  63.     , m_fTimePerFrame     (0.0)
  64.     , m_fNextTimestamp     (0.0)
  65. {
  66. }
  67. MP3DraftPayloadFormat::~MP3DraftPayloadFormat()
  68. {
  69.     HX_RELEASE(m_pContext);
  70.     HX_RELEASE(m_pClassFactory);
  71.     HX_RELEASE(m_pStreamHeader);
  72.     HX_DELETE(m_pFmtBuf);
  73.     HX_DELETE(m_pMp3Fmt);
  74. }
  75. // *** IUnknown methods ***
  76. /////////////////////////////////////////////////////////////////////////
  77. //  Method:
  78. // IUnknown::QueryInterface
  79. //  Purpose:
  80. // Implement this to export the interfaces supported by your 
  81. // object.
  82. //
  83. STDMETHODIMP 
  84. MP3DraftPayloadFormat::QueryInterface(REFIID riid, void** ppvObj)
  85. {
  86.     if (IsEqualIID(riid, IID_IUnknown))
  87.     {
  88. AddRef();
  89. *ppvObj = this;
  90. return HXR_OK;
  91.     }
  92.     else if (IsEqualIID(riid, IID_IHXPayloadFormatObject))
  93.     {
  94. AddRef();
  95. *ppvObj = (IHXPayloadFormatObject*)this;
  96. return HXR_OK;
  97.     }
  98.     *ppvObj = NULL;
  99.     return HXR_NOINTERFACE;
  100. }
  101. /////////////////////////////////////////////////////////////////////////
  102. //  Method:
  103. // IUnknown::AddRef
  104. //  Purpose:
  105. // Everyone usually implements this the same... feel free to use
  106. // this implementation.
  107. //
  108. STDMETHODIMP_(ULONG32) 
  109. MP3DraftPayloadFormat::AddRef()
  110. {
  111.     return InterlockedIncrement(&m_lRefCount);
  112. }
  113. /////////////////////////////////////////////////////////////////////////
  114. //  Method:
  115. // IUnknown::Release
  116. //  Purpose:
  117. // Everyone usually implements this the same... feel free to use
  118. // this implementation.
  119. //
  120. STDMETHODIMP_(ULONG32) 
  121. MP3DraftPayloadFormat::Release()
  122. {
  123.     if (InterlockedDecrement(&m_lRefCount) > 0)
  124.     {
  125.         return m_lRefCount;
  126.     }
  127.     delete this;
  128.     return 0;
  129. }
  130. STDMETHODIMP 
  131. MP3DraftPayloadFormat::Init(IUnknown* pContext,
  132.     BOOL bPacketize)
  133. {
  134.     HX_ASSERT(pContext);
  135.     HX_RELEASE(m_pContext);
  136.     m_pContext = pContext;
  137.     m_pContext->AddRef();
  138.     HX_RELEASE(m_pClassFactory);
  139.     m_pContext->QueryInterface(IID_IHXCommonClassFactory, 
  140. (void**)&m_pClassFactory);
  141.     HX_ASSERT(m_pClassFactory);
  142.     // Remember if we are packetizing or depacketizing
  143.     m_bPacketizing = bPacketize;
  144.     if (!m_bPacketizing)
  145.     {
  146. // For now, we don't support depacketizing
  147. return HXR_NOTIMPL;
  148.     }
  149.     // Create a ring buffer to store all incoming data
  150.     HX_DELETE(m_pFmtBuf);
  151.     m_pFmtBuf = new CIHXRingBuffer(m_pClassFactory, 8192, (1024<<1)+512);
  152.     // Create an MP3 format object to handle parsing
  153.     HX_DELETE(m_pMp3Fmt);
  154.     m_pMp3Fmt = new CMp3Format();
  155.     return HXR_OK;
  156. }
  157. STDMETHODIMP
  158. MP3DraftPayloadFormat::Reset()
  159. {
  160.     // Discard all data from the ring buffer
  161.     m_pFmtBuf->Reset();
  162.     // Create a new MP3 format object
  163.     HX_DELETE(m_pMp3Fmt);
  164.     m_pMp3Fmt = new CMp3Format();
  165.     m_bHeaderParsed = FALSE;
  166.     m_bPacketReceived = FALSE;
  167.     m_bFlushed = FALSE;
  168.     return HXR_OK;
  169. }
  170. STDMETHODIMP 
  171. MP3DraftPayloadFormat::SetStreamHeader(IHXValues* pHeader)
  172. {
  173.     HX_ASSERT(pHeader);
  174.     m_pStreamHeader = pHeader;
  175.     m_pStreamHeader->AddRef();
  176.     m_pStreamHeader->GetPropertyULONG32("StreamNumber", m_ulStreamNum);
  177.     return HXR_OK;
  178. }
  179. STDMETHODIMP 
  180. MP3DraftPayloadFormat::GetStreamHeader(REF(IHXValues*) pHeader)
  181. {
  182.     HX_ASSERT(m_pStreamHeader);
  183.     pHeader = m_pStreamHeader;
  184.     pHeader->AddRef();
  185.     return HXR_OK;
  186. }
  187. STDMETHODIMP 
  188. MP3DraftPayloadFormat::SetPacket(IHXPacket* pPacket)
  189. {
  190.     HX_RESULT hResult = HXR_OK;
  191.     HX_ASSERT(pPacket);
  192.     // Add the data from this buffer to the ring buffer
  193.     IHXBuffer* pBuffer = pPacket->GetBuffer();
  194.     m_pFmtBuf->CopyData(pBuffer->GetBuffer(), pBuffer->GetSize());
  195.     HX_RELEASE(pBuffer);
  196.     // Test for buffer overflow, and wrap the
  197.     // ring buffer if necessary
  198.     WrapRingBuffer();
  199.     if (!m_bPacketReceived)
  200.     {
  201. m_bPacketReceived = TRUE;
  202. m_fNextTimestamp = pPacket->GetTime();
  203.     }
  204.     if (!m_bHeaderParsed)
  205.     {
  206. UCHAR* pBuf = NULL;
  207. UINT32 ulBytes = 0;
  208. // See if we have enough data to initialize our formatter
  209. pBuf = m_pFmtBuf->GetReadPointer(ulBytes);
  210. int     nFrame;
  211. INT32    lScan = 0;
  212. lScan = m_pMp3Fmt->ScanForSyncWord(pBuf, ulBytes, nFrame);
  213. if (lScan == -1)
  214.     // We probably just don't have enough data yet to 
  215.     // be able to initialize our header information
  216.     hResult = HXR_OK;
  217. }
  218. else
  219. {
  220.     // We have enough data to initialize, but we
  221.     // need to advance past any initial garbage to
  222.     // get to the beginning of the first MP3 frame
  223.     m_pFmtBuf->AdvanceRead(lScan);
  224.     pBuf = m_pFmtBuf->GetReadPointer(ulBytes);
  225.     // Init our reformatter
  226.     if (!m_pMp3Fmt->Init(pBuf, ulBytes))
  227.     { 
  228. hResult = HXR_FAIL;
  229.     }
  230.     else
  231.     {
  232. UINT32 ulBitRate = 0;
  233. UINT32 ulMaxSampleRate = 0;
  234. int nChannels = 0;
  235. int nLayer = 0;
  236. int nSamplesPerFrame = 0;
  237. m_pMp3Fmt->GetEncodeInfo(pBuf, ulBytes, ulBitRate, 
  238.    ulMaxSampleRate, nChannels, 
  239.    nLayer, nSamplesPerFrame);
  240. // Compute frame duration in ms
  241. m_fTimePerFrame = nSamplesPerFrame * 1000.0 / ulMaxSampleRate; 
  242. hResult = HXR_OK;
  243. m_bHeaderParsed = TRUE;
  244.     }
  245. }
  246.     }
  247.     return hResult;
  248. }
  249. STDMETHODIMP 
  250. MP3DraftPayloadFormat::GetPacket(REF(IHXPacket*) pPacket)
  251. {
  252.     HX_RESULT hResult = HXR_OK;
  253.     pPacket = NULL;
  254.     if (!m_bHeaderParsed)
  255.     {
  256. if (m_bFlushed)
  257. {
  258.     // We have used up all available input
  259.     hResult = HXR_STREAM_DONE;
  260. }
  261. else
  262. {
  263.     // We don't have enough input 
  264.     // data to produce a packet
  265.     hResult = HXR_INCOMPLETE;
  266. }
  267.     }
  268.     else
  269.     {
  270. hResult = CreateNormalPacket(pPacket);
  271.     }
  272.     return hResult;
  273. }
  274. STDMETHODIMP 
  275. MP3DraftPayloadFormat::Flush()
  276. {
  277.     m_bFlushed = TRUE;
  278.     return HXR_OK;
  279. }
  280. HX_RESULT
  281. MP3DraftPayloadFormat::CreateNormalPacket(REF(IHXPacket*) pPacket)
  282. {
  283.     HX_RESULT hResult = HXR_OK;
  284.     UCHAR* pModFrameStart = NULL;
  285.     int nModFrameSize = 0;
  286.     // Make sure the current read position in the
  287.     // ring buffer is the beginning of an MP3 frame
  288.     hResult = FindMP3Frame();
  289.     if (SUCCEEDED(hResult))
  290.     {
  291. UINT32 nSync = 0;
  292. for (;;)
  293. {
  294.     // We need 1+ audio frames
  295.     UINT32 ulReadSize = 0;
  296.     pModFrameStart = m_pFmtBuf->GetReadPointer(ulReadSize);
  297.     nSync = m_pMp3Fmt->CheckValidFrame(pModFrameStart, ulReadSize);
  298.     if (ulReadSize >= nSync + 6 ||
  299. m_bFlushed)
  300.     {
  301. nModFrameSize = m_pMp3Fmt->ReformatMP3Frame(&pModFrameStart,
  302.       ulReadSize,
  303.       m_pFmtBuf->GetPrevBytes());
  304. // If we did not have enough back data to reformat, 
  305. // skip this frame in the format buffer
  306. if (!nModFrameSize && nSync)
  307. {
  308.     m_pFmtBuf->AdvanceRead(nSync);
  309. }
  310. else
  311. {
  312.     break;
  313. }
  314.     }
  315.     else
  316.     {
  317. nModFrameSize = 0;
  318. break;
  319.     }
  320. }
  321.         
  322.         if (nModFrameSize)
  323. {
  324.             m_pFmtBuf->AdvanceRead(nSync);
  325. }
  326.         else
  327.         {
  328.     hResult = HXR_INCOMPLETE;
  329.         }
  330.     }
  331.     if (SUCCEEDED(hResult))
  332.     {
  333. IHXBuffer* pBuffer = NULL;
  334. UCHAR* pBuf = NULL;
  335. // Create a packet with this new formatted frame
  336. m_pClassFactory->CreateInstance(CLSID_IHXPacket, (void**)&pPacket);
  337. HX_ASSERT(pPacket);
  338. m_pClassFactory->CreateInstance(CLSID_IHXBuffer, (void**)&pBuffer);
  339. HX_ASSERT(pBuffer);
  340. pBuffer->SetSize(nModFrameSize + 4);
  341. pBuf = pBuffer->GetBuffer();
  342. // Set the 4-Byte audio header for this packet 
  343. // (as dictated by RFC 2250)
  344. putshort(pBuf, 0);
  345. pBuf += 2;
  346. putshort(pBuf, 0);
  347. pBuf += 2;
  348. // Copy in the actual frame data
  349.         memcpy(pBuf, pModFrameStart, nModFrameSize); /* Flawfinder: ignore */
  350.         pPacket->Set(pBuffer, (UINT32)m_fNextTimestamp, (UINT16)m_ulStreamNum,
  351.     HX_ASM_SWITCH_ON | HX_ASM_SWITCH_OFF, 0);
  352. HX_RELEASE(pBuffer);
  353. m_fNextTimestamp += m_fTimePerFrame;
  354.     }
  355.     else if (m_bFlushed)
  356.     {
  357. // We have used up all available input
  358. hResult = HXR_STREAM_DONE;
  359.     }
  360.     return hResult;
  361. }
  362. HX_RESULT 
  363. MP3DraftPayloadFormat::FindMP3Frame()
  364. {
  365.     INT32   lScan = 0;
  366.     UCHAR* pFrame = NULL;
  367.     UINT32 ulBytes = 0;
  368.     pFrame = m_pFmtBuf->GetReadPointer(ulBytes);
  369.     // We should be at an mp3 frame, make sure we are
  370.     int nSync = m_pMp3Fmt->CheckValidFrame(pFrame, ulBytes);
  371.     // If we were not at a frame, scan for the next one
  372.     if (!nSync)
  373.     {
  374.         lScan = m_pMp3Fmt->ScanForSyncWord(pFrame,
  375.                                            ulBytes,
  376.                                            nSync);
  377. if (lScan == -1)
  378.     return HXR_INCOMPLETE;
  379. }
  380. // Skip leading garbage
  381. m_pFmtBuf->AdvanceRead(lScan);
  382. // Try again...
  383. pFrame = m_pFmtBuf->GetReadPointer(ulBytes);
  384.         nSync = m_pMp3Fmt->CheckValidFrame(pFrame, ulBytes);
  385.     }
  386.     
  387.     if (nSync)
  388.     {
  389. return HXR_OK;
  390.     }
  391.     return HXR_INCOMPLETE;
  392. }
  393. HX_RESULT
  394. MP3DraftPayloadFormat::WrapRingBuffer()
  395. {
  396.     UCHAR  *pTemp = NULL;
  397.     UINT32 ulBytes = 0;
  398.     pTemp = m_pFmtBuf->GetReadPointer(ulBytes);
  399.     UINT32  nSync = m_pMp3Fmt->CheckValidFrame(pTemp, ulBytes);
  400.     // Make sure we have 1+ frame in the buffer
  401.     if (!nSync ||
  402.         (m_pFmtBuf->GetBytesInBuffer() > (UINT32)nSync+6 &&
  403.          ulBytes < (UINT32)nSync + 6))
  404.     {
  405.         // Preserve enough data for main_data_begin
  406.         m_pFmtBuf->Wrap(512);
  407.     }
  408.     return HXR_OK;
  409. }