[Helix-client-dev] CR: Added UITS-atom logic to modules needed by GMPMetaEditor

Petar Basic <[email protected]> Tue, 2 Nov 2010 17:30:04 +0100
Newsgroups gmane.comp.multimedia.helix.devel
Message-ID <[email protected]>
Modified by: pbasic at real dot com
Date: 2010/11/02
Project: GMP MetaEditor (meta3gp.exe)

Synopsis:
Added UITS-atom logic to modules needed by GMPMetaEditor

Overview:
UITS Technical Specification V1.1 requires that UITS data be formatted
as BLOB inside a special UITS atom when stored within MP4-based file.
Current implementations of MP4 modules read/store UITS data within a
private frame inside ID32 atom.  The change proposed below brings
Helix implementation up to date with UITS spec V1.1.

Details:
1.) MP4 file-format changes:
--Added reading and processing of UITS atom (moov/udta/UITS).
--UITS data is still read from legacy position i.e. ID32 atom in case
there is no UITS atom present.

2.) MP4 file-writer changes:
--Added writing of UITS atom (moov/udta/UITS).
--By default, MP4 file-writer writes UITS metadata to UITS atom.
--Writer can be instructed via "MetaDataUITSLocation" FFDriver
property to output UITS data to legacy location i.e. ID32 atom.

3.) FFDriver updates:
--Introduced FFDriver "MetaDataUITSLocation" option which is intended
as instruction to file-writers.

4.) Metaeditor executable changes:
--Added "uitslocid32" command line option which forces output of UITS
data to ID32 atom.  This can be used to produce the same format of
output file as with previous Metaeditor versions.

Files Modified:
datatype/mp4/fileformat/qtatmmgs.cpp
datatype/mp4/fileformat/qtatoms.cpp
datatype/mp4/fileformat/qtffplin.cpp
datatype/mp4/fileformat/pub/qtatmmgs.h
datatype/mp4/fileformat/pub/qtatoms.h
datatype/mp4/fileformat/pub/qtffplin.h
datatype/mp4/filewriter/mp4atoms.h
datatype/mp4/filewriter/mp4sm.cpp
datatype/mp4/filewriter/mp4sm.h
datatype/tools/dtdriver/apps/meta3gp/main.cpp
datatype/tools/dtdriver/engine/ffdriver.cpp
datatype/tools/dtdriver/engine/pub/ffdriver.h

Platforms and Profiles Affected:
All

Image Size and Heap Use impact:
Small increase

Platforms and Profiles Build Verified:
system id: win32-i386-vc7, sunos-5.8-sparc-gcc-server
profile: helix-client-all-defines

Platforms and Profiles Functionality Verified:
x86 Windows XP SP2
Sparc SunOS 5.10

Branch:
GMPMetaEditor

Copyright assignment:
I am a RealNetworks employee or contractor.

_______________________________________________
Helix-client-dev mailing list
[email protected]
http://lists.helixcommunity.org/mailman/listinfo/helix-client-dev
datatype_mp4_fileformat.diff (application/octet-stream, 31.5 KB)
Index: datatype/mp4/fileformat/qtatmmgs.cpp
===================================================================
RCS file: /cvsroot/datatype/mp4/fileformat/qtatmmgs.cpp,v
retrieving revision 1.68
diff -w -U 30 -r1.68 qtatmmgs.cpp
--- datatype/mp4/fileformat/qtatmmgs.cpp	6 Jan 2010 16:17:16 -0000	1.68
+++ datatype/mp4/fileformat/qtatmmgs.cpp	2 Nov 2010 15:12:27 -0000
@@ -3401,177 +3401,189 @@
     , m_pAlbmAtom(NULL)
     , m_pYrrcAtom(NULL)
     , m_pID32Atom(NULL)
 #endif // QTCONFIG_3GPP_METAINFO
 
 #ifdef QTCONFIG_ITUNES_METAINFO
     , m_piTunesDataAtomA9nam(NULL)
     , m_piTunesDataAtomA9ART(NULL)
     , m_piTunesDataAtomA9alb(NULL)
     , m_piTunesDataAtomA9gen(NULL)
     , m_piTunesDataAtomA9day(NULL)
     , m_piTunesDataAtomA9cmt(NULL)
     , m_piTunesDataAtomA9wrt(NULL)
     , m_piTunesDataAtomA9too(NULL)
     , m_piTunesDataAtomA9enc(NULL)
     , m_piTunesDataAtomA9grp(NULL)
     , m_piTunesDataAtomgrup(NULL)
     , m_piTunesDataAtomaART(NULL)
     , m_piTunesDataAtomcprt(NULL)
     , m_piTunesDataAtomA9st3(NULL)
     , m_piTunesDataAtomA9lyr(NULL)
     , m_piTunesDataAtomtmpo(NULL)
     , m_piTunesDataAtomcpil(NULL)
     , m_piTunesDataAtomrtng(NULL)
     , m_piTunesDataAtomtrkn(NULL)
     , m_piTunesDataAtomdisk(NULL)
     , m_piTunesDataAtomgnre(NULL)
     , m_piTunesItemAtomcovr(NULL)
 #endif //QTCONFIG_ITUNES_METAINFO
 
+#if defined(QTCONFIG_3GPP_METAINFO) || defined(QTCONFIG_ITUNES_METAINFO)
+    , m_pUITSAtom(NULL)
+#endif //defined(QTCONFIG_3GPP_METAINFO) || defined(QTCONFIG_ITUNES_METAINFO)
+
     , m_pRTPSDPAtom(NULL)
     , m_pRefURL(NULL)
 {
     ;
 }
 
 CQT_MovieInfo_Manager::~CQT_MovieInfo_Manager()
 {
     Clear();
 }
 
 void CQT_MovieInfo_Manager::Clear()
 {
     HX_RELEASE(m_pNameAtom);
 
 #ifdef QTCONFIG_3GPP_TAC
     HX_RELEASE(m_pTitlAtom);
     HX_RELEASE(m_pAuthAtom);
     HX_RELEASE(m_pCprtAtom);
 #endif // QTCONFIG_3GPP_TAC
 #ifdef QTCONFIG_3GPP_METAINFO
     HX_RELEASE(m_pDscpAtom);
     HX_RELEASE(m_pPerfAtom);
     HX_RELEASE(m_pGnreAtom);
     HX_RELEASE(m_pRtngAtom);
     HX_RELEASE(m_pClsfAtom);
     HX_RELEASE(m_pKywdAtom);
     HX_RELEASE(m_pLociAtom);
     HX_RELEASE(m_pAlbmAtom);
     HX_RELEASE(m_pYrrcAtom);
     HX_RELEASE(m_pID32Atom);
 #endif // QTCONFIG_3GPP_METAINFO
 
 #ifdef QTCONFIG_ITUNES_METAINFO
     HX_RELEASE(m_piTunesDataAtomA9nam);
     HX_RELEASE(m_piTunesDataAtomA9ART);
     HX_RELEASE(m_piTunesDataAtomA9alb);
     HX_RELEASE(m_piTunesDataAtomA9gen);
     HX_RELEASE(m_piTunesDataAtomA9day);
     HX_RELEASE(m_piTunesDataAtomA9cmt);
     HX_RELEASE(m_piTunesDataAtomA9wrt);
     HX_RELEASE(m_piTunesDataAtomA9too);
     HX_RELEASE(m_piTunesDataAtomA9enc);
     HX_RELEASE(m_piTunesDataAtomA9grp);
     HX_RELEASE(m_piTunesDataAtomgrup);
     HX_RELEASE(m_piTunesDataAtomaART);
     HX_RELEASE(m_piTunesDataAtomcprt);
     HX_RELEASE(m_piTunesDataAtomA9st3);
     HX_RELEASE(m_piTunesDataAtomA9lyr);
     HX_RELEASE(m_piTunesDataAtomtmpo);
     HX_RELEASE(m_piTunesDataAtomcpil);
     HX_RELEASE(m_piTunesDataAtomrtng);
     HX_RELEASE(m_piTunesDataAtomtrkn);
     HX_RELEASE(m_piTunesDataAtomdisk);
     HX_RELEASE(m_piTunesDataAtomgnre);
     HX_RELEASE(m_piTunesItemAtomcovr);
 #endif //QTCONFIG_ITUNES_METAINFO
 
+#if defined(QTCONFIG_3GPP_METAINFO) || defined(QTCONFIG_ITUNES_METAINFO)
+    HX_RELEASE(m_pUITSAtom);
+#endif //defined(QTCONFIG_3GPP_METAINFO) || defined(QTCONFIG_ITUNES_METAINFO)
+
     HX_VECTOR_DELETE(m_pRefURL);
     HX_RELEASE(m_pRTPSDPAtom);
 }
 
 /****************************************************************************
  *  Main Interface
  */
 HX_RESULT CQT_MovieInfo_Manager::Init(CQTAtom* pAtom,
 				      CQTTrackManager* pTrackManager)
 {
     HX_RESULT retVal;
 
     m_ulMovieTimeScale = 0;
     m_ulMovieDuration = 0;
     HX_RELEASE(m_pNameAtom);
 
 #ifdef QTCONFIG_3GPP_TAC
     HX_RELEASE(m_pTitlAtom);
     HX_RELEASE(m_pAuthAtom);
     HX_RELEASE(m_pCprtAtom);
 #endif // QTCONFIG_3GPP_TAC
 #ifdef QTCONFIG_3GPP_METAINFO
     HX_RELEASE(m_pDscpAtom);
     HX_RELEASE(m_pPerfAtom);
     HX_RELEASE(m_pGnreAtom);
     HX_RELEASE(m_pRtngAtom);
     HX_RELEASE(m_pClsfAtom);
     HX_RELEASE(m_pKywdAtom);
     HX_RELEASE(m_pLociAtom);
     HX_RELEASE(m_pAlbmAtom);
     HX_RELEASE(m_pYrrcAtom);
     HX_RELEASE(m_pID32Atom);
 #endif // QTCONFIG_3GPP_METAINFO
 
 #ifdef QTCONFIG_ITUNES_METAINFO
     HX_RELEASE(m_piTunesDataAtomA9nam);
     HX_RELEASE(m_piTunesDataAtomA9ART);
     HX_RELEASE(m_piTunesDataAtomA9alb);
     HX_RELEASE(m_piTunesDataAtomA9gen);
     HX_RELEASE(m_piTunesDataAtomA9day);
     HX_RELEASE(m_piTunesDataAtomA9cmt);
     HX_RELEASE(m_piTunesDataAtomA9wrt);
     HX_RELEASE(m_piTunesDataAtomA9too);
     HX_RELEASE(m_piTunesDataAtomA9enc);
     HX_RELEASE(m_piTunesDataAtomA9grp);
     HX_RELEASE(m_piTunesDataAtomgrup);
     HX_RELEASE(m_piTunesDataAtomaART);
     HX_RELEASE(m_piTunesDataAtomcprt);
     HX_RELEASE(m_piTunesDataAtomA9st3);
     HX_RELEASE(m_piTunesDataAtomA9lyr);
     HX_RELEASE(m_piTunesDataAtomtmpo);
     HX_RELEASE(m_piTunesDataAtomcpil);
     HX_RELEASE(m_piTunesDataAtomrtng);
     HX_RELEASE(m_piTunesDataAtomtrkn);
     HX_RELEASE(m_piTunesDataAtomdisk);
     HX_RELEASE(m_piTunesDataAtomgnre);
     HX_RELEASE(m_piTunesItemAtomcovr);
 #endif //QTCONFIG_ITUNES_METAINFO
 
+#if defined(QTCONFIG_3GPP_METAINFO) || defined(QTCONFIG_ITUNES_METAINFO)
+    HX_RELEASE(m_pUITSAtom);
+#endif //defined(QTCONFIG_3GPP_METAINFO) || defined(QTCONFIG_ITUNES_METAINFO)
+
     HX_RELEASE(m_pRTPSDPAtom);
 
     if (pAtom && (pAtom->GetType() != QT_moov))
     {
 	pAtom = NULL;
     }
 
 #ifdef QTCONFIG_3GPP_METAINFO
     m_pID32Atom = FindID32Atom((CQT_moov_Atom*)pAtom);
     if(m_pID32Atom)
     {
         m_pID32Atom->AddRef();
     }
 #endif // QTCONFIG_3GPP_METAINFO
 
     if (pAtom)
     {
 	CQT_mvhd_Atom *pMovieHeaderAtom = NULL;
 
 	pMovieHeaderAtom = (CQT_mvhd_Atom*)
 			   pAtom->FindPresentChild(QT_mvhd);
 
 	CQT_rmra_Atom *pRmraHeaderAtom = NULL;
 	pRmraHeaderAtom = (CQT_rmra_Atom*)
 			   pAtom->FindPresentChild(QT_rmra);
 	if (pMovieHeaderAtom)
 	{
 	    m_ulMovieTimeScale = pMovieHeaderAtom->Get_TimeScale();
 	    m_ulMovieDuration = pMovieHeaderAtom->Get_Duration();
 	}
@@ -3610,60 +3622,68 @@
             }
             return retVal;
         }
 	else
 	{
 	    pAtom = NULL;
 	}
     }
 
 #ifdef QTCONFIG_FRAGMENTS
     if (pAtom)
     {
         CQT_mvex_Atom* pMvex = (CQT_mvex_Atom*)pAtom->FindPresentChild(QT_mvex);
         if (pMvex)
         {
             m_bFragmented = TRUE;
             CQT_mehd_Atom* pMehd = (CQT_mehd_Atom*)pMvex->FindPresentChild(QT_mehd);
             if (pMehd)
             {
                 m_ulMovieDuration = pMehd->Get_Duration();
             }
         }
     }
 #endif /* QTCONFIG_FRAGMENTS */
 
     if (pAtom)
     {
 	pAtom = pAtom->FindPresentChild(QT_udta);
     }
 
