diff options
| author | jhurst <jhurst@cinecert.com> | 2016-11-22 17:58:19 +0000 |
|---|---|---|
| committer | jhurst <> | 2016-11-22 17:58:19 +0000 |
| commit | 8fd602770d89acb171dbd878d8737ead85aa35d3 (patch) | |
| tree | 229577c9b4389f7e05694a1f4241d0a9160dd461 /src | |
| parent | b3e312cda7ce3e7027f5fb44ef2ffd87d713dd8d (diff) | |
o Added optional Generic Partition to IMF Aux Data prototype, used to carry global metadata
o Added support for 192, 200 and 240 fps images, includes 96, 100 and 120 fpe stereo
o Fixed raw essence detector for IMF Aux Data files
o Added missing MCA properties to MCALabelSubDescriptor (contributed by Ruppel)
o New MXF data type: LineMapPair
o Added default 0,0 VideoLineMap value when wrapping CDCI with as-02-wrap
o Added VideoLineMap property to GenericPictureEssenceDescriptor
o Added timed text unwrap support to as-02-unwrap (contributed by Ruppel)
Diffstat (limited to 'src')
| -rw-r--r-- | src/AS_02.h | 13 | ||||
| -rw-r--r-- | src/AS_02_internal.h | 2 | ||||
| -rwxr-xr-x | src/AS_DCP.h | 3 | ||||
| -rw-r--r-- | src/AS_DCP_ATMOS.cpp | 26 | ||||
| -rw-r--r-- | src/AS_DCP_DCData.cpp | 26 | ||||
| -rwxr-xr-x | src/AS_DCP_JP2K.cpp | 40 | ||||
| -rwxr-xr-x | src/AS_DCP_MXF.cpp | 2 | ||||
| -rwxr-xr-x | src/AS_DCP_PCM.cpp | 8 | ||||
| -rw-r--r-- | src/MDD.cpp | 39 | ||||
| -rwxr-xr-x | src/MDD.h | 14 | ||||
| -rwxr-xr-x | src/MXFTypes.h | 57 | ||||
| -rwxr-xr-x | src/Metadata.cpp | 158 | ||||
| -rwxr-xr-x | src/Metadata.h | 32 | ||||
| -rw-r--r-- | src/TimedText_Parser.cpp | 5 | ||||
| -rwxr-xr-x | src/as-02-unwrap.cpp | 116 | ||||
| -rwxr-xr-x | src/as-02-wrap.cpp | 92 | ||||
| -rwxr-xr-x | src/asdcp-test.cpp | 6 | ||||
| -rwxr-xr-x | src/asdcp-unwrap.cpp | 7 | ||||
| -rwxr-xr-x | src/asdcp-wrap.cpp | 11 | ||||
| -rw-r--r-- | src/h__02_Reader.cpp | 2 |
20 files changed, 611 insertions, 48 deletions
diff --git a/src/AS_02.h b/src/AS_02.h index 69f159b..5d621a7 100644 --- a/src/AS_02.h +++ b/src/AS_02.h @@ -511,8 +511,7 @@ namespace AS_02 // the operation cannot be completed or if nonsensical data is discovered // in the essence descriptor. Result_t OpenWrite(const std::string& filename, const ASDCP::WriterInfo&, - ASDCP::MXF::FileDescriptor* essence_descriptor, - ASDCP::MXF::InterchangeObject_list_t& essence_sub_descriptor_list, + const ASDCP::UL& data_essence_coding, const ASDCP::Rational& edit_rate, const ui32_t& header_size = 16384, const IndexStrategy_t& strategy = IS_FOLLOW, const ui32_t& partition_space = 10); @@ -522,8 +521,11 @@ namespace AS_02 // error occurs. Result_t WriteFrame(const ASDCP::FrameBuffer&, ASDCP::AESEncContext* = 0, ASDCP::HMACContext* = 0); - // Closes the MXF file, writing the index and revised header. + // Closes the MXF file, writing the index and revised header. No global metadata block is written. Result_t Finalize(); + + // Closes the MXF file, writing the global metadata block and then final index and revised header. + Result_t Finalize(const ASDCP::FrameBuffer& global_metadata); }; // @@ -547,6 +549,11 @@ namespace AS_02 // operation cannot be completed. Result_t OpenRead(const std::string& filename) const; + // Open the file for reading. The file must exist. Returns error if the + // operation cannot be completed. If global metadata is available it will + // be placed into the buffer object passed as the second argument. + Result_t OpenRead(const std::string& filename, ASDCP::FrameBuffer& global_metadata) const; + // Returns RESULT_INIT if the file is not open. Result_t Close() const; diff --git a/src/AS_02_internal.h b/src/AS_02_internal.h index bcee7a7..2f96c25 100644 --- a/src/AS_02_internal.h +++ b/src/AS_02_internal.h @@ -63,7 +63,7 @@ namespace AS_02 h__AS02Reader(const ASDCP::Dictionary&); virtual ~h__AS02Reader(); - Result_t OpenMXFRead(const char* filename); + Result_t OpenMXFRead(const std::string& filename); // USE FRAME WRAPPING... Result_t ReadEKLVFrame(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf, diff --git a/src/AS_DCP.h b/src/AS_DCP.h index 75ca97f..b1540aa 100755 --- a/src/AS_DCP.h +++ b/src/AS_DCP.h @@ -302,6 +302,9 @@ namespace ASDCP { const Rational EditRate_96 = Rational(96,1); const Rational EditRate_100 = Rational(100,1); const Rational EditRate_120 = Rational(120,1); + const Rational EditRate_192 = Rational(192,1); + const Rational EditRate_200 = Rational(200,1); + const Rational EditRate_240 = Rational(240,1); // Archival frame rates, see ST 428-21 // These rates are new and not supported by all systems. Do not assume that diff --git a/src/AS_DCP_ATMOS.cpp b/src/AS_DCP_ATMOS.cpp index f53ae71..a016f27 100644 --- a/src/AS_DCP_ATMOS.cpp +++ b/src/AS_DCP_ATMOS.cpp @@ -187,15 +187,18 @@ ASDCP::ATMOS::MXFReader::h__Reader::OpenRead(const std::string& filename) // check for sample/frame rate sanity if ( ASDCP_SUCCESS(result) - && m_DDesc.EditRate != EditRate_24 - && m_DDesc.EditRate != EditRate_25 - && m_DDesc.EditRate != EditRate_30 - && m_DDesc.EditRate != EditRate_48 - && m_DDesc.EditRate != EditRate_50 - && m_DDesc.EditRate != EditRate_60 - && m_DDesc.EditRate != EditRate_96 - && m_DDesc.EditRate != EditRate_100 - && m_DDesc.EditRate != EditRate_120 ) + && m_DDesc.EditRate != EditRate_24 + && m_DDesc.EditRate != EditRate_25 + && m_DDesc.EditRate != EditRate_30 + && m_DDesc.EditRate != EditRate_48 + && m_DDesc.EditRate != EditRate_50 + && m_DDesc.EditRate != EditRate_60 + && m_DDesc.EditRate != EditRate_96 + && m_DDesc.EditRate != EditRate_100 + && m_DDesc.EditRate != EditRate_120 + && m_DDesc.EditRate != EditRate_192 + && m_DDesc.EditRate != EditRate_200 + && m_DDesc.EditRate != EditRate_240 ) { DefaultLogSink().Error("DC Data file EditRate is not a supported value: %d/%d\n", // lu m_DDesc.EditRate.Numerator, m_DDesc.EditRate.Denominator); @@ -503,7 +506,10 @@ ASDCP::ATMOS::MXFWriter::h__Writer::SetSourceStream(ASDCP::DCData::DCDataDescrip && DDesc.EditRate != EditRate_60 && DDesc.EditRate != EditRate_96 && DDesc.EditRate != EditRate_100 - && DDesc.EditRate != EditRate_120 ) + && DDesc.EditRate != EditRate_120 + && DDesc.EditRate != EditRate_192 + && DDesc.EditRate != EditRate_200 + && DDesc.EditRate != EditRate_240 ) { DefaultLogSink().Error("DCDataDescriptor.EditRate is not a supported value: %d/%d\n", DDesc.EditRate.Numerator, DDesc.EditRate.Denominator); diff --git a/src/AS_DCP_DCData.cpp b/src/AS_DCP_DCData.cpp index 208e852..818af2c 100644 --- a/src/AS_DCP_DCData.cpp +++ b/src/AS_DCP_DCData.cpp @@ -157,15 +157,18 @@ ASDCP::DCData::MXFReader::h__Reader::OpenRead(const std::string& filename) // check for sample/frame rate sanity if ( ASDCP_SUCCESS(result) - && m_DDesc.EditRate != EditRate_24 - && m_DDesc.EditRate != EditRate_25 - && m_DDesc.EditRate != EditRate_30 - && m_DDesc.EditRate != EditRate_48 - && m_DDesc.EditRate != EditRate_50 - && m_DDesc.EditRate != EditRate_60 - && m_DDesc.EditRate != EditRate_96 - && m_DDesc.EditRate != EditRate_100 - && m_DDesc.EditRate != EditRate_120 ) + && m_DDesc.EditRate != EditRate_24 + && m_DDesc.EditRate != EditRate_25 + && m_DDesc.EditRate != EditRate_30 + && m_DDesc.EditRate != EditRate_48 + && m_DDesc.EditRate != EditRate_50 + && m_DDesc.EditRate != EditRate_60 + && m_DDesc.EditRate != EditRate_96 + && m_DDesc.EditRate != EditRate_100 + && m_DDesc.EditRate != EditRate_120 + && m_DDesc.EditRate != EditRate_192 + && m_DDesc.EditRate != EditRate_200 + && m_DDesc.EditRate != EditRate_240 ) { DefaultLogSink().Error("DC Data file EditRate is not a supported value: %d/%d\n", // lu m_DDesc.EditRate.Numerator, m_DDesc.EditRate.Denominator); @@ -444,7 +447,10 @@ ASDCP::DCData::MXFWriter::h__Writer::SetSourceStream(DCDataDescriptor const& DDe && DDesc.EditRate != EditRate_60 && DDesc.EditRate != EditRate_96 && DDesc.EditRate != EditRate_100 - && DDesc.EditRate != EditRate_120 ) + && DDesc.EditRate != EditRate_120 + && DDesc.EditRate != EditRate_192 + && DDesc.EditRate != EditRate_200 + && DDesc.EditRate != EditRate_240 ) { DefaultLogSink().Error("DCDataDescriptor.EditRate is not a supported value: %d/%d\n", DDesc.EditRate.Numerator, DDesc.EditRate.Denominator); diff --git a/src/AS_DCP_JP2K.cpp b/src/AS_DCP_JP2K.cpp index acb8f4e..937231f 100755 --- a/src/AS_DCP_JP2K.cpp +++ b/src/AS_DCP_JP2K.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2004-2014, John Hurst +Copyright (c) 2004-2016, John Hurst All rights reserved. Redistribution and use in source and binary forms, with or without @@ -397,7 +397,10 @@ lh__Reader::OpenRead(const std::string& filename, EssenceType_t type) || ( m_EditRate == EditRate_30 && m_SampleRate == EditRate_60 ) || ( m_EditRate == EditRate_48 && m_SampleRate == EditRate_96 ) || ( m_EditRate == EditRate_50 && m_SampleRate == EditRate_100 ) - || ( m_EditRate == EditRate_60 && m_SampleRate == EditRate_120 ) ) + || ( m_EditRate == EditRate_60 && m_SampleRate == EditRate_120 ) + || ( m_EditRate == EditRate_96 && m_SampleRate == EditRate_192 ) + || ( m_EditRate == EditRate_100 && m_SampleRate == EditRate_200 ) + || ( m_EditRate == EditRate_120 && m_SampleRate == EditRate_240 ) ) { DefaultLogSink().Debug("File may contain JPEG Interop stereoscopic images.\n"); return RESULT_SFORMAT; @@ -456,6 +459,30 @@ lh__Reader::OpenRead(const std::string& filename, EssenceType_t type) return RESULT_FORMAT; } } + else if ( m_EditRate == EditRate_96 ) + { + if ( m_SampleRate != EditRate_192 ) + { + DefaultLogSink().Error("EditRate and SampleRate not correct for 96/192 stereoscopic essence.\n"); + return RESULT_FORMAT; + } + } + else if ( m_EditRate == EditRate_100 ) + { + if ( m_SampleRate != EditRate_200 ) + { + DefaultLogSink().Error("EditRate and SampleRate not correct for 100/200 stereoscopic essence.\n"); + return RESULT_FORMAT; + } + } + else if ( m_EditRate == EditRate_120 ) + { + if ( m_SampleRate != EditRate_240 ) + { + DefaultLogSink().Error("EditRate and SampleRate not correct for 120/240 stereoscopic essence.\n"); + return RESULT_FORMAT; + } + } else { DefaultLogSink().Error("EditRate not correct for stereoscopic essence: %d/%d.\n", @@ -1330,6 +1357,15 @@ ASDCP::JP2K::MXFSWriter::OpenWrite(const std::string& filename, const WriterInfo else if ( PDesc.EditRate == ASDCP::EditRate_60 ) TmpPDesc.EditRate = ASDCP::EditRate_120; + else if ( PDesc.EditRate == ASDCP::EditRate_96 ) + TmpPDesc.EditRate = ASDCP::EditRate_192; + + else if ( PDesc.EditRate == ASDCP::EditRate_100 ) + TmpPDesc.EditRate = ASDCP::EditRate_200; + + else if ( PDesc.EditRate == ASDCP::EditRate_120 ) + TmpPDesc.EditRate = ASDCP::EditRate_240; + result = m_Writer->SetSourceStream(TmpPDesc, JP2K_S_PACKAGE_LABEL, PDesc.EditRate); } diff --git a/src/AS_DCP_MXF.cpp b/src/AS_DCP_MXF.cpp index ab400fb..f7f9db3 100755 --- a/src/AS_DCP_MXF.cpp +++ b/src/AS_DCP_MXF.cpp @@ -248,7 +248,7 @@ ASDCP::EssenceType(const std::string& filename, EssenceType_t& type) { type = ESS_AS02_TIMED_TEXT; } - else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(DCDataDescriptor))) ) + else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(IMFDynamicMetadataDescriptor))) ) { type = ESS_DCDATA_UNKNOWN; } diff --git a/src/AS_DCP_PCM.cpp b/src/AS_DCP_PCM.cpp index d905814..6cf1d42 100755 --- a/src/AS_DCP_PCM.cpp +++ b/src/AS_DCP_PCM.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2004-2013, John Hurst +Copyright (c) 2004-2016, John Hurst All rights reserved. Redistribution and use in source and binary forms, with or without @@ -293,6 +293,9 @@ ASDCP::PCM::MXFReader::h__Reader::OpenRead(const std::string& filename) && m_ADesc.EditRate != EditRate_96 && m_ADesc.EditRate != EditRate_100 && m_ADesc.EditRate != EditRate_120 + && m_ADesc.EditRate != EditRate_192 + && m_ADesc.EditRate != EditRate_200 + && m_ADesc.EditRate != EditRate_240 && m_ADesc.EditRate != EditRate_16 && m_ADesc.EditRate != EditRate_18 && m_ADesc.EditRate != EditRate_20 @@ -567,6 +570,9 @@ ASDCP::PCM::MXFWriter::h__Writer::SetSourceStream(const AudioDescriptor& ADesc) && ADesc.EditRate != EditRate_96 && ADesc.EditRate != EditRate_100 && ADesc.EditRate != EditRate_120 + && ADesc.EditRate != EditRate_192 + && ADesc.EditRate != EditRate_200 + && ADesc.EditRate != EditRate_240 && ADesc.EditRate != EditRate_16 && ADesc.EditRate != EditRate_18 && ADesc.EditRate != EditRate_20 diff --git a/src/MDD.cpp b/src/MDD.cpp index 2d6d0d2..d8f3be7 100644 --- a/src/MDD.cpp +++ b/src/MDD.cpp @@ -1198,6 +1198,45 @@ static const ASDCP::MDDEntry s_MDD_Table[] = { 0x0e, 0x09, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00 }, {0}, false, "PrivateDCDataDescriptor" }, + { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x0e, // 384 + 0x01, 0x05, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00 }, + {0}, false, "MCALabelSubDescriptor_MCATitle" }, + { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x0e, // 385 + 0x01, 0x05, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00 }, + {0}, false, "MCALabelSubDescriptor_MCATitleVersion" }, + { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x0e, // 386 + 0x01, 0x05, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00 }, + {0}, false, "MCALabelSubDescriptor_MCATitleSubVersion" }, + { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x0e, // 387 + 0x01, 0x05, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00 }, + {0}, false, "MCALabelSubDescriptor_MCAEpisode" }, + { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x0e, // 388 + 0x01, 0x04, 0x01, 0x05, 0x00, 0x00, 0x00, 0x00 }, + {0}, false, "MCALabelSubDescriptor_MCAPartitionKind" }, + { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x0e, // 389 + 0x01, 0x04, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00 }, + {0}, false, "MCALabelSubDescriptor_MCAPartitionNumber" }, + { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x0e, // 390 + 0x03, 0x02, 0x01, 0x02, 0x20, 0x00, 0x00, 0x00 }, + {0}, false, "MCALabelSubDescriptor_MCAAudioContentKind" }, + { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x0e, // 391 + 0x03, 0x02, 0x01, 0x02, 0x21, 0x00, 0x00, 0x00 }, + {0}, false, "MCALabelSubDescriptor_MCAAudioElementKind" }, + + // protype for generic aux data (IMF) + { { 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x05, // 392 + 0x0e, 0x09, 0x06, 0x07, 0x01, 0x01, 0x10, 0x00 }, + {0}, false, "IMFDynamicMetadataWrappingFrame" }, + { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x02, 0x01, 0x05, // 393 + 0x0e, 0x09, 0x06, 0x07, 0x01, 0x01, 0x11, 0x00 }, + {0}, false, "IMFDynamicMetadataEssence" }, + { { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x53, 0x01, 0x05, // 394 + 0x0e, 0x09, 0x06, 0x07, 0x01, 0x01, 0x12, 0x00 }, + {0}, false, "IMFDynamicMetadataDescriptor" }, + { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x05, // 395 + 0x0e, 0x09, 0x06, 0x07, 0x01, 0x01, 0x13, 0x00 }, + {0}, false, "IMFDynamicMetadataDescriptor_GlobalPayloadSID" }, + { {0}, {0}, false, 0 } }; @@ -419,6 +419,20 @@ namespace ASDCP { MDD_PrivateDCDataWrappingFrame, // 381 MDD_PrivateDCDataEssence, // 382 MDD_PrivateDCDataDescriptor, // 383 + + MDD_MCALabelSubDescriptor_MCATitle, // 384 + MDD_MCALabelSubDescriptor_MCATitleVersion, // 385 + MDD_MCALabelSubDescriptor_MCATitleSubVersion, // 386 + MDD_MCALabelSubDescriptor_MCAEpisode, // 387 + MDD_MCALabelSubDescriptor_MCAPartitionKind, // 388 + MDD_MCALabelSubDescriptor_MCAPartitionNumber, // 389 + MDD_MCALabelSubDescriptor_MCAAudioContentKind, // 390 + MDD_MCALabelSubDescriptor_MCAAudioElementKind, // 391 + + MDD_IMFDynamicMetadataWrappingFrame, // 392 + MDD_IMFDynamicMetadataEssence, // 393 + MDD_IMFDynamicMetadataDescriptor, // 394 + MDD_IMFDynamicMetadataDescriptor_GlobalPayloadSID, // 395 MDD_Max }; // enum MDD_t diff --git a/src/MXFTypes.h b/src/MXFTypes.h index 3bfa03d..48dbf3f 100755 --- a/src/MXFTypes.h +++ b/src/MXFTypes.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2005-2015, John Hurst +Copyright (c) 2005-2016, John Hurst All rights reserved. Redistribution and use in source and binary forms, with or without @@ -353,6 +353,61 @@ namespace ASDCP }; // + class LineMapPair : public Kumu::IArchive + { + public: + ui32_t First; + ui32_t Second; + + LineMapPair() {} + ~LineMapPair() {} + + LineMapPair(const ui32_t& first, const ui32_t& second) : IArchive() { + First = first; + Second = second; + } + + LineMapPair(const LineMapPair& rhs) : IArchive() { + First = rhs.First; + Second = rhs.Second; + } + + const LineMapPair& operator=(const LineMapPair& rhs) { + First = rhs.First; + Second = rhs.Second; + return *this; + } + + // + inline const char* EncodeString(char* str_buf, ui32_t buf_len) const { + snprintf(str_buf, buf_len, "%d,%d", First, Second); + return str_buf; + } + + inline virtual bool Unarchive(Kumu::MemIOReader* Reader) { + ui32_t n; + if ( ! Reader->ReadUi32BE(&n) ) return false; + if ( n != 4 ) return false; + if ( ! Reader->ReadUi32BE(&n) ) return false; + if ( n != 2 ) return false; + if ( ! Reader->ReadUi32BE((ui32_t*)&First) ) return false; + if ( ! Reader->ReadUi32BE((ui32_t*)&Second) ) return false; + return true; + } + + inline virtual bool HasValue() const { return true; } + inline virtual ui32_t ArchiveLength() const { return sizeof(ui32_t)*4; } + + inline virtual bool Archive(Kumu::MemIOWriter* Writer) const { + if ( ! Writer->WriteUi32BE(4UL) ) return false; + if ( ! Writer->WriteUi32BE(2UL) ) return false; + if ( ! Writer->WriteUi32BE((ui32_t)First) ) return false; + if ( ! Writer->WriteUi32BE((ui32_t)Second) ) return false; + return true; + } + }; + + // class VersionType : public Kumu::IArchive { public: diff --git a/src/Metadata.cpp b/src/Metadata.cpp index 72136d7..8662cfd 100755 --- a/src/Metadata.cpp +++ b/src/Metadata.cpp @@ -78,6 +78,7 @@ static InterchangeObject* DCDataDescriptor_Factory(const Dictionary*& Dict) { re static InterchangeObject* PrivateDCDataDescriptor_Factory(const Dictionary*& Dict) { return new PrivateDCDataDescriptor(Dict); } static InterchangeObject* DolbyAtmosSubDescriptor_Factory(const Dictionary*& Dict) { return new DolbyAtmosSubDescriptor(Dict); } static InterchangeObject* PHDRMetadataTrackSubDescriptor_Factory(const Dictionary*& Dict) { return new PHDRMetadataTrackSubDescriptor(Dict); } +static InterchangeObject* IMFDynamicMetadataDescriptor_Factory(const Dictionary*& Dict) { return new IMFDynamicMetadataDescriptor(Dict); } void @@ -122,6 +123,7 @@ ASDCP::MXF::Metadata_InitTypes(const Dictionary*& Dict) SetObjectFactory(Dict->ul(MDD_PrivateDCDataDescriptor), PrivateDCDataDescriptor_Factory); SetObjectFactory(Dict->ul(MDD_DolbyAtmosSubDescriptor), DolbyAtmosSubDescriptor_Factory); SetObjectFactory(Dict->ul(MDD_PHDRMetadataTrackSubDescriptor), PHDRMetadataTrackSubDescriptor_Factory); + SetObjectFactory(Dict->ul(MDD_IMFDynamicMetadataDescriptor), IMFDynamicMetadataDescriptor_Factory); } //------------------------------------------------------------------------------------------ @@ -1704,6 +1706,10 @@ GenericPictureEssenceDescriptor::InitFromTLVSet(TLVReader& TLVSet) result = TLVSet.ReadUi32(OBJ_READ_ARGS_OPT(GenericPictureEssenceDescriptor, ActiveYOffset)); ActiveYOffset.set_has_value( result == RESULT_OK ); } + if ( ASDCP_SUCCESS(result) ) { + result = TLVSet.ReadObject(OBJ_READ_ARGS_OPT(GenericPictureEssenceDescriptor, VideoLineMap)); + VideoLineMap.set_has_value( result == RESULT_OK ); + } return result; } @@ -1743,6 +1749,7 @@ GenericPictureEssenceDescriptor::WriteToTLVSet(TLVWriter& TLVSet) if ( ASDCP_SUCCESS(result) && ! ActiveHeight.empty() ) result = TLVSet.WriteUi32(OBJ_WRITE_ARGS_OPT(GenericPictureEssenceDescriptor, ActiveHeight)); if ( ASDCP_SUCCESS(result) && ! ActiveXOffset.empty() ) result = TLVSet.WriteUi32(OBJ_WRITE_ARGS_OPT(GenericPictureEssenceDescriptor, ActiveXOffset)); if ( ASDCP_SUCCESS(result) && ! ActiveYOffset.empty() ) result = TLVSet.WriteUi32(OBJ_WRITE_ARGS_OPT(GenericPictureEssenceDescriptor, ActiveYOffset)); + if ( ASDCP_SUCCESS(result) && ! VideoLineMap.empty() ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS_OPT(GenericPictureEssenceDescriptor, VideoLineMap)); return result; } @@ -1781,6 +1788,7 @@ GenericPictureEssenceDescriptor::Copy(const GenericPictureEssenceDescriptor& rhs ActiveHeight = rhs.ActiveHeight; ActiveXOffset = rhs.ActiveXOffset; ActiveYOffset = rhs.ActiveYOffset; + VideoLineMap = rhs.VideoLineMap; } // @@ -1875,6 +1883,9 @@ GenericPictureEssenceDescriptor::Dump(FILE* stream) if ( ! ActiveYOffset.empty() ) { fprintf(stream, " %22s = %d\n", "ActiveYOffset", ActiveYOffset.get()); } + if ( ! VideoLineMap.empty() ) { + fprintf(stream, " %22s = %s\n", "VideoLineMap", VideoLineMap.get().EncodeString(identbuf, IdentBufferLen)); + } } // @@ -3230,6 +3241,38 @@ MCALabelSubDescriptor::InitFromTLVSet(TLVReader& TLVSet) result = TLVSet.ReadObject(OBJ_READ_ARGS_OPT(MCALabelSubDescriptor, RFC5646SpokenLanguage)); RFC5646SpokenLanguage.set_has_value( result == RESULT_OK ); } + if ( ASDCP_SUCCESS(result) ) { + result = TLVSet.ReadObject(OBJ_READ_ARGS_OPT(MCALabelSubDescriptor, MCATitle)); + MCATitle.set_has_value( result == RESULT_OK ); + } + if ( ASDCP_SUCCESS(result) ) { + result = TLVSet.ReadObject(OBJ_READ_ARGS_OPT(MCALabelSubDescriptor, MCATitleVersion)); + MCATitleVersion.set_has_value( result == RESULT_OK ); + } + if ( ASDCP_SUCCESS(result) ) { + result = TLVSet.ReadObject(OBJ_READ_ARGS_OPT(MCALabelSubDescriptor, MCATitleSubVersion)); + MCATitleSubVersion.set_has_value( result == RESULT_OK ); + } + if ( ASDCP_SUCCESS(result) ) { + result = TLVSet.ReadObject(OBJ_READ_ARGS_OPT(MCALabelSubDescriptor, MCAEpisode)); + MCAEpisode.set_has_value( result == RESULT_OK ); + } + if ( ASDCP_SUCCESS(result) ) { + result = TLVSet.ReadObject(OBJ_READ_ARGS_OPT(MCALabelSubDescriptor, MCAPartitionKind)); + MCAPartitionKind.set_has_value( result == RESULT_OK ); + } + if ( ASDCP_SUCCESS(result) ) { + result = TLVSet.ReadObject(OBJ_READ_ARGS_OPT(MCALabelSubDescriptor, MCAPartitionNumber)); + MCAPartitionNumber.set_has_value( result == RESULT_OK ); + } + if ( ASDCP_SUCCESS(result) ) { + result = TLVSet.ReadObject(OBJ_READ_ARGS_OPT(MCALabelSubDescriptor, MCAAudioContentKind)); + MCAAudioContentKind.set_has_value( result == RESULT_OK ); + } + if ( ASDCP_SUCCESS(result) ) { + result = TLVSet.ReadObject(OBJ_READ_ARGS_OPT(MCALabelSubDescriptor, MCAAudioElementKind)); + MCAAudioElementKind.set_has_value( result == RESULT_OK ); + } return result; } @@ -3245,6 +3288,14 @@ MCALabelSubDescriptor::WriteToTLVSet(TLVWriter& TLVSet) if ( ASDCP_SUCCESS(result) && ! MCATagName.empty() ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS_OPT(MCALabelSubDescriptor, MCATagName)); if ( ASDCP_SUCCESS(result) && ! MCAChannelID.empty() ) result = TLVSet.WriteUi32(OBJ_WRITE_ARGS_OPT(MCALabelSubDescriptor, MCAChannelID)); if ( ASDCP_SUCCESS(result) && ! RFC5646SpokenLanguage.empty() ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS_OPT(MCALabelSubDescriptor, RFC5646SpokenLanguage)); + if ( ASDCP_SUCCESS(result) && ! MCATitle.empty() ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS_OPT(MCALabelSubDescriptor, MCATitle)); + if ( ASDCP_SUCCESS(result) && ! MCATitleVersion.empty() ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS_OPT(MCALabelSubDescriptor, MCATitleVersion)); + if ( ASDCP_SUCCESS(result) && ! MCATitleSubVersion.empty() ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS_OPT(MCALabelSubDescriptor, MCATitleSubVersion)); + if ( ASDCP_SUCCESS(result) && ! MCAEpisode.empty() ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS_OPT(MCALabelSubDescriptor, MCAEpisode)); + if ( ASDCP_SUCCESS(result) && ! MCAPartitionKind.empty() ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS_OPT(MCALabelSubDescriptor, MCAPartitionKind)); + if ( ASDCP_SUCCESS(result) && ! MCAPartitionNumber.empty() ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS_OPT(MCALabelSubDescriptor, MCAPartitionNumber)); + if ( ASDCP_SUCCESS(result) && ! MCAAudioContentKind.empty() ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS_OPT(MCALabelSubDescriptor, MCAAudioContentKind)); + if ( ASDCP_SUCCESS(result) && ! MCAAudioElementKind.empty() ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS_OPT(MCALabelSubDescriptor, MCAAudioElementKind)); return result; } @@ -3259,6 +3310,14 @@ MCALabelSubDescriptor::Copy(const MCALabelSubDescriptor& rhs) MCATagName = rhs.MCATagName; MCAChannelID = rhs.MCAChannelID; RFC5646SpokenLanguage = rhs.RFC5646SpokenLanguage; + MCATitle = rhs.MCATitle; + MCATitleVersion = rhs.MCATitleVersion; + MCATitleSubVersion = rhs.MCATitleSubVersion; + MCAEpisode = rhs.MCAEpisode; + MCAPartitionKind = rhs.MCAPartitionKind; + MCAPartitionNumber = rhs.MCAPartitionNumber; + MCAAudioContentKind = rhs.MCAAudioContentKind; + MCAAudioElementKind = rhs.MCAAudioElementKind; } // @@ -3284,6 +3343,30 @@ MCALabelSubDescriptor::Dump(FILE* stream) if ( ! RFC5646SpokenLanguage.empty() ) { fprintf(stream, " %22s = %s\n", "RFC5646SpokenLanguage", RFC5646SpokenLanguage.get().EncodeString(identbuf, IdentBufferLen)); } + if ( ! MCATitle.empty() ) { + fprintf(stream, " %22s = %s\n", "MCATitle", MCATitle.get().EncodeString(identbuf, IdentBufferLen)); + } + if ( ! MCATitleVersion.empty() ) { + fprintf(stream, " %22s = %s\n", "MCATitleVersion", MCATitleVersion.get().EncodeString(identbuf, IdentBufferLen)); + } + if ( ! MCATitleSubVersion.empty() ) { + fprintf(stream, " %22s = %s\n", "MCATitleSubVersion", MCATitleSubVersion.get().EncodeString(identbuf, IdentBufferLen)); + } + if ( ! MCAEpisode.empty() ) { + fprintf(stream, " %22s = %s\n", "MCAEpisode", MCAEpisode.get().EncodeString(identbuf, IdentBufferLen)); + } + if ( ! MCAPartitionKind.empty() ) { + fprintf(stream, " %22s = %s\n", "MCAPartitionKind", MCAPartitionKind.get().EncodeString(identbuf, IdentBufferLen)); + } + if ( ! MCAPartitionNumber.empty() ) { + fprintf(stream, " %22s = %s\n", "MCAPartitionNumber", MCAPartitionNumber.get().EncodeString(identbuf, IdentBufferLen)); + } + if ( ! MCAAudioContentKind.empty() ) { + fprintf(stream, " %22s = %s\n", "MCAAudioContentKind", MCAAudioContentKind.get().EncodeString(identbuf, IdentBufferLen)); + } + if ( ! MCAAudioElementKind.empty() ) { + fprintf(stream, " %22s = %s\n", "MCAAudioElementKind", MCAAudioElementKind.get().EncodeString(identbuf, IdentBufferLen)); + } } // @@ -3847,6 +3930,81 @@ PHDRMetadataTrackSubDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer) return InterchangeObject::WriteToBuffer(Buffer); } +//------------------------------------------------------------------------------------------ +// IMFDynamicMetadataDescriptor + +// + +IMFDynamicMetadataDescriptor::IMFDynamicMetadataDescriptor(const Dictionary*& d) : GenericDataEssenceDescriptor(d), m_Dict(d), GlobalPayloadSID(0) +{ + assert(m_Dict); + m_UL = m_Dict->ul(MDD_IMFDynamicMetadataDescriptor); +} + +IMFDynamicMetadataDescriptor::IMFDynamicMetadataDescriptor(const IMFDynamicMetadataDescriptor& rhs) : GenericDataEssenceDescriptor(rhs.m_Dict), m_Dict(rhs.m_Dict) +{ + assert(m_Dict); + m_UL = m_Dict->ul(MDD_IMFDynamicMetadataDescriptor); + Copy(rhs); +} + + +// +ASDCP::Result_t +IMFDynamicMetadataDescriptor::InitFromTLVSet(TLVReader& TLVSet) +{ + assert(m_Dict); + Result_t result = GenericDataEssenceDescriptor::InitFromTLVSet(TLVSet); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadUi32(OBJ_READ_ARGS(IMFDynamicMetadataDescriptor, GlobalPayloadSID)); + return result; +} + +// +ASDCP::Result_t +IMFDynamicMetadataDescriptor::WriteToTLVSet(TLVWriter& TLVSet) +{ + assert(m_Dict); + Result_t result = GenericDataEssenceDescriptor::WriteToTLVSet(TLVSet); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteUi32(OBJ_WRITE_ARGS(IMFDynamicMetadataDescriptor, GlobalPayloadSID)); + return result; +} + +// +void +IMFDynamicMetadataDescriptor::Copy(const IMFDynamicMetadataDescriptor& rhs) +{ + GenericDataEssenceDescriptor::Copy(rhs); + GlobalPayloadSID = rhs.GlobalPayloadSID; +} + +// +void +IMFDynamicMetadataDescriptor::Dump(FILE* stream) +{ + char identbuf[IdentBufferLen]; + *identbuf = 0; + + if ( stream == 0 ) + stream = stderr; + + GenericDataEssenceDescriptor::Dump(stream); + fprintf(stream, " %22s = %d\n", "GlobalPayloadSID", GlobalPayloadSID); +} + +// +ASDCP::Result_t +IMFDynamicMetadataDescriptor::InitFromBuffer(const byte_t* p, ui32_t l) +{ + return InterchangeObject::InitFromBuffer(p, l); +} + +// +ASDCP::Result_t +IMFDynamicMetadataDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer) +{ + return InterchangeObject::WriteToBuffer(Buffer); +} + // // end Metadata.cpp // diff --git a/src/Metadata.h b/src/Metadata.h index e71ddf2..e5133e8 100755 --- a/src/Metadata.h +++ b/src/Metadata.h @@ -502,6 +502,7 @@ namespace ASDCP optional_property<ui32_t > ActiveHeight; optional_property<ui32_t > ActiveXOffset; optional_property<ui32_t > ActiveYOffset; + optional_property<LineMapPair > VideoLineMap; GenericPictureEssenceDescriptor(const Dictionary*& d); GenericPictureEssenceDescriptor(const GenericPictureEssenceDescriptor& rhs); @@ -875,6 +876,14 @@ namespace ASDCP optional_property<UTF16String > MCATagName; optional_property<ui32_t > MCAChannelID; optional_property<ISO8String > RFC5646SpokenLanguage; + optional_property<UTF16String > MCATitle; + optional_property<UTF16String > MCATitleVersion; + optional_property<UTF16String > MCATitleSubVersion; + optional_property<UTF16String > MCAEpisode; + optional_property<UTF16String > MCAPartitionKind; + optional_property<UTF16String > MCAPartitionNumber; + optional_property<UTF16String > MCAAudioContentKind; + optional_property<UTF16String > MCAAudioElementKind; MCALabelSubDescriptor(const Dictionary*& d); MCALabelSubDescriptor(const MCALabelSubDescriptor& rhs); @@ -1054,6 +1063,29 @@ namespace ASDCP virtual Result_t WriteToBuffer(ASDCP::FrameBuffer&); }; + // + class IMFDynamicMetadataDescriptor : public GenericDataEssenceDescriptor + { + IMFDynamicMetadataDescriptor(); + + public: + const Dictionary*& m_Dict; + ui32_t GlobalPayloadSID; + + IMFDynamicMetadataDescriptor(const Dictionary*& d); + IMFDynamicMetadataDescriptor(const IMFDynamicMetadataDescriptor& rhs); + virtual ~IMFDynamicMetadataDescriptor() {} + + const IMFDynamicMetadataDescriptor& operator=(const IMFDynamicMetadataDescriptor& rhs) { Copy(rhs); return *this; } + virtual void Copy(const IMFDynamicMetadataDescriptor& rhs); + virtual const char* HasName() { return "IMFDynamicMetadataDescriptor"; } + virtual Result_t InitFromTLVSet(TLVReader& TLVSet); + virtual Result_t WriteToTLVSet(TLVWriter& TLVSet); + virtual void Dump(FILE* = 0); + virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l); + virtual Result_t WriteToBuffer(ASDCP::FrameBuffer&); + }; + } // namespace MXF } // namespace ASDCP diff --git a/src/TimedText_Parser.cpp b/src/TimedText_Parser.cpp index 5aeacf1..22d37bb 100644 --- a/src/TimedText_Parser.cpp +++ b/src/TimedText_Parser.cpp @@ -249,7 +249,10 @@ ASDCP::TimedText::DCSubtitleParser::h__SubtitleParser::OpenRead() && m_TDesc.EditRate != EditRate_60 && m_TDesc.EditRate != EditRate_96 && m_TDesc.EditRate != EditRate_100 - && m_TDesc.EditRate != EditRate_120 ) + && m_TDesc.EditRate != EditRate_120 + && m_TDesc.EditRate != EditRate_192 + && m_TDesc.EditRate != EditRate_200 + && m_TDesc.EditRate != EditRate_240 ) { DefaultLogSink(). Error("Unexpected EditRate: %d/%d\n", m_TDesc.EditRate.Numerator, m_TDesc.EditRate.Denominator); diff --git a/src/as-02-unwrap.cpp b/src/as-02-unwrap.cpp index 1f40050..3c100b9 100755 --- a/src/as-02-unwrap.cpp +++ b/src/as-02-unwrap.cpp @@ -99,6 +99,7 @@ Options:\n\ -d <duration> - Number of frames to process, default all\n\ -e <extension> - Extension to use for aux data files. default \"bin\"\n\ -f <start-frame> - Starting frame number, default 0\n\ + -g <filename> - Extract global metadata to the named file.\n\ -h | -help - Show help\n\ -k <key-string> - Use key for ciphertext operations\n\ -m - verify HMAC values when reading\n\ @@ -146,7 +147,7 @@ public: PCM::ChannelFormat_t channel_fmt; // audio channel arrangement const char* input_filename; const char* extension; - std::string prefix_buffer; + std::string global_metadata_filename, prefix_buffer; // CommandOptions(int argc, const char** argv) : @@ -203,6 +204,11 @@ public: start_frame = Kumu::xabs(strtol(argv[i], 0, 10)); break; + case 'g': + TEST_EXTRA_ARG(i, 'g'); + global_metadata_filename = argv[i]; + break; + case 'h': help_flag = true; break; case 'm': read_hmac = true; break; @@ -586,6 +592,87 @@ read_PCM_file(CommandOptions& Options) } +//------------------------------------------------------------------------------------------ +// TimedText essence + +// Read one or more timed text streams from a plaintext AS-02 file +// +Result_t +read_timed_text_file(CommandOptions& Options) +{ + AESDecContext* Context = 0; + HMACContext* HMAC = 0; + AS_02::TimedText::MXFReader Reader; + TimedText::FrameBuffer FrameBuffer(Options.fb_size); + //ASDCP::TimedText::FrameBuffer FrameBuffer(Options.fb_size); + AS_02::TimedText::TimedTextDescriptor TDesc; + ASDCP::MXF::TimedTextDescriptor *tt_descriptor = 0; + + Result_t result = Reader.OpenRead(Options.input_filename); + + if ( ASDCP_SUCCESS(result) ) + { + result = Reader.OP1aHeader().GetMDObjectByType(DefaultCompositeDict().ul(MDD_TimedTextDescriptor), + reinterpret_cast<MXF::InterchangeObject**>(&tt_descriptor)); + if ( Options.verbose_flag ) { + tt_descriptor->Dump(); + } + + + if ( ASDCP_FAILURE(result) ) + return result; + + std::string XMLDoc; + std::string out_path = Kumu::PathDirname(Options.file_prefix); + ui32_t write_count; + char buf[64]; + TimedText::ResourceList_t::const_iterator ri; + + result = Reader.ReadTimedTextResource(XMLDoc); + + if ( ASDCP_SUCCESS(result) ) + { + Reader.FillTimedTextDescriptor(TDesc); + FrameBuffer.Capacity(Options.fb_size); + + if ( Options.verbose_flag ) + TimedText::DescriptorDump(TDesc); + } + + if ( ASDCP_SUCCESS(result) && ( ! Options.no_write_flag ) ) + { + Kumu::FileWriter Writer; + result = Writer.OpenWrite(Options.file_prefix); + + if ( ASDCP_SUCCESS(result) ) + result = Writer.Write(reinterpret_cast<const byte_t*>(XMLDoc.c_str()), XMLDoc.size(), &write_count); + } + + for ( ri = TDesc.ResourceList.begin() ; ri != TDesc.ResourceList.end() && ASDCP_SUCCESS(result); ri++ ) + { + result = Reader.ReadAncillaryResource(ri->ResourceID, FrameBuffer, Context, HMAC); + + if ( ASDCP_SUCCESS(result) && ( ! Options.no_write_flag ) ) + { + Kumu::FileWriter Writer; + if (out_path != "") { + result = Writer.OpenWrite(Kumu::PathJoin(out_path, Kumu::UUID(ri->ResourceID).EncodeHex(buf, 64)).c_str()); + } else { + // Workaround for a bug in Kumu::PathJoin + result = Writer.OpenWrite(Kumu::UUID(ri->ResourceID).EncodeHex(buf, 64)); + } + + if ( ASDCP_SUCCESS(result) ) + result = Writer.Write(FrameBuffer.RoData(), FrameBuffer.Size(), &write_count); + + if ( Options.verbose_flag ) + FrameBuffer.Dump(stderr, Options.fb_dump_size); + } + } + } + return result; +} + // Read one or more plaintext DCData bytestreams from a plaintext ASDCP file // Read one or more plaintext DCData bytestreams from a ciphertext ASDCP file // Read one or more ciphertext DCData byestreams from a ciphertext ASDCP file @@ -599,7 +686,28 @@ read_aux_data_file(CommandOptions& Options) DCData::FrameBuffer FrameBuffer(Options.fb_size); ui32_t frame_count = 0; - Result_t result = Reader.OpenRead(Options.input_filename); + ASDCP::FrameBuffer global_metadata; + Result_t result = Reader.OpenRead(Options.input_filename, global_metadata); + + if ( ASDCP_SUCCESS(result) + && global_metadata.Size() + && ! Options.global_metadata_filename.empty() ) + { + ui32_t write_count = 0; + Kumu::FileWriter Writer; + + result = Writer.OpenWrite(Options.global_metadata_filename); + + if ( ASDCP_SUCCESS(result) ) + { + result = Writer.Write(global_metadata.RoData(), global_metadata.Size(), &write_count); + } + + if ( ASDCP_SUCCESS(result) && global_metadata.Size() != write_count) + { + return RESULT_WRITEFAIL; + } + } if ( ASDCP_SUCCESS(result) ) { @@ -705,6 +813,10 @@ main(int argc, const char** argv) result = read_PCM_file(Options); break; + case ESS_AS02_TIMED_TEXT: + result = read_timed_text_file(Options); + break; + case ESS_DCDATA_UNKNOWN: result = read_aux_data_file(Options); break; diff --git a/src/as-02-wrap.cpp b/src/as-02-wrap.cpp index 2e33a99..794f2be 100755 --- a/src/as-02-wrap.cpp +++ b/src/as-02-wrap.cpp @@ -141,9 +141,13 @@ Options:\n\ -e - Encrypt JP2K headers (default)\n\ -E - Do not encrypt JP2K headers\n\ -F (0|1) - Set field dominance for interlaced image (default: 0)\n\ + -g <filename> - Write global metadata from the named file.\n\ -i - Indicates input essence is interlaced fields (forces -Y)\n\ -j <key-id-str> - Write key ID instead of creating a random value\n\ -k <key-string> - Use key for ciphertext operations\n\ + -l <first>,<second>\n\ + - Integer values that set the VideoLineMap when creating\n\ + interlaced YCbCr files\n\ -M - Do not create HMAC values when writing\n\ -m <expr> - Write MCA labels using <expr>. Example:\n\ 51(L,R,C,LFE,Ls,Rs,),HI,VIN\n\ @@ -199,7 +203,7 @@ public: bool key_id_flag; // true if a key ID was given byte_t key_id_value[UUIDlen];// value of given key ID (when key_id_flag is true) byte_t asset_id_value[UUIDlen];// value of asset ID (when asset_id_flag is true) - std::string out_file; // + std::string global_metadata_filename, out_file; // bool show_ul_values_flag; /// if true, dump the UL table before going tp work. Kumu::PathList_t filenames; // list of filenames to be processed @@ -227,6 +231,23 @@ public: // UL aux_data_coding; + MXF::LineMapPair line_map; + + // + bool set_video_line_map(const std::string& arg) + { + const char* sep_str = strrchr(arg.c_str(), ','); + + if ( sep_str == 0 ) + { + fprintf(stderr, "Expecting <first>,<second>\n"); + return false; + } + + line_map.First = Kumu::xabs(strtol(arg.c_str(), 0, 10)); + line_map.Second = Kumu::xabs(strtol(sep_str+1, 0, 10)); + return true; + } // bool set_video_ref(const std::string& arg) @@ -269,7 +290,8 @@ public: mca_config(g_dict), rgba_MaxRef(1023), rgba_MinRef(0), horizontal_subsampling(2), vertical_subsampling(2), component_depth(10), frame_layout(0), aspect_ratio(ASDCP::Rational(4,3)), field_dominance(0), - mxf_header_size(16384), cdci_WhiteRefLevel(940), cdci_BlackRefLevel(64), cdci_ColorRange(897) + mxf_header_size(16384), cdci_WhiteRefLevel(940), cdci_BlackRefLevel(64), cdci_ColorRange(897), + line_map(0,0) { memset(key_value, 0, KeyLen); memset(key_id_value, 0, UUIDlen); @@ -353,6 +375,11 @@ public: } break; + case 'g': + TEST_EXTRA_ARG(i, 'g'); + global_metadata_filename = argv[i]; + break; + case 'h': help_flag = true; break; case 'i': @@ -389,6 +416,14 @@ public: } break; + case 'l': + TEST_EXTRA_ARG(i, 'y'); + if ( ! set_video_line_map(argv[i]) ) + { + return; + } + break; + case 'M': write_hmac = false; break; case 'm': @@ -589,6 +624,7 @@ write_JP2K_file(CommandOptions& Options) tmp_dscr->WhiteReflevel = Options.cdci_WhiteRefLevel; tmp_dscr->BlackRefLevel = Options.cdci_BlackRefLevel; tmp_dscr->ColorRange = Options.cdci_ColorRange; + tmp_dscr->VideoLineMap = Options.line_map; essence_descriptor = static_cast<ASDCP::MXF::FileDescriptor*>(tmp_dscr); } } @@ -987,6 +1023,15 @@ write_aux_data_file(CommandOptions& Options) byte_t IV_buf[CBC_BLOCK_SIZE]; Kumu::FortunaRNG RNG; + if ( ! Options.global_metadata_filename.empty() ) + { + if ( ! Kumu::PathIsFile(Options.global_metadata_filename) ) + { + fprintf(stderr, "No such file or filename: \"%s\".\n", Options.global_metadata_filename.c_str()); + return RESULT_PARAM; + } + } + // set up essence parser Result_t result = Parser.OpenRead(Options.filenames.front()); @@ -1042,14 +1087,7 @@ write_aux_data_file(CommandOptions& Options) if ( ASDCP_SUCCESS(result) ) { - ASDCP::MXF::InterchangeObject_list_t essence_sub_descriptor_list; // empty for now - ASDCP::MXF::DCDataDescriptor *essence_descriptor = new ASDCP::MXF::DCDataDescriptor(g_dict); - essence_descriptor->SampleRate = Options.edit_rate; - essence_descriptor->ContainerDuration = 0; - essence_descriptor->DataEssenceCoding = Options.aux_data_coding; - - result = Writer.OpenWrite(Options.out_file, Info, essence_descriptor, - essence_sub_descriptor_list, Options.edit_rate); + result = Writer.OpenWrite(Options.out_file, Info, Options.aux_data_coding, Options.edit_rate); } } @@ -1089,7 +1127,39 @@ write_aux_data_file(CommandOptions& Options) } if ( ASDCP_SUCCESS(result) && ! Options.no_write_flag ) - result = Writer.Finalize(); + { + if ( Options.global_metadata_filename.empty() ) + { + result = Writer.Finalize(); + } + else + { + ASDCP::FrameBuffer global_metadata; + ui32_t file_size = Kumu::FileSize(Options.global_metadata_filename); + result = global_metadata.Capacity(file_size); + + if ( ASDCP_SUCCESS(result) ) + { + ui32_t read_count = 0; + Kumu::FileReader Reader; + + result = Reader.OpenRead(Options.global_metadata_filename); + + if ( ASDCP_SUCCESS(result) ) + result = Reader.Read(global_metadata.Data(), file_size, &read_count); + + if ( ASDCP_SUCCESS(result) ) + { + if ( file_size != read_count) + return RESULT_READFAIL; + + global_metadata.Size(read_count); + } + } + + result = Writer.Finalize(global_metadata); + } + } return result; } diff --git a/src/asdcp-test.cpp b/src/asdcp-test.cpp index 1b491b0..df108c3 100755 --- a/src/asdcp-test.cpp +++ b/src/asdcp-test.cpp @@ -306,6 +306,9 @@ public: if ( picture_rate == 96 ) return EditRate_96; if ( picture_rate == 100 ) return EditRate_100; if ( picture_rate == 120 ) return EditRate_120; + if ( picture_rate == 192 ) return EditRate_192; + if ( picture_rate == 200 ) return EditRate_200; + if ( picture_rate == 240 ) return EditRate_240; return EditRate_24; } @@ -326,6 +329,9 @@ public: if ( picture_rate == 96 ) return "96"; if ( picture_rate == 100 ) return "100"; if ( picture_rate == 120 ) return "120"; + if ( picture_rate == 192 ) return "192"; + if ( picture_rate == 200 ) return "200"; + if ( picture_rate == 240 ) return "240"; return "24"; } diff --git a/src/asdcp-unwrap.cpp b/src/asdcp-unwrap.cpp index 3a8bdd0..a24219f 100755 --- a/src/asdcp-unwrap.cpp +++ b/src/asdcp-unwrap.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2003-2014, John Hurst +Copyright (c) 2003-2016, John Hurst All rights reserved. Redistribution and use in source and binary forms, with or without @@ -98,7 +98,7 @@ Options:\n\ -h | -help - Show help\n\ -k <key-string> - Use key for ciphertext operations\n\ -m - verify HMAC values when reading\n\ - -p <rate> - fps of picture when wrapping PCM or JP2K:\n\ + -p <rate> - Alternative picture rate when unwrapping PCM:\n\ Use one of [23|24|25|30|48|50|60], 24 is default\n\ -s <size> - Number of bytes to dump to output when -v is given\n\ -V - Show version information\n\ @@ -173,6 +173,9 @@ public: if ( picture_rate == 96 ) return EditRate_96; if ( picture_rate == 100 ) return EditRate_100; if ( picture_rate == 120 ) return EditRate_120; + if ( picture_rate == 192 ) return EditRate_192; + if ( picture_rate == 200 ) return EditRate_200; + if ( picture_rate == 240 ) return EditRate_240; return EditRate_24; } diff --git a/src/asdcp-wrap.cpp b/src/asdcp-wrap.cpp index e8bf2f1..4312cc7 100755 --- a/src/asdcp-wrap.cpp +++ b/src/asdcp-wrap.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2003-2015, John Hurst +Copyright (c) 2003-2016, John Hurst All rights reserved. Redistribution and use in source and binary forms, with or without @@ -266,6 +266,9 @@ public: if ( picture_rate == 96 ) return EditRate_96; if ( picture_rate == 100 ) return EditRate_100; if ( picture_rate == 120 ) return EditRate_120; + if ( picture_rate == 192 ) return EditRate_192; + if ( picture_rate == 200 ) return EditRate_200; + if ( picture_rate == 240 ) return EditRate_240; return EditRate_24; } @@ -286,6 +289,9 @@ public: if ( picture_rate == 96 ) return "96"; if ( picture_rate == 100 ) return "100"; if ( picture_rate == 120 ) return "120"; + if ( picture_rate == 192 ) return "192"; + if ( picture_rate == 200 ) return "200"; + if ( picture_rate == 240 ) return "240"; return "24"; } @@ -617,7 +623,8 @@ bool check_phfr_params(CommandOptions& Options, JP2K::PictureDescriptor& PDesc) { Rational rate = Options.PictureRate(); - if ( rate != EditRate_96 && rate != EditRate_100 && rate != EditRate_120 ) + if ( rate != EditRate_96 && rate != EditRate_100 && rate != EditRate_120 + && rate != EditRate_192 && rate != EditRate_200 && rate != EditRate_240 ) return true; if ( PDesc.StoredWidth > 2048 ) diff --git a/src/h__02_Reader.cpp b/src/h__02_Reader.cpp index 9e07f72..25a82e0 100644 --- a/src/h__02_Reader.cpp +++ b/src/h__02_Reader.cpp @@ -399,7 +399,7 @@ AS_02::h__AS02Reader::~h__AS02Reader() {} // AS-DCP method of opening an MXF file for read Result_t -AS_02::h__AS02Reader::OpenMXFRead(const char* filename) +AS_02::h__AS02Reader::OpenMXFRead(const std::string& filename) { bool has_header_essence = false; Result_t result = ASDCP::MXF::TrackFileReader<OP1aHeader, AS_02::MXF::AS02IndexReader>::OpenMXFRead(filename); |
