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

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 "hxcom.h"
  37. #include "hxccf.h"
  38. #include "ihxpckts.h"
  39. #include "hxslist.h"
  40. #include "hxamrpack.h"
  41. #include "amr_frame_hdr.h"
  42. #include "amr_mime_info.h"
  43. CHXAMRPayloadFormatPacketizer::CHXAMRPayloadFormatPacketizer() :
  44.     m_lRefCount(0),
  45.     m_pCCF(NULL),
  46.     m_pOutQueue(NULL),
  47.     m_ulMinPacketSize(DEFAULT_MIN_PACKET_SIZE),
  48.     m_ulAvgPacketSize(DEFAULT_AVG_PACKET_SIZE),
  49.     m_ulMaxPacketSize(DEFAULT_MAX_PACKET_SIZE),
  50.     m_ulPacketBytesConsumed(0),
  51.     m_ulDurationConsumed(0),
  52.     m_flavor(NarrowBand),
  53.     m_bFlush(FALSE)
  54. {
  55. }
  56. CHXAMRPayloadFormatPacketizer::~CHXAMRPayloadFormatPacketizer()
  57. {
  58.     ClearOutputQueue();
  59.     HX_RELEASE(m_pCCF);
  60.     HX_DELETE(m_pOutQueue);
  61. }
  62. STDMETHODIMP CHXAMRPayloadFormatPacketizer::QueryInterface(REFIID riid, void** ppvObj)
  63. {
  64.     QInterfaceList qiList[] =
  65.     {
  66. { GET_IIDHANDLE(IID_IUnknown), this },
  67. { GET_IIDHANDLE(IID_IHXPayloadFormatObject), (IHXPayloadFormatObject*) this },
  68.     };
  69.     HX_RESULT retVal = HXR_FAIL;
  70.     if (ppvObj)
  71.     {
  72.         // Set default
  73.         *ppvObj = NULL;
  74.         // Clear return
  75.         retVal = HXR_OK;
  76.         return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  77.     }
  78.     return retVal;
  79. }
  80. STDMETHODIMP_(ULONG32) CHXAMRPayloadFormatPacketizer::AddRef()
  81. {
  82.     return InterlockedIncrement(&m_lRefCount);
  83. }
  84. STDMETHODIMP_(ULONG32) CHXAMRPayloadFormatPacketizer::Release()
  85. {
  86.     if (InterlockedDecrement(&m_lRefCount) > 0)
  87.     {
  88.         return m_lRefCount;
  89.     }
  90.     delete this;
  91.     return 0;
  92. }
  93. STDMETHODIMP CHXAMRPayloadFormatPacketizer::Init(IUnknown* pContext, BOOL bPacketize)
  94. {
  95.     HX_RESULT retVal = HXR_FAIL;
  96.     if (pContext && bPacketize)
  97.     {
  98.         HX_RELEASE(m_pCCF);
  99.         retVal = pContext->QueryInterface(IID_IHXCommonClassFactory,
  100.                                           (void**) &m_pCCF);
  101.     }
  102.     return retVal;
  103. }
  104. STDMETHODIMP CHXAMRPayloadFormatPacketizer::Close()
  105. {
  106.     ClearOutputQueue();
  107.     return HXR_OK;
  108. }
  109. STDMETHODIMP CHXAMRPayloadFormatPacketizer::Reset()
  110. {
  111.     return Close();
  112. }
  113. STDMETHODIMP CHXAMRPayloadFormatPacketizer::SetStreamHeader(IHXValues* pHeader)
  114. {
  115.     HX_RESULT retVal = HXR_FAIL;
  116.     if (pHeader)
  117.     {
  118.         IHXBuffer* pTmp = NULL;
  119.         pHeader->GetPropertyCString("MimeType", pTmp);
  120.         if (pTmp)
  121.         {
  122.             const char* pszTmp = (const char*) pTmp->GetBuffer();
  123.             if (pszTmp)
  124.             {
  125.                 if (CAMRMimeInfo::IsHXAMR(pszTmp))
  126.                 {
  127.                     m_flavor = NarrowBand;
  128.                     retVal   = HXR_OK;
  129.                 }
  130.                 else if (CAMRMimeInfo::IsHXWideBandAMR(pszTmp))
  131.                 {
  132.                     m_flavor = WideBand;
  133.                     retVal   = HXR_OK;
  134.                 }
  135.                 if (SUCCEEDED(retVal))
  136.                 {
  137.                     // Get the max packet size if there is one
  138.                     m_ulMaxPacketSize = GetProp(pHeader, "MaxPacketSize");
  139.                     // Get the avg packet size if there is one
  140.                     m_ulAvgPacketSize = GetProp(pHeader, "AvgPacketSize");
  141.                     // Get the max packet size if there is one
  142.                     m_ulMinPacketSize = GetProp(pHeader, "MinPacketSize");
  143.                 }
  144.             }
  145.         }
  146.         HX_RELEASE(pTmp);
  147.     }
  148.     return retVal;
  149. }
  150. STDMETHODIMP CHXAMRPayloadFormatPacketizer::GetStreamHeader(REF(IHXValues*) pHeader)
  151. {
  152.     return HXR_NOTIMPL;
  153. }
  154. STDMETHODIMP CHXAMRPayloadFormatPacketizer::SetPacket(IHXPacket* pPacket)
  155. {
  156.     // Process this input packet into output queue packets.
  157.     // We could have done this either in SetPacket() or GetPacket(),
  158.     // but we choose to do it here. We don't force flushing yet,
  159.     // since we may get more data. Once we get a call to flush,
  160.     // then we process all the input, regardless of min size.
  161.     ProcessInputPacket(pPacket, m_bFlush, m_ulMinPacketSize,
  162.                        m_ulPacketBytesConsumed, m_ulDurationConsumed);
  163.     return HXR_OK;
  164. }
  165. STDMETHODIMP CHXAMRPayloadFormatPacketizer::GetPacket(REF(IHXPacket*) pOutPacket)
  166. {
  167.     HX_RESULT retVal = HXR_FAIL;
  168.     if (m_pOutQueue && m_pOutQueue->GetCount() > 0)
  169.     {
  170.         IHXPacket* pPacket = (IHXPacket*) m_pOutQueue->RemoveHead();
  171.         if (pPacket)
  172.         {
  173.             HX_RELEASE(pOutPacket);
  174.             pOutPacket = pPacket;
  175.             pOutPacket->AddRef();
  176.             // Clear the return value
  177.             retVal = HXR_OK;
  178.         }
  179.         // Release the queue's ref
  180.         HX_RELEASE(pPacket);
  181.     }
  182.     return retVal;
  183. }
  184. STDMETHODIMP CHXAMRPayloadFormatPacketizer::Flush()
  185. {
  186.     m_bFlush = TRUE;
  187.     return HXR_OK;
  188. }
  189. void CHXAMRPayloadFormatPacketizer::ClearOutputQueue()
  190. {
  191.     if (m_pOutQueue)
  192.     {
  193.         LISTPOSITION pos = m_pOutQueue->GetHeadPosition();
  194.         while (pos)
  195.         {
  196.             IHXPacket* pPacket = (IHXPacket*) m_pOutQueue->GetNext(pos);
  197.             HX_RELEASE(pPacket);
  198.         }
  199.         m_pOutQueue->RemoveAll();
  200.     }
  201. }
  202. BOOL CHXAMRPayloadFormatPacketizer::ProcessInputPacket(IHXPacket*  pPacket,
  203.                                                        BOOL        bFlush,
  204.                                                        UINT32      ulMinSize,
  205.                                                        REF(UINT32) rulBytesConsumed,
  206.                                                        REF(UINT32) rulTimeConsumed)
  207. {
  208.     BOOL bRet = FALSE;
  209.     if (pPacket)
  210.     {
  211.         IHXBuffer* pBuffer = pPacket->GetBuffer();
  212.         if (pBuffer)
  213.         {
  214.             BYTE*  pBufStart = pBuffer->GetBuffer();
  215.             BYTE*  pBuf      = pBufStart;
  216.             BYTE*  pBufLimit = pBuffer->GetBuffer() + pBuffer->GetSize();
  217.             UINT32 ulLen     = 0;
  218.             UINT32 ulDur     = 0;
  219.             UINT32 ulDurSum  = 0;
  220.             while (pBuf < pBufLimit &&
  221.                    FindAllAMRFramesLength(pBuf, pBufLimit - pBuf,
  222.                                           ulMinSize,
  223.                                           ulLen, ulDur))
  224.             {
  225.                 // Create the packet
  226.                 CreateAndQueuePacket(pBuf, ulLen,
  227.                                      pPacket->GetTime() + ulDurSum,
  228.                                      pPacket->GetStreamNumber(),
  229.                                      pPacket->GetASMFlags(),
  230.                                      pPacket->GetASMRuleNumber());
  231.                 // Advance the pointer
  232.                 pBuf += ulLen;
  233.                 // Add to duration sum
  234.                 ulDurSum += ulDur;
  235.             }
  236.             // Now if bFlush is TRUE and we have some bytes left,
  237.             // then we need to go ahead and consume everything.
  238.             if (bFlush && pBuf < pBufLimit)
  239.             {
  240.                 // Setting the minimum to 0 will cause everything
  241.                 // to be consumed.
  242.                 if (FindAllAMRFramesLength(pBuf, pBufLimit - pBuf, 0, ulLen, ulDur))
  243.                 {
  244.                     // Create the packet
  245.                     CreateAndQueuePacket(pBuf, ulLen,
  246.                                          pPacket->GetTime() + ulDurSum,
  247.                                          pPacket->GetStreamNumber(),
  248.                                          pPacket->GetASMFlags(),
  249.                                          pPacket->GetASMRuleNumber());
  250.                     // Advance the pointer
  251.                     pBuf += ulLen;
  252.                     // Add to duration sum.
  253.                     ulDurSum += ulDur;
  254.                 }
  255.             }
  256.             // Set the number of packet bytes consumed
  257.             rulBytesConsumed = pBuf - pBufStart;
  258.             // Set the duration consumed
  259.             rulTimeConsumed  = ulDurSum;
  260.             // If we produced any packets, then return TRUE
  261.             bRet = (pBuf > pBufStart ? TRUE : FALSE);
  262.         }
  263.         HX_RELEASE(pBuffer);
  264.     }
  265.     return bRet;
  266. }
  267. BOOL CHXAMRPayloadFormatPacketizer::FindAMRFrameLength(BYTE* pBuf, UINT32 ulLen,
  268.                                                        REF(UINT32) rulLen, REF(UINT32) rulDur)
  269. {
  270.     BOOL bRet = FALSE;
  271.     if (pBuf && ulLen)
  272.     {
  273.         CAMRFrameHdr cHdr(m_flavor);
  274.         cHdr.Unpack(pBuf);
  275.         if (cHdr.HdrBytes() + cHdr.DataBytes() <= ulLen)
  276.         {
  277.             rulLen = cHdr.HdrBytes() + cHdr.DataBytes();
  278.             rulDur = CAMRFrameInfo::FrameDuration();
  279.             bRet   = TRUE;
  280.         }
  281.     }
  282.     return bRet;
  283. }
  284. BOOL CHXAMRPayloadFormatPacketizer::FindAllAMRFramesLength(BYTE* pBuf, UINT32 ulLen,
  285.                                                            UINT32 ulMinSize, REF(UINT32) rulLen,
  286.                                                            REF(UINT32) rulDur)
  287. {
  288.     BOOL bRet = FALSE;
  289.     if (pBuf && ulLen)
  290.     {
  291.         BYTE*  pBufStart  = pBuf;
  292.         BYTE*  pBufLimit  = pBuf + ulLen;
  293.         UINT32 ulDurSum   = 0;
  294.         UINT32 ulFrameLen = 0;
  295.         UINT32 ulFrameDur = 0;
  296.         while (pBuf < pBufLimit &&
  297.                (ulMinSize ? (UINT32)(pBuf - pBufStart) < ulMinSize : TRUE) &&
  298.                FindAMRFrameLength(pBuf, pBufLimit - pBuf, ulFrameLen, ulFrameDur))
  299.         {
  300.             pBuf     += ulFrameLen;
  301.             ulDurSum += ulFrameDur;
  302.         }
  303.         if (pBuf > pBufStart && (UINT32)(pBuf - pBufStart) >= ulMinSize)
  304.         {
  305.             rulLen = pBuf - pBufStart;
  306.             rulDur = ulDurSum;
  307.             bRet   = TRUE;
  308.         }
  309.     }
  310.     return bRet;
  311. }
  312. BOOL CHXAMRPayloadFormatPacketizer::CreateAndQueuePacket(BYTE* pBuf, UINT32 ulLen, UINT32 ulTimeStamp,
  313.                                                          UINT16 usStream, UINT8 ucASMFlags, UINT16 usRuleNum)
  314. {
  315.     BOOL bRet = FALSE;
  316.     if (pBuf && ulLen && m_pCCF)
  317.     {
  318.         IHXBuffer* pBuffer = NULL;
  319.         m_pCCF->CreateInstance(CLSID_IHXBuffer, (void**) &pBuffer);
  320.         if (pBuffer)
  321.         {
  322.             HX_RESULT rv = pBuffer->Set(pBuf, ulLen);
  323.             if (SUCCEEDED(rv))
  324.             {
  325.                 IHXPacket* pPacket = NULL;
  326.                 m_pCCF->CreateInstance(CLSID_IHXPacket, (void**) &pPacket);
  327.                 if (pPacket)
  328.                 {
  329.                     rv = pPacket->Set(pBuffer, ulTimeStamp, usStream, ucASMFlags, usRuleNum);
  330.                     if (SUCCEEDED(rv))
  331.                     {
  332.                         if (!m_pOutQueue)
  333.                         {
  334.                             m_pOutQueue = new CHXSimpleList();
  335.                         }
  336.                         if (m_pOutQueue)
  337.                         {
  338.                             pPacket->AddRef();
  339.                             m_pOutQueue->AddTail((void*) pPacket);
  340.                             bRet = TRUE;
  341.                         }
  342.                     }
  343.                 }
  344.                 HX_RELEASE(pPacket);
  345.             }
  346.         }
  347.         HX_RELEASE(pBuffer);
  348.     }
  349.     return bRet;
  350. }
  351. UINT32 CHXAMRPayloadFormatPacketizer::GetProp(IHXValues* pValues, const char* pszName)
  352. {
  353.     UINT32 ulRet = 0;
  354.     if (pValues && pszName)
  355.     {
  356.         UINT32 ulTmp = 0;
  357.         if (SUCCEEDED(pValues->GetPropertyULONG32(pszName, ulTmp)) && ulTmp)
  358.         {
  359.             ulRet = ulTmp;
  360.         }
  361.     }
  362.     return ulRet;
  363. }