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

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 "hxassert.h"
  38. #include "hxslist.h"
  39. #include "hxcomm.h"
  40. #include "ihxpckts.h"
  41. #include "netbyte.h"
  42. #include "sspayld.h"
  43. #define DEFAULT_MAX_PACKET_SIZE 1500
  44. SimpleSegmentPayloadFormat::SimpleSegmentPayloadFormat()
  45. : m_lRefCount(0)
  46. , m_pCommonClassFactory(NULL)
  47. , m_pStreamHeader(NULL)
  48. , m_bPacketize(FALSE)
  49. , m_ulMaxSegmentSize(DEFAULT_MAX_PACKET_SIZE)
  50. , m_ulTotalSegments(0)
  51. , m_pSegmentedPackets(NULL)
  52. , m_pAssembledPacket(NULL)
  53. , m_bBigEndian(FALSE)
  54. {
  55.     m_pSegmentedPackets = new CHXSimpleList();
  56.     m_bBigEndian = TestBigEndian();
  57. }
  58. SimpleSegmentPayloadFormat::~SimpleSegmentPayloadFormat()
  59. {
  60.     Reset();
  61.     HX_DELETE(m_pSegmentedPackets);
  62.     HX_RELEASE(m_pCommonClassFactory);
  63. }
  64. // *** IUnknown methods ***
  65. /////////////////////////////////////////////////////////////////////////
  66. //  Method:
  67. //  IUnknown::QueryInterface
  68. //  Purpose:
  69. //  Implement this to export the interfaces supported by your
  70. //  object.
  71. //
  72. STDMETHODIMP
  73. SimpleSegmentPayloadFormat::QueryInterface(REFIID riid, void** ppvObj)
  74. {
  75.     QInterfaceList  qiList[] =
  76.     {
  77. { GET_IIDHANDLE(IID_IUnknown), this},
  78. { GET_IIDHANDLE(IID_IHXPayloadFormatObject), (IHXPayloadFormatObject*)this},
  79.     };
  80.     return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  81. }
  82. /////////////////////////////////////////////////////////////////////////
  83. //  Method:
  84. //  IUnknown::AddRef
  85. //  Purpose:
  86. //  Everyone usually implements this the same... feel free to use
  87. //  this implementation.
  88. //
  89. STDMETHODIMP_(ULONG32)
  90. SimpleSegmentPayloadFormat::AddRef()
  91. {
  92.     return InterlockedIncrement(&m_lRefCount);
  93. }
  94. /////////////////////////////////////////////////////////////////////////
  95. //  Method:
  96. //  IUnknown::Release
  97. //  Purpose:
  98. //  Everyone usually implements this the same... feel free to use
  99. //  this implementation.
  100. //
  101. STDMETHODIMP_(ULONG32)
  102. SimpleSegmentPayloadFormat::Release()
  103. {
  104.     if ( InterlockedDecrement(&m_lRefCount) > 0 )
  105.     {
  106.         return m_lRefCount;
  107.     }
  108.     delete this;
  109.     return 0;
  110. }
  111. STDMETHODIMP
  112. SimpleSegmentPayloadFormat::Init( IUnknown* pContext,
  113.                                   BOOL bPacketize )
  114. {
  115.     HX_ASSERT(pContext);
  116.     if ( !pContext )
  117.     {
  118.         return HXR_FAIL;
  119.     }
  120.     HX_RELEASE(m_pCommonClassFactory);
  121.     m_pCommonClassFactory = NULL;
  122.     if ( HXR_OK != pContext->QueryInterface( IID_IHXCommonClassFactory,
  123.                                              (void**) &m_pCommonClassFactory )
  124.        )
  125.     {
  126.         return HXR_FAIL;
  127.     }
  128.     m_bPacketize = bPacketize;
  129.     return HXR_OK;
  130. }
  131. STDMETHODIMP
  132. SimpleSegmentPayloadFormat::Reset()
  133. {
  134.     // Reset() is presumed not to be the complete opposite of Init();
  135.     // We reset stream information but keep our context and packetization
  136.     // orientation until the next Init()
  137.     HX_RELEASE( m_pStreamHeader );
  138.     m_pStreamHeader = NULL;
  139.     m_ulMaxSegmentSize = 0;
  140.     HX_RELEASE( m_pAssembledPacket );
  141.     m_pAssembledPacket = NULL;
  142.     return Flush();
  143. }
  144. STDMETHODIMP
  145. SimpleSegmentPayloadFormat::SetStreamHeader( IHXValues* pHeader )
  146. {
  147.     HX_ASSERT( pHeader );
  148.     if ( !pHeader )
  149.     {
  150.         return HXR_FAIL;
  151.     }
  152.     HX_RELEASE( m_pStreamHeader );
  153.     m_pStreamHeader = pHeader;
  154.     m_pStreamHeader->AddRef();
  155.     if ( HXR_OK != m_pStreamHeader->GetPropertyULONG32( "MaxPacketSize", m_ulMaxSegmentSize ) )
  156.     {
  157.         m_ulMaxSegmentSize = DEFAULT_MAX_PACKET_SIZE;
  158.     }
  159.     return HXR_OK;
  160. }
  161. STDMETHODIMP
  162. SimpleSegmentPayloadFormat::GetStreamHeader( REF(IHXValues*) pHeader )
  163. {
  164.     HX_ASSERT( m_pStreamHeader );
  165.     pHeader = m_pStreamHeader;
  166.     pHeader->AddRef();
  167.     return HXR_OK;
  168. }
  169. STDMETHODIMP
  170. SimpleSegmentPayloadFormat::SetPacket( IHXPacket* pPacket )
  171. {
  172.     HX_ASSERT(pPacket);
  173.     if ( !pPacket )
  174.     {
  175.         return HXR_FAIL;
  176.     }
  177.     if ( m_bPacketize )
  178.     {
  179.         // Segment the packet here rather than in GetPacket(), on
  180.         // the assumption that GetPacket() is a time sensitive function:
  181.         // We implicitly allow multiple SetPackets() before a GetPacket()
  182.         // in this case; it is up to the client to realize there are multiple
  183.         // segmented packets in our queue.
  184.         IHXBuffer* pPacketBuffer = pPacket->GetBuffer();
  185.         HX_ASSERT( pPacketBuffer );
  186.         if ( !pPacketBuffer )
  187.         {
  188.             return HXR_FAIL;
  189.         }
  190.         UCHAR* pPacketBufferData = pPacketBuffer->GetBuffer();
  191.         UINT32 uiBytesRemaining = pPacketBuffer->GetSize();
  192.         // An unsafe cast: to retain backwards compatibility, not much we can do about it.
  193.         // We could implement a high segment count as an escape sequence; this would break
  194.         // however, in the unlikely event someone wanted to segment a packet into 65535
  195.         // chunks using deployed code (CPNFragment).  To be investigated if the priority ever
  196.         // becomes high.
  197.         m_ulTotalSegments = (unsigned short) ( pPacketBuffer->GetSize() / m_ulMaxSegmentSize );
  198.         if ( pPacketBuffer->GetSize() % m_ulMaxSegmentSize )
  199.         {
  200.             m_ulTotalSegments++;
  201.         }
  202.         IHXBuffer* pSegmentBuffer;
  203.         IHXPacket* pSegmentPacket;
  204.         for ( int i = 0; uiBytesRemaining; i++ )
  205.         {
  206.             if ( HXR_OK != m_pCommonClassFactory->CreateInstance( IID_IHXBuffer,
  207.                                                                   (void**) &pSegmentBuffer )
  208.                )
  209.             {
  210.                 Flush();
  211.                 HX_RELEASE( pPacketBuffer );
  212.                 return HXR_OUTOFMEMORY;
  213.             }
  214.             if ( HXR_OK != m_pCommonClassFactory->CreateInstance( IID_IHXPacket,
  215.                                                                   (void**) &pSegmentPacket )
  216.                )
  217.             {
  218.                 Flush();
  219.                 HX_RELEASE( pSegmentBuffer );
  220.                 HX_RELEASE( pPacketBuffer );
  221.                 return HXR_OUTOFMEMORY;
  222.             }
  223.             pSegmentBuffer->SetSize( sizeof(SEGMENTHEADER) + (uiBytesRemaining > m_ulMaxSegmentSize) ? m_ulMaxSegmentSize : uiBytesRemaining );
  224.             LPSEGMENTHEADER pSegmentHeader = (LPSEGMENTHEADER) pSegmentBuffer->GetBuffer();
  225.             pSegmentHeader->ulOffset = i * ( m_ulMaxSegmentSize );
  226.             pSegmentHeader->usIndex = i;
  227.             pSegmentHeader->usTotalSegments = m_ulTotalSegments;
  228.             if ( !m_bBigEndian )
  229.             {
  230.                 SwapDWordBytes(&pSegmentHeader->ulOffset, 1);
  231.                 SwapWordBytes(&pSegmentHeader->usIndex, 1);
  232.                 SwapWordBytes(&pSegmentHeader->usTotalSegments, 1);
  233.             }
  234.             memcpy( (UCHAR*) pSegmentHeader + sizeof(SEGMENTHEADER), /* Flawfinder: ignore */
  235.                     pPacketBufferData + pSegmentHeader->ulOffset,
  236.                     pSegmentBuffer->GetSize() - sizeof(SEGMENTHEADER)
  237.                   );
  238.             uiBytesRemaining -= pSegmentBuffer->GetSize() - sizeof(SEGMENTHEADER);;
  239.             pSegmentPacket->Set( pSegmentBuffer,
  240.                                  pPacket->GetTime(),
  241.                                  pPacket->GetStreamNumber(),
  242.                                  pPacket->GetASMFlags(),
  243.                                  pPacket->GetASMRuleNumber()
  244.                                );
  245.             HX_RELEASE( pSegmentBuffer );
  246.             m_pSegmentedPackets->AddTail( pSegmentPacket );
  247.         }
  248.         HX_RELEASE( pPacketBuffer );
  249.     }
  250.     else
  251.     {
  252.         // This PayloadFormat does not return incomplete data;
  253.         // The client is assumed to be able to deal with lost data quantums
  254.         // of the size of m_ulPacketSize:
  255.         if ( pPacket->IsLost() )
  256.         {
  257.             Flush();
  258.             return HXR_OK;
  259.         }
  260.         IHXBuffer* pPacketBuffer = pPacket->GetBuffer();
  261.         UINT16 usSegment = ( (LPSEGMENTHEADER) pPacketBuffer->GetBuffer() )->usIndex;
  262.         if ( !m_bBigEndian )
  263.         {
  264.             SwapWordBytes( &usSegment, 1 );
  265.         }
  266.         HX_RELEASE( pPacketBuffer );
  267.         // Missing/lost segments?
  268.         if (usSegment != m_pSegmentedPackets->GetCount())
  269.         {
  270.             // Since we flush on lost packets, a non-zero segment list
  271.             // indicates a *missing* packet (bug in the core)
  272.             HX_ASSERT(m_pSegmentedPackets->GetCount() == 0 && "Missing segments!");
  273.             Flush();
  274.             return HXR_OK;
  275.         }
  276.         pPacket->AddRef();
  277.         m_pSegmentedPackets->AddTail( pPacket );
  278.         // New frame?
  279.         if ( usSegment == 0 )
  280.         {
  281.             IHXBuffer* pFirstBuffer = pPacket->GetBuffer();
  282.             HX_ASSERT( pFirstBuffer );
  283.             m_ulTotalSegments = ( (LPSEGMENTHEADER) pFirstBuffer->GetBuffer() )->usTotalSegments;
  284.             if ( !m_bBigEndian )
  285.             {
  286.                 SwapWordBytes( &m_ulTotalSegments, 1 );
  287.             }
  288.             HX_RELEASE( pFirstBuffer );
  289.             if (m_ulTotalSegments == 0)
  290.             {
  291.                 // No segments, eh?
  292.                 HX_ASSERT(FALSE && "Segment count zero - packetizer error!");
  293.                 Flush();
  294.                 return HXR_OK;
  295.             }
  296.         }
  297.         // Sort and reconstruct the packet here, rather than in GetPacket(), on
  298.         // the assumption that GetPacket() is a time sensitive function:
  299.         if ( m_pSegmentedPackets->GetCount() == m_ulTotalSegments )
  300.         {
  301.             // We use a simple O(n) reconstruction here (no sorting)
  302.             UINT32 uiPacketSize = 0;
  303.             IHXBuffer* pSegmentBuffer = NULL;
  304.             UCHAR* pSegmentBufferData = NULL;
  305.             // Find packet size and swap headers:
  306.             for ( CHXSimpleList::Iterator maxIterator = m_pSegmentedPackets->Begin();
  307.                 maxIterator != m_pSegmentedPackets->End();
  308.                 ++maxIterator )
  309.             {
  310.                 pSegmentBuffer = ( (IHXPacket*) *maxIterator )->GetBuffer();
  311.                 pSegmentBufferData = pSegmentBuffer->GetBuffer();
  312.                 if ( !m_bBigEndian )
  313.                 {
  314.                     SwapDWordBytes( &( (LPSEGMENTHEADER) pSegmentBufferData )->ulOffset, 1 );
  315.                 }
  316.                 if ( ( (LPSEGMENTHEADER) pSegmentBufferData )->ulOffset + pSegmentBuffer->GetSize() > uiPacketSize )
  317.                 {
  318.                     uiPacketSize = ( (LPSEGMENTHEADER) pSegmentBufferData )->ulOffset + pSegmentBuffer->GetSize();
  319.                 }
  320.                 HX_RELEASE(pSegmentBuffer);
  321.             }
  322.             uiPacketSize -= sizeof( SEGMENTHEADER );
  323.             // An assembled packet should have been collected by this point; we only assemble
  324.             // one packet at a time, for now, for simplicity.
  325.             HX_ASSERT( !m_pAssembledPacket );
  326.             HX_RELEASE( m_pAssembledPacket );
  327.             m_pAssembledPacket = NULL;
  328.             // Create our assembled packet, buffer:
  329.             IHXBuffer* pPacketBuffer = NULL;
  330.             if ( HXR_OK != m_pCommonClassFactory->CreateInstance( IID_IHXBuffer,
  331.                                                                   (void**) &pPacketBuffer )
  332.                )
  333.             {
  334.                 Flush();
  335.                 return HXR_FAIL;
  336.             }
  337.             if ( HXR_OK != m_pCommonClassFactory->CreateInstance( IID_IHXPacket,
  338.                                                                   (void**) &m_pAssembledPacket )
  339.                )
  340.             {
  341.                 Flush();
  342.                 HX_RELEASE( pPacketBuffer );
  343.                 return HXR_FAIL;
  344.             }
  345.             pPacketBuffer->SetSize( uiPacketSize );
  346.             IHXPacket* pPacketDetails = ( (IHXPacket*) m_pSegmentedPackets->GetHead() );
  347.             m_pAssembledPacket->Set(pPacketBuffer,
  348.                                     pPacketDetails->GetTime(),
  349.                                     pPacketDetails->GetStreamNumber(),
  350.                                     pPacketDetails->GetASMFlags(),
  351.                                     pPacketDetails->GetASMRuleNumber()
  352.                                    );
  353.             // This reconstruction approach may not assemble in segment order, but the
  354.             // performance penalty is small, and it keeps the code simple.  Using ulOffset
  355.             // also allows clever datatypes/compatible payload formatters to insert gaps in
  356.             // the buffer in which the renders could write data for their own bizzare
  357.             // purposes (use at your own peril).
  358.             UCHAR* pPacketBufferData = pPacketBuffer->GetBuffer();
  359.             UINT32 ulPacketBufferSize = pPacketBuffer->GetSize();
  360.             HX_RELEASE(pPacketBuffer);
  361.             IHXPacket* pSegmentPacket = NULL;
  362.             while ( !m_pSegmentedPackets->IsEmpty() )
  363.             {
  364.                 pSegmentPacket = (IHXPacket*) m_pSegmentedPackets->RemoveHead();
  365.                 HX_ASSERT( pSegmentPacket );
  366.                 pSegmentBuffer = pSegmentPacket->GetBuffer();
  367.                 HX_ASSERT( pSegmentBuffer );
  368.                 pSegmentBufferData = pSegmentBuffer->GetBuffer();
  369.                 UINT32 ulMaxCopyBytes = ulPacketBufferSize - ( (LPSEGMENTHEADER) pSegmentBufferData )->ulOffset;
  370.                 UINT32 ulBytesToCopy = pSegmentBuffer->GetSize() - sizeof(SEGMENTHEADER);
  371.                 if (ulBytesToCopy > ulMaxCopyBytes) ulBytesToCopy = ulMaxCopyBytes;
  372.                 memcpy( pPacketBufferData + ( (LPSEGMENTHEADER) pSegmentBufferData )->ulOffset, /* Flawfinder: ignore */
  373.                         pSegmentBufferData + sizeof(SEGMENTHEADER),
  374.                         ulBytesToCopy);
  375.                 HX_RELEASE( pSegmentBuffer );
  376.                 HX_RELEASE( pSegmentPacket );
  377.             }
  378.         }
  379.     }
  380.     return HXR_OK;
  381. }
  382. STDMETHODIMP
  383. SimpleSegmentPayloadFormat::GetPacket( REF(IHXPacket*) pPacket )
  384. {
  385.     pPacket = NULL;
  386.     if ( m_bPacketize )
  387.     {
  388.         if ( m_pSegmentedPackets->IsEmpty() )
  389.         {
  390.             return HXR_UNEXPECTED;
  391.         }
  392.         else
  393.         {
  394.             pPacket = (IHXPacket*) m_pSegmentedPackets->RemoveHead();
  395.         }
  396.     }
  397.     else
  398.     {
  399.         if ( m_pAssembledPacket )
  400.         {
  401.             pPacket = m_pAssembledPacket;
  402.             m_pAssembledPacket = NULL;
  403.         }
  404.         else
  405.         {
  406.             return HXR_INCOMPLETE;
  407.         }
  408.     }
  409.     return HXR_OK;
  410. }
  411. STDMETHODIMP
  412. SimpleSegmentPayloadFormat::Flush()
  413. {
  414.     // Release all of our segment packets; but keep any assembled
  415.     while ( !m_pSegmentedPackets->IsEmpty() )
  416.     {
  417.         IHXPacket* pPacket = (IHXPacket*) m_pSegmentedPackets->RemoveHead();
  418.         HX_RELEASE(pPacket);
  419.     }
  420.     m_ulTotalSegments = 0;
  421.     return HXR_OK;
  422. }