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

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 NO_STREAM_SET 0xFFFF
  39. #define FSWCHR_MAX_CHILD_COUNT    20
  40. /****************************************************************************
  41.  * Includes
  42.  */
  43. #include "qtffplin.ver"
  44. #include "hxtypes.h"
  45. #include "hxcom.h"
  46. #include "hxstrutl.h"
  47. #include "hxcomm.h"
  48. #include "ihxpckts.h"
  49. #include "hxfiles.h"
  50. #include "hxformt.h"
  51. #include "hxplugn.h"
  52. #include "hxpends.h"
  53. #include "hxengin.h"
  54. #include "hxerror.h"
  55. #include "hxupgrd.h"
  56. #include "hxmon.h"
  57. #include "hxbrdcst.h"
  58. #include "hxcore.h"
  59. #include "hxprefs.h"
  60. #include "defslice.h"
  61. #include "qtres.h"
  62. #include "hxsdesc.h"
  63. #include "hxstring.h"
  64. #include "qtffplin.h"
  65. #include "netbyte.h"
  66. #include "hxver.h"
  67. #include "hxxres.h"
  68. #include "hxxrsmg.h"
  69. #include "dbcs.h"
  70. #include "sdpchunk.h"
  71. #include "sdppyldinfo.h"
  72. #include "qtffrefcounter.h"
  73. #include "qttrack.h"
  74. #include "qtpktasm.h"
  75. /****************************************************************************
  76.  * Constants
  77.  */
  78. #define QTFF_AU_PREFIX "FileFormat/"
  79. #define QTFF_AU_PREFIX_SIZE (sizeof(QTFF_AU_PREFIX) - 1)
  80. #define MAX_EXTENSION_SIZE 256
  81. #define QTBUFFERFRAGMENT_POOL_SIZE     50
  82. #define QTBUFFERFRAGMENT_INITIAL_POOL_SIZE  5
  83. const char* const CQTFileFormat::zm_pDescription    = "RealNetworks Mpeg4 File Format Plugin";
  84. const char* const CQTFileFormat::zm_pCopyright      = HXVER_COPYRIGHT;
  85. const char* const CQTFileFormat::zm_pMoreInfoURL    = HXVER_MOREINFO;
  86. #define EXT_3GP     "3gp"
  87. #define EXT_3G2     "3g2"
  88. #define EXT_MP4     "mp4"
  89. #define EXT_M4A     "m4a"
  90. #define EXT_MOV     "mov", "qt"
  91. #define ONM_3GP     "3GPP-MP4 Files (*.3gp, *.3g2)"
  92. #define ONM_MP4     "MP4 Files (*.mp4)"
  93. #define ONM_MOV     "QuickTime Files (*.mov, *.qt)"
  94. const char* const CQTFileFormat::zm_pFileMimeTypes[]  = {"application/x-pn-quicktime-stream", "audio/3gpp", "video/3gpp", NULL};
  95. const char* const CQTFileFormat::zm_pFileExtensions[] = {EXT_MOV, EXT_MP4, EXT_3GP, EXT_3G2, EXT_M4A, NULL};
  96. const char* const CQTFileFormat::zm_pFileOpenNames[] = {ONM_MOV, ONM_MP4, ONM_3GP, NULL};
  97. const char* const CQTFileFormat::zm_pPacketFormats[]  = {"rtp", "rdt", NULL};
  98. #define WIDTH_METANAME "Width"
  99. #define HEIGHT_METANAME "Height"
  100. /****************************************************************************
  101.  * Globals
  102.  */
  103. g_base_nRefCount_qtff_TypeModifier INT32 g_base_nRefCount_qtff = 0;
  104. /****************************************************************************
  105.  *  Constructor/Destructor
  106.  */
  107. CQTFileFormat::CQTFileFormat()
  108.     : m_lRefCount(0)
  109.     , m_pContext(NULL)
  110.     , m_pFFResponse(NULL)
  111.     , m_pClassFactory(NULL)
  112.     , m_pScheduler(NULL)
  113.     , m_pRequest(NULL)
  114.     , m_pFileSwitcher(NULL)
  115.     , m_pAtomizer(NULL)
  116.     , m_pPacketAssembler(NULL)
  117.     , m_State(QTFF_Offline)
  118.     , m_pPacketCache(NULL)
  119.     , m_uNextPacketStreamNum(NO_STREAM_SET)
  120.     , m_ulPendingSeekTime(0)
  121.     , m_pErrorMessages(NULL)
  122.     , m_bQTLicensed(FALSE)
  123.     , m_bMP4Licensed(FALSE)
  124.     , m_uFormatFlavor(MAX_QTFORMAT_FLAVOR)
  125.     , m_bViewSourceRequest(FALSE)
  126. #ifdef QTCONFIG_BFRAG_FACTORY
  127.     , m_pBufferFragmentFactory(NULL)
  128. #endif // QTCONFIG_BFRAG_FACTORY
  129.     , m_ulStreamMetaInfoMask(META_INFO_NONE)
  130. {
  131.     g_nRefCount_qtff++;
  132. }
  133. CQTFileFormat::~CQTFileFormat()
  134. {
  135.     Close();
  136.     g_nRefCount_qtff--;
  137. }
  138. /************************************************************************
  139.  *  IHXPlugin methods
  140.  */
  141. /************************************************************************
  142.  *  IHXPlugin::InitPlugin
  143.  *  Purpose:
  144.  *    Initializes the plugin for use. This interface must always be
  145.  *    called before any other method is called. This is primarily needed 
  146.  *    so that the plugin can have access to the context for creation of
  147.  *    IHXBuffers and IMalloc.
  148.  */
  149. STDMETHODIMP CQTFileFormat::InitPlugin(IUnknown* /*IN*/ pContext)
  150. {
  151.     HX_RESULT retVal = HXR_OK;
  152.     if (pContext)
  153.     {
  154. m_pContext = pContext;
  155. m_pContext->AddRef();
  156.     }
  157.     else
  158.     {
  159. retVal = HXR_INVALID_PARAMETER;
  160.     }
  161.     /*
  162.      * Check for license
  163.      */     
  164.     if (SUCCEEDED(retVal))
  165.     {
  166. retVal = CheckLicense();
  167.     }
  168.     if (SUCCEEDED(retVal))
  169.     {
  170. HX_ASSERT(!m_pErrorMessages);
  171. pContext->QueryInterface(IID_IHXErrorMessages, 
  172.     (void**) &m_pErrorMessages);
  173. retVal = pContext->QueryInterface(IID_IHXCommonClassFactory,
  174.     (void**)&m_pClassFactory);
  175.     }
  176.     if (SUCCEEDED(retVal))
  177.     {
  178. retVal = pContext->QueryInterface(IID_IHXScheduler,
  179.     (void**)&m_pScheduler);
  180.     }
  181.     return retVal;
  182. }
  183. /************************************************************************
  184.  *  IHXPlugin::GetPluginInfo
  185.  *  Purpose:
  186.  *    Returns the basic information about this plugin. Including:
  187.  *
  188.  *    bLoadMultiple whether or not this plugin DLL can be loaded
  189.  * multiple times. All File Formats must set
  190.  * this value to TRUE.
  191.  *    pDescription which is used in about UIs (can be NULL)
  192.  *    pCopyright which is used in about UIs (can be NULL)
  193.  *    pMoreInfoURL which is used in about UIs (can be NULL)
  194.  */
  195. STDMETHODIMP CQTFileFormat::GetPluginInfo
  196. (
  197.     REF(BOOL) bLoadMultiple,
  198.     REF(const char*) pDescription,
  199.     REF(const char*) pCopyright,
  200.     REF(const char*) pMoreInfoURL,
  201.     REF(ULONG32) ulVersionNumber
  202. )
  203. {
  204.     bLoadMultiple = TRUE;   // Must be true for file formats.
  205.     pDescription    = (const char*) zm_pDescription;
  206.     pCopyright     = (const char*) zm_pCopyright;
  207.     pMoreInfoURL    = (const char*) zm_pMoreInfoURL;
  208.     ulVersionNumber = TARVER_ULONG32_VERSION;
  209.     return HXR_OK;
  210. }
  211. /************************************************************************
  212.  *  IHXFileFormatObject methods
  213.  */
  214. /************************************************************************
  215.  *  GetFileFormatInfo
  216.  *  Purpose:
  217.  *    If this object is a file format object this method returns
  218.  *    information vital to the instantiation of file format plugins.
  219.  *    If this object is not a file format object, it should return
  220.  *    HXR_UNEXPECTED.
  221.  */
  222. STDMETHODIMP CQTFileFormat::GetFileFormatInfo
  223. (
  224.     REF(const char**) /*OUT*/ pFileMimeTypes,
  225.     REF(const char**) /*OUT*/ pFileExtensions,
  226.     REF(const char**) /*OUT*/ pFileOpenNames
  227. )
  228. {
  229.     pFileMimeTypes  = (const char**) zm_pFileMimeTypes;
  230.     pFileExtensions = (const char**) zm_pFileExtensions;
  231.     pFileOpenNames  = (const char**) zm_pFileOpenNames;
  232.     return HXR_OK;
  233. }
  234. /************************************************************************
  235.  *  InitFileFormat
  236.  */
  237. STDMETHODIMP CQTFileFormat::InitFileFormat
  238. (
  239.     IHXRequest* /*IN*/ pRequest, 
  240.     IHXFormatResponse* /*IN*/ pFileFormatResponse,
  241.     IHXFileObject* /*IN*/  pFileObject
  242. )
  243. {
  244.     HX_RESULT retVal = HXR_OK;
  245.     if (m_State != QTFF_Offline)
  246.     {
  247. return HXR_UNEXPECTED;
  248.     }
  249.     m_State = QTFF_Init;
  250.     if ((pFileFormatResponse == NULL) ||
  251. (pFileObject == NULL))
  252.     {
  253. retVal = HXR_FAIL;
  254.     }
  255.     HX_RELEASE(m_pFFResponse);
  256.     m_pFFResponse = pFileFormatResponse;
  257.     m_pFFResponse->AddRef();
  258.     HX_RELEASE(m_pRequest);
  259.     m_pRequest = pRequest;
  260.     if (m_pRequest)
  261.     {
  262. m_pRequest->AddRef();
  263.     }
  264.     if (SUCCEEDED(retVal) && m_pRequest)
  265.     {
  266. IHXValues* pRequestHeaders = NULL;
  267. if (SUCCEEDED(m_pRequest->GetRequestHeaders(pRequestHeaders)) &&
  268.     pRequestHeaders)
  269. {
  270.     ULONG32 ulVal = 0;
  271.     if (SUCCEEDED(pRequestHeaders->GetPropertyULONG32(
  272.     "ViewSourceInfoHeaders",
  273.     ulVal)))
  274.     {
  275. m_bViewSourceRequest = ((ulVal == 0) ? FALSE : TRUE);
  276.     }
  277.     IHXBuffer* pBuffer = NULL;
  278.     retVal = pRequestHeaders->GetPropertyCString("AcceptMetaInfo",
  279.      pBuffer);
  280.     if(SUCCEEDED(retVal))
  281.     {
  282. retVal = ExtractAcceptMetaInfo(pBuffer);
  283.     }
  284.             // We want to proceed even if metadata fails.
  285.             retVal = HXR_OK;
  286.     HX_RELEASE(pBuffer);
  287. }
  288. HX_RELEASE(pRequestHeaders);
  289.     }
  290.     if (SUCCEEDED(retVal))
  291.     {
  292. HX_RELEASE(m_pFileSwitcher);
  293. HX_RELEASE(m_pAtomizer);
  294. #ifdef QTCONFIG_FSWITCHER
  295. m_pFileSwitcher = (IHXFileSwitcher*) new CFileSwitcher();
  296. #else // QTCONFIG_FSWITCHER
  297. m_pFileSwitcher = (IHXFileSwitcher*) new CFileSwitcherPassthrough();
  298. #endif // QTCONFIG_FSWITCHER
  299. if (m_pFileSwitcher)
  300. {
  301.     m_pFileSwitcher->AddRef();
  302. }
  303. else
  304. {
  305.     retVal = HXR_OUTOFMEMORY;
  306. }
  307.     }
  308.     if (SUCCEEDED(retVal))
  309.     {
  310. m_pAtomizer = new CAtomizer();
  311. if (m_pAtomizer)
  312. {
  313.     m_pAtomizer->AddRef();
  314. }
  315. else
  316. {
  317.     retVal = HXR_OUTOFMEMORY;
  318. }
  319.     }
  320.     if (SUCCEEDED(retVal))
  321.     {
  322. m_pPacketAssembler = new CQTPacketAssembler();
  323. if (m_pPacketAssembler)
  324. {
  325.     m_pPacketAssembler->AddRef();
  326.     retVal = m_pPacketAssembler->Init(this);
  327. }
  328. else
  329. {
  330.     retVal = HXR_OUTOFMEMORY;
  331. }
  332.     }
  333.     if (SUCCEEDED(retVal))
  334.     {
  335. retVal = m_pFileSwitcher->Init(pFileObject,
  336.        HX_FILE_READ | HX_FILE_BINARY,
  337.        (IHXFileResponse*) this,
  338.        m_pContext,
  339.        FSWCHR_MAX_CHILD_COUNT);
  340.     }
  341.     if (FAILED(retVal))
  342.     {
  343. m_State = QTFF_Error;
  344.     }
  345.     return retVal;
  346. }
  347. HX_RESULT
  348. CQTFileFormat::ExtractAcceptMetaInfo(IHXBuffer* pRequestedInfoBuffer)
  349. {
  350.     HX_RESULT res = HXR_OK;
  351.     if(!pRequestedInfoBuffer)
  352.     {
  353. res = HXR_POINTER;
  354. HX_ASSERT(FALSE);
  355. return res;
  356.     }
  357.     const char* pRequestedInfo = NULL;
  358.     if (pRequestedInfoBuffer)
  359.     {
  360. pRequestedInfo = (const char*) pRequestedInfoBuffer->GetBuffer();
  361.     }
  362.     if(*pRequestedInfo == '*')
  363.     {
  364. m_ulStreamMetaInfoMask |= META_INFO_ALL;
  365.     }
  366. #ifdef QTCONFIG_SERVER
  367.     else if (pRequestedInfo)
  368.     {     
  369. const char* pName;
  370. ULONG32 ulNameLength;
  371. // Set requested Meta Info
  372. do
  373. {
  374.     pName = pRequestedInfo;
  375.     
  376.     while ((*pRequestedInfo != '') &&
  377.    (*pRequestedInfo != ','))
  378.     {
  379. pRequestedInfo++;
  380.     }
  381.     
  382.     ulNameLength = (ULONG32) (pRequestedInfo - pName);
  383.     if (ulNameLength > 0)
  384.     {
  385. if ((strlen(WIDTH_METANAME) == ulNameLength) &&
  386.     (strncmp(pName, WIDTH_METANAME, ulNameLength) == 0))
  387. {
  388.     m_ulStreamMetaInfoMask |= META_INFO_WIDTH;
  389. }
  390. else if ((strlen(HEIGHT_METANAME) == ulNameLength) &&
  391.  (strncmp(pName, HEIGHT_METANAME, ulNameLength) == 0))
  392. {
  393.     m_ulStreamMetaInfoMask |= META_INFO_HEIGHT;
  394. }
  395.     }
  396.     if (*pRequestedInfo == '')
  397.     {
  398. break;
  399.     }
  400.     pRequestedInfo++;
  401. } while (TRUE);
  402.     } 
  403. #endif // QTCONFIG_SERVER
  404.     return res;
  405. }
  406. HX_RESULT CQTFileFormat::MakeFileHeader(HX_RESULT status)
  407. {
  408.     HX_RESULT retVal;
  409.     IHXValues* pHeader = NULL;
  410.     IHXBuffer* pTitle = NULL;
  411.     // Check the license
  412. #ifdef QTCONFIG_SERVER
  413.     if(SUCCEEDED(status))
  414.     {
  415.         switch(m_TrackManager.GetFType())
  416.         {
  417.             case QT_FTYPE_QT:
  418.             case QT_FTYPE_UNKNOWN:
  419.             {
  420.                 if(!m_bQTLicensed)
  421.                 {
  422.                     ReportError(IDS_ERR_QT_NOTLICENSED, HXR_NOT_LICENSED);
  423.                     return m_pFFResponse->FileHeaderReady(
  424.                         HXR_NOT_LICENSED, NULL);
  425.                 }
  426.                 break;
  427.             }
  428.             case QT_FTYPE_MP4:
  429.             {
  430.                 if(!m_bMP4Licensed)
  431.                 {
  432.                     ReportError(IDS_ERR_MP4_NOTLICENSED, HXR_NOT_LICENSED);
  433.                     return m_pFFResponse->FileHeaderReady(
  434.                         HXR_NOT_LICENSED, NULL);
  435.                 }
  436.                 break;
  437.             }
  438.         }
  439.     }
  440. #endif // QTCONFIG_SERVER
  441.     // Create needed buffers
  442.     if (SUCCEEDED(status))
  443.     {
  444. status = m_pClassFactory->CreateInstance(CLSID_IHXValues,
  445.  (void**) &pHeader);
  446.     }
  447.     
  448.     if (SUCCEEDED(status))
  449.     {
  450. status = m_pClassFactory->CreateInstance(CLSID_IHXBuffer,
  451.  (void**) &pTitle);
  452.     }
  453.     // Set Title
  454.     if (SUCCEEDED(status) && (m_MovieInfo.GetNameLength() > 0))
  455.     {
  456. UCHAR* pTitleMem;
  457. ULONG32 ulTitleMemLength = 0;
  458. status = pTitle->SetSize(m_MovieInfo.GetNameLength() + 1);
  459. if (SUCCEEDED(status))
  460. {
  461.     pTitle->Get(pTitleMem, ulTitleMemLength);
  462.     memcpy(pTitleMem, m_MovieInfo.GetName(), ulTitleMemLength - 1); /* Flawfinder: ignore */
  463.     pTitleMem[ulTitleMemLength - 1] = '';
  464.     pHeader->SetPropertyBuffer("Title", pTitle);
  465. }
  466.     }
  467.     HX_RELEASE(pTitle);
  468.     if (SUCCEEDED(status))
  469.     {
  470. status = GetSessionIdentity(pHeader, &m_MovieInfo);
  471.     }
  472. #ifdef QTCONFIG_ALTERNATE_STREAMS
  473.     // Set stream groupings
  474.     if (SUCCEEDED(status))
  475.     {
  476. UINT16 uStrmIdx;
  477. ULONG32 ulGroupID;
  478. ULONG32 ulGroupBitrate;
  479. CQTTrack* pTrack;
  480. IHXValues* pGroupInfo = NULL;
  481. for (uStrmIdx = 0; 
  482.      uStrmIdx < m_TrackManager.GetNumStreams();
  483.      uStrmIdx++)
  484. {
  485.     pTrack = m_TrackManager.GetStreamTrack(uStrmIdx);
  486.     if (pTrack->m_TrackInfo.GetSDPLength() > 0)
  487.     {
  488. retVal = SDPParseChunk(
  489.     (char*) pTrack->m_TrackInfo.GetSDP(),
  490.     pTrack->m_TrackInfo.GetSDPLength(),
  491.     pGroupInfo,
  492.     m_pClassFactory,
  493.     SDPCTX_Group,
  494.     FALSE);
  495. if (pGroupInfo &&
  496.     (pGroupInfo->GetPropertyULONG32("AlternateGroupID",
  497.     ulGroupID)
  498.      == HXR_OK))
  499. {
  500.     if (pGroupInfo->GetPropertyULONG32("AlternateGroupBitrate",
  501.        ulGroupBitrate)
  502. != HXR_OK)
  503.     {
  504. ulGroupBitrate = 0;
  505.     }
  506.     status = m_TrackManager.AddStreamToGroup(
  507. uStrmIdx,
  508. (UINT16) ulGroupID,
  509. ulGroupBitrate);
  510. }
  511.    
  512. HX_RELEASE(pGroupInfo);
  513. if (FAILED(status))
  514. {
  515.     break;
  516. }
  517.     }
  518. }
  519.     }
  520.     // Make Default subscriptions
  521.     if (SUCCEEDED(status))
  522.     {
  523. status = m_TrackManager.SubscribeDefault();
  524.     }
  525.     // If we are running in player, eliminate inactive stream tracks
  526.     if (SUCCEEDED(status))
  527.     {
  528. IHXClientEngine *pPlayer = NULL;
  529. if (SUCCEEDED(m_pContext->QueryInterface(IID_IHXClientEngine, 
  530.  (void**) &pPlayer)))
  531. {
  532.     // Running in player
  533.     status = m_TrackManager.RemoveInactiveStreams();
  534. }
  535. HX_RELEASE(pPlayer);
  536.     }
  537. #endif // QTCONFIG_ALTERNATE_STREAMS
  538.     // Set General properties, Stream Count and duration
  539.     if (SUCCEEDED(status))
  540.     {
  541. pHeader->SetPropertyULONG32("IsRealDataType", 0);
  542. pHeader->SetPropertyULONG32("StreamCount",  
  543.     m_TrackManager.GetNumStreams());
  544. pHeader->SetPropertyULONG32("Duration",
  545.     (ULONG32) ((1000.0 * ((double) m_MovieInfo.GetMovieDuration())) /
  546.                m_MovieInfo.GetMovieTimeScale()));
  547.     }
  548.     // Set the licensing information: Basically this information is used by the
  549.     // Broadcast Receiver plug-in to check and see if the RealServer is actually
  550.     // licensed to receive this content
  551. #ifdef QTCONFIG_SERVER
  552.     if(SUCCEEDED(status) && (!m_bViewSourceRequest))
  553.     {
  554.         switch(m_TrackManager.GetFType())
  555.         {
  556.             case QT_FTYPE_QT:
  557.             case QT_FTYPE_UNKNOWN:
  558.             {
  559.                 IHXBuffer* pFileTypeBuf = NULL;
  560.                 IHXBuffer* pLicenseKeyBuf = NULL;
  561.                 m_pClassFactory->CreateInstance(CLSID_IHXBuffer, (void**)&pFileTypeBuf);
  562.                 m_pClassFactory->CreateInstance(CLSID_IHXBuffer, (void**)&pLicenseKeyBuf);
  563.                 pFileTypeBuf->Set((const BYTE*)"QuickTime", strlen("QuickTime") + 1);
  564.                 pLicenseKeyBuf->Set((const BYTE*)REGISTRY_QUICKTIME_ENABLED, strlen(REGISTRY_QUICKTIME_ENABLED) + 1);
  565.                 pHeader->SetPropertyCString("FileType", pFileTypeBuf);
  566.                 pHeader->SetPropertyCString("LicenseKey", pLicenseKeyBuf);
  567.                 pHeader->SetPropertyULONG32("DefaultLicenseValue", LICENSE_QUICKTIME_ENABLED);
  568.                 HX_RELEASE(pFileTypeBuf);
  569.                 HX_RELEASE(pLicenseKeyBuf);
  570.                 break;
  571.             }
  572.             case QT_FTYPE_MP4:
  573.             {
  574.                 IHXBuffer* pFileTypeBuf = NULL;
  575.                 IHXBuffer* pLicenseKeyBuf = NULL;
  576.                 m_pClassFactory->CreateInstance(CLSID_IHXBuffer, (void**)&pFileTypeBuf);
  577.                 m_pClassFactory->CreateInstance(CLSID_IHXBuffer, (void**)&pLicenseKeyBuf);
  578.                 pFileTypeBuf->Set((const BYTE*)"MPEG4", strlen("MPEG4") + 1);
  579.                 pLicenseKeyBuf->Set((const BYTE*)REGISTRY_REALMP4_ENABLED, strlen(REGISTRY_REALMP4_ENABLED) + 1);
  580.                 pHeader->SetPropertyCString("FileType", pFileTypeBuf);
  581.                 pHeader->SetPropertyCString("LicenseKey", pLicenseKeyBuf);
  582.                 pHeader->SetPropertyULONG32("DefaultLicenseValue", LICENSE_REALMP4_ENABLED);
  583.                 HX_RELEASE(pFileTypeBuf);
  584.                 HX_RELEASE(pLicenseKeyBuf);
  585.                 break;
  586.             }
  587.         }
  588.     }
  589. #endif // QTCONFIG_SERVER
  590.     // Set Requested Meta Information
  591.     if (SUCCEEDED(status))
  592.     {
  593. IHXValues* pHeaders = NULL;
  594. IHXBuffer* pBuffer = NULL;
  595. if (m_pRequest &&
  596.     (m_pRequest->GetRequestHeaders(pHeaders) == HXR_OK) &&
  597.     pHeaders)
  598. {     
  599.     pHeaders->Release();
  600. }
  601. status = AddMetaInfo(pHeader);
  602. // We no longer need the request so release it
  603. HX_RELEASE(m_pRequest);
  604.     }
  605.     // Set View Source specific information
  606. #ifdef HELIX_FEATURE_VIEWSOURCE
  607.     if (SUCCEEDED(status) && m_bViewSourceRequest)
  608.     {
  609. IHXBuffer* pCStringBuffer = NULL;
  610. status = m_pClassFactory->CreateInstance(CLSID_IHXBuffer,
  611.  (void**) &pCStringBuffer);
  612. if (SUCCEEDED(status))
  613. {
  614.     const char* pString = "Not Hinted";
  615.     if (m_TrackManager.IsHinted())
  616.     {
  617. pString = "Hinted";
  618.     }
  619.     status = pCStringBuffer->Set((UINT8*) pString, strlen(pString) + 1);
  620. }
  621. if (SUCCEEDED(status))
  622. {
  623.     status = pHeader->SetPropertyCString("Characteristic", pCStringBuffer);
  624. }
  625. HX_RELEASE(pCStringBuffer);
  626. if (SUCCEEDED(status))
  627. {
  628.     status = pHeader->SetPropertyULONG32("ViewSourceInfoHeaders", 1);
  629. }
  630.     }
  631. #endif // HELIX_FEATURE_VIEWSOURCE
  632.     if (FAILED(status))
  633.     {
  634. HX_RELEASE(pHeader);
  635.     }
  636.     retVal = m_pFFResponse->FileHeaderReady(status, pHeader);
  637.     HX_RELEASE(pHeader);
  638.     return retVal;
  639. }
  640. HX_RESULT CQTFileFormat::ObtainStreamHeader(UINT16 unStreamNumber,
  641.     IHXValues* &pHeader)
  642. {
  643.     HX_RESULT retVal = HXR_OK;
  644.     CQTTrack* pTrack = NULL;
  645.     
  646.     pHeader = NULL;
  647.     // Check Entry requirements
  648.     if (m_State != QTFF_Ready)
  649.     {
  650. retVal = HXR_UNEXPECTED;
  651.     }
  652.     if (SUCCEEDED(retVal))
  653.     {
  654. retVal = HXR_INVALID_PARAMETER;
  655. if (unStreamNumber < m_TrackManager.GetNumStreams())
  656. {
  657.     retVal = HXR_OK;
  658. }
  659.     }
  660.     // See if made header is already available
  661.     if (SUCCEEDED(retVal))
  662.     {
  663. pTrack = m_TrackManager.GetStreamTrack(unStreamNumber);
  664. if (pTrack->m_TrackInfo.GetHeader(pHeader) != HXR_OK)
  665. {
  666.     retVal = BuildStreamHeader(pHeader,
  667.        pTrack,
  668.        &pTrack->m_TrackInfo,
  669.        &m_MovieInfo,
  670.        &m_TrackManager,
  671.        m_pClassFactory);
  672. }
  673.     }
  674.     if (SUCCEEDED(retVal))
  675.     {
  676. HX_ASSERT(pHeader);
  677. pHeader->SetPropertyULONG32("StreamNumber", unStreamNumber);
  678.     }
  679.     return retVal;
  680. }
  681. HX_RESULT CQTFileFormat::BuildStreamHeader(IHXValues* &pHeader,
  682.    CQTTrack* pTrack,
  683.    CQT_TrackInfo_Manager* pTrackInfo,
  684.    CQT_MovieInfo_Manager* pMovieInfo,
  685.    CQTTrackManager* pTrackManager,
  686.    IHXCommonClassFactory* pClassFactory)
  687. {
  688.     IHXBuffer* pName = NULL;
  689.     IHXBuffer* pASMRuleBook = NULL;
  690.     IHXBuffer* pMimeType = NULL;
  691.     ULONG32 ulPayloadType = QT_BAD_PAYLOAD;
  692.     ULONG32 ulAvgBitRate = 0;
  693.     ULONG32 ulMaxBitRate = 0;
  694.     ULONG32 ulPreroll = 0;
  695.     ULONG32 ulPredata = 0;
  696.     ULONG32 ulWidth = 0;
  697.     ULONG32 ulHeight = 0;
  698.     ULONG32 ulChannels = 0;
  699.     HX_RESULT retVal = HXR_OK;
  700.     // Create needed buffers
  701.     if (!pHeader)
  702.     {
  703. retVal = pClassFactory->CreateInstance(CLSID_IHXValues,
  704.  (void**) &pHeader);
  705.     }
  706.     if (SUCCEEDED(retVal))
  707.     {
  708. retVal = pClassFactory->CreateInstance(CLSID_IHXBuffer,
  709.  (void**) &pName);
  710.     }
  711.     if (SUCCEEDED(retVal))
  712.     {
  713. retVal = pClassFactory->CreateInstance(CLSID_IHXBuffer,
  714.  (void**) &pASMRuleBook);
  715.     }
  716.     // Set Stream Name
  717.     if (SUCCEEDED(retVal) && (pTrackInfo->GetNameLength() > 0))
  718.     {
  719. UCHAR* pNameMem;
  720. ULONG32 ulNameMemLength = 0;
  721. retVal = pName->SetSize(pTrackInfo->GetNameLength() + 1);
  722. if (SUCCEEDED(retVal))
  723. {
  724.     pName->Get(pNameMem, ulNameMemLength);
  725.     memcpy(pNameMem, pTrackInfo->GetName(), /* Flawfinder: ignore */
  726.    ulNameMemLength - 1);
  727.     pNameMem[ulNameMemLength - 1] = '';
  728.     pHeader->SetPropertyCString("StreamName", pName);
  729. }
  730.     }
  731.     HX_RELEASE(pName);
  732.     // Set Opaque Data - if any
  733.     if (SUCCEEDED(retVal) && (pTrackInfo->GetOpaqueDataLength() > 0))
  734.     {
  735. IHXBuffer* pOpaqueData = NULL;
  736. retVal = pClassFactory->CreateInstance(CLSID_IHXBuffer,
  737.        (void**) &pOpaqueData);
  738. if (SUCCEEDED(retVal))
  739. {
  740.     UCHAR* pOpaqueDataMem;
  741.     ULONG32 ulOpaqueDataLength = 0;
  742.     retVal = pOpaqueData->SetSize(pTrackInfo->GetOpaqueDataLength());
  743.     if (SUCCEEDED(retVal))
  744.     {
  745. pOpaqueData->Get(pOpaqueDataMem, ulOpaqueDataLength);
  746. memcpy(pOpaqueDataMem, /* Flawfinder: ignore */
  747.        pTrackInfo->GetOpaqueData(),
  748.        ulOpaqueDataLength);
  749. pHeader->SetPropertyBuffer("OpaqueData", pOpaqueData);
  750.     }
  751. }
  752. HX_RELEASE(pOpaqueData);
  753.     }
  754.     if (SUCCEEDED(retVal))
  755.     {
  756. retVal = GetPayloadIdentity(pHeader, pTrack, pTrackInfo);
  757.     }
  758.     
  759.     // Set Duration, AvgBitRate and Preroll
  760.     if (SUCCEEDED(retVal))
  761.     {
  762. ULONG32 ulDuration;
  763. ulDuration = (ULONG32) ((pTrackInfo->GetTrackDuration()
  764.  * 1000.0)
  765. / pMovieInfo->GetMovieTimeScale());
  766. ulAvgBitRate = pTrackInfo->GetAvgBitrate();
  767. ulMaxBitRate = pTrackInfo->GetMaxBitrate();
  768. ulPreroll = pTrackInfo->GetPreroll();
  769. ulPredata = pTrackInfo->GetPredata();
  770. ulWidth = pTrackInfo->GetTrackWidth();
  771. ulHeight= pTrackInfo->GetTrackHeight();
  772. if ((ulAvgBitRate == 0) && (ulDuration > 0))
  773. {
  774.     ULONG32 ulTrackSize = pTrackInfo->GetTrackSize();
  775.     if (ulTrackSize == 0)
  776.     {
  777.     pTrack->ComputeTrackSize(ulTrackSize);
  778. }
  779.     ulAvgBitRate = (ULONG32) ((((double) ulTrackSize) * 8000.0) 
  780.       / ulDuration + 0.5);
  781. }
  782. if (ulAvgBitRate == 0)
  783. {
  784.     ulAvgBitRate = SDPMapPayloadToBitrate(ulPayloadType);
  785. }
  786. pHeader->SetPropertyULONG32("Duration", ulDuration);
  787. if (ulAvgBitRate != 0)
  788. {
  789.     pHeader->SetPropertyULONG32("AvgBitRate", ulAvgBitRate);
  790. }
  791. if (ulMaxBitRate != 0)
  792. {
  793.     pHeader->SetPropertyULONG32("MaxBitRate", ulMaxBitRate);
  794. }
  795. if (ulPreroll != 0)
  796. {
  797.     pHeader->SetPropertyULONG32("Preroll", ulPreroll);
  798. }
  799. if (ulPredata != 0)
  800. {
  801.     pHeader->SetPropertyULONG32("Predata", ulPredata);
  802. }
  803. if(ulWidth != 0)
  804. {
  805.     pHeader->SetPropertyULONG32(WIDTH_METANAME, ulWidth);
  806. }
  807. if(ulHeight != 0)
  808. {
  809.     pHeader->SetPropertyULONG32(HEIGHT_METANAME, ulHeight);
  810. }
  811.     }
  812.     if (SUCCEEDED(retVal))
  813.     {
  814. // .mp4 and .mov files may produce streams with out-of-order time stamps
  815. // Client core does not normally expect this in RDT protocol so set this
  816. // property to alert client core of this fact.
  817. pHeader->SetPropertyULONG32("HasOutOfOrderTS", 1);
  818.     }
  819.     // Set ASM Rule Book
  820.     if (SUCCEEDED(retVal))
  821.     {
  822. char pRuleBook[128]; /* Flawfinder: ignore */
  823. #ifdef QTCONFIG_SERVER
  824. pHeader->GetPropertyULONG32("RTPPayloadType", ulPayloadType);
  825. if (pTrackManager->GetEType() != QT_ETYPE_CLIENT)
  826. {
  827.     // Server Side
  828.     retVal = HXR_FAIL;
  829.     if (ulPayloadType != QT_BAD_PAYLOAD)
  830.     {
  831. retVal = HXR_OK;
  832.     }
  833.     if (SUCCEEDED(retVal))
  834.     {
  835. BOOL bSupportedPayload = SDPIsKnownPayload(ulPayloadType);
  836. pHeader->GetPropertyCString("MimeType", pMimeType);
  837. // This is not a standard payload - 
  838. // but maybe the encoding is standard
  839. if (!bSupportedPayload && pMimeType)
  840. {
  841.     bSupportedPayload = (SDPMapMimeToPayload(pMimeType, 
  842.      ulPayloadType)
  843.  == HXR_OK);
  844. }
  845. // Set the ASM rule book
  846. if ((ulAvgBitRate > 0)
  847. #ifndef QTFORCE_AVG_BITRATE_DELIVERY
  848.     && bSupportedPayload
  849.     && SDPIsFixedRatePayload(ulPayloadType)
  850. #endif // QTFORCE_AVG_BITRATE_DELIVERY
  851.    )
  852. {
  853.     // divide avg bitrate
  854.     UINT32 ulAvgBandwidth = ulAvgBitRate / 2;
  855.     SafeSprintf(pRuleBook, 128, 
  856.     "Marker=%d,AverageBandwidth=%d;"
  857.     "Marker=%d,AverageBandwidth=%d;",
  858.     (QTASM_MARKER_ON_RULE == 0) ? 1 : 0,
  859.     ulAvgBitRate - ulAvgBandwidth,
  860.     (QTASM_MARKER_ON_RULE == 0) ? 0 : 1,
  861.     ulAvgBandwidth);
  862. }
  863. else
  864. {
  865.     if (ulAvgBitRate > 0)
  866.     {
  867. SafeSprintf(pRuleBook, 128, "Marker=%d,AverageBandwidth=%d,TimeStampDelivery=TRUE;"
  868.    "Marker=%d,AverageBandwidth=0,TimeStampDelivery=TRUE;",
  869.         (QTASM_MARKER_ON_RULE == 0) ? 1 : 0,
  870. ulAvgBitRate,
  871. (QTASM_MARKER_ON_RULE == 0) ? 0 : 1);
  872.     }
  873.     else
  874.     {
  875. SafeSprintf(pRuleBook, 128, "Marker=%d,TimeStampDelivery=TRUE;"
  876.    "Marker=%d,TimeStampDelivery=TRUE;",
  877.         (QTASM_MARKER_ON_RULE == 0) ? 1 : 0,
  878. (QTASM_MARKER_ON_RULE == 0) ? 0 : 1);
  879.     }
  880. }
  881.     }
  882. }
  883. else
  884. #endif // QTCONFIG_SERVER
  885. {
  886.     // Player Side
  887.     SafeSprintf(pRuleBook, 128, "Marker=%d;Marker=%d;",
  888. (QTASM_MARKER_ON_RULE == 0) ? 1 : 0,
  889. (QTASM_MARKER_ON_RULE == 0) ? 0 : 1);
  890. }
  891. if (SUCCEEDED(retVal))
  892. {
  893.     retVal = pASMRuleBook->Set((UCHAR*) pRuleBook, strlen(pRuleBook) + 1);
  894. }
  895. if (SUCCEEDED(retVal))
  896. {
  897.     pHeader->SetPropertyCString("ASMRuleBook", pASMRuleBook);
  898. }
  899.     }
  900.     HX_RELEASE(pASMRuleBook);
  901.     HX_RELEASE(pMimeType);
  902.     return retVal;
  903. }
  904. HX_RESULT CQTFileFormat::GetSessionIdentity(IHXValues* pHeader,
  905.     CQT_MovieInfo_Manager* pMovieInfo)
  906. {
  907.     return HXR_OK;
  908. }
  909. HX_RESULT CQTFileFormat::GetPayloadIdentity(IHXValues* pHeader,
  910.     CQTTrack* pTrack,
  911.     CQT_TrackInfo_Manager* pTrackInfo)
  912. {
  913.     HX_RESULT retVal = HXR_OK;
  914.     if (SUCCEEDED(retVal))
  915.     {
  916. const char* pMimeType = pTrackInfo->GetMimeType();
  917. retVal = HXR_FAIL;
  918. if (pMimeType)
  919. {
  920.     IHXBuffer* pMimeTypeBuffer = NULL;
  921.     UINT32 ulMimeTypeLength = strlen(pMimeType);
  922.     retVal = m_pClassFactory->CreateInstance(CLSID_IHXBuffer,
  923.      (void**) &pMimeTypeBuffer);
  924.     if (SUCCEEDED(retVal))
  925.     {
  926. retVal = pMimeTypeBuffer->SetSize(ulMimeTypeLength + 1);
  927.     }
  928.     if (SUCCEEDED(retVal))
  929.     {
  930. memcpy(pMimeTypeBuffer->GetBuffer(), /* Flawfinder: ignore */
  931.        pMimeType,
  932.        ulMimeTypeLength + 1);
  933. retVal = pHeader->SetPropertyCString("MimeType", pMimeTypeBuffer);
  934.     }
  935.     HX_RELEASE(pMimeTypeBuffer);
  936. }
  937.     }
  938.     if (SUCCEEDED(retVal))
  939.     {
  940. ULONG32 ulTimeScale = pTrackInfo->GetMediaTimeScale();
  941. retVal = HXR_FAIL;
  942. if (ulTimeScale != 0)
  943. {
  944.     retVal = pHeader->SetPropertyULONG32("SamplesPerSecond", ulTimeScale);
  945. }
  946.     }
  947.     if (SUCCEEDED(retVal))
  948.     {
  949. ULONG32 ulPayloadType = pTrackInfo->GetPayloadType();
  950. retVal = HXR_FAIL;
  951. if (ulPayloadType != QT_BAD_PAYLOAD)
  952. {
  953.     retVal = pHeader->SetPropertyULONG32("RTPPayloadType", ulPayloadType);
  954. }
  955.     }
  956.     return retVal;
  957. }
  958. /************************************************************************
  959.  *  GetPacket
  960.  *  Method:
  961.  * IHXFileFormatObject::GetPacket
  962.  *  Purpose:
  963.  * Called by controller to ask the file format for the next packet
  964.  * for a particular stream in the file. The file format should call
  965.  * IHXFileFormatResponse::Data*() for the IHXFileFormatResponse
  966.  * object that was passed in during initialization, when the packet
  967.  * is available.
  968.  */
  969. STDMETHODIMP CQTFileFormat::GetPacket(UINT16 unStreamNumber)
  970. {
  971.     HX_RESULT retVal;
  972.     if (unStreamNumber < m_TrackManager.GetNumStreams())
  973.     {
  974. switch (m_State)
  975. {
  976. case QTFF_Ready:
  977.     if (unStreamNumber == m_uNextPacketStreamNum)
  978.     {
  979. // Process this packet request
  980. // - but replace stream's cache first
  981. HX_ASSERT(m_pPacketCache);
  982. m_State = QTFF_GetPacket;
  983. return m_TrackManager.GetStreamTrack(unStreamNumber)->
  984. GetPacket(unStreamNumber);
  985.     }
  986.     else if (m_pPacketCache)
  987.     {
  988. // Delay processing packet for stream until its turn
  989. if (!m_pPacketCache[unStreamNumber].bStreamDone)
  990. {
  991.     if (!m_pPacketCache[unStreamNumber].bPending)
  992.     {
  993. m_pPacketCache[unStreamNumber].bPending = TRUE;
  994. return HXR_OK;
  995.     }
  996.     else
  997.     {
  998. retVal = HXR_UNEXPECTED;
  999.     }
  1000. }
  1001. else
  1002. {
  1003.     retVal = m_pFFResponse->StreamDone(unStreamNumber);
  1004. }
  1005.     }
  1006.     else
  1007.     {
  1008. // Packet Cache not primed - start priming
  1009. // To save memory, release streams not used
  1010. m_TrackManager.RemoveInactiveStreams(TRUE);
  1011. m_State = QTFF_PrimeCache;
  1012. m_pPacketCache = new 
  1013.     CPacketCache[m_TrackManager.GetNumStreams()];
  1014. if (m_pPacketCache)
  1015. {
  1016.     m_pPacketCache[unStreamNumber].bPending = TRUE;
  1017.     if (m_TrackManager.IsStreamTrackActive(0))
  1018.     {
  1019. return m_TrackManager.GetStreamTrack(0)->
  1020.     GetPacket(0);
  1021.     }
  1022.     else
  1023.     {
  1024. return PacketReady(0, 
  1025.    HXR_STREAM_DONE,
  1026.    NULL);
  1027.     }
  1028. }
  1029. else
  1030. {
  1031.     retVal = HXR_OUTOFMEMORY;
  1032.     m_State = QTFF_Error;
  1033. }
  1034.     }
  1035.     break;
  1036. case QTFF_GetPacket:
  1037. case QTFF_PrimeCache:
  1038.     // Delay processing packet for stream until Ready
  1039.     HX_ASSERT(m_pPacketCache);
  1040.     if (!m_pPacketCache[unStreamNumber].bStreamDone)
  1041.     {
  1042. if (!m_pPacketCache[unStreamNumber].bPending)
  1043. {
  1044.     m_pPacketCache[unStreamNumber].bPending = TRUE;
  1045.     return HXR_OK;
  1046. }
  1047. else
  1048. {
  1049.     retVal = HXR_UNEXPECTED;
  1050. }
  1051.     }
  1052.     else
  1053.     {
  1054. retVal = m_pFFResponse->StreamDone(unStreamNumber);
  1055.     }
  1056.     break;
  1057. default:
  1058.     retVal = HXR_UNEXPECTED;
  1059.     break;
  1060. }
  1061.     }
  1062.     else
  1063.     {
  1064. retVal = HXR_INVALID_PARAMETER;
  1065.     }
  1066.     return retVal;
  1067. }
  1068. /************************************************************************
  1069.  *  Seek
  1070.  *  Purpose:
  1071.  * Called by controller to tell the file format to seek to the 
  1072.  * nearest packet to the requested offset. The file format should 
  1073.  * call IHXFileFormatResponse::SeekDone() for the IHXFileFormat-
  1074.  * Session object that was passed in during initialization, when 
  1075.  * the seek has completed.
  1076.  */
  1077. STDMETHODIMP CQTFileFormat::Seek(ULONG32 ulOffset)
  1078. {
  1079.     UINT16 uStreamNum;
  1080.     HX_RESULT retVal = HXR_OK;
  1081.     switch (m_State)
  1082.     {
  1083.     case QTFF_Ready:
  1084. for (uStreamNum = 0;
  1085.      uStreamNum < m_TrackManager.GetNumStreams();
  1086.      uStreamNum++)
  1087. {
  1088.     if (m_TrackManager.IsStreamTrackActive(uStreamNum))
  1089.     {
  1090. m_TrackManager.GetStreamTrack(uStreamNum)->Seek(ulOffset);
  1091.     }
  1092. }
  1093. m_uNextPacketStreamNum = NO_STREAM_SET;
  1094. HX_VECTOR_DELETE(m_pPacketCache);
  1095. retVal = m_pFFResponse->SeekDone(HXR_OK);
  1096. break;
  1097.     case QTFF_GetPacket:
  1098.     case QTFF_PrimeCache:
  1099.     case QTFF_SeekPending:
  1100. m_State = QTFF_SeekPending;
  1101. m_ulPendingSeekTime = ulOffset;
  1102. break;
  1103.     default:
  1104. retVal = HXR_UNEXPECTED;
  1105. break;
  1106.     }
  1107.     return retVal;
  1108. }
  1109. /************************************************************************
  1110.  *  WriteDone
  1111.  *  Purpose:
  1112.  * Notification interface provided by users of the IHXFileObject
  1113.  * interface. This method is called by the IHXFileObject when the
  1114.  * last write to the file is complete.
  1115.  */
  1116. STDMETHODIMP CQTFileFormat::WriteDone(HX_RESULT status)
  1117. {
  1118.     return HXR_UNEXPECTED;
  1119. }
  1120. /************************************************************************
  1121.  *  SeekDone
  1122.  *  Purpose:
  1123.  * Notification interface provided by users of the IHXFileObject
  1124.  * interface. This method is called by the IHXFileObject when the
  1125.  * last seek in the file is complete.
  1126.  */
  1127. STDMETHODIMP CQTFileFormat::SeekDone(HX_RESULT status)
  1128. {
  1129.     return HXR_UNEXPECTED;
  1130. }
  1131. /************************************************************************
  1132.  *  Close
  1133.  */
  1134. STDMETHODIMP CQTFileFormat::Close()
  1135. {
  1136.     m_State = QTFF_Error;
  1137.     HX_RELEASE(m_pContext);
  1138.     HX_RELEASE(m_pRequest);
  1139.     HX_RELEASE(m_pFFResponse);
  1140.     HX_RELEASE(m_pClassFactory);
  1141.     HX_RELEASE(m_pScheduler);
  1142.     HX_RELEASE(m_pErrorMessages);
  1143.     if (m_pFileSwitcher)
  1144.     {
  1145. m_pFileSwitcher->Close(this);
  1146. m_pFileSwitcher->Release();
  1147. m_pFileSwitcher = NULL;
  1148.     }
  1149.     if (m_pAtomizer)
  1150.     {
  1151. m_pAtomizer->Close();
  1152. m_pAtomizer->Release();
  1153. m_pAtomizer = NULL;
  1154.     }
  1155.     HX_RELEASE(m_pPacketAssembler);
  1156. #ifdef QTCONFIG_BFRAG_FACTORY
  1157.     HX_RELEASE(m_pBufferFragmentFactory);
  1158. #endif // QTCONFIG_BFRAG_FACTORY
  1159.     HX_VECTOR_DELETE(m_pPacketCache);
  1160.     m_TrackManager.CloseTracks();
  1161.     return HXR_OK;
  1162. }
  1163. /************************************************************************
  1164.  *  IHXFileResponse
  1165.  */
  1166. /************************************************************************
  1167.  *  InitDone
  1168.  *  Purpose:
  1169.  *    Notification interface provided by users of the IHXFileObject
  1170.  *    interface. This method is called by the IHXFileObject when the
  1171.  *    initialization of the file is complete, and the Mime type is
  1172.  *    available for the request file. If the URL is not valid for the
  1173.  *    file system, the status HXR_FAILED should be returned,
  1174.  *    with a mime type of NULL. If the URL is valid but the mime type
  1175.  *    is unknown, then the status HXR_OK should be returned with
  1176.  *    a mime type of NULL.
  1177.  */
  1178. STDMETHODIMP CQTFileFormat::InitDone(HX_RESULT status)
  1179. {
  1180.     HX_RESULT retVal = HXR_OK;
  1181.     switch (m_State)
  1182.     {
  1183.     case QTFF_Init:
  1184. if (SUCCEEDED(status))
  1185. {
  1186.     status = m_pAtomizer->Init((IUnknown*)(IHXFileSwitcher*) m_pFileSwitcher,
  1187.        (IUnknown*)(IHXAtomizerResponse*) this,
  1188.        (IUnknown*)(IHXAtomizationCommander*) this);
  1189. }
  1190. m_State = SUCCEEDED(status) ? QTFF_Ready : QTFF_Error;
  1191. retVal = m_pFFResponse->InitDone(status);
  1192. break;
  1193.     default:
  1194. retVal = HXR_UNEXPECTED;
  1195. break;
  1196.     }
  1197.     return retVal;
  1198. }
  1199. /************************************************************************
  1200.  *  CloseDone
  1201.  *  Purpose:
  1202.  * Notification interface provided by users of the IHXFileObject
  1203.  * interface. This method is called by the IHXFileObject when the
  1204.  * close of the file is complete.
  1205.  */
  1206. STDMETHODIMP CQTFileFormat::CloseDone(HX_RESULT status)
  1207. {
  1208.     // nothing to do
  1209.     return HXR_OK;
  1210. }
  1211. /************************************************************************
  1212.  *  ReadDone
  1213.  *  Purpose:
  1214.  * Notification interface provided by users of the IHXFileObject
  1215.  * interface. This method is called by the IHXFileObject when the
  1216.  * last read from the file is complete and a buffer is available.
  1217.  */
  1218. STDMETHODIMP CQTFileFormat::ReadDone(HX_RESULT status,
  1219.     IHXBuffer* pBuffer)
  1220. {
  1221.     return HXR_UNEXPECTED;
  1222. }
  1223. /************************************************************************
  1224.  *  IHXAtomizationCommander
  1225.  */
  1226. /************************************************************************
  1227.  *  GetAtomCommand
  1228.  */
  1229. QTAtomizerCmd CQTFileFormat::GetAtomCommand(QTAtomType AtomType, CQTAtom* pParent)
  1230. {
  1231.     QTAtomizerCmd eCmd = ATMZR_CMD_LOAD;
  1232.     switch (AtomType)
  1233.     {
  1234.     case QT_udta:
  1235. if (pParent->GetType() == QT_HXROOT)
  1236. {
  1237.     eCmd = ATMZR_CMD_SKIP;
  1238. }
  1239. break;
  1240.     default:
  1241. // do nothing;
  1242. break;
  1243.     }
  1244.     return eCmd;
  1245. }
  1246. /************************************************************************
  1247.  *  IHXAtomizerResponse
  1248.  */
  1249. /************************************************************************
  1250.  *  AtomReady
  1251.  */
  1252. HX_RESULT CQTFileFormat::AtomReady(HX_RESULT status, CQTAtom* pRootAtom)
  1253. {
  1254.     HX_RESULT retVal = HXR_UNEXPECTED;
  1255.     CQTPacketizerFactory* pPacketizerFactory = NULL;
  1256.     switch (m_State)
  1257.     {
  1258.     case QTFF_Atomize:
  1259. if (SUCCEEDED(status))
  1260. {
  1261.     HX_ASSERT(pRootAtom);
  1262.     
  1263.     pRootAtom->AddRef();
  1264.     
  1265.     if (m_pAtomizer)
  1266.     {
  1267. m_pAtomizer->Close();
  1268. m_pAtomizer->Release();
  1269. m_pAtomizer = NULL;
  1270.     } 
  1271. }
  1272. else
  1273. {
  1274.     pRootAtom = NULL;
  1275. }
  1276. if (SUCCEEDED(status))
  1277. {
  1278.     IHXClientEngine* pPlayer = NULL;
  1279.     if (SUCCEEDED(m_pContext->QueryInterface(IID_IHXClientEngine, 
  1280.      (void**)&pPlayer)))
  1281.     {
  1282. m_TrackManager.SetEType(QT_ETYPE_CLIENT);
  1283.     }
  1284.     else
  1285.     {
  1286. m_TrackManager.SetEType(QT_ETYPE_SERVER);
  1287.     }
  1288.     HX_RELEASE(pPlayer);
  1289. }
  1290. if (SUCCEEDED(status))
  1291. {
  1292.     status = m_TrackManager.ManageTracks(pRootAtom);
  1293. }
  1294. #ifdef QTCONFIG_PACKETIZER_FACTORY
  1295. if (SUCCEEDED(status))
  1296. {
  1297.     pPacketizerFactory = BuildPacketizerFactory();
  1298.     if (!pPacketizerFactory)
  1299.     {
  1300. status = HXR_OUTOFMEMORY;
  1301.     }
  1302. }
  1303. #endif // QTCONFIG_PACKETIZER_FACTORY
  1304. if (SUCCEEDED(status))
  1305. {
  1306.     BOOL bIgnoreHintTracks = FALSE;
  1307.     while (1)
  1308.     {
  1309. status = m_TrackManager.ReadyTracks(bIgnoreHintTracks, 
  1310.          m_bViewSourceRequest);
  1311.           if (SUCCEEDED(status))
  1312. {
  1313.     status = m_MovieInfo.Init(pRootAtom->FindPresentChild(QT_moov),
  1314.       &m_TrackManager);
  1315. }
  1316.           if (SUCCEEDED(status))
  1317.           {         
  1318.          /*
  1319.          * return some error to indicate try something else
  1320.          */
  1321.          status = m_TrackManager.InitTracks(this, 
  1322.             m_pPacketAssembler,
  1323.             pPacketizerFactory);
  1324.          
  1325.          if ((HXR_NOT_SUPPORTED == status) && 
  1326. (bIgnoreHintTracks = !bIgnoreHintTracks))
  1327.     {
  1328. m_MovieInfo.Clear();
  1329. m_TrackManager.ResetTracks();
  1330.     }
  1331.     else
  1332.     {
  1333.      /*
  1334.           * Until we add support for unhinted content on the server....
  1335.           * 
  1336.           * Verify that hint tracks are present and log a warning message if
  1337.           * they're missing
  1338.           */          
  1339.      WarnIfNotHinted(status, bIgnoreHintTracks);
  1340.     
  1341.      /*
  1342.       * XXXGo - Change warning to take into account
  1343.       * hintrack and license for dynamic pktization
  1344.       * e.g. force pktization yet not licensed for dynamic pktization...
  1345.       */      
  1346.          
  1347.           if (FAILED(status) && m_bViewSourceRequest)
  1348.           {
  1349.          // For view source, proceed attempting to return as much
  1350.          // information as possible
  1351.          status = HXR_OK;
  1352.           }
  1353. break;
  1354.     }
  1355. }
  1356. else
  1357. {
  1358.     break;
  1359. }
  1360.     }
  1361. }
  1362. HX_DELETE(pPacketizerFactory);
  1363. #ifdef QTCONFIG_BFRAG_FACTORY
  1364. if (SUCCEEDED(status))
  1365. {
  1366.     HX_RELEASE(m_pBufferFragmentFactory);
  1367.     m_pBufferFragmentFactory = new CBufferFragmentFactory(
  1368. m_TrackManager.GetNumStreams() * QTBUFFERFRAGMENT_POOL_SIZE,
  1369. m_TrackManager.GetNumStreams() * QTBUFFERFRAGMENT_INITIAL_POOL_SIZE);
  1370.     retVal = HXR_OUTOFMEMORY;
  1371.     if (m_pBufferFragmentFactory)
  1372.     {
  1373. m_pBufferFragmentFactory->AddRef();
  1374. retVal = HXR_OK;
  1375.     }
  1376. }
  1377. #endif // QTCONFIG_BFRAG_FACTORY
  1378. HX_RELEASE(pRootAtom);
  1379. m_State = SUCCEEDED(status) ? QTFF_Ready : QTFF_Error;
  1380. retVal = MakeFileHeader(status);
  1381. break;
  1382.     default:
  1383. // nothing to do
  1384. break;
  1385.     }
  1386.     return retVal;
  1387. }
  1388. /************************************************************************
  1389.  *  IHXASMSource
  1390.  */
  1391. /************************************************************************
  1392.  *  Subscribe
  1393.  */
  1394. STDMETHODIMP CQTFileFormat::Subscribe(UINT16 uStreamNum,
  1395.       UINT16 uRuleNumber)
  1396. {
  1397.     return m_TrackManager.Subscribe(uStreamNum);
  1398. }
  1399. /************************************************************************
  1400.  *  Unsubscribe
  1401.  */
  1402. STDMETHODIMP CQTFileFormat::Unsubscribe(UINT16 uStreamNum,
  1403. UINT16 uRuleNumber)
  1404. {
  1405.     return m_TrackManager.Unsubscribe(uStreamNum);
  1406. }
  1407. /************************************************************************
  1408.  *      Method:
  1409.  *          IHXPacketFormat::GetSupportedPacketFormats
  1410.  *      Purpose:
  1411.  *          Obtains a list of packet formats supported by this file format
  1412.  */
  1413. STDMETHODIMP CQTFileFormat::GetSupportedPacketFormats
  1414. (
  1415.     REF(const char**) /*OUT*/ pPacketFormats
  1416. )
  1417. {
  1418.     pPacketFormats = (const char**) zm_pPacketFormats;
  1419.     return HXR_OK;
  1420. }
  1421. /************************************************************************
  1422.  *      Method:
  1423.  *          IHXPacketFormat::SetPacketFormat
  1424.  *      Purpose:
  1425.  *          Sets the packet type for this file format
  1426.  */
  1427. STDMETHODIMP CQTFileFormat::SetPacketFormat
  1428. (
  1429.     const char* pPacketFormat
  1430. )
  1431. {
  1432.     if (strcasecmp(pPacketFormat, "rtp") == 0)
  1433.     {
  1434.         m_ulPacketFormat = QTFF_RTP_FORMAT;
  1435.     }
  1436.     else
  1437.     {
  1438.         m_ulPacketFormat = QTFF_RDT_FORMAT;
  1439.     }
  1440.     return HXR_OK;
  1441. }
  1442. /************************************************************************
  1443.  *  Main Interface
  1444.  */
  1445. /************************************************************************
  1446.  *  PacketReady
  1447.  */
  1448. HX_RESULT CQTFileFormat::PacketReady(UINT16 uStreamNum, 
  1449.      HX_RESULT status, 
  1450.      IHXPacket* pPacket)
  1451. {
  1452.     HX_RESULT retVal;
  1453.     IHXPacket *pPacketToSend;
  1454.     switch (m_State)
  1455.     {
  1456.     case QTFF_GetPacket:
  1457. pPacketToSend = m_pPacketCache[uStreamNum].pPacket;
  1458. HX_ASSERT(pPacketToSend);
  1459. if (status == HXR_OK)
  1460. {
  1461.     HX_ASSERT(pPacket);
  1462.     m_pPacketCache[uStreamNum].pPacket = pPacket;
  1463.     pPacket->AddRef();
  1464. }
  1465. else
  1466. {
  1467.     m_pPacketCache[uStreamNum].pPacket = NULL;
  1468.     m_pPacketCache[uStreamNum].bStreamDone = TRUE;
  1469.     if (status == HXR_STREAM_DONE)
  1470.     {
  1471. status = HXR_OK;
  1472.     }
  1473. }
  1474. AddRef();   // Make Sure we do not die as a result of PacketReady
  1475. m_pPacketCache[uStreamNum].bPending = FALSE;
  1476. retVal = m_pFFResponse->PacketReady(status, pPacketToSend);
  1477. if (pPacketToSend)
  1478. {
  1479.     pPacketToSend->Release();
  1480. }
  1481. // Make sure the state did not change as result of PacketReady()
  1482. // The possible change is due to invocation of Close on PacketReady
  1483. if (m_State == QTFF_GetPacket)
  1484. {
  1485.     m_State = QTFF_Ready;
  1486.     // see if a pending request needs to be fullfilled
  1487.     m_uNextPacketStreamNum = GetNextPacketStreamNum();
  1488.     if ((m_uNextPacketStreamNum != NO_STREAM_SET) &&
  1489. m_pPacketCache[m_uNextPacketStreamNum].bPending)
  1490.     {
  1491. m_State = QTFF_GetPacket;
  1492. retVal = m_TrackManager.GetStreamTrack(m_uNextPacketStreamNum)->
  1493.     GetPacket(m_uNextPacketStreamNum);
  1494.     }
  1495. }
  1496. Release();
  1497. return retVal;
  1498.     case QTFF_PrimeCache:
  1499. if (status == HXR_OK)
  1500. {
  1501.     HX_ASSERT(pPacket);
  1502.     m_pPacketCache[uStreamNum].pPacket = pPacket;
  1503.     pPacket->AddRef();
  1504. }
  1505. else
  1506. {
  1507.     m_pPacketCache[uStreamNum].pPacket = NULL;
  1508.     m_pPacketCache[uStreamNum].bStreamDone = TRUE;
  1509.     if (status == HXR_STREAM_DONE)
  1510.     {
  1511. if (m_pPacketCache[uStreamNum].bPending)
  1512. {
  1513.     AddRef();   // Make sure we do not die
  1514.     m_pPacketCache[uStreamNum].bPending = FALSE;
  1515.     retVal = m_pFFResponse->StreamDone(uStreamNum);
  1516.     if (m_State != QTFF_PrimeCache)
  1517.     {
  1518. // StreamDone must have closed us
  1519. Release();
  1520. break;
  1521.     }
  1522.     Release();
  1523. }
  1524.     }
  1525.     else
  1526.     {
  1527. // Fatal failure
  1528. retVal = HandleFailure(status);
  1529. break;
  1530.     }
  1531. }
  1532. uStreamNum++;
  1533. if (uStreamNum < m_TrackManager.GetNumStreams())
  1534. {
  1535.     // we still have stream packets to prime
  1536.     if (m_TrackManager.IsStreamTrackActive(uStreamNum))
  1537.     {
  1538. retVal = m_TrackManager.GetStreamTrack(uStreamNum)->
  1539.     GetPacket(uStreamNum);
  1540.     }
  1541.     else
  1542.     {
  1543. retVal = PacketReady(uStreamNum, 
  1544.      HXR_STREAM_DONE,
  1545.      NULL);
  1546.     }
  1547. }
  1548. else
  1549. {
  1550.     // we are done priming the packets
  1551.     retVal = HXR_OK;
  1552.     m_State = QTFF_Ready;
  1553.     // see if a pending request needs to be fullfilled
  1554.     m_uNextPacketStreamNum = GetNextPacketStreamNum();
  1555.     if ((m_uNextPacketStreamNum != NO_STREAM_SET) &&
  1556. m_pPacketCache[m_uNextPacketStreamNum].bPending)
  1557.     {
  1558. m_State = QTFF_GetPacket;
  1559. retVal = m_TrackManager.
  1560.     GetStreamTrack(m_uNextPacketStreamNum)->
  1561. GetPacket(m_uNextPacketStreamNum);
  1562.     }
  1563. }
  1564. break;
  1565.     case QTFF_SeekPending:
  1566. HX_VECTOR_DELETE(m_pPacketCache);
  1567. m_uNextPacketStreamNum = NO_STREAM_SET;
  1568. m_State = QTFF_Ready;
  1569. retVal = Seek(m_ulPendingSeekTime);
  1570. break;
  1571.     default:
  1572. retVal = HXR_UNEXPECTED;
  1573. break;
  1574.     }
  1575.     return retVal;
  1576. }
  1577. /************************************************************************
  1578.  *  Protected Methods
  1579.  */
  1580. CQTPacketizerFactory* CQTFileFormat::BuildPacketizerFactory(void)
  1581. {
  1582. #ifdef QTCONFIG_PACKETIZER_FACTORY
  1583.     return new CQTPacketizerFactory();
  1584. #else // QTCONFIG_PACKETIZER_FACTORY
  1585.     return NULL;
  1586. #endif // QTCONFIG_PACKETIZER_FACTORY
  1587. }
  1588. /************************************************************************
  1589.  *  Private Methods
  1590.  */
  1591. /************************************************************************
  1592.  *  GetNextPacketStreamNum
  1593.  */
  1594. inline UINT16 CQTFileFormat::GetNextPacketStreamNum(void)
  1595. {
  1596.     UINT16 uStreamNum;
  1597.     ULONG32 ulLowestTime = 0xFFFFFFFF;
  1598.     UINT16 uNextPacketStream = NO_STREAM_SET;
  1599.     HX_ASSERT(m_pPacketCache);
  1600.     for (uStreamNum = 0;
  1601.  uStreamNum < m_TrackManager.GetNumStreams();
  1602.  uStreamNum++)
  1603.     {
  1604. if (!m_pPacketCache[uStreamNum].bStreamDone)
  1605. {
  1606.     HX_ASSERT(m_pPacketCache[uStreamNum].pPacket);
  1607.     if (ulLowestTime >
  1608. m_pPacketCache[uStreamNum].pPacket->GetTime())
  1609.     {
  1610. uNextPacketStream = uStreamNum;
  1611. ulLowestTime = m_pPacketCache[uStreamNum].
  1612.     pPacket->GetTime();
  1613.     }
  1614. }
  1615.     }
  1616.     return uNextPacketStream;
  1617. }
  1618. /************************************************************************
  1619.  *  HandleFailure
  1620.  */
  1621. HX_RESULT CQTFileFormat::HandleFailure(HX_RESULT status)
  1622. {
  1623.     HX_RESULT retVal = HXR_OK;
  1624.     HX_ASSERT(FAILED(status));
  1625.     switch (m_State)
  1626.     {
  1627.     case QTFF_PrimeCache:
  1628. {
  1629.     UINT16 uStreamNum = 0;
  1630.     m_State = QTFF_Error;
  1631.     
  1632.     AddRef();
  1633.     while (m_pPacketCache &&
  1634.    (uStreamNum < m_TrackManager.GetNumStreams()))
  1635.     {
  1636. if (m_pPacketCache[uStreamNum].bPending)
  1637. {
  1638.     m_pPacketCache[uStreamNum].bPending = FALSE;
  1639.     m_pFFResponse->PacketReady(status, NULL);
  1640. }
  1641. uStreamNum++;
  1642.     }
  1643.     Release();
  1644. }
  1645. break;
  1646.     default:
  1647. retVal = HXR_UNEXPECTED;
  1648. break;
  1649.     }
  1650.     return retVal;
  1651. }
  1652. /************************************************************************
  1653.  *  a standard way of pulling a error string out of a resource file in a 
  1654.  *  localization friendly manner :)
  1655.  */
  1656. void 
  1657. CQTFileFormat::ReportError(UINT32 ulErrorID, HX_RESULT retVal)
  1658. {
  1659.     // Try to get the string from the resource manager
  1660.     CHXString cErrStr;
  1661.     HX_RESULT errRet = GetResourceErrorString(ulErrorID, cErrStr);
  1662.     if (errRet != HXR_OK)
  1663.     {
  1664.         switch (ulErrorID)
  1665.         {
  1666.             case IDS_ERR_QT_NOTLICENSED:
  1667.                 cErrStr = ERRSTR_QT_NOTLICENSED;
  1668.                 break;
  1669.             default:
  1670.                 cErrStr = ERRSTR_QT_GENERALERROR;
  1671.                 break;
  1672.         }
  1673.     }
  1674.  
  1675.     if (m_pErrorMessages)
  1676.     {
  1677.         m_pErrorMessages->Report(HXLOG_CRIT, retVal, 0, (const char*) cErrStr,  NULL);
  1678.     }
  1679. }
  1680. HX_RESULT 
  1681. CQTFileFormat::GetResourceErrorString(UINT32 ulErrorID, CHXString& rErrorStr)
  1682. {
  1683.     IHXExternalResourceManager* pResMgr = NULL;
  1684.     HX_RESULT retVal = m_pContext->QueryInterface(IID_IHXExternalResourceManager, (void**) &pResMgr);
  1685.     if (retVal != HXR_OK)
  1686.     {
  1687.         return retVal;
  1688.     }
  1689. IHXExternalResourceReader* pResRdr = NULL;
  1690.     retVal = pResMgr->CreateExternalResourceReader(CORE_RESOURCE_SHORT_NAME, pResRdr);
  1691.     if (retVal != HXR_OK)
  1692.     {
  1693.         HX_RELEASE(pResMgr);
  1694.         return retVal;
  1695.     }
  1696.     IHXXResource* pRes = pResRdr->GetResource(HX_RT_STRING, ulErrorID);
  1697.     if(!pRes)
  1698.     {
  1699.         HX_RELEASE(pResRdr);
  1700.         HX_RELEASE(pResMgr);
  1701.         return HXR_FAIL;
  1702.     }
  1703.     // Assign the error string to the out parameter
  1704.     rErrorStr = (const char*) pRes->ResourceData();
  1705.     // Release all references
  1706.     HX_RELEASE(pRes);
  1707.     HX_RELEASE(pResRdr);
  1708.     HX_RELEASE(pResMgr);
  1709.     return HXR_OK;
  1710. }
  1711. /************************************************************************
  1712.  *  AddMetaInfo
  1713.  */
  1714. HX_RESULT CQTFileFormat::AddMetaInfo(IHXValues* pHeader)
  1715. {
  1716.     BOOL bAddAll;
  1717.     ULONG32 ulPresentationWidth = 0;
  1718.     ULONG32 ulPresentationHeight = 0;
  1719.     
  1720.     HX_ASSERT(pHeader);
  1721.     if ((m_TrackManager.GetEType() == QT_ETYPE_CLIENT) || 
  1722. (m_ulStreamMetaInfoMask & META_INFO_ALL) ||
  1723. (m_ulStreamMetaInfoMask & META_INFO_WIDTH) ||
  1724. (m_ulStreamMetaInfoMask & META_INFO_HEIGHT))
  1725.     {
  1726. UINT16 uStreamCount;
  1727. CQTTrack* pTrack;
  1728. // Collect Meta Info
  1729. for (uStreamCount = m_TrackManager.GetNumStreams();
  1730.      uStreamCount != 0;
  1731.      uStreamCount--)
  1732. {
  1733.     pTrack = m_TrackManager.GetStreamTrack(uStreamCount - 1);
  1734.     ulPresentationWidth += pTrack->m_TrackInfo.GetTrackWidth();
  1735.     ulPresentationHeight += pTrack->m_TrackInfo.GetTrackHeight();
  1736. }
  1737.     }
  1738.     bAddAll = ((m_TrackManager.GetEType() == QT_ETYPE_CLIENT) || 
  1739.        (m_ulStreamMetaInfoMask & META_INFO_ALL));
  1740.     if (bAddAll)
  1741.     {
  1742. if (ulPresentationWidth > 0)
  1743. {
  1744.     pHeader->SetPropertyULONG32(WIDTH_METANAME, 
  1745. ulPresentationWidth);
  1746. }
  1747. if (ulPresentationHeight > 0)
  1748. {
  1749.     pHeader->SetPropertyULONG32(HEIGHT_METANAME, 
  1750. ulPresentationHeight);
  1751. }
  1752.     }
  1753. #ifdef QTCONFIG_SERVER
  1754.     else if((m_ulStreamMetaInfoMask & META_INFO_ALL) ||
  1755. (m_ulStreamMetaInfoMask & META_INFO_WIDTH) ||
  1756. (m_ulStreamMetaInfoMask & META_INFO_HEIGHT))
  1757.     {     
  1758. if (ulPresentationWidth > 0 &&
  1759.     ((m_ulStreamMetaInfoMask & META_INFO_ALL) ||
  1760.     (m_ulStreamMetaInfoMask & META_INFO_WIDTH)))
  1761. {
  1762.     pHeader->SetPropertyULONG32(WIDTH_METANAME, 
  1763. ulPresentationWidth);
  1764. }
  1765. if (ulPresentationHeight > 0 &&
  1766.     ((m_ulStreamMetaInfoMask & META_INFO_ALL) ||
  1767.     (m_ulStreamMetaInfoMask & META_INFO_HEIGHT)))
  1768. {
  1769.     pHeader->SetPropertyULONG32(HEIGHT_METANAME, 
  1770. ulPresentationHeight);
  1771. }
  1772.     } 
  1773. #endif // QTCONFIG_SERVER
  1774.     return HXR_OK;
  1775. }
  1776. #ifdef QTCONFIG_SERVER
  1777. /************************************************************************
  1778.  *  CheckLicense
  1779.  */
  1780. HX_RESULT CQTFileFormat::CheckLicense(void)
  1781. {
  1782.     HX_ASSERT(m_pContext);
  1783.     
  1784.     IHXClientEngine* pPlayer = NULL;
  1785.     IHXRemoteBroadcastServices* pRBServices = NULL;
  1786.     if (SUCCEEDED(m_pContext->QueryInterface(IID_IHXClientEngine, (void**)&pPlayer))
  1787.         || SUCCEEDED(m_pContext->QueryInterface(IID_IHXRemoteBroadcastServices, (void**)&pRBServices)))
  1788.     {
  1789.         // Data types are always licensed on the Player and iqslta
  1790.         m_bQTLicensed = TRUE;
  1791. m_bMP4Licensed = TRUE;
  1792.     }
  1793.     else
  1794.     {    
  1795.         // On the Server, check the license section of the registry
  1796.         IHXRegistry* pRegistry = NULL;        
  1797. if (HXR_OK != m_pContext->QueryInterface(IID_IHXRegistry, 
  1798. (void**)&pRegistry))
  1799. {
  1800.     return HXR_UNEXPECTED;
  1801. }
  1802.         INT32 nLicensed = 0;
  1803.         if (!SUCCEEDED(pRegistry->GetIntByName(REGISTRY_QUICKTIME_ENABLED, 
  1804.             nLicensed)))
  1805.         {
  1806.             /* take default */
  1807.             nLicensed = LICENSE_QUICKTIME_ENABLED;
  1808.         }
  1809.         m_bQTLicensed = (nLicensed) ? (TRUE) : (FALSE);
  1810.         if (!SUCCEEDED(pRegistry->GetIntByName(REGISTRY_REALMP4_ENABLED, 
  1811.             nLicensed)))
  1812.         {
  1813.             /* take default */
  1814.             nLicensed = LICENSE_REALMP4_ENABLED;
  1815.         }
  1816.         m_bMP4Licensed = (nLicensed) ? (TRUE) : (FALSE);
  1817.         HX_RELEASE(pRegistry);
  1818.     }
  1819.     HX_RELEASE(pPlayer);
  1820.     HX_RELEASE(pRBServices);
  1821.     return HXR_OK;
  1822. }
  1823. /************************************************************************
  1824.  *  WarnIfNotHinted
  1825.  */
  1826. void CQTFileFormat::WarnIfNotHinted(HX_RESULT status, BOOL bIgnoreHintTracks)
  1827. {    
  1828.     /*
  1829.      * log what's going on...
  1830.      */    
  1831.     if ((m_TrackManager.GetEType() == QT_ETYPE_SERVER) && m_pErrorMessages
  1832. && HXR_OK == status)
  1833.     {
  1834.         /*
  1835.          * Check the registry to see if warnings are disabled.
  1836.          */
  1837.         INT32 nWarningDisabled = 0;
  1838.         IHXRegistry* pRegistry = NULL;
  1839.         if (m_pContext &&
  1840.             (HXR_OK == m_pContext->QueryInterface(IID_IHXRegistry, 
  1841.                                                  (void**)&pRegistry)))
  1842.         {
  1843.             pRegistry->GetIntByName("config.DisableHintingWarning",
  1844.                                     nWarningDisabled);
  1845.         }
  1846.         HX_RELEASE(pRegistry);
  1847.         if (nWarningDisabled)
  1848.         {
  1849.             return;
  1850.         }
  1851. const char* pszIgnore = 
  1852.     "Handling HINTED content - ignoring Hint Tracks (URL: /%s)n";
  1853. const char* pszHint = 
  1854.     "Handling HINTED content - using Hint Tracks (URL: /%s)n";
  1855. const char* pszNotHinted = 
  1856.     "Handling UNHINTED content (URL: /%s)n";
  1857. const char* pszMsg;
  1858. if (bIgnoreHintTracks)
  1859. {
  1860.     pszMsg = pszIgnore;
  1861. }
  1862. else if (m_TrackManager.IsHinted())
  1863. {
  1864.     pszMsg = pszHint;
  1865.     HX_ASSERT(HXR_NOT_LICENSED != status); // can't ever be this error
  1866. }
  1867. else
  1868. {
  1869.     pszMsg = pszNotHinted;
  1870. }
  1871.         const char* pReqURL = NULL;        
  1872.         UINT32 ulMaxURLLen = 1024 * 2;
  1873.         UINT32 ulBuffLen = ulMaxURLLen + strlen(pszMsg) + 1;
  1874.         HX_RESULT status = HXR_OK;
  1875.         if (m_pRequest)
  1876.         {
  1877.             status = m_pRequest->GetURL(pReqURL);
  1878.         }
  1879.         if (SUCCEEDED(status) && pReqURL)
  1880.         {
  1881.             UINT32 ulURLLen = strlen(pReqURL);
  1882.             if (ulURLLen >  ulMaxURLLen)
  1883.             {
  1884.                 pReqURL += ulURLLen - ulMaxURLLen;  
  1885.             }
  1886.         }
  1887.         else 
  1888.         {
  1889.             pReqURL = " ";
  1890.         }
  1891.         NEW_FAST_TEMP_STR(pszTmpStr, 4096, ulBuffLen);
  1892.         snprintf(pszTmpStr, ulBuffLen, pszMsg, pReqURL); 
  1893.         m_pErrorMessages->Report(HXLOG_WARNING, HXR_OK, 0, pszTmpStr, NULL);
  1894.         DELETE_FAST_TEMP_STR(pszTmpStr);
  1895.     }
  1896. }
  1897. #else // QTCONFIG_SERVER
  1898. HX_RESULT CQTFileFormat::CheckLicense(void)
  1899. {
  1900.     return HXR_OK;
  1901. }
  1902. void CQTFileFormat::WarnIfNotHinted(HX_RESULT status, BOOL bIgnoreHintTracks)
  1903. {
  1904.     return;
  1905. }
  1906. #endif // QTCONFIG_SERVER
  1907. /************************************************************************
  1908.  * Method:
  1909.  *     IHXThreadSafeMethods::IsThreadSafe
  1910.  */
  1911. STDMETHODIMP_(UINT32) CQTFileFormat::IsThreadSafe()
  1912. {
  1913.     return HX_THREADSAFE_METHOD_FF_GETPACKET |
  1914.    HX_THREADSAFE_METHOD_FSR_READDONE;
  1915. }
  1916. /************************************************************************
  1917.  *  IUnknown methods
  1918.  */
  1919. STDMETHODIMP CQTFileFormat::QueryInterface(REFIID riid, void** ppvObj)
  1920. {
  1921.     QInterfaceList qiList[] =
  1922.     {
  1923. { GET_IIDHANDLE(IID_IUnknown), (IUnknown*) (IHXPlugin*) this},
  1924. { GET_IIDHANDLE(IID_IHXPlugin), (IHXPlugin*) this},
  1925. { GET_IIDHANDLE(IID_IHXFileFormatObject), (IHXFileFormatObject*) this},
  1926. { GET_IIDHANDLE(IID_IHXAtomizerResponse), (IHXAtomizerResponse*) this},
  1927. { GET_IIDHANDLE(IID_IHXAtomizationCommander), (IHXAtomizationCommander*) this},
  1928. #ifdef QTCONFIG_ALTERNATE_STREAMS
  1929. { GET_IIDHANDLE(IID_IHXASMSource), (IHXASMSource*) this},
  1930. #endif // QTCONFIG_ALTERNATE_STREAMS
  1931. { GET_IIDHANDLE(IID_IHXPacketFormat), (IHXPacketFormat*) this},
  1932. { GET_IIDHANDLE(IID_IHXFileSwitcher), (IHXFileSwitcher*) m_pFileSwitcher},
  1933. { GET_IIDHANDLE(IID_IHXCommonClassFactory), m_pClassFactory},
  1934. { GET_IIDHANDLE(IID_IHXScheduler), m_pScheduler}
  1935.     };
  1936.     return QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  1937. }
  1938. STDMETHODIMP_(ULONG32) CQTFileFormat::AddRef()
  1939. {
  1940.     return InterlockedIncrement(&m_lRefCount);
  1941. }
  1942. STDMETHODIMP_(ULONG32) CQTFileFormat::Release()
  1943. {
  1944.     if (InterlockedDecrement(&m_lRefCount) > 0)
  1945.     {
  1946.         return m_lRefCount;
  1947.     }
  1948.     delete this;
  1949.     return 0;
  1950. }
  1951. /************************************************************************
  1952.  *  GetFileHeader
  1953.  *  Purpose:
  1954.  * Called by controller to ask the file format for the number of
  1955.  * headers in the file. The file format should call the 
  1956.  * IHXFormatResponse::StreamCountReady() for the IHXFileFormat-
  1957.  * Session object that was passed in during initialization, when the
  1958.  * header count is available.
  1959.  */
  1960. STDMETHODIMP CQTFileFormat::GetFileHeader()
  1961. {
  1962.     HX_RESULT retVal = HXR_UNEXPECTED;
  1963.     if (m_State == QTFF_Ready)
  1964.     {
  1965. if (m_pAtomizer)
  1966. {
  1967.     // This must be the first call to GetFileHeader - Atomize
  1968.     m_State = QTFF_Atomize;
  1969.     retVal = m_pAtomizer->Atomize();
  1970. }
  1971. else
  1972. {
  1973.     retVal = MakeFileHeader(HXR_OK);
  1974. }
  1975.     }
  1976.     
  1977.     return retVal;
  1978. }
  1979. /************************************************************************
  1980.  *  GetStreamHeader
  1981.  *  Purpose:
  1982.  * Called by controller to ask the file format for the header for
  1983.  * a particular stream in the file. The file format should call 
  1984.  * IHXFileFormatResponse::HeaderReady() for the IHXFileFormatResponse
  1985.  * object that was passed in during initialization, when the header
  1986.  * is available.
  1987.  */
  1988. STDMETHODIMP CQTFileFormat::GetStreamHeader(UINT16 unStreamNumber)
  1989. {
  1990.     HX_RESULT retVal;
  1991.     IHXValues* pHeader;
  1992.     retVal = ObtainStreamHeader(unStreamNumber, pHeader);
  1993.     if (SUCCEEDED(retVal))
  1994.     {
  1995. retVal = m_pFFResponse->StreamHeaderReady(retVal, pHeader);
  1996.     }
  1997.     HX_RELEASE(pHeader);
  1998.     return retVal;
  1999. }