summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hurst <jhurst@cinecert.com>2020-07-07 10:48:29 -0700
committerGitHub <noreply@github.com>2020-07-07 10:48:29 -0700
commit3562c679bc8fd59ac91541bba2144a778bfdbf02 (patch)
treee7a53012d45461876839fdc480aee939ab6d8cb1 /src
parentdc74dc00c2f225344f14c39969bd6b66664b4fd4 (diff)
parentf421cbb767e0437458332200e3f8537064feaaa8 (diff)
Merge pull request #45 from cinecert/iab-labels
Add support for IAB Track Files (SMPTE ST 2067-201)
Diffstat (limited to 'src')
-rw-r--r--src/AS_02_IAB.cpp618
-rw-r--r--src/AS_02_IAB.h239
-rw-r--r--src/AS_02_internal.h5
-rwxr-xr-xsrc/AS_DCP.h1
-rwxr-xr-xsrc/AS_DCP_MXF.cpp4
-rwxr-xr-xsrc/AS_DCP_internal.h21
-rw-r--r--src/CMakeLists.txt6
-rw-r--r--src/MDD.cpp21
-rwxr-xr-xsrc/MDD.h7
-rwxr-xr-xsrc/MXF.cpp6
-rw-r--r--src/Makefile.am2
-rwxr-xr-xsrc/Metadata.cpp146
-rwxr-xr-xsrc/Metadata.h44
13 files changed, 1114 insertions, 6 deletions
diff --git a/src/AS_02_IAB.cpp b/src/AS_02_IAB.cpp
new file mode 100644
index 0000000..cbee6e2
--- /dev/null
+++ b/src/AS_02_IAB.cpp
@@ -0,0 +1,618 @@
+/*
+Copyright (c) 2011-2020, Robert Scheler, Heiko Sparenberg Fraunhofer IIS,
+John Hurst, Pierre-Anthony Lemieux
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "AS_02_internal.h"
+#include "AS_02_IAB.h"
+
+#include <iostream>
+#include <iomanip>
+#include <stdexcept>
+
+namespace Kumu {
+ class RuntimeError : public std::runtime_error {
+ Kumu::Result_t m_Result;
+ RuntimeError();
+ public:
+ RuntimeError(const Kumu::Result_t& result) : std::runtime_error(result.Message()), m_Result(result) {}
+ Kumu::Result_t GetResult() { return this->m_Result; }
+ ~RuntimeError() throw() {}
+ };
+}
+
+//------------------------------------------------------------------------------------------
+
+
+AS_02::IAB::MXFWriter::MXFWriter() : m_ClipStart(0), m_State(ST_BEGIN) {
+}
+
+AS_02::IAB::MXFWriter::~MXFWriter() {}
+
+const ASDCP::MXF::OP1aHeader&
+AS_02::IAB::MXFWriter::OP1aHeader() const {
+ if (this->m_State == ST_BEGIN) {
+ throw Kumu::RuntimeError(Kumu::RESULT_INIT);
+ }
+
+ return this->m_Writer->m_HeaderPart;
+}
+
+const ASDCP::MXF::RIP&
+AS_02::IAB::MXFWriter::RIP() const {
+ if (this->m_State == ST_BEGIN) {
+ throw Kumu::RuntimeError(Kumu::RESULT_INIT);
+ }
+
+ return this->m_Writer->m_RIP;
+}
+
+Kumu::Result_t
+AS_02::IAB::MXFWriter::OpenWrite(
+ const std::string& filename,
+ const ASDCP::WriterInfo& Info,
+ const ASDCP::MXF::IABSoundfieldLabelSubDescriptor& sub,
+ const std::vector<ASDCP::UL>& conformsToSpecs,
+ const ASDCP::Rational& edit_rate,
+ const ASDCP::Rational& sample_rate) {
+
+ /* are we already running */
+
+ if (this->m_State != ST_BEGIN) {
+ return Kumu::RESULT_STATE;
+ }
+
+ Result_t result = Kumu::RESULT_OK;
+
+ /* initialize the writer */
+
+ this->m_Writer = new AS_02::IAB::MXFWriter::h__Writer(DefaultSMPTEDict());
+
+ this->m_Writer->m_Info = Info;
+
+ this->m_Writer->m_HeaderSize = 16 * 1024;
+
+ try {
+
+ /* open the file */
+
+ result = this->m_Writer->m_File.OpenWrite(filename.c_str());
+
+ if (result.Failure()) {
+ throw Kumu::RuntimeError(result);
+ }
+
+ /* initialize IAB descriptor */
+
+ ASDCP::MXF::IABEssenceDescriptor* desc = new ASDCP::MXF::IABEssenceDescriptor(this->m_Writer->m_Dict);
+
+ GenRandomValue(desc->InstanceUID); /* TODO: remove */
+ desc->SampleRate = edit_rate;
+ desc->AudioSamplingRate = sample_rate;
+ desc->ChannelCount = 0;
+ desc->SoundEssenceCoding = this->m_Writer->m_Dict->ul(MDD_ImmersiveAudioCoding);
+ desc->QuantizationBits = 24;
+
+ this->m_Writer->m_EssenceDescriptor = desc;
+
+ /* copy and add the IAB subdescriptor */
+
+ ASDCP::MXF::IABSoundfieldLabelSubDescriptor* subdesc = new ASDCP::MXF::IABSoundfieldLabelSubDescriptor(sub);
+
+ GenRandomValue(subdesc->InstanceUID); /* TODO: remove */
+ subdesc->MCATagName = "IAB";
+ subdesc->MCATagSymbol = "IAB";
+ subdesc->MCALabelDictionaryID = this->m_Writer->m_Dict->ul(MDD_IABSoundfield);
+ GenRandomValue(subdesc->MCALinkID);
+
+ this->m_Writer->m_EssenceSubDescriptorList.push_back(subdesc);
+ this->m_Writer->m_EssenceDescriptor->SubDescriptors.push_back(subdesc->InstanceUID);
+
+ /* initialize the index write */
+
+ this->m_Writer->m_IndexWriter.SetEditRate(edit_rate);
+
+ /* Essence Element UL */
+
+ byte_t element_ul_bytes[ASDCP::SMPTE_UL_LENGTH];
+
+ const ASDCP::MDDEntry& element_ul_entry = this->m_Writer->m_Dict->Type(MDD_IMF_IABEssenceClipWrappedElement);
+
+ std::copy(element_ul_entry.ul, element_ul_entry.ul + ASDCP::SMPTE_UL_LENGTH, element_ul_bytes);
+
+ /* only a single track */
+
+ element_ul_bytes[15] = 1;
+
+ /* write the file header*/
+ /* WriteAS02Header() takes ownership of desc and subdesc */
+
+ result = this->m_Writer->WriteAS02Header(
+ "Clip wrapping of IA bitstreams as specified in SMPTE ST 2067-201",
+ UL(this->m_Writer->m_Dict->ul(MDD_IMF_IABEssenceClipWrappedContainer)),
+ "IA Bitstream",
+ UL(element_ul_bytes),
+ UL(this->m_Writer->m_Dict->ul(MDD_SoundDataDef)),
+ edit_rate,
+ derive_timecode_rate_from_edit_rate(edit_rate),
+ &conformsToSpecs
+ );
+
+ if (result.Failure()) {
+ throw Kumu::RuntimeError(result);
+ }
+
+ /* start the clip */
+
+ this->m_ClipStart = this->m_Writer->m_File.Tell();
+
+ byte_t clip_buffer[24] = { 0 };
+
+ memcpy(clip_buffer, this->m_Writer->m_Dict->ul(MDD_IMF_IABEssenceClipWrappedElement), 16);
+
+ if (!Kumu::write_BER(clip_buffer + 16, 0, 8)) {
+ throw Kumu::RuntimeError(Kumu::RESULT_FAIL);
+ }
+
+ this->m_Writer->m_StreamOffset = 24;
+
+ result = this->m_Writer->m_File.Write(clip_buffer, 24);
+
+ if (result.Failure()) {
+ throw Kumu::RuntimeError(result);
+ }
+
+ this->m_State = ST_READY;
+
+ } catch (Kumu::RuntimeError e) {
+
+ this->Reset();
+
+ return e.GetResult();
+
+ }
+
+ return result;
+
+}
+
+Result_t
+AS_02::IAB::MXFWriter::WriteFrame(const ui8_t* frame, ui32_t sz) {
+
+ /* are we running */
+
+ if (this->m_State == ST_BEGIN) {
+ return Kumu::RESULT_INIT;
+ }
+
+ Result_t result = Kumu::RESULT_OK;
+
+ /* update the index */
+
+ IndexTableSegment::IndexEntry Entry;
+
+ Entry.StreamOffset = this->m_Writer->m_StreamOffset;
+
+ this->m_Writer->m_IndexWriter.PushIndexEntry(Entry);
+
+ try {
+
+ /* write the frame */
+
+ result = this->m_Writer->m_File.Write(frame, sz);
+
+ if (result.Failure()) {
+ throw Kumu::RuntimeError(result);
+ }
+
+ /* increment the frame counter */
+
+ this->m_Writer->m_FramesWritten++;
+
+ /* increment stream offset */
+
+ this->m_Writer->m_StreamOffset += sz;
+
+ /* we are running now */
+
+ this->m_State = ST_RUNNING;
+
+ } catch (Kumu::RuntimeError e) {
+
+ this->Reset();
+
+ return e.GetResult();
+
+ }
+
+ return result;
+}
+
+Result_t
+AS_02::IAB::MXFWriter::Finalize() {
+
+ /* are we running */
+
+ if (this->m_State == ST_BEGIN) {
+ return Kumu::RESULT_INIT;
+ }
+
+ Result_t result = RESULT_OK;
+
+ try {
+
+ /* write clip length */
+
+ ui64_t current_position = this->m_Writer->m_File.Tell();
+
+ result = this->m_Writer->m_File.Seek(m_ClipStart + 16);
+
+ byte_t clip_buffer[8] = { 0 };
+
+ ui64_t size = static_cast<ui64_t>(this->m_Writer->m_StreamOffset);
+
+ bool check = Kumu::write_BER(clip_buffer, size, 8);
+
+ if (!check) {
+ throw Kumu::RuntimeError(Kumu::RESULT_FAIL);
+ }
+
+ result = this->m_Writer->m_File.Write(clip_buffer, 8);
+
+ if (result.Failure()) {
+ throw Kumu::RuntimeError(result);
+ }
+
+ result = this->m_Writer->m_File.Seek(current_position);
+
+ if (result.Failure()) {
+ throw Kumu::RuntimeError(result);
+ }
+
+ /* write footer */
+
+ result = this->m_Writer->WriteAS02Footer();
+
+ if (result.Failure()) {
+ throw Kumu::RuntimeError(result);
+ }
+
+ } catch (Kumu::RuntimeError e) {
+
+ /* nothing to do since we are about to reset */
+
+ result = e.GetResult();
+
+ }
+
+ /* we are ready to start again */
+
+ this->Reset();
+
+ return result;
+}
+
+void
+AS_02::IAB::MXFWriter::Reset() {
+ this->m_Writer.set(NULL);
+ this->m_State = ST_BEGIN;
+}
+
+
+//------------------------------------------------------------------------------------------
+
+
+AS_02::IAB::MXFReader::MXFReader() : m_State(ST_READER_BEGIN) {}
+
+AS_02::IAB::MXFReader::~MXFReader() {}
+
+ASDCP::MXF::OP1aHeader&
+AS_02::IAB::MXFReader::OP1aHeader() const {
+ if (this->m_State == ST_READER_BEGIN) {
+ throw Kumu::RuntimeError(Kumu::RESULT_INIT);
+ }
+
+ return this->m_Reader->m_HeaderPart;
+}
+
+const ASDCP::MXF::RIP&
+AS_02::IAB::MXFReader::RIP() const {
+ if (this->m_State == ST_READER_BEGIN) {
+ throw Kumu::RuntimeError(Kumu::RESULT_INIT);
+ }
+
+ return this->m_Reader->m_RIP;
+}
+
+Result_t
+AS_02::IAB::MXFReader::OpenRead(const std::string& filename) {
+
+ /* are we already running */
+
+ if (this->m_State != ST_READER_BEGIN) {
+ return Kumu::RESULT_STATE;
+ }
+
+ Result_t result = Kumu::RESULT_OK;
+
+ /* initialize the writer */
+
+ this->m_Reader = new h__Reader(DefaultCompositeDict());
+
+ try {
+
+ result = this->m_Reader->OpenMXFRead(filename);
+
+ if (result.Failure()) {
+ throw Kumu::RuntimeError(result);
+ }
+
+ InterchangeObject* tmp_iobj = 0;
+
+ this->m_Reader->m_HeaderPart.GetMDObjectByType(
+ this->m_Reader->m_Dict->Type(MDD_IABEssenceDescriptor).ul,
+ &tmp_iobj
+ );
+
+ if (!tmp_iobj) {
+ throw Kumu::RuntimeError(Kumu::RESULT_FAIL);
+ }
+
+ this->m_Reader->m_HeaderPart.GetMDObjectByType(
+ this->m_Reader->m_Dict->Type(MDD_IABSoundfieldLabelSubDescriptor).ul,
+ &tmp_iobj
+ );
+
+ if (!tmp_iobj) {
+ throw Kumu::RuntimeError(Kumu::RESULT_FAIL);
+ }
+
+ std::list<InterchangeObject*> ObjectList;
+
+ this->m_Reader->m_HeaderPart.GetMDObjectsByType(
+ this->m_Reader->m_Dict->Type(MDD_Track).ul,
+ ObjectList
+ );
+
+ if (ObjectList.empty()) {
+ throw Kumu::RuntimeError(Kumu::RESULT_FAIL);
+ }
+
+ /* invalidate current frame */
+
+ this->m_CurrentFrameIndex = -1;
+
+ /* we are ready */
+
+ this->m_State = ST_READER_READY;
+
+ } catch (Kumu::RuntimeError e) {
+
+ this->Reset();
+
+ return e.GetResult();
+ }
+
+ return RESULT_OK;
+}
+
+
+Result_t
+AS_02::IAB::MXFReader::Close() {
+
+ /* are we already running */
+
+ if (this->m_State == ST_READER_BEGIN) {
+ return Kumu::RESULT_INIT;
+ }
+
+ this->Reset();
+
+ return Kumu::RESULT_OK;
+}
+
+
+Result_t AS_02::IAB::MXFReader::GetFrameCount(ui32_t& frameCount) const {
+
+ /* are we already running */
+
+ if (this->m_State == ST_READER_BEGIN) {
+ return Kumu::RESULT_INIT;
+ }
+
+ frameCount = m_Reader->m_IndexAccess.GetDuration();
+
+ return Kumu::RESULT_OK;
+}
+
+Result_t
+AS_02::IAB::MXFReader::ReadFrame(ui32_t frame_number, AS_02::IAB::MXFReader::Frame& frame) {
+
+ /* are we already running */
+
+ if (this->m_State == ST_READER_BEGIN) {
+ return Kumu::RESULT_INIT;
+ }
+
+ Result_t result = RESULT_OK;
+
+ /* have we already read the frame */
+
+ if (frame_number != this->m_CurrentFrameIndex) {
+
+ try {
+
+ // look up frame index node
+ IndexTableSegment::IndexEntry index_entry;
+
+ result = this->m_Reader->m_IndexAccess.Lookup(frame_number, index_entry);
+
+ if (result.Failure()) {
+ DefaultLogSink().Error("Frame value out of range: %u\n", frame_number);
+ throw Kumu::RuntimeError(result);
+ }
+
+ result = this->m_Reader->m_File.Seek(index_entry.StreamOffset);
+
+ if (result.Failure()) {
+ DefaultLogSink().Error("Cannot seek to stream offset: %u\n", index_entry.StreamOffset);
+ throw Kumu::RuntimeError(result);
+ }
+
+ /* read the preamble info */
+
+ const int preambleTLLen = 5;
+ const int frameTLLen = 5;
+
+ ui32_t buffer_offset = 0;
+
+ this->m_CurrentFrameBuffer.resize(preambleTLLen);
+
+ result = this->m_Reader->m_File.Read(&this->m_CurrentFrameBuffer[buffer_offset], preambleTLLen);
+
+ if (result.Failure()) {
+ DefaultLogSink().Error("Error reading IA Frame preamble\n", index_entry.StreamOffset);
+ throw Kumu::RuntimeError(result);
+ }
+
+ ui32_t preambleLen = ((ui32_t)this->m_CurrentFrameBuffer[1 + buffer_offset] << 24) +
+ ((ui32_t)this->m_CurrentFrameBuffer[2 + buffer_offset] << 16) +
+ ((ui32_t)this->m_CurrentFrameBuffer[3 + buffer_offset] << 8) +
+ (ui32_t)this->m_CurrentFrameBuffer[4 + buffer_offset];
+
+ buffer_offset += preambleTLLen;
+
+ /* read the preamble*/
+
+ if (preambleLen > 0) {
+
+ this->m_CurrentFrameBuffer.resize(preambleTLLen + preambleLen);
+
+ result = this->m_Reader->m_File.Read(&this->m_CurrentFrameBuffer[buffer_offset], preambleLen);
+
+ if (result.Failure()) {
+ DefaultLogSink().Error("Error reading IA Frame preamble\n", index_entry.StreamOffset);
+ throw Kumu::RuntimeError(result);
+ }
+
+ buffer_offset += preambleLen;
+
+ }
+
+ /* read the IA Frame info */
+
+ this->m_CurrentFrameBuffer.resize(preambleTLLen + preambleLen + frameTLLen);
+
+ result = this->m_Reader->m_File.Read(&this->m_CurrentFrameBuffer[buffer_offset], frameTLLen);
+
+ if (result.Failure()) {
+ DefaultLogSink().Error("Error reading IA Frame data\n", index_entry.StreamOffset);
+ throw Kumu::RuntimeError(result);
+ }
+
+ ui32_t frameLen = ((ui32_t)this->m_CurrentFrameBuffer[buffer_offset + 1] << 24) +
+ ((ui32_t)this->m_CurrentFrameBuffer[buffer_offset + 2] << 16) +
+ ((ui32_t)this->m_CurrentFrameBuffer[buffer_offset + 3] << 8) +
+ (ui32_t)this->m_CurrentFrameBuffer[buffer_offset + 4];
+
+ buffer_offset += frameTLLen;
+
+ /* read the IA Frame */
+
+ if (frameLen > 0) {
+
+ this->m_CurrentFrameBuffer.resize(preambleTLLen + preambleLen + frameTLLen + frameLen);
+
+ result = this->m_Reader->m_File.Read(&this->m_CurrentFrameBuffer[buffer_offset], frameLen);
+
+ if (result.Failure()) {
+ DefaultLogSink().Error("Error reading IA Frame data\n", index_entry.StreamOffset);
+ throw Kumu::RuntimeError(result);
+ }
+
+ buffer_offset += frameLen;
+
+ }
+
+ /* update current frame */
+
+ this->m_CurrentFrameIndex = frame_number;
+
+ } catch (Kumu::RuntimeError e) {
+
+ this->Reset();
+
+ return e.GetResult();
+
+ }
+
+ }
+
+ frame = std::pair<size_t, const ui8_t*>(this->m_CurrentFrameBuffer.size(), &this->m_CurrentFrameBuffer[0]);
+
+ this->m_State = ST_READER_RUNNING;
+
+ return result;
+}
+
+Result_t
+AS_02::IAB::MXFReader::FillWriterInfo(WriterInfo& Info) const {
+ /* are we already running */
+
+ if (this->m_State == ST_READER_BEGIN) {
+ return Kumu::RESULT_FAIL;
+ }
+
+ Info = m_Reader->m_Info;
+
+ return Kumu::RESULT_OK;
+}
+
+void
+AS_02::IAB::MXFReader::DumpHeaderMetadata(FILE* stream) const {
+ if (this->m_State != ST_READER_BEGIN) {
+ this->m_Reader->m_HeaderPart.Dump(stream);
+ }
+}
+
+
+void
+AS_02::IAB::MXFReader::DumpIndex(FILE* stream) const {
+ if (this->m_State != ST_READER_BEGIN) {
+ this->m_Reader->m_IndexAccess.Dump(stream);
+ }
+}
+
+void
+AS_02::IAB::MXFReader::Reset() {
+ this->m_Reader.set(NULL);
+ this->m_State = ST_READER_BEGIN;
+}
+
+//
+// end AS_02_IAB.cpp
+//
diff --git a/src/AS_02_IAB.h b/src/AS_02_IAB.h
new file mode 100644
index 0000000..57fb77e
--- /dev/null
+++ b/src/AS_02_IAB.h
@@ -0,0 +1,239 @@
+/*
+Copyright (c), Bjoern Stresing, Patrick Bichiou, Wolfgang Ruppel,
+John Hurst, Pierre-Anthony Lemieux
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * Reader and writer classes for IAB Track Files, as defined in SMPTE ST 2067-201
+ *
+ * @file
+ */
+
+#ifndef AS_02_IAB_h__
+#define AS_02_IAB_h__
+
+#include "AS_02.h"
+#include "AS_02_internal.h"
+#include "Metadata.h"
+
+namespace AS_02 {
+
+ namespace IAB {
+
+ /**
+ * Writes IAB Track Files as specified in ST SMPTE 2067-201
+ *
+ */
+ class MXFWriter {
+
+ typedef h__AS02Writer<AS_02::MXF::AS02IndexWriterVBR> h__Writer;
+
+ ASDCP::mem_ptr<h__Writer> m_Writer;
+ ui64_t m_ClipStart;
+ WriterState_t m_State;
+
+ void Reset();
+
+ ASDCP_NO_COPY_CONSTRUCT(MXFWriter);
+
+ public:
+ MXFWriter();
+ virtual ~MXFWriter();
+
+ /**
+ * Must be preceded by a succesful OpenWrite() call followed by zero or more WriteFrame() calls
+ *
+ * Warning: direct manipulation of MXF structures can interfere
+ * with the normal operation of the wrapper. Caveat emptor!
+ *
+ * @return Header of the Track File
+ *
+ * @throws std::runtime_error if the Track File is not open
+ */
+ virtual const ASDCP::MXF::OP1aHeader& OP1aHeader() const;
+
+ /**
+ * Must be preceded by a succesful OpenWrite() call followed by zero or more WriteFrame() calls
+ *
+ * Warning: direct manipulation of MXF structures can interfere
+ * with the normal operation of the wrapper. Caveat emptor!
+ *
+ * @return RIP of the Track File
+ *
+ * @throws std::runtime_error if the Track File is not open
+ */
+ virtual const ASDCP::MXF::RIP& RIP() const;
+
+ /**
+ * Creates and prepares an IAB Track File for writing.
+ *
+ * Must be called following instantiation or after Finalize() call
+ *
+ * @param filename Path to the file. The file must no exist.
+ * @param Info MXF file metadata to be written.
+ * @param sub IAB Soundfield Subdescritor items to be written. MCATagName, MCATagSymbol, MCALabelDictionaryID, MCALinkID are ignored.
+ * @param conformsToSpecs Value of the ConformsToSpecifications preface item
+ * @param edit_rate Frame rate of the IA Bitstream
+ * @param sampling_rate Sampling rate of the audio essence within the IA Bitstream
+ *
+ * @return RESULT_OK indicates that frames are ready to be written,
+ * otherwise the reader is reset and the file is left is an undermined state.
+ */
+ Result_t OpenWrite(
+ const std::string& filename,
+ const ASDCP::WriterInfo& Info,
+ const ASDCP::MXF::IABSoundfieldLabelSubDescriptor& sub,
+ const std::vector<ASDCP::UL>& conformsToSpecs,
+ const ASDCP::Rational& edit_rate,
+ const ASDCP::Rational& sampling_rate = ASDCP::SampleRate_48k
+ );
+
+ /**
+ * Writes a single frame.
+ *
+ * Must be preceded by a succesful OpenWrite() call followed by zero or more WriteFrame() calls
+ *
+ * @param frame Pointer to a complete IA Frame
+ * @param sz Size in bytes of the IA Frame
+ * @return RESULT_OK indicates that the frame is written and additional frames can be written,
+ * otherwise the reader is reset and the file is left is an undermined state.
+ */
+ Result_t WriteFrame(const ui8_t* frame, ui32_t sz);
+
+ /**
+ * Writes the Track File footer and closes the file.
+ *
+ * Must be preceded by a succesful OpenWrite() call followed by zero or more WriteFrame() calls
+ *
+ * @return RESULT_OK indicates that the frame is written and additional frames can be written,
+ * otherwise the reader is reset and the file is left is an undermined state.
+ */
+ Result_t Finalize();
+ };
+
+ /**
+ * Reads IAB Track Files as specified in ST SMPTE 2067-201
+ *
+ */
+ class MXFReader {
+
+ typedef h__AS02Reader h__Reader;
+
+ ASDCP::mem_ptr<h__Reader> m_Reader;
+
+ i64_t m_CurrentFrameIndex;
+ std::vector<ui8_t> m_CurrentFrameBuffer;
+ ReaderState_t m_State;
+
+ void Reset();
+
+ ASDCP_NO_COPY_CONSTRUCT(MXFReader);
+
+ public:
+
+ /* typedefs*/
+
+ typedef std::pair<size_t, const ui8_t*> Frame;
+
+ /* methods */
+
+ MXFReader();
+ virtual ~MXFReader();
+
+ /**
+ * Warning: direct manipulation of MXF structures can interfere
+ * with the normal operation of the wrapper. Caveat emptor!
+ *
+ * @return Header of the Track File
+ *
+ * @throws std::runtime_error if the Track File is not open
+ */
+ virtual ASDCP::MXF::OP1aHeader& OP1aHeader() const;
+
+ /**
+ * Warning: direct manipulation of MXF structures can interfere
+ * with the normal operation of the wrapper. Caveat emptor!
+ *
+ * @return RIP of the Track File
+ *
+ * @throws std::runtime_error if the Track File is not open
+ */
+ virtual const ASDCP::MXF::RIP& RIP() const;
+
+ /**
+ * Creates and prepares an IAB Track File for reading.
+ *
+ * @param filename Path to the file. The file must no exist.
+ *
+ * @return RESULT_OK indicates that frames are ready to be read,
+ * otherwise the reader is reset
+ */
+ Result_t OpenRead(const std::string& filename);
+
+ /**
+ * Closes the IAB Track File.
+ *
+ * @return RESULT_OK indicates that the Track File was successfully closed.
+ */
+ Result_t Close();
+
+ /**
+ * Fill a WriterInfo struct with the values from the Track File's header.
+ *
+ * @param writer_info Struct to be filled
+ * @return RESULT_OK indicates that writer_info was successfully filled.
+ */
+ Result_t FillWriterInfo(ASDCP::WriterInfo& writer_info) const;
+
+ /**
+ * Reads an IA Frame.
+ *
+ * @param frame_number Index of the frame to be read. Must be in the range [0, GetFrameCount()).
+ * @param frame Frame data. Must not be modified. Remains valid until the next call to ReadFrame().
+ * @return RESULT_OK indicates that more frames are ready to be read,
+ * otherwise the file is closed and the reader reset
+ */
+ Result_t ReadFrame(ui32_t frame_number, Frame& frame);
+
+ /**
+ * Returns the number of IA Frame in the Track File.
+ *
+ * @param frameCount Number of IA Frames
+ * @return RESULT_OK unless the file is not open
+ */
+ Result_t GetFrameCount(ui32_t& frameCount) const;
+
+ // Print debugging information to stream
+ void DumpHeaderMetadata(FILE* = 0) const;
+ void DumpIndex(FILE* = 0) const;
+ };
+
+ } //namespace IAB
+
+} // namespace AS_02
+
+#endif // AS_02_IAB_h__
diff --git a/src/AS_02_internal.h b/src/AS_02_internal.h
index e6038c3..b5d8282 100644
--- a/src/AS_02_internal.h
+++ b/src/AS_02_internal.h
@@ -164,7 +164,8 @@ namespace AS_02
// all the above for a single source clip
Result_t WriteAS02Header(const std::string& PackageLabel, const ASDCP::UL& WrappingUL,
const std::string& TrackName, const ASDCP::UL& EssenceUL,
- const ASDCP::UL& DataDefinition, const ASDCP::Rational& EditRate)
+ const ASDCP::UL& DataDefinition, const ASDCP::Rational& EditRate,
+ const std::vector<ASDCP::UL>* conformsToSpecifications = NULL)
{
if ( EditRate.Numerator == 0 || EditRate.Denominator == 0 )
{
@@ -172,7 +173,7 @@ namespace AS_02
return RESULT_PARAM;
}
- InitHeader(MXFVersion_2011);
+ InitHeader(MXFVersion_2011, conformsToSpecifications);
AddSourceClip(EditRate, EditRate/*TODO: for a moment*/, 0 /*no timecode track*/, TrackName, EssenceUL, DataDefinition, PackageLabel);
AddEssenceDescriptor(WrappingUL);
diff --git a/src/AS_DCP.h b/src/AS_DCP.h
index f39c9c8..f089f06 100755
--- a/src/AS_DCP.h
+++ b/src/AS_DCP.h
@@ -223,6 +223,7 @@ namespace ASDCP {
ESS_AS02_TIMED_TEXT, // the file contains a TTML document and zero or more resources
ESS_AS02_ISXD, // the file contains an ISXD document stream (per SMPTE RDD 47)
ESS_AS02_ACES, // the file contains two or more ACES codestreams (per SMPTE ST 2067-50)
+ ESS_AS02_IAB, // the file contains an IAB stream (per SMPTE ST 2067-201)
ESS_MAX
};
diff --git a/src/AS_DCP_MXF.cpp b/src/AS_DCP_MXF.cpp
index d3606fe..c478f2f 100755
--- a/src/AS_DCP_MXF.cpp
+++ b/src/AS_DCP_MXF.cpp
@@ -277,6 +277,10 @@ ASDCP::EssenceType(const std::string& filename, EssenceType_t& type)
{
type = ESS_AS02_ACES;
}
+ else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(IABEssenceDescriptor))) )
+ {
+ type = ESS_AS02_IAB;
+ }
}
}
else
diff --git a/src/AS_DCP_internal.h b/src/AS_DCP_internal.h
index a684ba5..7162368 100755
--- a/src/AS_DCP_internal.h
+++ b/src/AS_DCP_internal.h
@@ -624,7 +624,7 @@ namespace ASDCP
const MXF::RIP& GetRIP() const { return m_RIP; }
- void InitHeader(const MXFVersion& mxf_ver)
+ void InitHeader(const MXFVersion& mxf_ver, const std::vector<ASDCP::UL>* conformsToSpecifications = NULL)
{
assert(m_Dict);
assert(m_EssenceDescriptor);
@@ -633,6 +633,18 @@ namespace ASDCP
m_HeaderPart.m_Preface = new Preface(m_Dict);
m_HeaderPart.AddChildObject(m_HeaderPart.m_Preface);
+ // add conformsToSpecifications, if it exists
+
+ if (conformsToSpecifications && conformsToSpecifications->size() > 0) {
+
+ m_HeaderPart.m_Preface->ConformsToSpecifications.set_has_value();
+
+ m_HeaderPart.m_Preface->ConformsToSpecifications.get().insert(
+ conformsToSpecifications->begin(),
+ conformsToSpecifications->end()
+ );
+ }
+
// Set the Operational Pattern label -- we're just starting and have no RIP or index,
// so we tell the world by using OP1a
m_HeaderPart.m_Preface->OperationalPattern = UL(m_Dict->ul(MDD_OP1a));
@@ -881,6 +893,13 @@ namespace ASDCP
//------------------------------------------------------------------------------------------
//
+// state machine for mxf reader
+ enum ReaderState_t {
+ ST_READER_BEGIN, // waiting for Open()
+ ST_READER_READY, // ready to read frames
+ ST_READER_RUNNING, // one or more frames read
+ };
+
//
class h__ASDCPReader : public MXF::TrackFileReader<OP1aHeader, OPAtomIndexFooter>
{
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 842f44a..2787e46 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -37,13 +37,13 @@ set(asdcp_src ${asdcp_src} Wav.h WavFileWriter.h MXF.h Metadata.h JP2K.h AS_DCP.
# ----------as02----------
# source
-set(as02_src h__02_Reader.cpp h__02_Writer.cpp AS_02_ISXD.cpp AS_02_JP2K.cpp AS_02_PCM.cpp ST2052_TextParser.cpp AS_02_TimedText.cpp AS_02_ACES.cpp ACES_Codestream_Parser.cpp ACES_Sequence_Parser.cpp ACES.cpp)
+set(as02_src h__02_Reader.cpp h__02_Writer.cpp AS_02_ISXD.cpp AS_02_JP2K.cpp AS_02_PCM.cpp ST2052_TextParser.cpp AS_02_TimedText.cpp AS_02_ACES.cpp ACES_Codestream_Parser.cpp ACES_Sequence_Parser.cpp ACES.cpp AS_02_IAB.cpp)
# header for deployment (install target)
-set(as02_deploy_header AS_02.h Metadata.h MXF.h MXFTypes.h KLV.h MDD.h AS_02_ACES.h ACES.h)
+set(as02_deploy_header AS_02.h Metadata.h MXF.h MXFTypes.h KLV.h MDD.h AS_02_ACES.h ACES.h AS_02_IAB.h AS_02_internal.h)
# header
-set(as02_src ${as02_src} AS_02.h AS_02_internal.h AS_02_ACES.h ACES.h)
+set(as02_src ${as02_src} AS_02.h AS_02_internal.h AS_02_ACES.h ACES.h AS_02_IAB.h)
include_directories("${PROJECT_SOURCE_DIR}/src" "${OpenSSLLib_include_DIR}" "${XercescppLib_include_DIR}")
diff --git a/src/MDD.cpp b/src/MDD.cpp
index 6db1bec..772b96d 100644
--- a/src/MDD.cpp
+++ b/src/MDD.cpp
@@ -1639,6 +1639,27 @@ static const ASDCP::MDDEntry s_MDD_Table[] = {
{ { 0x06, 0x0e, 0x2b, 0x34, 01, 0x01, 0x01, 0x0e,
06, 0x01, 0x01, 0x02, 06, 0x00, 0x00, 0x00 },
{0}, false, "TimedTextDescriptor_ZPositionInUse" }, // 528
+ { { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x53, 0x01, 0x01, // 529
+ 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x7b, 0x00 },
+ {0}, false, "IABEssenceDescriptor" },
+ { { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x53, 0x01, 0x01, // 530
+ 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x7c, 0x00 },
+ {0}, false, "IABSoundfieldLabelSubDescriptor" },
+ { { 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x0d, // 531
+ 0x01, 0x01, 0x02, 0x01, 0x02, 0x00, 0x00, 0x00 },
+ {0}, false, "IMF_IABTrackFileLevel0" },
+ { { 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x0d, // 532
+ 0x0d, 0x01, 0x03, 0x01, 0x02, 0x1d, 0x01, 0x01 },
+ {0}, false, "IMF_IABEssenceClipWrappedContainer" },
+ { { 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x0d, // 533
+ 0x03, 0x02, 0x02, 0x21, 0x00, 0x00, 0x00, 0x00 },
+ {0}, false, "IABSoundfield" },
+ { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x02, 0x01, 0x01, // 534
+ 0x0d, 0x01, 0x03, 0x01, 0x16, 0x7f, 0x0d, 0x7f },
+ {0}, false, "IMF_IABEssenceClipWrappedElement" },
+ { { 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x05, // 535
+ 0x0e, 0x09, 0x06, 0x04, 0x00, 0x00, 0x00, 0x00 },
+ {0}, false, "ImmersiveAudioCoding" },
{ {0}, {0}, false, 0 },
};
diff --git a/src/MDD.h b/src/MDD.h
index 4e3dcaf..ba0cbbf 100755
--- a/src/MDD.h
+++ b/src/MDD.h
@@ -564,6 +564,13 @@ namespace ASDCP {
MDD_TimedTextDescriptor_DisplayType, // 526
MDD_TimedTextDescriptor_IntrinsicPictureResolution, // 527
MDD_TimedTextDescriptor_ZPositionInUse, // 528
+ MDD_IABEssenceDescriptor, // 529
+ MDD_IABSoundfieldLabelSubDescriptor, // 530
+ MDD_IMF_IABTrackFileLevel0, // 531
+ MDD_IMF_IABEssenceClipWrappedContainer, // 532
+ MDD_IABSoundfield, // 533
+ MDD_IMF_IABEssenceClipWrappedElement, // 534
+ MDD_ImmersiveAudioCoding, // 535
MDD_Max
}; // enum MDD_t
diff --git a/src/MXF.cpp b/src/MXF.cpp
index af406ee..5cab95e 100755
--- a/src/MXF.cpp
+++ b/src/MXF.cpp
@@ -1742,6 +1742,12 @@ ASDCP::MXF::decode_mca_string(const std::string& s, const mca_label_map_t& label
return false;
}
+ if ( ! ul_is_an_mca_channel(i->second.ul) )
+ {
+ DefaultLogSink().Error("Not a channel symbol: '%s'\n", symbol_buf.c_str());
+ return false;
+ }
+
ASDCP::MXF::AudioChannelLabelSubDescriptor *channel_descr =
new ASDCP::MXF::AudioChannelLabelSubDescriptor(dict);
GenRandomValue(channel_descr->MCALinkID);
diff --git a/src/Makefile.am b/src/Makefile.am
index 74c0b11..7768b39 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -143,6 +143,7 @@ libas02_la_SOURCES = \
AS_02_internal.h \
ACES.h \
AS_02_ACES.h \
+ AS_02_IAB.h \
h__02_Reader.cpp \
h__02_Writer.cpp \
AS_02_JP2K.cpp \
@@ -151,6 +152,7 @@ libas02_la_SOURCES = \
ST2052_TextParser.cpp \
AS_02_TimedText.cpp \
ACES.cpp \
+ AS_02_IAB.cpp \
ACES_Codestream_Parser.cpp \
ACES_Sequence_Parser.cpp \
AS_02_ACES.cpp
diff --git a/src/Metadata.cpp b/src/Metadata.cpp
index adaac11..9ca3d66 100755
--- a/src/Metadata.cpp
+++ b/src/Metadata.cpp
@@ -87,6 +87,8 @@ static InterchangeObject* GenericStreamTextBasedSet_Factory(const Dictionary*& D
static InterchangeObject* ISXDDataEssenceDescriptor_Factory(const Dictionary*& Dict) { return new ISXDDataEssenceDescriptor(Dict); }
static InterchangeObject* PHDRMetadataTrackSubDescriptor_Factory(const Dictionary*& Dict) { return new PHDRMetadataTrackSubDescriptor(Dict); }
static InterchangeObject* PIMFDynamicMetadataDescriptor_Factory(const Dictionary*& Dict) { return new PIMFDynamicMetadataDescriptor(Dict); }
+static InterchangeObject* IABEssenceDescriptor_Factory(const Dictionary*& Dict) { return new IABEssenceDescriptor(Dict); }
+static InterchangeObject* IABSoundfieldLabelSubDescriptor_Factory(const Dictionary*& Dict) { return new IABSoundfieldLabelSubDescriptor(Dict); }
void
@@ -140,6 +142,8 @@ ASDCP::MXF::Metadata_InitTypes(const Dictionary*& Dict)
SetObjectFactory(Dict->ul(MDD_ISXDDataEssenceDescriptor), ISXDDataEssenceDescriptor_Factory);
SetObjectFactory(Dict->ul(MDD_PHDRMetadataTrackSubDescriptor), PHDRMetadataTrackSubDescriptor_Factory);
SetObjectFactory(Dict->ul(MDD_PIMFDynamicMetadataDescriptor), PIMFDynamicMetadataDescriptor_Factory);
+ SetObjectFactory(Dict->ul(MDD_IABEssenceDescriptor), IABEssenceDescriptor_Factory);
+ SetObjectFactory(Dict->ul(MDD_IABSoundfieldLabelSubDescriptor), IABSoundfieldLabelSubDescriptor_Factory);
}
//------------------------------------------------------------------------------------------
@@ -4851,6 +4855,148 @@ PIMFDynamicMetadataDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer)
return InterchangeObject::WriteToBuffer(Buffer);
}
+//------------------------------------------------------------------------------------------
+// IABEssenceDescriptor
+
+//
+
+IABEssenceDescriptor::IABEssenceDescriptor(const Dictionary*& d) : GenericSoundEssenceDescriptor(d), m_Dict(d)
+{
+ assert(m_Dict);
+ m_UL = m_Dict->ul(MDD_IABEssenceDescriptor);
+}
+
+IABEssenceDescriptor::IABEssenceDescriptor(const IABEssenceDescriptor& rhs) : GenericSoundEssenceDescriptor(rhs.m_Dict), m_Dict(rhs.m_Dict)
+{
+ assert(m_Dict);
+ m_UL = m_Dict->ul(MDD_IABEssenceDescriptor);
+ Copy(rhs);
+}
+
+
+//
+ASDCP::Result_t
+IABEssenceDescriptor::InitFromTLVSet(TLVReader& TLVSet)
+{
+ assert(m_Dict);
+ Result_t result = GenericSoundEssenceDescriptor::InitFromTLVSet(TLVSet);
+ return result;
+}
+
+//
+ASDCP::Result_t
+IABEssenceDescriptor::WriteToTLVSet(TLVWriter& TLVSet)
+{
+ assert(m_Dict);
+ Result_t result = GenericSoundEssenceDescriptor::WriteToTLVSet(TLVSet);
+ return result;
+}
+
+//
+void
+IABEssenceDescriptor::Copy(const IABEssenceDescriptor& rhs)
+{
+ GenericSoundEssenceDescriptor::Copy(rhs);
+}
+
+//
+void
+IABEssenceDescriptor::Dump(FILE* stream)
+{
+ char identbuf[IdentBufferLen];
+ *identbuf = 0;
+
+ if ( stream == 0 )
+ stream = stderr;
+
+ GenericSoundEssenceDescriptor::Dump(stream);
+}
+
+//
+ASDCP::Result_t
+IABEssenceDescriptor::InitFromBuffer(const byte_t* p, ui32_t l)
+{
+ return InterchangeObject::InitFromBuffer(p, l);
+}
+
+//
+ASDCP::Result_t
+IABEssenceDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer)
+{
+ return InterchangeObject::WriteToBuffer(Buffer);
+}
+
+//------------------------------------------------------------------------------------------
+// IABSoundfieldLabelSubDescriptor
+
+//
+
+IABSoundfieldLabelSubDescriptor::IABSoundfieldLabelSubDescriptor(const Dictionary*& d) : MCALabelSubDescriptor(d), m_Dict(d)
+{
+ assert(m_Dict);
+ m_UL = m_Dict->ul(MDD_IABSoundfieldLabelSubDescriptor);
+}
+
+IABSoundfieldLabelSubDescriptor::IABSoundfieldLabelSubDescriptor(const IABSoundfieldLabelSubDescriptor& rhs) : MCALabelSubDescriptor(rhs.m_Dict), m_Dict(rhs.m_Dict)
+{
+ assert(m_Dict);
+ m_UL = m_Dict->ul(MDD_IABSoundfieldLabelSubDescriptor);
+ Copy(rhs);
+}
+
+
+//
+ASDCP::Result_t
+IABSoundfieldLabelSubDescriptor::InitFromTLVSet(TLVReader& TLVSet)
+{
+ assert(m_Dict);
+ Result_t result = MCALabelSubDescriptor::InitFromTLVSet(TLVSet);
+ return result;
+}
+
+//
+ASDCP::Result_t
+IABSoundfieldLabelSubDescriptor::WriteToTLVSet(TLVWriter& TLVSet)
+{
+ assert(m_Dict);
+ Result_t result = MCALabelSubDescriptor::WriteToTLVSet(TLVSet);
+ return result;
+}
+
+//
+void
+IABSoundfieldLabelSubDescriptor::Copy(const IABSoundfieldLabelSubDescriptor& rhs)
+{
+ MCALabelSubDescriptor::Copy(rhs);
+}
+
+//
+void
+IABSoundfieldLabelSubDescriptor::Dump(FILE* stream)
+{
+ char identbuf[IdentBufferLen];
+ *identbuf = 0;
+
+ if ( stream == 0 )
+ stream = stderr;
+
+ MCALabelSubDescriptor::Dump(stream);
+}
+
+//
+ASDCP::Result_t
+IABSoundfieldLabelSubDescriptor::InitFromBuffer(const byte_t* p, ui32_t l)
+{
+ return InterchangeObject::InitFromBuffer(p, l);
+}
+
+//
+ASDCP::Result_t
+IABSoundfieldLabelSubDescriptor::WriteToBuffer(ASDCP::FrameBuffer& Buffer)
+{
+ return InterchangeObject::WriteToBuffer(Buffer);
+}
+
//
// end Metadata.cpp
//
diff --git a/src/Metadata.h b/src/Metadata.h
index c624784..ab11034 100755
--- a/src/Metadata.h
+++ b/src/Metadata.h
@@ -1297,6 +1297,50 @@ namespace ASDCP
virtual Result_t WriteToBuffer(ASDCP::FrameBuffer&);
};
+ //
+ class IABEssenceDescriptor : public GenericSoundEssenceDescriptor
+ {
+ IABEssenceDescriptor();
+
+ public:
+ const Dictionary*& m_Dict;
+
+ IABEssenceDescriptor(const Dictionary*& d);
+ IABEssenceDescriptor(const IABEssenceDescriptor& rhs);
+ virtual ~IABEssenceDescriptor() {}
+
+ const IABEssenceDescriptor& operator=(const IABEssenceDescriptor& rhs) { Copy(rhs); return *this; }
+ virtual void Copy(const IABEssenceDescriptor& rhs);
+ virtual const char* HasName() { return "IABEssenceDescriptor"; }
+ 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&);
+ };
+
+ //
+ class IABSoundfieldLabelSubDescriptor : public MCALabelSubDescriptor
+ {
+ IABSoundfieldLabelSubDescriptor();
+
+ public:
+ const Dictionary*& m_Dict;
+
+ IABSoundfieldLabelSubDescriptor(const Dictionary*& d);
+ IABSoundfieldLabelSubDescriptor(const IABSoundfieldLabelSubDescriptor& rhs);
+ virtual ~IABSoundfieldLabelSubDescriptor() {}
+
+ const IABSoundfieldLabelSubDescriptor& operator=(const IABSoundfieldLabelSubDescriptor& rhs) { Copy(rhs); return *this; }
+ virtual void Copy(const IABSoundfieldLabelSubDescriptor& rhs);
+ virtual const char* HasName() { return "IABSoundfieldLabelSubDescriptor"; }
+ 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