+//
+ASDCP::Result_t
+ASDCP::TimedText::MXFReader::h__Reader::MD_to_TimedText_TDesc(TimedText::TimedTextDescriptor& TDesc)
+{
+ assert(m_EssenceDescriptor);
+ memset(&m_TDesc.AssetID, 0, UUIDlen);
+ MXF::DCTimedTextDescriptor* TDescObj = (MXF::DCTimedTextDescriptor*)m_EssenceDescriptor;
+
+ TDesc.EditRate = TDescObj->SampleRate;
+ TDesc.ContainerDuration = TDescObj->ContainerDuration;
+ TDesc.NamespaceName = TDescObj->RootNamespaceName;
+ TDesc.EncodingName = TDescObj->UTFEncoding;
+
+ Batch<UUID>::const_iterator sdi = TDescObj->SubDescriptors.begin();
+ DCTimedTextResourceDescriptor* DescObject = 0;
+ Result_t result = RESULT_OK;
+
+ for ( ; sdi != TDescObj->SubDescriptors.end() && KM_SUCCESS(result); sdi++ )
+ {
+ result = m_HeaderPart.GetMDObjectByID(*sdi, (InterchangeObject**)&DescObject);
+
+ if ( KM_SUCCESS(result) )
+ {
+ TimedTextResourceDescriptor TmpResource;
+ memcpy(TmpResource.ResourceID, DescObject->ResourcePackageID.Value(), UUIDlen);
+
+ if ( DescObject->ResourceMIMEType.find("font/") != std::string::npos )
+ TmpResource.Type = MT_OPENTYPE;
+
+ else if ( DescObject->ResourceMIMEType.find("image/png") != std::string::npos )
+ TmpResource.Type = MT_PNG;
+
+ else
+ TmpResource.Type = MT_BIN;
+
+ TDesc.ResourceList.push_back(TmpResource);
+ m_ResourceMap.insert(ResourceMap_t::value_type(DescObject->ResourcePackageID, *sdi));
+ }
+ else
+ {
+ DefaultLogSink().Error("Broken sub-descriptor link\n");
+ return RESULT_FORMAT;
+ }
+ }
+
+ return RESULT_OK;
+}
+
+//
+ASDCP::Result_t
+ASDCP::TimedText::MXFReader::h__Reader::OpenRead(char const* filename)
+{
+ Result_t result = OpenMXFRead(filename);
+
+ if( ASDCP_SUCCESS(result) )
+ {
+ if ( m_EssenceDescriptor == 0 )
+ m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(DCTimedTextDescriptor), (InterchangeObject**)&m_EssenceDescriptor);
+
+ result = MD_to_TimedText_TDesc(m_TDesc);
+ }
+
+ if( ASDCP_SUCCESS(result) )
+ result = InitMXFIndex();
+
+ if( ASDCP_SUCCESS(result) )
+ result = InitInfo();
+
+ if( ASDCP_SUCCESS(result) )
+ memcpy(m_TDesc.AssetID, m_Info.AssetUUID, UUIDlen);
+
+ return result;
+}
+
+//
+ASDCP::Result_t
+ASDCP::TimedText::MXFReader::h__Reader::ReadTimedTextResource(FrameBuffer& FrameBuf,
+ AESDecContext* Ctx, HMACContext* HMAC)
+{
+ if ( ! m_File.IsOpen() )
+ return RESULT_INIT;
+
+ Result_t result = ReadEKLVFrame(0, FrameBuf, Dict::ul(MDD_DCTimedTextEssence), Ctx, HMAC);
+
+ if( ASDCP_SUCCESS(result) )
+ {
+ FrameBuf.AssetID(m_TDesc.AssetID);
+ FrameBuf.MIMEType("text/xml");
+ }
+
+ return result;
+}
+
+//
+ASDCP::Result_t
+ASDCP::TimedText::MXFReader::h__Reader::ReadAncillaryResource(const byte_t* uuid, FrameBuffer& FrameBuf,
+ AESDecContext* Ctx, HMACContext* HMAC)
+{
+ KM_TEST_NULL_L(uuid);
+ UUID RID(uuid);
+
+ ResourceMap_t::const_iterator ri = m_ResourceMap.find(RID);
+ if ( ri == m_ResourceMap.end() )
+ {
+ char buf[64];
+ DefaultLogSink().Error("No such resource: %s\n", RID.EncodeHex(buf, 64));
+ return RESULT_RANGE;
+ }
+
+ DCTimedTextResourceDescriptor* DescObject = 0;
+ // get the subdescriptor
+ Result_t result = m_HeaderPart.GetMDObjectByID((*ri).second, (InterchangeObject**)&DescObject);
+
+ if ( KM_SUCCESS(result) )
+ {
+ Array<RIP::Pair>::const_iterator pi;
+ RIP::Pair TmpPair;
+ ui32_t sequence = 1;
+
+ // Look up the partition start in the RIP using the SID.
+ // Count the sequence length in because this is the sequence
+ // value needed to complete the HMAC.
+ for ( pi = m_HeaderPart.m_RIP.PairArray.begin(); pi != m_HeaderPart.m_RIP.PairArray.end(); pi++, sequence++ )
+ {
+ if ( (*pi).BodySID == DescObject->ResourceSID )
+ {
+ TmpPair = *pi;
+ break;
+ }
+ }
+
+ if ( TmpPair.ByteOffset == 0 )
+ {
+ DefaultLogSink().Error("Body SID not found in RIP set: %d\n", DescObject->ResourceSID);
+ return RESULT_FORMAT;
+ }
+
+ if ( KM_SUCCESS(result) )
+ {
+ FrameBuf.AssetID(uuid);
+ FrameBuf.MIMEType(DescObject->ResourceMIMEType);
+
+ // seek tp the start of the partition
+ if ( (Kumu::fpos_t)TmpPair.ByteOffset != m_LastPosition )
+ {
+ m_LastPosition = TmpPair.ByteOffset;
+ result = m_File.Seek(TmpPair.ByteOffset);
+ }
+
+ // read the partition header
+ MXF::Partition GSPart;
+ result = GSPart.InitFromFile(m_File);
+
+ if( ASDCP_SUCCESS(result) )
+ {
+ // check the SID
+ if ( DescObject->ResourceSID != GSPart.BodySID )
+ {
+ char buf[64];
+ DefaultLogSink().Error("Generic stream partition body differs: %s\n", RID.EncodeHex(buf, 64));
+ return RESULT_FORMAT;
+ }
+
+ // read the essence packet
+ if( ASDCP_SUCCESS(result) )
+ result = ReadEKLVPacket(0, FrameBuf, Dict::ul(MDD_DCTimedTextDescriptor), Ctx, HMAC);
+ }
+ }
+ }
+
+ return result;
+}
+
+