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

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. #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 "mhead.h"
  49. #include "mpapayld.h"
  50. MPAPayloadFormat::MPAPayloadFormat()
  51.     : m_lRefCount     (0)
  52.     , m_pContext     (NULL)
  53.     , m_pClassFactory     (NULL)
  54.     , m_pStreamHeader     (NULL)
  55.     , m_ulStreamNum     (0)
  56.     , m_bPacketizing     (FALSE)
  57.     , m_ulFrameSize     (0)
  58.     , m_bFragmentFrames     (FALSE)
  59.     , m_ulFramesPerPacket   (0)
  60.     , m_ulPacketsPerFrame   (0)
  61.     , m_ulFrameOffset     (0)
  62.     , m_bFlushed     (FALSE)
  63.     , m_pInputPackets     (NULL)
  64.     , m_ulInputSize     (0)
  65.     , m_ulInputUsed     (0)
  66.     , m_pPartialPacket     (NULL)
  67.     , m_pPartialBuffer     (NULL)
  68.     , m_ulMaxPacketSize     (0)
  69. {
  70.     m_pInputPackets = new CHXSimpleList();
  71. }
  72. MPAPayloadFormat::~MPAPayloadFormat()
  73. {
  74.     HX_RELEASE(m_pContext);
  75.     HX_RELEASE(m_pClassFactory);
  76.     HX_RELEASE(m_pStreamHeader);
  77.     if (!m_pInputPackets->IsEmpty())
  78.     {
  79. IHXPacket* pPacket = (IHXPacket*)m_pInputPackets->RemoveHead();
  80. HX_RELEASE(pPacket);
  81.     }
  82.     HX_DELETE(m_pInputPackets);
  83.     HX_RELEASE(m_pPartialPacket);
  84.     HX_RELEASE(m_pPartialBuffer);
  85. }
  86. // *** IUnknown methods ***
  87. /////////////////////////////////////////////////////////////////////////
  88. //  Method:
  89. // IUnknown::QueryInterface
  90. //  Purpose:
  91. // Implement this to export the interfaces supported by your 
  92. // object.
  93. //
  94. STDMETHODIMP 
  95. MPAPayloadFormat::QueryInterface(REFIID riid, void** ppvObj)
  96. {
  97.     if (IsEqualIID(riid, IID_IUnknown))
  98.     {
  99. AddRef();
  100. *ppvObj = this;
  101. return HXR_OK;
  102.     }
  103.     else if (IsEqualIID(riid, IID_IHXPayloadFormatObject))
  104.     {
  105. AddRef();
  106. *ppvObj = (IHXPayloadFormatObject*)this;
  107. return HXR_OK;
  108.     }
  109.     *ppvObj = NULL;
  110.     return HXR_NOINTERFACE;
  111. }
  112. /////////////////////////////////////////////////////////////////////////
  113. //  Method:
  114. // IUnknown::AddRef
  115. //  Purpose:
  116. // Everyone usually implements this the same... feel free to use
  117. // this implementation.
  118. //
  119. STDMETHODIMP_(ULONG32) 
  120. MPAPayloadFormat::AddRef()
  121. {
  122.     return InterlockedIncrement(&m_lRefCount);
  123. }
  124. /////////////////////////////////////////////////////////////////////////
  125. //  Method:
  126. // IUnknown::Release
  127. //  Purpose:
  128. // Everyone usually implements this the same... feel free to use
  129. // this implementation.
  130. //
  131. STDMETHODIMP_(ULONG32) 
  132. MPAPayloadFormat::Release()
  133. {
  134.     if (InterlockedDecrement(&m_lRefCount) > 0)
  135.     {
  136.         return m_lRefCount;
  137.     }
  138.     delete this;
  139.     return 0;
  140. }
  141. STDMETHODIMP 
  142. MPAPayloadFormat::Init(IUnknown* pContext,
  143.        BOOL bPacketize)
  144. {
  145.     HX_ASSERT(pContext);
  146.     HX_RELEASE(m_pContext);
  147.     m_pContext = pContext;
  148.     m_pContext->AddRef();
  149.     m_pContext->QueryInterface(IID_IHXCommonClassFactory, 
  150. (void**)&m_pClassFactory);
  151.     HX_ASSERT(m_pClassFactory);
  152.     // Remember if we are packetizing or depacketizing
  153.     m_bPacketizing = bPacketize;
  154.     return HXR_OK;
  155. }
  156. STDMETHODIMP
  157. MPAPayloadFormat::Reset()
  158. {
  159.     // Release all input packets we have stored
  160.     if (!m_pInputPackets->IsEmpty())
  161.     {
  162. IHXPacket* pPacket = (IHXPacket*)m_pInputPackets->RemoveHead();
  163. HX_RELEASE(pPacket);
  164.     }
  165.     // Reset all relevant state variables
  166.     m_ulFrameSize = 0;
  167.     m_bFragmentFrames = FALSE;
  168.     m_ulFramesPerPacket = 0;
  169.     m_ulPacketsPerFrame = 0;
  170.     m_ulFrameOffset = 0;
  171.     m_bFlushed = FALSE;
  172.     m_ulInputSize = 0;
  173.     m_ulInputUsed = 0;
  174.     HX_RELEASE(m_pPartialPacket);
  175.     HX_RELEASE(m_pPartialBuffer);
  176.     return HXR_OK;
  177. }
  178. STDMETHODIMP 
  179. MPAPayloadFormat::SetStreamHeader(IHXValues* pHeader)
  180. {
  181.     HX_ASSERT(pHeader);
  182.     m_pStreamHeader = pHeader;
  183.     m_pStreamHeader->AddRef();
  184.     m_pStreamHeader->GetPropertyULONG32("StreamNumber", m_ulStreamNum);
  185.     m_pStreamHeader->GetPropertyULONG32("MaxPacketSize", m_ulMaxPacketSize);
  186.     HX_ASSERT(m_ulMaxPacketSize > 4);
  187.     // We will add 4 Bytes of header data,
  188.     m_ulMaxPacketSize -= 4;
  189.     return HXR_OK;
  190. }
  191. STDMETHODIMP 
  192. MPAPayloadFormat::GetStreamHeader(REF(IHXValues*) pHeader)
  193. {
  194.     HX_ASSERT(m_pStreamHeader);
  195.     pHeader = m_pStreamHeader;
  196.     pHeader->AddRef();
  197.     return HXR_OK;
  198. }
  199. STDMETHODIMP 
  200. MPAPayloadFormat::SetPacket(IHXPacket* pPacket)
  201. {
  202.     HX_RESULT hResult = HXR_OK;
  203.     IHXBuffer* pBuffer = NULL;
  204.     HX_ASSERT(pPacket);
  205.     pBuffer = pPacket->GetBuffer();
  206.     // Add this packet to our list of input packets
  207.     pPacket->AddRef();
  208.     m_pInputPackets->AddTail(pPacket);
  209.     m_ulInputSize += pBuffer->GetSize();
  210.     if (m_bPacketizing && !m_ulFrameSize)
  211.     {
  212. UINT32 ulBytesSkipped = 0;
  213. m_ulFrameSize = GetFrameSize(pBuffer->GetBuffer(), 
  214.     pBuffer->GetSize(), ulBytesSkipped);
  215. if (ulBytesSkipped)
  216. {
  217.     // If we had to skip any Bytes to find the header
  218.     // info, discard those leading Bytes as garbage
  219.     m_ulInputUsed = ulBytesSkipped;
  220.     m_ulInputSize -= ulBytesSkipped;
  221. }
  222. if (m_ulFrameSize &&
  223.     m_ulFrameSize <= m_ulMaxPacketSize)
  224. {
  225.     // An integral number of frames can fit into
  226.     // one packet, so pack them accordingly
  227.     m_bFragmentFrames = FALSE;
  228.     m_ulFramesPerPacket = m_ulMaxPacketSize / m_ulFrameSize;
  229. }
  230. else if (m_ulFrameSize)
  231. {
  232.     // Not even 1 entire frame will fit into one packet, 
  233.     // so break each frame up across multiple packets
  234.     m_bFragmentFrames = TRUE;
  235.     m_ulPacketsPerFrame = (m_ulFrameSize / m_ulMaxPacketSize) + 1;
  236. }
  237. else
  238. {
  239.     // We couldn't figure out the frame size, so toss
  240.     // this packet and return a failure code
  241.     m_pInputPackets->RemoveHead();
  242.     HX_RELEASE(pPacket);
  243.     hResult = HXR_FAIL;
  244. }
  245.     }
  246.     HX_RELEASE(pBuffer);
  247.     return hResult;
  248. }
  249. STDMETHODIMP 
  250. MPAPayloadFormat::GetPacket(REF(IHXPacket*) pPacket)
  251. {
  252.     HX_RESULT hResult = HXR_OK;
  253.     pPacket = NULL;
  254.     if (m_pInputPackets->IsEmpty())
  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 if (m_bPacketizing)
  269.     {
  270. // We are converting normal packets into
  271. // RTP packets...
  272. if (m_bFragmentFrames)
  273. {
  274.     hResult = CreateFragmentedPacket(pPacket);
  275. }
  276. else
  277. {
  278.     hResult = CreateNormalPacket(pPacket);
  279. }
  280.     }
  281.     else
  282.     {
  283. // We are converting RTP packets back into
  284. // normal packets...
  285. hResult = UnformatRTPPacket(pPacket);
  286.     }
  287.     return hResult;
  288. }
  289. STDMETHODIMP 
  290. MPAPayloadFormat::Flush()
  291. {
  292.     m_bFlushed = TRUE;
  293.     return HXR_OK;
  294. }
  295. UINT32
  296. MPAPayloadFormat::GetFrameSize(UCHAR* pBuffer, 
  297.        UINT32 ulSize, 
  298.        REF(UINT32) ulBytesSkipped)
  299. {
  300.     UCHAR* pStart = pBuffer;
  301.     UINT32 ulFrameSize = 0;
  302.     ulBytesSkipped = ulSize;
  303.     HX_ASSERT(pBuffer);
  304.     HX_ASSERT(ulSize);
  305.     if (pBuffer && ulSize)
  306.     {
  307. MPEG_HEAD h;
  308. INT32 iFrameSize = 0;
  309. BOOL bCheckWord = FALSE;
  310. for (UINT32 i = 0; i < ulSize; i++)
  311. {
  312.             bCheckWord = ((pStart[i] & 0xF0) == 0xF0) |
  313.                          ((pStart[i] & 0xF0) == 0xE0);
  314.     if (bCheckWord)
  315.     {
  316. memset(&h, 0, sizeof(h));
  317. iFrameSize = head_info(&pStart[i], ulSize - i, &h, 0);
  318. if (iFrameSize)
  319. {
  320.     ulFrameSize = (UINT32)iFrameSize;
  321.     ulBytesSkipped = i;
  322.     break;
  323. }
  324.     }
  325. }
  326.     }
  327.     return ulFrameSize;
  328. }
  329. UINT32
  330. MPAPayloadFormat::GetFrameOffset(IHXBuffer* pBuffer)
  331. {
  332.     UCHAR* pBuf = NULL;
  333.     
  334.     HX_ASSERT(pBuffer);
  335.     pBuf = pBuffer->GetBuffer();
  336.     HX_ASSERT(pBuf);
  337.     // Skip the first 2 Bytes which are specified
  338.     // as "reserved" in RFC 2250
  339.     pBuf += 2;
  340.     // The next two Bytes contain the frame offset
  341.     return (UINT32)getshort(pBuf);
  342. }
  343. HX_RESULT
  344. MPAPayloadFormat::CreateNormalPacket(REF(IHXPacket*) pPacket)
  345. {
  346.     HX_RESULT hResult = HXR_OK;
  347.     UINT32 ulBufSize = 0;
  348.     UCHAR* pBuf = NULL;
  349.     IHXPacket* pNewPacket = NULL;
  350.     IHXBuffer* pNewBuffer = NULL;
  351.     if ((m_ulInputSize < (m_ulFramesPerPacket * m_ulFrameSize)) && 
  352. !m_bFlushed)
  353.     {
  354. // We don't have enough input 
  355. // data to produce a packet
  356. hResult = HXR_INCOMPLETE;
  357.     }
  358.     else
  359.     {
  360. // Create a new packet
  361. m_pClassFactory->CreateInstance(CLSID_IHXPacket, 
  362.     (void**)&pNewPacket);
  363. // Create a new buffer
  364. m_pClassFactory->CreateInstance(CLSID_IHXBuffer, 
  365.     (void**)&pNewBuffer);
  366. // Figure out what the timestamp should be
  367. UINT32 ulNewTimestamp = GetNextTimestamp();
  368. // Set the size of the buffer appropriately
  369. ulBufSize = (m_ulFrameSize * m_ulFramesPerPacket);
  370. if (m_ulInputSize < ulBufSize)
  371. {
  372.     // We must have been flushed, so fill the packet
  373.     // with whatever remaining data we have
  374.     HX_ASSERT(m_bFlushed);
  375.     ulBufSize = m_ulInputSize;
  376. }
  377. ulBufSize += 4;
  378. pNewBuffer->SetSize(ulBufSize);
  379. pBuf = pNewBuffer->GetBuffer();
  380. // Set the 4-Byte audio header for this packet 
  381. // (as dictated by RFC 2250)
  382. putshort(pBuf, 0);
  383. pBuf += 2;
  384. putshort(pBuf, 0);
  385. pBuf += 2;
  386. // Copy the data from the input packet list 
  387. // into the new packet buffer
  388. CopyInput(pBuf, ulBufSize - 4);
  389. // Finalize the new packet
  390. pNewPacket->Set(pNewBuffer, ulNewTimestamp, 
  391.     (UINT16)m_ulStreamNum, HX_ASM_SWITCH_ON, 0);
  392. HX_RELEASE(pNewBuffer);
  393. pPacket = pNewPacket;
  394.     }
  395.     return hResult;
  396. }
  397. HX_RESULT
  398. MPAPayloadFormat::CreateFragmentedPacket(REF(IHXPacket*) pPacket)
  399. {
  400.     HX_RESULT hResult = HXR_OK;
  401.     UINT32 ulBufSize = 0;
  402.     UCHAR* pBuf = NULL;
  403.     IHXPacket* pNewPacket = NULL;
  404.     IHXBuffer* pNewBuffer = NULL;
  405.     // Figure out how much we want to put in this packet, based on the
  406.     // frame size, frame offset, and max packet size
  407.     ulBufSize = m_ulFrameSize - m_ulFrameOffset;
  408.     if (ulBufSize > m_ulMaxPacketSize)
  409.     {
  410. ulBufSize = m_ulMaxPacketSize;
  411.     }
  412.     if ((m_ulInputSize < ulBufSize) && 
  413. !m_bFlushed)
  414.     {
  415. // We don't have enough input 
  416. // data to produce a full packet
  417. hResult = HXR_INCOMPLETE;
  418.     }
  419.     else
  420.     {
  421. // Create a new packet
  422. m_pClassFactory->CreateInstance(CLSID_IHXPacket, 
  423.     (void**)&pNewPacket);
  424. // Create a new buffer
  425. m_pClassFactory->CreateInstance(CLSID_IHXBuffer, 
  426.     (void**)&pNewBuffer);
  427. // Figure out what the timestamp should be
  428. UINT32 ulNewTimestamp = GetNextTimestamp();
  429. // Set the size of the buffer appropriately
  430. if (m_ulInputSize < ulBufSize)
  431. {
  432.     // We must have been flushed, so fill the packet
  433.     // with whatever remaining data we have
  434.     HX_ASSERT(m_bFlushed);
  435.     ulBufSize = m_ulInputSize;
  436. }
  437. ulBufSize += 4;
  438. pNewBuffer->SetSize(ulBufSize);
  439. pBuf = pNewBuffer->GetBuffer();
  440. // Set the 4-Byte audio header for this packet 
  441. // (as dictated by RFC 2250)
  442. putshort(pBuf, 0);
  443. pBuf += 2;
  444. putshort(pBuf, (UINT16)m_ulFrameOffset);
  445. pBuf += 2;
  446. // Update the current frame offset
  447. m_ulFrameOffset += ulBufSize - 4;
  448. if (m_ulFrameOffset == m_ulFrameSize)
  449. {
  450.     // We finished a frame, so reset our offset
  451.     m_ulFrameOffset = 0;
  452. }
  453. // Copy the data from the input packet list 
  454. // into the new packet buffer
  455. CopyInput(pBuf, ulBufSize - 4);
  456. // Finalize the new packet
  457. pNewPacket->Set(pNewBuffer, ulNewTimestamp, 
  458.     (UINT16)m_ulStreamNum, HX_ASM_SWITCH_ON, 0);
  459. HX_RELEASE(pNewBuffer);
  460. pPacket = pNewPacket;
  461.     }
  462.     return hResult;
  463. }
  464. HX_RESULT
  465. MPAPayloadFormat::UnformatRTPPacket(REF(IHXPacket*) pPacket)
  466. {
  467.     HX_RESULT hResult = HXR_OK;
  468.     BOOL bDone = FALSE;
  469.     while (!bDone)
  470.     {
  471. if (m_pPartialPacket)
  472. {
  473.     // We've already unformatted part of an audio frame,
  474.     // so grab then next packet and add it to the end
  475.     hResult = UnformatNextPacket(pPacket, bDone);
  476. }
  477. else
  478. {
  479.     // We don't have any partially unformatted data,
  480.     // so just grab the first packet and deal with it
  481.     hResult = UnformatFirstPacket(pPacket, bDone);
  482. }
  483.     }
  484.     return hResult;
  485. }
  486. HX_RESULT
  487. MPAPayloadFormat::UnformatFirstPacket(REF(IHXPacket*) pPacket, 
  488.       REF(BOOL) bDone)
  489. {
  490.     IHXPacket* pNextPacket = NULL;
  491.     IHXBuffer* pNextBuffer = NULL;
  492.     bDone = FALSE;
  493.     // Get the next input packet
  494.     pNextPacket = (IHXPacket*)m_pInputPackets->RemoveHead();
  495.     HX_ASSERT(pNextPacket);
  496.     // If this is a lost packet, give it
  497.     // straight back to the caller
  498.     if (pNextPacket->IsLost())
  499.     {
  500. pPacket = pNextPacket;
  501. bDone = TRUE;
  502. return HXR_OK;
  503.     }
  504.     pNextBuffer = pNextPacket->GetBuffer();
  505.     HX_ASSERT(pNextBuffer);
  506.     // Create a new packet
  507.     m_pClassFactory->CreateInstance(CLSID_IHXPacket, 
  508. (void**)&m_pPartialPacket);
  509.     HX_ASSERT(m_pPartialPacket);
  510.     // Create a new buffer
  511.     m_pClassFactory->CreateInstance(CLSID_IHXBuffer, 
  512. (void**)&m_pPartialBuffer);
  513.     HX_ASSERT(m_pPartialBuffer);
  514.     // Add this onto the new packet
  515.     m_pPartialBuffer->SetSize(pNextBuffer->GetSize() - 4);
  516.     memcpy(m_pPartialBuffer->GetBuffer(), /* Flawfinder: ignore */
  517.    pNextBuffer->GetBuffer() + 4, 
  518.    pNextBuffer->GetSize() - 4);
  519.     // Set all properties except buffer from this packet
  520.     m_pPartialPacket->Set(m_pPartialBuffer, 
  521.   pNextPacket->GetTime(), 
  522.   pNextPacket->GetStreamNumber(), 
  523.   pNextPacket->GetASMFlags(), 
  524.   pNextPacket->GetASMRuleNumber());
  525.     // Find out if this packet contains an integral number
  526.     // of full frames or a fragment of a single large frame
  527.     UINT32 ulOffset = GetFrameOffset(pNextBuffer);
  528.     if (!ulOffset && !m_ulFrameSize)
  529.     {
  530. UINT32 ulBytesSkipped = 0;
  531. m_ulFrameSize = GetFrameSize(pNextBuffer->GetBuffer() + 4,
  532.     pNextBuffer->GetSize() - 4, ulBytesSkipped);
  533. HX_ASSERT(m_ulFrameSize);
  534. if (ulBytesSkipped)
  535. {
  536.     // If we had to skip any Bytes to find the header
  537.     // info, discard those leading Bytes as garbage
  538.     m_ulInputUsed = ulBytesSkipped;
  539.     m_ulInputSize -= ulBytesSkipped;
  540. }
  541.     }
  542.     if (ulOffset)
  543.     {
  544. // We must have lost the previous packet in this
  545. // frame, so toss out the rest for now
  546. //
  547. // XXXDPS - If we can actually make some use of a
  548. // partial audio frame, we may want to do something
  549. // more intelligent here...
  550. HX_RELEASE(m_pPartialBuffer);
  551. HX_RELEASE(m_pPartialPacket);
  552. bDone = FALSE;
  553.     }
  554.     else
  555.     {
  556. if (m_ulFrameSize <= (pNextBuffer->GetSize() - 4))
  557. {
  558.     // The packet contains an integral number of full frames
  559.     // Return the packet we've constructed
  560.     pPacket = m_pPartialPacket;
  561.     pPacket->AddRef();
  562.     HX_RELEASE(m_pPartialBuffer);
  563.     HX_RELEASE(m_pPartialPacket);
  564.     bDone = TRUE;
  565. }
  566. else
  567. {
  568.     // The packet contains the first fragment of a large
  569.     // frame that spans several packets
  570.     // We will keep looping and adding data to this buffer
  571.     // until we have constructed an entire frame of audio...
  572. }
  573.     }
  574.     HX_RELEASE(pNextBuffer);
  575.     HX_RELEASE(pNextPacket);
  576.     return HXR_OK;
  577. }
  578. HX_RESULT
  579. MPAPayloadFormat::UnformatNextPacket(REF(IHXPacket*) pPacket, 
  580.      REF(BOOL) bDone)
  581. {
  582.     HX_RESULT hResult = HXR_OK;
  583.     IHXPacket* pNextPacket = NULL;
  584.     IHXBuffer* pNextBuffer = NULL;
  585.     bDone = FALSE;
  586.     if (m_pInputPackets->IsEmpty())
  587.     {
  588. if (!m_bFlushed)
  589. {
  590.     // We don't have enough input 
  591.     // data to produce a full packet
  592.     hResult = HXR_INCOMPLETE;
  593. }
  594. else
  595. {
  596.     // Return the (partial) packet we've constructed
  597.     pPacket = m_pPartialPacket;
  598.     pPacket->AddRef();
  599.     HX_RELEASE(m_pPartialBuffer);
  600.     HX_RELEASE(m_pPartialPacket);
  601. }
  602. bDone = TRUE;
  603.     }
  604.     else
  605.     {
  606. // Get the next input packet
  607. pNextPacket = (IHXPacket*)m_pInputPackets->RemoveHead();
  608. HX_ASSERT(pNextPacket);
  609. if (pNextPacket->IsLost())
  610. {
  611.     // If the packet is a lost packet, discard any
  612.     // partial packet we may have been building and
  613.     // forward this lost packet back to the caller
  614.     pPacket = pNextPacket;
  615.     pPacket->AddRef();
  616.     HX_RELEASE(m_pPartialBuffer);
  617.     HX_RELEASE(m_pPartialPacket);
  618.     bDone = TRUE;
  619. }
  620. else
  621. {
  622.     pNextBuffer = pNextPacket->GetBuffer();
  623.     HX_ASSERT(pNextBuffer);
  624.     // Add the data from this packet onto our cumulative buffer
  625.     // Temporarily Release() our references on the buffer, since
  626.     // m_pPartialPacket has a reference on it and we can't set a
  627.     // buffer with 2 references. We will re-AddRef() it in a sec.
  628.     m_pPartialBuffer->Release();
  629.     UINT32 ulPrevSize = m_pPartialBuffer->GetSize();
  630.     m_pPartialBuffer->SetSize(ulPrevSize + 
  631. pNextBuffer->GetSize() - 4);
  632.     memcpy(m_pPartialBuffer->GetBuffer() + ulPrevSize, /* Flawfinder: ignore */
  633.    pNextBuffer->GetBuffer() + 4,
  634.    pNextBuffer->GetSize() - 4);
  635.     // Re-AddRef() the buffer now that we have set it
  636.     m_pPartialBuffer->AddRef();
  637.     m_pPartialPacket->Set(m_pPartialBuffer, 
  638.   m_pPartialPacket->GetTime(), 
  639.   m_pPartialPacket->GetStreamNumber(), 
  640.   m_pPartialPacket->GetASMFlags(), 
  641.   m_pPartialPacket->GetASMRuleNumber());
  642.     if (m_pPartialBuffer->GetSize() >= m_ulFrameSize)
  643.     {
  644. // Return the (full) packet we've constructed
  645. pPacket = m_pPartialPacket;
  646. pPacket->AddRef();
  647. HX_RELEASE(m_pPartialBuffer);
  648. HX_RELEASE(m_pPartialPacket);
  649. bDone = TRUE;
  650.     }
  651.     HX_RELEASE(pNextBuffer);
  652. }
  653. HX_RELEASE(pNextPacket);
  654.     }
  655.     return hResult;
  656. }
  657. HX_RESULT
  658. MPAPayloadFormat::CreateLostPacket(IHXPacket* pOldPacket, 
  659.    REF(IHXPacket*) pNewPacket)
  660. {
  661.     // Create a new packet
  662.     m_pClassFactory->CreateInstance(CLSID_IHXPacket, 
  663. (void**)&pNewPacket);
  664.     HX_ASSERT(pNewPacket);
  665.     // Set all properties except buffer and time from
  666.     // the old packet
  667.     pNewPacket->Set(NULL, 
  668.     0, 
  669.     pOldPacket->GetStreamNumber(), 
  670.     pOldPacket->GetASMFlags(), 
  671.     pOldPacket->GetASMRuleNumber());
  672.     pNewPacket->SetAsLost();
  673.     return HXR_OK;
  674. }
  675. UINT32
  676. MPAPayloadFormat::GetNextTimestamp()
  677. {
  678.     if (m_pInputPackets->IsEmpty())
  679.     {
  680. return 0;
  681.     }
  682.     else
  683.     {
  684. IHXPacket* pPacket = (IHXPacket*)m_pInputPackets->GetHead();
  685. HX_ASSERT(pPacket);
  686. return pPacket->GetTime();
  687.     }
  688. }
  689. void
  690. MPAPayloadFormat::CopyInput(UCHAR* pDest, UINT32 ulSize)
  691. {
  692.     UINT32 ulBytesCopied = 0;
  693.     while (ulBytesCopied < ulSize)
  694.     {
  695. IHXPacket* pPacket = (IHXPacket*)m_pInputPackets->RemoveHead();
  696. HX_ASSERT(pPacket);
  697. IHXBuffer* pBuffer = pPacket->GetBuffer();
  698. HX_ASSERT(pBuffer);
  699. UCHAR* pSrc = pBuffer->GetBuffer();
  700. HX_ASSERT(pSrc);
  701. UINT32 ulSrcSize = pBuffer->GetSize();
  702. HX_ASSERT(ulSrcSize);
  703. // Offset the input buffer based on 
  704. // how much we have previously used
  705. pSrc += m_ulInputUsed;
  706. ulSrcSize -= m_ulInputUsed;
  707. if (ulSrcSize < ulSize - ulBytesCopied)
  708. {
  709.     memcpy(pDest, pSrc, ulSrcSize); /* Flawfinder: ignore */
  710.     pDest += ulSrcSize;
  711.     ulBytesCopied += ulSrcSize;
  712.     m_ulInputUsed = 0;
  713. }
  714. else if (ulSrcSize > ulSize - ulBytesCopied)
  715. {
  716.     // This packet is more than big enough
  717.     // to fill our requested size
  718.     UINT32 ulBytesToCopy = ulSize - ulBytesCopied;
  719.     memcpy(pDest, pSrc, ulBytesToCopy); /* Flawfinder: ignore */
  720.     pDest += ulBytesToCopy;
  721.     ulBytesCopied += ulBytesToCopy;
  722.     // Add this packet back onto the list
  723.     pPacket->AddRef();
  724.     m_pInputPackets->AddHead(pPacket);
  725.     // Remember how much of it we have used
  726.     m_ulInputUsed += ulBytesToCopy;
  727. }
  728. else
  729. {
  730.     // An exact match!
  731.     memcpy(pDest, pSrc, ulSrcSize); /* Flawfinder: ignore */
  732.     pDest += ulSrcSize;
  733.     ulBytesCopied += ulSrcSize;
  734.     m_ulInputUsed = 0;
  735. }
  736. HX_RELEASE(pBuffer);
  737. HX_RELEASE(pPacket);
  738.     }
  739.     m_ulInputSize -= ulBytesCopied;
  740. }