summaryrefslogtreecommitdiff
path: root/src/AS_DCP_IAB.cpp
diff options
context:
space:
mode:
authorPierre-Anthony Lemieux <pal@palemieux.com>2020-03-10 20:47:33 -0700
committerPierre-Anthony Lemieux <pal@palemieux.com>2020-03-10 20:47:33 -0700
commitc93f726df76687de551b8b9258305975d56ff102 (patch)
treeec52fdffd17911a4e74aa3c81a9dc77eed84ab96 /src/AS_DCP_IAB.cpp
parent7b70b206a3bd767aad3a9a3c789cff9d0e9c38f2 (diff)
Replaced ATMOS with IAB terminologyissues/0015-replace-ATMOS-w-IAB
Diffstat (limited to 'src/AS_DCP_IAB.cpp')
-rw-r--r--src/AS_DCP_IAB.cpp693
1 files changed, 693 insertions, 0 deletions
diff --git a/src/AS_DCP_IAB.cpp b/src/AS_DCP_IAB.cpp
new file mode 100644
index 0000000..9b27923
--- /dev/null
+++ b/src/AS_DCP_IAB.cpp
@@ -0,0 +1,693 @@
+/*
+Copyright (c) 2004-2016, John Hurst
+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.
+*/
+/*! \file AS_DCP_IAB.cpp
+ \version $Id$
+ \brief AS-DCP library, IAB essence reader and writer implementation
+*/
+
+
+#include <iostream>
+
+#include "AS_DCP.h"
+#include "AS_DCP_internal.h"
+
+namespace ASDCP
+{
+namespace IAB
+{
+ static std::string IAB_PACKAGE_LABEL = "File Package: SMPTE-GC frame wrapping of IAB data";
+ static std::string IAB_DEF_LABEL = "IAB Data Track";
+ static byte_t IAB_ESSENCE_CODING[SMPTE_UL_LENGTH] = { 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x05,
+ 0x0e, 0x09, 0x06, 0x04, 0x00, 0x00, 0x00, 0x00 };
+} // namespace IAB
+} // namespace ASDCP
+
+//
+std::ostream&
+ASDCP::IAB::operator << (std::ostream& strm, const IABDescriptor& ADesc)
+{
+ char str_buf[40];
+ strm << " EditRate: " << ADesc.EditRate.Numerator << "/" << ADesc.EditRate.Denominator << std::endl;
+ strm << " ContainerDuration: " << (unsigned) ADesc.ContainerDuration << std::endl;
+ strm << " DataEssenceCoding: " << UL(ADesc.DataEssenceCoding).EncodeString(str_buf, 40) << std::endl;
+ strm << " ImmersiveAudioVersion: " << (unsigned) ADesc.ImmersiveAudioVersion << std::endl;
+ strm << " MaxChannelCount: " << (unsigned) ADesc.MaxChannelCount << std::endl;
+ strm << " MaxObjectCount: " << (unsigned) ADesc.MaxObjectCount << std::endl;
+ strm << " ImmersiveAudioID: " << UUID(ADesc.ImmersiveAudioID).EncodeString(str_buf, 40) << std::endl;
+ strm << " FirstFrame: " << (unsigned) ADesc.FirstFrame << std::endl;
+ return strm;
+}
+
+//
+void
+ASDCP::IAB::IADataEssenceSubDescriptorDump(const IABDescriptor& ADesc, FILE* stream)
+{
+ char str_buf[40];
+ char ImmersiveAudioID_buf[40];
+ if ( stream == 0 )
+ stream = stderr;
+
+ fprintf(stream, "\
+ EditRate: %d/%d\n\
+ ContainerDuration: %u\n\
+ DataEssenceCoding: %s\n\
+ ImmersiveAudioVersion: %u\n\
+ MaxChannelCount: %u\n\
+ MaxObjectCount: %u\n\
+ ImmersiveAudioID: %s\n\
+ FirsFrame: %u\n",
+ ADesc.EditRate.Numerator, ADesc.EditRate.Denominator,
+ ADesc.ContainerDuration,
+ UL(ADesc.DataEssenceCoding).EncodeString(str_buf, 40),
+ ADesc.ImmersiveAudioVersion,
+ ADesc.MaxChannelCount,
+ ADesc.MaxObjectCount,
+ UUID(ADesc.ImmersiveAudioID).EncodeString(ImmersiveAudioID_buf, 40),
+ ADesc.FirstFrame);
+}
+
+//
+bool
+ASDCP::IAB::IsIAB(const std::string& filename)
+{
+ // TODO
+ // For now use an IAB extension
+ bool result = ( 0 == (std::string("atmos").compare(Kumu::PathGetExtension(filename))) );
+ return result;
+}
+
+
+//------------------------------------------------------------------------------------------
+
+typedef std::list<MXF::InterchangeObject*> SubDescriptorList_t;
+
+class ASDCP::IAB::MXFReader::h__Reader : public ASDCP::h__ASDCPReader
+{
+ MXF::IADataEssenceDescriptor* m_EssenceDescriptor;
+ MXF::IADataEssenceSubDescriptor* m_EssenceSubDescriptor;
+
+ KM_NO_COPY_CONSTRUCT(h__Reader);
+ h__Reader();
+
+ public:
+ ASDCP::DCData::DCDataDescriptor m_DDesc;
+ IABDescriptor m_ADesc;
+
+ h__Reader(const Dictionary& d) :
+ ASDCP::h__ASDCPReader(d), m_EssenceDescriptor(0), m_EssenceSubDescriptor(0) {}
+ virtual ~h__Reader() {}
+ Result_t OpenRead(const std::string&);
+ Result_t ReadFrame(ui32_t, FrameBuffer&, AESDecContext*, HMACContext*);
+ Result_t MD_to_DCData_DDesc(ASDCP::DCData::DCDataDescriptor& DDesc);
+ Result_t MD_to_IAB_ADesc(IAB::IABDescriptor& ADesc);
+};
+
+ASDCP::Result_t
+ASDCP::IAB::MXFReader::h__Reader::MD_to_DCData_DDesc(ASDCP::DCData::DCDataDescriptor& DDesc)
+{
+ ASDCP_TEST_NULL(m_EssenceDescriptor);
+ MXF::IADataEssenceDescriptor* DDescObj = m_EssenceDescriptor;
+ DDesc.EditRate = DDescObj->SampleRate;
+ assert(DDescObj->ContainerDuration <= 0xFFFFFFFFL);
+ DDesc.ContainerDuration = static_cast<ui32_t>(DDescObj->ContainerDuration);
+ memcpy(DDesc.DataEssenceCoding, DDescObj->DataEssenceCoding.Value(), SMPTE_UL_LENGTH);
+ return RESULT_OK;
+}
+
+ASDCP::Result_t
+ASDCP::IAB::MXFReader::h__Reader::MD_to_IAB_ADesc(IAB::IABDescriptor& ADesc)
+{
+ ASDCP_TEST_NULL(m_EssenceSubDescriptor);
+ Result_t result = MD_to_DCData_DDesc(ADesc);
+ if( ASDCP_SUCCESS(result) )
+ {
+ MXF::IADataEssenceSubDescriptor* ADescObj = m_EssenceSubDescriptor;
+ ADesc.MaxChannelCount = ADescObj->MaxChannelCount;
+ ADesc.MaxObjectCount = ADescObj->MaxObjectCount;
+ ::memcpy(ADesc.ImmersiveAudioID, ADescObj->ImmersiveAudioID.Value(), UUIDlen);
+ ADesc.ImmersiveAudioVersion = ADescObj->ImmersiveAudioVersion;
+ ADesc.FirstFrame = ADescObj->FirstFrame;
+ }
+ return result;
+}
+
+//
+//
+ASDCP::Result_t
+ASDCP::IAB::MXFReader::h__Reader::OpenRead(const std::string& filename)
+{
+ Result_t result = OpenMXFRead(filename);
+ m_EssenceDescriptor = 0;
+
+ if ( KM_SUCCESS(result) )
+ {
+ InterchangeObject* iObj = 0;
+ result = m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(IADataEssenceDescriptor), &iObj);
+
+ if ( KM_SUCCESS(result) )
+ {
+ m_EssenceDescriptor = static_cast<MXF::IADataEssenceDescriptor*>(iObj);
+ }
+ }
+
+ if ( m_EssenceDescriptor == 0 )
+ {
+ DefaultLogSink().Error("DCDataDescriptor object not found in IAB file.\n");
+ result = RESULT_FORMAT;
+ }
+
+ if ( KM_SUCCESS(result) )
+ {
+ result = MD_to_DCData_DDesc(m_DDesc);
+ }
+
+ // 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_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);
+
+ return RESULT_FORMAT;
+ }
+
+ if( ASDCP_SUCCESS(result) )
+ {
+
+ if (NULL == m_EssenceSubDescriptor)
+ {
+ InterchangeObject* iObj = NULL;
+ result = m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(IADataEssenceSubDescriptor), &iObj);
+ m_EssenceSubDescriptor = static_cast<MXF::IADataEssenceSubDescriptor*>(iObj);
+
+ if ( iObj == 0 )
+ {
+ DefaultLogSink().Error("IADataEssenceSubDescriptor object not found.\n");
+ return RESULT_FORMAT;
+ }
+ }
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ result = MD_to_IAB_ADesc(m_ADesc);
+ }
+ }
+
+ return result;
+}
+
+//
+ASDCP::Result_t
+ASDCP::IAB::MXFReader::h__Reader::ReadFrame(ui32_t FrameNum, FrameBuffer& FrameBuf,
+ AESDecContext* Ctx, HMACContext* HMAC)
+{
+ if ( ! m_File.IsOpen() )
+ return RESULT_INIT;
+
+ assert(m_Dict);
+ return ReadEKLVFrame(FrameNum, FrameBuf, m_Dict->ul(MDD_IADataElement), Ctx, HMAC);
+}
+
+
+//------------------------------------------------------------------------------------------
+
+ASDCP::IAB::MXFReader::MXFReader()
+{
+ m_Reader = new h__Reader(IABSMPTEDict());
+}
+
+
+ASDCP::IAB::MXFReader::~MXFReader()
+{
+ if ( m_Reader && m_Reader->m_File.IsOpen() )
+ m_Reader->Close();
+}
+
+// Warning: direct manipulation of MXF structures can interfere
+// with the normal operation of the wrapper. Caveat emptor!
+//
+ASDCP::MXF::OP1aHeader&
+ASDCP::IAB::MXFReader::OP1aHeader()
+{
+ if ( m_Reader.empty() )
+ {
+ assert(g_OP1aHeader);
+ return *g_OP1aHeader;
+ }
+
+ return m_Reader->m_HeaderPart;
+}
+
+// Warning: direct manipulation of MXF structures can interfere
+// with the normal operation of the wrapper. Caveat emptor!
+//
+ASDCP::MXF::OPAtomIndexFooter&
+ASDCP::IAB::MXFReader::OPAtomIndexFooter()
+{
+ if ( m_Reader.empty() )
+ {
+ assert(g_OPAtomIndexFooter);
+ return *g_OPAtomIndexFooter;
+ }
+
+ return m_Reader->m_IndexAccess;
+}
+
+// Warning: direct manipulation of MXF structures can interfere
+// with the normal operation of the wrapper. Caveat emptor!
+//
+ASDCP::MXF::RIP&
+ASDCP::IAB::MXFReader::RIP()
+{
+ if ( m_Reader.empty() )
+ {
+ assert(g_RIP);
+ return *g_RIP;
+ }
+
+ return m_Reader->m_RIP;
+}
+
+// Open the file for reading. The file must exist. Returns error if the
+// operation cannot be completed.
+ASDCP::Result_t
+ASDCP::IAB::MXFReader::OpenRead(const std::string& filename) const
+{
+ return m_Reader->OpenRead(filename);
+}
+
+//
+ASDCP::Result_t
+ASDCP::IAB::MXFReader::ReadFrame(ui32_t FrameNum, DCData::FrameBuffer& FrameBuf,
+ AESDecContext* Ctx, HMACContext* HMAC) const
+{
+ if ( m_Reader && m_Reader->m_File.IsOpen() )
+ return m_Reader->ReadFrame(FrameNum, FrameBuf, Ctx, HMAC);
+
+ return RESULT_INIT;
+}
+
+ASDCP::Result_t
+ASDCP::IAB::MXFReader::LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const
+{
+ return m_Reader->LocateFrame(FrameNum, streamOffset, temporalOffset, keyFrameOffset);
+}
+
+
+// Fill the struct with the values from the file's header.
+// Returns RESULT_INIT if the file is not open.
+ASDCP::Result_t
+ASDCP::IAB::MXFReader::FillIABDescriptor(IABDescriptor& ADesc) const
+{
+ if ( m_Reader && m_Reader->m_File.IsOpen() )
+ {
+ ADesc = m_Reader->m_ADesc;
+ return RESULT_OK;
+ }
+
+ return RESULT_INIT;
+}
+
+
+// Fill the struct with the values from the file's header.
+// Returns RESULT_INIT if the file is not open.
+ASDCP::Result_t
+ASDCP::IAB::MXFReader::FillWriterInfo(WriterInfo& Info) const
+{
+ if ( m_Reader && m_Reader->m_File.IsOpen() )
+ {
+ Info = m_Reader->m_Info;
+ return RESULT_OK;
+ }
+
+ return RESULT_INIT;
+}
+
+//
+void
+ASDCP::IAB::MXFReader::DumpHeaderMetadata(FILE* stream) const
+{
+ if ( m_Reader->m_File.IsOpen() )
+ m_Reader->m_HeaderPart.Dump(stream);
+}
+
+//
+void
+ASDCP::IAB::MXFReader::DumpIndex(FILE* stream) const
+{
+ if ( m_Reader->m_File.IsOpen() )
+ m_Reader->m_IndexAccess.Dump(stream);
+}
+
+//
+ASDCP::Result_t
+ASDCP::IAB::MXFReader::Close() const
+{
+ if ( m_Reader && m_Reader->m_File.IsOpen() )
+ {
+ m_Reader->Close();
+ return RESULT_OK;
+ }
+
+ return RESULT_INIT;
+}
+
+
+//------------------------------------------------------------------------------------------
+
+//
+class ASDCP::IAB::MXFWriter::h__Writer : public ASDCP::h__ASDCPWriter
+{
+ ASDCP::DCData::DCDataDescriptor m_DDesc;
+ byte_t m_EssenceUL[SMPTE_UL_LENGTH];
+ MXF::IADataEssenceSubDescriptor* m_EssenceSubDescriptor;
+
+ ASDCP_NO_COPY_CONSTRUCT(h__Writer);
+ h__Writer();
+
+ public:
+ IABDescriptor m_ADesc;
+
+ h__Writer(const Dictionary& d) : ASDCP::h__ASDCPWriter(d),
+ m_EssenceSubDescriptor(0), m_ADesc() {
+ memset(m_EssenceUL, 0, SMPTE_UL_LENGTH);
+ }
+
+ virtual ~h__Writer(){}
+
+ Result_t OpenWrite(const std::string&, ui32_t HeaderSize, const IABDescriptor& ADesc);
+ Result_t SetSourceStream(const DCData::DCDataDescriptor&, const byte_t*, const std::string&, const std::string&);
+ Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0);
+ Result_t Finalize();
+ Result_t DCData_DDesc_to_MD(ASDCP::DCData::DCDataDescriptor& DDesc);
+ Result_t IAB_ADesc_to_MD(const IABDescriptor& ADesc);
+};
+
+//
+ASDCP::Result_t
+ASDCP::IAB::MXFWriter::h__Writer::DCData_DDesc_to_MD(ASDCP::DCData::DCDataDescriptor& DDesc)
+{
+ ASDCP_TEST_NULL(m_EssenceDescriptor);
+ MXF::IADataEssenceDescriptor* DDescObj = static_cast<MXF::IADataEssenceDescriptor *>(m_EssenceDescriptor);
+
+ DDescObj->SampleRate = DDesc.EditRate;
+ DDescObj->ContainerDuration = DDesc.ContainerDuration;
+ DDescObj->DataEssenceCoding.Set(DDesc.DataEssenceCoding);
+ return RESULT_OK;
+}
+
+//
+ASDCP::Result_t
+ASDCP::IAB::MXFWriter::h__Writer::IAB_ADesc_to_MD(const IABDescriptor& ADesc)
+{
+ ASDCP_TEST_NULL(m_EssenceDescriptor);
+ ASDCP_TEST_NULL(m_EssenceSubDescriptor);
+ MXF::IADataEssenceSubDescriptor * ADescObj = m_EssenceSubDescriptor;
+ ADescObj->MaxChannelCount = ADesc.MaxChannelCount;
+ ADescObj->MaxObjectCount = ADesc.MaxObjectCount;
+ ADescObj->ImmersiveAudioID.Set(ADesc.ImmersiveAudioID);
+ ADescObj->ImmersiveAudioVersion = ADesc.ImmersiveAudioVersion;
+ ADescObj->FirstFrame = ADesc.FirstFrame;
+ return RESULT_OK;
+}
+
+//
+ASDCP::Result_t
+ASDCP::IAB::MXFWriter::h__Writer::OpenWrite(const std::string& filename, ui32_t HeaderSize, const IABDescriptor& ADesc)
+{
+ if ( ! m_State.Test_BEGIN() )
+ return RESULT_STATE;
+
+ Result_t result = m_File.OpenWrite(filename);
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ m_HeaderSize = HeaderSize;
+ m_EssenceDescriptor = new MXF::IADataEssenceDescriptor(m_Dict);
+ m_EssenceSubDescriptor = new IADataEssenceSubDescriptor(m_Dict);
+ SubDescriptorList_t subDescriptors;
+ subDescriptors.push_back(m_EssenceSubDescriptor);
+
+ SubDescriptorList_t::const_iterator sDObj;
+ SubDescriptorList_t::const_iterator lastDescriptor = subDescriptors.end();
+ for (sDObj = subDescriptors.begin(); sDObj != lastDescriptor; ++sDObj)
+ {
+ m_EssenceSubDescriptorList.push_back(*sDObj);
+ GenRandomValue((*sDObj)->InstanceUID);
+ m_EssenceDescriptor->SubDescriptors.push_back((*sDObj)->InstanceUID);
+ }
+ result = m_State.Goto_INIT();
+ }
+
+ if ( ASDCP_FAILURE(result) )
+ delete m_EssenceSubDescriptor;
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ m_ADesc = ADesc;
+ memcpy(m_ADesc.DataEssenceCoding, IAB_ESSENCE_CODING, SMPTE_UL_LENGTH);
+ result = IAB_ADesc_to_MD(m_ADesc);
+ }
+
+ return result;
+}
+
+//
+ASDCP::Result_t
+ASDCP::IAB::MXFWriter::h__Writer::SetSourceStream(ASDCP::DCData::DCDataDescriptor const& DDesc,
+ const byte_t * essenceCoding,
+ const std::string& packageLabel,
+ const std::string& defLabel)
+{
+ if ( ! m_State.Test_INIT() )
+ return RESULT_STATE;
+
+ if ( DDesc.EditRate != EditRate_24
+ && DDesc.EditRate != EditRate_25
+ && DDesc.EditRate != EditRate_30
+ && DDesc.EditRate != EditRate_48
+ && DDesc.EditRate != EditRate_50
+ && DDesc.EditRate != EditRate_60
+ && DDesc.EditRate != EditRate_96
+ && DDesc.EditRate != EditRate_100
+ && 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);
+ return RESULT_RAW_FORMAT;
+ }
+
+ assert(m_Dict);
+ m_DDesc = DDesc;
+ if (NULL != essenceCoding)
+ memcpy(m_DDesc.DataEssenceCoding, essenceCoding, SMPTE_UL_LENGTH);
+ Result_t result = DCData_DDesc_to_MD(m_DDesc);
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ memcpy(m_EssenceUL, m_Dict->ul(MDD_IADataElement), SMPTE_UL_LENGTH);
+ m_EssenceUL[SMPTE_UL_LENGTH-1] = 1; // first (and only) essence container
+ result = m_State.Goto_READY();
+ }
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ ui32_t TCFrameRate = m_DDesc.EditRate.Numerator;
+
+ result = WriteASDCPHeader(packageLabel, UL(m_Dict->ul(MDD_MXF_GC_IAData_Frame_Wrapped)),
+ defLabel, UL(m_EssenceUL), UL(m_Dict->ul(MDD_DataDataDef)),
+ m_DDesc.EditRate, TCFrameRate);
+ }
+
+ return result;
+}
+
+//
+ASDCP::Result_t
+ASDCP::IAB::MXFWriter::h__Writer::WriteFrame(const FrameBuffer& FrameBuf,
+ ASDCP::AESEncContext* Ctx, ASDCP::HMACContext* HMAC)
+{
+ Result_t result = RESULT_OK;
+
+ if ( m_State.Test_READY() )
+ result = m_State.Goto_RUNNING(); // first time through
+
+ ui64_t StreamOffset = m_StreamOffset;
+
+ if ( ASDCP_SUCCESS(result) )
+ result = WriteEKLVPacket(FrameBuf, m_EssenceUL, MXF_BER_LENGTH, Ctx, HMAC);
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ IndexTableSegment::IndexEntry Entry;
+ Entry.StreamOffset = StreamOffset;
+ m_FooterPart.PushIndexEntry(Entry);
+ m_FramesWritten++;
+ }
+ return result;
+}
+
+// Closes the MXF file, writing the index and other closing information.
+//
+ASDCP::Result_t
+ASDCP::IAB::MXFWriter::h__Writer::Finalize()
+{
+ if ( ! m_State.Test_RUNNING() )
+ return RESULT_STATE;
+
+ m_State.Goto_FINAL();
+
+ return WriteASDCPFooter();
+}
+
+
+
+//------------------------------------------------------------------------------------------
+
+ASDCP::IAB::MXFWriter::MXFWriter()
+{
+}
+
+ASDCP::IAB::MXFWriter::~MXFWriter()
+{
+}
+
+// Warning: direct manipulation of MXF structures can interfere
+// with the normal operation of the wrapper. Caveat emptor!
+//
+ASDCP::MXF::OP1aHeader&
+ASDCP::IAB::MXFWriter::OP1aHeader()
+{
+ if ( m_Writer.empty() )
+ {
+ assert(g_OP1aHeader);
+ return *g_OP1aHeader;
+ }
+
+ return m_Writer->m_HeaderPart;
+}
+
+// Warning: direct manipulation of MXF structures can interfere
+// with the normal operation of the wrapper. Caveat emptor!
+//
+ASDCP::MXF::OPAtomIndexFooter&
+ASDCP::IAB::MXFWriter::OPAtomIndexFooter()
+{
+ if ( m_Writer.empty() )
+ {
+ assert(g_OPAtomIndexFooter);
+ return *g_OPAtomIndexFooter;
+ }
+
+ return m_Writer->m_FooterPart;
+}
+
+// Warning: direct manipulation of MXF structures can interfere
+// with the normal operation of the wrapper. Caveat emptor!
+//
+ASDCP::MXF::RIP&
+ASDCP::IAB::MXFWriter::RIP()
+{
+ if ( m_Writer.empty() )
+ {
+ assert(g_RIP);
+ return *g_RIP;
+ }
+
+ return m_Writer->m_RIP;
+}
+
+// Open the file for writing. The file must not exist. Returns error if
+// the operation cannot be completed.
+ASDCP::Result_t
+ASDCP::IAB::MXFWriter::OpenWrite(const std::string& filename, const WriterInfo& Info,
+ const IABDescriptor& ADesc, ui32_t HeaderSize)
+{
+ if ( Info.LabelSetType != LS_MXF_SMPTE )
+ {
+ DefaultLogSink().Error("IAB support requires LS_MXF_SMPTE\n");
+ return RESULT_FORMAT;
+ }
+
+ m_Writer = new h__Writer(IABSMPTEDict());
+ m_Writer->m_Info = Info;
+
+ Result_t result = m_Writer->OpenWrite(filename, HeaderSize, ADesc);
+
+ if ( ASDCP_SUCCESS(result) )
+ result = m_Writer->SetSourceStream(ADesc, IAB_ESSENCE_CODING, IAB_PACKAGE_LABEL,
+ IAB_DEF_LABEL);
+
+ if ( ASDCP_FAILURE(result) )
+ m_Writer.release();
+
+ return result;
+}
+
+// Writes a frame of essence to the MXF file. If the optional AESEncContext
+// argument is present, the essence is encrypted prior to writing.
+// Fails if the file is not open, is finalized, or an operating system
+// error occurs.
+ASDCP::Result_t
+ASDCP::IAB::MXFWriter::WriteFrame(const DCData::FrameBuffer& FrameBuf, AESEncContext* Ctx, HMACContext* HMAC)
+{
+ if ( m_Writer.empty() )
+ return RESULT_INIT;
+
+ return m_Writer->WriteFrame(FrameBuf, Ctx, HMAC);
+}
+
+// Closes the MXF file, writing the index and other closing information.
+ASDCP::Result_t
+ASDCP::IAB::MXFWriter::Finalize()
+{
+ if ( m_Writer.empty() )
+ return RESULT_INIT;
+
+ return m_Writer->Finalize();
+}
+
+
+//
+// end AS_DCP_IAB.cpp
+//
+
+