X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2FAS_DCP_internal.h;h=83272c09b431a8861ab0a0355abc0172d186d961;hb=0317dcb43c14eae0393552999bc2389abec52336;hp=6fa4fa19b58901de33943cc18e6584849becac63;hpb=12051ad32d54a72a1a8682e15af1a185a61f1c61;p=asdcplib.git diff --git a/src/AS_DCP_internal.h b/src/AS_DCP_internal.h index 6fa4fa1..83272c0 100755 --- a/src/AS_DCP_internal.h +++ b/src/AS_DCP_internal.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2004-2013, John Hurst +Copyright (c) 2004-2018, John Hurst All rights reserved. Redistribution and use in source and binary forms, with or without @@ -47,6 +47,10 @@ using namespace ASDCP::MXF; #endif +// uncomment to remove MXFGCGenericEssenceMultipleMappings from your AS-02 files +// #define ASDCP_GCMULTI_PATCH + + #ifdef DEFAULT_MD_DECL ASDCP::MXF::OP1aHeader *g_OP1aHeader; ASDCP::MXF::OPAtomIndexFooter *g_OPAtomIndexFooter; @@ -60,7 +64,6 @@ extern MXF::RIP *g_RIP; namespace ASDCP { - void default_md_object_init(); // static std::vector @@ -74,14 +77,14 @@ namespace ASDCP { assert(r >= pstr); if ( r > pstr ) - result.push_back(atoi(pstr)); + result.push_back(strtol(pstr, 0, 10)); pstr = r + 1; r = strchr(pstr, '.'); } if( strlen(pstr) > 0 ) - result.push_back(atoi(pstr)); + result.push_back(strtol(pstr, 0, 10)); assert(result.size() == 3); return result; @@ -123,42 +126,55 @@ namespace ASDCP { 0x43, 0x48, 0x55, 0x4b, 0x43, 0x48, 0x55, 0x4b, 0x43, 0x48, 0x55, 0x4b, 0x43, 0x48, 0x55, 0x4b }; + // Version of MXF spec to which an MXF file conforms + enum MXFVersion + { + MXFVersion_2004, + MXFVersion_2011, + MXFVersion_MAX + }; + + // version numbers from the MXF spec, to be written into files + + ui8_t const MXF_ObjectModelVersion = 1; + ui8_t const MXF_2004_MinorVersion = 2; + ui8_t const MXF_2011_MinorVersion = 3; + + //------------------------------------------------------------------------------------------ // + ui32_t derive_timecode_rate_from_edit_rate(const ASDCP::Rational& edit_rate); + Result_t MD_to_WriterInfo(MXF::Identification*, WriterInfo&); Result_t MD_to_CryptoInfo(MXF::CryptographicContext*, WriterInfo&, const Dictionary&); Result_t EncryptFrameBuffer(const ASDCP::FrameBuffer&, ASDCP::FrameBuffer&, AESEncContext*); Result_t DecryptFrameBuffer(const ASDCP::FrameBuffer&, ASDCP::FrameBuffer&, AESDecContext*); - Result_t MD_to_JP2K_PDesc(const ASDCP::MXF::RGBAEssenceDescriptor& EssenceDescriptor, - const ASDCP::MXF::JPEG2000PictureSubDescriptor& EssenceSubDescriptor, - const ASDCP::Rational& EditRate, const ASDCP::Rational& SampleRate, - ASDCP::JP2K::PictureDescriptor& PDesc); - - Result_t JP2K_PDesc_to_MD(const JP2K::PictureDescriptor& PDesc, - const ASDCP::Dictionary& dict, - ASDCP::MXF::RGBAEssenceDescriptor *EssenceDescriptor, - ASDCP::MXF::JPEG2000PictureSubDescriptor *EssenceSubDescriptor); - - Result_t MD_to_JP2K_PDesc(const ASDCP::MXF::CDCIEssenceDescriptor& EssenceDescriptor, + Result_t MD_to_JP2K_PDesc(const ASDCP::MXF::GenericPictureEssenceDescriptor& EssenceDescriptor, const ASDCP::MXF::JPEG2000PictureSubDescriptor& EssenceSubDescriptor, const ASDCP::Rational& EditRate, const ASDCP::Rational& SampleRate, ASDCP::JP2K::PictureDescriptor& PDesc); Result_t JP2K_PDesc_to_MD(const JP2K::PictureDescriptor& PDesc, const ASDCP::Dictionary& dict, - ASDCP::MXF::CDCIEssenceDescriptor *EssenceDescriptor, - ASDCP::MXF::JPEG2000PictureSubDescriptor *EssenceSubDescriptor); + ASDCP::MXF::GenericPictureEssenceDescriptor& EssenceDescriptor, + ASDCP::MXF::JPEG2000PictureSubDescriptor& EssenceSubDescriptor); Result_t PCM_ADesc_to_MD(PCM::AudioDescriptor& ADesc, ASDCP::MXF::WaveAudioDescriptor* ADescObj); Result_t MD_to_PCM_ADesc(ASDCP::MXF::WaveAudioDescriptor* ADescObj, PCM::AudioDescriptor& ADesc); - void AddDMScrypt(Partition& HeaderPart, SourcePackage& Package, + void AddDmsCrypt(Partition& HeaderPart, SourcePackage& Package, WriterInfo& Descr, const UL& WrappingUL, const Dictionary*& Dict); - Result_t Read_EKLV_Packet(Kumu::FileReader& File, const ASDCP::Dictionary& Dict, const MXF::OP1aHeader& HeaderPart, + Result_t AddDmsTrackGenericPartUtf8Text(Kumu::FileWriter&, ASDCP::MXF::OP1aHeader&, SourcePackage&, + ASDCP::MXF::RIP&, const Dictionary*&); + // + Result_t WriteGenericStreamPartition(Kumu::FileWriter&, ASDCP::MXF::OP1aHeader&, ASDCP::MXF::RIP&, const Dictionary*&, + const ASDCP::FrameBuffer&, ASDCP::AESEncContext* = 0, ASDCP::HMACContext* = 0); + + Result_t Read_EKLV_Packet(Kumu::FileReader& File, const ASDCP::Dictionary& Dict, const ASDCP::WriterInfo& Info, Kumu::fpos_t& LastPosition, ASDCP::FrameBuffer& CtFrameBuf, ui32_t FrameNum, ui32_t SequenceNum, ASDCP::FrameBuffer& FrameBuf, const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC); @@ -166,9 +182,9 @@ namespace ASDCP Result_t Write_EKLV_Packet(Kumu::FileWriter& File, const ASDCP::Dictionary& Dict, const MXF::OP1aHeader& HeaderPart, const ASDCP::WriterInfo& Info, ASDCP::FrameBuffer& CtFrameBuf, ui32_t& FramesWritten, ui64_t & StreamOffset, const ASDCP::FrameBuffer& FrameBuf, const byte_t* EssenceUL, + const ui32_t& MinEssenceElementBerLength, AESEncContext* Ctx, HMACContext* HMAC); - // class KLReader : public ASDCP::KLVPacket { @@ -222,7 +238,7 @@ namespace ASDCP const MXF::RIP& GetRIP() const { return m_RIP; } // - Result_t OpenMXFRead(const char* filename) + Result_t OpenMXFRead(const std::string& filename) { m_LastPosition = 0; Result_t result = m_File.OpenRead(filename); @@ -233,7 +249,7 @@ namespace ASDCP if ( ASDCP_SUCCESS(result) ) { result = m_RIP.InitFromFile(m_File); - ui32_t test_s = m_RIP.PairArray.size(); + ui32_t test_s = (ui32_t)m_RIP.PairArray.size(); if ( ASDCP_FAILURE(result) ) { @@ -295,7 +311,8 @@ namespace ASDCP } // positions file before reading - Result_t ReadEKLVFrame(const ASDCP::MXF::Partition& CurrentPartition, + // allows external control of index offset + Result_t ReadEKLVFrame(const ui64_t& body_offset, ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf, const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC) { @@ -308,8 +325,8 @@ namespace ASDCP return RESULT_RANGE; } - // get frame position and go read the frame's key and length - Kumu::fpos_t FilePosition = CurrentPartition.BodyOffset + TmpEntry.StreamOffset; + // get relative frame position, apply offset and go read the frame's key and length + Kumu::fpos_t FilePosition = body_offset + TmpEntry.StreamOffset; Result_t result = RESULT_OK; if ( FilePosition != m_LastPosition ) @@ -324,17 +341,46 @@ namespace ASDCP return result; } + // positions file before reading + // assumes "processed" index entries have absolute positions + Result_t ReadEKLVFrame(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf, + const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC) + { + // look up frame index node + IndexTableSegment::IndexEntry TmpEntry; + + if ( KM_FAILURE(m_IndexAccess.Lookup(FrameNum, TmpEntry)) ) + { + DefaultLogSink().Error("Frame value out of range: %u\n", FrameNum); + return RESULT_RANGE; + } + + // get absolute frame position and go read the frame's key and length + Result_t result = RESULT_OK; + + if ( TmpEntry.StreamOffset != m_LastPosition ) + { + m_LastPosition = TmpEntry.StreamOffset; + result = m_File.Seek(TmpEntry.StreamOffset); + } + + if ( KM_SUCCESS(result) ) + result = ReadEKLVPacket(FrameNum, FrameNum + 1, FrameBuf, EssenceUL, Ctx, HMAC); + + return result; + } + // reads from current position Result_t ReadEKLVPacket(ui32_t FrameNum, ui32_t SequenceNum, ASDCP::FrameBuffer& FrameBuf, const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC) { assert(m_Dict); - return Read_EKLV_Packet(m_File, *m_Dict, m_HeaderPart, m_Info, m_LastPosition, m_CtFrameBuf, + return Read_EKLV_Packet(m_File, *m_Dict, m_Info, m_LastPosition, m_CtFrameBuf, FrameNum, SequenceNum, FrameBuf, EssenceUL, Ctx, HMAC); } // Get the position of a frame from a track file - Result_t LocateFrame(const ASDCP::MXF::Partition& CurrentPartition, + Result_t LocateFrame(const ui64_t& body_offset, ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) { @@ -348,13 +394,77 @@ namespace ASDCP } // get frame position, temporal offset, and key frame ofset - streamOffset = CurrentPartition.BodyOffset + TmpEntry.StreamOffset; + streamOffset = body_offset + TmpEntry.StreamOffset; temporalOffset = TmpEntry.TemporalOffset; keyFrameOffset = TmpEntry.KeyFrameOffset; return RESULT_OK; } + // Reads a Generic Stream Partition payload. Returns RESULT_FORMAT if the SID is + // not present in the RIP, or if the actual partition at ByteOffset does not have + // a matching BodySID value. Encryption is not currently supported. + Result_t ReadGenericStreamPartitionPayload(const ui32_t sid, ASDCP::FrameBuffer& frame_buf, + AESDecContext* Ctx, HMACContext* HMAC) + { + Kumu::fpos_t start_offset = 0, end_offset = 0; + ui32_t sequence = 0; + + // locate SID, record the offset + // Count the sequence length in because this is the sequence + // value needed to complete the HMAC. + ASDCP::MXF::RIP::const_pair_iterator i; + for ( i = m_RIP.PairArray.begin(); i != m_RIP.PairArray.end(); ++i, ++sequence ) + { + if ( sid == i->BodySID ) + { + start_offset = i->ByteOffset; + } + else if ( start_offset != 0 ) + { + end_offset = i->ByteOffset; + break; + } + } + + if ( start_offset == 0 || end_offset == 0 ) + { + DefaultLogSink().Error("Body SID not found: %d.\n", sid); + return RESULT_NOT_FOUND; + } + + // Read the Partition header and then read the payload. + Result_t result = m_File.Seek(start_offset); + + if ( KM_SUCCESS(result) ) + { + result = frame_buf.Capacity(end_offset-start_offset); + } + + if ( KM_SUCCESS(result) ) + { + // read the partition header + ASDCP::MXF::Partition GSPart(m_Dict); + result = GSPart.InitFromFile(m_File); + + if ( KM_SUCCESS(result) ) + { + // check the SID + if ( GSPart.BodySID != sid ) + { + DefaultLogSink().Error("Generic stream partition Body SID differs: %s\n", sid); + result = RESULT_FORMAT; + } + else + { + result = ReadEKLVPacket(0, sequence, frame_buf, m_Dict->ul(MDD_GenericStream_DataElement), Ctx, HMAC); + } + } + } + + return result; + } + // void Close() { @@ -380,13 +490,13 @@ namespace ASDCP template TrackSet CreateTrackAndSequence(OP1aHeader& Header, PackageT& Package, const std::string TrackName, - const MXF::Rational& EditRate, const UL& Definition, ui32_t TrackID, const Dictionary*& Dict) + const MXF::Rational& clip_edit_rate, const UL& Definition, ui32_t TrackID, const Dictionary*& Dict) { TrackSet NewTrack; NewTrack.Track = new Track(Dict); Header.AddChildObject(NewTrack.Track); - NewTrack.Track->EditRate = EditRate; + NewTrack.Track->EditRate = clip_edit_rate; Package.Tracks.push_back(NewTrack.Track->InstanceUID); NewTrack.Track->TrackID = TrackID; NewTrack.Track->TrackName = TrackName.c_str(); @@ -403,17 +513,19 @@ namespace ASDCP template TrackSet CreateTimecodeTrack(OP1aHeader& Header, PackageT& Package, - const MXF::Rational& EditRate, ui32_t TCFrameRate, ui64_t TCStart, const Dictionary*& Dict) + const MXF::Rational& tc_edit_rate, ui32_t tc_frame_rate, ui64_t TCStart, const Dictionary*& Dict) { assert(Dict); UL TCUL(Dict->ul(MDD_TimecodeDataDef)); - TrackSet NewTrack = CreateTrackAndSequence(Header, Package, "Timecode Track", EditRate, TCUL, 1, Dict); + TrackSet NewTrack = + CreateTrackAndSequence(Header, Package, "Timecode Track", + tc_edit_rate, TCUL, 1, Dict); NewTrack.Clip = new TimecodeComponent(Dict); Header.AddChildObject(NewTrack.Clip); NewTrack.Sequence->StructuralComponents.push_back(NewTrack.Clip->InstanceUID); - NewTrack.Clip->RoundedTimecodeBase = TCFrameRate; + NewTrack.Clip->RoundedTimecodeBase = tc_frame_rate; NewTrack.Clip->StartTimecode = TCStart; NewTrack.Clip->DataDefinition = TCUL; @@ -428,6 +540,7 @@ namespace ASDCP ST_READY, // ready to write frames ST_RUNNING, // one or more frames written ST_FINAL, // index written, file closed + ST_MAX }; // implementation of h__WriterState class Goto_* methods @@ -477,6 +590,7 @@ namespace ASDCP MaterialPackage* m_MaterialPackage; SourcePackage* m_FilePackage; + ContentStorage* m_ContentStorage; FileDescriptor* m_EssenceDescriptor; std::list m_EssenceSubDescriptorList; @@ -491,9 +605,9 @@ namespace ASDCP DurationElementList_t m_DurationUpdateList; TrackFileWriter(const Dictionary& d) : - m_Dict(&d), m_HeaderPart(m_Dict), m_RIP(m_Dict), - m_HeaderSize(0), m_EssenceDescriptor(0), - m_FramesWritten(0), m_StreamOffset(0) + m_Dict(&d), m_HeaderSize(0), m_HeaderPart(m_Dict), m_RIP(m_Dict), + m_MaterialPackage(0), m_FilePackage(0), m_ContentStorage(0), + m_EssenceDescriptor(0), m_FramesWritten(0), m_StreamOffset(0) { default_md_object_init(); } @@ -504,11 +618,11 @@ namespace ASDCP const MXF::RIP& GetRIP() const { return m_RIP; } - void InitHeader() + void InitHeader(const MXFVersion& mxf_ver) { assert(m_Dict); assert(m_EssenceDescriptor); - + m_HeaderPart.m_Primer.ClearTagList(); m_HeaderPart.m_Preface = new Preface(m_Dict); m_HeaderPart.AddChildObject(m_HeaderPart.m_Preface); @@ -518,6 +632,20 @@ namespace ASDCP m_HeaderPart.m_Preface->OperationalPattern = UL(m_Dict->ul(MDD_OP1a)); m_HeaderPart.OperationalPattern = m_HeaderPart.m_Preface->OperationalPattern; + if ( mxf_ver == MXFVersion_2004 ) + { + m_HeaderPart.MinorVersion = MXF_2004_MinorVersion; + m_HeaderPart.m_Preface->Version = ((MXF_ObjectModelVersion << 8) | MXF_2004_MinorVersion); + m_HeaderPart.m_Preface->ObjectModelVersion = MXF_ObjectModelVersion; + } + else + { + assert(mxf_ver == MXFVersion_2011); + m_HeaderPart.MinorVersion = MXF_2011_MinorVersion; + m_HeaderPart.m_Preface->Version = ((MXF_ObjectModelVersion << 8) | MXF_2011_MinorVersion); + m_HeaderPart.m_Preface->ObjectModelVersion = MXF_ObjectModelVersion; + } + // Identification Identification* Ident = new Identification(m_Dict); m_HeaderPart.AddChildObject(Ident); @@ -540,18 +668,21 @@ namespace ASDCP } // - void AddSourceClip(const MXF::Rational& EditRate, ui32_t TCFrameRate, + void AddSourceClip(const MXF::Rational& clip_edit_rate, + const MXF::Rational& tc_edit_rate, ui32_t TCFrameRate, const std::string& TrackName, const UL& EssenceUL, const UL& DataDefinition, const std::string& PackageLabel) { - // - ContentStorage* Storage = new ContentStorage(m_Dict); - m_HeaderPart.AddChildObject(Storage); - m_HeaderPart.m_Preface->ContentStorage = Storage->InstanceUID; + if ( m_ContentStorage == 0 ) + { + m_ContentStorage = new ContentStorage(m_Dict); + m_HeaderPart.AddChildObject(m_ContentStorage); + m_HeaderPart.m_Preface->ContentStorage = m_ContentStorage->InstanceUID; + } EssenceContainerData* ECD = new EssenceContainerData(m_Dict); m_HeaderPart.AddChildObject(ECD); - Storage->EssenceContainerData.push_back(ECD->InstanceUID); + m_ContentStorage->EssenceContainerData.push_back(ECD->InstanceUID); ECD->IndexSID = 129; ECD->BodySID = 1; @@ -564,22 +695,26 @@ namespace ASDCP // Material Package // m_MaterialPackage = new MaterialPackage(m_Dict); - m_MaterialPackage->Name = "AS-DCP Material Package"; + m_MaterialPackage->Name = "Material Package"; m_MaterialPackage->PackageUID = MaterialPackageUMID; m_HeaderPart.AddChildObject(m_MaterialPackage); - Storage->Packages.push_back(m_MaterialPackage->InstanceUID); + m_ContentStorage->Packages.push_back(m_MaterialPackage->InstanceUID); TrackSet MPTCTrack = CreateTimecodeTrack(m_HeaderPart, *m_MaterialPackage, - EditRate, TCFrameRate, 0, m_Dict); - m_DurationUpdateList.push_back(&(MPTCTrack.Sequence->Duration)); - m_DurationUpdateList.push_back(&(MPTCTrack.Clip->Duration)); + tc_edit_rate, TCFrameRate, 0, m_Dict); + + MPTCTrack.Sequence->Duration.set_has_value(); + m_DurationUpdateList.push_back(&(MPTCTrack.Sequence->Duration.get())); + MPTCTrack.Clip->Duration.set_has_value(); + m_DurationUpdateList.push_back(&(MPTCTrack.Clip->Duration.get())); TrackSet MPTrack = CreateTrackAndSequence(m_HeaderPart, *m_MaterialPackage, - TrackName, EditRate, DataDefinition, + TrackName, clip_edit_rate, DataDefinition, 2, m_Dict); - m_DurationUpdateList.push_back(&(MPTrack.Sequence->Duration)); + MPTrack.Sequence->Duration.set_has_value(); + m_DurationUpdateList.push_back(&(MPTrack.Sequence->Duration.get())); MPTrack.Clip = new SourceClip(m_Dict); m_HeaderPart.AddChildObject(MPTrack.Clip); @@ -587,7 +722,9 @@ namespace ASDCP MPTrack.Clip->DataDefinition = DataDefinition; MPTrack.Clip->SourcePackageID = SourcePackageUMID; MPTrack.Clip->SourceTrackID = 2; - m_DurationUpdateList.push_back(&(MPTrack.Clip->Duration)); + + MPTrack.Clip->Duration.set_has_value(); + m_DurationUpdateList.push_back(&(MPTrack.Clip->Duration.get())); // @@ -599,19 +736,24 @@ namespace ASDCP ECD->LinkedPackageUID = SourcePackageUMID; m_HeaderPart.AddChildObject(m_FilePackage); - Storage->Packages.push_back(m_FilePackage->InstanceUID); + m_ContentStorage->Packages.push_back(m_FilePackage->InstanceUID); TrackSet FPTCTrack = CreateTimecodeTrack(m_HeaderPart, *m_FilePackage, - EditRate, TCFrameRate, - ui64_C(3600) * TCFrameRate, m_Dict); - m_DurationUpdateList.push_back(&(FPTCTrack.Sequence->Duration)); - m_DurationUpdateList.push_back(&(FPTCTrack.Clip->Duration)); + tc_edit_rate, TCFrameRate, 0, m_Dict); + + FPTCTrack.Sequence->Duration.set_has_value(); + m_DurationUpdateList.push_back(&(FPTCTrack.Sequence->Duration.get())); + FPTCTrack.Clip->Duration.set_has_value(); + m_DurationUpdateList.push_back(&(FPTCTrack.Clip->Duration.get())); + TrackSet FPTrack = CreateTrackAndSequence(m_HeaderPart, *m_FilePackage, - TrackName, EditRate, DataDefinition, + TrackName, clip_edit_rate, DataDefinition, 2, m_Dict); - m_DurationUpdateList.push_back(&(FPTrack.Sequence->Duration)); + + FPTrack.Sequence->Duration.set_has_value(); + m_DurationUpdateList.push_back(&(FPTrack.Sequence->Duration.get())); // Consult ST 379:2004 Sec. 6.3, "Element to track relationship" to see where "12" comes from. FPTrack.Track->TrackNumber = KM_i32_BE(Kumu::cp2i((EssenceUL.Value() + 12))); @@ -624,93 +766,10 @@ namespace ASDCP // for now we do not allow setting this value, so all files will be 'original' FPTrack.Clip->SourceTrackID = 0; FPTrack.Clip->SourcePackageID = NilUMID; - m_DurationUpdateList.push_back(&(FPTrack.Clip->Duration)); - - m_EssenceDescriptor->LinkedTrackID = FPTrack.Track->TrackID; - } - - // - void AddDMSegment(const MXF::Rational& EditRate, ui32_t TCFrameRate, - const std::string& TrackName, const UL& DataDefinition, - const std::string& PackageLabel) - { - // - ContentStorage* Storage = new ContentStorage(m_Dict); - m_HeaderPart.AddChildObject(Storage); - m_HeaderPart.m_Preface->ContentStorage = Storage->InstanceUID; - - EssenceContainerData* ECD = new EssenceContainerData(m_Dict); - m_HeaderPart.AddChildObject(ECD); - Storage->EssenceContainerData.push_back(ECD->InstanceUID); - ECD->IndexSID = 129; - ECD->BodySID = 1; - - UUID assetUUID(m_Info.AssetUUID); - UMID SourcePackageUMID, MaterialPackageUMID; - SourcePackageUMID.MakeUMID(0x0f, assetUUID); - MaterialPackageUMID.MakeUMID(0x0f); // unidentified essence - - // - // Material Package - // - m_MaterialPackage = new MaterialPackage(m_Dict); - m_MaterialPackage->Name = "AS-DCP Material Package"; - m_MaterialPackage->PackageUID = MaterialPackageUMID; - m_HeaderPart.AddChildObject(m_MaterialPackage); - Storage->Packages.push_back(m_MaterialPackage->InstanceUID); - - TrackSet MPTCTrack = - CreateTimecodeTrack(m_HeaderPart, *m_MaterialPackage, - EditRate, TCFrameRate, 0, m_Dict); - m_DurationUpdateList.push_back(&(MPTCTrack.Sequence->Duration)); - m_DurationUpdateList.push_back(&(MPTCTrack.Clip->Duration)); - - TrackSet MPTrack = - CreateTrackAndSequence(m_HeaderPart, *m_MaterialPackage, - TrackName, EditRate, DataDefinition, - 2, m_Dict); - m_DurationUpdateList.push_back(&(MPTrack.Sequence->Duration)); - MPTrack.Clip = new DMSegment(m_Dict); - m_HeaderPart.AddChildObject(MPTrack.Clip); - MPTrack.Sequence->StructuralComponents.push_back(MPTrack.Clip->InstanceUID); - MPTrack.Clip->DataDefinition = DataDefinition; - // MPTrack.Clip->SourcePackageID = SourcePackageUMID; - // MPTrack.Clip->SourceTrackID = 2; - m_DurationUpdateList.push_back(&(MPTrack.Clip->Duration)); - - - // - // File (Source) Package - // - m_FilePackage = new SourcePackage(m_Dict); - m_FilePackage->Name = PackageLabel.c_str(); - m_FilePackage->PackageUID = SourcePackageUMID; - ECD->LinkedPackageUID = SourcePackageUMID; - - m_HeaderPart.AddChildObject(m_FilePackage); - Storage->Packages.push_back(m_FilePackage->InstanceUID); - - TrackSet FPTCTrack = - CreateTimecodeTrack(m_HeaderPart, *m_FilePackage, - EditRate, TCFrameRate, - ui64_C(3600) * TCFrameRate, m_Dict); - m_DurationUpdateList.push_back(&(FPTCTrack.Sequence->Duration)); - m_DurationUpdateList.push_back(&(FPTCTrack.Clip->Duration)); - - TrackSet FPTrack = - CreateTrackAndSequence(m_HeaderPart, *m_FilePackage, - TrackName, EditRate, DataDefinition, - 2, m_Dict); - m_DurationUpdateList.push_back(&(FPTrack.Sequence->Duration)); - - FPTrack.Clip = new DMSegment(m_Dict); - m_HeaderPart.AddChildObject(FPTrack.Clip); - FPTrack.Sequence->StructuralComponents.push_back(FPTrack.Clip->InstanceUID); - FPTrack.Clip->DataDefinition = DataDefinition; - FPTrack.Clip->EventComment = "D-Cinema Timed Text"; + FPTrack.Clip->Duration.set_has_value(); + m_DurationUpdateList.push_back(&(FPTrack.Clip->Duration.get())); - m_DurationUpdateList.push_back(&(FPTrack.Clip->Duration)); m_EssenceDescriptor->LinkedTrackID = FPTrack.Track->TrackID; } @@ -727,15 +786,18 @@ namespace ASDCP // Essence Descriptors // assert(m_Dict); +#ifndef ASDCP_GCMULTI_PATCH UL GenericContainerUL(m_Dict->ul(MDD_GCMulti)); m_HeaderPart.EssenceContainers.push_back(GenericContainerUL); +#endif if ( m_Info.EncryptedEssence ) { UL CryptEssenceUL(m_Dict->ul(MDD_EncryptedContainerLabel)); m_HeaderPart.EssenceContainers.push_back(CryptEssenceUL); m_HeaderPart.m_Preface->DMSchemes.push_back(UL(m_Dict->ul(MDD_CryptographicFrameworkLabel))); - AddDMScrypt(m_HeaderPart, *m_FilePackage, m_Info, WrappingUL, m_Dict); + AddDmsCrypt(m_HeaderPart, *m_FilePackage, m_Info, WrappingUL, m_Dict); + //// TODO: fix DMSegment Duration value } else { @@ -752,6 +814,48 @@ namespace ASDCP m_FilePackage->Descriptor = m_EssenceDescriptor->InstanceUID; } + Result_t AddDmsGenericPartUtf8Text(const ASDCP::FrameBuffer& frame_buffer, + ASDCP::AESEncContext* enc = 0, ASDCP::HMACContext* hmac = 0) + { + Kumu::fpos_t previous_partition_offset = m_RIP.PairArray.back().ByteOffset; + Result_t result = AddDmsTrackGenericPartUtf8Text(m_File, m_HeaderPart, *m_FilePackage, m_RIP, m_Dict); + + if ( KM_SUCCESS(result) ) + { + // m_RIP now contains an entry (at the back) for the new generic stream + // (this entry was created during the call to AddDmsTrackGenericPartUtf8Text()) + if ( m_File.Tell() != m_RIP.PairArray.back().ByteOffset ) + { + DefaultLogSink().Error("File offset has moved since RIP modification. Unrecoverable error.\n"); + return RESULT_FAIL; + } + + // create generic stream partition header + static UL GenericStream_DataElement(m_Dict->ul(MDD_GenericStream_DataElement)); + ASDCP::MXF::Partition GSPart(m_Dict); + + GSPart.MajorVersion = m_HeaderPart.MajorVersion; + GSPart.MinorVersion = m_HeaderPart.MinorVersion; + GSPart.ThisPartition = m_RIP.PairArray.back().ByteOffset; + GSPart.PreviousPartition = previous_partition_offset; + GSPart.OperationalPattern = m_HeaderPart.OperationalPattern; + GSPart.BodySID = m_RIP.PairArray.back().BodySID; + GSPart.EssenceContainers = m_HeaderPart.EssenceContainers; + + static UL gs_part_ul(m_Dict->ul(MDD_GenericStreamPartition)); + Result_t result = GSPart.WriteToFile(m_File, gs_part_ul); + + if ( KM_SUCCESS(result) ) + { + result = Write_EKLV_Packet(m_File, *m_Dict, m_HeaderPart, m_Info, m_CtFrameBuf, m_FramesWritten, + m_StreamOffset, frame_buffer, GenericStream_DataElement.Value(), + MXF_BER_LENGTH, enc, hmac); + } + } + + return result; + } + // void Close() { @@ -777,7 +881,7 @@ namespace ASDCP h__ASDCPReader(const Dictionary&); virtual ~h__ASDCPReader(); - Result_t OpenMXFRead(const char* filename); + Result_t OpenMXFRead(const std::string& filename); Result_t ReadEKLVFrame(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf, const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC); Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, @@ -805,6 +909,7 @@ namespace ASDCP Result_t CreateBodyPart(const MXF::Rational& EditRate, ui32_t BytesPerEditUnit = 0); Result_t WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,const byte_t* EssenceUL, + const ui32_t& MinEssenceElementBerLength, AESEncContext* Ctx, HMACContext* HMAC); Result_t WriteASDCPFooter(); };