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

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 _LOG_DATA_ACCESS
  39. #define QTTRACKCACHE_PAGE_SIZE 0x0000FFFF
  40. /****************************************************************************
  41.  *  Includes
  42.  */
  43. #include "qtpktasm.h"
  44. #include "qtffplin.h"
  45. #include "qtpacketizerfct.h"
  46. #include "qttrack.h"
  47. #include "qtffrefcounter.h"
  48. /****************************************************************************
  49.  *  Class CQTTrack
  50.  */
  51. /****************************************************************************
  52.  *  Constructor/Destructor
  53.  */
  54. CQTTrack::CQTTrack(CQTAtom* pTrackAtom)
  55.     : m_pTrackAtom((CQT_trak_Atom*) pTrackAtom)
  56.     , m_pFileFormat(NULL)
  57.     , m_pPacketAssembler(NULL)
  58.     , m_pReadFileNameBuffer(NULL)
  59.     , m_pReadFileName(NULL)
  60.     , m_pFileSwitcher(NULL)
  61.     , m_pPacketizer(NULL)
  62.     , m_pClassFactory(NULL)
  63.     , m_ulTrackID(0)
  64.     , m_bTrackDone(FALSE)
  65.     , m_PendingState(QTT_Offline)
  66.     , m_uStreamNumber(0)
  67.     , m_ulReadSize(0)
  68.     , m_ulReadPageSize(0)
  69.     , m_ulReadPageOffset(0)
  70.     , m_uBytesPerCBlock(0)
  71.     , m_uSamplesPerCBlock(0)
  72.     , m_lRefCount(0)
  73.     , m_ulLastSampleDescIdx(0)
  74. {
  75.     CQT_tkhd_Atom* pTrackHeaderAtom = NULL;
  76.     HX_ASSERT(pTrackAtom);
  77.     pTrackAtom->AddRef();
  78.     
  79.     if (pTrackAtom)
  80.     {
  81. pTrackHeaderAtom = (CQT_tkhd_Atom*) 
  82.     pTrackAtom->FindPresentChild(QT_tkhd);
  83.     }
  84.     
  85.     if (pTrackHeaderAtom)
  86.     {
  87. m_ulTrackID = pTrackHeaderAtom->Get_TrackID();
  88.     }
  89.     g_nRefCount_qtff++;
  90. }
  91. CQTTrack::~CQTTrack()
  92. {
  93.     Close();
  94.     g_nRefCount_qtff--;
  95. }
  96. /****************************************************************************
  97.  *  Main Interface
  98.  */
  99. /****************************************************************************
  100.  *  Init
  101.  */
  102. HX_RESULT CQTTrack::Init(CQTFileFormat *pFileFormat,
  103.  CQTPacketAssembler *pPacketAssembler,
  104.  CQTPacketizerFactory* pPacketizerFactory,
  105.  const char* pProtocol)
  106. {
  107.     CQTAtom* pAtom = NULL;
  108.     BOOL bIsStreamTrack = FALSE;
  109.     HX_RESULT retVal = HXR_OK;
  110.     if (!m_pTrackAtom)
  111.     {
  112. retVal = HXR_UNEXPECTED;
  113.     }
  114.     pAtom = m_pTrackAtom;
  115.     m_uBytesPerCBlock = 0;
  116.     m_uSamplesPerCBlock = 0;
  117.     if (SUCCEEDED(retVal))
  118.     {
  119. HX_ASSERT(pFileFormat);
  120. bIsStreamTrack = pFileFormat->m_TrackManager.IsStreamTrack(this);
  121. m_pFileFormat = pFileFormat;
  122. pFileFormat->AddRef();
  123. HX_ASSERT(pPacketAssembler);
  124. m_pPacketAssembler = pPacketAssembler;
  125. pPacketAssembler->AddRef();
  126. retVal = pFileFormat->QueryInterface(
  127.     IID_IHXFileSwitcher,
  128.     (void**) &m_pFileSwitcher);
  129.     }
  130.     if (SUCCEEDED(retVal))
  131.     {
  132. retVal = pFileFormat->QueryInterface(IID_IHXCommonClassFactory,
  133.      (void**) &m_pClassFactory);
  134.     }
  135.     if (SUCCEEDED(retVal))
  136.     {
  137. CQT_tkhd_Atom* pTrackHeaderAtom = NULL;
  138. HX_ASSERT(m_pFileSwitcher);
  139. if (pAtom)
  140. {
  141.     pTrackHeaderAtom = (CQT_tkhd_Atom*) 
  142.        pAtom->FindPresentChild(QT_tkhd);
  143. }
  144. if (pTrackHeaderAtom)
  145. {
  146.     m_ulTrackID = pTrackHeaderAtom->Get_TrackID();
  147. }
  148. else
  149. {
  150.     retVal = HXR_FAIL;
  151. }
  152.     }
  153.     if (SUCCEEDED(retVal))
  154.     {
  155. IHXCommonClassFactory* pClassFactory = NULL;
  156. CQTAtom* pChildAtom = NULL;
  157. if (pAtom)
  158. {
  159.     pAtom = pAtom->FindPresentChild(QT_mdia);
  160. }
  161. if (pAtom)
  162. {
  163.     pAtom = pAtom->FindPresentChild(QT_minf);
  164. }
  165. if (pAtom)
  166. {
  167.     pChildAtom = pAtom->FindPresentChild(QT_dinf);
  168. }
  169. retVal = pFileFormat->QueryInterface(
  170.     IID_IHXCommonClassFactory,
  171.     (void**) &pClassFactory);
  172. if (SUCCEEDED(retVal))
  173. {
  174.     retVal = m_DataRef.Init(pChildAtom, pClassFactory);
  175. }
  176. HX_RELEASE(pClassFactory);
  177.     }
  178.     if (retVal == HXR_OK)
  179.     {
  180. if (pAtom)
  181. {
  182.     pAtom = pAtom->FindPresentChild(QT_stbl);
  183. }
  184. retVal = m_SampleSize.Init(pAtom);
  185.     }
  186.     if (retVal == HXR_OK)
  187.     {
  188. retVal = m_SampleToChunk.Init(pAtom);
  189.     }
  190.     if (retVal == HXR_OK)
  191.     {
  192. retVal = m_TimeToSample.Init(pAtom);
  193.     }
  194.     if (retVal == HXR_OK)
  195.     {
  196. retVal = m_ChunkToOffset.Init(pAtom);
  197.     }
  198.     if (retVal == HXR_OK)
  199.     {
  200. retVal = m_SampleDesc.Init(pAtom);
  201.     }
  202.     if ((retVal == HXR_OK) && bIsStreamTrack)
  203.     {
  204. retVal = m_TrackInfo.Init(pFileFormat->GetContext(),
  205.   m_pTrackAtom,
  206.   &m_SampleDesc,
  207.   &pFileFormat->m_TrackManager,
  208.   &pFileFormat->m_MovieInfo);
  209.     }
  210.     if ((retVal == HXR_OK) && bIsStreamTrack)
  211.     {
  212. retVal = InitPacketizer(m_pPacketizer,
  213. pPacketizerFactory,
  214. pProtocol,
  215. &m_TrackInfo,
  216. &pFileFormat->m_MovieInfo,
  217. &pFileFormat->m_TrackManager,
  218. this,
  219. pFileFormat->GetContext());
  220.     }
  221.     if ((retVal == HXR_OK) && bIsStreamTrack)
  222.     {
  223. CQTAtom* pChildAtom = NULL;
  224. pChildAtom = m_pTrackAtom->FindPresentChild(QT_edts);
  225. retVal = m_TrackEdit.Init(
  226.     pChildAtom,
  227.     pFileFormat->m_MovieInfo.GetMovieTimeScale(),
  228.     m_TrackInfo.GetMediaTimeScale());
  229.     }
  230.     if ((retVal == HXR_OK) && bIsStreamTrack)
  231.     {
  232. retVal = Seek(0);
  233. if (retVal == HXR_STREAM_DONE)
  234. {
  235.     retVal = HXR_OK;
  236. }
  237.     }
  238.     HX_RELEASE(m_pTrackAtom);
  239.     return retVal;
  240. }
  241. /****************************************************************************
  242.  *  Close
  243.  */
  244. void CQTTrack::Close(void)
  245. {
  246.     m_PendingState = QTT_Offline;
  247.     HX_RELEASE(m_pTrackAtom);
  248.     HX_RELEASE(m_pFileFormat);
  249.     HX_RELEASE(m_pPacketAssembler);
  250.     HX_RELEASE(m_pReadFileNameBuffer);
  251.     HX_RELEASE(m_pFileSwitcher);
  252.     HX_RELEASE(m_pPacketizer);
  253.     HX_RELEASE(m_pClassFactory);
  254. }
  255. /****************************************************************************
  256.  *  Seek
  257.  */
  258. HX_RESULT CQTTrack::Seek(ULONG32 ulTime)
  259. {
  260.     if (m_pPacketizer)
  261.     {
  262. m_pPacketizer->Reset();
  263.     }
  264.     m_bTrackDone = !m_TrackEdit.EstablishByTime(ulTime);
  265.     if (!m_bTrackDone)
  266.     {
  267. m_bTrackDone = !SequenceToTime(m_TrackEdit,
  268.        m_TimeToSample,
  269.        m_SampleToChunk,
  270.        QTTRK_USE_KEY_FRAMES);
  271.     }
  272.     return m_bTrackDone ? HXR_STREAM_DONE : HXR_OK;
  273. }
  274. /****************************************************************************
  275.  *  GetPacket
  276.  */
  277. HX_RESULT CQTTrack::GetPacket(UINT16 uStreamNum)
  278. {
  279.     HX_RESULT retVal = HXR_STREAM_DONE;
  280.     m_uStreamNumber = uStreamNum;
  281.     if (m_pPacketizer)
  282.     {
  283. IHXPacket* pPacket = NULL;
  284. retVal = m_pPacketizer->GetPacket(pPacket);
  285. if (retVal != HXR_INCOMPLETE)
  286. {
  287.     m_pFileFormat->PacketReady(m_uStreamNumber, 
  288. retVal, 
  289. pPacket);
  290.     
  291.     HX_RELEASE(pPacket);
  292.     
  293.     return HXR_OK;
  294. }
  295. retVal = HXR_STREAM_DONE;
  296.     }
  297.     if (!m_bTrackDone)
  298.     {
  299. m_PendingState = QTT_SampleRead;
  300. // Locate Sample
  301. if (m_ChunkToOffset.EstablishByChunk(
  302. m_SampleToChunk.GetChunkNum()) &&
  303.     m_SampleSize.EstablishBySample(
  304. m_TimeToSample.GetSampleNumber(),
  305. m_SampleToChunk.GetChunkSampleNum()) &&
  306.     m_SampleDesc.EstablishByIdx(
  307. m_SampleToChunk.GetSampleDescIdx()) &&
  308.     m_DataRef.EstablishByIdx(
  309. m_SampleDesc.GetDataRefIdx()))
  310. {
  311.     ULONG32 ulFileOffset = m_ChunkToOffset.GetChunkOffset() +
  312.    m_SampleSize.GetChunkSampleOffset();
  313. #ifdef QTCONFIG_TRACK_CACHE
  314.     if (m_DataRef.GetDataRefName() == NULL)
  315.     {
  316. if (m_TrackCache.IsInPage(ulFileOffset, m_SampleSize.GetSampleSize()))
  317. {
  318.     IHXBuffer* pBuffer;
  319.     UINT32 ulPageOffset;
  320.     m_TrackCache.Get(ulFileOffset,
  321.      pBuffer,
  322.      ulPageOffset);
  323.     return ReturnPacket(HXR_OK,
  324. pBuffer,
  325. ulPageOffset, 
  326. m_SampleSize.GetSampleSize());
  327. }
  328.     }
  329. #endif // QTCONFIG_TRACK_CACHE
  330.     retVal = LoadData(
  331. m_DataRef.GetDataRefName(),
  332. ulFileOffset,
  333. m_SampleSize.GetSampleSize());
  334. }
  335. else
  336. {
  337.     retVal = ReturnPacket(retVal, NULL);
  338. }
  339.     }
  340.     else
  341.     {
  342. retVal = ReturnPacket(retVal, NULL);
  343.     }
  344.     return retVal;
  345. }
  346. /****************************************************************************
  347.  *  ComputeTrackSize
  348.  */
  349. HX_RESULT CQTTrack::ComputeTrackSize(ULONG32& ulTrackSizeOut)
  350. {
  351.     ULONG32 ulTrackSize = 0;
  352.     ULONG32 ulCurrentMediaTime = m_TrackEdit.GetMediaTime();
  353.     HX_RESULT retVal = Seek(0);
  354.     if (SUCCEEDED(retVal))
  355.     {
  356. do
  357. {
  358.     if (!m_SampleSize.EstablishBySample(
  359.     m_TimeToSample.GetSampleNumber(),
  360.     m_SampleToChunk.GetChunkSampleNum()))
  361.     {
  362. break;
  363.     }
  364.     ulTrackSize += m_SampleSize.GetSampleSize();
  365. } while (AdvanceSample(m_TrackEdit,
  366.        m_TimeToSample,
  367.        m_SampleToChunk));
  368. ulTrackSizeOut = ulTrackSize;
  369.     }
  370.     Seek(ulCurrentMediaTime);
  371.     return retVal;
  372. }
  373. /****************************************************************************
  374.  *  IHXThreadSafeMethods method
  375.  */
  376. /****************************************************************************
  377.  *  IsThreadSafe
  378.  */
  379. STDMETHODIMP_(UINT32)
  380. CQTTrack::IsThreadSafe()
  381. {
  382.     return HX_THREADSAFE_METHOD_FF_GETPACKET | HX_THREADSAFE_METHOD_FSR_READDONE;
  383. }
  384. /****************************************************************************
  385.  *  Protected Functions
  386.  */
  387. /****************************************************************************
  388.  *  InitPacketizer
  389.  */
  390. HX_RESULT CQTTrack::InitPacketizer(IHXPayloadFormatObject* &pPacketizer,
  391.    CQTPacketizerFactory* pPacketizerFactory,
  392.    const char* pProtocol,
  393.    CQT_TrackInfo_Manager* pTrackInfo,
  394.    CQT_MovieInfo_Manager* pMovieInfo,
  395.    CQTTrackManager* pTrackManager,
  396.    CQTTrack* pTrack,
  397.    IUnknown* pContext)
  398. {
  399.     HX_RESULT retVal = HXR_OK;
  400. #ifdef QTCONFIG_PACKETIZER_FACTORY
  401.     if (pPacketizerFactory)
  402.     {
  403. retVal = pPacketizerFactory->Construct(pPacketizer,
  404.        pProtocol,
  405.        pTrackInfo,
  406.        pMovieInfo,
  407.        pTrackManager,
  408.        pTrack,
  409.        pContext);
  410. if (retVal == HXR_NO_DATA)
  411. {
  412.     retVal = HXR_OK;
  413. }
  414.     }
  415.     if (SUCCEEDED(retVal))
  416.     {
  417. if (pPacketizer)
  418. {
  419.     IHXValues* pHeader = NULL;
  420.     retVal = pPacketizer->Init(pContext, TRUE);
  421.     if (SUCCEEDED(retVal))
  422.     {
  423. retVal = m_pFileFormat->BuildStreamHeader(pHeader,
  424.   this,
  425.   pTrackInfo,
  426.   pMovieInfo,
  427.   pTrackManager,
  428.   m_pClassFactory);
  429.     }
  430.     if (SUCCEEDED(retVal))
  431.     {
  432. retVal = pPacketizer->SetStreamHeader(pHeader);
  433.     }
  434.     HX_RELEASE(pHeader);
  435.     if (SUCCEEDED(retVal))
  436.     {
  437. retVal = pPacketizer->GetStreamHeader(pHeader);
  438.     }
  439.     if (SUCCEEDED(retVal))
  440.     {
  441. pTrackInfo->SetHeader(pHeader);
  442.     }
  443.     HX_RELEASE(pHeader);
  444. }
  445.     }
  446. #endif // QTCONFIG_PACKETIZER_FACTORY
  447.     return retVal;
  448. }
  449. /****************************************************************************
  450.  *  LoadData
  451.  */
  452. HX_RESULT CQTTrack::LoadData(IHXBuffer* pFileName,
  453.     ULONG32 ulOffset,
  454.     ULONG32 ulSize)
  455. {
  456.     HX_RELEASE(m_pReadFileNameBuffer);
  457.     m_pReadFileName = NULL;
  458. #ifdef _LOG_DATA_ACCESS
  459.     FILE* pf = fopen("C:\qt_access.txt", "a");
  460.     fprintf(pf, "%d %d %dn", m_ulTrackID, ulOffset, ulSize);
  461.     fclose(pf);
  462. #endif // _LOG_DATA_ACCESS
  463. #ifdef QTCONFIG_TRACK_CACHE
  464.     m_TrackCache.ReleasePage();
  465. #endif // QTCONFIG_TRACK_CACHE
  466.     m_ulReadSize = ulSize;
  467.     m_ulReadPageSize = ulSize;
  468.     m_ulReadPageOffset = ulOffset;
  469.     
  470.     if (pFileName)
  471.     {
  472. m_pReadFileNameBuffer = pFileName;
  473. pFileName->AddRef();
  474. m_pReadFileName = (char *) pFileName->GetBuffer();
  475.     }
  476. #ifdef QTCONFIG_TRACK_CACHE
  477.     else if (m_TrackCache.IsEnabled() && (ulSize < QTTRACKCACHE_PAGE_SIZE))
  478.     {
  479. m_ulReadPageSize = QTTRACKCACHE_PAGE_SIZE;
  480.     }
  481. #endif // QTCONFIG_TRACK_CACHE
  482.     return m_pFileSwitcher->Seek(   ulOffset,
  483.     FALSE,
  484.     (IHXFileResponse*) this,
  485.     m_pReadFileName);
  486. }
  487. /****************************************************************************
  488.  *  DataReady
  489.  */
  490. HX_RESULT CQTTrack::DataReady(HX_RESULT status, IHXBuffer *pBuffer)
  491. {
  492. #ifdef QTCONFIG_TRACK_CACHE
  493.     if (status == HXR_OK)
  494.     {
  495. if (m_ulReadPageSize > m_ulReadSize)
  496. {
  497.     m_TrackCache.SetPage(m_ulReadPageOffset, pBuffer);
  498. }
  499.     }
  500.     else
  501.     {
  502. if (m_TrackCache.IsEnabled())
  503. {
  504.     m_TrackCache.Enable(FALSE);
  505.     return LoadData(m_pReadFileNameBuffer,
  506.     m_ulReadPageOffset,
  507.     m_ulReadSize);
  508. }
  509.     }
  510. #endif // QTCONFIG_TRACK_CACHE
  511.     switch (m_PendingState)
  512.     {
  513.     case QTT_SegmentRead:
  514. m_PendingState = QTT_Offline;
  515. if (m_pPacketAssembler)
  516. {
  517.     return m_pPacketAssembler->SegmentReady(status, pBuffer,
  518.     0, m_ulReadSize);
  519. }
  520. break;
  521.     case QTT_SampleRead:
  522. m_PendingState = QTT_Offline;
  523. return ReturnPacket(status, pBuffer, 0, m_ulReadSize);
  524.     }
  525.     return HXR_UNEXPECTED;
  526. }
  527. /****************************************************************************
  528.  *  ReturnPacket
  529.  */
  530. HX_RESULT CQTTrack::ReturnPacket(HX_RESULT status, 
  531.  IHXBuffer *pBuffer)
  532. {
  533.     return ReturnPacket(status,
  534. pBuffer,
  535. 0,
  536. pBuffer ? pBuffer->GetSize() : 0);
  537. }
  538. /****************************************************************************
  539.  *  ReturnPacket
  540.  */
  541. HX_RESULT CQTTrack::ReturnPacket(HX_RESULT status, 
  542. IHXBuffer *pBuffer,
  543. ULONG32 ulOffset,
  544. ULONG32 ulSize)
  545. {
  546.     ULONG32 ulTime = (ULONG32) (m_TrackEdit.GetRealTime() + 0.5);
  547.     ULONG32 ulRTPTime = m_TrackEdit.GetMediaTime() + 
  548. m_TimeToSample.GetCompositionOffset();
  549.     IHXPacket* pPacket = NULL;
  550.     HX_RESULT retVal = HXR_OK;
  551.     if (pBuffer)
  552.     {
  553. #ifdef QTCONFIG_BFRAG
  554. if ((ulOffset != 0) || (ulSize != pBuffer->GetSize()))
  555. {
  556. #ifdef QTCONFIG_BFRAG_FACTORY
  557.     pBuffer = 
  558. m_pFileFormat->m_pBufferFragmentFactory->WrapFragment(
  559.     pBuffer, ulOffset, ulSize);
  560. #else // QTCONFIG_BFRAG_FACTORY
  561.     pBuffer = new CBufferFragment(pBuffer, ulOffset, ulSize);
  562.     
  563.     if (pBuffer)
  564.     {
  565. pBuffer->AddRef();
  566.     }
  567. #endif // QTCONFIG_BFRAG_FACTORY
  568. }
  569. else
  570. #else // QTCONFIG_BFRAG
  571. HX_ASSERT((ulOffset == 0) && (ulSize == pBuffer->GetSize()));
  572. #endif // QTCONFIG_BFRAG
  573. {
  574.     pBuffer->AddRef();
  575. }
  576.     }
  577.     // Form packet
  578.     if (status == HXR_OK)
  579.     {
  580. status = m_pClassFactory->CreateInstance(CLSID_IHXRTPPacket,
  581.  (void**) &pPacket);
  582.     }
  583.     if (pBuffer)
  584.     {
  585. if (status == HXR_OK)
  586. {
  587.     status = ((IHXRTPPacket*) pPacket)->SetRTP(
  588. pBuffer,
  589. ulTime,
  590. ulRTPTime,
  591. m_uStreamNumber,
  592. m_TimeToSample.IsOnSyncSample() ? 
  593.     (HX_ASM_SWITCH_ON | HX_ASM_SWITCH_OFF) :
  594.     HX_ASM_SWITCH_OFF,     // ASM Flags
  595. QTASM_MARKER_ON_RULE);
  596. }
  597. pBuffer->Release();
  598. pBuffer = NULL;
  599.     }
  600.     
  601.     if (status == HXR_OK)
  602.     {
  603. m_ulLastSampleDescIdx = m_SampleToChunk.GetSampleDescIdx();
  604. m_bTrackDone = !AdvanceSample(m_TrackEdit,
  605.       m_TimeToSample,
  606.       m_SampleToChunk);
  607.     }
  608.     else
  609.     {
  610. m_bTrackDone = TRUE;
  611.     }
  612.     if (m_pPacketizer)
  613.     {
  614. if (status == HXR_OK)
  615. {
  616.     m_pPacketizer->SetPacket(pPacket);
  617. }
  618. HX_RELEASE(pPacket);
  619. if (m_bTrackDone)
  620. {
  621.     m_pPacketizer->Flush();
  622. }
  623. status = m_pPacketizer->GetPacket(pPacket);
  624. if (status == HXR_INCOMPLETE)
  625. {
  626.     if (!m_bTrackDone)
  627.     {
  628. status = GetPacket(m_uStreamNumber);
  629. if (status == HXR_OK)
  630. {
  631.     return status;
  632. }
  633.     }
  634.     else
  635.     {
  636. status = HXR_STREAM_DONE;
  637.     }
  638. }
  639.     }
  640.     retVal = m_pFileFormat->PacketReady(m_uStreamNumber, status, pPacket);
  641.     HX_RELEASE(pPacket);
  642.     return retVal;
  643. }
  644. /****************************************************************************
  645.  *  SequenceToTime
  646.  */
  647. BOOL CQTTrack::SequenceToTime(CQT_TrackEdit_Manager &TrackEdit,
  648.      CQT_TimeToSample_Manager &TimeToSample,
  649.      CQT_SampleToChunk_Manager &SampleToChunk,
  650.      BOOL bUseNonKeyFrames)
  651. {
  652.     BOOL bOverSeek;
  653.     do
  654.     {
  655. bOverSeek = !( bUseNonKeyFrames ?
  656. TimeToSample.EstablishByMediaTime(
  657.     TrackEdit.GetMediaTime()) :
  658. TimeToSample.EstablishAtKeyByMediaTime(
  659.     TrackEdit.GetMediaTime()));
  660.     } while ((!bOverSeek) &&
  661.      TrackEdit.AdvanceByMediaTime(
  662. TimeToSample.GetLastMediaSyncTime(), bOverSeek) &&
  663.      (!bOverSeek));
  664.     if (!bOverSeek)
  665.     {
  666. bOverSeek = !SampleToChunk.EstablishBySample(
  667.     TimeToSample.GetSampleNumber());
  668.     }
  669.     return !bOverSeek;
  670. }
  671. /****************************************************************************
  672.  *  AdvanceSample
  673.  */
  674. BOOL CQTTrack::AdvanceSample(CQT_TrackEdit_Manager &TrackEdit,
  675.     CQT_TimeToSample_Manager &TimeToSample,
  676.     CQT_SampleToChunk_Manager &SampleToChunk)
  677. {
  678.     BOOL bStreamDone;
  679.     if (TrackEdit.AdvanceByMediaTime(
  680.     TimeToSample.GetSampleDuration(),
  681.     bStreamDone))
  682.     {
  683. // Advancement in time caused change in edit segment
  684. if (!bStreamDone)
  685. {
  686.     bStreamDone = !SequenceToTime(TrackEdit,
  687.   TimeToSample,
  688.   SampleToChunk,
  689.   QTTRK_USE_ANY_FRAME);
  690. }
  691.     }
  692.     else
  693.     {
  694. bStreamDone = ((!TimeToSample.AdvanceBySample()) ||
  695.        (!SampleToChunk.AdvanceBySample()));
  696.     }
  697.     return !bStreamDone;
  698. }
  699. /****************************************************************************
  700.  *  IHXFileResponse methods 
  701.  */
  702. /****************************************************************************
  703.  *  ReadDone
  704.  */
  705. STDMETHODIMP CQTTrack::ReadDone(HX_RESULT status,
  706. IHXBuffer* pBuffer)
  707. {
  708.     return DataReady(status, pBuffer);
  709. }
  710. /****************************************************************************
  711.  *  SeekDone
  712.  */
  713. STDMETHODIMP CQTTrack::SeekDone(HX_RESULT status)
  714. {
  715.     if (SUCCEEDED(status))
  716.     {
  717. return m_pFileSwitcher->Read( m_ulReadPageSize,
  718. (IHXFileResponse*) this,
  719. m_pReadFileName);
  720.     }
  721.     return DataReady(status, NULL);
  722. }
  723. /****************************************************************************
  724.  *  IUnknown methods
  725.  */
  726. /////////////////////////////////////////////////////////////////////////
  727. //  Method:
  728. // IUnknown::QueryInterface
  729. //
  730. STDMETHODIMP CQTTrack::QueryInterface(REFIID riid, void** ppvObj)
  731. {
  732.     if (IsEqualIID(riid, IID_IHXThreadSafeMethods))
  733.     {
  734. AddRef();
  735. *ppvObj = (IHXThreadSafeMethods*) this;
  736. return HXR_OK;
  737.     }
  738.     else if (IsEqualIID(riid, IID_IUnknown))
  739.     {
  740. AddRef();
  741. *ppvObj = this;
  742. return HXR_OK;
  743.     }
  744.     *ppvObj = NULL;
  745.     return HXR_NOINTERFACE;
  746. }
  747. /////////////////////////////////////////////////////////////////////////
  748. //  Method:
  749. // IUnknown::AddRef
  750. //
  751. STDMETHODIMP_(ULONG32) CQTTrack::AddRef()
  752. {
  753.     return InterlockedIncrement(&m_lRefCount);
  754. }
  755. /////////////////////////////////////////////////////////////////////////
  756. //  Method:
  757. // IUnknown::Release
  758. //
  759. STDMETHODIMP_(ULONG32) CQTTrack::Release()
  760. {
  761.     if (InterlockedDecrement(&m_lRefCount) > 0)
  762.     {
  763.         return m_lRefCount;
  764.     }
  765.     delete this;
  766.     return 0;
  767. }