/*
-Copyright (c) 2004-2006, John Hurst
+Copyright (c) 2004-2012, John Hurst
All rights reserved.
Redistribution and use in source and binary forms, with or without
using namespace ASDCP;
using namespace ASDCP::MXF;
+#ifdef DEFAULT_MD_DECL
+ASDCP::MXF::OPAtomHeader *g_OPAtomHeader;
+ASDCP::MXF::OPAtomIndexFooter *g_OPAtomIndexFooter;
+#else
+extern MXF::OPAtomHeader *g_OPAtomHeader;
+extern MXF::OPAtomIndexFooter *g_OPAtomIndexFooter;
+#endif
namespace ASDCP
{
+ void default_md_object_init();
+
+ //
+ static std::vector<int>
+ version_split(const char* str)
+ {
+ std::vector<int> result;
+ const char* pstr = str;
+ const char* r = strchr(pstr, '.');
+
+ while ( r != 0 )
+ {
+ assert(r >= pstr);
+ if ( r > pstr )
+ result.push_back(atoi(pstr));
+
+ pstr = r + 1;
+ r = strchr(pstr, '.');
+ }
+
+ if( strlen(pstr) > 0 )
+ result.push_back(atoi(pstr));
+
+ assert(result.size() == 3);
+ return result;
+ }
+
// constant values used to calculate KLV and EKLV packet sizes
static const ui32_t klv_cryptinfo_size =
MXF_BER_LENGTH
//
Result_t MD_to_WriterInfo(MXF::Identification*, WriterInfo&);
- Result_t MD_to_CryptoInfo(MXF::CryptographicContext*, 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 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,
+ WriterInfo& Descr, const UL& WrappingUL, const Dictionary*& Dict);
+
+ Result_t Read_EKLV_Packet(Kumu::FileReader& File, const ASDCP::Dictionary& Dict, const MXF::OPAtomHeader& HeaderPart,
+ 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);
+
+ //
+ class KLReader : public ASDCP::KLVPacket
+ {
+ ASDCP_NO_COPY_CONSTRUCT(KLReader);
+ byte_t m_KeyBuf[SMPTE_UL_LENGTH*2];
+
+ public:
+ KLReader() {}
+ ~KLReader() {}
+
+ inline const byte_t* Key() { return m_KeyBuf; }
+ inline const ui64_t Length() { return m_ValueLength; }
+ inline const ui64_t KLLength() { return m_KLLength; }
+
+ Result_t ReadKLFromFile(Kumu::FileReader& Reader);
+ };
+
+ namespace MXF
+ {
+ //---------------------------------------------------------------------------------
+ //
+
+ /// void default_md_object_init();
+
+ template <class HeaderType, class FooterType>
+ class TrackFileReader
+ {
+ KM_NO_COPY_CONSTRUCT(TrackFileReader);
+ TrackFileReader();
+
+ public:
+ const Dictionary* m_Dict;
+ Kumu::FileReader m_File;
+ HeaderType m_HeaderPart;
+ FooterType m_FooterPart;
+ WriterInfo m_Info;
+ ASDCP::FrameBuffer m_CtFrameBuf;
+ Kumu::fpos_t m_LastPosition;
+
+ TrackFileReader(const Dictionary& d) :
+ m_HeaderPart(m_Dict), m_FooterPart(m_Dict), m_Dict(&d)
+ {
+ default_md_object_init();
+ }
+
+ virtual ~TrackFileReader() {
+ Close();
+ }
+
+ Result_t InitInfo()
+ {
+ assert(m_Dict);
+ InterchangeObject* Object;
+
+ // Identification
+ Result_t result = m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(Identification), &Object);
+
+ // Writer Info and SourcePackage
+ if ( KM_SUCCESS(result) )
+ {
+ MD_to_WriterInfo((Identification*)Object, m_Info);
+ result = m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(SourcePackage), &Object);
+ }
+
+ if ( KM_SUCCESS(result) )
+ {
+ SourcePackage* SP = (SourcePackage*)Object;
+ memcpy(m_Info.AssetUUID, SP->PackageUID.Value() + 16, UUIDlen);
+ }
+
+ // optional CryptographicContext
+ if ( KM_SUCCESS(result) )
+ {
+ Result_t cr_result = m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(CryptographicContext), &Object);
+
+ if ( KM_SUCCESS(cr_result) )
+ MD_to_CryptoInfo((CryptographicContext*)Object, m_Info, *m_Dict);
+ }
+
+ return result;
+ }
+
+ //
+ Result_t OpenMXFRead(const char* filename)
+ {
+ m_LastPosition = 0;
+ Result_t result = m_File.OpenRead(filename);
+
+ if ( KM_SUCCESS(result) )
+ result = m_HeaderPart.InitFromFile(m_File);
+
+ return result;
+ }
+
+ // positions file before reading
+ Result_t ReadEKLVFrame(const ASDCP::MXF::Partition& CurrentPartition,
+ 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_FooterPart.Lookup(FrameNum, TmpEntry)) )
+ {
+ DefaultLogSink().Error("Frame value out of range: %u\n", FrameNum);
+ return RESULT_RANGE;
+ }
+
+ // get frame position and go read the frame's key and length
+ Kumu::fpos_t FilePosition = CurrentPartition.BodyOffset + TmpEntry.StreamOffset;
+ Result_t result = RESULT_OK;
+
+ if ( FilePosition != m_LastPosition )
+ {
+ m_LastPosition = FilePosition;
+ result = m_File.Seek(FilePosition);
+ }
+
+ 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,
+ FrameNum, SequenceNum, FrameBuf, EssenceUL, Ctx, HMAC);
+ }
+
+ //
+ void Close() {
+ m_File.Close();
+ }
+ };
+
+ }/// namespace MXF
//
- class h__Reader
+ class h__ASDCPReader : public MXF::TrackFileReader<OPAtomHeader, OPAtomIndexFooter>
{
- ASDCP_NO_COPY_CONSTRUCT(h__Reader);
+ ASDCP_NO_COPY_CONSTRUCT(h__ASDCPReader);
+ h__ASDCPReader();
public:
- Kumu::FileReader m_File;
- OPAtomHeader m_HeaderPart;
- Partition m_BodyPart;
- OPAtomIndexFooter m_FooterPart;
- ui64_t m_EssenceStart;
- WriterInfo m_Info;
- ASDCP::FrameBuffer m_CtFrameBuf;
- Kumu::fpos_t m_LastPosition;
+ Partition m_BodyPart;
- h__Reader();
- virtual ~h__Reader();
+ h__ASDCPReader(const Dictionary&);
+ virtual ~h__ASDCPReader();
- Result_t InitInfo();
Result_t OpenMXFRead(const char* filename);
+ Result_t InitInfo();
Result_t InitMXFIndex();
- Result_t ReadEKLVPacket(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
- const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC);
- void Close();
+ Result_t ReadEKLVFrame(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
+ const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC);
};
inline Result_t Goto_FINAL() { Goto_body(ST_RUNNING, ST_FINAL); }
};
+ typedef std::list<ui64_t*> DurationElementList_t;
+
//
class h__Writer
{
ASDCP_NO_COPY_CONSTRUCT(h__Writer);
+ h__Writer();
public:
+ const Dictionary* m_Dict;
Kumu::FileWriter m_File;
ui32_t m_HeaderSize;
OPAtomHeader m_HeaderPart;
ui64_t m_EssenceStart;
MaterialPackage* m_MaterialPackage;
- Sequence* m_MPTCSequence;
- TimecodeComponent* m_MPTimecode;
- Sequence* m_MPClSequence;
- SourceClip* m_MPClip; //! Material Package SourceClip for each essence stream
-
SourcePackage* m_FilePackage;
- Sequence* m_FPTCSequence;
- TimecodeComponent* m_FPTimecode;
- Sequence* m_FPClSequence;
- SourceClip* m_FPClip; //! File Package SourceClip for each essence stream
FileDescriptor* m_EssenceDescriptor;
+ std::list<InterchangeObject*> m_EssenceSubDescriptorList;
ui32_t m_FramesWritten;
ui64_t m_StreamOffset;
ASDCP::FrameBuffer m_CtFrameBuf;
h__WriterState m_State;
WriterInfo m_Info;
+ DurationElementList_t m_DurationUpdateList;
- h__Writer();
+ h__Writer(const Dictionary&);
virtual ~h__Writer();
+ void InitHeader();
+ void AddSourceClip(const MXF::Rational& EditRate, ui32_t TCFrameRate,
+ const std::string& TrackName, const UL& EssenceUL,
+ const UL& DataDefinition, const std::string& PackageLabel);
+ void AddDMSegment(const MXF::Rational& EditRate, ui32_t TCFrameRate,
+ const std::string& TrackName, const UL& DataDefinition,
+ const std::string& PackageLabel);
+ void AddEssenceDescriptor(const UL& WrappingUL);
+ Result_t CreateBodyPart(const MXF::Rational& EditRate, ui32_t BytesPerEditUnit = 0);
+
+ // all the above for a single source clip
Result_t WriteMXFHeader(const std::string& PackageLabel, const UL& WrappingUL,
- const std::string& TrackName, const UL& DataDefinition,
- const MXF::Rational& EditRate,
+ const std::string& TrackName, const UL& EssenceUL,
+ const UL& DataDefinition, const MXF::Rational& EditRate,
ui32_t TCFrameRate, ui32_t BytesPerEditUnit = 0);
Result_t WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,
~IntegrityPack() {}
- Result_t CalcValues(const ASDCP::FrameBuffer&, byte_t* AssetID, ui32_t sequence, HMACContext* HMAC);
- Result_t TestValues(const ASDCP::FrameBuffer&, byte_t* AssetID, ui32_t sequence, HMACContext* HMAC);
+ Result_t CalcValues(const ASDCP::FrameBuffer&, const byte_t* AssetID, ui32_t sequence, HMACContext* HMAC);
+ Result_t TestValues(const ASDCP::FrameBuffer&, const byte_t* AssetID, ui32_t sequence, HMACContext* HMAC);
};