+#if defined(QTCONFIG_3GPP_METAINFO) || defined(QTCONFIG_ITUNES_METAINFO)
+    m_pUITSAtom = FindUITSAtom((CQT_udta_Atom*)pAtom);
+    if(m_pUITSAtom)
+    {
+        m_pUITSAtom->AddRef();
+    }
+#endif //defined(QTCONFIG_3GPP_METAINFO) || defined(QTCONFIG_ITUNES_METAINFO)
+
     if (pAtom)
     {
 	m_pNameAtom = (CQT_name_Atom*) pAtom->FindPresentChild(QT_name);
 	if (m_pNameAtom)
 	{
 	    m_pNameAtom->AddRef();
 	}
 
 #ifdef QTCONFIG_3GPP_TAC
         m_pTitlAtom = (CQT_titl_Atom*) pAtom->FindPresentChild(QT_titl);
         if (m_pTitlAtom)
         {
             m_pTitlAtom->AddRef();
         }
 
         m_pAuthAtom = (CQT_auth_Atom*) pAtom->FindPresentChild(QT_auth);
         if (m_pAuthAtom)
         {
             m_pAuthAtom->AddRef();
         }
 
         m_pCprtAtom = (CQT_cprt_Atom*) pAtom->FindPresentChild(QT_cprt);
         if (m_pCprtAtom)
         {
             m_pCprtAtom->AddRef();
         }
 #endif // QTCONFIG_3GPP_TAC
 #ifdef QTCONFIG_3GPP_METAINFO
         m_pDscpAtom = (CQT_dscp_Atom*) pAtom->FindPresentChild(QT_dscp);
         if (m_pDscpAtom)
@@ -3914,50 +3934,61 @@
 CQT_ID32_Atom* CQT_MovieInfo_Manager::FindID32Atom(CQT_moov_Atom* pMoovAtom)
 {
     CQT_ID32_Atom* pID32Atom = NULL;
 
     // We must have 'moov' atom, otherwise the file is not valid
     if(pMoovAtom)
     {
         // At most one 'meta' atom may be present at multiple levels: file, 'moov', 'trak'.
         // This procedure searches for first existing 'ID32' atom by checking 'meta' atoms in the following order:
         // 1) 'moov' level
         // 2) file level
         // 3) 'trak' levels are handled by track info manager
 
         // Check 'moov' level
         pID32Atom = CQT_ManagerTools::FindID32Atom(CQT_ManagerTools::FindMetaAtom(pMoovAtom));
 
         // Check file level
         if(!pID32Atom)
         {
             CQTAtom* pRootAtom = pMoovAtom->GetParent();
             if(pRootAtom && pRootAtom->GetType() == QT_HXROOT)
             {
                 pID32Atom = CQT_ManagerTools::FindID32Atom(CQT_ManagerTools::FindMetaAtom(pRootAtom));
             }
         }
     }
     return pID32Atom;
 }
 #endif //QTCONFIG_3GPP_METAINFO
 
+#if defined(QTCONFIG_3GPP_METAINFO) || defined(QTCONFIG_ITUNES_METAINFO)
+CQT_UITS_Atom* CQT_MovieInfo_Manager::FindUITSAtom(CQT_udta_Atom* pUdtaAtom)
+{
+    if(pUdtaAtom)
+    {
+        return (CQT_UITS_Atom*)pUdtaAtom->FindPresentChild(QT_UITS);
+    }
+    return 0;
+}
+#endif //defined(QTCONFIG_3GPP_METAINFO) || defined(QTCONFIG_ITUNES_METAINFO)
+
 #ifdef QTCONFIG_ITUNES_METAINFO
 UINT32 CQT_MovieInfo_Manager::GetiTunesReleaseDateYear(void)
 {
     const char* szReleaseDate = (const char*)(m_piTunesDataAtomA9day ? m_piTunesDataAtomA9day->GetStringValue() : 0);
     if(szReleaseDate)
     {
         char szYear[5];
 
         memset(szYear, 0, 5);
         strncpy(szYear, szReleaseDate, 4);
 
         long iYear = strtol(szYear, 0, 10);
         if(iYear > 0)
         {
             return UINT32(iYear);
         }
     }
     return 0;
 }
 #endif //QTCONFIG_ITUNES_METAINFO
Index: datatype/mp4/fileformat/qtatoms.cpp
===================================================================
RCS file: /cvsroot/datatype/mp4/fileformat/qtatoms.cpp,v
retrieving revision 1.16
diff -w -U 30 -r1.16 qtatoms.cpp
--- datatype/mp4/fileformat/qtatoms.cpp	9 Nov 2009 19:49:21 -0000	1.16
+++ datatype/mp4/fileformat/qtatoms.cpp	2 Nov 2010 15:12:28 -0000
@@ -105,60 +105,63 @@
 #if defined(QTCONFIG_3GPP_METAINFO) || defined(QTCONFIG_ITUNES_METAINFO)
     case QT_rtng:
 #ifdef QTCONFIG_3GPP_METAINFO
         if (pCurrentRoot && pCurrentRoot->GetType() == QT_udta)
         {
             return new CQT_rtng_Atom(ulOffset, ulSize, pParent);
         }
 #endif //QTCONFIG_3GPP_METAINFO
 #ifdef QTCONFIG_ITUNES_METAINFO
         if (pCurrentRoot && pCurrentRoot->GetType() == QT_ilst)
         {
             return new CQT_iTunes_rtng_Atom(ulOffset, ulSize, pParent);
         }
 #endif //QTCONFIG_ITUNES_METAINFO
         break;
 
     case QT_gnre:
 #ifdef QTCONFIG_3GPP_METAINFO
         if (pCurrentRoot && pCurrentRoot->GetType() == QT_udta)
         {
             return new CQT_gnre_Atom(ulOffset, ulSize, pParent);
         }
 #endif //QTCONFIG_3GPP_METAINFO
 #ifdef QTCONFIG_ITUNES_METAINFO
         if (pCurrentRoot && pCurrentRoot->GetType() == QT_ilst)
         {
             return new CQT_iTunes_gnre_Atom(ulOffset, ulSize, pParent);
         }
 #endif //QTCONFIG_ITUNES_METAINFO
         break;
+
+    case QT_UITS:
+        return new CQT_UITS_Atom(ulOffset, ulSize, pParent);
 #endif //defined(QTCONFIG_3GPP_METAINFO) || defined(QTCONFIG_ITUNES_METAINFO)
 
 
 #ifdef QTCONFIG_3GPP_TAC
     // 3GPP Asset Info atom types
     case QT_titl:
         return new CQT_titl_Atom(ulOffset, ulSize, pParent);
     case QT_auth:
         return new CQT_auth_Atom(ulOffset, ulSize, pParent);
 #endif // QTCONFIG_3GPP_TAC
 #ifdef QTCONFIG_3GPP_METAINFO
     case QT_dscp:
         return new CQT_dscp_Atom(ulOffset, ulSize, pParent);
     case QT_perf:
         return new CQT_perf_Atom(ulOffset, ulSize, pParent);
     case QT_clsf:
         return new CQT_clsf_Atom(ulOffset, ulSize, pParent);
     case QT_kywd:
         return new CQT_kywd_Atom(ulOffset, ulSize, pParent);
     case QT_loci:
         return new CQT_loci_Atom(ulOffset, ulSize, pParent);
     case QT_albm:
         return new CQT_albm_Atom(ulOffset, ulSize, pParent);
     case QT_yrrc:
         return new CQT_yrrc_Atom(ulOffset, ulSize, pParent);
     case QT_ID32:
         return new CQT_ID32_Atom(ulOffset, ulSize, pParent);
 #endif // QTCONFIG_3GPP_METAINFO
 
 #ifdef QTCONFIG_ITUNES_METAINFO
Index: datatype/mp4/fileformat/qtffplin.cpp
===================================================================
RCS file: /cvsroot/datatype/mp4/fileformat/qtffplin.cpp,v
retrieving revision 1.84
diff -w -U 30 -r1.84 qtffplin.cpp
--- datatype/mp4/fileformat/qtffplin.cpp	6 Jan 2010 16:17:16 -0000	1.84
+++ datatype/mp4/fileformat/qtffplin.cpp	2 Nov 2010 15:12:33 -0000
@@ -1038,60 +1038,79 @@
                 }
 
                 // inject frame into the header
                 if(SUCCEEDED(status) && pFrame)
                 {
                     char key[128];
                     sprintf(key, _ITUNES_META_INFO_PICTURE_KEY, int(iAPICDataIndex));
 
                     status = pFrame->SerializeToBufferProperty(m_pContext, pHeader, key);
                 }
 
                 // update image count property
                 if(SUCCEEDED(status))
                 {
                     iAPICDataIndex++;
 
                     PropTools::CopyPropertyULONG32(pHeader, TRUE, iAPICDataIndex,
                                         _GENERIC_META_INFO_PICTURE_COUNT_KEY, TRUE);
                 }
 
                 // cleanup
                 delete pFrame;
             }
         }
     }
 
     return status;
 }
 #endif //QTCONFIG_ITUNES_METAINFO
 
