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

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. /****************************************************************************
  36.  *  Defines
  37.  */
  38. #define MP4T_RN_3GPP_TEXT_PAYLOAD_MIME_TYPE "video/X-RN-3GPP-TEXT"
  39. #define FLUSH_ALL_PACKETS   0xFFFFFFFF
  40. #define FORMAT_PARAMETERS_PREFIX "a=fmtp:0 "
  41. #define FORMAT_PARAMETERS_PREFIX_SIZE (sizeof(FORMAT_PARAMETERS_PREFIX) - 1)
  42. #define MAX_INT_TEXT_LENGTH 10
  43. // /XXXEH- need to revisit this.  How (if at all) is a sparse data stream
  44. // handled in RDT:
  45. #define _3GPPT_DEFAULT_SAMPLES_PER_SEC 10
  46. /****************************************************************************
  47.  *  Includes
  48.  */
  49. #include "hxtypes.h"
  50. #include "hxwintyp.h"
  51. #include "hxcom.h"
  52. #include "hxcomm.h"
  53. #include "hxassert.h"
  54. #include "hxslist.h"
  55. #include "hxstrutl.h"
  56. #include "hxcomm.h"
  57. #include "ihxpckts.h"
  58. #include "hxformt.h"
  59. #include "hxrendr.h"
  60. #include "hxformt.h"
  61. #include "hxengin.h"
  62. #include "rule2flg.h" // /For RuleToFlagMap (ASM-rule-to-flag map)
  63. #include "qtatmmgs.h" // /For CQT_TrackInfo_Manager
  64. #include "qttrack.h"  // /For CQTTrack
  65. #include "mp4desc.h"
  66. #include "mp4tpyld.h"
  67. MP4TPayloadFormat::MP4TPayloadFormat(CQTTrack* pTrack,
  68.     CQT_TrackInfo_Manager* pTrackInfoMgr,
  69.     CHXBufferMemoryAllocator* pAllocator)
  70.     : m_lRefCount (0)
  71.     , m_pClassFactory (NULL)
  72.     , m_pStreamHeader (NULL)
  73.     , m_pTextHeader (NULL)
  74.     , m_ulTextCfgHeaderSize (0)
  75.     , m_ulSamplesPerSecond(1000)
  76.     , m_bFlushed (FALSE)
  77.     , m_bFirstPacket (TRUE)
  78.     , m_bUsesRTPPackets (FALSE)
  79.     , m_bRTPPacketTested(FALSE)
  80.     , m_pAllocator (pAllocator)
  81.     , m_bPacketize (FALSE)
  82.     , m_PayloadID (PYID_X_HX_3GPP_TEXT)
  83.     , m_pTrack          (pTrack)
  84.     , m_pTrackInfoMgr   (pTrackInfoMgr)
  85.     , m_pRuleToFlagMap(NULL)
  86.     , m_ulPriorPacketContentBeginTime(0)
  87. {
  88.     if (m_pAllocator)
  89.     {
  90. m_pAllocator->AddRef();
  91.     }
  92. }
  93. MP4TPayloadFormat::~MP4TPayloadFormat()
  94. {
  95.     FlushPackets(FLUSH_ALL_PACKETS);
  96.     if (m_pRuleToFlagMap)
  97.     {
  98. if (m_pRuleToFlagMap->rule_to_flag_map)
  99. {
  100.     delete[] m_pRuleToFlagMap->rule_to_flag_map;
  101. }
  102. delete m_pRuleToFlagMap;
  103. m_pRuleToFlagMap = NULL;
  104.     }
  105.     HX_VECTOR_DELETE(m_pTextHeader);
  106.     if (m_pAllocator)
  107.     {
  108.         m_pAllocator->Release();
  109.         m_pAllocator = NULL;
  110.     }
  111.     HX_RELEASE(m_pClassFactory);
  112.     HX_RELEASE(m_pStreamHeader);
  113. }
  114. // *** IUnknown methods ***
  115. /////////////////////////////////////////////////////////////////////////
  116. //  Method:
  117. // IUnknown::QueryInterface
  118. //  Purpose:
  119. // Implement this to export the interfaces supported by your
  120. // object.
  121. //
  122. STDMETHODIMP
  123. MP4TPayloadFormat::QueryInterface(REFIID riid, void** ppvObj)
  124. {
  125.     QInterfaceList qiList[] =
  126.     {
  127. { GET_IIDHANDLE(IID_IUnknown), this },
  128. { GET_IIDHANDLE(IID_IHXPayloadFormatObject), (IHXPayloadFormatObject*) this },
  129.     };
  130.     return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  131. }
  132. /////////////////////////////////////////////////////////////////////////
  133. //  Method:
  134. // IUnknown::AddRef
  135. //  Purpose:
  136. // Everyone usually implements this the same... feel free to use
  137. // this implementation.
  138. //
  139. STDMETHODIMP_(ULONG32)
  140. MP4TPayloadFormat::AddRef()
  141. {
  142.     return InterlockedIncrement(&m_lRefCount);
  143. }
  144. /////////////////////////////////////////////////////////////////////////
  145. //  Method:
  146. // IUnknown::Release
  147. //  Purpose:
  148. // Everyone usually implements this the same... feel free to use
  149. // this implementation.
  150. //
  151. STDMETHODIMP_(ULONG32)
  152. MP4TPayloadFormat::Release()
  153. {
  154.     if (InterlockedDecrement(&m_lRefCount) > 0)
  155.     {
  156.         return m_lRefCount;
  157.     }
  158.     delete this;
  159.     return 0;
  160. }
  161. STDMETHODIMP
  162. MP4TPayloadFormat::Init(IUnknown* pContext,
  163. BOOL bPacketize)
  164. {
  165.     HX_RESULT retVal = HXR_OK;
  166.     HX_RELEASE(m_pClassFactory);
  167.     m_bPacketize = bPacketize;
  168.     if (SUCCEEDED(retVal))
  169.     {
  170. retVal = pContext->QueryInterface(IID_IHXCommonClassFactory,
  171.   (void**) &m_pClassFactory);
  172.     }
  173.     return retVal;
  174. }
  175. STDMETHODIMP
  176. MP4TPayloadFormat::Reset()
  177. {
  178.     // Release all input packets we have stored
  179.     FlushPackets(FLUSH_ALL_PACKETS);
  180.     m_bFlushed = FALSE;
  181.     m_bFirstPacket = TRUE;
  182.     m_bUsesRTPPackets = FALSE;
  183.     m_bRTPPacketTested = FALSE;
  184.     m_TSConverter.Reset();
  185.     return HXR_OK;
  186. }
  187. STDMETHODIMP
  188. MP4TPayloadFormat::SetStreamHeader(IHXValues* pHeader)
  189. {
  190.     HX_RESULT retVal = HXR_OK;
  191.     HX_ASSERT(pHeader);
  192.     HX_RELEASE(m_pStreamHeader);
  193.     m_pStreamHeader = pHeader;
  194.     if (m_pStreamHeader)
  195.     {
  196. m_pStreamHeader->AddRef();
  197.     }
  198.     // /We need to add an ASM rulebook with n rules, one for each sample
  199.     // description.  Note: in future, we may have multiple rules that map to
  200.     // a particular sample description, so we use a RuleToFlagMap to
  201.     // make sure the renderer knows which maps to which:
  202.     IHXBuffer* pASMRuleBook = NULL;
  203.     if (!m_pClassFactory  ||  !m_pTrackInfoMgr)
  204.     {
  205. retVal = HXR_UNEXPECTED;
  206.     }
  207.     else
  208.     {
  209. // /3GPP Timed Text renderer needs width, height, and matrix (for
  210. // origin offset),
  211. HX_ASSERT(m_pTrackInfoMgr->GetTrackWidth());
  212. if (m_pTrackInfoMgr->GetTrackWidth())
  213. {
  214.     m_pStreamHeader->SetPropertyULONG32("3GPPTextTrackWidth",
  215.     m_pTrackInfoMgr->GetTrackWidth());
  216. }
  217. HX_ASSERT(m_pTrackInfoMgr->GetTrackHeight());
  218. if (m_pTrackInfoMgr->GetTrackHeight())
  219. {
  220.     m_pStreamHeader->SetPropertyULONG32("3GPPTextTrackHeight",
  221.     m_pTrackInfoMgr->GetTrackHeight());
  222. }
  223. if (m_pTrackInfoMgr->GetTrackTransformX())
  224. {
  225.     m_pStreamHeader->SetPropertyULONG32("3GPPTextTrackTransformX",
  226.     m_pTrackInfoMgr->GetTrackTransformX());
  227. }
  228. if (m_pTrackInfoMgr->GetTrackTransformY())
  229. {
  230.     m_pStreamHeader->SetPropertyULONG32("3GPPTextTrackTransformY",
  231.     m_pTrackInfoMgr->GetTrackTransformY());
  232. }
  233. retVal = m_pClassFactory->CreateInstance(CLSID_IHXBuffer,
  234.        (void**) &pASMRuleBook);
  235. // /XXXEH- should the rule(s) contain "priority=10" as well?:
  236. char* pszNewRuleStr = "TimestampDelivery=TRUE;";
  237. UINT32 ulNewRuleStrLen = (UINT32)strlen(pszNewRuleStr);
  238. UINT32 ulNumEntries = m_pTrackInfoMgr->GetNumSamplesInOpaqueData();
  239. char* pRuleBook = new char[(ulNumEntries * ulNewRuleStrLen) + 1];
  240. if (pRuleBook)
  241. {
  242.     char* pTmp = pRuleBook;
  243.     for (UINT32 ulIi = 0; ulIi<ulNumEntries;
  244.     ulIi++, pTmp += ulNewRuleStrLen)
  245.     {
  246. memcpy(pTmp, pszNewRuleStr, ulNewRuleStrLen); /* Flawfinder: ignore */
  247.     }
  248.     *pTmp = '';
  249. }
  250. else
  251. {
  252.     retVal = HXR_OUTOFMEMORY;
  253. }
  254. // /Next, build the RuleToFlagMap so the renderer can map each
  255. // text sample (one per packet) to its sample description (array of
  256. // which is in the stream header's "OpaqueData" property):
  257. IHXBuffer* p3GPPTTRuleToFlagMapBuffer = NULL;
  258. if (SUCCEEDED(retVal)  &&  HXR_OK ==
  259. m_pClassFactory->CreateInstance(CLSID_IHXBuffer,
  260. (void**)&p3GPPTTRuleToFlagMapBuffer))
  261. {
  262.     m_pRuleToFlagMap = new RuleToFlagMap;
  263.     m_pRuleToFlagMap->num_rules = (UINT16)ulNumEntries;
  264.     m_pRuleToFlagMap->rule_to_flag_map =
  265.     new UINT16[m_pRuleToFlagMap->num_rules];
  266.     // /Note: if more rules get added, above, this will need redoing:
  267.     for (UINT16 uiI = 0; uiI<m_pRuleToFlagMap->num_rules; uiI++)
  268.     {
  269. m_pRuleToFlagMap->rule_to_flag_map[uiI] = uiI;
  270.     }
  271.     p3GPPTTRuleToFlagMapBuffer->SetSize(sizeof(UINT16) +
  272.     (sizeof(UINT16) * m_pRuleToFlagMap->num_rules));
  273.     UINT32 ulSize;
  274.     // /Put it into network-order (Big-endian):
  275.     m_pRuleToFlagMap->pack(
  276.     p3GPPTTRuleToFlagMapBuffer->GetBuffer(), ulSize);
  277.     HX_ASSERT(ulSize == p3GPPTTRuleToFlagMapBuffer->GetSize());
  278.     m_pStreamHeader->SetPropertyBuffer(HX_3GPPTT_RULE_TO_FLAG_MAP_PROPERTY,
  279.     p3GPPTTRuleToFlagMapBuffer);
  280.     HX_RELEASE(p3GPPTTRuleToFlagMapBuffer);
  281. }
  282. if (SUCCEEDED(retVal))
  283. {
  284.     retVal = pASMRuleBook->Set((UCHAR*) pszNewRuleStr,
  285.     strlen(pszNewRuleStr) + 1);
  286. }
  287. if (SUCCEEDED(retVal))
  288. {
  289.     m_pStreamHeader->SetPropertyCString("ASMRuleBook", pASMRuleBook);
  290. }
  291.     }
  292.     HX_RELEASE(pASMRuleBook);
  293.     if (m_pStreamHeader)
  294.     {
  295. m_pStreamHeader->AddRef();
  296.     }
  297.     return retVal;
  298. }
  299. STDMETHODIMP
  300. MP4TPayloadFormat::GetStreamHeader(REF(IHXValues*) pHeader)
  301. {
  302.     HX_RESULT retVal = HXR_FAIL;
  303.     HX_ASSERT(m_pStreamHeader);
  304.     if (m_pStreamHeader)
  305.     {
  306. retVal = HXR_OK;
  307. pHeader = m_pStreamHeader;
  308. pHeader->AddRef();
  309.     }
  310.     return retVal;
  311. }
  312. STDMETHODIMP
  313. MP4TPayloadFormat::SetPacket(IHXPacket* pOrigPacket)
  314. {
  315.     HX_RESULT retVal;
  316.     HX_ASSERT(pOrigPacket);
  317.     IHXBuffer* pBuffer = pOrigPacket->GetBuffer();
  318.     if (!pBuffer  ||  !m_pTrackInfoMgr  ||  !m_pTrack)
  319.     {
  320. HX_ASSERT(pBuffer);
  321. HX_ASSERT(m_pTrackInfoMgr);
  322. HX_ASSERT(m_pTrack);
  323. retVal = HXR_UNEXPECTED;
  324.     }
  325.     else
  326.     {
  327. if (!m_bRTPPacketTested)
  328. {
  329.     IHXRTPPacket* pRTPPacket = NULL;
  330.     m_bUsesRTPPackets = (pOrigPacket->QueryInterface(
  331.     IID_IHXRTPPacket,
  332.     (void**) &pRTPPacket)
  333. == HXR_OK);
  334.     m_bRTPPacketTested = TRUE;
  335.     HX_RELEASE(pRTPPacket);
  336.     if (!m_bUsesRTPPackets)
  337.             {
  338. m_ulSamplesPerSecond = _3GPPT_DEFAULT_SAMPLES_PER_SEC; // RDT time stamp
  339.             }
  340.     HX_ASSERT(m_ulSamplesPerSecond != 0);
  341.     m_TSConverter.SetBase(m_ulSamplesPerSecond,
  342.   m_ulSamplesPerSecond);
  343. }
  344. // /Now, set the ASM rule # to map to the sample desc index:
  345. // / For 3GPP Text tracks, we'll use the ASM rule number to
  346. // map to the sample description index for the renderer's use:
  347. UINT32 ulSamplDescIndx = m_pTrack->GetLastSampleDescIdx();
  348. // Search through m_pRuleToFlagMap to find one whose flag
  349. // matches this sampleDescr index:
  350. // /First, see if it's a 1-1 mapping to save time in most cases:
  351. UINT16 uiASMRuleNum = 0;
  352. if (m_pRuleToFlagMap->rule_to_flag_map[ulSamplDescIndx] ==
  353. ulSamplDescIndx)
  354. {
  355.     uiASMRuleNum = (UINT16)ulSamplDescIndx;
  356.         }
  357. else
  358. {
  359.     for (UINT16 uii=0; uii < m_pRuleToFlagMap->num_rules; uii++)
  360.             {
  361. if (m_pRuleToFlagMap->rule_to_flag_map[uii] == ulSamplDescIndx)
  362.                 {
  363.     uiASMRuleNum = uii;
  364.     break; // /Found it
  365.                 }
  366.             }
  367.         }
  368. #if defined(HELIX_FEATURE_3GPPTT_STREAMING)
  369. UINT32 ulTimeStamp = m_ulPriorPacketContentBeginTime;
  370. #else
  371.         // /Just make every packet a time-0 packet.  This will have to be
  372.         // revisited as soon as we handle post-Rel5 version of 3GPP-TT.
  373.         // Rel5 specifies that all packets should be delivered up front:
  374.         // (Helps fix Helix Issue #667: allows for seeking without
  375.         // packet-offset problems, and Negates Helix issue #675: allows
  376.         // for "streaming" without packet-offset problems) :
  377.         UINT32 ulTimeStamp = 0; 
  378. #endif // /XXXEH_TESTING_FIXING_SEEKING_AND_STREAMING
  379.         UINT32 ulRTPTime = pOrigPacket->GetTime();
  380. UINT16 uiStream = pOrigPacket->GetStreamNumber();
  381. UINT16 uiASMFlags = pOrigPacket->GetASMRuleNumber();
  382.         if (!m_bUsesRTPPackets)
  383.         {
  384.             retVal = pOrigPacket->Set(pBuffer, ulTimeStamp, uiStream,
  385.                     uiASMFlags, uiASMRuleNum);
  386.         }
  387.         else
  388.         {
  389.             // /Set the time stamp to the prior packet's time so it gets
  390.             // to the renderer in time to set the prior packet's end time,
  391.             // then set the RTP time to the begin time of the contents:
  392.             retVal = ((IHXRTPPacket*) pOrigPacket) ->SetRTP(
  393.                     pBuffer,
  394.                     ulTimeStamp,
  395.                     ulRTPTime,
  396.                     uiStream,
  397.                     uiASMFlags,
  398.                     uiASMRuleNum);
  399.         }
  400.         m_ulPriorPacketContentBeginTime = ulRTPTime; // /Save for next pkt
  401. // Add this packet to our list of input packets
  402. pOrigPacket->AddRef();
  403. m_InputPackets.AddTail(pOrigPacket);
  404.     }
  405.     return retVal;
  406. }
  407. STDMETHODIMP
  408. MP4TPayloadFormat::GetPacket(REF(IHXPacket*) pOutPacket)
  409. {
  410.     HX_RESULT retVal = HXR_OK;
  411.     retVal = GetPacketizerPacket(pOutPacket);
  412.     return retVal;
  413. }
  414. HX_RESULT
  415. MP4TPayloadFormat::GetPacketizerPacket(IHXPacket* &pOutPacket)
  416. {
  417.     HX_RESULT retVal = HXR_INCOMPLETE;
  418.     if (!m_InputPackets.IsEmpty())
  419.     {
  420. pOutPacket = (IHXPacket*) m_InputPackets.RemoveHead();
  421. retVal = HXR_OK;
  422.     }
  423.     else if (m_bFlushed)
  424.     {
  425. retVal = HXR_STREAM_DONE;
  426.     }
  427.     return retVal;
  428. }
  429. void
  430. MP4TPayloadFormat::FlushPackets(ULONG32 ulCount)
  431. {
  432.     IHXPacket* pDeadPacket;
  433.     while ((ulCount > 0) && (!m_InputPackets.IsEmpty()))
  434.     {
  435. pDeadPacket = (IHXPacket*) m_InputPackets.RemoveHead();
  436. HX_RELEASE(pDeadPacket);
  437. if (ulCount != FLUSH_ALL_PACKETS)
  438. {
  439.     ulCount--;
  440. }
  441.     }
  442. }
  443. STDMETHODIMP
  444. MP4TPayloadFormat::Flush()
  445. {
  446.     m_bFlushed = TRUE;
  447.     return HXR_OK;
  448. }
  449. ULONG32
  450. MP4TPayloadFormat::GetPacketTime(IHXPacket* pPacket)
  451. {
  452.     ULONG32 ulTime;
  453.     HX_ASSERT(pPacket);
  454.     if (m_bUsesRTPPackets && (m_ulSamplesPerSecond != 0))
  455.     {
  456. ulTime = ((IHXRTPPacket*) pPacket)->GetRTPTime();
  457. ulTime = m_TSConverter.Convert(ulTime);
  458.     }
  459.     else
  460.     {
  461. ulTime = pPacket->GetTime();
  462.     }
  463.     return ulTime;
  464. }