summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjhurst <jhurst@cinecert.com>2016-11-22 17:58:19 +0000
committerjhurst <>2016-11-22 17:58:19 +0000
commit8fd602770d89acb171dbd878d8737ead85aa35d3 (patch)
tree229577c9b4389f7e05694a1f4241d0a9160dd461 /src
parentb3e312cda7ce3e7027f5fb44ef2ffd87d713dd8d (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.h13
-rw-r--r--src/AS_02_internal.h2
-rwxr-xr-xsrc/AS_DCP.h3
-rw-r--r--src/AS_DCP_ATMOS.cpp26
-rw-r--r--src/AS_DCP_DCData.cpp26
-rwxr-xr-xsrc/AS_DCP_JP2K.cpp40
-rwxr-xr-xsrc/AS_DCP_MXF.cpp2
-rwxr-xr-xsrc/AS_DCP_PCM.cpp8
-rw-r--r--src/MDD.cpp39
-rwxr-xr-xsrc/MDD.h14
-rwxr-xr-xsrc/MXFTypes.h57
-rwxr-xr-xsrc/Metadata.cpp158
-rwxr-xr-xsrc/Metadata.h32
-rw-r--r--src/TimedText_Parser.cpp5
-rwxr-xr-xsrc/as-02-unwrap.cpp116
-rwxr-xr-xsrc/as-02-wrap.cpp92
-rwxr-xr-xsrc/asdcp-test.cpp6
-rwxr-xr-xsrc/asdcp-unwrap.cpp7
-rwxr-xr-xsrc/asdcp-wrap.cpp11
-rw-r--r--src/h__02_Reader.cpp2
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 }
};
diff --git a/src/MDD.h b/src/MDD.h
index cef2db3..7240ba2 100755
--- a/src/MDD.h
+++ b/src/MDD.h
@@ -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);