+#if defined(QTCONFIG_3GPP_METAINFO) || defined(QTCONFIG_ITUNES_METAINFO)
+HX_RESULT CQTFileFormat::ExtractUITSInfoToHeader(HX_RESULT status, IHXValues* pHeader)
+{
+    if(SUCCEEDED(status) && m_MovieInfo.GetUITSBlobSize())
+    {
+        HX_TEXT_ENCODING_TYPE enc = HX_TEXT_ENCODING_TYPE_UNKNOWN;
+        status = MetaInfo::ScanXMLStringEncoding(m_MovieInfo.GetUITSBlob(), m_MovieInfo.GetUITSBlobSize(), enc);
+
+        if(SUCCEEDED(status))
+        {
+            status = UpdateHeaderProperty(status, pHeader, _GENERIC_META_INFO_UITS_KEY,
+                        (const char*)m_MovieInfo.GetUITSBlob(), m_MovieInfo.GetUITSBlobSize(), enc);
+        }
+    }
+
+    return status;
+}
+#endif //defined(QTCONFIG_3GPP_METAINFO) || defined(QTCONFIG_ITUNES_METAINFO)
+
 HX_RESULT CQTFileFormat::MakeFileHeader(HX_RESULT status)
 {
     HX_RESULT retVal;
     IHXValues* pHeader = NULL;
 
     // Check the license
 #ifdef QTCONFIG_SERVER
     if (SUCCEEDED(status) && (m_TrackManager.GetEType() == QT_ETYPE_SERVER))
     {
         switch (m_TrackManager.GetFType())
         {
             case QT_FTYPE_QT:
             case QT_FTYPE_UNKNOWN:
             {
                 if(!m_bQTLicensed)
                 {
                     ReportError(IDS_ERR_QT_NOTLICENSED, HXR_NOT_LICENSED);
                     return m_pFFResponse->FileHeaderReady(
                         HXR_NOT_LICENSED, NULL);
                 }
                 break;
             }
             case QT_FTYPE_MP4:
             {
 		UINT32 ulBrand = 0;
 		m_TrackManager.GetMajorBrand(&ulBrand);
 
 		switch (ulBrand)
 		{
 		// If major brand is a rel6 brand, check that the 3GPP rel6 license is enabled
@@ -1235,60 +1254,68 @@
     UINT32 uliTunesExtractorIndex = 0;
     UINT32 ul3GPPExtractorIndex = 1;
 
     // M4A case: If we're reading M4A branded file, extract iTunes-info last to override
     // any meta-info obtained by other means.
     UINT32 uMajorBrand = 0;
     if(SUCCEEDED(m_TrackManager.GetMajorBrand(&uMajorBrand)) && (uMajorBrand == QT_m4a))
     {
         ul3GPPExtractorIndex = 0;
         uliTunesExtractorIndex = 1;
     }
 
 #if defined(QTCONFIG_3GPP_TAC) || defined(QTCONFIG_3GPP_METAINFO)
     aExtractAssetInfoToHeader[ul3GPPExtractorIndex] = &CQTFileFormat::Extract3GPPAssetInfoToHeader;
 #endif // QTCONFIG_3GPP_TAC || defined(QTCONFIG_3GPP_METAINFO)
 
 #ifdef QTCONFIG_ITUNES_METAINFO
     aExtractAssetInfoToHeader[uliTunesExtractorIndex] = &CQTFileFormat::ExtractiTunesAssetInfoToHeader;
 #endif //QTCONFIG_ITUNES_METAINFO
 
     // Extraction functions prioritized, go ahead and call them
     for(UINT32 ulSetAssetInfo = 0; ulSetAssetInfo < ulMetaInfoExtractionFunctionCount; ulSetAssetInfo++)
     {
         PFNExtractAssetInfoToHeader pfnExtractAssetInfoToHeader = aExtractAssetInfoToHeader[ulSetAssetInfo];
         if(SUCCEEDED(status) && pfnExtractAssetInfoToHeader)
         {
             status = (this->*pfnExtractAssetInfoToHeader)(status, pHeader);
         }
     }
 
+    // UITS atom has priority over UITS data extracted from ID32 blobs (legacy files).
+#if defined(QTCONFIG_3GPP_METAINFO) || defined(QTCONFIG_ITUNES_METAINFO)
+    if(SUCCEEDED(status))
+    {
+        status = ExtractUITSInfoToHeader(status, pHeader);
+    }
+#endif //defined(QTCONFIG_3GPP_METAINFO) || defined(QTCONFIG_ITUNES_METAINFO)
+
     // Session identity
     if (SUCCEEDED(status))
     {
 	status = GetSessionIdentity(pHeader, &m_MovieInfo);
     }
 
 #ifdef QTCONFIG_ALTERNATE_STREAMS
 #ifdef QTCONFIG_LEGACY_ALTERNATE_STREAMS
     // Set stream groupings based on QuickTime AlternateGroup SDP entries.
     if (SUCCEEDED(status))
     {
 	UINT16 uStrmIdx;
 	ULONG32 ulGroupID;
 	ULONG32 ulGroupBitrate;
 	IQTTrack* pTrack;
 	IHXValues* pGroupInfo = NULL;	
 
 	for (uStrmIdx = 0; 
 	     uStrmIdx < m_TrackManager.GetNumStreams();
 	     uStrmIdx++)
 	{
 	    pTrack = m_TrackManager.GetStreamTrack(uStrmIdx);
 
 	    if (pTrack->GetSDPLength() > 0)
 	    {
 		SDPParseChunk(
 		    (char*) pTrack->GetSDP(),
 		    pTrack->GetSDPLength(),
 		    pGroupInfo,
 		    m_pClassFactory,
Index: datatype/mp4/fileformat/pub/qtatmmgs.h
===================================================================
RCS file: /cvsroot/datatype/mp4/fileformat/pub/qtatmmgs.h,v
retrieving revision 1.34
diff -w -U 30 -r1.34 qtatmmgs.h
--- datatype/mp4/fileformat/pub/qtatmmgs.h	8 Jan 2010 04:29:25 -0000	1.34
+++ datatype/mp4/fileformat/pub/qtatmmgs.h	2 Nov 2010 15:12:35 -0000
@@ -1694,95 +1694,119 @@
         return m_piTunesDataAtomdisk ? m_piTunesDataAtomdisk->GetSpecialValue_DiskCount() : 0;
     }
 
     //*** iTunes covr atom / Cover Art *************************************
 
     UINT16 GetiTunesImageCount(void)
     {
         return m_piTunesItemAtomcovr ? m_piTunesItemAtomcovr->GetImageAtomCount() : 0;
     }
 
     const char* GetiTunesImageValueMimeType(UINT16 imageIndex)
     {
         CQT_iTunes_data_Atom* pDataAtom = m_piTunesItemAtomcovr ? m_piTunesItemAtomcovr->GetImageAtom(imageIndex) : 0;
         return pDataAtom ? pDataAtom->GetImageValueMimeType() : 0;
     }
     
     UINT32 GetiTunesImageValueByteLength(UINT16 imageIndex)
     {
         CQT_iTunes_data_Atom* pDataAtom = m_piTunesItemAtomcovr ? m_piTunesItemAtomcovr->GetImageAtom(imageIndex) : 0;
         return pDataAtom ? pDataAtom->GetImageValueByteLength() : 0;
     }
 
     UINT8* GetiTunesImageValue(UINT16 imageIndex)
     {
         CQT_iTunes_data_Atom* pDataAtom = m_piTunesItemAtomcovr ? m_piTunesItemAtomcovr->GetImageAtom(imageIndex) : 0;
         return pDataAtom ? pDataAtom->GetImageValue() : 0;
     }
 
 #endif //QTCONFIG_ITUNES_METAINFO
 
+#if defined(QTCONFIG_3GPP_METAINFO) || defined(QTCONFIG_ITUNES_METAINFO)
+
+    //*** UITS Atom *********************************************
+
+    UINT32 GetUITSBlobSize(void)
+    {
+        return m_pUITSAtom ? m_pUITSAtom->GetBlobSize() : 0;
+    }
+
+    UINT8* GetUITSBlob(void)
+    {
+        return m_pUITSAtom ? m_pUITSAtom->GetBlob() : 0;
+    }
+
+#endif //defined(QTCONFIG_3GPP_METAINFO) || defined(QTCONFIG_ITUNES_METAINFO)
+
 private:
     HX_RESULT ParseMovieHintInfo(CQTAtom* pAtom);
 	
 #ifdef QTCONFIG_3GPP_METAINFO
     static CQT_ID32_Atom* FindID32Atom(CQT_moov_Atom* pMoovAtom);
 #endif // QTCONFIG_3GPP_METAINFO
 
+#if defined(QTCONFIG_3GPP_METAINFO) || defined(QTCONFIG_ITUNES_METAINFO)
+    static CQT_UITS_Atom* FindUITSAtom(CQT_udta_Atom* pMoovAtom);
+#endif //defined(QTCONFIG_3GPP_METAINFO) || defined(QTCONFIG_ITUNES_METAINFO)
+
     char *m_pRefURL;
     ULONG32 m_ulMovieTimeScale;
     ULONG32 m_ulMovieDuration;
     HXBOOL m_bFragmented;
 
     CQT_name_Atom*    m_pNameAtom;
 
 #ifdef QTCONFIG_3GPP_TAC
     CQT_titl_Atom*    m_pTitlAtom;
     CQT_auth_Atom*    m_pAuthAtom;
     CQT_cprt_Atom*    m_pCprtAtom;
 #endif // QTCONFIG_3GPP_TAC
 #ifdef QTCONFIG_3GPP_METAINFO
     CQT_dscp_Atom*    m_pDscpAtom;
     CQT_perf_Atom*    m_pPerfAtom;
     CQT_gnre_Atom*    m_pGnreAtom;
     CQT_rtng_Atom*    m_pRtngAtom;
     CQT_clsf_Atom*    m_pClsfAtom;
     CQT_kywd_Atom*    m_pKywdAtom;
     CQT_loci_Atom*    m_pLociAtom;
     CQT_albm_Atom*    m_pAlbmAtom;
     CQT_yrrc_Atom*    m_pYrrcAtom;
     CQT_ID32_Atom*    m_pID32Atom;
 #endif // QTCONFIG_3GPP_METAINFO
 
 #ifdef QTCONFIG_ITUNES_METAINFO
     CQT_iTunes_data_Atom*  m_piTunesDataAtomA9nam;
     CQT_iTunes_data_Atom*  m_piTunesDataAtomA9ART;
     CQT_iTunes_data_Atom*  m_piTunesDataAtomA9alb;
     CQT_iTunes_data_Atom*  m_piTunesDataAtomA9gen;
     CQT_iTunes_data_Atom*  m_piTunesDataAtomA9day;
     CQT_iTunes_data_Atom*  m_piTunesDataAtomA9cmt;
     CQT_iTunes_data_Atom*  m_piTunesDataAtomA9wrt;
     CQT_iTunes_data_Atom*  m_piTunesDataAtomA9too;
     CQT_iTunes_data_Atom*  m_piTunesDataAtomA9enc;
     CQT_iTunes_data_Atom*  m_piTunesDataAtomA9grp;
     CQT_iTunes_data_Atom*  m_piTunesDataAtomgrup;
     CQT_iTunes_data_Atom*  m_piTunesDataAtomaART;
     CQT_iTunes_data_Atom*  m_piTunesDataAtomcprt;
     CQT_iTunes_data_Atom*  m_piTunesDataAtomA9st3;
     CQT_iTunes_data_Atom*  m_piTunesDataAtomA9lyr;
     CQT_iTunes_data_Atom*  m_piTunesDataAtomtmpo;
     CQT_iTunes_data_Atom*  m_piTunesDataAtomcpil;
     CQT_iTunes_data_Atom*  m_piTunesDataAtomrtng;
     CQT_iTunes_data_Atom*  m_piTunesDataAtomtrkn;
     CQT_iTunes_data_Atom*  m_piTunesDataAtomdisk;
     CQT_iTunes_data_Atom*  m_piTunesDataAtomgnre;
     CQT_iTunes_covr_Atom*  m_piTunesItemAtomcovr;
 #endif //QTCONFIG_ITUNES_METAINFO
 
+#if defined(QTCONFIG_3GPP_METAINFO) || defined(QTCONFIG_ITUNES_METAINFO)
+    CQT_UITS_Atom* m_pUITSAtom;
+#endif //defined(QTCONFIG_3GPP_METAINFO) || defined(QTCONFIG_ITUNES_METAINFO)
+
     CQT_rtp_Atom*     m_pRTPSDPAtom;
 };
 
 #ifdef QTCONFIG_SPEED_OVER_SIZE
 #include "qtatmmgs_inline.h"
 #endif	// QTCONFIG_SPEED_OVER_SIZE
 
 #endif  // _QTATMMGS_H_
Index: datatype/mp4/fileformat/pub/qtatoms.h
===================================================================
RCS file: /cvsroot/datatype/mp4/fileformat/pub/qtatoms.h,v
retrieving revision 1.39
diff -w -U 30 -r1.39 qtatoms.h
--- datatype/mp4/fileformat/pub/qtatoms.h	6 Jan 2010 16:17:16 -0000	1.39
+++ datatype/mp4/fileformat/pub/qtatoms.h	2 Nov 2010 15:12:39 -0000
@@ -89,60 +89,61 @@
     QT_stss = QT_ENCODE_TYPE('s', 't', 's', 's'),
     QT_stsd = QT_ENCODE_TYPE('s', 't', 's', 'd'),
     QT_stsz = QT_ENCODE_TYPE('s', 't', 's', 'z'),
     QT_stz2 = QT_ENCODE_TYPE('s', 't', 'z', '2'),
     QT_stsc = QT_ENCODE_TYPE('s', 't', 's', 'c'),
     QT_stco = QT_ENCODE_TYPE('s', 't', 'c', 'o'),
     QT_co64 = QT_ENCODE_TYPE('c', 'o', '6', '4'),
     QT_smhd = QT_ENCODE_TYPE('s', 'm', 'h', 'd'),
     QT_hint = QT_ENCODE_TYPE('h', 'i', 'n', 't'),
     QT_mhlr = QT_ENCODE_TYPE('m', 'h', 'l', 'r'),
     QT_alis = QT_ENCODE_TYPE('a', 'l', 'i', 's'),
     QT_rsrc = QT_ENCODE_TYPE('r', 's', 'r', 'c'),
     QT_tsel = QT_ENCODE_TYPE('t', 's', 'e', 'l'),
     QT_hinf = QT_ENCODE_TYPE('h', 'i', 'n', 'f'),
     QT_hnti = QT_ENCODE_TYPE('h', 'n', 't', 'i'),
     QT_sdp  = QT_ENCODE_TYPE('s', 'd', 'p', ' '),
     QT_trpy = QT_ENCODE_TYPE('t', 'r', 'p', 'y'),
     QT_nump = QT_ENCODE_TYPE('n', 'u', 'm', 'p'),
     QT_tpyl = QT_ENCODE_TYPE('t', 'p', 'y', 'l'),
     QT_payt = QT_ENCODE_TYPE('p', 'a', 'y', 't'),
     QT_udta = QT_ENCODE_TYPE('u', 'd', 't', 'a'),
     QT_name = QT_ENCODE_TYPE('n', 'a', 'm', 'e'),
 
 #if defined(QTCONFIG_3GPP_TAC) || defined(QTCONFIG_ITUNES_METAINFO)
     QT_cprt = QT_ENCODE_TYPE('c', 'p', 'r', 't'),
 #endif //defined(QTCONFIG_3GPP_TAC) || defined(QTCONFIG_ITUNES_METAINFO)
 
 #if defined(QTCONFIG_3GPP_METAINFO) || defined(QTCONFIG_ITUNES_METAINFO)
     QT_gnre = QT_ENCODE_TYPE('g', 'n', 'r', 'e'),
     QT_rtng = QT_ENCODE_TYPE('r', 't', 'n', 'g'),
+    QT_UITS = QT_ENCODE_TYPE('U', 'I', 'T', 'S'),
 #endif //defined(QTCONFIG_3GPP_METAINFO) || defined(QTCONFIG_ITUNES_METAINFO)
 
 #ifdef QTCONFIG_3GPP_TAC
     // /-->> 3GPP Asset Info Data box types:
     QT_titl = QT_ENCODE_TYPE('t', 'i', 't', 'l'),
     QT_auth = QT_ENCODE_TYPE('a', 'u', 't', 'h'),
 #endif // QTCONFIG_3GPP_TAC
 #ifdef QTCONFIG_3GPP_METAINFO
     QT_dscp = QT_ENCODE_TYPE('d', 's', 'c', 'p'),
     QT_perf = QT_ENCODE_TYPE('p', 'e', 'r', 'f'),
     QT_clsf = QT_ENCODE_TYPE('c', 'l', 's', 'f'),
     QT_kywd = QT_ENCODE_TYPE('k', 'y', 'w', 'd'),
     QT_loci = QT_ENCODE_TYPE('l', 'o', 'c', 'i'),
     QT_albm = QT_ENCODE_TYPE('a', 'l', 'b', 'm'),
     QT_yrrc = QT_ENCODE_TYPE('y', 'r', 'r', 'c'),
     QT_ID32 = QT_ENCODE_TYPE('I', 'D', '3', '2'),
     // /<<-- end Asset Info Data box types
 #endif // QTCONFIG_3GPP_METAINFO
 
 #ifdef QTCONFIG_ITUNES_METAINFO
     QT_mdir = QT_ENCODE_TYPE('m', 'd', 'i', 'r'),
     QT_ilst = QT_ENCODE_TYPE('i', 'l', 's', 't'),
     QT_data = QT_ENCODE_TYPE('d', 'a', 't', 'a'),
     QT_A9nam = QT_ENCODE_TYPE(0xA9, 'n', 'a', 'm'),
     QT_A9ART = QT_ENCODE_TYPE(0xA9, 'A', 'R', 'T'),
     QT_A9alb = QT_ENCODE_TYPE(0xA9, 'a', 'l', 'b'),
     QT_A9gen = QT_ENCODE_TYPE(0xA9, 'g', 'e', 'n'),
     QT_A9day = QT_ENCODE_TYPE(0xA9, 'd', 'a', 'y'),
     QT_A9cmt = QT_ENCODE_TYPE(0xA9, 'c', 'm', 't'),
     QT_A9wrt = QT_ENCODE_TYPE(0xA9, 'w', 'r', 't'),
@@ -449,60 +450,104 @@
     } PACKING;
 
     /*
      *	Constructor/Destructor
      */
     CQT_meta_Atom(ULONG32 ulOffset,
                   ULONG32 ulSize, 
                   CQTAtom *pParent) : CQTAtom(ulOffset,
                                               ulSize,
                                               pParent) {;}
 
     /*
      *	Required Virtual Methods
      */
     virtual HXBOOL      IsLeafType(void)    { return FALSE; }
     virtual QTAtomType  GetType(void)       { return QT_meta; }
     virtual UINT32      GetNonLeafTypeBodySize(void) { return QT_NONLEAFTYPE_BODY_SIZE_FULLBOX; }
 };
 
 #if defined(QTCONFIG_3GPP_TAC) || defined(QTCONFIG_3GPP_METAINFO)
 
 /****************************************************************************
  *  Language encoding field is common to most meta atoms.
  */
 inline void InitLanguageEncoding(char out[3])
 {
     out[0] = out[1] = out[2] = ' ';
 }
 void ExtractLanguageEncoding(UINT8* pPadAndLang, char out[3]);
 
+/****************************************************************************
+ *  UITS Atom Class
+ */
+class CQT_UITS_Atom : public CQTAtom
+{
+public:
+    /*
+     *	Leaf Data Format
+     */
+    struct Data
+    {
+        UINT8 pBlob[1];
+    } PACKING;
+
+    /*
+     *	Constructor/Destructor
+     */
+    CQT_UITS_Atom(ULONG32 ulOffset,
+                  ULONG32 ulSize,
+                  CQTAtom *pParent) : CQTAtom(ulOffset,
+                                              ulSize,
+                                              pParent) {;}
+
+    /*
+     *	Required Virtual Methods
+     */
+    virtual HXBOOL      IsLeafType(void)  { return TRUE; }
+    virtual QTAtomType  GetType(void)     { return QT_UITS; }
+
+    /*
+     *	Data Access Methods
+     */
+    UINT8* GetBlob(void)
+    {
+        HX_ASSERT(m_pData);
+        return (m_pData) ? ((Data*) m_pData)->pBlob : NULL;
+    }
+
+    ULONG32 GetBlobSize(void)
+    {
+        return (GetDataSize() - sizeof(Data) + sizeof(UINT8));
+    }
+};
+
 #endif // QTCONFIG_3GPP_TAC || QTCONFIG_3GPP_METAINFO
 
 #ifdef QTCONFIG_3GPP_TAC
 /****************************************************************************
  *  cprt Atom Class
  */
 class CQT_cprt_Atom : public CQTAtom
 {
 public:
     /*
      *	Leaf Data Format
      */
     struct Data
     {
         UINT8 pVersion[1];
         UINT8 pFlags[3];
         UINT8 pPadAndLang[2];
         UINT8 pCopyright[1];
     } PACKING;
 
     /*
      *	Constructor/Destructor
      */
     CQT_cprt_Atom(ULONG32 ulOffset,
                   ULONG32 ulSize,
                   CQTAtom *pParent) : CQTAtom(ulOffset,
                                               ulSize,
                                               pParent) {;}
 
     /*
Index: datatype/mp4/fileformat/pub/qtffplin.h
===================================================================
RCS file: /cvsroot/datatype/mp4/fileformat/pub/qtffplin.h,v
retrieving revision 1.26
diff -w -U 30 -r1.26 qtffplin.h
--- datatype/mp4/fileformat/pub/qtffplin.h	16 Nov 2009 22:12:12 -0000	1.26
+++ datatype/mp4/fileformat/pub/qtffplin.h	2 Nov 2010 15:12:41 -0000
@@ -280,60 +280,64 @@
     CQT_MovieInfo_Manager m_MovieInfo;
     CQTTrackManager m_TrackManager;
 
 #ifdef QTCONFIG_BFRAG_FACTORY
     CBufferFragmentFactory* m_pBufferFragmentFactory;
 #endif	// QTCONFIG_BFRAG_FACTORY
 
 protected:
     virtual CQTPacketizerFactory* BuildPacketizerFactory(void);
 
     virtual HX_RESULT GetSessionIdentity(IHXValues* pHeader,
 					 CQT_MovieInfo_Manager* pMovieInfo);
 
     virtual ~CQTFileFormat(); 
 
     virtual HX_RESULT InitTracks(CQTPacketizerFactory* pPacketizerFactory);
     virtual HXBOOL IgnoreHintTracks() {return FALSE;}
     /*
      *	Meta-info extractors
      */
     typedef HX_RESULT (CQTFileFormat::*PFNExtractAssetInfoToHeader)(HX_RESULT status, IHXValues* pHeader);
 
 #if defined(QTCONFIG_3GPP_TAC) || defined(QTCONFIG_3GPP_METAINFO)
     HX_RESULT Extract3GPPAssetInfoToHeader(HX_RESULT status, IHXValues* pHeader);
 #endif //defined(QTCONFIG_3GPP_TAC) || defined(QTCONFIG_3GPP_METAINFO)
 
 #ifdef QTCONFIG_ITUNES_METAINFO
     HX_RESULT ExtractiTunesAssetInfoToHeader(HX_RESULT status, IHXValues* pHeader);
 #endif //QTCONFIG_ITUNES_METAINFO
 
+#if defined(QTCONFIG_3GPP_METAINFO) || defined(QTCONFIG_ITUNES_METAINFO)
+    HX_RESULT ExtractUITSInfoToHeader(HX_RESULT status, IHXValues* pHeader);
+#endif //defined(QTCONFIG_3GPP_METAINFO) || defined(QTCONFIG_ITUNES_METAINFO)
+
 #if defined(QTCONFIG_3GPP_TAC) || defined(QTCONFIG_3GPP_METAINFO) || defined(QTCONFIG_ITUNES_METAINFO)
     HX_RESULT UpdateHeaderProperty(HX_RESULT status, IHXValues* pHeader,
                                   const char* key,
                                   const char* value, ULONG32 valueLength,
                                   HX_TEXT_ENCODING_TYPE encoding = HX_TEXT_ENCODING_TYPE_UNKNOWN);
 #endif //defined(QTCONFIG_3GPP_TAC) || defined(QTCONFIG_3GPP_METAINFO) || defined(QTCONFIG_ITUNES_METAINFO)
 
     /*
      *	Other public members
      */
     IUnknown* m_pContext;
     IHXCommonClassFactory* m_pClassFactory;
     IHXFormatResponse* m_pFFResponse;
     ULONG32 m_ulPacketFormat;
     CQTPacketAssembler* m_pPacketAssembler;
 
 private:
     typedef enum
     {
 	QTFF_Offline,
 	QTFF_Ready,
 	QTFF_Error,
 	QTFF_Init,
 	QTFF_Atomize,
 	QTFF_GetPacket,
 	QTFF_PrimeCache,
 	QTFF_SeekPending
     } QTFileFormatState;
 
     class CPacketCache
datatype_mp4_filewriter.diff (application/octet-stream, 21.5 KB)
Index: datatype/mp4/filewriter/mp4atoms.h
===================================================================
RCS file: /cvsroot/datatype/mp4/filewriter/mp4atoms.h,v
retrieving revision 1.17.2.1
diff -w -U 30 -r1.17.2.1 mp4atoms.h
--- datatype/mp4/filewriter/mp4atoms.h	11 Jan 2010 17:43:16 -0000	1.17.2.1
+++ datatype/mp4/filewriter/mp4atoms.h	2 Nov 2010 15:12:44 -0000
@@ -3401,31 +3401,89 @@
 
         if (pszRTPMap && ucLen)
         {
             // Clear any previous RTPmap string
             HX_VECTOR_DELETE(m_pszRTPMapText);
             m_ucRTPMapTextLength = 0;
             // Set the return value
             retVal = HXR_OUTOFMEMORY;
             // Allocate a new buffer
             char* pTmp = new char [ucLen];
             if (pTmp)
             {
                 // Copy in the memory
                 memcpy(pTmp, pszRTPMap, ucLen);
                 // Clear the return value
                 retVal = HXR_OK;
                 // Assign the member variables
                 m_ucRTPMapTextLength = ucLen;
                 m_pszRTPMapText      = pTmp;
             }
         }
 
         return retVal;
     };
 private:
     UINT32 m_ulPayloadID;
     UINT8  m_ucRTPMapTextLength;
     char*  m_pszRTPMapText;
 };
 
+// UITS
+class CMP4Atom_UITS : public CMP4Atom
+{
+public:
+    CMP4Atom_UITS()
+        : CMP4Atom(MP4_BUILD_ATOMID('U','I','T','S'))
+        , m_pBlob(0)
+        , m_uBlobSize(0)
+    {
+    }
+
+    virtual ~CMP4Atom_UITS()
+    {
+        HX_VECTOR_DELETE(m_pBlob);
+    }
+
+    HX_RESULT SetBlob(const UCHAR* pData, UINT32 size)
+    {
+        HX_VECTOR_DELETE(m_pBlob);
+        m_uBlobSize = 0;
+
+        m_pBlob = new UCHAR[size];
+        if(m_pBlob)
+        {
+            m_uBlobSize = size;
+            memcpy(m_pBlob, pData, size);
+            return HXR_OK;
+        }
+        return HXR_OUTOFMEMORY;
+    }
+
+    STDMETHOD_(UINT32, GetCurrentSize)(THIS_ HXBOOL bIncludeChildren = FALSE)
+    {
+        return 8 + (bIncludeChildren ? GetSizeOfChildren() : 0) +
+                m_uBlobSize;
+    }
+
+    STDMETHOD(WriteToBuffer)(THIS_ UCHAR*& pBuffer, HXBOOL bIncludeChildren = FALSE)
+    {
+        HX_RESULT retVal = HXR_OK;
+        if(pBuffer)
+        {
+            WriteToBufferAndInc( pBuffer, GetCurrentSize(bIncludeChildren) );
+            WriteToBufferAndInc( pBuffer, m_ulAtomID );
+
+            if(m_uBlobSize)
+            {
+                CMP4Atom::WriteToBufferAndInc( pBuffer, (UCHAR*)m_pBlob, m_uBlobSize );
+            }
+        }
+        return retVal;
+    }
+
+private:
+    UCHAR* m_pBlob;
+    UINT32 m_uBlobSize;
+};
+
 #endif /* _MP4ATOMS_H_ */
Index: datatype/mp4/filewriter/mp4sm.cpp
===================================================================
RCS file: /cvsroot/datatype/mp4/filewriter/mp4sm.cpp,v
retrieving revision 1.24.2.2
diff -w -U 30 -r1.24.2.2 mp4sm.cpp
--- datatype/mp4/filewriter/mp4sm.cpp	15 Jan 2010 16:16:16 -0000	1.24.2.2
+++ datatype/mp4/filewriter/mp4sm.cpp	2 Nov 2010 15:12:52 -0000
@@ -635,60 +635,61 @@
 }
 
 CMP4StreamMixer::HintInfo::~HintInfo()
 {
 }
 
 CMP4StreamMixer::CMP4StreamMixer(IUnknown* pContext, CMP4Archiver* pArchiver)
     : m_lRefCount(0)
     , m_ulLastTimestamp(0)
     , m_ulActualDuration(0)
     , m_ulReportedDuration(0)
     , m_uiByteCount(0)
     , m_uiReservedBlockCount(0)
     , m_ulFirstTimestamp(0)
     , m_eIsRtp(UNCHECKED)
     , m_bMoovAtEnd(FALSE)
     , m_bForceMoovFirst(FALSE)
     , m_pMvhd(NULL)
     , m_pFileHeader(NULL)
     , m_pStreamInfo(NULL)
     , m_ulStreamCount(0)
     , m_ulStreamGroupCount(0)
     , m_ulStreamHeaderReceived(0)
     , m_ulStreamDoneReceived(0)
     , m_eMetaFlavor(META_ITUNES)
     , m_bRequestedOutputMetaFlavor3GPP(FALSE)
     , m_bRequestedOutputMetaFlavorITUNES(FALSE)
     , m_bIgnoreID32Blob(FALSE)
     , m_uID3TagVersionMinorOutput(4)
     , m_bFileHeaderCarriesUITSData(FALSE)
+    , m_bOutputUITSToID32Atom(FALSE)
     , m_bUTF16Output(FALSE)
     , m_e3gpMode(M3GPP_NONE)
     , m_bTSInterleave(FALSE)
     , m_bGenerateHintTracks(FALSE)
     , m_uiBaseWriteOffset(0)
     , m_uiCurrentOffset(0)
     , m_uiGlobalFlush(0)
 {
     m_pContext = pContext;
     HX_ADDREF(m_pContext);
 
     HX_ASSERT( pArchiver );
     m_pArchiver = pArchiver;
     m_pArchiver->AddRef();
 
     m_pRootAtom = new CMP4Atom_file();
     HX_ASSERT( m_pRootAtom );
     m_pRootAtom->AddRef();
 }
 
 
 CMP4StreamMixer::~CMP4StreamMixer()
 {
     HX_RELEASE( m_pArchiver );
     HX_RELEASE( m_pRootAtom );
     HX_RELEASE( m_pFileHeader );
     HX_VECTOR_DELETE(m_pStreamInfo);
     HX_RELEASE( m_pContext );
 }
 
@@ -729,60 +730,84 @@
     ulVal = 0;
     PropTools::CopyPropertyULONG32(ulVal, pProperties, "MetaDataIgnore");
 
     const UINT32 METADATAIGNORE_ID32BLOB = 0x00000001; //from ffdriver.h
     m_bIgnoreID32Blob = (ulVal & METADATAIGNORE_ID32BLOB) ? TRUE : FALSE;
 
     // Meta-data ID3v2 output control
     ulVal = 0;
     PropTools::CopyPropertyULONG32(ulVal, pProperties, "MetaDataID3Version");
 
     const UINT32 METADATAID3VERSION_230  = 0x00020300; //from ffdriver.h
     const UINT32 METADATAID3VERSION_240  = 0x00020400;
     const UINT32 METADATAID3VERSION_NONE = 0x01000000;
 
     switch(ulVal)
     {
         case METADATAID3VERSION_NONE:
             m_uID3TagVersionMinorOutput = 0;
             break;
 
         case METADATAID3VERSION_230:
             m_uID3TagVersionMinorOutput = 3;
             break;
 
         case METADATAID3VERSION_240:
         default:
             m_uID3TagVersionMinorOutput = 4;
             break;
     }
 
+    // Meta-data UITS output control
+    ulVal = 0;
+    PropTools::CopyPropertyULONG32(ulVal, pProperties, "MetaDataUITSLocation");
+
+    const UINT32 METADATAUITSLOCATION_DEFAULT  = 0x00000000;
+    const UINT32 METADATAUITSLOCATION_ID32ATOM = 0x00000001;
+    const UINT32 METADATAUITSLOCATION_UITSATOM = 0x00000002;
+
+    switch(ulVal)
+    {
+        case METADATAUITSLOCATION_DEFAULT:
+            m_bOutputUITSToID32Atom = FALSE;
+            break;
+
+        case METADATAUITSLOCATION_ID32ATOM:
+            m_bOutputUITSToID32Atom = TRUE;
+            break;
+
+        case METADATAUITSLOCATION_UITSATOM:
+        default:
+            m_bOutputUITSToID32Atom = FALSE;
+            break;
+    }
+
     // UTF16 output option
     ulVal = 0;
     PropTools::CopyPropertyULONG32(ulVal, pProperties, "UTF16Output");
     m_bUTF16Output = ulVal ? TRUE : FALSE;
 
     // Compatibility option
     PropTools::CopyPropertyBuffer(m_spCompatibility, pProperties, "Compatibility");
 
     // 3GPP Mode option
     IHXBuffer *buf;
 
     if (SUCCEEDED(pProperties->GetPropertyCString("3GPPMode", buf)))
     {
 	UINT32 n = buf->GetSize();
 	const char *p3gpmode = (const char *)buf->GetBuffer();
 
 	if (n >= 4 && strncasecmp(p3gpmode, "none", 4) == 0)
 	{
 	    m_e3gpMode = M3GPP_NONE;
 	}
 	else if (n >= 7 && strncasecmp(p3gpmode, "general", 7) == 0)
 	{
 	    m_e3gpMode = M3GPP_GENERAL;
 	}
 	else if (n >= 5 && strncasecmp(p3gpmode, "basic", 5) == 0)
 	{
 	    m_e3gpMode = M3GPP_BASIC;
 	}
 	else if (n >= 9 && strncasecmp(p3gpmode, "streaming", 9) == 0)
 	{
@@ -838,61 +863,61 @@
 
     return HXR_OK;
 }
 
 STDMETHODIMP CMP4StreamMixer::SetFileHeader( THIS_ IHXValues* pFileHeader )
 {
     HX_RESULT retVal = HXR_OK;
 
     pFileHeader->AddRef();
     m_pFileHeader = pFileHeader;
 
     //get stream count; this may be bigger than the actual number of tracks in
     //the output file, depending on how many NUL handlers are there
     m_pFileHeader->GetPropertyULONG32("StreamCount", m_ulStreamCount);
     m_pFileHeader->GetPropertyULONG32("StreamGroupCount", m_ulStreamGroupCount);
 
     if (m_ulStreamCount)
     {
         m_pStreamInfo = new StreamInfo[m_ulStreamCount];
     }
 
     HX_ASSERT(m_pStreamInfo);
 
     m_ulStreamHeaderReceived = 0;
     m_ulStreamDoneReceived = 0;
 
     // check if the header carries UITS data
     m_bFileHeaderCarriesUITSData = FALSE;
 
     IHXBuffer* pUITSDataBuffer = 0;
-    if(SUCCEEDED(m_pFileHeader->GetPropertyBuffer(_3GPP_META_INFO_UITS_KEY, pUITSDataBuffer)) && pUITSDataBuffer)
+    if(SUCCEEDED(m_pFileHeader->GetPropertyBuffer(_GENERIC_META_INFO_UITS_KEY, pUITSDataBuffer)) && pUITSDataBuffer)
     {
         m_bFileHeaderCarriesUITSData = TRUE;
     }
     HX_RELEASE(pUITSDataBuffer);
 
     return retVal;
 }
 
 STDMETHODIMP CMP4StreamMixer::SetStreamHeader( THIS_ IHXValues* pStreamHeader )
 {
     HX_RESULT retVal = HXR_OK;
 
     //save the stream header
     UINT32 ulStreamNumber = m_ulStreamCount;
     pStreamHeader->GetPropertyULONG32("StreamNumber",ulStreamNumber);
 
     if (ulStreamNumber >= m_ulStreamCount)
     {
         return HXR_INVALID_PARAMETER;
     }
 
     // Save the stream group number
     UINT32 ulStreamGroupNumber = HX_INVALID_STREAM_GROUP_NUMBER;
     pStreamHeader->GetPropertyULONG32("StreamGroupNumber", ulStreamGroupNumber);
 
     // If we have a "StreamGroupCount" in the file header, then we
     // should have a stream group number in each stream header
     if (m_ulStreamGroupCount && ulStreamGroupNumber >= m_ulStreamGroupCount)
     {
         return HXR_INVALID_PARAMETER;
@@ -1700,66 +1725,72 @@
 		
 		if (hi != NULL && hi->trak != NULL)
 		    pMoov->AddChild(hi->trak);
 	    }
         }
 
         // Do we need to generate a udta box that is a child
         // of the moov box?
         if (SUCCEEDED(retVal) && NeedToAddUdtaChildToMoovBox())
         {
             // Set the return value
             retVal = HXR_OUTOFMEMORY;
 
             // Create the udta box
             CMP4Atom_udta* pUdta = new CMP4Atom_udta();
             if (pUdta)
             {
                 // Clear the return value
                 retVal = HXR_OK;
 
                 // Check the meta-data format we are supposed to generate
                 if (m_bRequestedOutputMetaFlavorITUNES || (m_eMetaFlavor == META_ITUNES))
                 {
                     // Build iTunes meta-data
                     BuildiTunesMetaData(pUdta);
                 }
 
                 CMP4Atom_meta* pMeta = 0;
 
                 if (m_bRequestedOutputMetaFlavor3GPP || (m_eMetaFlavor == META_3GPP)
-                    || m_bFileHeaderCarriesUITSData)
+                    || (m_bFileHeaderCarriesUITSData && m_bOutputUITSToID32Atom))
                 {
                     // Build 3GP meta-data
                     Build3GPPMetaData(pUdta, pMoov, &pMeta);
                 }
 
+                // Output UITS meta-data
+                if(m_bFileHeaderCarriesUITSData && !m_bOutputUITSToID32Atom)
+                {
+                    BuildUITSMetaData(pUdta);
+                }
+
                 // Are we generating a hinted file?
                 if (m_bGenerateHintTracks)
                 {
                     // Add the hnti box as a child of the udta box
                     AddMovieHintInformation(pUdta);
                 }
 
                 // Add this udta box as a child of the moov box
                 pMoov->AddChild(pUdta);
 
                 // Add meta box as a child of the moov box.
                 // XXXPB: Add 'meta' after the 'udta' to improve
                 // compatibility of output file with some handsets (HTC).
                 if(pMeta)
                 {
                     pMoov->AddChild(pMeta);
                 }
             }
         }
 
         // uuid/USMT atom for PSP style meta info
         if( SUCCEEDED( retVal ) && m_eMetaFlavor == META_PSP )
         {
             retVal = HXR_OUTOFMEMORY;
             CPSPAtom_USMT* pUsmt = new CPSPAtom_USMT();
             if( pUsmt )
             {
                 retVal = HXR_OK;
 
                 // Call out to build the metadata tree
@@ -3712,60 +3743,92 @@
         retVal = HXR_OUTOFMEMORY;
         return;
     }
 
     if( !pPropName || !pIlst || !pItem )
     {
         retVal = HXR_INVALID_PARAMETER;
         return;
     }
 
     if( !m_pFileHeader )
     {
         retVal = HXR_FAILED;
         return;
     }
 
     if( transfer.ExtractData(*m_pFileHeader, pPropName) )
     {
         retVal = HXR_OUTOFMEMORY;
 
         CiTunesAtom_data* pData = new CiTunesAtom_data();
         if( pData )
         {
             retVal = transfer.InjectData(*pData);
         }
 
         MetaiTunes_LinkAtoms(retVal, pIlst, pItem, pData);
     }
 }
 
+HX_RESULT CMP4StreamMixer::BuildUITSMetaData( CMP4Atom* pUdta )
+{
+    HX_RESULT retVal = HXR_OK;
+
+    if(m_bFileHeaderCarriesUITSData && !m_bOutputUITSToID32Atom)
+    {
+        EncodedString sUITSData;
+        if(PropTools::CopyPropertyBuffer(sUITSData, m_pFileHeader, _GENERIC_META_INFO_UITS_KEY))
+        {
+            retVal = HXR_OUTOFMEMORY;
+
+            CMP4Atom_UITS* pUITS = new CMP4Atom_UITS();
+
+            if(pUITS)
+            {
+                retVal = pUITS->SetBlob((const UCHAR*)sUITSData.GetData(), sUITSData.GetByteLength(FALSE));
+
+                if(SUCCEEDED(retVal))
+                {
+                    pUdta->AddChild(pUITS);
+                }
+                else
+                {
+                    delete pUITS;
+                }
+            }
+        }
+    }
+
+    return retVal;
+}
+
 HX_RESULT CMP4StreamMixer::BuildiTunesMetaData( CMP4Atom* pUdta )
 {
     HX_RESULT retVal = HXR_OUTOFMEMORY;
 
     // The metadata tree looks like this
     // udta
     //   meta
     //     hdlr
     //     ilst
     //     free
     CiTunesAtom_meta* pMeta = new CiTunesAtom_meta();
 
     if( pMeta )
     {
         retVal = HXR_OK;
 
         pUdta->AddChild( pMeta );
     }
 
     CMP4Atom_free* pFree = NULL;
     CiTunesAtom_ilst* pIlst = NULL;
     if( SUCCEEDED( retVal ) )
     {
         retVal = HXR_OUTOFMEMORY;
 
         // hdlr
         CiTunesAtom_hdlr* pHdlr = new CiTunesAtom_hdlr();
         if( pHdlr )
         {
             retVal = HXR_OK;
@@ -4570,64 +4633,64 @@
 
     // Extract APIC frames from buffer properties.
     if(m_bRequestedOutputMetaFlavor3GPP || (m_eMetaFlavor == META_3GPP))
     {
         UINT32 uAPICDataCount = 0;
         PropTools::CopyPropertyULONG32(uAPICDataCount, pHeader, _3GPP_META_INFO_PICTURE_COUNT_KEY);
 
         if(uAPICDataCount)
         {
             for(UINT32 uAPICData = 0; SUCCEEDED(retVal) && (uAPICData < uAPICDataCount); uAPICData++)
             {
                 retVal = HXR_OUTOFMEMORY;
                 ID3Tools::APICFrame* pFrame = new ID3Tools::APICFrame;
                 if(pFrame)
                 {
                     char key[128];
                     sprintf(key, _3GPP_META_INFO_PICTURE_KEY, int(uAPICData));
 
                     retVal = pFrame->DeserializeFromBufferProperty(pHeader, key);
 
                     if(SUCCEEDED(retVal))
                     {
                         retVal = tag.AddFrame(pFrame);
                     }
                 }
             }
         }
     }
 
     // Extract UITS data from buffer property. Write UITS to file header only.
-    if(bFileHeader && m_bFileHeaderCarriesUITSData)
+    if(bFileHeader && m_bFileHeaderCarriesUITSData && m_bOutputUITSToID32Atom)
     {
         EncodedString sUITSData;
-        if(PropTools::CopyPropertyBuffer(sUITSData, m_pFileHeader, _3GPP_META_INFO_UITS_KEY))
+        if(PropTools::CopyPropertyBuffer(sUITSData, m_pFileHeader, _GENERIC_META_INFO_UITS_KEY))
         {
             retVal = HXR_OUTOFMEMORY;
             ID3Tools::PRIVFrame* pFrame = new ID3Tools::PRIVFrame;
             if(pFrame)
             {
                 pFrame->SetOwnerIdentifier(_META_INFO_UITS_OWNER_IDENTIFIER);
                 retVal = pFrame->SetPrivateData((const UINT8*)sUITSData.GetData(), sUITSData.GetByteLength(FALSE));
 
                 if(SUCCEEDED(retVal))
                 {
                     retVal = tag.AddFrame(pFrame);
                 }
             }
         }
     }
 
     // write out the tag into the ID32 box
     if(SUCCEEDED(retVal) && tag.GetNumFrames())
     {
         retVal = HXR_OUTOFMEMORY;
 
         // construct ID32 payload buffer
         UINT32 ulID32BlobSize = tag.CalcSerializationBufferSize();
         UINT8* pID32Blob = new UINT8[ulID32BlobSize];
         if(pID32Blob)
         {
             retVal = tag.SerializeToBuffer(pID32Blob, ulID32BlobSize, m_uID3TagVersionMinorOutput);
         }
 
         if(SUCCEEDED(retVal))
Index: datatype/mp4/filewriter/mp4sm.h
===================================================================
RCS file: /cvsroot/datatype/mp4/filewriter/mp4sm.h,v
retrieving revision 1.16.2.1
diff -w -U 30 -r1.16.2.1 mp4sm.h
--- datatype/mp4/filewriter/mp4sm.h	15 Jan 2010 16:16:16 -0000	1.16.2.1
+++ datatype/mp4/filewriter/mp4sm.h	2 Nov 2010 15:12:52 -0000
@@ -186,60 +186,61 @@
         ~StreamInfo();
 
         IHXValues*     m_pStreamHeader;
         CStblManager*  m_pStblManager;
         HXBOOL         m_bHaveSeenFirstPacket;
         HXBOOL         m_bIsAudio;
         HXBOOL         m_bIsVideo;
         UINT32         m_ulFirstTimestamp;
         UINT32         m_ulLastTimestamp;
         UINT32         m_ulLastTimestampDelta;
         UINT32         m_ulFirstRTPTimestamp;
         UINT32         m_ulStreamGroupNumber;
         UINT32         m_ulSwitchGroupID;
         UINT32         m_ulAvgBitRate;
         UINT32         m_ulASMAverageBandwidth;
         UINT32         m_ulTrackID;
         UINT32         m_ulHintTrackID;
         UINT32         m_ulBaseRule;
         UINT32         m_ulNumASMRules;
         HXASMRuleInfo* m_pASMRuleInfo;
         CHXSimpleList* m_pPacketList;
         CMP4Atom_tkhd* m_pTkhd;
         CMP4Atom_mdhd* m_pMdhd;
         HintInfo*      m_pHintInfo;
     };
 
     // Build the entire atom tree
     HX_RESULT BuildMP4Atoms();
     
     // Build the metadata subtree
+    HX_RESULT BuildUITSMetaData( CMP4Atom* pUdta );
     HX_RESULT BuildiTunesMetaData( CMP4Atom* pUdta );
     HX_RESULT BuildPSPMetaData( CMP4Atom* pUsmt );
     HX_RESULT Build3GPPMetaDataStandardSet( CMP4Atom* pUdta, CMP4Atom* pMoov );
     HX_RESULT Build3GPPMetaData( CMP4Atom* pUdta, CMP4Atom* pMoov, CMP4Atom_meta** ppMeta );
     HX_RESULT Build3GPPMetaDataID32( IHXValues* pHeader, CMP4Atom_meta** ppMeta, HXBOOL bFileHeader );
     HX_RESULT Build3GPPMetaDataID32( IHXValues* pHeader, CMP4Atom_meta** ppMeta, const UINT8* pID32Blob, UINT32 ulID32BlobSize);
 
     // Build the trak subtree
     HX_RESULT BuildTrack( UINT16 usStreamNum, CMP4Atom* pTrak );
     HXBOOL    IsStreamInSwitchGroup(UINT32 ulStreamNumber, UINT32* pulSwitchGroupID = NULL);
     void      SetSwitchGroup(CMP4Atom_udta* pUdtaAtom, UINT32 ulStreamNumber);
     HXBOOL    NeedToAddUdtaChildToTrakBox(CMP4Atom_trak* pTrakBox, UINT32 ulStreamNumber);
     HXBOOL    NeedToAddUdtaChildToMoovBox();
     HX_RESULT AddMovieHintInformation(CMP4Atom_udta* pUdta);
     HX_RESULT GenerateMovieLevelSDP(CHXString* pSDPStr);
     HX_RESULT GenerateAltGroupSDP(CHXString* pAltGroupSDPStr);
     HX_RESULT FindStreamNumInAlternateGroupWithAvgBandwidth(UINT32 ulStreamGroupNumber, UINT32 ulStreamBandwidth, UINT32* pulStreamNum);
     HX_RESULT GetTrackIDForAssociatedHintTrack(UINT32 ulStreamNumber, UINT32* pulHintTrackID);
     HX_RESULT ParseASMRulePropertyUINT32(IHXValues* pProps, const char* pszName, UINT32 ulFlag, UINT32* pulAllFlags, UINT32* pulValue);
     HX_RESULT ParseASMRulePropertyPresence(IHXValues* pProps, const char* pszName, UINT32 ulFlag, UINT32* pulAllFlags, HXBOOL* pbValue);
     HX_RESULT ParseASMRuleProperties(IHXValues* pProps, HXASMRuleInfo* pInfo);
     HX_RESULT ParseStreamASMRuleBook(StreamInfo* pInfo);
     HX_RESULT FindStreamInSwitchGroup(UINT32 ulSwitchGroupID, UINT32 ulASMRule, UINT32* pulStreamNumber);
     HX_RESULT ChangePacketStreamNumber(IHXPacket* pPacket, UINT32 ulNewStreamNumber, REF(IHXPacket*) rpPacket);
     void      CheckForRTPPackets(IHXPacket* pPacket);
     void      ChooseTrackIDs();
     HX_RESULT DetermineStreamType(IHXValues* pStreamHeader, HXBOOL* pbIsAudio, HXBOOL* pbIsVideo);
     HX_RESULT GetStreamBandwidth(UINT32 ulStreamNum, UINT32* pulBandwidth);
     void      AddHintingStatisticsBoxes(CMP4Atom_udta* pUdta);
 
@@ -315,57 +316,58 @@
 
     StreamInfo* m_pStreamInfo;
     
     CMP4Archiver* m_pArchiver;
 
     enum RTPPacketStream
     {
 	UNCHECKED = 0,
 	IS_RTP    = 1,
 	NOT_RTP   = 2,
     };
 
     RTPPacketStream m_eIsRtp;
     
     UINT32 m_uiByteCount;
     UINT32 m_uiReservedBlockCount;
 
     enum MetaFlavor
     {
         META_ITUNES,
         META_3GPP,
         META_PSP
     };
 
     MetaFlavor    m_eMetaFlavor;
     HXBOOL        m_bRequestedOutputMetaFlavor3GPP;
     HXBOOL        m_bRequestedOutputMetaFlavorITUNES;
     HXBOOL        m_bIgnoreID32Blob;
     UINT8         m_uID3TagVersionMinorOutput;
     HXBOOL        m_bFileHeaderCarriesUITSData;
+    HXBOOL        m_bOutputUITSToID32Atom;
     HXBOOL        m_bUTF16Output;
     EncodedString m_spCompatibility;
 
 protected:
     enum ThreeGPPMode
     {
 	M3GPP_NONE,
 	M3GPP_GENERAL,
 	M3GPP_BASIC,
 	M3GPP_STREAMING,
 	M3GPP_PROGDL,
 	M3GPP_STREAMDL,
 	M3GPP_REL5
     };
     ThreeGPPMode m_e3gpMode;
     HXBOOL m_bTSInterleave;
     HXBOOL m_bGenerateHintTracks;
 
     friend class CStblManager;
 
     UINT32 m_uiBaseWriteOffset;
     UINT32 m_uiCurrentOffset;
     UINT32 m_uiGlobalFlush;
 };
 
 
 #endif // _MP4SM_H_
datatype_tools_dtdriver_apps_meta3gp.diff (application/octet-stream, 15.5 KB)
Index: datatype/tools/dtdriver/apps/meta3gp/main.cpp
===================================================================
RCS file: /cvsroot/datatype/tools/dtdriver/apps/meta3gp/main.cpp,v
retrieving revision 1.7.2.8
diff -w -U 30 -r1.7.2.8 main.cpp
--- datatype/tools/dtdriver/apps/meta3gp/main.cpp	13 Apr 2010 02:04:59 -0000	1.7.2.8
+++ datatype/tools/dtdriver/apps/meta3gp/main.cpp	2 Nov 2010 15:12:58 -0000
@@ -87,60 +87,61 @@
 /****************************************************************************
  *  DLLAccessPath Variable
  */
 ENABLE_DLLACCESS_PATHS(g_Meta3GPAccessPath);
 
 
 /****************************************************************************
  *  Defines
  */
 #define PROGRAM_VENDOR_STRING       "RealNetworks"
 #define PROGRAM_NAME_STRING         PROGRAM_VENDOR_STRING" meta-data editor"
 #define PROGRAM_COPYRIGHT_STRING    "Copyright (c) "PROGRAM_VENDOR_STRING" 2010"
 
 // input/output control
 #ifdef _WINDOWS
 #define OPTION_STRING_ASYNCMODE      "dev-asyncmode"
 #endif //_WINDOWS
 
 #define OPTION_STRING_DEFMETAPROC    "dev-defmetaproc"
 #define OPTION_STRING_INPUTFILE      "if"
 #define OPTION_STRING_OUTPUTFILE     "of"
 #define OPTION_STRING_XMLINPUTFILE   "xmlin"
 #define OPTION_STRING_XMLOUTPUTFILE  "xmlout"
 #define OPTION_STRING_CLEARMETADATA  "metaclear"
 #define OPTION_STRING_METASTYLE      "metastyle"
 #define OPTION_STRING_UTF16OUTPUT    "utf16out"
 #define OPTION_STRING_UTF8INPUT      "utf8in"
 #define OPTION_STRING_ID3V240OUTPUT  "id3v240"
 #define OPTION_STRING_ID3V230OUTPUT  "id3v230"
 #define OPTION_STRING_ID3V2NOOUTPUT  "id3v2no"
+#define OPTION_STRING_UITSLOCATIONID32 "uitslocid32"
 #define OPTION_STRING_OVERWRITEFILE  "overwrite"
 #define OPTION_STRING_DISABLEPROGRESSIVEDOWNLOAD "disableprogressivedownload"
 #define OPTION_STRING_PRINTMETADATA  "print"
 #define OPTION_STRING_HELP           "help"
 #define OPTION_STRING_GENERATEHASH   "audiohash"
 #define OPTION_STRING_LOGFILE        "log"
 
 // common metadata
 #define OPTION_STRING_TITLE            "title"
 #define OPTION_STRING_ARTIST           "artist"
 #define OPTION_STRING_ALBUM            "album"
 #define OPTION_STRING_GENRE            "genre"
 #define OPTION_STRING_COMPOSER         "composer"
 #define OPTION_STRING_COMMENT          "comment"
 #define OPTION_STRING_TRACKNUMBER      "track"
 #define OPTION_STRING_YEAR             "year"
 
 #define OPTION_STRING_PICTURE_ADD      "addpic"
 #define OPTION_STRING_PICTURE_REMOVE   "rempic"
 #define OPTION_STRING_PICTURE_CLEAR    "clrpic"
 #define OPTION_STRING_PICTURE_EXTRACT  "savepic"
 
 #define OPTION_STRING_UITS_INSERT      "insertsignature"
 #define OPTION_STRING_UITS_EXTRACT     "extractsignature"
 
 // iTunes specific metadata
 #define OPTION_STRING_SOFTWARE     "software"
 #define OPTION_STRING_ENCODEDBY    "encodedby"
 #define OPTION_STRING_GROUPING     "grouping"
 #define OPTION_STRING_ALBUMARTIST  "albumartist"
@@ -414,61 +415,61 @@
         for(int i = 0; i < descs.GetSize(); i++)
         {
             OptionDesc* od = (OptionDesc*)descs.GetAt(i);
             if(strArg == od->GetOptionString())
             {
                 return od;
             }
         }
         return NULL;
     }
 
     OptionDesc* GetOptionDescWithPath(CHXString& strArg) const
     {
         for(int i = 0; i < descs.GetSize(); i++)
         {
             OptionDesc* od = (OptionDesc*)descs.GetAt(i);
             if(od->MatchesXPath(strArg))
             {
                 return od;
             }
         }
         return NULL;
     }
 
     void InitializeXmlPathDescs(CXmlPathDescs& xmlPathDescs)
     {
         for(int i = 0; i < descs.GetSize(); i++)
         {
             OptionDesc* desc = (OptionDesc*)descs.GetAt(i);
 
-            for(int iPath = 0; iPath < desc->GetNumXPaths(); iPath++)
+            for(int iPath = 0; iPath < (int)desc->GetNumXPaths(); iPath++)
             {
                 CHXString xpath = desc->GetXPath(iPath);
                 if(!xpath.IsEmpty())
                 {
                     xmlPathDescs.Add(new XmlPathDesc(xpath));
                 }
             }
         }
     }
 
 private:
     CHXPtrArray descs;
 };
 
 void DisplayProgramInfo()
 {
     const char* pszDbg = "";
 #if defined(DEBUG) || defined(_DEBUG)
     pszDbg = ".debug";
 #endif
 
     printf("\n--- %s ---\n    %s\n    Version %s%s\n\n",
             PROGRAM_NAME_STRING, PROGRAM_COPYRIGHT_STRING, TARVER_STRING_VERSION, pszDbg);
 }
 
 void DisplayUsage(const char* argv0, OptionRegistry& optionReg)
 {
     CHXString exeName = CHXFileSpecUtils::GetCurrentApplication().GetName();
 
     printf("usage: %s [ -option [value]... ]...\n", (const char*)exeName);
@@ -1757,81 +1758,83 @@
     FPHXMEDIAPLATFORMOPEN fpHXMediaPlatformOpen = 0;
     FPHXCREATEMEDIAPLATFORM fpHXCreateMediaPlatform = 0;
     FPHXMEDIAPLATFORMCLOSE fpHXMediaPlatformClose = 0;
 
     IHXMediaPlatform* pMediaPlatform = 0;
     IHXCommonClassFactory* pCommonClassFactory = 0;
     CHXXmlInputParser* pInputParser = 0;
     IHXMetaDataEditor* pEditor = 0;
     CResponse* pResponse = 0;
     CProcessor* pProcessor = 0;
     IHXValues* pOptions = 0;
 
     char pDllPath[_MAX_PATH] = {0};
     char pDllFile[_MAX_PATH] = {0};
     const char* pszHelixPluginPath = 0;
 
     CHXString strInputFileName;
     CHXString strOutputFileName;
     CHXString strOutputXMLFileName;
     CHXString strPictureFileNamePrefix;
     CHXString strUITSDataOutputFileName;
     CHXString strMetaStyleName;
 
     HXBOOL bDisplayHelp = FALSE;
     HXBOOL bOverwriteFile = FALSE;
     HXBOOL bDisableProgressiveDownload = FALSE;
     HXBOOL bPrintMetaData = FALSE;
     HXBOOL bExtractPicturesToFiles = FALSE;
     HXBOOL bUTF16Output = FALSE;
     HXBOOL bUTF8Input = FALSE;
+    UINT32 ulMetaDataUITSLocation = METADATAUITSLOCATION_UITSATOM;
     UINT32 ulMetaDataID3VersionOutput = METADATAID3VERSION_240;
 
     MetaProcessorVars metaProcessorVars;
 
     // construct option registry
     OptionRegistry optionReg;
 
     optionReg.Add(new OptionDesc(OPTION_STRING_LOGFILE, "<filename>", "redirect console output to log file", 1));
     optionReg.Add(new OptionDesc(OPTION_STRING_INPUTFILE, "<filename>", "input file", 1, "/albums/album/track/mediaFile/fileName"));
     optionReg.Add(new OptionDesc(OPTION_STRING_OUTPUTFILE, "<filename>", "output file", 1, "/albums/album/track/outputFileName"));
     optionReg.Add(new OptionDesc(OPTION_STRING_XMLINPUTFILE, "<filename>", "XML file with input parameters", 1));
     optionReg.Add(new OptionDesc(OPTION_STRING_XMLOUTPUTFILE, "<filename>", "metadata output XML file", 1));
     optionReg.Add(new OptionDesc(OPTION_STRING_OVERWRITEFILE, 0, "overwrite output file if it exists", 0));
     optionReg.Add(new OptionDesc(OPTION_STRING_DISABLEPROGRESSIVEDOWNLOAD, 0, "disable progressive download to improve performance when not using http or ftp protocol", 0));
     optionReg.Add(new OptionDesc(OPTION_STRING_CLEARMETADATA, 0, "clear all extracted metadata before injection", 0));
     optionReg.Add(new OptionDesc(OPTION_STRING_METASTYLE, "<3GPP | iTunes>", "flavor of injected metadata", 1));
     optionReg.Add(new OptionDesc(OPTION_STRING_UTF16OUTPUT, 0, "use UTF16 format to store strings in output file", 0));
     optionReg.Add(new OptionDesc(OPTION_STRING_UTF8INPUT, 0, "parse command line as UTF8 strings", 0));
     optionReg.Add(new OptionDesc(OPTION_STRING_ID3V240OUTPUT, 0, "inject ID3v2 version 2.4.0, default", 0));
     optionReg.Add(new OptionDesc(OPTION_STRING_ID3V230OUTPUT, 0, "inject ID3v2 version 2.3.0", 0));
     optionReg.Add(new OptionDesc(OPTION_STRING_ID3V2NOOUTPUT, 0, "skip injecting ID3v2 tag", 0));
+    optionReg.Add(new OptionDesc(OPTION_STRING_UITSLOCATIONID32, 0, "inject UITS data into ID32 atom (legacy mode)", 0));
     optionReg.Add(new OptionDesc(OPTION_STRING_PRINTMETADATA, 0, "print updated metadata", 0));
     optionReg.Add(new OptionDesc(OPTION_STRING_PICTURE_EXTRACT, "[filename prefix]", "save extracted pictures", -1));
 
 #ifdef HELIX_FEATURE_METAEDIT_AUDIO_HASH
     optionReg.Add(new OptionDesc(OPTION_STRING_GENERATEHASH, 0, "generate hash", 0));
 #endif //HELIX_FEATURE_METAEDIT_AUDIO_HASH
 
     optionReg.Add(new OptionDesc());
     optionReg.Add(new OptionDesc(OPTION_STRING_TITLE, "<string>", "update title", 1, "/albums/album/track/name"));
     optionReg.Add(new OptionDesc(OPTION_STRING_ARTIST, "<string>", "update 3GPP performer, iTunes artist", 1, "/albums/album/track/artist/name"));
     optionReg.Add(new OptionDesc(OPTION_STRING_ALBUM, "<string>", "update album", 1, "/albums/album/name"));
     optionReg.Add(new OptionDesc(OPTION_STRING_GENRE, "<string>", "update genre", 1, "/albums/album/track/style/name"));
     optionReg.Add(new OptionDesc(OPTION_STRING_COMPOSER, "<string>", "update 3GPP author, iTunes composer", 1, "/albums/album/track/artist/composer"));
     optionReg.Add(new OptionDesc(OPTION_STRING_COMMENT, "<string>", "update 3GPP description, iTunes comment", 1, "/albums/album/pline"));
     optionReg.Add(new OptionDesc(OPTION_STRING_COPYRIGHT, "<string>", "update copyright", 1, "/albums/album/cline"));
     optionReg.Add(new OptionDesc(OPTION_STRING_TRACKNUMBER, "<integer 0..255>", "update track number", 1, "/albums/album/track/sequence"));
     optionReg.Add(new OptionDesc(OPTION_STRING_YEAR, "<integer 0..65536>", "update 3GPP recording year, iTunes release date", 1, "/albums/album/OrigReleaseYear"));
     {
         // Add picture
         CHXPtrArray* pPictureAddXPaths = new CHXPtrArray;
         pPictureAddXPaths->Add(new CHXString("/albums/album/image/fileName"));
         pPictureAddXPaths->Add(new CHXString("/albums/album/image/fileName2"));
 
         optionReg.Add(new OptionDesc(OPTION_STRING_PICTURE_ADD, "<filename>", "add picture", 1, 0, pPictureAddXPaths));
     }
     optionReg.Add(new OptionDesc(OPTION_STRING_PICTURE_REMOVE, "<APIC picture type>", "remove picture", 1));
     optionReg.Add(new OptionDesc(OPTION_STRING_PICTURE_CLEAR, 0, "clear all extracted pictures", 0));
     optionReg.Add(new OptionDesc(OPTION_STRING_UITS_INSERT, "<filename>", "insert UITS signature from file", 1));
     optionReg.Add(new OptionDesc(OPTION_STRING_UITS_EXTRACT, "<filename>", "extract UITS signature into file", 1));
     optionReg.Add(new OptionDesc());
@@ -2289,60 +2292,64 @@
                         }
                         else
                         {
                             retVal = HXR_PARSE_ERROR;
                             progRetCode = RC_ERROR_BAD_COMMAND_LINE;
                             ReportInvalidValueForOption(OPTION_STRING_METASTYLE, option->GetEffectiveOptionValueUTF8());
                         }
                     }
                 }
             }
             else if(strOption == OPTION_STRING_UTF16OUTPUT)
             {
                 bUTF16Output = TRUE;
             }
             else if(strOption == OPTION_STRING_UTF8INPUT)
             {
                 bUTF8Input = TRUE;
             }
             else if(strOption == OPTION_STRING_ID3V240OUTPUT)
             {
                 ulMetaDataID3VersionOutput = METADATAID3VERSION_240;
             }
             else if(strOption == OPTION_STRING_ID3V230OUTPUT)
             {
                 ulMetaDataID3VersionOutput = METADATAID3VERSION_230;
             }
             else if(strOption == OPTION_STRING_ID3V2NOOUTPUT)
             {
                 ulMetaDataID3VersionOutput = METADATAID3VERSION_NONE;
             }
