diff options
| author | jelkins <jelkins@cinecert.com> | 2020-10-08 09:49:48 -0700 |
|---|---|---|
| committer | jelkins <jelkins@cinecert.com> | 2020-10-08 09:49:48 -0700 |
| commit | ee40718aa383cb40beb67be317b3565c218d32c1 (patch) | |
| tree | d2bd150d132a7dbf8c6bbe0dd6ca0c001292158c | |
| parent | 6b98e08246b5b6a191152e3a3a4a69b459d1ae35 (diff) | |
| parent | d417531ed59434ecaee487adfdf54646408479bf (diff) | |
Merge branch 'master' of https://github.com/Jason-elkins/asdcplib into check_optional_values_arent_empty
41 files changed, 1549 insertions, 71 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..8a2da82 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,39 @@ +name: CI + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build_ubuntu_autoconf: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: autoreconf + run: autoreconf -if + - name: configure + run: ./configure --enable-as-02 + - name: make + run: make + + build_ubuntu_cmake: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: dependencies + run: sudo apt-get update && sudo apt-get install -y + libxerces-c-dev + - name: Create build dir + run: mkdir build + - name: cmake + working-directory: build + run: cmake .. + - name: make + working-directory: build + run: make @@ -56,9 +56,9 @@ auto-tooled version by untarring the distribution and running ```sh autoreconf -if -./configure --enable-freedist --enable-as-02 +./configure --enable-as-02 make -make dist +make install ``` ## Libraries diff --git a/configure.ac b/configure.ac index 24e42b3..8bbcaa6 100644 --- a/configure.ac +++ b/configure.ac @@ -136,5 +136,5 @@ AC_CHECK_LIB([pthread], [pthread_create]) AC_CONFIG_FILES([Makefile src/Makefile win32/Makefile - win32/Makefile.mak:win32/Makefile.wmk]) + win32/Makefile.mak:win32/Makefile32.wmk]) AC_OUTPUT diff --git a/m4/ax_lib_openssl.m4 b/m4/ax_lib_openssl.m4 index 8a70f99..a7f69f0 100644 --- a/m4/ax_lib_openssl.m4 +++ b/m4/ax_lib_openssl.m4 @@ -237,7 +237,7 @@ SSLeay(); if test -f "$openssl_include_dir/openssl/opensslv.h"; then OPENSSL_VERSION=`grep OPENSSL_VERSION_TEXT $openssl_include_dir/openssl/opensslv.h \ - | grep -v fips | grep -v PTEXT | cut -f 2 | tr -d \"` + | grep -v fips | grep -v PTEXT | sed -e 's/[ ][ ][ ]*/\t/g' | cut -f 2 | tr -d \"` AC_SUBST([OPENSSL_VERSION]) dnl Decompose required version string and calculate numerical representation @@ -259,7 +259,7 @@ SSLeay(); \+ $((0xf))` dnl Calculate numerical representation of detected version - openssl_version_number=`expr $(($(grep OPENSSL_VERSION_NUMBER $openssl_include_dir/openssl/opensslv.h | cut -f 2 | tr -d L)))` + openssl_version_number=`expr $(($(grep OPENSSL_VERSION_NUMBER $openssl_include_dir/openssl/opensslv.h | sed -e 's/[ ][ ][ ]*/\t/g' | cut -f 2 | tr -d L)))` openssl_version_check=`expr $openssl_version_number \>\= $openssl_version_req_number` if test "$openssl_version_check" = "1"; then diff --git a/registers/dolby/ASDCP-PHDR-elements.xml b/registers/dolby/ASDCP-PHDR-elements.xml new file mode 100644 index 0000000..eaa0972 --- /dev/null +++ b/registers/dolby/ASDCP-PHDR-elements.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="utf-8"?>
+<!-- Metadata tags to support XML file editing -->
+<!-- author= Raymond Yeung (raymond.yeung@dolby.com) -->
+<ElementsRegister xmlns="http://www.smpte-ra.org/schemas/335/2012">
+ <Entries>
+ <Entry>
+ <Register>Elements</Register>
+ <NamespaceName>http://www.smpte-ra.org/reg/335/2012/14/9</NamespaceName>
+ <Symbol>DataDefinition</Symbol>
+ <UL>urn:smpte:ul:060e2b34.01010105.0e090607.01010104</UL>
+ <Kind>LEAF</Kind>
+ <Name>Data Definition</Name>
+ <Definition>Identifies the value of PHDR Data Definition</Definition>
+ <DefiningDocument>ASDCP</DefiningDocument>
+ <IsDeprecated>false</IsDeprecated>
+ <ContextScope>UnknownContext</ContextScope>
+ <Type>urn:smpte:ul:060e2b34.01040101.04011100.00000000</Type>
+ <ValueLength>16 bytes</ValueLength>
+ </Entry>
+ <Entry>
+ <Register>Elements</Register>
+ <NamespaceName>http://www.smpte-ra.org/reg/335/2012/14/9</NamespaceName>
+ <Symbol>SourceTrackID</Symbol>
+ <UL>urn:smpte:ul:060e2b34.01010105.0e090607.01010105</UL>
+ <Kind>LEAF</Kind>
+ <Name>Source Track ID</Name>
+ <Definition>Identifies the Source Track ID of the PHDR Data Items</Definition>
+ <DefiningDocument>ASDCP</DefiningDocument>
+ <IsDeprecated>false</IsDeprecated>
+ <ContextScope>UnknownContext</ContextScope>
+ <Type>urn:smpte:ul:060e2b34.01040101.01010300.00000000</Type>
+ <ValueLength>4 bytes</ValueLength>
+ </Entry>
+ <Entry>
+ <Register>Elements</Register>
+ <NamespaceName>http://www.smpte-ra.org/reg/335/2012/14/9</NamespaceName>
+ <Symbol>SimplePayloadSID</Symbol>
+ <UL>urn:smpte:ul:060e2b34.01010105.0e090607.01010106</UL>
+ <Kind>LEAF</Kind>
+ <Name>Simple Payload SID</Name>
+ <Definition>Identifies the Source Track ID of the ST 410 GSP as static data</Definition>
+ <DefiningDocument>ASDCP</DefiningDocument>
+ <IsDeprecated>false</IsDeprecated>
+ <ContextScope>UnknownContext</ContextScope>
+ <Type>urn:smpte:ul:060e2b34.01040101.01010300.00000000</Type>
+ <ValueLength>4 bytes</ValueLength>
+ </Entry>
+ </Entries>
+</ElementsRegister>
diff --git a/registers/dolby/ASDCP-PHDR-essence-keys.xml b/registers/dolby/ASDCP-PHDR-essence-keys.xml new file mode 100644 index 0000000..8db3acf --- /dev/null +++ b/registers/dolby/ASDCP-PHDR-essence-keys.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?>
+<!-- Metadata tags to support XML file editing -->
+<!-- author= Raymond Yeung (raymond.yeung@dolby.com) -->
+<EssenceRegister xmlns="http://www.smpte-ra.org/schemas/2088/2019">
+ <Entries>
+ <Entry>
+ <Register>Essence</Register>
+ <NamespaceName>http://www.smpte-ra.org/reg/2088/2019/14/9</NamespaceName>
+ <Symbol>PHDRImageMetadataItem</Symbol>
+ <UL>urn:smpte:ul:060e2b34.01020105.0e090607.01010100</UL>
+ <Kind>LEAF</Kind>
+ <Name>PHDR Image Metadata Item</Name>
+ <Definition>Identifies a PHDR image metadata item</Definition>
+ <Notes>**PROPOSED**</Notes>
+ <DefiningDocument>ASDCP</DefiningDocument>
+ <IsDeprecated>false</IsDeprecated>
+ </Entry>
+ </Entries>
+</EssenceRegister>
diff --git a/registers/dolby/ASDCP-PHDR-groups.xml b/registers/dolby/ASDCP-PHDR-groups.xml new file mode 100644 index 0000000..3bd49e1 --- /dev/null +++ b/registers/dolby/ASDCP-PHDR-groups.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?>
+<!-- Metadata tags to support XML file editing -->
+<!-- author= Raymond Yeung (raymond.yeung@dolby.com) -->
+<GroupsRegister xmlns="http://www.smpte-ra.org/ns/395/2016">
+ <Entries>
+ <Entry>
+ <Register>Groups</Register>
+ <NamespaceName>http://www.smpte-ra.org/reg/395/2014/14/9</NamespaceName>
+ <Symbol>PHDRMetadataTrackSubDescriptor</Symbol>
+ <UL>urn:smpte:ul:060e2b34.027f0105.0e090607.01010103</UL>
+ <Kind>LEAF</Kind>
+ <Name>PHDR Metadata Track Sub Descriptor</Name>
+ <Definition>Identifies a PHDR Metadata Track Sub Descriptor</Definition>
+ <DefiningDocument>ASDCP</DefiningDocument>
+ <IsDeprecated>false</IsDeprecated>
+ <Parent>urn:smpte:ul:060e2b34.027f0101.0d010101.01015900</Parent>
+ <IsConcrete>true</IsConcrete>
+ <KLVSyntax>06 53</KLVSyntax>
+ <Contents>
+ <Record>
+ <UL>urn:smpte:ul:060e2b34.01010105.0e090607.01010104</UL>
+ <IsOptional>false</IsOptional>
+ </Record>
+ <Record>
+ <UL>urn:smpte:ul:060e2b34.01010105.0e090607.01010105</UL>
+ <IsOptional>false</IsOptional>
+ </Record>
+ <Record>
+ <UL>urn:smpte:ul:060e2b34.01010105.0e090607.01010106</UL>
+ <IsOptional>false</IsOptional>
+ </Record>
+ </Contents>
+ </Entry>
+ </Entries>
+</GroupsRegister>
diff --git a/registers/dolby/ASDCP-PHDR-labels.xml b/registers/dolby/ASDCP-PHDR-labels.xml new file mode 100644 index 0000000..bcae150 --- /dev/null +++ b/registers/dolby/ASDCP-PHDR-labels.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?>
+<!-- Metadata tags to support XML file editing -->
+<!-- author= Raymond Yeung (raymond.yeung@dolby.com) -->
+<LabelsRegister xmlns="http://www.smpte-ra.org/schemas/400/2012">
+ <Entries>
+ <Entry>
+ <Register>Labels</Register>
+ <NamespaceName>http://www.smpte-ra.org/reg/400/2012/14/9</NamespaceName>
+ <Symbol>PHDRImageMetadataWrappingFrame</Symbol>
+ <UL>urn:smpte:ul:060e2b34.04010105.0e090607.01010101</UL>
+ <Kind>LEAF</Kind>
+ <Name>PHDR Image Metadata Wrapping Frame</Name>
+ <Definition>Identifies a frame of wrapped PHDR image metadata</Definition>
+ <DefiningDocument>ASDCP</DefiningDocument>
+ <IsDeprecated>false</IsDeprecated>
+ </Entry>
+ </Entries>
+</LabelsRegister>
diff --git a/registers/dolby/RDD47-ISXD-elements.xml b/registers/dolby/RDD47-ISXD-elements.xml new file mode 100644 index 0000000..519f892 --- /dev/null +++ b/registers/dolby/RDD47-ISXD-elements.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?>
+<!-- Metadata tags to support XML file editing -->
+<!-- author= Raymond Yeung (raymond.yeung@dolby.com) -->
+<ElementsRegister xmlns="http://www.smpte-ra.org/schemas/335/2012">
+ <Entries>
+ <Entry>
+ <Register>Elements</Register>
+ <NamespaceName>http://www.smpte-ra.org/reg/335/2012/14/9</NamespaceName>
+ <Symbol>NamespaceURI</Symbol>
+ <UL>urn:smpte:ul:060e2b34.01010105.0e090400.00000000</UL>
+ <Kind>LEAF</Kind>
+ <Name>Namespace URI</Name>
+ <Definition>Identifies the default namespace of the essence XML documents</Definition>
+ <DefiningDocument>RDD47</DefiningDocument>
+ <IsDeprecated>false</IsDeprecated>
+ <ContextScope>UnknownContext</ContextScope>
+ <Type>urn:smpte:ul:060e2b34.01040101.01100600.00000000</Type>
+ <ValueLength>variable</ValueLength>
+ </Entry>
+ </Entries>
+</ElementsRegister>
diff --git a/registers/dolby/RDD47-ISXD-essence-keys.xml b/registers/dolby/RDD47-ISXD-essence-keys.xml new file mode 100644 index 0000000..7e6acb2 --- /dev/null +++ b/registers/dolby/RDD47-ISXD-essence-keys.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?>
+<!-- Metadata tags to support XML file editing -->
+<!-- author= Raymond Yeung (raymond.yeung@dolby.com) -->
+<EssenceRegister xmlns="http://www.smpte-ra.org/schemas/2088/2019">
+ <Entries>
+ <Entry>
+ <Register>Essence</Register>
+ <NamespaceName>http://www.smpte-ra.org/reg/2088/2019/14/9</NamespaceName>
+ <Symbol>FrameWrappedISXDData</Symbol>
+ <UL>urn:smpte:ul:060e2b34.01020105.0e090502.017f017f</UL>
+ <Kind>LEAF</Kind>
+ <Name>Frame Wrapped ISXD Data</Name>
+ <Definition>Identifies Frame Wrapped ISXD Data Essence</Definition>
+ <Notes>**PROPOSED**</Notes>
+ <DefiningDocument>SMPTE RDD 47</DefiningDocument>
+ <IsDeprecated>false</IsDeprecated>
+ </Entry>
+ </Entries>
+</EssenceRegister>
diff --git a/registers/dolby/RDD47-ISXD-groups.xml b/registers/dolby/RDD47-ISXD-groups.xml new file mode 100644 index 0000000..d2f6fd8 --- /dev/null +++ b/registers/dolby/RDD47-ISXD-groups.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?>
+<!-- Metadata tags to support XML file editing -->
+<!-- author= Raymond Yeung (raymond.yeung@dolby.com) -->
+<GroupsRegister xmlns="http://www.smpte-ra.org/ns/395/2016">
+ <Entries>
+ <Entry>
+ <Register>Groups</Register>
+ <NamespaceName>http://www.smpte-ra.org/reg/395/2014/14/9</NamespaceName>
+ <Symbol>ISXDDataEssenceDescriptor</Symbol>
+ <UL>urn:smpte:ul:060e2b34.027f0105.0e090502.00000000</UL>
+ <Kind>LEAF</Kind>
+ <Name>ISXD Data Essence Descriptor</Name>
+ <Definition>Identifies an ISXD Data Essence Descriptor</Definition>
+ <DefiningDocument>RDD47</DefiningDocument>
+ <IsDeprecated>false</IsDeprecated>
+ <Parent>urn:smpte:ul:060e2b34.027f0101.0d010101.01012400</Parent>
+ <IsConcrete>true</IsConcrete>
+ <KLVSyntax>06 53</KLVSyntax>
+ <Contents>
+ <Record>
+ <UL>urn:smpte:ul:060e2b34.01010105.0e090400.00000000</UL>
+ <IsOptional>false</IsOptional>
+ </Record>
+ </Contents>
+ </Entry>
+ </Entries>
+</GroupsRegister>
diff --git a/registers/dolby/RDD47-ISXD-labels.xml b/registers/dolby/RDD47-ISXD-labels.xml new file mode 100644 index 0000000..f4d6e2e --- /dev/null +++ b/registers/dolby/RDD47-ISXD-labels.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?>
+<!-- Metadata tags to support XML file editing -->
+<!-- author= Raymond Yeung (raymond.yeung@dolby.com) -->
+<LabelsRegister xmlns="http://www.smpte-ra.org/schemas/400/2012">
+ <Entries>
+ <Entry>
+ <Register>Labels</Register>
+ <NamespaceName>http://www.smpte-ra.org/reg/400/2012/14/9</NamespaceName>
+ <Symbol>FrameWrappedISXDContainer</Symbol>
+ <UL>urn:smpte:ul:060e2b34.04010105.0e090607.01010103</UL>
+ <Kind>LEAF</Kind>
+ <Name>Frame Wrapped ISXD Container</Name>
+ <Definition>Identifies Frame Wrapped ISXD Container</Definition>
+ <DefiningDocument>RDD47</DefiningDocument>
+ <IsDeprecated>false</IsDeprecated>
+ </Entry>
+ <Entry>
+ <Register>Labels</Register>
+ <NamespaceName>http://www.smpte-ra.org/reg/400/2012/14/9</NamespaceName>
+ <Symbol>UTF8TextDataEssenceCoding</Symbol>
+ <UL>urn:smpte:ul:060e2b34.04010105.0e090606.00000000</UL>
+ <Kind>LEAF</Kind>
+ <Name>UTF-8 Text Data Essence Coding</Name>
+ <Definition>Identifies UTF-8 Text Data Essence Coding</Definition>
+ <DefiningDocument>RDD47</DefiningDocument>
+ <IsDeprecated>false</IsDeprecated>
+ </Entry>
+ </Entries>
+</LabelsRegister>
diff --git a/registers/readme.md b/registers/readme.md new file mode 100644 index 0000000..86b5def --- /dev/null +++ b/registers/readme.md @@ -0,0 +1,5 @@ + +# Ancillary Registers + +This directory contains XML register files that are compatible with SMPTE 2001-1 "XML Representation of SMPTE Registered Data (Reg-XML) — Mapping Rules" and SMPTE 2001-2 "XML Representation of SMPTE Registered Data (Reg-XML) — AAF and MXF Data". These files contain register entries that are not appropriate for distribution via the standard [registers](https://registry.smpte-ra.org/) published by SMPTE because they are defined in private namespaces or are in some other way incompatible with the SMPTE Engineering Document process. Nonetheless these values are in use in the industry, including their use in asdcplib, and so they are distributed here with permission from the original publisher. + diff --git a/src/AS_02_ACES.cpp b/src/AS_02_ACES.cpp index 9a847cc..876af18 100644 --- a/src/AS_02_ACES.cpp +++ b/src/AS_02_ACES.cpp @@ -603,7 +603,7 @@ AS_02::Result_t AS_02::ACES::MXFWriter::h__Writer::SetSourceStream(const std::st { result = WriteAS02Header(label, UL(m_Dict->ul(MDD_MXFGCFrameWrappedACESPictures)), //Essence Container Label per 2065-5 section 8.1 (frame wrapping) PICT_DEF_LABEL, UL(m_EssenceUL), UL(m_Dict->ul(MDD_PictureDataDef)), - edit_rate, derive_timecode_rate_from_edit_rate(edit_rate)); + edit_rate); if(KM_SUCCESS(result)) { diff --git a/src/AS_02_IAB.cpp b/src/AS_02_IAB.cpp new file mode 100644 index 0000000..e7c1fc6 --- /dev/null +++ b/src/AS_02_IAB.cpp @@ -0,0 +1,629 @@ +/* +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() {} + }; +} + +//------------------------------------------------------------------------------------------ + +/* Size of the BER Length of the clip */ +static const int CLIP_BER_LENGTH_SIZE = 8; + +/* Combined size of the Key and Length of the clip */ +static const int RESERVED_KL_SIZE = ASDCP::SMPTE_UL_LENGTH + CLIP_BER_LENGTH_SIZE; + + +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; + + /* only a single element */ + + element_ul_bytes[13] = 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, + &conformsToSpecs + ); + + if (result.Failure()) { + throw Kumu::RuntimeError(result); + } + + /* start the clip */ + + this->m_ClipStart = this->m_Writer->m_File.Tell(); + + /* reserve space for the KL of the KLV, which will be written later during finalization */ + + byte_t clip_buffer[RESERVED_KL_SIZE] = { 0 }; + + memcpy(clip_buffer, element_ul_bytes, ASDCP::SMPTE_UL_LENGTH); + + if (!Kumu::write_BER(clip_buffer + ASDCP::SMPTE_UL_LENGTH, 0, CLIP_BER_LENGTH_SIZE)) { + throw Kumu::RuntimeError(Kumu::RESULT_FAIL); + } + + result = this->m_Writer->m_File.Write(clip_buffer, RESERVED_KL_SIZE); + + if (result.Failure()) { + throw Kumu::RuntimeError(result); + } + + this->m_Writer->m_StreamOffset = RESERVED_KL_SIZE; + + 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 + ASDCP::SMPTE_UL_LENGTH); + + byte_t clip_buffer[CLIP_BER_LENGTH_SIZE] = { 0 }; + + ui64_t size = static_cast<ui64_t>(this->m_Writer->m_StreamOffset) /* total size of the KLV */ - RESERVED_KL_SIZE; + + bool check = Kumu::write_BER(clip_buffer, size, CLIP_BER_LENGTH_SIZE); + + if (!check) { + throw Kumu::RuntimeError(Kumu::RESULT_FAIL); + } + + result = this->m_Writer->m_File.Write(clip_buffer, CLIP_BER_LENGTH_SIZE); + + 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_ISXD.cpp b/src/AS_02_ISXD.cpp index 6230c58..a374664 100644 --- a/src/AS_02_ISXD.cpp +++ b/src/AS_02_ISXD.cpp @@ -338,7 +338,7 @@ AS_02::ISXD::MXFWriter::h__Writer::SetSourceStream(const std::string& label, con { result = WriteAS02Header(label, UL(m_Dict->ul(MDD_FrameWrappedISXDContainer)), PICT_DEF_LABEL, UL(m_EssenceUL), UL(m_Dict->ul(MDD_DataDataDef)), - edit_rate, derive_timecode_rate_from_edit_rate(edit_rate)); + edit_rate); if ( KM_SUCCESS(result) ) { diff --git a/src/AS_02_JP2K.cpp b/src/AS_02_JP2K.cpp index 321abfc..ac951e4 100644 --- a/src/AS_02_JP2K.cpp +++ b/src/AS_02_JP2K.cpp @@ -363,7 +363,7 @@ AS_02::JP2K::MXFWriter::h__Writer::SetSourceStream(const std::string& label, con result = WriteAS02Header(label, wrapping_label, PICT_DEF_LABEL, UL(m_EssenceUL), UL(m_Dict->ul(MDD_PictureDataDef)), - edit_rate, derive_timecode_rate_from_edit_rate(edit_rate)); + edit_rate); if ( KM_SUCCESS(result) ) { diff --git a/src/AS_02_PCM.cpp b/src/AS_02_PCM.cpp index 8532887..aa7b2a2 100644 --- a/src/AS_02_PCM.cpp +++ b/src/AS_02_PCM.cpp @@ -423,7 +423,7 @@ AS_02::PCM::MXFWriter::h__Writer::SetSourceStream(const ASDCP::Rational& edit_ra m_BytesPerSample = AS_02::MXF::CalcSampleSize(*m_WaveAudioDescriptor); result = WriteAS02Header(PCM_PACKAGE_LABEL, UL(m_Dict->ul(MDD_WAVWrappingClip)), SOUND_DEF_LABEL, UL(m_EssenceUL), UL(m_Dict->ul(MDD_SoundDataDef)), - m_EssenceDescriptor->SampleRate, derive_timecode_rate_from_edit_rate(edit_rate)); + m_EssenceDescriptor->SampleRate); if ( KM_SUCCESS(result) ) { diff --git a/src/AS_02_PHDR.cpp b/src/AS_02_PHDR.cpp index c08efd0..471d226 100644 --- a/src/AS_02_PHDR.cpp +++ b/src/AS_02_PHDR.cpp @@ -349,8 +349,7 @@ class AS_02::PHDR::MXFWriter::h__Writer : public AS_02::h__AS02WriterFrame Result_t WritePHDRHeader(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 ui32_t& TCFrameRate); + const ASDCP::UL& DataDefinition, const ASDCP::Rational& EditRate); public: byte_t m_EssenceUL[SMPTE_UL_LENGTH]; @@ -436,8 +435,7 @@ AS_02::PHDR::MXFWriter::h__Writer::OpenWrite(const std::string& filename, Result_t AS_02::PHDR::MXFWriter::h__Writer::WritePHDRHeader(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 ui32_t& TCFrameRate) + const ASDCP::UL& DataDefinition, const ASDCP::Rational& EditRate) { if ( EditRate.Numerator == 0 || EditRate.Denominator == 0 ) { @@ -447,7 +445,7 @@ AS_02::PHDR::MXFWriter::h__Writer::WritePHDRHeader(const std::string& PackageLab InitHeader(MXFVersion_2011); - AddSourceClip(EditRate, EditRate/*TODO: for a moment*/, TCFrameRate, TrackName, EssenceUL, DataDefinition, PackageLabel); + AddSourceClip(EditRate, EditRate/*TODO: for a moment*/, 0 /*no timecode track*/, TrackName, EssenceUL, DataDefinition, PackageLabel); // add metadata track TrackSet<SourceClip> metdata_track = @@ -534,7 +532,7 @@ AS_02::PHDR::MXFWriter::h__Writer::SetSourceStream(const std::string& label, con { result = WritePHDRHeader(label, UL(m_Dict->ul(MDD_MXFGCFUFrameWrappedPictureElement)), PICT_DEF_LABEL, UL(m_EssenceUL), UL(m_Dict->ul(MDD_PictureDataDef)), - edit_rate, derive_timecode_rate_from_edit_rate(edit_rate)); + edit_rate); if ( KM_SUCCESS(result) ) { diff --git a/src/AS_02_TimedText.cpp b/src/AS_02_TimedText.cpp index 6868395..09f7103 100644 --- a/src/AS_02_TimedText.cpp +++ b/src/AS_02_TimedText.cpp @@ -496,7 +496,7 @@ AS_02::TimedText::MXFWriter::h__Writer::SetSourceStream(ASDCP::TimedText::TimedT m_EditRate = TDesc.EditRate; result = WriteAS02Header(TIMED_TEXT_PACKAGE_LABEL, UL(m_Dict->ul(MDD_TimedTextWrappingClip)), "Data Track", UL(m_EssenceUL), UL(m_Dict->ul(MDD_DataDataDef)), - TDesc.EditRate, derive_timecode_rate_from_edit_rate(TDesc.EditRate)); + TDesc.EditRate); } return result; diff --git a/src/AS_02_internal.h b/src/AS_02_internal.h index 4be764d..b5d8282 100644 --- a/src/AS_02_internal.h +++ b/src/AS_02_internal.h @@ -165,7 +165,7 @@ namespace AS_02 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 ui32_t& TCFrameRate) + const std::vector<ASDCP::UL>* conformsToSpecifications = NULL) { if ( EditRate.Numerator == 0 || EditRate.Denominator == 0 ) { @@ -173,9 +173,9 @@ namespace AS_02 return RESULT_PARAM; } - InitHeader(MXFVersion_2011); + InitHeader(MXFVersion_2011, conformsToSpecifications); - AddSourceClip(EditRate, EditRate/*TODO: for a moment*/, TCFrameRate, TrackName, EssenceUL, DataDefinition, PackageLabel); + AddSourceClip(EditRate, EditRate/*TODO: for a moment*/, 0 /*no timecode track*/, TrackName, EssenceUL, DataDefinition, PackageLabel); AddEssenceDescriptor(WrappingUL); this->m_IndexWriter.SetPrimerLookup(&this->m_HeaderPart.m_Primer); diff --git a/src/AS_DCP.h b/src/AS_DCP.h index 74991f6..fa8b00a 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 }; @@ -507,6 +508,11 @@ namespace ASDCP { // point to a readable area of memory that is at least HMAC_SIZE bytes in length. // Returns error if the buf argument is NULL or if the values do ot match. Result_t TestHMACValue(const byte_t* buf) const; + + // Writes MIC key to given buffer. buf must point to a writable area of + // memory that is at least KeyLen bytes in length. Returns error if the + // buf argument is NULL. + Result_t GetMICKey(byte_t* buf) const; }; //--------------------------------------------------------------------------------- @@ -1455,7 +1461,7 @@ namespace ASDCP { byte_t ResourceID[UUIDlen]; MIMEType_t Type; - TimedTextResourceDescriptor() : Type(MT_BIN) {} + TimedTextResourceDescriptor() : Type(MT_BIN) { memset(ResourceID, 0, UUIDlen); } }; typedef std::list<TimedTextResourceDescriptor> ResourceList_t; @@ -1469,7 +1475,7 @@ namespace ASDCP { std::string EncodingName; ResourceList_t ResourceList; - TimedTextDescriptor() : ContainerDuration(0), EncodingName("UTF-8") {} // D-Cinema format is always UTF-8 + TimedTextDescriptor() : ContainerDuration(0), EncodingName("UTF-8") { memset(AssetID, 0, UUIDlen); } // D-Cinema format is always UTF-8 }; // Print debugging information to std::ostream diff --git a/src/AS_DCP_AES.cpp b/src/AS_DCP_AES.cpp index 379e8ab..6409f5b 100755 --- a/src/AS_DCP_AES.cpp +++ b/src/AS_DCP_AES.cpp @@ -349,6 +349,13 @@ public: SHA1_Final(m_SHAValue, &SHA); m_Final = true; } + + // + void + GetMICKey(byte_t* buf) const + { + memcpy(buf, m_key, KeyLen); + } }; @@ -444,6 +451,20 @@ HMACContext::TestHMACValue(const byte_t* buf) const } +// +Result_t +HMACContext::GetMICKey(byte_t* buf) const +{ + KM_TEST_NULL_L(buf); + + if ( m_Context.empty() ) + return RESULT_INIT; + + m_Context->GetMICKey(buf); + return RESULT_OK; +} + + // // end AS_DCP_AES.cpp diff --git a/src/AS_DCP_JP2K.cpp b/src/AS_DCP_JP2K.cpp index 129f53d..d5fddaa 100755 --- a/src/AS_DCP_JP2K.cpp +++ b/src/AS_DCP_JP2K.cpp @@ -319,7 +319,7 @@ ASDCP::JP2K_PDesc_to_MD(const JP2K::PictureDescriptor& PDesc, EssenceSubDescriptor.PictureComponentSizing.set_has_value(); ui32_t precinct_set_size = 0; - for ( ui32_t i = 0; PDesc.CodingStyleDefault.SPcod.PrecinctSize[i] != 0 && i < MaxPrecincts; ++i ) + for ( ui32_t i = 0; i < MaxPrecincts && PDesc.CodingStyleDefault.SPcod.PrecinctSize[i] != 0; ++i ) precinct_set_size++; ui32_t csd_size = sizeof(CodingStyleDefault_t) - MaxPrecincts + precinct_set_size; 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 57ed006..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)); @@ -675,7 +687,7 @@ namespace ASDCP // void AddSourceClip(const MXF::Rational& clip_edit_rate, - const MXF::Rational& tc_edit_rate, ui32_t TCFrameRate, + const MXF::Rational& tc_edit_rate, ui32_t tc_frame_rate, const std::string& TrackName, const UL& EssenceUL, const UL& DataDefinition, const std::string& PackageLabel) { @@ -706,14 +718,17 @@ namespace ASDCP m_HeaderPart.AddChildObject(m_MaterialPackage); m_ContentStorage->Packages.push_back(m_MaterialPackage->InstanceUID); - TrackSet<TimecodeComponent> MPTCTrack = - CreateTimecodeTrack<MaterialPackage>(m_HeaderPart, *m_MaterialPackage, - tc_edit_rate, TCFrameRate, 0, m_Dict); - - MPTCTrack.Sequence->Duration.set_has_value(); - m_DurationUpdateList.push_back(&(MPTCTrack.Sequence->Duration.get())); - MPTCTrack.Clip->Duration.set_has_value(); - m_DurationUpdateList.push_back(&(MPTCTrack.Clip->Duration.get())); + if ( tc_frame_rate ) + { + TrackSet<TimecodeComponent> MPTCTrack = + CreateTimecodeTrack<MaterialPackage>(m_HeaderPart, *m_MaterialPackage, + tc_edit_rate, tc_frame_rate, 0, m_Dict); + + MPTCTrack.Sequence->Duration.set_has_value(); + m_DurationUpdateList.push_back(&(MPTCTrack.Sequence->Duration.get())); + MPTCTrack.Clip->Duration.set_has_value(); + m_DurationUpdateList.push_back(&(MPTCTrack.Clip->Duration.get())); + } TrackSet<SourceClip> MPTrack = CreateTrackAndSequence<MaterialPackage, SourceClip>(m_HeaderPart, *m_MaterialPackage, @@ -744,14 +759,17 @@ namespace ASDCP m_HeaderPart.AddChildObject(m_FilePackage); m_ContentStorage->Packages.push_back(m_FilePackage->InstanceUID); - TrackSet<TimecodeComponent> FPTCTrack = - CreateTimecodeTrack<SourcePackage>(m_HeaderPart, *m_FilePackage, - tc_edit_rate, TCFrameRate, 0, m_Dict); - - FPTCTrack.Sequence->Duration.set_has_value(); - m_DurationUpdateList.push_back(&(FPTCTrack.Sequence->Duration.get())); - FPTCTrack.Clip->Duration.set_has_value(); - m_DurationUpdateList.push_back(&(FPTCTrack.Clip->Duration.get())); + if ( tc_frame_rate ) + { + TrackSet<TimecodeComponent> FPTCTrack = + CreateTimecodeTrack<SourcePackage>(m_HeaderPart, *m_FilePackage, + tc_edit_rate, tc_frame_rate, 0, m_Dict); + + FPTCTrack.Sequence->Duration.set_has_value(); + m_DurationUpdateList.push_back(&(FPTCTrack.Sequence->Duration.get())); + FPTCTrack.Clip->Duration.set_has_value(); + m_DurationUpdateList.push_back(&(FPTCTrack.Clip->Duration.get())); + } TrackSet<SourceClip> FPTrack = CreateTrackAndSequence<SourcePackage, SourceClip>(m_HeaderPart, *m_FilePackage, @@ -875,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/KM_fileio.cpp b/src/KM_fileio.cpp index 27a5bfa..4ee73c2 100644 --- a/src/KM_fileio.cpp +++ b/src/KM_fileio.cpp @@ -719,7 +719,9 @@ Kumu::fsize_t Kumu::FileReader::Size() const { #ifdef KM_WIN32 - return FileSize(m_Filename.c_str()); + LARGE_INTEGER size; + GetFileSizeEx(m_Handle, &size); + return size.QuadPart; #else fstat_t info; 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 }, }; @@ -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 6d7cdd8..c5cc07e 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 ef6e17e..fd4c115 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 diff --git a/src/h__02_Writer.cpp b/src/h__02_Writer.cpp index 9b1c6c6..d7cfaa3 100644 --- a/src/h__02_Writer.cpp +++ b/src/h__02_Writer.cpp @@ -161,7 +161,17 @@ AS_02::MXF::AS02IndexWriterVBR::PushIndexEntry(const IndexTableSegment::IndexEnt m_CurrentSegment->DeltaEntryArray.push_back(IndexTableSegment::DeltaEntry()); m_CurrentSegment->IndexEditRate = m_EditRate; m_CurrentSegment->IndexStartPosition = 0; - } + } else if (m_CurrentSegment->IndexEntryArray.size() >= CBRIndexEntriesPerSegment) { // no, this one is full, start another + m_CurrentSegment->IndexDuration = m_CurrentSegment->IndexEntryArray.size(); + ui64_t StartPosition = m_CurrentSegment->IndexStartPosition + m_CurrentSegment->IndexDuration; + + m_CurrentSegment = new IndexTableSegment(m_Dict); + assert(m_CurrentSegment); + AddChildObject(m_CurrentSegment); + m_CurrentSegment->DeltaEntryArray.push_back(IndexTableSegment::DeltaEntry()); + m_CurrentSegment->IndexEditRate = m_EditRate; + m_CurrentSegment->IndexStartPosition = StartPosition; + } m_CurrentSegment->IndexEntryArray.push_back(Entry); } diff --git a/src/h__Writer.cpp b/src/h__Writer.cpp index fc7f060..0c56b4c 100755 --- a/src/h__Writer.cpp +++ b/src/h__Writer.cpp @@ -374,6 +374,15 @@ ASDCP::Write_EKLV_Packet(Kumu::FileWriter& File, const ASDCP::Dictionary& Dict, byte_t overhead[128]; Kumu::MemIOWriter Overhead(overhead, 128); + // We declare HMACOverhead and its buffer in the outer scope, even though it is not used on + // unencrypted content: the reason is that File.Writev(const byte_t* buf, ui32_t buf_len) doesn't + // write data right away but saves a pointer on the buffer. And we write all the buffers at the end + // when calling File.writev(). + // Declaring the buffer variable in an inner scope means the buffer will go out of scope + // before the data it contains has been actually written, which means its content could be + // overwritten/get corrupted. + byte_t hmoverhead[512]; + Kumu::MemIOWriter HMACOverhead(hmoverhead, 512); if ( FrameBuf.Size() == 0 ) { @@ -455,9 +464,6 @@ ASDCP::Write_EKLV_Packet(Kumu::FileWriter& File, const ASDCP::Dictionary& Dict, { StreamOffset += CtFrameBuf.Size(); - byte_t hmoverhead[512]; - Kumu::MemIOWriter HMACOverhead(hmoverhead, 512); - // write the HMAC if ( Info.UsesHMAC ) { diff --git a/win32/Makefile.wmk b/win32/Makefile.common index 1a0956d..5f90bc7 100755 --- a/win32/Makefile.wmk +++ b/win32/Makefile.common @@ -1,5 +1,5 @@ # $Id$
-# Copyright (c) 2007-2012 John Hurst. All rights reserved.
+# Copyright (c) 2007-2020 John Hurst. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -34,17 +34,16 @@ OBJDIR = . !ifdef ENABLE_RANDOM_UUID
CXXFLAGS1 = /nologo /W3 /GR /EHsc /DWIN32 /DKM_WIN32 /D_CONSOLE /I. /I$(SRCDIR) /DASDCP_PLATFORM=\"win32\" \
/D_CRT_SECURE_NO_WARNINGS /D_CRT_NONSTDC_NO_WARNINGS /DPACKAGE_VERSION=\"@PACKAGE_VERSION@\" \
- /I"$(WITH_OPENSSL)"\inc32 /DCONFIG_RANDOM_UUID=1
+ /I"$(WITH_OPENSSL)"\include /DCONFIG_RANDOM_UUID=1
!else
CXXFLAGS1 = /nologo /W3 /GR /EHsc /DWIN32 /DKM_WIN32 /D_CONSOLE /I. /I$(SRCDIR) /DASDCP_PLATFORM=\"win32\" \
/D_CRT_SECURE_NO_WARNINGS /D_CRT_NONSTDC_NO_WARNINGS /DPACKAGE_VERSION=\"@PACKAGE_VERSION@\" \
- /I"$(WITH_OPENSSL)"\inc32
+ /I"$(WITH_OPENSSL)"\include
!endif
LIB_EXE = lib.exe
-LIBFLAGS1 = /NOLOGO /LIBPATH:"$(WITH_OPENSSL)"\out32dll
+LIBFLAGS1 = /NOLOGO /LIBPATH:"$(WITH_OPENSSL)"\lib
LINK = link.exe
-LINKFLAGS1 = /NOLOGO /SUBSYSTEM:console /MACHINE:I386 /LIBPATH:. /DEBUG
!ifdef DEBUG
@@ -110,14 +109,14 @@ clean: libkumu.lib : $(KUMU_OBJS)
!IFDEF WITH_XERCES
!IFDEF DEBUG
- $(LIB_EXE) $(LIBFLAGS) /OUT:libkumu.lib $** libeay32.lib xerces-c_2D.lib
+ $(LIB_EXE) $(LIBFLAGS) /OUT:libkumu.lib $** libcrypto.lib xerces-c_3D.lib
!ELSE
- $(LIB_EXE) $(LIBFLAGS) /OUT:libkumu.lib $** libeay32.lib xerces-c_2.lib
+ $(LIB_EXE) $(LIBFLAGS) /OUT:libkumu.lib $** libcrypto.lib xerces-c_3.lib
!ENDIF
!ELSEIFDEF WITH_XML_PARSER
- $(LIB_EXE) $(LIBFLAGS) /OUT:libkumu.lib $** libeay32.lib libexpatMT.lib
+ $(LIB_EXE) $(LIBFLAGS) /OUT:libkumu.lib $** libcrypto.lib libexpatMT.lib
!ELSE
- $(LIB_EXE) $(LIBFLAGS) /OUT:libkumu.lib $** libeay32.lib
+ $(LIB_EXE) $(LIBFLAGS) /OUT:libkumu.lib $** libcrypto.lib
!ENDIF
libasdcp.lib: libkumu.lib $(ASDCP_OBJS)
diff --git a/win32/Makefile32.wmk b/win32/Makefile32.wmk new file mode 100644 index 0000000..5fc0887 --- /dev/null +++ b/win32/Makefile32.wmk @@ -0,0 +1,28 @@ +# $Id$ +# Copyright (c) 2007-2020 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. + +LINKFLAGS1 = /NOLOGO /SUBSYSTEM:console /MACHINE:I386 /LIBPATH:. /DEBUG + +include Makefile.common diff --git a/win32/Makefile64.wmk b/win32/Makefile64.wmk new file mode 100644 index 0000000..c1ad4a5 --- /dev/null +++ b/win32/Makefile64.wmk @@ -0,0 +1,28 @@ +# $Id$ +# Copyright (c) 2007-2020 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. + +LINKFLAGS1 = /NOLOGO /SUBSYSTEM:console /MACHINE:X64 /LIBPATH:. /DEBUG + +include Makefile.common diff --git a/win32/README.txt b/win32/README.txt index 76e76c7..4dbdd14 100755 --- a/win32/README.txt +++ b/win32/README.txt @@ -35,29 +35,25 @@ variable KM_USE_RANDOM_UUID is set during runtime. Open a command prompt in which the VS build tools are available on the command line (e.g., the
"Visual Studio command prompt"). The nmake invocation follows this form:
C:\>nmake WITH_OPENSSL=<OpenSSL directory> [WITH_XERCES=<Xerces directory>|
- WITH_XML_PARSER=<Expat directory>] [ENABLE_RANDOM_UUID=1] /f Makefile.mak
+ WITH_XML_PARSER=<Expat directory>] [ENABLE_RANDOM_UUID=1] /f Makefile32.wmk
On our Windows development machine, the invocation with XML parsing by Xerces-C++ is as such:
-C:\Program Files\asdcplib\win32>nmake WITH_OPENSSL="c:\Program Files\openssl-0.9.8j"
- WITH_XERCES="C:\Program Files\xerces-c_2_8_0-x86-windows-vc_8_0" /f Makefile.mak
+C:\Program Files (x86)\asdcplib\win32>nmake WITH_OPENSSL="C:\Program Files (x86)\openssl"
+ WITH_XERCES="C:\Program Files (x86)\xerces-c" /f Makefile32.wmk
With XML parsing by Expat and random UUID generation enabled:
-C:\Program Files\asdcplib\win32>nmake WITH_OPENSSL="c:\Program Files\openssl-0.9.8j"
- WITH_XML_PARSER="C:\Program Files\Expat 2.0.1" ENABLE_RANDOM_UUID=1 /f Makefile.mak
+C:\Program Files (x86)\asdcplib\win32>nmake WITH_OPENSSL="C:\Program Files (x86)\openssl"
+ WITH_XML_PARSER="C:\Program Files (x86)\Expat 2.0.1" ENABLE_RANDOM_UUID=1 /f Makefile32.wmk
Without XML parsing:
-C:\Program Files\asdcplib\win32>nmake WITH_OPENSSL="c:\Program Files\openssl-0.9.8j"
- /f Makefile.mak
+C:\Program Files (x86)\asdcplib\win32>nmake WITH_OPENSSL="C:\Program Files (x86)\openssl"
+ /f Makefile32.wmk
Without XML parsing but with the AS-02 library and executables:
-C:\Program Files\asdcplib\win32>nmake WITH_OPENSSL="c:\Program Files\openssl-0.9.8j"
- USE_AS_02=1 /f Makefile.mak
-
-Want a 64-bit build? Change the following line in Makefile.mak:
- LINKFLAGS1 = /NOLOGO /SUBSYSTEM:console /MACHINE:I386 /LIBPATH:. /DEBUG
-to
- LINKFLAGS1 = /NOLOGO /SUBSYSTEM:console /MACHINE:X64 /LIBPATH:. /DEBUG
+C:\Program Files (x86)\asdcplib\win32>nmake WITH_OPENSSL="C:\Program Files (x86)\openssl"
+ USE_AS_02=1 /f Makefile32.wmk
+Want a 64-bit build? Use Makefile64.wmk and specify 64-bit library locations.
IV. CONCLUSION
==============
|
