[datatype-dev] CR:Changes to support rmra, rmda, rdrf atom in mov file

[datatype-dev] CR:Changes to support rmra, rmda, rdrf atom in mov file

Varun Kathuria vkathuria at real.com
Fri Mar 27 04:10:52 PDT 2009


Hi Eric,

Please find the attached updated diff.
& see replies inline.

Thanks
Varun Kathuria
----- Original Message ----- 
From: "Eric Hyche" <ehyche at real.com>
To: "'Varun Kathuria'" <vkathuria at real.com>;
<datatype-dev at helixcommunity.org>
Sent: Thursday, March 26, 2009 8:41 PM
Subject: RE: [datatype-dev] CR:Changes to support rmra, rmda,rdrf atom in
mov file


> Varun,
>
> Here are my comments:
>
> STDMETHODIMP CQTFileFormat::GetPacket(UINT16 unStreamNumber)
> {
> +    if(m_pRedirectFFObject)
> +    {
> +        return m_pRedirectFFObject->GetPacket(unStreamNumber);
> +    }
> +
>
> You should set the state, like this:
>
> STDMETHODIMP CQTFileFormat::GetPacket(UINT16 unStreamNumber)
> {
> +    if(m_pRedirectFFObject)
> +    {
> +        m_state = QTFF_GetPacket;
> +        return m_pRedirectFFObject->GetPacket(unStreamNumber);
> +    }
> +
>
> STDMETHODIMP CQTFileFormat::Seek(ULONG32 ulOffset)
> {
> +    if(m_pRedirectFFObject)
> +    {
> +        return m_pRedirectFFObject->Seek(ulOffset);
> +    }
> +
>
> Same thing here - set the state to QTFF_SeekPending
> before calling m_pRedirectFFObject->Seek(ulOffset).
>
> STDMETHODIMP CQTFileFormat::SeekDone(HX_RESULT status)
> {
> + if(m_State == QTFF_Atomize)
> + {
> + return m_pFFResponse->SeekDone(status);
> + }
>
> This is not correct. You are assuming here that
> the outer FF always stays in the state QTFF_Atomize.
> It should not.  The state of the outer FF should be
> updating to the correct states even though it is proxying
> calls to the inner FF. The states should be:
>
> - Set to QTFF_Offline upon creation of CQTFileFormat until
>  InitFileFormat is called.
> - Set to QTFF_Init upon call to InitFileFormat and then
>  set to QTFF_Ready when IHXFormatResponse::InitDone() is called.
> - Set to QTFF_Atomize when GetFileHeader() is called and
>  then set back to QTFF_Ready() right before FileHeaderReady() is called.
> - Set to QTFF_GetPacket when GetPacket() is called and
>  returned to QTFF_Ready right before PacketReady() is called.
> - Set the QTFF_SeekPending when Seek() is called
>  and then reset to QTFF_Ready right before SeekDone() is called.
>
> So the code above should be:
>
> STDMETHODIMP CQTFileFormat::SeekDone(HX_RESULT status)
> {
> + if (m_pRedirectFFObject && m_State == QTFF_SeekPending)
> + {
> +           m_State = QTFF_Ready;
> + return m_pFFResponse->SeekDone(status);
> + }
>
>
>
>     }
> -
> +    HX_RELEASE(m_pRedirectFFObject);
>     m_TrackManager.CloseTracks();
> You need to call Close() on the m_pRedirectFFObject
> before releasing it.
>
>
> +                status =
> m_MovieInfo.Init(pRootAtom->FindPresentChild(QT_moov), &m_TrackManager);
> Don't think you need to call pRootAtom->FindPresentChild(QT_moov)
> again here. You already have the moov atom in pMoovAtom
> from above.

Varun: There is no need of calling pRootAtom->FindPresentChild(QT_moov)
again.Replaced it with pMoovAtom

> +                            if(purl.IsRelativeURL())
> +                            {
> +                                //If the URL is relative, then this code
> changes it to absolute URL.
> +                                const char *poriginal_url = NULL;
> +                                m_pRequest->GetURL(poriginal_url);
> +                                const char *prel =
> strrchr(poriginal_url,'/');
> +                                szURL = poriginal_url;
> +                                szURL = szURL.Left(prel-poriginal_url+1);
> +                                szURL += pszReferenceURL;
> +                            }
>
> Has this code been tested? Have you found a
> .mov with a relative URL?

Varun: The code for URL is tested for both relative & absolute URL.

> +                            retVal =
> CreateNewFileFormatObject(szURL.GetBuffer(0));
>
> Why szURL.GetBuffer()? Don't you just need the
> const char* that this CHXString represents? If so,
> then you should just cast the CHXString to const char*, like this:
>
> +                            retVal = CreateNewFileFormatObject((const
> char*) szURL);
>
>
> +                status =
> m_MovieInfo.Init(pRootAtom->FindPresentChild(QT_moov), &m_TrackManager);
> +                if (SUCCEEDED(status))
> +                {
> +                        retVal = HXR_FAIL;
> +                        // Get the Reference Url
> +                        const char* pszReferenceURL = NULL;
> +                        pszReferenceURL = m_MovieInfo.GetRefURL();
> +                        if(pszReferenceURL)
> +                        {
> +                            CHXString szURL="";
> +                            CHXURL purl(pszReferenceURL,m_pContext);
> +                            if(purl.IsRelativeURL())
> +                            {
> +                                //If the URL is relative, then this code
> changes it to absolute URL.
> +                                const char *poriginal_url = NULL;
> +                                m_pRequest->GetURL(poriginal_url);
> +                                const char *prel =
> strrchr(poriginal_url,'/');
> +                                szURL = poriginal_url;
> +                                szURL = szURL.Left(prel-poriginal_url+1);
> +                                szURL += pszReferenceURL;
> +                            }
> +                            else
> +                            {
> +                                szURL = pszReferenceURL;
> +                            }
> +                            retVal =
> CreateNewFileFormatObject(szURL.GetBuffer(0));
> +                        }
> +                }
> +                return retVal;
>
> Make sure you handle the failure case correctly. Right now
> if we fail to create the file format for some reason,
> then the outerFF will hang, since it will just return
> a failure code in AtomReady(), but it will never make
> a call to FileHeaderReady(). This will hang the HXFileSource
> which is waiting on the FileHeaderReady() call.

Varun:     For handling failure case correctly.
                I have replaced
                      +  return retVal
                with
                        + if(SUCCEDDED(retVal))
                        + {
                        +     return retVal
                        + }
Now if we fail to create fileformat due to some reason then it will not
return. It will call MakeFileHeader() in AtomReady() which will call
FileHeaderReady() with in itself & it will not hang filesource.

>    STDMETHOD(GetSupportedPacketFormats)    (THIS_
>     REF(const char**) pFormats);
>
>    STDMETHOD(SetPacketFormat)     (THIS_
>     const char* pFormat);
>
>    STDMETHOD(ConvertFileOffsetToDur)   (THIS_
>                                        UINT32 /*IN*/ ulLastReadOffset,
>                                        UINT32 /*IN*/ ulCompleteFileSize,
>                                        REF(UINT32) /*OUT*/ ulREFDuration);
>
>    STDMETHOD(GetFileDuration)          (THIS_
>                                        UINT32 /*IN*/ ulCompleteFileSize,
>                                        REF(UINT32) /*OUT*/ ulREFDur);
>
> These methods also need to be redirected to the inner FF.

> +        pRequest->SetURL((const char*)purl); // Set the reference URL
> +        pRequestHandler->SetRequest(pRequest);
>
> You probably also need to take the request headers
> from the request passed to the outer FF and copy
> them into this request that is passed to the inner FF.

Varun: I have taken request headers from outer FF & passes them into inner
file format request.

> +    if (FAILED(pPlugin->InitPlugin((IUnknown*) (IHXStreamSource*)this)))
>
> This looks like a cut-n-paste error. CQTFileFormat does not implement
> IHXStreamSource, so this is not correct. The outer FF should
> just pass along the context it received in InitPlugin(). So this
> should just be:
>
> +    if (FAILED(pPlugin->InitPlugin(m_pContext)))
>
> +    theErr =
> m_pRedirectFFObject->InitFileFormat(pRequest,this,pFileObject);
>
> You need to cast the "this" pointer to (IHXFormatResponse*) here.
>
> +    STDMETHODIMP CQTFileFormat::PacketReady(THIS_
> + HX_RESULT status,
> + IHXPacket* pPacket)
> +    {
> +        return m_pFFResponse->PacketReady(status,pPacket);
> +    }
> +
> +    STDMETHODIMP CQTFileFormat::FileHeaderReady (THIS_
> + HX_RESULT status,
> + IHXValues* pHeader)
> +    {
> +        return m_pFFResponse->FileHeaderReady(status,pHeader);
> +    }
> +
> +    STDMETHODIMP CQTFileFormat::StreamHeaderReady (THIS_
> + HX_RESULT status,
> + IHXValues* pHeader)
> +    {
> +        return m_pFFResponse->StreamHeaderReady(status,pHeader);
> +    }
> +
> +    STDMETHODIMP CQTFileFormat::StreamDone(THIS_
> + UINT16 unStreamNumber)
> +    {
> +        return m_pFFResponse->StreamDone(unStreamNumber);
> +    }
> +
>
> In all of these the outer FF needs to reset m_state back to
> the appropriate state before making the IHXFormatResponse call.
>
> +     * IHXFormatResponse methods
> +     */
> +
> +   STDMETHOD(PacketReady) (THIS_
> + HX_RESULT status,
> + IHXPacket* pPacket);
> +
> +    STDMETHOD(FileHeaderReady) (THIS_
> + HX_RESULT status,
> + IHXValues* pHeader) ;
> +
> +    STDMETHOD(StreamHeaderReady) (THIS_
> + HX_RESULT status,
> + IHXValues* pHeader) ;
> +
> +    STDMETHOD(StreamDone) (THIS_
> + UINT16 unStreamNumber) ;
> +
> +    /*
>
> Please include InitDone() and SeekDone() but comment
> them out and include a comment that these methods
> are duplicated in IHXFileResponse, which explains
> why they would be commented out.
>
> +    HX_RESULT  CreateNewFileFormatObject(char* purl);
>
> This should be const char* instead of char*.
>
>
> =======================================
> Eric Hyche (ehyche at real.com)
> Principal Engineer
> RealNetworks, Inc.
>
>
-------------- next part --------------
Index: qtffplin.cpp
===================================================================
RCS file: /cvsroot/datatype/mp4/fileformat/qtffplin.cpp,v
retrieving revision 1.60.2.5
diff -u -r1.60.2.5 qtffplin.cpp
--- qtffplin.cpp	31 Dec 2008 11:22:02 -0000	1.60.2.5
+++ qtffplin.cpp	27 Mar 2009 08:35:54 -0000
@@ -89,6 +89,7 @@
 #include "qtoffsetmpr.h"
 
 #include "metainfokeys.h"
+#include "hxurl.h"
 
 /****************************************************************************
  * Constants
@@ -185,6 +186,7 @@
     , m_pOffsetToTimeMapper(NULL)
     , m_pFileObject(NULL)
     , m_ulNextPacketTime(0)
+    , m_pRedirectFFObject(NULL)
 {
     g_nRefCount_qtff++;
 }
@@ -1651,6 +1653,12 @@
  */
 STDMETHODIMP CQTFileFormat::GetPacket(UINT16 unStreamNumber)
 {
+    if(m_pRedirectFFObject)
+    {
+        m_State = QTFF_GetPacket;
+        return m_pRedirectFFObject->GetPacket(unStreamNumber);
+    }
+
     HX_RESULT retVal;
 
     if (unStreamNumber < m_TrackManager.GetNumStreams())
@@ -1783,6 +1791,12 @@
  */
 STDMETHODIMP CQTFileFormat::Seek(ULONG32 ulOffset)
 {
+    if(m_pRedirectFFObject && m_State == QTFF_Ready)
+    {
+        m_State = QTFF_SeekPending;
+        return m_pRedirectFFObject->Seek(ulOffset);
+    }
+
     UINT16 uStreamNum;
     HX_RESULT retVal = HXR_OK;
 
@@ -1841,6 +1855,11 @@
  */
 STDMETHODIMP CQTFileFormat::SeekDone(HX_RESULT status)
 {
+    if(m_pRedirectFFObject && m_State == QTFF_SeekPending)
+    {
+        m_State = QTFF_Ready;
+        return m_pFFResponse->SeekDone(status);
+    }
     return HXR_UNEXPECTED;
 }
 
@@ -1885,7 +1904,11 @@
 	m_pFileObject->Close();
 	HX_RELEASE(m_pFileObject);
     }
-
+    if(m_pRedirectFFObject)
+    {
+        m_pRedirectFFObject->Close();
+        HX_RELEASE(m_pRedirectFFObject);
+    }
     m_TrackManager.CloseTracks();
 
     return HXR_OK;
@@ -1910,6 +1933,12 @@
 {
     HX_RESULT retVal = HXR_OK;
 
+    if(m_pRedirectFFObject && m_State == QTFF_Init)
+    {	
+        m_State = QTFF_Atomize;
+        return m_pRedirectFFObject->GetFileHeader();
+    }
+
     switch (m_State)
     {
     case QTFF_Init:
@@ -2020,7 +2049,7 @@
 		m_pAtomizer->Close();
 		m_pAtomizer->Release();
 		m_pAtomizer = NULL;
-	    } 
+	    }
 	}
 	else
 	{
@@ -2057,9 +2086,54 @@
 	    }
 	}
 #endif	// QTCONFIG_PACKETIZER_FACTORY
-	
+
 	if (SUCCEEDED(status))
 	{
+        CQT_moov_Atom *pMoovAtom = NULL;
+        pMoovAtom = (CQT_moov_Atom *)pRootAtom->FindPresentChild(QT_moov);
+        if(pMoovAtom)
+        {
+            HX_RESULT retVal = HXR_OK;
+            CQT_mvhd_Atom *pMovieHeaderAtom = NULL;
+            pMovieHeaderAtom = (CQT_mvhd_Atom*)pMoovAtom->FindPresentChild(QT_mvhd);
+            CQT_rmra_Atom *pRmraHeaderAtom = NULL;
+            pRmraHeaderAtom = (CQT_rmra_Atom*)pMoovAtom->FindPresentChild(QT_rmra);
+            if(!pMovieHeaderAtom && pRmraHeaderAtom)
+            {
+                status = m_MovieInfo.Init(pMoovAtom, &m_TrackManager);
+                if (SUCCEEDED(status))
+                {
+                    status = HXR_FAIL;
+                    // Get the Reference Url
+                    const char* pszReferenceURL = NULL;
+                    pszReferenceURL = m_MovieInfo.GetRefURL();
+                    if(pszReferenceURL)
+                    {
+                        CHXString szURL="";
+                        CHXURL purl(pszReferenceURL,m_pContext);
+                        if(purl.IsRelativeURL())
+                        {
+                            //If the URL is relative, then this code changes it to absolute URL.
+                            const char *poriginal_url = NULL;
+                            m_pRequest->GetURL(poriginal_url);
+                            const char *prel = strrchr(poriginal_url,'/');
+                            szURL = poriginal_url;
+                            szURL = szURL.Left(prel-poriginal_url+1);
+                            szURL += pszReferenceURL;
+                        }
+                        else
+                        {
+                            szURL = pszReferenceURL;
+                        }
+                        status = CreateNewFileFormatObject((const char*)szURL);
+                    }
+                }
+                if(SUCCEEDED(status))
+                {						
+                    return status;
+                }
+            }
+        }
 	    HXBOOL bIgnoreHintTracks = FALSE;
 	    do
 	    {
@@ -2169,6 +2243,17 @@
 STDMETHODIMP CQTFileFormat::Subscribe(UINT16 uStreamNum,
 				      UINT16 uRuleNumber)
 {
+    if(m_pRedirectFFObject)
+    {
+        IHXASMSource* pASMSource=NULL;
+        HX_RESULT retVal = HXR_FAIL;
+        if(SUCCEEDED(m_pRedirectFFObject->QueryInterface(IID_IHXASMSource,(void **)&pASMSource)))
+        {	
+            retVal = pASMSource->Subscribe(uStreamNum,uRuleNumber);
+            HX_RELEASE(pASMSource);
+        }
+        return retVal;
+    }
     return m_TrackManager.Subscribe(uStreamNum, uRuleNumber);
 }
 
@@ -2178,6 +2263,17 @@
 STDMETHODIMP CQTFileFormat::Unsubscribe(UINT16 uStreamNum,
 					UINT16 uRuleNumber)
 {
+    if(m_pRedirectFFObject)
+    {
+        IHXASMSource* pASMSource=NULL;
+        HX_RESULT retVal = HXR_FAIL;
+        if(SUCCEEDED(m_pRedirectFFObject->QueryInterface(IID_IHXASMSource,(void **)&pASMSource)))
+        {	
+            retVal = pASMSource->Unsubscribe(uStreamNum,uRuleNumber);
+            HX_RELEASE(pASMSource);
+        }
+        return retVal;
+    }
     return m_TrackManager.Unsubscribe(uStreamNum, uRuleNumber);
 }
 
@@ -2193,6 +2289,17 @@
     REF(const char**) /*OUT*/ pPacketFormats
 )
 {
+    if(m_pRedirectFFObject)
+    {					
+        HX_RESULT retVal = HXR_FAIL;
+        IHXPacketFormat* pPacketFormat = 0;
+        if(SUCCEEDED(m_pRedirectFFObject->QueryInterface (IID_IHXPacketFormat,(void**)&pPacketFormat)))
+        {
+            retVal = pPacketFormat->GetSupportedPacketFormats(pPacketFormats);
+            HX_RELEASE(pPacketFormat);
+        }
+        return retVal;
+    }
     pPacketFormats = (const char**) zm_pPacketFormats;
     return HXR_OK;
 }
@@ -2208,6 +2315,17 @@
     const char* pPacketFormat
 )
 {
+    if(m_pRedirectFFObject)
+    {					
+        HX_RESULT retVal = HXR_FAIL;
+        IHXPacketFormat* pPktFormat = 0;
+        if(SUCCEEDED(m_pRedirectFFObject->QueryInterface(IID_IHXPacketFormat,(void**)&pPktFormat)))
+        {
+            retVal = pPktFormat->SetPacketFormat(pPacketFormat);
+            HX_RELEASE(pPktFormat);
+        }
+        return retVal;
+    }
     if (strcasecmp(pPacketFormat, "rtp") == 0)
     {
         m_ulPacketFormat = QTFF_RTP_FORMAT;
@@ -2256,6 +2374,17 @@
                                       UINT32 /*IN*/ ulCompleteFileSize,
                                       REF(UINT32) /*OUT*/ ulREFDur)
 {
+    if(m_pRedirectFFObject)
+    {					
+        HX_RESULT retVal = HXR_FAIL;
+        IHXMediaBytesToMediaDur* pMediaBytesToMediaDur = 0;
+        if(SUCCEEDED(m_pRedirectFFObject->QueryInterface (IID_IHXMediaBytesToMediaDur,(void**)&pMediaBytesToMediaDur)))
+        {
+            retVal = pMediaBytesToMediaDur->ConvertFileOffsetToDur(ulLastReadOffset,ulCompleteFileSize,ulREFDur);
+            HX_RELEASE(pMediaBytesToMediaDur);
+        }
+        return retVal;
+    }
     HX_RESULT retVal = HXR_OK;
     UINT32 ulDurOut = HX_PROGDOWNLD_UNKNOWN_DURATION;
 
@@ -2339,6 +2468,17 @@
 CQTFileFormat::GetFileDuration(UINT32 /*IN*/ ulCompleteFileSize,
                                REF(UINT32) /*OUT*/ ulREFDur)
 {
+    if(m_pRedirectFFObject)
+    {					
+        HX_RESULT retVal = HXR_FAIL;
+        IHXMediaBytesToMediaDur* pMediaBytesToMediaDur = 0;
+        if(SUCCEEDED(m_pRedirectFFObject->QueryInterface (IID_IHXMediaBytesToMediaDur,(void**)&pMediaBytesToMediaDur)))
+        {
+            retVal = pMediaBytesToMediaDur->GetFileDuration(ulCompleteFileSize,ulREFDur);
+            HX_RELEASE(pMediaBytesToMediaDur);
+        }
+        return retVal;
+    }
     HX_RESULT retVal = HXR_OK;
     UINT32 ulDuration = HX_PROGDOWNLD_UNKNOWN_DURATION;
 
@@ -2905,6 +3045,7 @@
     {
 	{ GET_IIDHANDLE(IID_IUnknown), (IUnknown*) (IHXPlugin*) this},
 	{ GET_IIDHANDLE(IID_IHXPlugin), (IHXPlugin*) this},
+	{ GET_IIDHANDLE(IID_IHXFormatResponse), (IHXFormatResponse*) this},
 	{ GET_IIDHANDLE(IID_IHXFileFormatObject), (IHXFileFormatObject*) this},
 	{ GET_IIDHANDLE(IID_IHXAtomizerResponse), (IHXAtomizerResponse*) this},
 	{ GET_IIDHANDLE(IID_IHXAtomizationCommander), (IHXAtomizationCommander*) this},
@@ -3003,6 +3144,11 @@
  */
 STDMETHODIMP CQTFileFormat::GetStreamHeader(UINT16 unStreamNumber)
 {
+    if(m_pRedirectFFObject && m_State == QTFF_Ready)
+    {
+        return m_pRedirectFFObject->GetStreamHeader(unStreamNumber);
+    }
+
     HX_RESULT retVal;
     IHXValues* pHeader;
 
@@ -3015,3 +3161,186 @@
     return retVal;
 }
 
+HX_RESULT CQTFileFormat::CreateNewFileFormatObject(const char* purl)
+{
+    HX_RESULT theErr = HXR_FAIL;
+    char*   pExtension = "mov"; //rmra can only contain QuickTime movie reference
+    IHXPluginHandler3* pPlugin2Handler3 = NULL;
+    IHXPlugin*  pPlugin      = NULL;
+    IUnknown* pCurrentFileFormatUnk = NULL;
+    IHXPluginSearchEnumerator* pFileFormatEnumerator = NULL;
+    IHXFileObject* pFileObject = NULL;
+    IHXRequest* pRequest = NULL;
+    IUnknown*	    pUnknown = NULL;
+    IUnknown*	    pObject = NULL;
+    IHXFileSystemObject* pFSObject = NULL;
+    IHXPlugin2Handler* pPlugin2Handler = NULL;
+    IHXPlugin *pHXPlugin = NULL;
+    IHXRequestHandler* pRequestHandler=NULL;
+
+    const char* pProtocolEnd = HXFindChar(purl,':');
+    if (!pProtocolEnd)
+    {
+        return HXR_UNEXPECTED;
+    }
+
+    int nLength = pProtocolEnd - purl;
+    CHXString strProtocol(purl,nLength);
+
+    if (FAILED(m_pContext->QueryInterface(IID_IHXPlugin2Handler, (void**)&pPlugin2Handler)))
+    {
+        goto exit;
+    }
+
+    if (FAILED( pPlugin2Handler->FindPluginUsingStrings(PLUGIN_CLASS, PLUGIN_FILESYSTEM_TYPE, 
+        PLUGIN_FILESYSTEMPROTOCOL, (char*)(const char*)strProtocol, NULL, NULL, pUnknown)))
+    {
+        goto exit;
+    }
+
+    if(FAILED(pUnknown->QueryInterface(IID_IHXFileSystemObject, (void**) &pFSObject)))
+    {
+        goto exit;
+    }
+
+    if (FAILED (pFSObject->QueryInterface(IID_IHXPlugin,(void**)&pHXPlugin)))
+    {
+        goto exit;
+    }
+
+    if (FAILED(pHXPlugin->InitPlugin(m_pContext)))
+    {
+        goto exit;
+    }
+
+    if (FAILED(pFSObject->CreateFile(&pObject)))
+    {
+        goto exit;
+    }
+
+    if (FAILED(pObject->QueryInterface(IID_IHXFileObject, (void**)&pFileObject)))
+    {
+        goto exit;
+    }
+
+    if (FAILED(pObject->QueryInterface(IID_IHXRequestHandler, (void**)&pRequestHandler)))
+    {
+        goto exit;
+    }
+
+    if(m_pClassFactory && (HXR_OK !=m_pClassFactory->CreateInstance(CLSID_IHXRequest, (void**) &pRequest)))
+    {
+        goto exit;
+    }
+
+    if (pRequest)
+    {
+        IHXValues* pRequestHeaders = NULL;
+        pRequest->SetURL((const char*)purl); // Set the reference URL
+        if (SUCCEEDED(m_pRequest->GetRequestHeaders(pRequestHeaders)) && pRequestHeaders)
+        {
+            pRequest->SetRequestHeaders(pRequestHeaders);
+            pRequestHeaders->Release();
+        }
+        pRequestHandler->SetRequest(pRequest);
+    }
+	
+    if(m_pContext && (HXR_OK != m_pContext->QueryInterface(IID_IHXPluginHandler3, (void**) &pPlugin2Handler3)))
+    {
+        goto exit;
+    }
+
+    if (FAILED(pPlugin2Handler3->FindGroupOfPluginsUsingStrings(PLUGIN_CLASS, PLUGIN_FILEFORMAT_TYPE, 
+            PLUGIN_FILEEXTENSIONS, pExtension, 0 ,0, pFileFormatEnumerator)))
+    {
+        goto exit;
+    }
+
+    if (pFileFormatEnumerator)
+    {
+        pFileFormatEnumerator->GetNextPlugin(pCurrentFileFormatUnk, NULL);
+        HX_ASSERT(pCurrentFileFormatUnk != NULL);
+    }
+
+    if (FAILED( pCurrentFileFormatUnk->QueryInterface(IID_IHXFileFormatObject, (void**) &m_pRedirectFFObject)))
+    {
+        goto exit;
+    }
+    m_State = QTFF_Offline; 
+    if (FAILED(m_pRedirectFFObject->QueryInterface(IID_IHXPlugin,(void**)&pPlugin)))
+    {
+        goto exit;
+    }
+
+    if (FAILED(pPlugin->InitPlugin(m_pContext)))
+    {
+        goto exit;
+    }
+    m_State = QTFF_Init;
+    theErr = m_pRedirectFFObject->InitFileFormat(pRequest,(IHXFormatResponse*)this,pFileObject);
+
+exit:
+    HX_RELEASE(pPlugin2Handler);
+    HX_RELEASE(pUnknown);
+    HX_RELEASE(pFSObject);
+    HX_RELEASE(pHXPlugin);
+    HX_RELEASE(pObject);
+    HX_RELEASE(pFileObject);
+    HX_RELEASE(pRequestHandler);
+    HX_RELEASE(pRequest);
+    HX_RELEASE(pPlugin2Handler3);
+    HX_RELEASE(pFileFormatEnumerator);
+    HX_RELEASE(pCurrentFileFormatUnk);
+    HX_RELEASE(pPlugin);
+    return theErr;
+}
+
+    STDMETHODIMP CQTFileFormat::PacketReady(THIS_
+					HX_RESULT	status,
+					IHXPacket*	pPacket)
+    {
+        HX_RESULT retVal = HXR_FAIL;
+        if(m_pRedirectFFObject)
+        {
+            m_State = QTFF_Ready;		
+            retVal = m_pFFResponse->PacketReady(status,pPacket);
+        }
+        return retVal;
+    }
+
+    STDMETHODIMP CQTFileFormat::FileHeaderReady	(THIS_
+					HX_RESULT	status,
+					IHXValues*	pHeader) 
+    {
+        HX_RESULT retVal = HXR_FAIL;
+        if(m_pRedirectFFObject && m_State==QTFF_Atomize)
+        {
+            m_State = QTFF_Ready;
+            retVal = m_pFFResponse->FileHeaderReady(status,pHeader);
+        }
+        return retVal;
+    }
+    
+    STDMETHODIMP CQTFileFormat::StreamHeaderReady	(THIS_
+					HX_RESULT	status,
+					IHXValues*	pHeader) 
+    {
+        HX_RESULT retVal = HXR_FAIL;
+        if(m_pRedirectFFObject && m_State == QTFF_Ready)
+        {
+            retVal = m_pFFResponse->StreamHeaderReady(status,pHeader);
+        }
+        return retVal;
+    }
+    
+    STDMETHODIMP CQTFileFormat::StreamDone(THIS_
+					UINT16		unStreamNumber)
+    {
+        HX_RESULT retVal = HXR_FAIL;
+        if(m_pRedirectFFObject)
+        {
+            retVal = m_pFFResponse->StreamDone(unStreamNumber);
+        }
+        return retVal;
+    }
+
Index: pub/qtffplin.h
===================================================================
RCS file: /cvsroot/datatype/mp4/fileformat/pub/qtffplin.h,v
retrieving revision 1.17.8.2
diff -u -r1.17.8.2 qtffplin.h
--- pub/qtffplin.h	28 Apr 2008 17:30:19 -0000	1.17.8.2
+++ pub/qtffplin.h	27 Mar 2009 08:35:54 -0000
@@ -84,6 +84,7 @@
  */
 class CQTFileFormat :	public IHXPlugin, 
 			public IHXFileFormatObject, 
+			public IHXFormatResponse,
 			public IHXFileResponse,
 			public IHXAtomizationCommander,
 			public IHXAtomizerResponse,
@@ -171,6 +172,36 @@
 			    HX_RESULT status);
 
     /*
+     *	IHXFormatResponse methods
+     */
+
+   STDMETHOD(PacketReady)		(THIS_
+					HX_RESULT	status,
+					IHXPacket*	pPacket);
+
+    STDMETHOD(FileHeaderReady)		(THIS_
+					HX_RESULT	status,
+					IHXValues*	pHeader) ;
+
+    STDMETHOD(StreamHeaderReady)	(THIS_
+					HX_RESULT	status,
+					IHXValues*	pHeader) ;
+
+    STDMETHOD(StreamDone)		(THIS_
+					UINT16		unStreamNumber) ;
+
+    /*
+        These methods are duplicated in IHXFileResponse.			    
+
+        STDMETHOD(InitDone)	    (THIS_
+     	        	            HX_RESULT status);
+     
+        STDMETHOD(SeekDone)	    (THIS_ 
+     		                    HX_RESULT status);
+     
+    */
+
+    /*
      *	IHXAtomizationCommander
      */
     STDMETHOD_(QTAtomizerCmd,GetAtomCommand)	(THIS_
@@ -309,7 +340,7 @@
     HX_RESULT GetResourceErrorString(UINT32 ulErrorID, CHXString& rErrorStr);
 
     void  WarnIfNotHinted(HX_RESULT status, HXBOOL bIgnoreHintTracks);
-    
+    HX_RESULT  CreateNewFileFormatObject(const char* purl);
     IHXScheduler* m_pScheduler;
 
     IHXErrorMessages*	m_pErrorMessages;
@@ -365,6 +396,7 @@
     CQTOffsetToTimeMapper* m_pOffsetToTimeMapper;
     IHXFileObject*  m_pFileObject;
     UINT32 m_ulNextPacketTime;	// in milliseconds
+    IHXFileFormatObject*   m_pRedirectFFObject;
 };
 
 


More information about the Datatype-dev mailing list
 

Site Map   |   Terms of Use   |   Privacy Policy   |   Contact Us

Copyright © 1995-2007 RealNetworks, Inc. All rights reserved. RealNetworks and Helix are trademarks of RealNetworks.
All other trademarks or registered trademarks are the property of their respective holders.