+            else if(strOption == OPTION_STRING_UITSLOCATIONID32)
+            {
+                ulMetaDataUITSLocation = METADATAUITSLOCATION_ID32ATOM;
+            }
             else if(strOption == OPTION_STRING_TITLE)
             {
                 retVal = ProcessDependentStringOption(clpp, option,
                                     metaProcessorVars, MetaInfo::StringMetaItem_Title);
             }
             else if(strOption == OPTION_STRING_ARTIST)
             {
                 retVal = ProcessDependentStringOption(clpp, option,
                                     metaProcessorVars, MetaInfo::StringMetaItem_Artist);
             }
             else if(strOption == OPTION_STRING_ALBUM)
             {
                 retVal = ProcessDependentStringOption(clpp, option,
                                     metaProcessorVars, MetaInfo::StringMetaItem_Album);
             }
             else if(strOption == OPTION_STRING_GENRE)
             {
                 retVal = ProcessDependentStringOption(clpp, option,
                                     metaProcessorVars, MetaInfo::StringMetaItem_Genre);
             }
             else if(strOption == OPTION_STRING_COMPOSER)
             {
                 retVal = ProcessDependentStringOption(clpp, option,
                                     metaProcessorVars, MetaInfo::StringMetaItem_Composer);
             }
             else if(strOption == OPTION_STRING_COMMENT)
             {
                 retVal = ProcessDependentStringOption(clpp, option,
                                     metaProcessorVars, MetaInfo::StringMetaItem_Description);
             }
