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

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 _IGNORE_MP4_AUDIO
  39. #define TRACK_SDP_CHUNK_SIZE 512
  40. /****************************************************************************
  41.  *  Includes
  42.  */
  43. #include "qtatmmgs.h"
  44. #include "qttrkmgr.h"
  45. #include "mp4desc.h"
  46. #include "hxstrutl.h"
  47. #include "rtptypes.h"
  48. #include "rtsputil.h"
  49. #ifndef QTCONFIG_SPEED_OVER_SIZE
  50. #include "qtatmmgs_inline.h"
  51. #endif // QTCONFIG_SPEED_OVER_SIZE
  52. /****************************************************************************
  53.  *  Track Edit Manager
  54.  */
  55. #define QT_MAX_MOVIE_DURATION 0xFFFFFFFF
  56. /****************************************************************************
  57.  *  Constructor/Destructor
  58.  */
  59. CQT_TrackEdit_Manager::CQT_TrackEdit_Manager(void)
  60.     : m_pEditListAtom(NULL)
  61.     , m_ulMovieTimeScale(1)
  62.     , m_ulMediaTimeScale(1)
  63.     , m_ulNumEdits(0)
  64.     , m_ulCurrentEditIdx(0)
  65.     , m_ulCurrentEditTime(0)
  66.     , m_ulCurrentInEditTime(0)
  67.     , m_ulCurrentEditDuration(QT_MAX_MOVIE_DURATION)
  68.     , m_ulCurrentMediaStartTime(0)
  69. {
  70.     ;
  71. }
  72. CQT_TrackEdit_Manager::~CQT_TrackEdit_Manager(void)
  73. {
  74.     HX_RELEASE(m_pEditListAtom);
  75. }
  76. /****************************************************************************
  77.  *  Main Interface
  78.  */
  79. /****************************************************************************
  80.  *  Init
  81.  */
  82. HX_RESULT CQT_TrackEdit_Manager::Init(CQTAtom* pAtom,
  83.       ULONG32 ulMovieTimeScale,
  84.       ULONG32 ulMediaTimeScale)
  85. {
  86.     HX_RESULT retVal = HXR_OK;
  87.     HX_ASSERT(ulMovieTimeScale);
  88.     HX_ASSERT(ulMediaTimeScale);
  89.     
  90.     m_ulMovieTimeScale = ulMovieTimeScale;
  91.     m_ulMediaTimeScale = ulMediaTimeScale;
  92.     m_ulNumEdits = 0;
  93.     
  94.     HX_RELEASE(m_pEditListAtom);
  95.     if (pAtom)
  96.     {
  97. if (pAtom->GetType() == QT_elst)
  98. {
  99.     m_pEditListAtom = (CQT_elst_Atom*) pAtom;
  100. }
  101. else
  102. {
  103.     m_pEditListAtom = (CQT_elst_Atom*) pAtom->FindPresentChild(QT_elst);
  104. }
  105. if (m_pEditListAtom)
  106. {
  107.     m_pEditListAtom->AddRef();
  108.     m_ulNumEdits = m_pEditListAtom->Get_NumEntries();
  109. }
  110.     }
  111.     if (!EstablishByTime(0))
  112.     {
  113. retVal = HXR_FAIL;
  114. // Reset State
  115. HX_RELEASE(m_pEditListAtom);
  116. m_ulNumEdits = 0;
  117. EstablishByTime(0);
  118.     }
  119.     return retVal;
  120. }
  121. /****************************************************************************
  122.  *  EstablishByMovieTime
  123.  */
  124. BOOL CQT_TrackEdit_Manager::EstablishByTime(ULONG32 ulTime)
  125. {
  126.     m_ulCurrentEditIdx = 0;
  127.     m_ulCurrentEditTime = 0;
  128.     m_ulCurrentInEditTime = (ULONG32) (ulTime / 1000.0 *
  129.        m_ulMediaTimeScale +
  130.        0.5);
  131.     if (m_ulNumEdits > 0)
  132.     {
  133. m_ulCurrentEditDuration = MovieToMediaUnits(
  134.     m_pEditListAtom->Get_TrackDuration(0));
  135. m_ulCurrentMediaStartTime = m_pEditListAtom->Get_MediaTime(0);
  136. return SequenceToEdit();
  137.     }
  138.     else
  139.     {
  140. m_ulCurrentEditDuration = QT_MAX_MOVIE_DURATION;
  141. m_ulCurrentMediaStartTime = 0;
  142.     }
  143.     return TRUE;
  144. }
  145. /****************************************************************************
  146.  *  Private Methods
  147.  */
  148. /****************************************************************************
  149.  *  SequenceToEdit
  150.  */
  151. BOOL CQT_TrackEdit_Manager::SequenceToEdit(void)
  152. {
  153.     while ((m_ulCurrentMediaStartTime == QT_EMPTY_EDIT) ||
  154.    (m_ulCurrentInEditTime >= m_ulCurrentEditDuration))
  155.     {
  156. m_ulCurrentEditIdx++;
  157. if (m_ulCurrentEditIdx < m_ulNumEdits)
  158. {
  159.     if (m_ulCurrentMediaStartTime != QT_EMPTY_EDIT)
  160.     {
  161. m_ulCurrentInEditTime -= m_ulCurrentEditDuration;
  162.     }
  163.     m_ulCurrentEditTime += m_ulCurrentEditDuration;
  164.     m_ulCurrentEditDuration = MovieToMediaUnits(
  165. m_pEditListAtom->Get_TrackDuration(
  166.     m_ulCurrentEditIdx));
  167.     m_ulCurrentMediaStartTime = m_pEditListAtom->Get_MediaTime(
  168.     m_ulCurrentEditIdx);
  169. }
  170. else
  171. {
  172.     m_ulCurrentEditIdx--;
  173.     return FALSE;
  174. }
  175.     }
  176.     return TRUE;
  177. }
  178. /****************************************************************************
  179.  *  Sample To Chunk Manager
  180.  */
  181. #define QT_MAX_SAMPLES_PER_CHUNK 0xFFFFFFFF
  182. #define QT_NULL_CHUNK_NUM 0
  183. /****************************************************************************
  184.  *  Constructor/Destructor
  185.  */
  186. CQT_SampleToChunk_Manager::CQT_SampleToChunk_Manager(void)
  187.     : m_ulNumEntries(0)
  188.     , m_pSampleToChunkAtom(NULL)
  189.     , m_ulSampleInChunkNum(0)
  190.     , m_ulCurrentChunk(0)
  191.     , m_ulNextEntryChunk(QT_NULL_CHUNK_NUM)
  192.     , m_ulCurrentEntryIdx(0)
  193.     , m_ulSamplesPerChunk(QT_MAX_SAMPLES_PER_CHUNK)
  194.     , m_ulSampleNumber(0)
  195.     , m_ulSampleDescIdx(QT_BAD_IDX)
  196. #ifdef _STCO_ZERO_BASED_IQ
  197.     , m_ulChunkNumOffset(0)
  198. #endif // _STCO_ZERO_BASED_IQ
  199. {
  200.     ;
  201. }
  202. CQT_SampleToChunk_Manager::~CQT_SampleToChunk_Manager()
  203. {
  204.     HX_RELEASE(m_pSampleToChunkAtom);
  205. }
  206. /****************************************************************************
  207.  *  Init
  208.  */
  209. HX_RESULT CQT_SampleToChunk_Manager::Init(CQTAtom* pAtom)
  210. {
  211.     HX_RESULT retVal = HXR_OK;
  212.     HX_RELEASE(m_pSampleToChunkAtom);
  213.     m_ulNumEntries = 0;
  214.     m_ulSampleNumber = 0;
  215.     if (pAtom)
  216.     {
  217. if (pAtom->GetType() == QT_stsc)
  218. {
  219.     m_pSampleToChunkAtom = (CQT_stsc_Atom*) pAtom;
  220. }
  221. else
  222. {
  223.     m_pSampleToChunkAtom = (CQT_stsc_Atom*) pAtom->FindPresentChild(QT_stsc);
  224. }
  225. if (m_pSampleToChunkAtom)
  226. {
  227.     m_pSampleToChunkAtom->AddRef();
  228.     m_ulNumEntries = m_pSampleToChunkAtom->Get_NumEntries();
  229. }
  230.     }
  231.     if (m_ulNumEntries == 0)
  232.     {
  233. EstablishBySample(0);
  234. retVal = HXR_NO_DATA;
  235.     }
  236.     else
  237.     {
  238. m_ulSampleNumber = 2;  // Force full initialization
  239. retVal = EstablishBySample(1) ? HXR_OK : HXR_FAIL;
  240. #ifdef _STCO_ZERO_BASED_IQ
  241. m_ulChunkNumOffset = 0;
  242. if (retVal == HXR_OK)
  243. {
  244.     if ((m_ulCurrentChunk == 0) ||
  245. (m_ulSampleDescIdx == ((ULONG32) -1)))
  246.     {
  247. m_ulCurrentChunk = 1;
  248. m_ulNextEntryChunk++;
  249. m_ulSampleDescIdx++;
  250. m_ulChunkNumOffset = 1;
  251.     }
  252. }
  253. #endif // _STCO_ZERO_BASED_IQ
  254.     }
  255.     return retVal;
  256. }
  257. /****************************************************************************
  258.  *  EstablishBySample
  259.  */
  260. BOOL CQT_SampleToChunk_Manager::EstablishBySample(ULONG32 ulSampleNum)
  261. {
  262.     if (m_ulNumEntries > 0)
  263.     {
  264. HX_ASSERT(ulSampleNum);
  265. if (ulSampleNum >= m_ulSampleNumber)
  266. {
  267.     // Search Forward
  268.     m_ulSampleInChunkNum += (ulSampleNum - m_ulSampleNumber);
  269.     m_ulSampleNumber = ulSampleNum;
  270.     return SequenceToChunk();
  271. }
  272. else if (ulSampleNum > (m_ulSampleNumber >> 1))
  273. {
  274.     // Search in Reverse
  275.     m_ulSampleInChunkNum = m_ulSamplesPerChunk -
  276.    m_ulSampleInChunkNum +
  277.    m_ulSampleNumber -
  278.    ulSampleNum +
  279.    1;
  280.     m_ulSampleNumber = ulSampleNum;
  281.     if (SequenceReverseToChunk())
  282.     {
  283. m_ulSampleInChunkNum = m_ulSamplesPerChunk -
  284.        m_ulSampleInChunkNum +
  285.        1;
  286. return TRUE;
  287.     }
  288. }
  289. else
  290. {
  291.     // Search Forward from the beginning
  292.     m_ulSampleInChunkNum = ulSampleNum;
  293.     m_ulCurrentEntryIdx = 0;
  294.     m_ulCurrentChunk = m_pSampleToChunkAtom->Get_FirstChunk(0)
  295. #ifdef _STCO_ZERO_BASED_IQ
  296.        + m_ulChunkNumOffset
  297. #endif // _STCO_ZERO_BASED_IQ
  298.        ;
  299.     m_ulSamplesPerChunk = m_pSampleToChunkAtom->Get_SamplesPerChunk(0);
  300.     m_ulSampleDescIdx = m_pSampleToChunkAtom->Get_SampleDescID(0) - 1
  301. #ifdef _STCO_ZERO_BASED_IQ
  302.         + m_ulChunkNumOffset
  303. #endif // _STCO_ZERO_BASED_IQ
  304.        ;
  305.     if (m_ulNumEntries > 1)
  306.     {
  307. m_ulNextEntryChunk = m_pSampleToChunkAtom->
  308.     Get_FirstChunk(1)
  309. #ifdef _STCO_ZERO_BASED_IQ
  310.     + m_ulChunkNumOffset
  311. #endif // _STCO_ZERO_BASED_IQ
  312.     ;
  313.     }
  314.     else
  315.     {
  316. // No more chunk entries
  317. m_ulNextEntryChunk = QT_NULL_CHUNK_NUM;
  318.     }
  319.     m_ulSampleNumber = ulSampleNum;
  320.     return SequenceToChunk();
  321. }
  322.     }
  323.     else
  324.     {
  325. m_ulSampleNumber = 0;
  326. m_ulSampleInChunkNum = 0;
  327. m_ulCurrentChunk = 0;
  328. m_ulSamplesPerChunk = QT_MAX_SAMPLES_PER_CHUNK;
  329. m_ulSampleDescIdx = QT_BAD_IDX;
  330. #ifdef _STCO_ZERO_BASED_IQ
  331. m_ulChunkNumOffset = 0;
  332. #endif // _STCO_ZERO_BASED_IQ
  333.     }
  334.     return FALSE;
  335. }
  336. /****************************************************************************
  337.  *  Private Methods
  338.  */
  339. /****************************************************************************
  340.  *  SequenceToChunk
  341.  */
  342. #ifdef STCMGR_USE_MODULUS_SEQUENCING
  343. // This sequencing algorithm has better efficiency (than non-modulus 
  344. // sequencing) on files containing many chunks per table entry and/or those 
  345. // whose progression through the table is irratic (has skipps).
  346. BOOL CQT_SampleToChunk_Manager::SequenceToChunk(void)
  347. {
  348.     ULONG32 ulTargetChunk;
  349.     BOOL bEntryIdxChanged;
  350.     if (m_ulSampleInChunkNum > m_ulSamplesPerChunk)
  351.     {
  352. bEntryIdxChanged = FALSE;
  353. do
  354. {
  355.     if (m_ulSamplesPerChunk == 0)
  356.     {
  357. ulTargetChunk = m_ulCurrentChunk + 1;
  358.     }
  359.     else
  360.     {
  361. ulTargetChunk = m_ulCurrentChunk +
  362.      (m_ulSampleInChunkNum - 1) /
  363. m_ulSamplesPerChunk;
  364.     }
  365.     if ((ulTargetChunk >= m_ulNextEntryChunk) &&
  366. (m_ulNextEntryChunk != QT_NULL_CHUNK_NUM))
  367.     {
  368. m_ulSampleInChunkNum -= (m_ulNextEntryChunk -
  369.  m_ulCurrentChunk) *
  370. m_ulSamplesPerChunk;
  371. m_ulCurrentChunk = m_ulNextEntryChunk;
  372. m_ulCurrentEntryIdx++;
  373. bEntryIdxChanged = TRUE;
  374. m_ulSamplesPerChunk = m_pSampleToChunkAtom->
  375.     Get_SamplesPerChunk(m_ulCurrentEntryIdx);
  376. if ((m_ulCurrentEntryIdx + 1) < m_ulNumEntries)
  377. {
  378.     m_ulNextEntryChunk = m_pSampleToChunkAtom->
  379. Get_FirstChunk(m_ulCurrentEntryIdx + 1);
  380. }
  381. else
  382. {
  383.     // No more chunk entries
  384.     m_ulNextEntryChunk = QT_NULL_CHUNK_NUM;
  385. }
  386.     }
  387.     else
  388.     {
  389. m_ulCurrentChunk = ulTargetChunk;
  390. if (m_ulSamplesPerChunk != 0)
  391. {  
  392.     m_ulSampleInChunkNum = (m_ulSampleInChunkNum - 1) %
  393.     m_ulSamplesPerChunk +
  394.     1;
  395. }
  396. else
  397. {
  398.     // encountered empty chunk at the end of table
  399.     return FALSE;
  400. }
  401.     }
  402. } while (m_ulSampleInChunkNum > m_ulSamplesPerChunk);
  403. if (bEntryIdxChanged)
  404. {
  405.     m_ulSampleDescIdx = m_pSampleToChunkAtom->
  406. Get_SampleDescID(m_ulCurrentEntryIdx) - 1
  407. #ifdef _STCO_ZERO_BASED_IQ
  408. + m_ulChunkNumOffset
  409. #endif // _STCO_ZERO_BASED_IQ
  410.        ;
  411. }
  412.     }
  413.     return TRUE;
  414. }
  415. #else // STCMGR_USE_MODULUS_SEQUENCING
  416. // This sequencing algorithm is more efficient for files
  417. // containing fewer chunks per table entry and/or those
  418. // whose progression through the chunks involves fewer
  419. // skipps.
  420. BOOL CQT_SampleToChunk_Manager::SequenceToChunk(void)
  421. {
  422.     BOOL bEntryIdxChanged;
  423.     if (m_ulSampleInChunkNum > m_ulSamplesPerChunk)
  424.     {
  425. bEntryIdxChanged = FALSE;
  426. do
  427. {
  428.     m_ulSampleInChunkNum = m_ulSampleInChunkNum - m_ulSamplesPerChunk;
  429.     m_ulCurrentChunk++;
  430.     
  431.     if (m_ulCurrentChunk == m_ulNextEntryChunk)
  432.     {
  433. m_ulCurrentEntryIdx++;
  434. bEntryIdxChanged = TRUE;
  435. m_ulSamplesPerChunk = m_pSampleToChunkAtom->
  436.     Get_SamplesPerChunk(m_ulCurrentEntryIdx);
  437. if ((m_ulCurrentEntryIdx + 1) < m_ulNumEntries)
  438. {
  439.     m_ulNextEntryChunk = m_pSampleToChunkAtom->
  440. Get_FirstChunk(m_ulCurrentEntryIdx + 1)
  441. #ifdef _STCO_ZERO_BASED_IQ
  442. + m_ulChunkNumOffset
  443. #endif // _STCO_ZERO_BASED_IQ
  444. ;
  445. }
  446. else
  447. {
  448.     // No more chunk entries
  449.     m_ulNextEntryChunk = QT_NULL_CHUNK_NUM;
  450. }
  451.     }
  452.     else if ((m_ulSamplesPerChunk == 0) && 
  453. (m_ulNextEntryChunk == QT_NULL_CHUNK_NUM))
  454.     {
  455. return FALSE;
  456.     }
  457. } while (m_ulSampleInChunkNum > m_ulSamplesPerChunk);
  458. if (bEntryIdxChanged)
  459. {
  460.     m_ulSampleDescIdx = m_pSampleToChunkAtom->
  461. Get_SampleDescID(m_ulCurrentEntryIdx) - 1
  462. #ifdef _STCO_ZERO_BASED_IQ
  463. + m_ulChunkNumOffset
  464. #endif // _STCO_ZERO_BASED_IQ
  465. ;
  466. }
  467.     }
  468.     return TRUE;
  469. }
  470. #endif // STCMGR_USE_MODULUS_SEQUENCING
  471. /****************************************************************************
  472.  *  SequenceReverseToChunk
  473.  */
  474. BOOL CQT_SampleToChunk_Manager::SequenceReverseToChunk(void)
  475. {
  476.     ULONG32 ulEntryFirstChunk;
  477.     BOOL bEntryIdxChanged;
  478.     if (m_ulSampleInChunkNum > m_ulSamplesPerChunk)
  479.     {
  480. bEntryIdxChanged = FALSE;
  481. ulEntryFirstChunk = m_pSampleToChunkAtom->
  482.     Get_FirstChunk(m_ulCurrentEntryIdx);
  483. do
  484. {
  485.     m_ulSampleInChunkNum = m_ulSampleInChunkNum - m_ulSamplesPerChunk;
  486.     m_ulCurrentChunk--;
  487.     
  488.     if (m_ulCurrentChunk < ulEntryFirstChunk)
  489.     {
  490. if (m_ulCurrentEntryIdx == 0)
  491. {
  492.     return FALSE;
  493. }
  494. m_ulCurrentEntryIdx--;
  495. bEntryIdxChanged = TRUE;
  496. m_ulSamplesPerChunk = m_pSampleToChunkAtom->
  497.     Get_SamplesPerChunk(m_ulCurrentEntryIdx);
  498. ulEntryFirstChunk = m_pSampleToChunkAtom->
  499.     Get_FirstChunk(m_ulCurrentEntryIdx);
  500.     }
  501. } while (m_ulSampleInChunkNum > m_ulSamplesPerChunk);
  502. if (bEntryIdxChanged)
  503. {
  504.     m_ulSampleDescIdx = m_pSampleToChunkAtom->
  505. Get_SampleDescID(m_ulCurrentEntryIdx) - 1
  506. #ifdef _STCO_ZERO_BASED_IQ
  507. + m_ulChunkNumOffset
  508. #endif // _STCO_ZERO_BASED_IQ
  509. ;
  510. }
  511. if ((m_ulCurrentEntryIdx + 1) < m_ulNumEntries)
  512. {
  513.     m_ulNextEntryChunk = m_pSampleToChunkAtom->
  514. Get_FirstChunk(m_ulCurrentEntryIdx + 1)
  515. #ifdef _STCO_ZERO_BASED_IQ
  516. + m_ulChunkNumOffset
  517. #endif // _STCO_ZERO_BASED_IQ
  518. ;
  519. }
  520. else
  521. {
  522.     // No more chunk entries
  523.     m_ulNextEntryChunk = QT_NULL_CHUNK_NUM;
  524. }
  525.     }
  526.     return TRUE;
  527. }
  528. #define INVALID_COMP_SAMPLE_NUM     0xFFFFFFFF
  529. /****************************************************************************
  530.  *  Time To Sample Manager
  531.  */
  532. /****************************************************************************
  533.  *  Constructor/Destructor
  534.  */
  535. CQT_TimeToSample_Manager::CQT_TimeToSample_Manager(void)
  536.     : m_pTimeToSampleAtom(NULL)
  537.     , m_pCompOffsetAtom(NULL)
  538.     , m_pSyncSampleAtom(NULL)
  539.     , m_ulNumEntries(0)
  540.     , m_ulCurrentEntryIdx(0)
  541.     , m_ulSampleNumber(0)
  542.     , m_ulSamplesLeftInEntry(0)
  543.     , m_ulSampleDuration(0)
  544.     , m_ulLastSyncTime(0)
  545.     , m_ulNumCompEntries(0)
  546.     , m_ulCurrentCompEntryIdx(0)
  547.     , m_ulCompSampleNumber(INVALID_COMP_SAMPLE_NUM)
  548.     , m_ulSamplesLeftInCompEntry(0)
  549.     , m_ulCompOffset(0)
  550.     , m_ulNumSyncEntries(0)
  551.     , m_ulCurrentSyncEntryIdx(0)
  552.     , m_ulSyncSampleNumber(0)
  553. #ifdef _STSS_ZERO_BASED_IQ
  554.     , m_ulKeyFrameNumOffset(0)
  555. #endif // _STSS_ZERO_BASED_IQ
  556. {
  557.     ;
  558. }
  559. CQT_TimeToSample_Manager::~CQT_TimeToSample_Manager()
  560. {
  561.     HX_RELEASE(m_pTimeToSampleAtom);
  562.     HX_RELEASE(m_pCompOffsetAtom);
  563.     HX_RELEASE(m_pSyncSampleAtom);
  564. }
  565. /****************************************************************************
  566.  *  Init
  567.  */
  568. HX_RESULT CQT_TimeToSample_Manager::Init(CQTAtom* pAtom)
  569. {
  570.     HX_RESULT retVal = HXR_OK;
  571.     HX_RELEASE(m_pTimeToSampleAtom);
  572.     HX_RELEASE(m_pCompOffsetAtom);
  573.     HX_RELEASE(m_pSyncSampleAtom);
  574.     
  575.     m_ulNumEntries = 0;
  576.     m_ulCompSampleNumber = INVALID_COMP_SAMPLE_NUM;
  577.     if (pAtom)
  578.     {
  579. if (pAtom->GetType() == QT_stts)
  580. {
  581.     m_pTimeToSampleAtom = (CQT_stts_Atom*) pAtom;
  582. }
  583. else
  584. {
  585.     m_pTimeToSampleAtom = (CQT_stts_Atom*) pAtom->
  586.     FindPresentChild(QT_stts);
  587.     m_pCompOffsetAtom = (CQT_ctts_Atom*) pAtom->
  588.     FindPresentChild(QT_ctts);
  589. }
  590. if (m_pTimeToSampleAtom)
  591. {
  592.     m_pTimeToSampleAtom->AddRef();
  593.     m_ulNumEntries = m_pTimeToSampleAtom->Get_NumEntries();
  594. }
  595. if (m_pCompOffsetAtom)
  596. {
  597.     m_pCompOffsetAtom->AddRef();
  598.     m_ulNumCompEntries = m_pCompOffsetAtom->Get_NumEntries();
  599. }
  600.     }
  601.     if (m_ulNumEntries > 0)
  602.     {
  603. if (pAtom != m_pTimeToSampleAtom)
  604. {
  605.     m_pSyncSampleAtom = (CQT_stss_Atom*) pAtom->
  606.     FindPresentChild(QT_stss);
  607.     if (m_pSyncSampleAtom)
  608.     {
  609. ULONG32 ulNumSyncEntries = 0;
  610. ulNumSyncEntries = m_pSyncSampleAtom->Get_NumEntries();
  611. #ifdef _STSS_ZERO_BASED_IQ
  612. if (ulNumSyncEntries > 0)
  613. {
  614.     ULONG32 ulKeyFrameSample;
  615.     ulKeyFrameSample = m_pSyncSampleAtom->
  616.     Get_SampleNum(0);
  617.     if (ulKeyFrameSample == 0)
  618.     {
  619. m_ulKeyFrameNumOffset = 1;
  620.     }
  621. }
  622. #endif // _STSS_ZERO_BASED_IQ
  623. #ifdef _STSS_TRACK_SYNC
  624. m_ulNumSyncEntries = ulNumSyncEntries;
  625. #endif // _STSS_TRACK_SYNC
  626. m_pSyncSampleAtom->AddRef();
  627.     }
  628. }
  629.     }
  630.     retVal = EstablishByMediaTime(0) ? HXR_OK : HXR_NO_DATA;
  631.     return retVal;
  632. }
  633. /****************************************************************************
  634.  *  EstablishAtKeyByMediaTime
  635.  */
  636. BOOL CQT_TimeToSample_Manager::EstablishAtKeyByMediaTime(ULONG32 ulMediaTime)
  637. {
  638.     ULONG32 ulSyncEntryIdx;
  639.     ULONG32 ulKeyFrameSample;
  640.     ULONG32 ulNumSyncEntries = 0;
  641.     BOOL bEstablished = FALSE;
  642.     if (EstablishByMediaTime(ulMediaTime))
  643.     {
  644. ulNumSyncEntries = m_ulNumSyncEntries;
  645. if ((ulNumSyncEntries == 0) && m_pSyncSampleAtom)
  646. {
  647.     ulNumSyncEntries = m_pSyncSampleAtom->Get_NumEntries();
  648. }
  649. bEstablished = (ulNumSyncEntries == 0);
  650. for (ulSyncEntryIdx = m_ulCurrentSyncEntryIdx; 
  651.      ulSyncEntryIdx < ulNumSyncEntries;
  652.      ulSyncEntryIdx++)
  653. {
  654.     ulKeyFrameSample = m_pSyncSampleAtom->
  655. Get_SampleNum(ulSyncEntryIdx) + m_ulKeyFrameNumOffset;
  656.     while (ulKeyFrameSample >= m_ulSampleNumber)
  657.     {
  658. if (ulKeyFrameSample == m_ulSampleNumber)
  659. {
  660.     // Key Sample lined up with the Sample
  661.     return TRUE;
  662. }
  663. // We'll try to line up the Sample with the key sample
  664. if (!AdvanceBySample())
  665. {
  666.     return FALSE;
  667. }
  668. // Keep track of how for beyond initally requested time
  669. // the key frame was found.
  670. m_ulLastSyncTime += m_ulSampleDuration;
  671.     }
  672. }
  673.     }
  674.     return bEstablished;
  675. }
  676. /****************************************************************************
  677.  *  EstablishByMediaTime
  678.  */
  679. BOOL CQT_TimeToSample_Manager::EstablishByMediaTime(ULONG32 ulMediaTime)
  680. {
  681.     BOOL bIsEstablished;
  682.     m_ulCurrentEntryIdx = 0;
  683.     m_ulLastSyncTime = 0;
  684.     m_ulCurrentSyncEntryIdx = 0;
  685.     
  686.     if (m_ulNumEntries > 0)
  687.     {
  688. m_ulSampleNumber = 0;
  689. m_ulSamplesLeftInEntry = m_pTimeToSampleAtom->Get_SampleCount(0);
  690. m_ulSampleDuration = m_pTimeToSampleAtom->Get_SampleDuration(0);
  691.     }
  692.     else
  693.     {
  694. m_ulSampleNumber = 0;
  695. m_ulSamplesLeftInEntry = 0;
  696. m_ulSampleDuration = 0;
  697.     }
  698.     if (m_ulNumSyncEntries > 0)
  699.     {
  700. m_ulSyncSampleNumber = m_pSyncSampleAtom->Get_SampleNum(0) +
  701.        m_ulKeyFrameNumOffset;
  702.     }
  703.     else
  704.     {
  705. m_ulSyncSampleNumber = 0;
  706.     }
  707.     bIsEstablished = EstablishCompBySample(0);
  708.     if (bIsEstablished)
  709.     {
  710. bIsEstablished = AdvanceBySample();
  711.     }
  712.     if (bIsEstablished)
  713.     {
  714. while (ulMediaTime > 0)
  715. {
  716.     if (ulMediaTime >= m_ulSampleDuration)
  717.     {
  718. ulMediaTime -= m_ulSampleDuration;
  719.     }
  720.     else
  721.     {
  722. m_ulLastSyncTime = m_ulSampleDuration - ulMediaTime;
  723. ulMediaTime = 0;
  724.     }
  725.     if (!AdvanceBySample())
  726.     {
  727. bIsEstablished = FALSE;
  728. break;
  729.     }
  730. }
  731.     }
  732.     return bIsEstablished;
  733. }
  734. /****************************************************************************
  735.  *  EstablishCompByOffset
  736.  */
  737. BOOL CQT_TimeToSample_Manager::EstablishCompBySample(ULONG32 ulSampleNum)
  738. {
  739.     BOOL bIsEstablished = TRUE;
  740.     if (m_ulNumCompEntries == 0)
  741.     {
  742. return bIsEstablished;
  743.     }
  744.     if (m_ulCompSampleNumber >= ulSampleNum)
  745.     {
  746. m_ulCompSampleNumber = 0;
  747. m_ulCurrentCompEntryIdx = 0;
  748. m_ulSamplesLeftInCompEntry = m_pCompOffsetAtom->Get_SampleCount(0);
  749. m_ulCompOffset = m_pCompOffsetAtom->Get_SampleOffset(0);
  750.     }
  751.     while (m_ulCompSampleNumber < ulSampleNum)
  752.     {
  753. if (!(bIsEstablished = AdvanceCompBySample()))
  754. {
  755.     break;
  756. }
  757.     }
  758.     return bIsEstablished;
  759. }
  760. /****************************************************************************
  761.  *  Sample Size Manager
  762.  */
  763. /****************************************************************************
  764.  *  Constructor/Destructor
  765.  */
  766. CQT_SampleSize_Manager::CQT_SampleSize_Manager(void)
  767.     : m_pSampleSizeAtom(NULL)
  768.     , m_ulGenericSize(0)
  769.     , m_ulNumEntries(0)
  770.     , m_ulSampleSize(0)
  771.     , m_ulChunkSize(0)
  772.     , m_ulChunkSampleOffset(0)
  773.     , m_ulChunkStartSampleNum(QT_BAD_IDX)
  774.     , m_ulSampleNum(QT_BAD_IDX)
  775. {
  776.     ;
  777. }
  778. CQT_SampleSize_Manager::~CQT_SampleSize_Manager()
  779. {
  780.     HX_RELEASE(m_pSampleSizeAtom);
  781. }
  782. /****************************************************************************
  783.  *  Init
  784.  */
  785. HX_RESULT CQT_SampleSize_Manager::Init(CQTAtom *pAtom)
  786. {
  787.     HX_RESULT retVal = HXR_OK;
  788.     HX_RELEASE(m_pSampleSizeAtom);
  789.     m_ulGenericSize = 0;
  790.     m_ulSampleSize = 0;
  791.     m_ulChunkSampleOffset = 0;
  792.     m_ulChunkSize = 0;
  793.     m_ulNumEntries = 0;
  794.     m_ulChunkStartSampleNum = QT_BAD_IDX;
  795.     m_ulSampleNum = QT_BAD_IDX;
  796.     if (pAtom)
  797.     {
  798. if (pAtom->GetType() == QT_stsz)
  799. {
  800.     m_pSampleSizeAtom = (CQT_stsz_Atom*) pAtom;
  801. }
  802. else
  803. {
  804.     m_pSampleSizeAtom = (CQT_stsz_Atom*) pAtom->FindPresentChild(QT_stsz);
  805. }
  806. if (m_pSampleSizeAtom)
  807. {
  808.     m_pSampleSizeAtom->AddRef();
  809.     m_ulGenericSize = m_pSampleSizeAtom->Get_SampleSize();
  810.     m_ulNumEntries = m_pSampleSizeAtom->Get_NumEntries();
  811. }
  812.     }
  813.     if (m_ulGenericSize == 0)
  814.     {
  815. if (m_ulNumEntries == 0)
  816. {
  817.     retVal = HXR_NO_DATA;
  818. }
  819.     }
  820.     else
  821.     {
  822. m_ulSampleSize = m_ulGenericSize;
  823. // All samples have the same size - do not need the table
  824. HX_RELEASE(m_pSampleSizeAtom);
  825. m_ulNumEntries = 0;
  826.     }
  827.     return retVal;
  828. }
  829. /****************************************************************************
  830.  *  EstablishBySample
  831.  */
  832. BOOL CQT_SampleSize_Manager::EstablishBySample(ULONG32 ulSampleNum, 
  833.        ULONG32 ulChunkSampleNum,
  834.        ULONG32 ulSamplesPerChunk)
  835. {
  836.     ULONG32 ulChunkStartSampleNum;
  837.     ULONG32 ulChunkEndSampleNum;
  838.     if ((ulChunkSampleNum > 0) &&
  839. (ulSampleNum >= ulChunkSampleNum))
  840.     {
  841. if (ulSamplesPerChunk < ulChunkSampleNum)
  842. {
  843.     ulSamplesPerChunk = ulChunkSampleNum;
  844. }
  845. if (m_ulGenericSize)
  846. {
  847.     m_ulChunkSampleOffset = (ulChunkSampleNum - 1) * m_ulGenericSize;
  848.     m_ulChunkSize = ulSamplesPerChunk * m_ulGenericSize;
  849.     return TRUE;
  850. }
  851. ulChunkStartSampleNum = ulSampleNum - ulChunkSampleNum;
  852. ulChunkEndSampleNum = ulChunkStartSampleNum + ulSamplesPerChunk;
  853. if (ulChunkEndSampleNum
  854.     <= m_ulNumEntries)
  855. {
  856.     // Convert to 0 based index for efficiency
  857.     ulSampleNum--;
  858.     
  859.     if (m_ulChunkStartSampleNum == ulChunkStartSampleNum)
  860.     {
  861. if (m_ulSampleNum == ulSampleNum)   // m_ulSampleNum is 1 based
  862. {
  863.     m_ulChunkSampleOffset += m_ulSampleSize;
  864.     m_ulSampleSize = m_pSampleSizeAtom->Get_SampleSize(m_ulSampleNum++);
  865.     return TRUE;
  866. }
  867. else if (m_ulSampleNum == (ulSampleNum + 1))
  868. {
  869.     // Already computed
  870.     return TRUE;
  871. }
  872.     }
  873.     // Convert to 0 based index for efficiency
  874.     ulChunkSampleNum--;
  875.     
  876.     m_ulSampleSize = m_pSampleSizeAtom->Get_SampleSize(ulSampleNum);
  877.     m_ulChunkStartSampleNum = ulChunkStartSampleNum;
  878.     m_ulSampleNum = ulSampleNum + 1;
  879.     
  880.     for (m_ulChunkSampleOffset = 0;
  881.  ulChunkStartSampleNum < ulSampleNum;
  882.  ulChunkStartSampleNum++)
  883.     {
  884. m_ulChunkSampleOffset += m_pSampleSizeAtom->
  885.     Get_SampleSize(ulChunkStartSampleNum);
  886.     }
  887.     /*** Not needed
  888.     m_ulChunkSize = m_ulChunkSampleOffset;
  889.     do
  890.     {
  891. m_ulChunkSize += m_pSampleSizeAtom->
  892.     Get_SampleSize(ulChunkStartSampleNum++);
  893.     } while (ulChunkStartSampleNum < ulChunkEndSampleNum);
  894.     ***/
  895.     
  896.     return TRUE;
  897. }
  898.     }
  899.     return FALSE;
  900. }
  901. /****************************************************************************
  902.  *  Chunk To Offset Manager
  903.  */
  904. /****************************************************************************
  905.  *  Constructor/Destructor
  906.  */
  907. CQT_ChunkToOffset_Manager::CQT_ChunkToOffset_Manager(void)
  908.     : m_pChunkToOffsetAtom(NULL)
  909.     , m_ulChunkOffset(0)
  910.     , m_ulNumEntries(0)
  911. {
  912.     ;
  913. }
  914. CQT_ChunkToOffset_Manager::~CQT_ChunkToOffset_Manager()
  915. {
  916.     HX_RELEASE(m_pChunkToOffsetAtom);
  917. }
  918. /****************************************************************************
  919.  *  Main Interface
  920.  */
  921. HX_RESULT CQT_ChunkToOffset_Manager::Init(CQTAtom* pAtom)
  922. {
  923.     HX_RESULT retVal = HXR_OK;
  924.     HX_RELEASE(m_pChunkToOffsetAtom);
  925.     m_ulChunkOffset = 0;
  926.     m_ulNumEntries = 0;
  927.     if (pAtom)
  928.     {
  929. if (pAtom->GetType() == QT_stco)
  930. {
  931.     m_pChunkToOffsetAtom = (CQT_stco_Atom*) pAtom;
  932. }
  933. else
  934. {
  935.     m_pChunkToOffsetAtom = (CQT_stco_Atom*) pAtom->FindPresentChild(QT_stco);
  936. }
  937. if (m_pChunkToOffsetAtom)
  938. {
  939.     m_pChunkToOffsetAtom->AddRef();
  940.     m_ulNumEntries = m_pChunkToOffsetAtom->Get_NumEntries();
  941. }
  942.     }
  943.     if (m_ulNumEntries == 0)
  944.     {
  945. retVal = HXR_FAIL;
  946. HX_RELEASE(m_pChunkToOffsetAtom);
  947.     }
  948.    
  949.     return retVal;
  950. }
  951. /****************************************************************************
  952.  *  Sample Description Manager
  953.  */
  954. /****************************************************************************
  955.  *  Constructor/Destructor
  956.  */
  957. CQT_SampleDescription_Manager::CQT_SampleDescription_Manager(void)
  958.     : m_ulSampleDescIdx(QT_BAD_IDX)
  959.     , m_pSampleDescriptionAtom(NULL)
  960.     , m_pSampleDesc(NULL)
  961.     , m_ulDataRefIdx(QT_BAD_IDX)
  962.     , m_ulDataFormat(0)
  963.     , m_ulRTPTimeScale(0)
  964.     , m_lTimeStampOffset(0)
  965.     , m_lSequenceNumOffset(0)
  966.     , m_ulNumEntries(0)
  967.     , m_ulDataRefIdxOffset(1)
  968. {
  969.     ;
  970. }
  971. CQT_SampleDescription_Manager::~CQT_SampleDescription_Manager()
  972. {
  973.     HX_RELEASE(m_pSampleDescriptionAtom);
  974. }
  975. /****************************************************************************
  976.  *  Main Interface Manager
  977.  */
  978. HX_RESULT CQT_SampleDescription_Manager::Init(CQTAtom* pAtom)
  979. {
  980.     HX_RESULT retVal = HXR_OK;
  981.     HX_RELEASE(m_pSampleDescriptionAtom);
  982.     m_ulSampleDescIdx = QT_BAD_IDX;
  983.     m_pSampleDesc = NULL;
  984.     m_ulDataRefIdx = QT_BAD_IDX;
  985.     m_ulDataFormat = 0;
  986.     m_ulRTPTimeScale = 0;
  987.     m_lTimeStampOffset = 0;
  988.     m_lSequenceNumOffset = 0;
  989.     m_ulNumEntries = 0;
  990.     if (pAtom)
  991.     {
  992. if (pAtom->GetType() == QT_stsd)
  993. {
  994.     m_pSampleDescriptionAtom = (CQT_stsd_Atom*) pAtom;
  995. }
  996. else
  997. {
  998.     m_pSampleDescriptionAtom = (CQT_stsd_Atom*) pAtom->FindPresentChild(QT_stsd);
  999. }
  1000. if (m_pSampleDescriptionAtom)
  1001. {
  1002.     m_pSampleDescriptionAtom->AddRef();
  1003.     m_ulNumEntries = m_pSampleDescriptionAtom->Get_NumEntries();
  1004. }
  1005.     }
  1006. #ifdef _STSD_ZERO_BASED_IQ
  1007.     ULONG32 ulIdx;
  1008.     for (ulIdx = 0; ulIdx < m_ulNumEntries; ulIdx++)
  1009.     {
  1010. if (EstablishByIdx(ulIdx))
  1011. {
  1012.     if (m_ulDataRefIdx == ((ULONG32) -1))
  1013.     {
  1014. m_ulDataRefIdxOffset = 0;
  1015. break;
  1016.     }
  1017. }
  1018.     }
  1019.     m_ulSampleDescIdx = QT_BAD_IDX;
  1020. #endif // _STSD_ZERO_BASED_IQ
  1021.     retVal = EstablishByIdx(0) ? HXR_OK : HXR_FAIL;
  1022.    
  1023.     return retVal;
  1024. }
  1025. /****************************************************************************
  1026.  *  Private Methods
  1027.  */
  1028. BOOL CQT_SampleDescription_Manager::ParseSampleDescription(void)
  1029. {
  1030.     BOOL bSuccess = TRUE;
  1031.     ULONG32 ulTaggedEntryIdx = 0;
  1032.     CQT_stsd_Atom::TaggedEntry* pTaggedEntry;
  1033.     // Find The Needed Sample
  1034.     m_pSampleDesc = m_pSampleDescriptionAtom->
  1035. Get_SampleDesc(m_ulSampleDescIdx);
  1036.     // Extract Needed Fixed Sample Fields
  1037.     m_ulDataRefIdx = m_pSampleDescriptionAtom->
  1038. Get_DataRefIdx(m_pSampleDesc) - m_ulDataRefIdxOffset;
  1039.     m_ulDataFormat = m_pSampleDescriptionAtom->
  1040. Get_DataFormat(m_pSampleDesc);
  1041.     m_ulRTPTimeScale = 0;
  1042.     m_lTimeStampOffset = 0;
  1043.     m_lSequenceNumOffset = 0;
  1044.     if (m_ulDataFormat == QT_rtp)
  1045.     {
  1046. // Extract Needed Tagged Entries
  1047. while ((pTaggedEntry = m_pSampleDescriptionAtom->
  1048.     Get_TaggedEntry((CQT_stsd_Atom::HintArrayEntry *) m_pSampleDesc, 
  1049.     ulTaggedEntryIdx)) != NULL)
  1050. {
  1051.     switch (CQTAtom::GetUL32(pTaggedEntry->pTag))
  1052.     {
  1053.     case QT_tims:
  1054. m_ulRTPTimeScale = CQTAtom::GetUL32(pTaggedEntry->pData);
  1055. break;
  1056.     case QT_tsro:
  1057. m_lTimeStampOffset = (LONG32) CQTAtom::GetUL32(pTaggedEntry->pData);
  1058. break;
  1059.     case QT_snro:
  1060. m_lSequenceNumOffset = (LONG32) CQTAtom::GetUL32(pTaggedEntry->pData);
  1061. break;
  1062.     default:
  1063. // nothing to do
  1064. break;
  1065.     }
  1066.     
  1067.     ulTaggedEntryIdx++;
  1068. }
  1069. bSuccess = (m_ulRTPTimeScale > 0);
  1070.     }
  1071.     return bSuccess;
  1072. }
  1073. /****************************************************************************
  1074.  *  Data Reference Manager
  1075.  */
  1076. /****************************************************************************
  1077.  *  Constructor/Destructor
  1078.  */
  1079. CQT_DataReference_Manager::CQT_DataReference_Manager(void)
  1080.     : m_pDataReferenceAtom(NULL)
  1081.     , m_ulDataRefIdx(QT_BAD_IDX)
  1082.     , m_pDataRefName(NULL)
  1083.     , m_pClassFactory(NULL)
  1084.     , m_ulNumEntries(0)
  1085. {
  1086.     ;
  1087. }
  1088. CQT_DataReference_Manager::~CQT_DataReference_Manager()
  1089. {
  1090.     HX_RELEASE(m_pDataReferenceAtom);
  1091.     HX_RELEASE(m_pDataRefName);
  1092.     HX_RELEASE(m_pClassFactory);
  1093. }
  1094. /****************************************************************************
  1095.  *  Main Interface
  1096.  */
  1097. HX_RESULT CQT_DataReference_Manager::Init
  1098. (
  1099.     CQTAtom* pAtom,
  1100.     IHXCommonClassFactory* pClassFactory
  1101. )
  1102. {
  1103.     HX_RESULT retVal = HXR_OK;
  1104.     HX_RELEASE(m_pDataReferenceAtom);
  1105.     HX_RELEASE(m_pDataRefName);
  1106.     HX_RELEASE(m_pClassFactory);
  1107.     m_ulDataRefIdx = QT_BAD_IDX;
  1108.     m_ulNumEntries = 0;
  1109.     if (pAtom)
  1110.     {
  1111. HX_ASSERT(pClassFactory);
  1112. m_pClassFactory = pClassFactory;
  1113. pClassFactory->AddRef();
  1114. if (pAtom->GetType() == QT_dref)
  1115. {
  1116.     m_pDataReferenceAtom = (CQT_dref_Atom*) pAtom;
  1117. }
  1118. else
  1119. {
  1120.     m_pDataReferenceAtom = (CQT_dref_Atom*) pAtom->FindPresentChild(QT_dref);
  1121. }
  1122. if (m_pDataReferenceAtom)
  1123. {
  1124.     m_pDataReferenceAtom->AddRef();
  1125.     m_ulNumEntries = m_pDataReferenceAtom->Get_NumEntries();
  1126. }
  1127.     }
  1128.     retVal = EstablishByIdx(0) ? HXR_OK : HXR_FAIL;
  1129.    
  1130.     return retVal;
  1131. }
  1132. /****************************************************************************
  1133.  *  Private methods
  1134.  */
  1135. BOOL CQT_DataReference_Manager::ParseDataReference(void)
  1136. {
  1137.     CQT_dref_Atom::ArrayEntry* pRefEntry;
  1138.     BOOL bSuccess = TRUE;
  1139.     HX_RELEASE(m_pDataRefName);
  1140.     pRefEntry = m_pDataReferenceAtom->GetRefEntry(m_ulDataRefIdx);
  1141.     if (!m_pDataReferenceAtom->Get_RefFlags(pRefEntry))
  1142.     {
  1143. bSuccess = FALSE;
  1144. #ifdef QTCONFIG_ALLOW_EXTERNAL_DATAREFS
  1145. /* handle Mac. Alias and form m_pDataRefName */        
  1146. UINT8* pDataRef = (UINT8*) 
  1147.   m_pDataReferenceAtom->Get_RefData(pRefEntry);
  1148. ULONG32 ulCurrentPos = pDataRef - m_pDataReferenceAtom->GetData();
  1149. ULONG32 ulDataRefLength = m_pDataReferenceAtom->GetDataSize();
  1150. UINT8* pRelPath = NULL;
  1151. ULONG32 ulPathLength = 0;
  1152. if (ulDataRefLength > ulCurrentPos)
  1153. {
  1154.     ulDataRefLength -= ulCurrentPos;
  1155.     bSuccess = FindRelPath(pDataRef, 
  1156.    ulDataRefLength, 
  1157.    pRelPath, 
  1158.    ulPathLength);
  1159. }
  1160. if (bSuccess)
  1161. {
  1162.     HX_ASSERT(pRelPath);
  1163.     HX_ASSERT(ulPathLength);
  1164.     bSuccess = FALSE;
  1165.     if (SUCCEEDED(m_pClassFactory->CreateInstance(
  1166. CLSID_IHXBuffer, 
  1167. (void**) &m_pDataRefName)))
  1168.     {
  1169. if (m_pDataRefName->SetSize(ulPathLength + 1) == HXR_OK)
  1170. {
  1171.     UINT8* pData = m_pDataRefName->GetBuffer();
  1172.     bSuccess = TRUE;
  1173.     memcpy(pData, /* Flawfinder: ignore */
  1174.    pRelPath,
  1175.    ulPathLength);
  1176.     pData[ulPathLength] = '';
  1177.     while (*pData != '')
  1178.     {
  1179. if (*pData == ':')
  1180. {
  1181.     *pData = '/';
  1182. }
  1183. pData++;
  1184.     }
  1185. }
  1186.     }
  1187. }
  1188. #endif // QTCONFIG_ALLOW_EXTERNAL_DATAREFS
  1189.     }
  1190.     return bSuccess;
  1191. }
  1192. /****************************************************************************
  1193.  *  FindRelPath
  1194.  */
  1195. #ifdef QTCONFIG_ALLOW_EXTERNAL_DATAREFS
  1196. BOOL CQT_DataReference_Manager::FindRelPath(UINT8* pData, 
  1197.     ULONG32 ulDataLength, 
  1198.     UINT8* &pRelPath, 
  1199.     ULONG32 &ulPathLength)
  1200. {
  1201.     UINT8* pCurrentPos;
  1202.     UINT8* pPathStart;
  1203.     UINT8* pPathEnd;
  1204.     BOOL bSuccess = FALSE;
  1205.     INT16 lNLvlTo;
  1206.     INT16 lNLvlFrom;
  1207.     CQT_dref_Atom::ItemEntry* pItem;
  1208.     pCurrentPos = pData + (sizeof(CQT_dref_Atom::DataRef) - 1);
  1209.     bSuccess = (((ULONG32) (pCurrentPos - 
  1210.     pData + 
  1211.     sizeof(CQT_dref_Atom::ItemEntry) - 
  1212.     1)) <= ulDataLength);
  1213.     if (bSuccess)
  1214.     {
  1215. CQT_dref_Atom::DataRef* pDataRef = (CQT_dref_Atom::DataRef*) pData;
  1216. lNLvlTo = CQTAtom::GetI16(pDataRef->pNLvlTo);
  1217. lNLvlFrom = CQTAtom::GetI16(pDataRef->pNLvlFrom);
  1218. // Make sure the path give is relative
  1219. bSuccess = ((lNLvlTo >= 0) && (lNLvlFrom >= 0));
  1220.     }
  1221.   
  1222.     // Search for the absolute pathname marker
  1223.     if (bSuccess)
  1224.     {
  1225. ULONG32 ulIdx;
  1226. bSuccess = FALSE;
  1227. for (ulIdx = QT_ALIS_MAXCOUNT; ulIdx != 0; ulIdx--)
  1228. {
  1229.     pItem = (CQT_dref_Atom::ItemEntry*) pCurrentPos;
  1230.     
  1231.     if ((CQTAtom::GetI16(pItem->pType) == QT_ALIS_ABSPATH) ||
  1232. (CQTAtom::GetI16(pItem->pType) == QT_ALIS_END))
  1233.     {
  1234. bSuccess = (CQTAtom::GetI16(pItem->pType) == QT_ALIS_ABSPATH);
  1235. break;
  1236.     }
  1237.     
  1238.     pCurrentPos = pItem->pData + 
  1239.   ((CQTAtom::GetI16(pItem->pSize) + 1) & ~1);
  1240.     
  1241.     bSuccess = (((ULONG32) (pCurrentPos - pData)) <= ulDataLength);
  1242. }
  1243.     }
  1244.     
  1245.     if (bSuccess)
  1246.     {
  1247. // Strip off the absolute portions
  1248. pPathStart = pItem->pData;
  1249. pPathEnd = (pPathStart + CQTAtom::GetUI16(pItem->pSize));
  1250. pCurrentPos = pPathEnd;
  1251. bSuccess = (((ULONG32) (pCurrentPos - pData)) <= ulDataLength);
  1252.     }
  1253.     if (bSuccess)
  1254.     {
  1255. while (lNLvlTo && (pCurrentPos >= pPathStart))
  1256. {
  1257.     if (*(pCurrentPos--) == ':')
  1258.     {
  1259. lNLvlTo--;
  1260.     }
  1261. }
  1262. pCurrentPos++;
  1263. if(*pCurrentPos == ':')
  1264. {
  1265.     pCurrentPos++;
  1266. }
  1267. pRelPath = pCurrentPos;
  1268. ulPathLength = pPathEnd + 1 - pCurrentPos;
  1269. bSuccess = (ulPathLength != 0);
  1270.     }
  1271.     return bSuccess;
  1272. }
  1273. #else // QTCONFIG_ALLOW_EXTERNAL_DATAREFS
  1274. /****************************************************************************
  1275.  *  FindRelPath
  1276.  */
  1277. BOOL CQT_DataReference_Manager::FindRelPath(UINT8* pData, 
  1278.     ULONG32 ulDataLength, 
  1279.     UINT8* &pRelPath, 
  1280.     ULONG32 &ulPathLength)
  1281. {
  1282.     return FALSE;
  1283. }
  1284. #endif // QTCONFIG_ALLOW_EXTERNAL_DATAREFS
  1285. /****************************************************************************
  1286.  *  Track Info Manager
  1287.  */
  1288. /****************************************************************************
  1289.  *  Constructor/Destructor
  1290.  */
  1291. CQT_TrackInfo_Manager::CQT_TrackInfo_Manager(void)
  1292.     : m_pNameAtom(NULL)
  1293.     , m_pSDPAtom(NULL)
  1294.     , m_ulMediaTimeScale(0)
  1295.     , m_ulPayloadType(QT_BAD_PAYLOAD)
  1296.     , m_ulTrackDuration(0)
  1297.     , m_ulTrackSize(0)
  1298.     , m_ulRefTrackID(QT_BAD_IDX)
  1299.     , m_ulAvgBitrate(0)
  1300.     , m_ulMaxBitrate(0)
  1301.     , m_ulPreroll(0)
  1302.     , m_ulPredata(0)
  1303.     , m_ulTrackWidth(0)
  1304.     , m_ulTrackHeight(0)
  1305.     , m_ulFrameWidth(0)
  1306.     , m_ulFrameHeight(0)
  1307.     , m_ulChannels(0)
  1308.     , m_ulTrackMatrixTransformX(0)
  1309.     , m_ulTrackMatrixTransformY(0)
  1310.     , m_pPayloadTypeAtom(NULL)
  1311.     , m_pName(NULL)
  1312.     , m_pSDP(NULL)
  1313.     , m_pMimeType(NULL)
  1314.     , m_pOpaqueData(NULL)
  1315.     , m_ulOpaqueDataSize(0)
  1316.     , m_pHeader(NULL)
  1317.     , m_bOpaqueDataShouldBeDeleted(FALSE)
  1318.     , m_ulNumSamplesInOpaqueData(0)
  1319. {
  1320.     ;
  1321. }
  1322. CQT_TrackInfo_Manager::~CQT_TrackInfo_Manager()
  1323. {
  1324.     Clear();
  1325. }
  1326. /****************************************************************************
  1327.  *  Main Interface
  1328.  */
  1329. HX_RESULT CQT_TrackInfo_Manager::Init(IUnknown* pContext,
  1330.       CQTAtom* pAtom,
  1331.       CQT_SampleDescription_Manager* pSampleDescManager,
  1332.       CQTTrackManager* pTrackManager,
  1333.       CQT_MovieInfo_Manager* pMovieInfo)
  1334. {
  1335.     HX_RESULT retVal = HXR_OK;
  1336.     
  1337.     Clear();
  1338.     
  1339.     if (pAtom->GetType() != QT_trak)
  1340.     {
  1341. pAtom = NULL;
  1342.     }
  1343.     // Extract Track Type
  1344.     if (pAtom)
  1345.     {
  1346. CQT_hdlr_Atom* pHdlrAtom = CQTTrackManager::GetTrackAtomHdlr(
  1347. (CQT_trak_Atom *) pAtom);
  1348. if (pHdlrAtom)
  1349. {
  1350.     m_TrackType = pHdlrAtom->Get_CompSubtype();
  1351. }
  1352. else
  1353. {
  1354.     // Fail
  1355.     pAtom = NULL;
  1356. }
  1357.     }
  1358.     // Extract track duration
  1359.     if (pAtom)
  1360.     {
  1361. CQT_tkhd_Atom* pTrackHeaderAtom = NULL;
  1362. pTrackHeaderAtom = (CQT_tkhd_Atom*) 
  1363.    pAtom->FindPresentChild(QT_tkhd);
  1364. if (pTrackHeaderAtom)
  1365. {
  1366.     m_ulTrackDuration = pTrackHeaderAtom->Get_Duration();
  1367.     m_ulTrackWidth    = (UINT32) pTrackHeaderAtom->Get_TrackWidth();
  1368.     m_ulTrackHeight   = (UINT32) pTrackHeaderAtom->Get_TrackHeight();
  1369.     // /These are the offsets from the origin (video's upper left):
  1370.     m_ulTrackMatrixTransformX = (UINT32) pTrackHeaderAtom->Get_TrackMatrixTx();
  1371.     m_ulTrackMatrixTransformY = (UINT32) pTrackHeaderAtom->Get_TrackMatrixTy();
  1372. }
  1373. else
  1374. {
  1375.     pAtom = NULL;
  1376. }
  1377.     }
  1378.     // Extract Track Time Scale
  1379.     if (pAtom)
  1380.     {
  1381. CQTAtom* pChildAtom = pAtom->FindPresentChild(QT_mdia);
  1382. if (pChildAtom)
  1383. {
  1384.     CQT_mdhd_Atom* pMediaHeaderAtom = (CQT_mdhd_Atom*)
  1385.        pChildAtom->FindPresentChild(QT_mdhd);
  1386.     if (pMediaHeaderAtom)
  1387.     {
  1388. m_ulMediaTimeScale = pMediaHeaderAtom->Get_TimeScale();
  1389.     }
  1390. }
  1391. if (m_ulMediaTimeScale == 0)
  1392. {
  1393.     pAtom = NULL;
  1394. }
  1395.     }
  1396.     if (pAtom)
  1397.     {
  1398. switch (m_TrackType)
  1399. {
  1400. case QT_hint:
  1401.     retVal = InitHinted(pAtom,
  1402. pSampleDescManager,
  1403. pTrackManager,
  1404. pMovieInfo);
  1405.             if (HXR_OK == retVal && m_pSDPAtom)
  1406.             {
  1407.                 retVal = CheckForcePacketization(m_pSDPAtom, pContext);
  1408.             }
  1409. #ifdef _IGNORE_MP4_AUDIO
  1410.     if (pTrackManager->GetFType() == QT_FTYPE_MP4)
  1411.     {
  1412. const char* pSDPData = (char*) GetSDP();
  1413. if (pSDPData && (GetSDPLength() >= (sizeof("audio") - 1)))
  1414. {
  1415.     if (strncmp(pSDPData, "m=audio", sizeof("audio") - 1) == 0)
  1416.     {
  1417. retVal = HXR_IGNORE;
  1418.     }
  1419. }
  1420.     }
  1421. #endif // _IGNORE_MP4_AUDIO
  1422.     break;
  1423. case QT_soun:
  1424. #ifdef _IGNORE_MP4_AUDIO
  1425.     if (pTrackManager->GetFType() == QT_FTYPE_MP4)
  1426.     {
  1427. retVal = HXR_IGNORE;
  1428. break;
  1429.     }
  1430. #endif // _IGNORE_MP4_AUDIO
  1431. case QT_vide:
  1432. case QT_text:
  1433.     retVal = InitNonHinted(pAtom,
  1434.    pSampleDescManager,
  1435.    pTrackManager,
  1436.    pMovieInfo);
  1437.     break;
  1438. default:
  1439.     // not supported
  1440.     retVal = HXR_IGNORE;
  1441. }
  1442. if (FAILED(retVal))
  1443. {
  1444.     pAtom = NULL;
  1445. }
  1446.     }
  1447.     if (SUCCEEDED(retVal) && (pAtom == NULL))
  1448.     {
  1449. retVal = HXR_FAIL;
  1450.     }
  1451.    
  1452.     return retVal;
  1453. }
  1454. ULONG32 CQT_TrackInfo_Manager::GetNameLength(void)
  1455. {
  1456.     ULONG32 ulSize = 0;
  1457.     
  1458.     if (m_pNameAtom)
  1459.     {
  1460. ulSize = m_pNameAtom->GetDataSize();
  1461.     }
  1462.     else if (m_pName)
  1463.     {
  1464. ulSize = strlen(m_pName);
  1465.     }
  1466.     
  1467.     return ulSize;
  1468. }
  1469. const UINT8* CQT_TrackInfo_Manager::GetName(void)
  1470. {
  1471.     return m_pNameAtom ? m_pNameAtom->GetData() : ((UINT8*) m_pName);
  1472. }
  1473. ULONG32 CQT_TrackInfo_Manager::GetSDPLength(void)
  1474. {
  1475.     ULONG32 ulSize = 0;
  1476.     
  1477.     if (m_pSDPAtom)
  1478.     {
  1479. ulSize = m_pSDPAtom->GetDataSize();
  1480.     }
  1481.     else if (m_pSDP)
  1482.     {
  1483. ulSize = strlen(m_pSDP);
  1484.     }
  1485.     
  1486.     return ulSize;
  1487. }
  1488. const UINT8* CQT_TrackInfo_Manager::GetSDP(void)
  1489. {
  1490.     return m_pSDPAtom ? m_pSDPAtom->GetData() : ((UINT8*) m_pSDP);
  1491. }
  1492. ULONG32 CQT_TrackInfo_Manager::GetOpaqueDataLength(void)
  1493. {    
  1494.     return m_ulOpaqueDataSize;
  1495. }
  1496. const UINT8* CQT_TrackInfo_Manager::GetOpaqueData(void)
  1497. {
  1498.     return m_pOpaqueData;
  1499. }
  1500. const UINT32 CQT_TrackInfo_Manager::GetNumSamplesInOpaqueData(void)
  1501. {
  1502.     return m_ulNumSamplesInOpaqueData;
  1503. }
  1504. HX_RESULT CQT_TrackInfo_Manager::GetHeader(IHXValues* &pHeader)
  1505. {
  1506.     HX_RESULT retVal = HXR_FAIL;
  1507.     if (m_pHeader)
  1508.     {
  1509. pHeader = m_pHeader;
  1510. pHeader->AddRef();
  1511. retVal = HXR_OK;
  1512.     }
  1513.     return retVal;
  1514. }
  1515. void CQT_TrackInfo_Manager::SetHeader(IHXValues* pHeader)
  1516. {
  1517.     HX_RELEASE(m_pHeader);
  1518.     m_pHeader = pHeader;
  1519.     if (m_pHeader)
  1520.     {
  1521. m_pHeader->AddRef();
  1522.     }
  1523. }
  1524. /****************************************************************************
  1525.  *  Private functions
  1526.  */
  1527. void CQT_TrackInfo_Manager::Clear(void)
  1528. {
  1529.     HX_RELEASE(m_pNameAtom);
  1530.     HX_RELEASE(m_pSDPAtom);
  1531.     HX_RELEASE(m_pPayloadTypeAtom);
  1532.     HX_RELEASE(m_pHeader);
  1533.     HX_VECTOR_DELETE(m_pSDP);
  1534.     HX_VECTOR_DELETE(m_pMimeType);
  1535.     m_ulMediaTimeScale = 0;
  1536.     m_ulTrackDuration = 0;
  1537.     m_ulTrackSize = 0;
  1538.     m_ulRefTrackID = QT_BAD_IDX;
  1539.     m_ulTrackWidth = 0;
  1540.     m_ulTrackHeight = 0;
  1541.     m_ulFrameWidth = 0;
  1542.     m_ulFrameHeight = 0;
  1543.     m_ulTrackMatrixTransformX = m_ulTrackMatrixTransformY = 0;
  1544.     m_ulOpaqueDataSize = 0;
  1545.     if (m_bOpaqueDataShouldBeDeleted  &&  m_pOpaqueData)
  1546.     {
  1547. delete [] m_pOpaqueData;
  1548. m_pOpaqueData = NULL;
  1549. m_ulOpaqueDataSize = 0;
  1550. m_bOpaqueDataShouldBeDeleted = FALSE;
  1551. m_ulNumSamplesInOpaqueData = 0;
  1552.     }
  1553. }
  1554. HX_RESULT CQT_TrackInfo_Manager::InitNonHinted(CQTAtom* pAtom,
  1555.        CQT_SampleDescription_Manager* pSampleDescManager,
  1556.        CQTTrackManager* pTrackManager,
  1557.        CQT_MovieInfo_Manager* pMovieInfo)
  1558. {
  1559.     const char* pMediaType = NULL;
  1560.     const char* pMediaName = NULL;
  1561.     UINT8 uProfileObjectIndication = MP4OBJ_FORBIDDEN;
  1562.     UINT8 uStreamType = MP4STRM_FORBIDDEN;
  1563.     HX_RESULT retVal = HXR_OK;
  1564.     // Form Track name
  1565.     switch (m_TrackType)
  1566.     {
  1567.     case QT_vide:
  1568. m_pName = "Video Track";
  1569. break;
  1570.     case QT_soun:
  1571. m_pName = "Audio Track";
  1572. break;
  1573.     case QT_text:
  1574. m_pName = "Text Track";
  1575. break;
  1576.     default:
  1577. retVal = HXR_IGNORE;
  1578. break;
  1579.     }
  1580.     m_ulOpaqueDataSize = 0;
  1581.     if (m_bOpaqueDataShouldBeDeleted  &&  m_pOpaqueData)
  1582.     {
  1583. delete [] m_pOpaqueData;
  1584. m_pOpaqueData = NULL;
  1585.     }
  1586.     m_ulOpaqueDataSize = 0;
  1587.     m_bOpaqueDataShouldBeDeleted = FALSE;
  1588.     m_ulNumSamplesInOpaqueData = 0;
  1589.     // Extract Opaque Data
  1590.     if ((retVal == HXR_OK) && pAtom)
  1591.     {
  1592. if (pSampleDescManager->GetNumEntries() == 1)
  1593. {
  1594.     CQT_stsd_Atom::ArrayEntry* pSampleDescEntry = 
  1595. pSampleDescManager->GetSampleDescEntry();
  1596.     ULONG32 ulSampleDescEntrySize = 
  1597. CQTAtom::GetUL32(pSampleDescEntry->pSize);
  1598.     if (pTrackManager->GetFType() == QT_FTYPE_MP4)
  1599.     {
  1600. switch (pSampleDescManager->GetDataFormat())
  1601. {
  1602. case QT_mp4v:
  1603.     if (ulSampleDescEntrySize > 
  1604. sizeof(CQT_stsd_Atom::VideoMP4ArrayEntry))
  1605.     {
  1606. m_pOpaqueData = ((CQT_stsd_Atom::VideoMP4ArrayEntry*) 
  1607.     pSampleDescEntry)->pESDescriptor;
  1608.     }
  1609.     break;
  1610. case QT_mp4a:
  1611.     if (ulSampleDescEntrySize > 
  1612. sizeof(CQT_stsd_Atom::AudioMP4ArrayEntry))
  1613.                     {
  1614.                         m_ulChannels = CQTAtom::GetUI16((UINT8*)
  1615.                             (((CQT_stsd_Atom::AudioArrayEntry*) 
  1616.     pSampleDescEntry)->pNumChannels));
  1617. m_pOpaqueData = ((CQT_stsd_Atom::AudioMP4ArrayEntry*) 
  1618.     pSampleDescEntry)->pESDescriptor;
  1619.     }
  1620.     break;
  1621. case QT_s263:
  1622.     if (ulSampleDescEntrySize > 
  1623. sizeof(CQT_stsd_Atom::VideoS263ArrayEntry))
  1624.     {
  1625.                         m_ulFrameWidth = CQTAtom::GetUI16((UINT8*)
  1626.                            (((CQT_stsd_Atom::VideoS263ArrayEntry*)
  1627.                            pSampleDescEntry)->pWidth));
  1628.                         m_ulFrameHeight = CQTAtom::GetUI16((UINT8*)
  1629.                            (((CQT_stsd_Atom::VideoS263ArrayEntry*)
  1630.                            pSampleDescEntry)->pHeight));
  1631. m_pOpaqueData = ((CQT_stsd_Atom::VideoS263ArrayEntry*) 
  1632.     pSampleDescEntry)->pDecoderSpecificInfo;
  1633.     }
  1634.     break;
  1635. case QT_samr:
  1636.     if (ulSampleDescEntrySize > 
  1637. sizeof(CQT_stsd_Atom::AudioSAMRArrayEntry))
  1638.     {
  1639. m_pOpaqueData = ((CQT_stsd_Atom::AudioSAMRArrayEntry*) 
  1640.     pSampleDescEntry)->pDecoderSpecificInfo;
  1641.     }
  1642.     break;
  1643. case QT_sawb:
  1644.     if (ulSampleDescEntrySize > 
  1645. sizeof(CQT_stsd_Atom::AudioSAWBArrayEntry))
  1646.     {
  1647. m_pOpaqueData = ((CQT_stsd_Atom::AudioSAWBArrayEntry*) 
  1648.     pSampleDescEntry)->pDecoderSpecificInfo;
  1649.     }
  1650.     break;
  1651. #ifdef QTCONFIG_TIMEDTEXT_PACKETIZER
  1652. case QT_tx3g:
  1653.     m_ulNumSamplesInOpaqueData = 1;
  1654.     // /Use entire descEntry as opaque stream data; unpack it
  1655.     // in renderer:
  1656.     if (ulSampleDescEntrySize >= 
  1657.     sizeof(CQT_stsd_Atom::TextSampleEntry))
  1658.     {
  1659. CQT_stsd_Atom* pSampleDescAtom =
  1660. pSampleDescManager->GetSampleDescriptionAtom();
  1661. m_pOpaqueData = pSampleDescAtom->GetData();
  1662. m_ulOpaqueDataSize = pSampleDescAtom->GetDataSize();
  1663.     }
  1664.     else
  1665.     {
  1666. retVal = HXR_UNEXPECTED;
  1667. m_ulNumSamplesInOpaqueData = 0;
  1668.     }
  1669.     break;
  1670. #endif // QTCONFIG_TIMEDTEXT_PACKETIZER
  1671. default:
  1672.     retVal = HXR_IGNORE;
  1673.     break;
  1674. }
  1675.     }
  1676.     else
  1677.     {
  1678. switch (m_TrackType)
  1679. {
  1680. case QT_vide:
  1681.     if (ulSampleDescEntrySize >=
  1682. sizeof(CQT_stsd_Atom::VideoArrayEntry))
  1683.     {
  1684. m_pOpaqueData = ((CQT_stsd_Atom::VideoArrayEntry*) 
  1685.     pSampleDescEntry)->pVersion;
  1686.     }
  1687.     break;
  1688. case QT_soun:
  1689.     if (ulSampleDescEntrySize >=
  1690. sizeof(CQT_stsd_Atom::AudioArrayEntry))
  1691.     {
  1692. m_pOpaqueData = ((CQT_stsd_Atom::AudioArrayEntry*) 
  1693.     pSampleDescEntry)->pVersion;
  1694.     }
  1695.     break;
  1696. default:
  1697.     retVal = HXR_IGNORE;
  1698.     break;
  1699. }
  1700.     }
  1701.     if (m_pOpaqueData)
  1702.     {
  1703. m_ulOpaqueDataSize = ulSampleDescEntrySize - 
  1704.      (m_pOpaqueData - ((UINT8*) pSampleDescEntry));
  1705. #ifndef HELIX_FEATURE_3GPPCLIENT_ONLY
  1706. if ((pSampleDescManager->GetDataFormat() == QT_mp4v) || 
  1707.     (pSampleDescManager->GetDataFormat() == QT_mp4a))
  1708. {
  1709.     ES_Descriptor ESDesc;
  1710.     DecoderConfigDescriptor* pDCDesc = NULL;
  1711.     UINT8* pOpaqueData = m_pOpaqueData;
  1712.     ULONG32 ulOpaqueDataSize = m_ulOpaqueDataSize;
  1713.     
  1714.     retVal = ESDesc.Unpack(pOpaqueData, ulOpaqueDataSize);
  1715.     
  1716.     if (SUCCEEDED(retVal))
  1717.     {
  1718. retVal = HXR_FAIL;
  1719. pDCDesc = ESDesc.m_pDecConfigDescr;
  1720. if (pDCDesc)
  1721. {
  1722.     m_ulAvgBitrate = pDCDesc->m_ulAvgBitrate;
  1723.     m_ulMaxBitrate = pDCDesc->m_ulMaxBitrate;
  1724.     uProfileObjectIndication = pDCDesc->m_uObjectProfileIndication;
  1725.     uStreamType = pDCDesc->m_uStreamType;
  1726.     retVal = HXR_OK;
  1727. }
  1728.     }
  1729.     
  1730. #ifdef _TINF_NO_MEDIA_SCALE_IQ
  1731.     if (SUCCEEDED(retVal) && pMovieInfo)
  1732.     {
  1733. // PacketVideo format records sample times in movie
  1734. // scale.  That format also has a flaw in ES_Descriptor
  1735. // that forces ES_Descriptor into the alternate 
  1736. // parsing mode which results in setting of the
  1737. // SIZE_HEADER_INCLUSIVE flag. Thus, the media time scale 
  1738. // is corrected based on this condition.
  1739. if (ESDesc.m_ulFlags &
  1740.     MP4BaseDescriptor::SIZE_HEADER_INCLUSIVE)
  1741. {
  1742.     m_ulMediaTimeScale = pMovieInfo->GetMovieTimeScale();
  1743. }
  1744.     }
  1745. #endif // _TINF_NO_MEDIA_SCALE_IQ
  1746. }
  1747. #endif // HELIX_FEATURE_3GPPCLIENT_ONLY
  1748.     }
  1749.     else
  1750.     {
  1751. if (retVal == HXR_OK)
  1752. {
  1753.     retVal = HXR_FAIL;
  1754. }
  1755.     }
  1756. }
  1757. #ifdef QTCONFIG_TIMEDTEXT_PACKETIZER
  1758. else if (pSampleDescManager->GetNumEntries() > 1  &&
  1759. QT_tx3g == pSampleDescManager->GetDataFormat())
  1760. {
  1761.     // /Cycle through and combine these into one opaque blob for
  1762.     // the stream header:
  1763.     UINT32 ulNumEntries = pSampleDescManager->GetNumEntries();
  1764.     CQT_stsd_Atom* pSampleDescAtom =
  1765.     pSampleDescManager->GetSampleDescriptionAtom();
  1766.     if (pSampleDescAtom  &&  ulNumEntries)
  1767.     {
  1768. m_ulNumSamplesInOpaqueData = ulNumEntries;
  1769. m_ulOpaqueDataSize = pSampleDescAtom->GetDataSize();
  1770. m_pOpaqueData = pSampleDescAtom->GetData();
  1771.     }
  1772. }
  1773. #endif // QTCONFIG_TIMEDTEXT_PACKETIZER
  1774.     }
  1775.     // Form SDP Segment
  1776.     if ((retVal == HXR_OK) && pAtom)
  1777.     {
  1778. // Set default media name
  1779. if (pTrackManager->GetFType() == QT_FTYPE_MP4)
  1780. {
  1781.     pMediaName = "X-RN-MP4-RAWAU";
  1782. }
  1783. else
  1784. {
  1785.     pMediaName = "X-RN-QT-RAWAU";
  1786. }
  1787. switch (m_TrackType)
  1788. {
  1789. case QT_vide:
  1790.     pMediaType = "video";
  1791.     switch (pSampleDescManager->GetDataFormat())
  1792.     {
  1793.     case QT_mp4v:
  1794.     case QT_mp4a:
  1795. pMediaName = "X-RN-MP4";
  1796. break;
  1797.     case QT_s263:
  1798. pMediaName = "X-RN-3GPP-H263";
  1799. break;
  1800.     default:
  1801. // nothing to do
  1802. break;
  1803.     }
  1804.     break;
  1805.     
  1806.     case QT_soun:
  1807. pMediaType = "audio";
  1808. switch (pSampleDescManager->GetDataFormat())
  1809. {
  1810. #ifndef HELIX_FEATURE_3GPPCLIENT_ONLY
  1811. case QT_mp4v:
  1812. case QT_mp4a:
  1813.     if ((uProfileObjectIndication == MP4OBJ_VISUAL_ISO_IEC_11172_3) &&
  1814. (uStreamType == MP4STRM_AUDIO))
  1815.     {
  1816. pMediaName = "MPEG-ELEMENTARY";
  1817. m_pOpaqueData = NULL;
  1818. m_ulOpaqueDataSize = 0;
  1819. m_ulPreroll = 1000;
  1820.     }
  1821.     break;
  1822. #endif // HELIX_FEATURE_3GPPCLIENT_ONLY
  1823. case QT_samr:
  1824.     pMediaName = "X-RN-3GPP-AMR";
  1825.     break;
  1826. case QT_sawb:
  1827.     pMediaName = "X-RN-3GPP-AMR-WB";
  1828.     break;
  1829. default:
  1830.     // nothing to do
  1831.     break;
  1832. }
  1833. break;
  1834. #ifdef QTCONFIG_TIMEDTEXT_PACKETIZER
  1835. case QT_text:
  1836.     pMediaType = "video";
  1837.     pMediaName = "X-RN-3GPP-TEXT";
  1838.     break;
  1839. #endif // QTCONFIG_TIMEDTEXT_PACKETIZER
  1840.     
  1841. default:
  1842.     pMediaType = "application";
  1843.     break;
  1844. }
  1845. m_ulPayloadType = RTP_PAYLOAD_RTSP;
  1846. #ifdef QTCONFIG_SERVER
  1847. HX_VECTOR_DELETE(m_pSDP);
  1848. m_pSDP = new char [TRACK_SDP_CHUNK_SIZE];
  1849. retVal = HXR_OUTOFMEMORY;
  1850. if (m_pSDP)
  1851. {
  1852.     char* pWriter;
  1853.     char* pWriterEnd = m_pSDP + TRACK_SDP_CHUNK_SIZE;
  1854.     retVal = HXR_OK;
  1855.     
  1856.     pWriter = m_pSDP;
  1857.     
  1858.     pWriter += SafeSprintf(pWriter, pWriterEnd - pWriter,
  1859.    "m=%s 0 RTP/AVP %drn", 
  1860.    pMediaType, 
  1861.    m_ulPayloadType);
  1862.     
  1863.     pWriter += SafeSprintf(pWriter, pWriterEnd - pWriter,
  1864.    "a=rtpmap:%d %s/%drn",
  1865.    m_ulPayloadType,
  1866.    pMediaName,
  1867.    m_ulMediaTimeScale);
  1868.     HX_ASSERT((pWriter - m_pSDP) < TRACK_SDP_CHUNK_SIZE);
  1869. }
  1870. #endif // QTCONFIG_SERVER
  1871.     }
  1872.     if ((retVal == HXR_OK) && pAtom)
  1873.     {
  1874. HX_ASSERT(pMediaType);
  1875. HX_ASSERT(pMediaName);
  1876. ULONG32 ulMediaTypeLen = strlen(pMediaType);
  1877. ULONG32 ulMediaNameLen = strlen(pMediaName);
  1878. m_pMimeType = new char [ulMediaTypeLen + ulMediaNameLen + 2];
  1879. retVal = HXR_OUTOFMEMORY;
  1880. if (m_pMimeType)
  1881. {
  1882.     retVal = HXR_OK;
  1883.     strcpy(m_pMimeType, pMediaType); /* Flawfinder: ignore */
  1884.     strcpy(m_pMimeType + ulMediaTypeLen + 1, pMediaName); /* Flawfinder: ignore */
  1885.     m_pMimeType[ulMediaTypeLen] = '/';
  1886. }
  1887.     }
  1888.     return retVal;
  1889. }
  1890. /****************************************************************************
  1891.  *  Movie Info Manager
  1892.  */
  1893. /****************************************************************************
  1894.  *  Constructor/Destructor
  1895.  */
  1896. CQT_MovieInfo_Manager::CQT_MovieInfo_Manager(void)
  1897.     : m_ulMovieTimeScale(0)
  1898.     , m_ulMovieDuration(0)
  1899.     , m_pNameAtom(NULL)
  1900.     , m_pRTPSDPAtom(NULL)
  1901. {
  1902.     ;
  1903. }
  1904. CQT_MovieInfo_Manager::~CQT_MovieInfo_Manager()
  1905. {
  1906.     Clear();
  1907. }
  1908. void CQT_MovieInfo_Manager::Clear()
  1909. {
  1910.     HX_RELEASE(m_pNameAtom);
  1911.     HX_RELEASE(m_pRTPSDPAtom);
  1912. }
  1913. /****************************************************************************
  1914.  *  Main Interface
  1915.  */
  1916. HX_RESULT CQT_MovieInfo_Manager::Init(CQTAtom* pAtom, 
  1917.       CQTTrackManager* pTrackManager)
  1918. {
  1919.     HX_RESULT retVal;
  1920.     m_ulMovieTimeScale = 0;
  1921.     m_ulMovieDuration = 0;
  1922.     HX_RELEASE(m_pNameAtom);
  1923.     HX_RELEASE(m_pRTPSDPAtom);
  1924.     if (pAtom && (pAtom->GetType() != QT_moov))
  1925.     {
  1926. pAtom = NULL;
  1927.     }
  1928.     if (pAtom)
  1929.     {
  1930. CQT_mvhd_Atom *pMovieHeaderAtom = NULL;
  1931. pMovieHeaderAtom = (CQT_mvhd_Atom*) 
  1932.    pAtom->FindPresentChild(QT_mvhd);
  1933. if (pMovieHeaderAtom)
  1934. {
  1935.     m_ulMovieTimeScale = pMovieHeaderAtom->Get_TimeScale();
  1936.     m_ulMovieDuration = pMovieHeaderAtom->Get_Duration();
  1937. }
  1938. else
  1939. {
  1940.     pAtom = NULL;
  1941. }
  1942.     }
  1943.     if (pAtom)
  1944.     {
  1945. pAtom = pAtom->FindPresentChild(QT_udta);
  1946.     }
  1947.     if (pAtom)
  1948.     {
  1949. m_pNameAtom = (CQT_name_Atom*) pAtom->FindPresentChild(QT_name);
  1950. if (m_pNameAtom)
  1951. {
  1952.     m_pNameAtom->AddRef();
  1953. }
  1954. pAtom = pAtom->FindPresentChild(QT_hnti);
  1955.     }
  1956.     ParseMovieHintInfo(pAtom);
  1957.     
  1958.     retVal = m_ulMovieTimeScale ? HXR_OK : HXR_FAIL;
  1959.    
  1960.     return retVal;
  1961. }