@@ -2664,60 +2671,66 @@
         // suppress packet processing in pure extraction mode
         if(strOutputFileName.IsEmpty() && !metaProcessorVars.GenerateHash)
         {
             retVal = pOptions->SetPropertyULONG32(TIMER_OPTION_NAME, 0);
         }
     }
 
     if(SUCCEEDED(retVal))
     {
         retVal = pOptions->SetPropertyULONG32(BLASTFILE_OPTION_NAME, bOverwriteFile ? 1 : 0);
     }
 
     if(SUCCEEDED(retVal))
     {
         retVal = pOptions->SetPropertyULONG32(DISABLEPROGRESSIVEDOWNLOAD_OPTION_NAME, bDisableProgressiveDownload ? 1 : 0);
     }
 
     if(SUCCEEDED(retVal))
     {
         retVal = pOptions->SetPropertyULONG32(UTF16OUTPUT_OPTION_NAME, bUTF16Output ? 1 : 0);
     }
 
     if(SUCCEEDED(retVal))
     {
         // Notify writer about the version of ID3 tag it should output.
         retVal = pOptions->SetPropertyULONG32(METADATAID3VERSION_OPTION_NAME, ulMetaDataID3VersionOutput);
     }
 
     if(SUCCEEDED(retVal))
     {
+        // Notify writer whether to use legacy location for UITS data.
+        retVal = pOptions->SetPropertyULONG32(METADATAUITSLOCATION_OPTION_NAME, ulMetaDataUITSLocation);
+    }
+
+    if(SUCCEEDED(retVal))
+    {
         // Notify meta-editor about the flavor of meta-data it should process.
         retVal = pOptions->SetPropertyULONG32(METADATAFLAVOR_OPTION_NAME, metaProcessorVars.InjectedMetaFlavors);
     }
 
     if(SUCCEEDED(retVal))
     {
         // Legacy ID32_BLOB property must not get in the way of newly defined properties.
         // Tell file-writer to ignore it.
         retVal = pOptions->SetPropertyULONG32(METADATAIGNORE_OPTION_NAME, METADATAIGNORE_ID32BLOB);
     }
 
     if(SUCCEEDED(retVal))
     {
         if(g_bUseDefaultMetaEditorProcessor)
         {
             retVal = pOptions->SetPropertyULONG32(BLASTMETADATA_OPTION_NAME, metaProcessorVars.ClearMetaData ? 1 : 0);
         }
         else
         {
             // Notify meta-editor that we do not want it to perform any default internal meta-data merging.
             // Custom processor in this application performs special merging of extracted and injected meta-data.
             retVal = pOptions->SetPropertyULONG32(BLASTMETADATA_OPTION_NAME, 1);
         }
     }
 
     if(FAILED(retVal))
     {
         printf("Failed to initialize options.\n");
         progRetCode = RC_ERROR_CANNOT_INIT_PROGRAM_OBJECT;
         goto cleanup;
datatype_tools_dtdriver_engine.diff (application/octet-stream, 14.5 KB)
Index: datatype/tools/dtdriver/engine/ffdriver.cpp
===================================================================
RCS file: /cvsroot/datatype/tools/dtdriver/engine/ffdriver.cpp,v
retrieving revision 1.64.2.1
diff -w -U 30 -r1.64.2.1 ffdriver.cpp
--- datatype/tools/dtdriver/engine/ffdriver.cpp	13 Apr 2010 02:04:03 -0000	1.64.2.1
+++ datatype/tools/dtdriver/engine/ffdriver.cpp	2 Nov 2010 15:13:05 -0000
@@ -257,60 +257,61 @@
     , m_ulCurrentBw(0)
     , m_ulLastThreasholdEventTime(0)
     , m_state(State_Initializing)
     , m_status(HXR_OK)
     , m_pInputFileName(NULL)
     , m_pInputURL(NULL)
     , m_pWriteFileName(NULL)
     , m_pTempDirName(NULL)
     , m_pInputFileProtocol(NULL)
     , m_pInputFileSysShortName(NULL)
     , m_uOptionFlags(DFLT_OPTIONS)
     , m_bUseNuggetFormat(FALSE)
     , m_uBandwidth(0)
     , m_ulRateMode(RATE_MODE_CONSTANT)
     , m_ulRateModeInterval(0)
     , m_ulMinBwThreshold(0)
     , m_ulMaxBwThreshold(0)
     , m_ulStartTime(0)
     , m_ulProcessUntil(0)
     , m_ulProcessTimeUnits(0)
     , m_bBandwidthExplicitlySet(FALSE)
     , m_bStartTimeExplicitlySet(FALSE)
     , m_bParseSDP(FALSE)
     , m_uServerMode(0)
     , m_ulContextEvents(0)
     , m_lTimerValue(-1)
     , m_ulRotationSize(0)
     , m_ulMetaDataFlavor(0)
     , m_ulMetaDataIgnore(0)
     , m_ulMetaDataID3Version(METADATAID3VERSION_240)
+    , m_ulMetaDataUITSLocation(METADATAUITSLOCATION_DEFAULT)
     , m_bStop(FALSE)
     , m_bSoftStop(FALSE)
     , m_bPacketReady(FALSE)
     , m_pMemProbeArray(NULL)
     , m_ulGetPacketEvents(0)
     , m_bPadToSize(FALSE)
     , m_ulTargetSize(0)
     , m_ulMediaSize(0)
     , m_pLastWrittenPacket(NULL)
     , m_pLastWrittenFileHeader(NULL)
     , m_pDupPacketTrackerList(NULL)
 #if defined (HELIX_CONFIG_USE_EXTERNAL_CONTEXT)
     , m_bPersistentContext(TRUE)
 #else
     , m_bPersistentContext(FALSE)
 #endif
     , m_ulStartTS(DTDR_INVALID_TS)
     , m_ulStartTick(0)
     , m_ulProcessingRate(0) // 0 = as fast as possible
 #ifdef HELIX_FEATURE_DTDR_USE_RECOGNIZER
     , m_pFileRecognizer(NULL)
 #endif
     , m_bUseFileRecognition(FALSE)
     , m_bLiveSource(FALSE)
     , m_bTerminated(FALSE)
 {
 #ifdef _WRITER_WRITE_SIZE_TEST
     m_bPadToSize = TRUE;
     m_ulTargetSize = WRITER_WRITE_SIZE_TEST_GOAL;
 #endif  // _WRITER_WRITE_SIZE_TEST
@@ -669,60 +670,64 @@
                 {
                     m_ulProcessTimeUnits = uOptValue;
                 }
                 else if (strcmp(pOptName, ROTATIONSIZE_OPTION_NAME) == 0)
                 {
                     m_ulRotationSize = uOptValue;
                 }
                 else if (strcmp(pOptName, PROCESSHEADERS_OPTION_NAME) == 0)
                 {
                     if (m_lTimerValue < 0)
                     {
                         m_lTimerValue = 0;
                     }
                 }
                 else if (strcmp(pOptName, FILERECOGNITION_OPTION_NAME) == 0 && uOptValue)
                 {
                     m_bUseFileRecognition = TRUE;
                 }
                 else if (strcmp(pOptName, METADATAFLAVOR_OPTION_NAME) == 0)
                 {
                     m_ulMetaDataFlavor = uOptValue;
                 }
                 else if (strcmp(pOptName, METADATAIGNORE_OPTION_NAME) == 0)
                 {
                     m_ulMetaDataIgnore = uOptValue;
                 }
                 else if (strcmp(pOptName, METADATAID3VERSION_OPTION_NAME) == 0)
                 {
                     m_ulMetaDataID3Version = uOptValue;
                 }
+                else if (strcmp(pOptName, METADATAUITSLOCATION_OPTION_NAME) == 0)
+                {
+                    m_ulMetaDataUITSLocation = uOptValue;
+                }
             }
             Status = pOptions->GetNextPropertyULONG32(pOptName, uOptValue);
         }
     }
 
     // If we are to process packets for 0 amount of time and
     // PROCESSHEADERS_OPTION_NAME is not explicitly set, assume
     // PROCESSHEADERS_OPTION_NAME is needed.
     if ((m_lTimerValue == 0) && m_pOptions)
     {
         ULONG32 ulVal = 0;
         if (FAILED(m_pOptions->GetPropertyULONG32(
             PROCESSHEADERS_OPTION_NAME,
             ulVal)))
         {
             m_pOptions->SetPropertyULONG32(
             PROCESSHEADERS_OPTION_NAME,
             1);
         }
     }
 
     // set the input option to disable progressive download for imporved performance
     if (m_pOptions)
     {
         if (m_uOptionFlags & PDOWNLOADD_OPTION)
         {
             m_pOptions->SetPropertyULONG32(
                 DISABLEPROGRESSIVEDOWNLOAD_OPTION_NAME, 
                 1);
         }
@@ -2084,60 +2089,69 @@
 
     if (SUCCEEDED(retVal))
     {
         if (m_ulMetaDataFlavor != 0)
         {
             retVal = pNewProps->SetPropertyULONG32(METADATAFLAVOR_OPTION_NAME,
                                 m_ulMetaDataFlavor);
         }
     }
 
     if (SUCCEEDED(retVal))
     {
         if (m_ulMetaDataIgnore != 0)
         {
             retVal = pNewProps->SetPropertyULONG32(METADATAIGNORE_OPTION_NAME,
                                 m_ulMetaDataIgnore);
         }
     }
 
     if (SUCCEEDED(retVal))
     {
         if (m_ulMetaDataID3Version != 0)
         {
             retVal = pNewProps->SetPropertyULONG32(METADATAID3VERSION_OPTION_NAME,
                                 m_ulMetaDataID3Version);
         }
     }
 
     if (SUCCEEDED(retVal))
     {
+        if (m_ulMetaDataUITSLocation != 0)
+        {
+            retVal = pNewProps->SetPropertyULONG32(METADATAUITSLOCATION_OPTION_NAME,
+                                m_ulMetaDataUITSLocation);
+        }
+    }
+
+    if (SUCCEEDED(retVal))
+    {
         if (m_uOptionFlags & RELATIVETS_OPTION)
         {
             retVal = pNewProps->SetPropertyULONG32("UseRelativeTS", 1);
         }
     }
 
     if (SUCCEEDED(retVal))
     {
         if (m_ulRotationSize != 0)
         {
             retVal = pNewProps->SetPropertyULONG32("RotationSize", 
                                m_ulRotationSize);
         }
     }
 
     if (SUCCEEDED(retVal))
     {
         if (m_bBandwidthExplicitlySet || 
             (m_uBandwidth != 0) ||
             (m_ulRateMode != RATE_MODE_CONSTANT))
         {
             retVal = pNewProps->SetPropertyULONG32("ForceIntoSingleRate", 1);
         }
     }
 
     if (SUCCEEDED(retVal))
     {
 	ULONG32 ulUseTempFiles = 0;
 	if (SUCCEEDED(m_pOptions->GetPropertyULONG32(USETEMPFILES_OPTION_NAME, ulUseTempFiles)))
 	{
Index: datatype/tools/dtdriver/engine/pub/ffdriver.h
===================================================================
RCS file: /cvsroot/datatype/tools/dtdriver/engine/pub/ffdriver.h,v
retrieving revision 1.47.2.1
diff -w -U 30 -r1.47.2.1 ffdriver.h
--- datatype/tools/dtdriver/engine/pub/ffdriver.h	13 Apr 2010 02:04:04 -0000	1.47.2.1
+++ datatype/tools/dtdriver/engine/pub/ffdriver.h	2 Nov 2010 15:13:05 -0000
@@ -53,60 +53,61 @@
 #define RATEMAX_OPTION_NAME	    "RateMax"
 #define RATEMIN_OPTION_NAME	    "RateMin"
 #define PACE_OPTION_NAME	    "Pace"
 #define RATEMODEINTERVAL_OPTION_NAME "RateModeInterval"
 #define TIMER_OPTION_NAME	    "Timer"
 #define PASSSWOFFPKTS_OPTION_NAME   "PassSwitchOffPackets"
 #define USETEMPFILES_OPTION_NAME    "UseTempFiles"
 #define USENUGGETFORMAT_OPTION_NAME	    "UseNuggetFormat"
 #define NUGGETEXPIRATION_OPTION_NAME	    "NuggetExpiration"
 #define NUGGETCONNECTTIME_OPTION_NAME	    "NuggetConnectTime"
 #define NUGGETREMOTESOURCEURL_OPTION_NAME   "NuggetRemoteSourceURL"
 #define QUIET_OPTION_NAME           "Quiet"
 #define JUMPSTART_OPTION_NAME	    "StartTime"
 #define PROCESSUNTIL_OPTION_NAME    "ProcessUntil"
 #define PROCESSTIMEUNITS_OPTION_NAME    "ProcessTimeUnits"
 #define PROCESSDECODEDTIMEUNITS_OPTION_NAME    "ProcessDecodedTimeUnits"
 #define TIMING_OPTION_NAME	    "Timing"
 #define EVENT_OPTION_NAME	    "Event"
 #define DURATION_OPTION_NAME	    "Duration"
 #define TITLE_OPTION_NAME   	    "Title"
 #define AUTHOR_OPTION_NAME	    "Author"
 #define COPYRIGHT_OPTION_NAME	    "Copyright"
 #define ABSTRACT_OPTION_NAME	    "Abstract"
 #define KEYWORDS_OPTION_NAME	    "Keywords"
 #define PREROLL_OPTION_NAME	    "RecomputePreroll"
 #define BLASTFILE_OPTION_NAME	    "BlastFiles"
 #define UTF16OUTPUT_OPTION_NAME     "UTF16Output"
 #define METADATAFLAVOR_OPTION_NAME  "MetaDataFlavor"
 #define METADATAIGNORE_OPTION_NAME  "MetaDataIgnore"
 #define METADATAID3VERSION_OPTION_NAME  "MetaDataID3Version"
+#define METADATAUITSLOCATION_OPTION_NAME    "MetaDataUITSLocation"
 #define SYNCHRONOUS_OPTION_NAME     "Synchronous"
 #define RECORDASLIVE_OPTION_NAME    "RecordAsLive"
 #define ROTATIONSIZE_OPTION_NAME    "RotationSize"
 #define VIDEOOFFSET_OPTION_NAME	    "VideoTimeOffset"
 #define SOURCEOFFSET_OPTION_NAME    "SourceTimeOffset"
 #define VIDEOTIMESCALE_OPTION_NAME  "VideoTimeScale"
 #define KEYFRAMESONLY_OPTION_NAME   "KeyFramesOnly"
 #define MAXFRAMERATE_OPTION_NAME    "MaxFrameRate"
 #define MINFRAMERATE_OPTION_NAME    "MinFrameRate"
 #define LOOKAHEAD_OPTION_NAME       "LookAhead"
 #define RELATIVETS_OPTION_NAME	    "RelativeTS"
 #define DECRYPT_OPTION_NAME	    "DecryptSource"
 #define DECODE_OPTION_NAME	    "DecodeSource"
 #define DECODEAUDIO_OPTION_NAME	    "DecodeAudio"
 #define DECODEVIDEO_OPTION_NAME	    "DecodeVideo"
 #define DECODENONAV_OPTION_NAME	    "DecodeNonAV"
 #define DECODESTREAM_OPTION_NAME    "DecodeStream"
 #define DECODESTREAMMODE_OPTION_NAME	"DecodeStreamMode"
 #define OUTPUTSAMPLESPERSECOND_OPTION_NAME  "OutputSamplesPerSecond"
 #define OUTPUTCHANNELS_OPTION_NAME	    "OutputChannels"
 #define OUTPUTBITSPERSAMPLE_OPTION_NAME	    "OutputBitsPerSample"	
 #define MINOUTPUTBITSPERSAMPLE_OPTION_NAME  "MinOutputBitsPerSample"	
 #define MAXOUTPUTBITSPERSAMPLE_OPTION_NAME  "MaxOutputBitsPerSample"	
 #define ENCODE_OPTION_NAME	    "EncodeSource"
 #define ENCODEAUDIO_OPTION_NAME	    "EncodeAudioFormat"
 #define ENCODEVIDEO_OPTION_NAME	    "EncodeVideoFormat"
 #define ENCODEAUDIORATE_OPTION_NAME "EncodeAudioRate"
 #define ENCODEAUDIORATETOL_OPTION_NAME "EncodeAudioRateTol"
 #define ENCODEAUDIORATEMAX_OPTION_NAME "EncodeAudioRateMax"
 #define ENCODEAUDIORATECOMPFMTS_OPTION_NAME "EncodeAudioCompFormats"
@@ -141,60 +142,65 @@
 #define DECODED_VIDEO_RESIZE_PRESERVE_ASPECT_OPTION_NAME "DecodedVideoResizePreserveAspect"
 #define COMPATIBILITY_OPTION_NAME   "Compatibility"
 
 // Merge sorter related options
 #define MERGESORTFF_OPTION_NAME       "MergeSortFileFormat"
 #define MERGESORTDEC_OPTION_NAME      "MergeSortDecode"
 #define MERGESORTENC_OPTION_NAME      "MergeSortEncode"
 #define MERGESORTFFDEPTH_OPTION_NAME  "MergeSortMaxQueueDepthPostFileFormat"
 #define MERGESORTFFTIME_OPTION_NAME   "MergeSortMaxQueueTimespanFileFormat"
 #define MERGESORTFFBYTES_OPTION_NAME  "MergeSortMaxQueueBytesFileFormat"
 #define MERGESORTDECDEPTH_OPTION_NAME "MergeSortMaxQueueDepthDecode"
 #define MERGESORTDECTIME_OPTION_NAME  "MergeSortMaxQueueTimespanDecode"
 #define MERGESORTDECBYTES_OPTION_NAME "MergeSortMaxQueueBytesDecode"
 #define MERGESORTENCDEPTH_OPTION_NAME "MergeSortMaxQueueDepthEncode"
 #define MERGESORTENCTIME_OPTION_NAME  "MergeSortMaxQueueTimespanEncode"
 #define MERGESORTENCBYTES_OPTION_NAME "MergeSortMaxQueueBytesEncode"
 
 #define RATE_MODE_CONSTANT  0
 #define RATE_MODE_UPDOWN    1
 #define RATE_MODE_UP        2
 #define RATE_MODE_DOWN      3
 
 // MetaDataIgnore values
 #define METADATAIGNORE_ID32BLOB  0x00000001
 
 // MetaDataID3Version values
 #define METADATAID3VERSION_230   0x00020300
 #define METADATAID3VERSION_240   0x00020400
 #define METADATAID3VERSION_NONE  0x01000000
 
+// MetaDataUITSLocation values
+#define METADATAUITSLOCATION_DEFAULT    0x00000000
+#define METADATAUITSLOCATION_ID32ATOM   0x00000001
+#define METADATAUITSLOCATION_UITSATOM   0x00000002
+
 
 /****************************************************************************
  *  Includes
  */
 #include "hlxclib/stdio.h"
 #include "hlxclib/stdarg.h"
 
 #include "minicntx.h"
 #include "hxmemprb.h"
 
 #include "hxsrcin.h"
 #include "hxformt.h"
 #include "hxfiles.h"
 #include "hxfwrtr.h"
 #include "hxengin.h"
 
 #include "hxslist.h"
 
 
 #ifdef HELIX_FEATURE_DTDR_USE_RECOGNIZER
 #include "recognizer.h"
 #endif
 
 
 
 
 /****************************************************************************
  * 
  *  Class:
  *
@@ -638,60 +644,61 @@
     UINT32		    m_ulLastThreasholdEventTime;
     ProcState               m_state;
     HX_RESULT               m_status;
     char*		    m_pInputFileName;
     char*		    m_pInputURL;
     char*		    m_pWriteFileName;
     char*		    m_pTempDirName;
     char*		    m_pInputFileProtocol;
     char*		    m_pInputFileSysShortName;
     ULONG32		    m_uOptionFlags;
     ULONG32		    m_uBandwidth;
     ULONG32		    m_ulRateMode;
     ULONG32		    m_ulRateModeInterval;
     ULONG32		    m_ulMinBwThreshold;
     ULONG32		    m_ulMaxBwThreshold;
     ULONG32		    m_ulStartTime;
     ULONG32		    m_ulProcessUntil;
     ULONG32                 m_ulProcessTimeUnits;
     HXBOOL		    m_bUseNuggetFormat;
     HXBOOL		    m_bBandwidthExplicitlySet;
     HXBOOL		    m_bStartTimeExplicitlySet;
     HXBOOL		    m_bParseSDP;
     ULONG32		    m_uServerMode;
     ULONG32		    m_ulContextEvents;
     ULONG32		    m_ulGetPacketEvents;
     LONG32		    m_lTimerValue;
     ULONG32		    m_ulRotationSize;
     ULONG32                 m_ulMetaDataFlavor;
     ULONG32                 m_ulMetaDataIgnore;
     ULONG32                 m_ulMetaDataID3Version;
+    ULONG32                 m_ulMetaDataUITSLocation;
     HXBOOL		    m_bStop;
     HXBOOL		    m_bSoftStop;
     HXBOOL		    m_bAwaitingFirstNonLostPacket;
     HXBOOL		    m_bPacketReady;
     HXBOOL		    m_bPadToSize;
     ULONG32		    m_ulTargetSize;
     ULONG32		    m_ulMediaSize;
     IHXPacket*		    m_pLastWrittenPacket;
     IHXValues*		    m_pLastWrittenFileHeader;
     IHXPacket**		    m_pDupPacketTrackerList;
     HXBOOL		    m_bPersistentContext;
     UINT32		    m_ulStartTS;
     UINT32		    m_ulStartTick;
     UINT32		    m_ulProcessingRate;
     HXBOOL		    m_bLiveSource;
     HXBOOL		    m_bTerminated;
 
     CHXMemProbe		    *m_pMemProbeArray;
 
 
 #ifdef HELIX_FEATURE_DTDR_USE_RECOGNIZER
 public:
     STDMETHOD(GetMimeTypeDone)(THIS_ HX_RESULT status, IHXBuffer* pMimeType);
 private:
     IHXFileRecognizer*      m_pFileRecognizer;
     CHXString               m_strMimeType;
 #endif
     HXBOOL                  m_bUseFileRecognition;