diff options
Diffstat (limited to 'src')
34 files changed, 704 insertions, 559 deletions
diff --git a/src/AS_02.h b/src/AS_02.h index 3437152..6b34c77 100644 --- a/src/AS_02.h +++ b/src/AS_02.h @@ -97,7 +97,6 @@ namespace AS_02 Result_t Lookup(ui32_t frame_num, ASDCP::MXF::IndexTableSegment::IndexEntry&) const; }; - // Returns size in bytes of a single sample of data described by ADesc inline ui32_t CalcSampleSize(const ASDCP::MXF::WaveAudioDescriptor& d) @@ -119,7 +118,8 @@ namespace AS_02 } // Returns number of frames for data described by ADesc, given a duration in samples and an edit rate - inline ui32_t CalcFramesFromDurationInSamples(const ui32_t durationInSamples, const ASDCP::MXF::WaveAudioDescriptor& d, const ASDCP::Rational& edit_rate) + inline ui32_t CalcFramesFromDurationInSamples(const ui32_t durationInSamples, const ASDCP::MXF::WaveAudioDescriptor& d, + const ASDCP::Rational& edit_rate) { return static_cast<ui32_t>(static_cast<ui64_t>(durationInSamples) * static_cast<ui64_t>(d.AudioSamplingRate.Denominator * edit_rate.Numerator) / @@ -142,7 +142,7 @@ namespace AS_02 }; namespace JP2K - { + { // class MXFWriter { @@ -167,7 +167,7 @@ namespace AS_02 ASDCP::MXF::InterchangeObject_list_t& essence_sub_descriptor_list, const ASDCP::Rational& edit_rate, const ui32_t& header_size = 16384, const IndexStrategy_t& strategy = IS_FOLLOW, const ui32_t& partition_space = 10); - + // 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 @@ -238,7 +238,7 @@ namespace AS_02 // the reader to signal the number of samples to be read by each call to ReadFrame(); // - class MXFWriter + class MXFWriter { class h__Writer; ASDCP::mem_ptr<h__Writer> m_Writer; diff --git a/src/AS_02_JP2K.cpp b/src/AS_02_JP2K.cpp index a8eff1a..48b98fe 100644 --- a/src/AS_02_JP2K.cpp +++ b/src/AS_02_JP2K.cpp @@ -55,8 +55,6 @@ class AS_02::JP2K::MXFReader::h__Reader : public AS_02::h__AS02Reader ASDCP_NO_COPY_CONSTRUCT(h__Reader); public: - PictureDescriptor m_PDesc; // codestream parameter list - h__Reader(const Dictionary& d) : AS_02::h__AS02Reader(d) {} @@ -229,7 +227,7 @@ AS_02::JP2K::MXFReader::FillWriterInfo(WriterInfo& Info) const //------------------------------------------------------------------------------------------ // -class AS_02::JP2K::MXFWriter::h__Writer : public AS_02::h__AS02Writer +class AS_02::JP2K::MXFWriter::h__Writer : public AS_02::h__AS02WriterFrame { ASDCP_NO_COPY_CONSTRUCT(h__Writer); h__Writer(); @@ -237,10 +235,9 @@ class AS_02::JP2K::MXFWriter::h__Writer : public AS_02::h__AS02Writer JPEG2000PictureSubDescriptor* m_EssenceSubDescriptor; public: - PictureDescriptor m_PDesc; byte_t m_EssenceUL[SMPTE_UL_LENGTH]; - h__Writer(const Dictionary& d) : h__AS02Writer(d), m_EssenceSubDescriptor(0) { + h__Writer(const Dictionary& d) : h__AS02WriterFrame(d), m_EssenceSubDescriptor(0) { memset(m_EssenceUL, 0, SMPTE_UL_LENGTH); } @@ -334,6 +331,11 @@ AS_02::JP2K::MXFWriter::h__Writer::SetSourceStream(const std::string& label, con result = WriteAS02Header(label, UL(m_Dict->ul(MDD_JPEG_2000WrappingFrame)), PICT_DEF_LABEL, UL(m_EssenceUL), UL(m_Dict->ul(MDD_PictureDataDef)), edit_rate, derive_timecode_rate_from_edit_rate(edit_rate)); + + if ( KM_SUCCESS(result) ) + { + this->m_IndexWriter.SetPrimerLookup(&this->m_HeaderPart.m_Primer); + } } return result; diff --git a/src/AS_02_PCM.cpp b/src/AS_02_PCM.cpp index 2ffc45e..9a6a98c 100644 --- a/src/AS_02_PCM.cpp +++ b/src/AS_02_PCM.cpp @@ -49,6 +49,7 @@ class AS_02::PCM::MXFReader::h__Reader : public AS_02::h__AS02Reader { ui64_t m_ClipEssenceBegin; ui64_t m_SamplesPerFrame; + ui32_t m_BytesPerFrame; ui32_t m_ContainerDuration; ASDCP_NO_COPY_CONSTRUCT(h__Reader); @@ -56,7 +57,7 @@ class AS_02::PCM::MXFReader::h__Reader : public AS_02::h__AS02Reader public: h__Reader(const Dictionary& d) : AS_02::h__AS02Reader(d), m_ClipEssenceBegin(0), - m_SamplesPerFrame(0), m_ContainerDuration(0) {} + m_SamplesPerFrame(0), m_BytesPerFrame(0), m_ContainerDuration(0) {} virtual ~h__Reader() {} ASDCP::Result_t OpenRead(const std::string&, const ASDCP::Rational& edit_rate); @@ -75,17 +76,20 @@ AS_02::PCM::MXFReader::h__Reader::OpenRead(const std::string& filename, const AS if( KM_SUCCESS(result) ) { - if ( KM_SUCCESS(m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(WaveAudioDescriptor), - reinterpret_cast<InterchangeObject**>(&wave_descriptor))) ) + InterchangeObject* tmp_obj = 0; + + if ( KM_SUCCESS(m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(WaveAudioDescriptor), &tmp_obj)) ) { - if ( wave_descriptor == 0 ) - { - DefaultLogSink().Error("WaveAudioDescriptor object not found.\n"); - return RESULT_AS02_FORMAT; - } + wave_descriptor = dynamic_cast<ASDCP::MXF::WaveAudioDescriptor*>(tmp_obj); } } + if ( wave_descriptor == 0 ) + { + DefaultLogSink().Error("WaveAudioDescriptor object not found.\n"); + result = RESULT_AS02_FORMAT; + } + if ( KM_SUCCESS(result) ) result = m_IndexAccess.Lookup(0, tmp_entry); @@ -131,8 +135,9 @@ AS_02::PCM::MXFReader::h__Reader::OpenRead(const std::string& filename, const AS m_ClipEssenceBegin = m_File.Tell(); m_SamplesPerFrame = AS_02::MXF::CalcSamplesPerFrame(*wave_descriptor, edit_rate); - m_ContainerDuration = static_cast<ui32_t>(8ULL * reader.Length() / - (m_SamplesPerFrame * wave_descriptor->ChannelCount * wave_descriptor->QuantizationBits)); + m_BytesPerFrame = AS_02::MXF::CalcFrameBufferSize(*wave_descriptor, edit_rate); + m_ContainerDuration = static_cast<ui32_t>(reader.Length() / ( m_SamplesPerFrame * AS_02::MXF::CalcSampleSize(*wave_descriptor))); + } } @@ -144,8 +149,6 @@ ASDCP::Result_t AS_02::PCM::MXFReader::h__Reader::ReadFrame(ui32_t FrameNum, ASDCP::PCM::FrameBuffer& FrameBuf, ASDCP::AESDecContext* Ctx, ASDCP::HMACContext* HMAC) { - ASDCP::MXF::WaveAudioDescriptor* wave_descriptor = 0; - if ( ! m_File.IsOpen() ) { return RESULT_INIT; @@ -157,23 +160,9 @@ AS_02::PCM::MXFReader::h__Reader::ReadFrame(ui32_t FrameNum, ASDCP::PCM::FrameBu } assert(m_ClipEssenceBegin); + ui64_t position = m_ClipEssenceBegin + ( FrameNum * m_BytesPerFrame ); Result_t result = RESULT_OK; - if( KM_SUCCESS(result) ) - { - if ( KM_SUCCESS(m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(WaveAudioDescriptor), - reinterpret_cast<InterchangeObject**>(&wave_descriptor))) ) - { - if ( wave_descriptor == 0 ) - { - DefaultLogSink().Error("WaveAudioDescriptor object not found.\n"); - return RESULT_AS02_FORMAT; - } - } - } - - ui64_t position = m_ClipEssenceBegin + ( FrameNum * m_SamplesPerFrame * wave_descriptor->ChannelCount * wave_descriptor->BlockAlign ); - if ( m_File.Tell() != position ) { result = m_File.Seek(position); @@ -181,12 +170,12 @@ AS_02::PCM::MXFReader::h__Reader::ReadFrame(ui32_t FrameNum, ASDCP::PCM::FrameBu if ( KM_SUCCESS(result) ) { - result = m_File.Read(FrameBuf.Data(), m_SamplesPerFrame * wave_descriptor->ChannelCount * wave_descriptor->BlockAlign); + result = m_File.Read(FrameBuf.Data(), m_BytesPerFrame); } if ( KM_SUCCESS(result) ) { - FrameBuf.Size(m_SamplesPerFrame * wave_descriptor->ChannelCount * wave_descriptor->BlockAlign); + FrameBuf.Size(m_BytesPerFrame); } return result; @@ -322,7 +311,7 @@ AS_02::PCM::MXFReader::DumpIndex(FILE* stream) const //------------------------------------------------------------------------------------------ // -class AS_02::PCM::MXFWriter::h__Writer : public AS_02::h__AS02Writer +class AS_02::PCM::MXFWriter::h__Writer : public AS_02::h__AS02WriterClip { ASDCP_NO_COPY_CONSTRUCT(h__Writer); h__Writer(); @@ -333,7 +322,7 @@ public: ui32_t m_BytesPerFrame; ui32_t m_SamplesPerFrame; - h__Writer(const Dictionary& d) : AS_02::h__AS02Writer(d), m_WaveAudioDescriptor(0), m_BytesPerFrame(0), m_SamplesPerFrame(0) + h__Writer(const Dictionary& d) : AS_02::h__AS02WriterClip(d), m_WaveAudioDescriptor(0), m_BytesPerFrame(0), m_SamplesPerFrame(0) { memset(m_EssenceUL, 0, SMPTE_UL_LENGTH); } @@ -355,15 +344,15 @@ AS_02::PCM::MXFWriter::h__Writer::OpenWrite(const std::string& filename, ASDCP:: { assert(essence_descriptor); - if ( essence_descriptor->GetUL() != UL(m_Dict->ul(MDD_WaveAudioDescriptor)) ) + m_WaveAudioDescriptor = dynamic_cast<ASDCP::MXF::WaveAudioDescriptor*>(essence_descriptor); + + if ( m_WaveAudioDescriptor == 0 ) { DefaultLogSink().Error("Essence descriptor is not a WaveAudioDescriptor.\n"); essence_descriptor->Dump(); return RESULT_AS02_FORMAT; } - m_WaveAudioDescriptor = reinterpret_cast<ASDCP::MXF::WaveAudioDescriptor*>(essence_descriptor); - if ( ! m_State.Test_BEGIN() ) { return RESULT_STATE; @@ -420,10 +409,16 @@ AS_02::PCM::MXFWriter::h__Writer::SetSourceStream(const ASDCP::Rational& edit_ra m_BytesPerFrame = AS_02::MXF::CalcFrameBufferSize(*m_WaveAudioDescriptor, edit_rate); m_SamplesPerFrame = AS_02::MXF::CalcSamplesPerFrame(*m_WaveAudioDescriptor, edit_rate); m_WaveAudioDescriptor->ContainerDuration = 0; - + assert(m_BytesPerFrame); 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_BytesPerFrame); + m_EssenceDescriptor->SampleRate, derive_timecode_rate_from_edit_rate(edit_rate)); + + if ( KM_SUCCESS(result) ) + { + this->m_IndexWriter.SetEditRate(m_WaveAudioDescriptor->AudioSamplingRate, + AS_02::MXF::CalcSampleSize(*m_WaveAudioDescriptor)); + } } return result; @@ -467,7 +462,7 @@ AS_02::PCM::MXFWriter::h__Writer::WriteFrame(const FrameBuffer& frame_buf, AESEn if ( KM_SUCCESS(result) ) { - m_FramesWritten++; + m_FramesWritten += m_SamplesPerFrame; } return result; @@ -483,14 +478,11 @@ AS_02::PCM::MXFWriter::h__Writer::Finalize() m_State.Goto_FINAL(); - Result_t result = FinalizeClip(m_BytesPerFrame); + Result_t result = FinalizeClip(AS_02::MXF::CalcSampleSize(*m_WaveAudioDescriptor)); if ( KM_SUCCESS(result) ) { - m_FramesWritten = m_FramesWritten * m_SamplesPerFrame; - m_IndexWriter.ThisPartition = m_File.Tell(); - m_IndexWriter.WriteToFile(m_File); - m_RIP.PairArray.push_back(RIP::Pair(0, m_IndexWriter.ThisPartition)); + m_IndexWriter.m_Duration = m_FramesWritten; WriteAS02Footer(); } @@ -541,7 +533,6 @@ AS_02::PCM::MXFWriter::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 diff --git a/src/AS_02_internal.h b/src/AS_02_internal.h index 0a45a24..4bdb64c 100644 --- a/src/AS_02_internal.h +++ b/src/AS_02_internal.h @@ -52,95 +52,273 @@ namespace AS_02 void default_md_object_init(); + + // + class h__AS02Reader : public ASDCP::MXF::TrackFileReader<ASDCP::MXF::OP1aHeader, AS_02::MXF::AS02IndexReader> + { + ASDCP_NO_COPY_CONSTRUCT(h__AS02Reader); + h__AS02Reader(); + + public: + h__AS02Reader(const ASDCP::Dictionary&); + virtual ~h__AS02Reader(); + + Result_t OpenMXFRead(const char* filename); + + // USE FRAME WRAPPING... + Result_t ReadEKLVFrame(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf, + const byte_t* EssenceUL, ASDCP::AESDecContext* Ctx, ASDCP::HMACContext* HMAC); + + // OR CLIP WRAPPING... + // clip wrapping is handled directly by the essence-specific classes + // Result_t ReadyClip(const ui32_t& FrameNum, const byte_t* EssenceUL, ASDCP::AESDecContext* Ctx, ASDCP::HMACContext* HMAC, ui64_t& position); + /// Result_t ReadClipBlock(ASDCP::FrameBuffer& FrameBuf, const ui32_t& read_size); + + // NOT BOTH! + }; + + namespace MXF { // - class AS02IndexWriter : public ASDCP::MXF::Partition + class AS02IndexWriterVBR : public ASDCP::MXF::Partition { ASDCP::MXF::IndexTableSegment* m_CurrentSegment; - ui32_t m_BytesPerEditUnit; ASDCP::MXF::Rational m_EditRate; - KM_NO_COPY_CONSTRUCT(AS02IndexWriter); - AS02IndexWriter(); + KM_NO_COPY_CONSTRUCT(AS02IndexWriterVBR); + AS02IndexWriterVBR(); public: const ASDCP::Dictionary*& m_Dict; ASDCP::IPrimerLookup* m_Lookup; - AS02IndexWriter(const ASDCP::Dictionary*&); - virtual ~AS02IndexWriter(); + AS02IndexWriterVBR(const ASDCP::Dictionary*&); + virtual ~AS02IndexWriterVBR(); + + // + void SetPrimerLookup(ASDCP::IPrimerLookup* lookup) { + assert(lookup); + m_Lookup = lookup; + } Result_t WriteToFile(Kumu::FileWriter& Writer); - void ResetCBR(Kumu::fpos_t offset); void Dump(FILE* = 0); ui32_t GetDuration() const; void PushIndexEntry(const ASDCP::MXF::IndexTableSegment::IndexEntry&); - void SetIndexParamsCBR(ASDCP::IPrimerLookup* lookup, ui32_t size, const ASDCP::Rational& Rate); - void SetIndexParamsVBR(ASDCP::IPrimerLookup* lookup, const ASDCP::Rational& Rate, Kumu::fpos_t offset); }; - } - // - class h__AS02Reader : public ASDCP::MXF::TrackFileReader<ASDCP::MXF::OP1aHeader, AS_02::MXF::AS02IndexReader> - { - ASDCP_NO_COPY_CONSTRUCT(h__AS02Reader); - h__AS02Reader(); - public: - h__AS02Reader(const ASDCP::Dictionary&); - virtual ~h__AS02Reader(); + // + class AS02IndexWriterCBR : public ASDCP::MXF::Partition + { + ASDCP::MXF::IndexTableSegment* m_CurrentSegment; + ASDCP::MXF::Rational m_EditRate; - Result_t OpenMXFRead(const char* filename); + KM_NO_COPY_CONSTRUCT(AS02IndexWriterCBR); + AS02IndexWriterCBR(); - // USE FRAME WRAPPING... - Result_t ReadEKLVFrame(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf, - const byte_t* EssenceUL, ASDCP::AESDecContext* Ctx, ASDCP::HMACContext* HMAC); + public: + const ASDCP::Dictionary*& m_Dict; + ASDCP::IPrimerLookup* m_Lookup; + ui32_t m_Duration; + ui32_t m_SampleSize; + + AS02IndexWriterCBR(const ASDCP::Dictionary*&); + virtual ~AS02IndexWriterCBR(); - // OR CLIP WRAPPING... - // clip wrapping is handled directly by the essence-specific classes - // Result_t ReadyClip(const ui32_t& FrameNum, const byte_t* EssenceUL, ASDCP::AESDecContext* Ctx, ASDCP::HMACContext* HMAC, ui64_t& position); - /// Result_t ReadClipBlock(ASDCP::FrameBuffer& FrameBuf, const ui32_t& read_size); + // + void SetPrimerLookup(ASDCP::IPrimerLookup* lookup) { + assert(lookup); + m_Lookup = lookup; + } - // NOT BOTH! - }; + Result_t WriteToFile(Kumu::FileWriter& Writer); + ui32_t GetDuration() const; + void SetEditRate(const ASDCP::Rational& edit_rate, const ui32_t& sample_size); + }; + } // + template <class IndexWriterType> class h__AS02Writer : public ASDCP::MXF::TrackFileWriter<ASDCP::MXF::OP1aHeader> { ASDCP_NO_COPY_CONSTRUCT(h__AS02Writer); h__AS02Writer(); public: - ui64_t m_ECStart; // offset of the first essence element - ui64_t m_ClipStart; // state variable for clip-wrap-in-progress ui32_t m_PartitionSpace; // edit units per partition - AS_02::MXF::AS02IndexWriter m_IndexWriter; - IndexStrategy_t m_IndexStrategy; // per SMPTE ST 2067-5 + IndexWriterType m_IndexWriter; + ui64_t m_ECStart; // offset of the first essence element + + // + h__AS02Writer(const ASDCP::Dictionary& d) : + ASDCP::MXF::TrackFileWriter<ASDCP::MXF::OP1aHeader>(d), m_IndexWriter(m_Dict), m_ECStart(0) {} - h__AS02Writer(const Dictionary&); - virtual ~h__AS02Writer(); + ~h__AS02Writer() {} + + // 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, - ui32_t TCFrameRate, ui32_t BytesPerEditUnit = 0); + const ui32_t& TCFrameRate) + { + if ( EditRate.Numerator == 0 || EditRate.Denominator == 0 ) + { + DefaultLogSink().Error("Non-zero edit-rate reqired.\n"); + return RESULT_PARAM; + } + + InitHeader(); + + AddSourceClip(EditRate, EditRate/*TODO: for a moment*/, TCFrameRate, TrackName, EssenceUL, DataDefinition, PackageLabel); + AddEssenceDescriptor(WrappingUL); + + this->m_IndexWriter.SetPrimerLookup(&this->m_HeaderPart.m_Primer); + this->m_RIP.PairArray.push_back(RIP::Pair(0, 0)); // Header partition RIP entry + this->m_IndexWriter.OperationalPattern = this->m_HeaderPart.OperationalPattern; + this->m_IndexWriter.EssenceContainers = this->m_HeaderPart.EssenceContainers; + + Result_t result = this->m_HeaderPart.WriteToFile(this->m_File, this->m_HeaderSize); + + if ( KM_SUCCESS(result) ) + { + this->m_PartitionSpace *= floor( EditRate.Quotient() + 0.5 ); // convert seconds to edit units + this->m_ECStart = this->m_File.Tell(); + this->m_IndexWriter.IndexSID = 129; + + UL body_ul(this->m_Dict->ul(MDD_ClosedCompleteBodyPartition)); + Partition body_part(this->m_Dict); + body_part.BodySID = 1; + body_part.OperationalPattern = this->m_HeaderPart.OperationalPattern; + body_part.EssenceContainers = this->m_HeaderPart.EssenceContainers; + body_part.ThisPartition = this->m_ECStart; + result = body_part.WriteToFile(this->m_File, body_ul); + this->m_RIP.PairArray.push_back(RIP::Pair(1, body_part.ThisPartition)); // Second RIP Entry + } + + return result; + } + + // standard method of writing the header and footer of a completed AS-02 file + // + Result_t WriteAS02Footer() + { + if ( this->m_IndexWriter.GetDuration() > 0 ) + { + this->m_IndexWriter.ThisPartition = this->m_File.Tell(); + this->m_IndexWriter.WriteToFile(this->m_File); + this->m_RIP.PairArray.push_back(RIP::Pair(0, this->m_IndexWriter.ThisPartition)); + } + + // update all Duration properties + ASDCP::MXF::Partition footer_part(this->m_Dict); + DurationElementList_t::iterator dli = this->m_DurationUpdateList.begin(); + + for (; dli != this->m_DurationUpdateList.end(); ++dli ) + { + **dli = this->m_FramesWritten; + } + + this->m_EssenceDescriptor->ContainerDuration = this->m_FramesWritten; + footer_part.PreviousPartition = this->m_RIP.PairArray.back().ByteOffset; + + Kumu::fpos_t here = this->m_File.Tell(); + this->m_RIP.PairArray.push_back(RIP::Pair(0, here)); // Last RIP Entry + this->m_HeaderPart.FooterPartition = here; + + assert(this->m_Dict); + footer_part.OperationalPattern = this->m_HeaderPart.OperationalPattern; + footer_part.EssenceContainers = this->m_HeaderPart.EssenceContainers; + footer_part.FooterPartition = here; + footer_part.ThisPartition = here; + + UL footer_ul(this->m_Dict->ul(MDD_CompleteFooter)); + Result_t result = footer_part.WriteToFile(this->m_File, footer_ul); + + if ( KM_SUCCESS(result) ) + result = this->m_RIP.WriteToFile(this->m_File); + + if ( KM_SUCCESS(result) ) + result = this->m_File.Seek(0); + + if ( KM_SUCCESS(result) ) + result = m_HeaderPart.WriteToFile(this->m_File, this->m_HeaderSize); + + if ( KM_SUCCESS(result) ) + { + ASDCP::MXF::Array<ASDCP::MXF::RIP::Pair>::const_iterator i = this->m_RIP.PairArray.begin(); + ui64_t header_byte_count = this->m_HeaderPart.HeaderByteCount; + ui64_t previous_partition = 0; + + for ( i = this->m_RIP.PairArray.begin(); KM_SUCCESS(result) && i != this->m_RIP.PairArray.end(); ++i ) + { + ASDCP::MXF::Partition plain_part(this->m_Dict); + result = this->m_File.Seek(i->ByteOffset); + + if ( KM_SUCCESS(result) ) + result = plain_part.InitFromFile(this->m_File); + + if ( KM_SUCCESS(result) + && ( plain_part.IndexSID > 0 || plain_part.BodySID > 0 ) ) + { + plain_part.PreviousPartition = previous_partition; + plain_part.FooterPartition = footer_part.ThisPartition; + previous_partition = plain_part.ThisPartition; + result = this->m_File.Seek(i->ByteOffset); + + if ( KM_SUCCESS(result) ) + { + UL tmp_ul = plain_part.GetUL(); + result = plain_part.WriteToFile(this->m_File, tmp_ul); + } + } + } + } + + this->m_File.Close(); + return result; + } + }; + + // + class h__AS02WriterFrame : public h__AS02Writer<AS_02::MXF::AS02IndexWriterVBR> + { + ASDCP_NO_COPY_CONSTRUCT(h__AS02WriterFrame); + h__AS02WriterFrame(); + + public: + IndexStrategy_t m_IndexStrategy; // per SMPTE ST 2067-5 + + h__AS02WriterFrame(const Dictionary&); + virtual ~h__AS02WriterFrame(); - // USE FRAME WRAPPING... Result_t WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,const byte_t* EssenceUL, AESEncContext* Ctx, HMACContext* HMAC); + }; + + // + class h__AS02WriterClip : public h__AS02Writer<AS_02::MXF::AS02IndexWriterCBR> + { + ASDCP_NO_COPY_CONSTRUCT(h__AS02WriterClip); + h__AS02WriterClip(); + + public: + ui64_t m_ECStart; // offset of the first essence element + ui64_t m_ClipStart; // state variable for clip-wrap-in-progress + // AS_02::MXF::AS02IndexWriterCBR m_IndexWriter; + IndexStrategy_t m_IndexStrategy; // per SMPTE ST 2067-5 + + h__AS02WriterClip(const Dictionary&); + virtual ~h__AS02WriterClip(); - // OR CLIP WRAPPING... bool HasOpenClip() const; Result_t StartClip(const byte_t* EssenceUL, AESEncContext* Ctx, HMACContext* HMAC); Result_t WriteClipBlock(const ASDCP::FrameBuffer& FrameBuf); Result_t FinalizeClip(ui32_t bytes_per_frame); - - // NOT BOTH! - - Result_t WriteAS02Footer(); }; } // namespace AS_02 diff --git a/src/AS_DCP.h b/src/AS_DCP.h index 6f99698..6b598cc 100755 --- a/src/AS_DCP.h +++ b/src/AS_DCP.h @@ -208,8 +208,12 @@ namespace ASDCP { // The file accessors in this library implement a bounded set of essence types. // This list will be expanded when support for new types is added to the library. enum EssenceType_t { - ESS_UNKNOWN, // the file is not a supported AS-DCP essence container - ESS_MPEG2_VES, // the file contains an MPEG video elementary stream + ESS_UNKNOWN, // the file is not a supported AS-DCP of AS-02 essence container + + // + ESS_MPEG2_VES, // the file contains an MPEG-2 video elementary stream + + // d-cinema essence types ESS_JPEG_2000, // the file contains one or more JPEG 2000 codestreams ESS_PCM_24b_48k, // the file contains one or more PCM audio pairs ESS_PCM_24b_96k, // the file contains one or more PCM audio pairs @@ -217,18 +221,25 @@ namespace ASDCP { ESS_JPEG_2000_S, // the file contains one or more JPEG 2000 codestream pairs (stereoscopic) ESS_DCDATA_UNKNOWN, // the file contains one or more D-Cinema Data bytestreams ESS_DCDATA_DOLBY_ATMOS, // the file contains one or more DolbyATMOS bytestreams + + // IMF essence types + ESS_AS02_JPEG_2000, // the file contains one or more JPEG 2000 codestreams + ESS_AS02_PCM_24b_48k, // the file contains one or more PCM audio pairs, clip wrapped + ESS_AS02_PCM_24b_96k, // the file contains one or more PCM audio pairs, clip wrapped + ESS_AS02_TIMED_TEXT, // the file contains a TTML document and zero or more resources + ESS_MAX }; // Determine the type of essence contained in the given MXF file. RESULT_OK // is returned if the file is successfully opened and contains a valid MXF // stream. If there is an error, the result code will indicate the reason. - Result_t EssenceType(const char* filename, EssenceType_t& type); + Result_t EssenceType(const std::string& filename, EssenceType_t& type); // Determine the type of essence contained in the given raw file. RESULT_OK // is returned if the file is successfully opened and contains a known // stream type. If there is an error, the result code will indicate the reason. - Result_t RawEssenceType(const char* filename, EssenceType_t& type); + Result_t RawEssenceType(const std::string& filename, EssenceType_t& type); //--------------------------------------------------------------------------------- @@ -707,7 +718,7 @@ namespace ASDCP { // Opens the stream for reading, parses enough data to provide a complete // set of stream metadata for the MXFWriter below. - Result_t OpenRead(const char* filename) const; + Result_t OpenRead(const std::string& filename) const; // Fill a VideoDescriptor struct with the values from the file's header. // Returns RESULT_INIT if the file is not open. @@ -745,7 +756,7 @@ namespace ASDCP { // Open the file for writing. The file must not exist. Returns error if // the operation cannot be completed or if nonsensical data is discovered // in the essence descriptor. - Result_t OpenWrite(const char* filename, const WriterInfo&, + Result_t OpenWrite(const std::string& filename, const WriterInfo&, const VideoDescriptor&, ui32_t HeaderSize = 16384); // Writes a frame of essence to the MXF file. If the optional AESEncContext @@ -777,7 +788,7 @@ namespace ASDCP { // Open the file for reading. The file must exist. Returns error if the // operation cannot be completed. - Result_t OpenRead(const char* filename) const; + Result_t OpenRead(const std::string& filename) const; // Returns RESULT_INIT if the file is not open. Result_t Close() const; @@ -848,6 +859,7 @@ namespace ASDCP { CF_CFG_3, // 7.1 (SDDS) with optional HI/VI CF_CFG_4, // Wild Track Format CF_CFG_5, // 7.1 DS with optional HI/VI + CF_CFG_6, // ST 377-4 (MCA) labels (see also ASDCP::MXF::decode_mca_string) CF_MAXIMUM }; @@ -918,7 +930,7 @@ namespace ASDCP { // Opens the stream for reading, parses enough data to provide a complete // set of stream metadata for the MXFWriter below. PictureRate controls // ther frame rate for the MXF frame wrapping option. - Result_t OpenRead(const char* filename, const Rational& PictureRate) const; + Result_t OpenRead(const std::string& filename, const Rational& PictureRate) const; // Fill an AudioDescriptor struct with the values from the file's header. // Returns RESULT_INIT if the file is not open. @@ -953,7 +965,7 @@ namespace ASDCP { // Open the file for writing. The file must not exist. Returns error if // the operation cannot be completed or if nonsensical data is discovered // in the essence descriptor. - Result_t OpenWrite(const char* filename, const WriterInfo&, + Result_t OpenWrite(const std::string& filename, const WriterInfo&, const AudioDescriptor&, ui32_t HeaderSize = 16384); // Writes a frame of essence to the MXF file. If the optional AESEncContext @@ -985,7 +997,7 @@ namespace ASDCP { // Open the file for reading. The file must exist. Returns error if the // operation cannot be completed. - Result_t OpenRead(const char* filename) const; + Result_t OpenRead(const std::string& filename) const; // Returns RESULT_INIT if the file is not open. Result_t Close() const; @@ -1124,7 +1136,7 @@ namespace ASDCP { // The frame buffer's PlaintextOffset parameter will be set to the first // byte of the data segment. Set this value to zero if you want // encrypted headers. - Result_t OpenReadFrame(const char* filename, FrameBuffer&) const; + Result_t OpenReadFrame(const std::string& filename, FrameBuffer&) const; // Fill a PictureDescriptor struct with the values from the file's codestream. // Returns RESULT_INIT if the file is not open. @@ -1154,7 +1166,7 @@ namespace ASDCP { // MXFWriter below. If the "pedantic" parameter is given and is true, the // parser will check the metadata for each codestream and fail if a // mismatch is detected. - Result_t OpenRead(const char* filename, bool pedantic = false) const; + Result_t OpenRead(const std::string& filename, bool pedantic = false) const; // Opens a file sequence for reading. The sequence is expected to contain one or // more filenames, each naming a file containing the codestream for exactly one @@ -1202,7 +1214,7 @@ namespace ASDCP { // Open the file for writing. The file must not exist. Returns error if // the operation cannot be completed or if nonsensical data is discovered // in the essence descriptor. - Result_t OpenWrite(const char* filename, const WriterInfo&, + Result_t OpenWrite(const std::string& filename, const WriterInfo&, const PictureDescriptor&, ui32_t HeaderSize = 16384); // Writes a frame of essence to the MXF file. If the optional AESEncContext @@ -1234,7 +1246,7 @@ namespace ASDCP { // Open the file for reading. The file must exist. Returns error if the // operation cannot be completed. - Result_t OpenRead(const char* filename) const; + Result_t OpenRead(const std::string& filename) const; // Returns RESULT_INIT if the file is not open. Result_t Close() const; @@ -1307,7 +1319,7 @@ namespace ASDCP { // Open the file for writing. The file must not exist. Returns error if // the operation cannot be completed or if nonsensical data is discovered // in the essence descriptor. - Result_t OpenWrite(const char* filename, const WriterInfo&, + Result_t OpenWrite(const std::string& filename, const WriterInfo&, const PictureDescriptor&, ui32_t HeaderSize = 16384); // Writes a pair of frames of essence to the MXF file. If the optional AESEncContext @@ -1349,7 +1361,7 @@ namespace ASDCP { // Open the file for reading. The file must exist. Returns error if the // operation cannot be completed. - Result_t OpenRead(const char* filename) const; + Result_t OpenRead(const std::string& filename) const; // Returns RESULT_INIT if the file is not open. Result_t Close() const; @@ -1486,12 +1498,12 @@ namespace ASDCP { // Opens an XML file for reading, parses data to provide a complete // set of stream metadata for the MXFWriter below. - Result_t OpenRead(const char* filename) const; + Result_t OpenRead(const std::string& filename) const; // Parses an XML document to provide a complete set of stream metadata // for the MXFWriter below. The optional filename argument is used to // initialize the default resource resolver (see ReadAncillaryResource). - Result_t OpenRead(const std::string& xml_doc, const char* filename = 0) const; + Result_t OpenRead(const std::string& xml_doc, const std::string& filename) const; // Fill a TimedTextDescriptor struct with the values from the file's contents. // Returns RESULT_INIT if the file is not open. @@ -1531,7 +1543,7 @@ namespace ASDCP { // Open the file for writing. The file must not exist. Returns error if // the operation cannot be completed or if nonsensical data is discovered // in the essence descriptor. - Result_t OpenWrite(const char* filename, const WriterInfo&, + Result_t OpenWrite(const std::string& filename, const WriterInfo&, const TimedTextDescriptor&, ui32_t HeaderSize = 16384); // Writes the Timed-Text Resource to the MXF file. The file must be UTF-8 @@ -1573,7 +1585,7 @@ namespace ASDCP { // Open the file for reading. The file must exist. Returns error if the // operation cannot be completed. - Result_t OpenRead(const char* filename) const; + Result_t OpenRead(const std::string& filename) const; // Returns RESULT_INIT if the file is not open. Result_t Close() const; @@ -1662,7 +1674,7 @@ namespace ASDCP { // The frame buffer's PlaintextOffset parameter will be set to the first // byte of the data segment. Set this value to zero if you want // encrypted headers. - Result_t OpenReadFrame(const char* filename, FrameBuffer&) const; + Result_t OpenReadFrame(const std::string& filename, FrameBuffer&) const; // Fill a DCDataDescriptor struct with the values from the file's bytestream. // Returns RESULT_INIT if the file is not open. @@ -1684,7 +1696,7 @@ namespace ASDCP { // more files, each containing the bytestream for exactly one frame. The files // must be named such that the frames are in temporal order when sorted // alphabetically by filename. - Result_t OpenRead(const char* filename) const; + Result_t OpenRead(const std::string& filename) const; // Opens a file sequence for reading. The sequence is expected to contain one or // more filenames, each naming a file containing the bytestream for exactly one @@ -1727,7 +1739,7 @@ namespace ASDCP { // Open the file for writing. The file must not exist. Returns error if // the operation cannot be completed or if nonsensical data is discovered // in the essence descriptor. - Result_t OpenWrite(const char* filename, const WriterInfo&, + Result_t OpenWrite(const std::string& filename, const WriterInfo&, const DCDataDescriptor&, ui32_t HeaderSize = 16384); // Writes a frame of essence to the MXF file. If the optional AESEncContext @@ -1759,7 +1771,7 @@ namespace ASDCP { // Open the file for reading. The file must exist. Returns error if the // operation cannot be completed. - Result_t OpenRead(const char* filename) const; + Result_t OpenRead(const std::string& filename) const; // Returns RESULT_INIT if the file is not open. Result_t Close() const; @@ -1812,7 +1824,7 @@ namespace ASDCP { // Print debugging information to stream (stderr default) void AtmosDescriptorDump(const AtmosDescriptor&, FILE* = 0); // Determine if a file is a raw atmos file - bool IsDolbyAtmos(const char* filename); + bool IsDolbyAtmos(const std::string& filename); // class MXFWriter @@ -1835,7 +1847,7 @@ namespace ASDCP { // Open the file for writing. The file must not exist. Returns error if // the operation cannot be completed or if nonsensical data is discovered // in the essence descriptor. - Result_t OpenWrite(const char* filename, const WriterInfo&, + Result_t OpenWrite(const std::string& filename, const WriterInfo&, const AtmosDescriptor&, ui32_t HeaderSize = 16384); // Writes a frame of essence to the MXF file. If the optional AESEncContext @@ -1867,7 +1879,7 @@ namespace ASDCP { // Open the file for reading. The file must exist. Returns error if the // operation cannot be completed. - Result_t OpenRead(const char* filename) const; + Result_t OpenRead(const std::string& filename) const; // Returns RESULT_INIT if the file is not open. Result_t Close() const; diff --git a/src/AS_DCP_ATMOS.cpp b/src/AS_DCP_ATMOS.cpp index e8a2a8a..7fa8c09 100644 --- a/src/AS_DCP_ATMOS.cpp +++ b/src/AS_DCP_ATMOS.cpp @@ -93,11 +93,11 @@ ASDCP::ATMOS::AtmosDescriptorDump(const AtmosDescriptor& ADesc, FILE* stream) // bool -ASDCP::ATMOS::IsDolbyAtmos(const char* filename) +ASDCP::ATMOS::IsDolbyAtmos(const std::string& filename) { // TODO // For now use an atmos extension - bool result = (0 == (std::string("atmos").compare(Kumu::PathGetExtension(std::string(filename))))); + bool result = ( 0 == (std::string("atmos").compare(Kumu::PathGetExtension(filename))) ); return result; } @@ -118,7 +118,7 @@ class ASDCP::ATMOS::MXFReader::h__Reader : public ASDCP::DCData::h__Reader h__Reader(const Dictionary& d) : DCData::h__Reader(d), m_EssenceSubDescriptor(NULL), m_ADesc() {} virtual ~h__Reader() {} - Result_t OpenRead(const char*); + Result_t OpenRead(const std::string&); Result_t MD_to_Atmos_ADesc(ATMOS::AtmosDescriptor& ADesc); }; @@ -142,7 +142,7 @@ ASDCP::ATMOS::MXFReader::h__Reader::MD_to_Atmos_ADesc(ATMOS::AtmosDescriptor& AD // // ASDCP::Result_t -ASDCP::ATMOS::MXFReader::h__Reader::OpenRead(const char* filename) +ASDCP::ATMOS::MXFReader::h__Reader::OpenRead(const std::string& filename) { Result_t result = DCData::h__Reader::OpenRead(filename); @@ -234,7 +234,7 @@ ASDCP::ATMOS::MXFReader::RIP() // Open the file for reading. The file must exist. Returns error if the // operation cannot be completed. ASDCP::Result_t -ASDCP::ATMOS::MXFReader::OpenRead(const char* filename) const +ASDCP::ATMOS::MXFReader::OpenRead(const std::string& filename) const { return m_Reader->OpenRead(filename); } @@ -334,7 +334,7 @@ class ASDCP::ATMOS::MXFWriter::h__Writer : public DCData::h__Writer virtual ~h__Writer(){} - Result_t OpenWrite(const char*, ui32_t HeaderSize, const AtmosDescriptor& ADesc); + Result_t OpenWrite(const std::string&, ui32_t HeaderSize, const AtmosDescriptor& ADesc); Result_t Atmos_ADesc_to_MD(const AtmosDescriptor& ADesc); }; @@ -355,7 +355,7 @@ ASDCP::ATMOS::MXFWriter::h__Writer::Atmos_ADesc_to_MD(const AtmosDescriptor& ADe // ASDCP::Result_t -ASDCP::ATMOS::MXFWriter::h__Writer::OpenWrite(const char* filename, ui32_t HeaderSize, const AtmosDescriptor& ADesc) +ASDCP::ATMOS::MXFWriter::h__Writer::OpenWrite(const std::string& filename, ui32_t HeaderSize, const AtmosDescriptor& ADesc) { m_EssenceSubDescriptor = new DolbyAtmosSubDescriptor(m_Dict); @@ -436,7 +436,7 @@ ASDCP::ATMOS::MXFWriter::RIP() // Open the file for writing. The file must not exist. Returns error if // the operation cannot be completed. ASDCP::Result_t -ASDCP::ATMOS::MXFWriter::OpenWrite(const char* filename, const WriterInfo& Info, +ASDCP::ATMOS::MXFWriter::OpenWrite(const std::string& filename, const WriterInfo& Info, const AtmosDescriptor& ADesc, ui32_t HeaderSize) { if ( Info.LabelSetType != LS_MXF_SMPTE ) diff --git a/src/AS_DCP_DCData.cpp b/src/AS_DCP_DCData.cpp index a1bb043..e145e1f 100644 --- a/src/AS_DCP_DCData.cpp +++ b/src/AS_DCP_DCData.cpp @@ -91,7 +91,7 @@ ASDCP::DCData::h__Reader::MD_to_DCData_DDesc(DCData::DCDataDescriptor& DDesc) // // ASDCP::Result_t -ASDCP::DCData::h__Reader::OpenRead(const char* filename) +ASDCP::DCData::h__Reader::OpenRead(const std::string& filename) { Result_t result = OpenMXFRead(filename); @@ -244,7 +244,7 @@ ASDCP::DCData::MXFReader::RIP() // Open the file for reading. The file must exist. Returns error if the // operation cannot be completed. ASDCP::Result_t -ASDCP::DCData::MXFReader::OpenRead(const char* filename) const +ASDCP::DCData::MXFReader::OpenRead(const std::string& filename) const { return m_Reader->OpenRead(filename); } @@ -346,7 +346,7 @@ ASDCP::DCData::h__Writer::DCData_DDesc_to_MD(DCData::DCDataDescriptor& DDesc) // ASDCP::Result_t -ASDCP::DCData::h__Writer::OpenWrite(char const* filename, ui32_t HeaderSize, +ASDCP::DCData::h__Writer::OpenWrite(const std::string& filename, ui32_t HeaderSize, const SubDescriptorList_t& subDescriptors) { if ( ! m_State.Test_BEGIN() ) @@ -534,7 +534,7 @@ ASDCP::DCData::MXFWriter::RIP() // Open the file for writing. The file must not exist. Returns error if // the operation cannot be completed. ASDCP::Result_t -ASDCP::DCData::MXFWriter::OpenWrite(const char* filename, const WriterInfo& Info, +ASDCP::DCData::MXFWriter::OpenWrite(const std::string& filename, const WriterInfo& Info, const DCDataDescriptor& DDesc, ui32_t HeaderSize) { if ( Info.LabelSetType != LS_MXF_SMPTE ) diff --git a/src/AS_DCP_DCData_internal.h b/src/AS_DCP_DCData_internal.h index 93ccb7e..a9e510d 100644 --- a/src/AS_DCP_DCData_internal.h +++ b/src/AS_DCP_DCData_internal.h @@ -60,7 +60,7 @@ namespace DCData h__Reader(const Dictionary& d) : ASDCP::h__ASDCPReader(d), m_EssenceDescriptor(0), m_DDesc() {} ~h__Reader() {} - Result_t OpenRead(const char*); + Result_t OpenRead(const std::string&); Result_t ReadFrame(ui32_t, FrameBuffer&, AESDecContext*, HMACContext*); Result_t MD_to_DCData_DDesc(DCData::DCDataDescriptor& DDesc); }; @@ -80,7 +80,7 @@ namespace DCData ~h__Writer(){} - Result_t OpenWrite(const char*, ui32_t HeaderSize, const SubDescriptorList_t& subDescriptors); + Result_t OpenWrite(const std::string&, ui32_t HeaderSize, const SubDescriptorList_t& subDescriptors); Result_t SetSourceStream(const DCDataDescriptor&, const byte_t*, const std::string&, const std::string&); Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0); Result_t Finalize(); diff --git a/src/AS_DCP_JP2K.cpp b/src/AS_DCP_JP2K.cpp index 1b3bc54..62c9e78 100755 --- a/src/AS_DCP_JP2K.cpp +++ b/src/AS_DCP_JP2K.cpp @@ -339,7 +339,7 @@ public: virtual ~lh__Reader() {} - Result_t OpenRead(const char*, EssenceType_t); + Result_t OpenRead(const std::string&, EssenceType_t); Result_t ReadFrame(ui32_t, JP2K::FrameBuffer&, AESDecContext*, HMACContext*); }; @@ -347,7 +347,7 @@ public: // // ASDCP::Result_t -lh__Reader::OpenRead(const char* filename, EssenceType_t type) +lh__Reader::OpenRead(const std::string& filename, EssenceType_t type) { Result_t result = OpenMXFRead(filename); @@ -582,7 +582,7 @@ ASDCP::JP2K::MXFReader::RIP() // Open the file for reading. The file must exist. Returns error if the // operation cannot be completed. ASDCP::Result_t -ASDCP::JP2K::MXFReader::OpenRead(const char* filename) const +ASDCP::JP2K::MXFReader::OpenRead(const std::string& filename) const { return m_Reader->OpenRead(filename, ASDCP::ESS_JPEG_2000); } @@ -809,7 +809,7 @@ ASDCP::JP2K::MXFSReader::RIP() // Open the file for reading. The file must exist. Returns error if the // operation cannot be completed. ASDCP::Result_t -ASDCP::JP2K::MXFSReader::OpenRead(const char* filename) const +ASDCP::JP2K::MXFSReader::OpenRead(const std::string& filename) const { return m_Reader->OpenRead(filename, ASDCP::ESS_JPEG_2000_S); } @@ -929,7 +929,7 @@ public: virtual ~lh__Writer(){} - Result_t OpenWrite(const char*, EssenceType_t type, ui32_t HeaderSize); + Result_t OpenWrite(const std::string&, EssenceType_t type, ui32_t HeaderSize); Result_t SetSourceStream(const PictureDescriptor&, const std::string& label, ASDCP::Rational LocalEditRate = ASDCP::Rational(0,0)); Result_t WriteFrame(const JP2K::FrameBuffer&, bool add_index, AESEncContext*, HMACContext*); @@ -939,7 +939,7 @@ public: // Open the file for writing. The file must not exist. Returns error if // the operation cannot be completed. ASDCP::Result_t -lh__Writer::OpenWrite(const char* filename, EssenceType_t type, ui32_t HeaderSize) +lh__Writer::OpenWrite(const std::string& filename, EssenceType_t type, ui32_t HeaderSize) { if ( ! m_State.Test_BEGIN() ) return RESULT_STATE; @@ -1137,7 +1137,7 @@ ASDCP::JP2K::MXFWriter::RIP() // Open the file for writing. The file must not exist. Returns error if // the operation cannot be completed. ASDCP::Result_t -ASDCP::JP2K::MXFWriter::OpenWrite(const char* filename, const WriterInfo& Info, +ASDCP::JP2K::MXFWriter::OpenWrite(const std::string& filename, const WriterInfo& Info, const PictureDescriptor& PDesc, ui32_t HeaderSize) { if ( Info.LabelSetType == LS_MXF_SMPTE ) @@ -1283,7 +1283,7 @@ ASDCP::JP2K::MXFSWriter::RIP() // Open the file for writing. The file must not exist. Returns error if // the operation cannot be completed. ASDCP::Result_t -ASDCP::JP2K::MXFSWriter::OpenWrite(const char* filename, const WriterInfo& Info, +ASDCP::JP2K::MXFSWriter::OpenWrite(const std::string& filename, const WriterInfo& Info, const PictureDescriptor& PDesc, ui32_t HeaderSize) { if ( Info.LabelSetType == LS_MXF_SMPTE ) diff --git a/src/AS_DCP_MPEG2.cpp b/src/AS_DCP_MPEG2.cpp index 21991bf..8353ea4 100755 --- a/src/AS_DCP_MPEG2.cpp +++ b/src/AS_DCP_MPEG2.cpp @@ -170,7 +170,7 @@ public: h__Reader(const Dictionary& d) : ASDCP::h__ASDCPReader(d) {} virtual ~h__Reader() {} - Result_t OpenRead(const char*); + Result_t OpenRead(const std::string&); Result_t ReadFrame(ui32_t, FrameBuffer&, AESDecContext*, HMACContext*); Result_t ReadFrameGOPStart(ui32_t, FrameBuffer&, AESDecContext*, HMACContext*); Result_t FindFrameGOPStart(ui32_t, ui32_t&); @@ -181,7 +181,7 @@ public: // // ASDCP::Result_t -ASDCP::MPEG2::MXFReader::h__Reader::OpenRead(const char* filename) +ASDCP::MPEG2::MXFReader::h__Reader::OpenRead(const std::string& filename) { Result_t result = OpenMXFRead(filename); @@ -385,7 +385,7 @@ ASDCP::MPEG2::MXFReader::RIP() // Open the file for reading. The file must exist. Returns error if the // operation cannot be completed. ASDCP::Result_t -ASDCP::MPEG2::MXFReader::OpenRead(const char* filename) const +ASDCP::MPEG2::MXFReader::OpenRead(const std::string& filename) const { return m_Reader->OpenRead(filename); } @@ -521,7 +521,7 @@ public: virtual ~h__Writer(){} - Result_t OpenWrite(const char*, ui32_t HeaderSize); + Result_t OpenWrite(const std::string&, ui32_t HeaderSize); Result_t SetSourceStream(const VideoDescriptor&); Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0); Result_t Finalize(); @@ -531,7 +531,7 @@ public: // Open the file for writing. The file must not exist. Returns error if // the operation cannot be completed. ASDCP::Result_t -ASDCP::MPEG2::MXFWriter::h__Writer::OpenWrite(const char* filename, ui32_t HeaderSize) +ASDCP::MPEG2::MXFWriter::h__Writer::OpenWrite(const std::string& filename, ui32_t HeaderSize) { if ( ! m_State.Test_BEGIN() ) return RESULT_STATE; @@ -568,6 +568,8 @@ ASDCP::MPEG2::MXFWriter::h__Writer::SetSourceStream(const VideoDescriptor& VDesc if ( ASDCP_SUCCESS(result) ) { + m_FooterPart.SetDeltaParams(IndexTableSegment::DeltaEntry(-1, 0, 0)); + result = WriteASDCPHeader(MPEG_PACKAGE_LABEL, UL(m_Dict->ul(MDD_MPEG2_VESWrappingFrame)), PICT_DEF_LABEL, UL(m_EssenceUL), UL(m_Dict->ul(MDD_PictureDataDef)), m_VDesc.EditRate, derive_timecode_rate_from_edit_rate(m_VDesc.EditRate)); @@ -711,7 +713,7 @@ ASDCP::MPEG2::MXFWriter::RIP() // Open the file for writing. The file must not exist. Returns error if // the operation cannot be completed. ASDCP::Result_t -ASDCP::MPEG2::MXFWriter::OpenWrite(const char* filename, const WriterInfo& Info, +ASDCP::MPEG2::MXFWriter::OpenWrite(const std::string& filename, const WriterInfo& Info, const VideoDescriptor& VDesc, ui32_t HeaderSize) { if ( Info.LabelSetType == LS_MXF_SMPTE ) diff --git a/src/AS_DCP_MXF.cpp b/src/AS_DCP_MXF.cpp index f3ad310..82ec81c 100755 --- a/src/AS_DCP_MXF.cpp +++ b/src/AS_DCP_MXF.cpp @@ -161,14 +161,12 @@ ASDCP::MD_to_CryptoInfo(CryptographicContext* InfoObj, WriterInfo& Info, const D // // ASDCP::Result_t -ASDCP::EssenceType(const char* filename, EssenceType_t& type) +ASDCP::EssenceType(const std::string& filename, EssenceType_t& type) { const Dictionary* m_Dict = &DefaultCompositeDict(); InterchangeObject* md_object = 0; assert(m_Dict); - - ASDCP_TEST_NULL_STR(filename); Kumu::FileReader Reader; OP1aHeader TestHeader(m_Dict); @@ -180,47 +178,80 @@ ASDCP::EssenceType(const char* filename, EssenceType_t& type) if ( ASDCP_SUCCESS(result) ) { type = ESS_UNKNOWN; - if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(JPEG2000PictureSubDescriptor))) ) + + if ( TestHeader.OperationalPattern == UL(m_Dict->ul(MDD_OPAtom)) + || TestHeader.OperationalPattern == UL(m_Dict->ul(MDD_MXFInterop_OPAtom)) ) { - if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(StereoscopicPictureSubDescriptor))) ) + if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(JPEG2000PictureSubDescriptor))) ) { - type = ESS_JPEG_2000_S; + if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(StereoscopicPictureSubDescriptor))) ) + { + type = ESS_JPEG_2000_S; + } + else + { + type = ESS_JPEG_2000; + } } - else + else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(WaveAudioDescriptor), &md_object)) ) { - type = ESS_JPEG_2000; + assert(md_object); + if ( static_cast<ASDCP::MXF::WaveAudioDescriptor*>(md_object)->AudioSamplingRate == SampleRate_96k ) + { + type = ESS_PCM_24b_96k; + } + else + { + type = ESS_PCM_24b_48k; + } } - } - else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(WaveAudioDescriptor), &md_object)) ) - { - assert(md_object); - if ( static_cast<ASDCP::MXF::WaveAudioDescriptor*>(md_object)->AudioSamplingRate == SampleRate_96k ) + else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(MPEG2VideoDescriptor))) ) { - type = ESS_PCM_24b_96k; + type = ESS_MPEG2_VES; } - else + else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(TimedTextDescriptor))) ) { - type = ESS_PCM_24b_48k; + type = ESS_TIMED_TEXT; + } + else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(DCDataDescriptor))) ) + { + if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(DolbyAtmosSubDescriptor))) ) + { + type = ESS_DCDATA_DOLBY_ATMOS; + } + else + { + type = ESS_DCDATA_UNKNOWN; + } } } - else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(MPEG2VideoDescriptor))) ) - { - type = ESS_MPEG2_VES; - } - else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(TimedTextDescriptor))) ) - { - type = ESS_TIMED_TEXT; - } - else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(DCDataDescriptor))) ) + else if ( TestHeader.OperationalPattern == UL(m_Dict->ul(MDD_OP1a)) ) { - if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(DolbyAtmosSubDescriptor))) ) + if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(JPEG2000PictureSubDescriptor))) ) { - type = ESS_DCDATA_DOLBY_ATMOS; + type = ESS_AS02_JPEG_2000; } - else + else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(WaveAudioDescriptor), &md_object)) ) { - type = ESS_DCDATA_UNKNOWN; + assert(md_object); + if ( static_cast<ASDCP::MXF::WaveAudioDescriptor*>(md_object)->AudioSamplingRate == SampleRate_96k ) + { + type = ESS_AS02_PCM_24b_96k; + } + else + { + type = ESS_AS02_PCM_24b_48k; + } } + else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(TimedTextDescriptor))) ) + { + type = ESS_AS02_TIMED_TEXT; + } + } + else + { + DefaultLogSink().Error("Unsupported MXF Operational Pattern.\n"); + return RESULT_FORMAT; } } @@ -229,9 +260,8 @@ ASDCP::EssenceType(const char* filename, EssenceType_t& type) // ASDCP::Result_t -ASDCP::RawEssenceType(const char* filename, EssenceType_t& type) +ASDCP::RawEssenceType(const std::string& filename, EssenceType_t& type) { - ASDCP_TEST_NULL_STR(filename); type = ESS_UNKNOWN; ASDCP::FrameBuffer FB; Kumu::FileReader Reader; @@ -317,10 +347,7 @@ ASDCP::RawEssenceType(const char* filename, EssenceType_t& type) if ( next_file[0] == '.' ) // no hidden files or internal links continue; - std::string Str(filename); - Str += "/"; - Str += next_file; - result = Reader.OpenRead(Str.c_str()); + result = Reader.OpenRead(Kumu::PathJoin(filename, next_file)); if ( ASDCP_SUCCESS(result) ) { @@ -354,7 +381,7 @@ ASDCP::RawEssenceType(const char* filename, EssenceType_t& type) return RESULT_FORMAT; } } - else if ( ASDCP::ATMOS::IsDolbyAtmos(Str.c_str()) ) + else if ( ASDCP::ATMOS::IsDolbyAtmos(Kumu::PathJoin(filename, next_file)) ) { type = ESS_DCDATA_DOLBY_ATMOS; } diff --git a/src/AS_DCP_PCM.cpp b/src/AS_DCP_PCM.cpp index 8011a55..88ccd1f 100755 --- a/src/AS_DCP_PCM.cpp +++ b/src/AS_DCP_PCM.cpp @@ -77,6 +77,10 @@ ASDCP::PCM_ADesc_to_MD(PCM::AudioDescriptor& ADesc, MXF::WaveAudioDescriptor* AD case PCM::CF_CFG_5: ADescObj->ChannelAssignment = DefaultSMPTEDict().Type(MDD_DCAudioChannelCfg_5_7p1_DS).ul; break; + + case PCM::CF_CFG_6: + ADescObj->ChannelAssignment = DefaultSMPTEDict().Type(MDD_DCAudioChannelCfg_MCA).ul; + break; } return RESULT_OK; @@ -116,6 +120,9 @@ ASDCP::MD_to_PCM_ADesc(MXF::WaveAudioDescriptor* ADescObj, PCM::AudioDescriptor& else if ( ADescObj->ChannelAssignment == DefaultSMPTEDict().Type(MDD_DCAudioChannelCfg_5_7p1_DS).ul ) ADesc.ChannelFormat = PCM::CF_CFG_5; + + else if ( ADescObj->ChannelAssignment == DefaultSMPTEDict().Type(MDD_DCAudioChannelCfg_MCA).ul ) + ADesc.ChannelFormat = PCM::CF_CFG_6; } return RESULT_OK; @@ -161,6 +168,10 @@ ASDCP::PCM::operator << (std::ostream& strm, const AudioDescriptor& ADesc) case CF_CFG_5: strm << "Config 5 (7.1 DS with optional HI/VI)"; break; + + case CF_CFG_6: + strm << "Config 6 (ST 377-1 MCA)"; + break; } strm << std::endl; @@ -237,7 +248,7 @@ public: h__Reader(const Dictionary& d) : ASDCP::h__ASDCPReader(d) {} virtual ~h__Reader() {} - Result_t OpenRead(const char*); + Result_t OpenRead(const std::string&); Result_t ReadFrame(ui32_t, FrameBuffer&, AESDecContext*, HMACContext*); }; @@ -245,7 +256,7 @@ public: // // ASDCP::Result_t -ASDCP::PCM::MXFReader::h__Reader::OpenRead(const char* filename) +ASDCP::PCM::MXFReader::h__Reader::OpenRead(const std::string& filename) { Result_t result = OpenMXFRead(filename); @@ -397,7 +408,7 @@ ASDCP::PCM::MXFReader::RIP() // Open the file for reading. The file must exist. Returns error if the // operation cannot be completed. ASDCP::Result_t -ASDCP::PCM::MXFReader::OpenRead(const char* filename) const +ASDCP::PCM::MXFReader::OpenRead(const std::string& filename) const { return m_Reader->OpenRead(filename); } @@ -500,7 +511,7 @@ public: virtual ~h__Writer(){} - Result_t OpenWrite(const char*, ui32_t HeaderSize); + Result_t OpenWrite(const std::string&, ui32_t HeaderSize); Result_t SetSourceStream(const AudioDescriptor&); Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0); Result_t Finalize(); @@ -511,7 +522,7 @@ public: // Open the file for writing. The file must not exist. Returns error if // the operation cannot be completed. ASDCP::Result_t -ASDCP::PCM::MXFWriter::h__Writer::OpenWrite(const char* filename, ui32_t HeaderSize) +ASDCP::PCM::MXFWriter::h__Writer::OpenWrite(const std::string& filename, ui32_t HeaderSize) { if ( ! m_State.Test_BEGIN() ) return RESULT_STATE; @@ -682,7 +693,7 @@ ASDCP::PCM::MXFWriter::RIP() // Open the file for writing. The file must not exist. Returns error if // the operation cannot be completed. ASDCP::Result_t -ASDCP::PCM::MXFWriter::OpenWrite(const char* filename, const WriterInfo& Info, +ASDCP::PCM::MXFWriter::OpenWrite(const std::string& filename, const WriterInfo& Info, const AudioDescriptor& ADesc, ui32_t HeaderSize) { if ( Info.LabelSetType == LS_MXF_SMPTE ) diff --git a/src/AS_DCP_TimedText.cpp b/src/AS_DCP_TimedText.cpp index e5425b4..e158cde 100644 --- a/src/AS_DCP_TimedText.cpp +++ b/src/AS_DCP_TimedText.cpp @@ -139,7 +139,7 @@ public: virtual ~h__Reader() {} - Result_t OpenRead(const char*); + Result_t OpenRead(const std::string&); Result_t MD_to_TimedText_TDesc(TimedText::TimedTextDescriptor& TDesc); Result_t ReadTimedTextResource(FrameBuffer& FrameBuf, AESDecContext* Ctx, HMACContext* HMAC); Result_t ReadAncillaryResource(const byte_t*, FrameBuffer& FrameBuf, AESDecContext* Ctx, HMACContext* HMAC); @@ -201,7 +201,7 @@ ASDCP::TimedText::MXFReader::h__Reader::MD_to_TimedText_TDesc(TimedText::TimedTe // ASDCP::Result_t -ASDCP::TimedText::MXFReader::h__Reader::OpenRead(char const* filename) +ASDCP::TimedText::MXFReader::h__Reader::OpenRead(const std::string& filename) { Result_t result = OpenMXFRead(filename); @@ -385,7 +385,7 @@ ASDCP::TimedText::MXFReader::RIP() // Open the file for reading. The file must exist. Returns error if the // operation cannot be completed. ASDCP::Result_t -ASDCP::TimedText::MXFReader::OpenRead(const char* filename) const +ASDCP::TimedText::MXFReader::OpenRead(const std::string& filename) const { return m_Reader->OpenRead(filename); } @@ -506,7 +506,7 @@ public: virtual ~h__Writer() {} - Result_t OpenWrite(const char*, ui32_t HeaderSize); + Result_t OpenWrite(const std::string&, ui32_t HeaderSize); Result_t SetSourceStream(const TimedTextDescriptor&); Result_t WriteTimedTextResource(const std::string& XMLDoc, AESEncContext* = 0, HMACContext* = 0); Result_t WriteAncillaryResource(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0); @@ -532,7 +532,7 @@ ASDCP::TimedText::MXFWriter::h__Writer::TimedText_TDesc_to_MD(TimedText::TimedTe // ASDCP::Result_t -ASDCP::TimedText::MXFWriter::h__Writer::OpenWrite(char const* filename, ui32_t HeaderSize) +ASDCP::TimedText::MXFWriter::h__Writer::OpenWrite(const std::string& filename, ui32_t HeaderSize) { if ( ! m_State.Test_BEGIN() ) return RESULT_STATE; @@ -749,7 +749,7 @@ ASDCP::TimedText::MXFWriter::RIP() // Open the file for writing. The file must not exist. Returns error if // the operation cannot be completed. ASDCP::Result_t -ASDCP::TimedText::MXFWriter::OpenWrite(const char* filename, const WriterInfo& Info, +ASDCP::TimedText::MXFWriter::OpenWrite(const std::string& filename, const WriterInfo& Info, const TimedTextDescriptor& TDesc, ui32_t HeaderSize) { if ( Info.LabelSetType != LS_MXF_SMPTE ) diff --git a/src/AS_DCP_internal.h b/src/AS_DCP_internal.h index 675f96d..24020e5 100755 --- a/src/AS_DCP_internal.h +++ b/src/AS_DCP_internal.h @@ -213,7 +213,7 @@ namespace ASDCP const MXF::RIP& GetRIP() const { return m_RIP; } // - Result_t OpenMXFRead(const char* filename) + Result_t OpenMXFRead(const std::string& filename) { m_LastPosition = 0; Result_t result = m_File.OpenRead(filename); @@ -803,7 +803,7 @@ namespace ASDCP h__ASDCPReader(const Dictionary&); virtual ~h__ASDCPReader(); - Result_t OpenMXFRead(const char* filename); + Result_t OpenMXFRead(const std::string& filename); Result_t ReadEKLVFrame(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf, const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC); Result_t LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, diff --git a/src/DCData_ByteStream_Parser.cpp b/src/DCData_ByteStream_Parser.cpp index 73565d4..28e1869 100644 --- a/src/DCData_ByteStream_Parser.cpp +++ b/src/DCData_ByteStream_Parser.cpp @@ -52,9 +52,8 @@ public: ~h__BytestreamParser() {} - Result_t OpenReadFrame(const char* filename, FrameBuffer& FB) + Result_t OpenReadFrame(const std::string& filename, FrameBuffer& FB) { - ASDCP_TEST_NULL_STR(filename); m_File.Close(); Result_t result = m_File.OpenRead(filename); @@ -95,7 +94,7 @@ ASDCP::DCData::BytestreamParser::~BytestreamParser() // Opens the stream for reading, parses enough data to provide a complete // set of stream metadata for the MXFWriter below. ASDCP::Result_t -ASDCP::DCData::BytestreamParser::OpenReadFrame(const char* filename, FrameBuffer& FB) const +ASDCP::DCData::BytestreamParser::OpenReadFrame(const std::string& filename, FrameBuffer& FB) const { const_cast<ASDCP::DCData::BytestreamParser*>(this)->m_Parser = new h__BytestreamParser; return m_Parser->OpenReadFrame(filename, FB); diff --git a/src/DCData_Sequence_Parser.cpp b/src/DCData_Sequence_Parser.cpp index 45594c5..de9f39a 100644 --- a/src/DCData_Sequence_Parser.cpp +++ b/src/DCData_Sequence_Parser.cpp @@ -66,7 +66,7 @@ class ASDCP::DCData::FileList : public std::list<std::string> } // - Result_t InitFromDirectory(const char* path) + Result_t InitFromDirectory(const std::string& path) { char next_file[Kumu::MaxFilePath]; Kumu::DirScanner Scanner; @@ -125,7 +125,7 @@ class ASDCP::DCData::SequenceParser::h__SequenceParser Close(); } - Result_t OpenRead(const char* filename); + Result_t OpenRead(const std::string& filename); Result_t OpenRead(const std::list<std::string>& file_list); void Close() {} @@ -174,10 +174,8 @@ ASDCP::DCData::SequenceParser::h__SequenceParser::OpenRead() // ASDCP::Result_t -ASDCP::DCData::SequenceParser::h__SequenceParser::OpenRead(const char* filename) +ASDCP::DCData::SequenceParser::h__SequenceParser::OpenRead(const std::string& filename) { - ASDCP_TEST_NULL_STR(filename); - Result_t result = m_FileList.InitFromDirectory(filename); if ( ASDCP_SUCCESS(result) ) @@ -228,7 +226,7 @@ ASDCP::DCData::SequenceParser::~SequenceParser() // Opens the stream for reading, parses enough data to provide a complete // set of stream metadata for the MXFWriter below. ASDCP::Result_t -ASDCP::DCData::SequenceParser::OpenRead(const char* filename) const +ASDCP::DCData::SequenceParser::OpenRead(const std::string& filename) const { const_cast<ASDCP::DCData::SequenceParser*>(this)->m_Parser = new h__SequenceParser; diff --git a/src/JP2K_Codestream_Parser.cpp b/src/JP2K_Codestream_Parser.cpp index a1385d1..c820646 100755 --- a/src/JP2K_Codestream_Parser.cpp +++ b/src/JP2K_Codestream_Parser.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2004-2009, John Hurst +Copyright (c) 2004-2013, John Hurst All rights reserved. Redistribution and use in source and binary forms, with or without @@ -55,9 +55,8 @@ public: ~h__CodestreamParser() {} - Result_t OpenReadFrame(const char* filename, FrameBuffer& FB) + Result_t OpenReadFrame(const std::string& filename, FrameBuffer& FB) { - ASDCP_TEST_NULL_STR(filename); m_File.Close(); Result_t result = m_File.OpenRead(filename); @@ -198,7 +197,7 @@ ASDCP::JP2K::CodestreamParser::~CodestreamParser() // Opens the stream for reading, parses enough data to provide a complete // set of stream metadata for the MXFWriter below. ASDCP::Result_t -ASDCP::JP2K::CodestreamParser::OpenReadFrame(const char* filename, FrameBuffer& FB) const +ASDCP::JP2K::CodestreamParser::OpenReadFrame(const std::string& filename, FrameBuffer& FB) const { const_cast<ASDCP::JP2K::CodestreamParser*>(this)->m_Parser = new h__CodestreamParser; return m_Parser->OpenReadFrame(filename, FB); diff --git a/src/JP2K_Sequence_Parser.cpp b/src/JP2K_Sequence_Parser.cpp index c33321e..a0fd5d0 100755 --- a/src/JP2K_Sequence_Parser.cpp +++ b/src/JP2K_Sequence_Parser.cpp @@ -59,7 +59,7 @@ public: } // - Result_t InitFromDirectory(const char* path) + Result_t InitFromDirectory(const std::string& path) { char next_file[Kumu::MaxFilePath]; Kumu::DirScanner Scanner; @@ -119,7 +119,7 @@ public: Close(); } - Result_t OpenRead(const char* filename, bool pedantic); + Result_t OpenRead(const std::string& filename, bool pedantic); Result_t OpenRead(const std::list<std::string>& file_list, bool pedantic); void Close() {} @@ -168,9 +168,8 @@ ASDCP::JP2K::SequenceParser::h__SequenceParser::OpenRead() // ASDCP::Result_t -ASDCP::JP2K::SequenceParser::h__SequenceParser::OpenRead(const char* filename, bool pedantic) +ASDCP::JP2K::SequenceParser::h__SequenceParser::OpenRead(const std::string& filename, bool pedantic) { - ASDCP_TEST_NULL_STR(filename); m_Pedantic = pedantic; Result_t result = m_FileList.InitFromDirectory(filename); @@ -327,7 +326,7 @@ ASDCP::JP2K::SequenceParser::~SequenceParser() // Opens the stream for reading, parses enough data to provide a complete // set of stream metadata for the MXFWriter below. ASDCP::Result_t -ASDCP::JP2K::SequenceParser::OpenRead(const char* filename, bool pedantic) const +ASDCP::JP2K::SequenceParser::OpenRead(const std::string& filename, bool pedantic) const { const_cast<ASDCP::JP2K::SequenceParser*>(this)->m_Parser = new h__SequenceParser; diff --git a/src/KM_fileio.cpp b/src/KM_fileio.cpp index fdd4719..0866acd 100644 --- a/src/KM_fileio.cpp +++ b/src/KM_fileio.cpp @@ -684,9 +684,8 @@ Kumu::FileWriter::Writev(const byte_t* buf, ui32_t buf_len) // Kumu::Result_t -Kumu::FileReader::OpenRead(const char* filename) const +Kumu::FileReader::OpenRead(const std::string& filename) const { - KM_TEST_NULL_STR_L(filename); const_cast<FileReader*>(this)->m_Filename = filename; // suppress popup window on error @@ -809,15 +808,14 @@ Kumu::FileReader::Read(byte_t* buf, ui32_t buf_len, ui32_t* read_count) const // Kumu::Result_t -Kumu::FileWriter::OpenWrite(const char* filename) +Kumu::FileWriter::OpenWrite(const std::string& filename) { - KM_TEST_NULL_STR_L(filename); m_Filename = filename; // suppress popup window on error UINT prev = ::SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); - m_Handle = ::CreateFileA(filename, + m_Handle = ::CreateFileA(filename.c_str(), (GENERIC_WRITE|GENERIC_READ), // open for reading FILE_SHARE_READ, // share for reading NULL, // no security @@ -908,11 +906,10 @@ Kumu::FileWriter::Write(const byte_t* buf, ui32_t buf_len, ui32_t* bytes_written // Kumu::Result_t -Kumu::FileReader::OpenRead(const char* filename) const +Kumu::FileReader::OpenRead(const std::string& filename) const { - KM_TEST_NULL_STR_L(filename); const_cast<FileReader*>(this)->m_Filename = filename; - const_cast<FileReader*>(this)->m_Handle = open(filename, O_RDONLY, 0); + const_cast<FileReader*>(this)->m_Handle = open(filename.c_str(), O_RDONLY, 0); return ( m_Handle == -1L ) ? RESULT_FILEOPEN : RESULT_OK; } @@ -988,15 +985,14 @@ Kumu::FileReader::Read(byte_t* buf, ui32_t buf_len, ui32_t* read_count) const // Kumu::Result_t -Kumu::FileWriter::OpenWrite(const char* filename) +Kumu::FileWriter::OpenWrite(const std::string& filename) { - KM_TEST_NULL_STR_L(filename); m_Filename = filename; - m_Handle = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0664); + m_Handle = open(filename.c_str(), O_RDWR|O_CREAT|O_TRUNC, 0664); if ( m_Handle == -1L ) { - DefaultLogSink().Error("Error opening file %s: %s\n", filename, strerror(errno)); + DefaultLogSink().Error("Error opening file %s: %s\n", filename.c_str(), strerror(errno)); return RESULT_FILEOPEN; } @@ -1006,15 +1002,14 @@ Kumu::FileWriter::OpenWrite(const char* filename) // Kumu::Result_t -Kumu::FileWriter::OpenModify(const char* filename) +Kumu::FileWriter::OpenModify(const std::string& filename) { - KM_TEST_NULL_STR_L(filename); m_Filename = filename; - m_Handle = open(filename, O_RDWR|O_CREAT, 0664); + m_Handle = open(filename.c_str(), O_RDWR|O_CREAT, 0664); if ( m_Handle == -1L ) { - DefaultLogSink().Error("Error opening file %s: %s\n", filename, strerror(errno)); + DefaultLogSink().Error("Error opening file %s: %s\n", filename.c_str(), strerror(errno)); return RESULT_FILEOPEN; } @@ -1080,15 +1075,13 @@ Kumu::FileWriter::Write(const byte_t* buf, ui32_t buf_len, ui32_t* bytes_written // Kumu::Result_t -Kumu::ReadFileIntoString(const char* filename, std::string& outString, ui32_t max_size) +Kumu::ReadFileIntoString(const std::string& filename, std::string& outString, ui32_t max_size) { fsize_t fsize = 0; ui32_t read_size = 0; FileReader File; ByteString ReadBuf; - KM_TEST_NULL_STR_L(filename); - Result_t result = File.OpenRead(filename); if ( KM_SUCCESS(result) ) @@ -1097,13 +1090,13 @@ Kumu::ReadFileIntoString(const char* filename, std::string& outString, ui32_t ma if ( fsize > (Kumu::fpos_t)max_size ) { - DefaultLogSink().Error("%s: exceeds available buffer size (%u)\n", filename, max_size); + DefaultLogSink().Error("%s: exceeds available buffer size (%u)\n", filename.c_str(), max_size); return RESULT_ALLOC; } if ( fsize == 0 ) { - DefaultLogSink().Error("%s: zero file size\n", filename); + DefaultLogSink().Error("%s: zero file size\n", filename.c_str()); return RESULT_READFAIL; } @@ -1122,11 +1115,10 @@ Kumu::ReadFileIntoString(const char* filename, std::string& outString, ui32_t ma // Kumu::Result_t -Kumu::WriteStringIntoFile(const char* filename, const std::string& inString) +Kumu::WriteStringIntoFile(const std::string& filename, const std::string& inString) { FileWriter File; ui32_t write_count = 0; - KM_TEST_NULL_STR_L(filename); Result_t result = File.OpenWrite(filename); @@ -1152,7 +1144,7 @@ Kumu::ReadFileIntoObject(const std::string& Filename, Kumu::IArchive& Object, ui ui32_t read_count = 0; FileWriter Reader; - result = Reader.OpenRead(Filename.c_str()); + result = Reader.OpenRead(Filename); if ( KM_SUCCESS(result) ) result = Reader.Read(Buffer.Data(), file_size, &read_count); @@ -1187,7 +1179,7 @@ Kumu::WriteObjectIntoFile(const Kumu::IArchive& Object, const std::string& Filen if ( KM_SUCCESS(result) ) { Buffer.Length(MemWriter.Length()); - result = Writer.OpenWrite(Filename.c_str()); + result = Writer.OpenWrite(Filename); } if ( KM_SUCCESS(result) ) @@ -1212,7 +1204,7 @@ Kumu::ReadFileIntoBuffer(const std::string& Filename, Kumu::ByteString& Buffer, ui32_t read_count = 0; FileWriter Reader; - result = Reader.OpenRead(Filename.c_str()); + result = Reader.OpenRead(Filename); if ( KM_SUCCESS(result) ) result = Reader.Read(Buffer.Data(), file_size, &read_count); @@ -1236,7 +1228,7 @@ Kumu::WriteBufferIntoFile(const Kumu::ByteString& Buffer, const std::string& Fil ui32_t write_count = 0; FileWriter Writer; - Result_t result = Writer.OpenWrite(Filename.c_str()); + Result_t result = Writer.OpenWrite(Filename); if ( KM_SUCCESS(result) ) result = Writer.Write(Buffer.RoData(), Buffer.Length(), &write_count); @@ -1261,18 +1253,16 @@ Kumu::DirScanner::DirScanner(void) : m_Handle(-1) {} // // Result_t -Kumu::DirScanner::Open(const char* filename) +Kumu::DirScanner::Open(const std::string& filename) { - KM_TEST_NULL_STR_L(filename); - // we need to append a '*' to read the entire directory - ui32_t fn_len = strlen(filename); + ui32_t fn_len = filename.size(); char* tmp_file = (char*)malloc(fn_len + 8); if ( tmp_file == 0 ) return RESULT_ALLOC; - strcpy(tmp_file, filename); + strcpy(tmp_file, filename.c_str()); char* p = &tmp_file[fn_len] - 1; if ( *p != '/' && *p != '\\' ) @@ -1348,13 +1338,11 @@ Kumu::DirScanner::DirScanner(void) : m_Handle(NULL) {} // Result_t -Kumu::DirScanner::Open(const char* filename) +Kumu::DirScanner::Open(const std::string& dirname) { - KM_TEST_NULL_STR_L(filename); - Result_t result = RESULT_OK; - if ( ( m_Handle = opendir(filename) ) == NULL ) + if ( ( m_Handle = opendir(dirname.c_str()) ) == NULL ) { switch ( errno ) { @@ -1370,7 +1358,7 @@ Kumu::DirScanner::Open(const char* filename) case ENFILE: result = RESULT_STATE; default: - DefaultLogSink().Error("DirScanner::Open(%s): %s\n", filename, strerror(errno)); + DefaultLogSink().Error("DirScanner::Open(%s): %s\n", dirname.c_str(), strerror(errno)); result = RESULT_FAIL; } } diff --git a/src/KM_fileio.h b/src/KM_fileio.h index a051e8e..46e2000 100755 --- a/src/KM_fileio.h +++ b/src/KM_fileio.h @@ -65,7 +65,7 @@ namespace Kumu DirScanner(void); ~DirScanner() { Close(); } - Result_t Open(const char*); + Result_t Open(const std::string&); Result_t Close(); Result_t GetNext(char*); }; @@ -242,10 +242,10 @@ namespace Kumu // Instant IO for strings // // Reads an entire file into a string. - Result_t ReadFileIntoString(const char* filename, std::string& outString, ui32_t max_size = 8 * Megabyte); + Result_t ReadFileIntoString(const std::string& filename, std::string& outString, ui32_t max_size = 8 * Megabyte); // Writes a string to a file, overwrites the existing file if present. - Result_t WriteStringIntoFile(const char* filename, const std::string& inString); + Result_t WriteStringIntoFile(const std::string& filename, const std::string& inString); // Instant IO for archivable objects // @@ -282,7 +282,7 @@ namespace Kumu FileReader() : m_Handle(INVALID_HANDLE_VALUE) {} virtual ~FileReader() { Close(); } - Result_t OpenRead(const char*) const; // open the file for reading + Result_t OpenRead(const std::string&) const; // open the file for reading Result_t Close() const; // close the file fsize_t Size() const; // returns the file's current size Result_t Seek(Kumu::fpos_t = 0, SeekPos_t = SP_BEGIN) const; // move the file pointer @@ -312,8 +312,8 @@ namespace Kumu FileWriter(); virtual ~FileWriter(); - Result_t OpenWrite(const char*); // open a new file, overwrites existing - Result_t OpenModify(const char*); // open a file for read/write + Result_t OpenWrite(const std::string&); // open a new file, overwrites existing + Result_t OpenModify(const std::string&); // open a file for read/write // this part of the interface takes advantage of the iovec structure on // platforms that support it. For each call to Writev(const byte_t*, ui32_t, ui32_t*), diff --git a/src/MPEG2_Parser.cpp b/src/MPEG2_Parser.cpp index 140a53f..89abbfd 100755 --- a/src/MPEG2_Parser.cpp +++ b/src/MPEG2_Parser.cpp @@ -371,7 +371,7 @@ public: h__Parser() : m_TmpBuffer(VESReadSize*8) {} ~h__Parser() { Close(); } - Result_t OpenRead(const char* filename); + Result_t OpenRead(const std::string& filename); void Close(); Result_t Reset(); Result_t ReadFrame(FrameBuffer&); @@ -399,9 +399,8 @@ ASDCP::MPEG2::Parser::h__Parser::Close() // ASDCP::Result_t -ASDCP::MPEG2::Parser::h__Parser::OpenRead(const char* filename) +ASDCP::MPEG2::Parser::h__Parser::OpenRead(const std::string& filename) { - ASDCP_TEST_NULL_STR(filename) ui32_t read_count = 0; Result_t result = m_FileReader.OpenRead(filename); @@ -443,7 +442,7 @@ ASDCP::MPEG2::Parser::h__Parser::OpenRead(const char* filename) if ( ASDCP_FAILURE(result) ) { - DefaultLogSink().Error("Unable to identify a wrapping mode for the essence in file \"%s\"\n", filename); + DefaultLogSink().Error("Unable to identify a wrapping mode for the essence in file \"%s\"\n", filename.c_str()); m_FileReader.Close(); } @@ -566,7 +565,7 @@ ASDCP::MPEG2::Parser::~Parser() // Opens the stream for reading, parses enough data to provide a complete // set of stream metadata for the MXFWriter below. ASDCP::Result_t -ASDCP::MPEG2::Parser::OpenRead(const char* filename) const +ASDCP::MPEG2::Parser::OpenRead(const std::string& filename) const { const_cast<ASDCP::MPEG2::Parser*>(this)->m_Parser = new h__Parser; diff --git a/src/MXF.cpp b/src/MXF.cpp index 02bf1e9..ac4bb1d 100755 --- a/src/MXF.cpp +++ b/src/MXF.cpp @@ -694,7 +694,7 @@ ASDCP::MXF::OP1aHeader::~OP1aHeader() {} ASDCP::Result_t ASDCP::MXF::OP1aHeader::InitFromFile(const Kumu::FileReader& Reader) { - Result_t result = result = Partition::InitFromFile(Reader); + Result_t result = Partition::InitFromFile(Reader); if ( ASDCP_FAILURE(result) ) return result; @@ -714,10 +714,15 @@ ASDCP::MXF::OP1aHeader::InitFromFile(const Kumu::FileReader& Reader) // slurp up the remainder of the header if ( HeaderByteCount < 1024 ) - DefaultLogSink().Warn("Improbably small HeaderByteCount value: %u\n", HeaderByteCount); - - assert (HeaderByteCount <= 0xFFFFFFFFL); - result = m_HeaderData.Capacity((ui32_t)HeaderByteCount); + { + DefaultLogSink().Warn("Improbably small HeaderByteCount value: %qu\n", HeaderByteCount); + } + else if (HeaderByteCount > ( 4 * Kumu::Megabyte ) ) + { + DefaultLogSink().Warn("Improbably huge HeaderByteCount value: %qu\n", HeaderByteCount); + } + + result = m_HeaderData.Capacity(Kumu::xmin(4*Kumu::Megabyte, static_cast<ui32_t>(HeaderByteCount))); if ( ASDCP_SUCCESS(result) ) { @@ -1219,6 +1224,13 @@ ASDCP::MXF::OPAtomIndexFooter::Lookup(ui32_t frame_num, IndexTableSegment::Index // void +ASDCP::MXF::OPAtomIndexFooter::SetDeltaParams(const IndexTableSegment::DeltaEntry& delta) +{ + m_DefaultDeltaEntry = delta; +} + +// +void ASDCP::MXF::OPAtomIndexFooter::SetIndexParamsCBR(IPrimerLookup* lookup, ui32_t size, const Rational& Rate) { assert(lookup); @@ -1259,7 +1271,7 @@ ASDCP::MXF::OPAtomIndexFooter::PushIndexEntry(const IndexTableSegment::IndexEntr m_CurrentSegment = new IndexTableSegment(m_Dict); assert(m_CurrentSegment); AddChildObject(m_CurrentSegment); - m_CurrentSegment->DeltaEntryArray.push_back(IndexTableSegment::DeltaEntry()); + m_CurrentSegment->DeltaEntryArray.push_back(m_DefaultDeltaEntry); m_CurrentSegment->IndexEditRate = m_EditRate; m_CurrentSegment->IndexStartPosition = 0; } @@ -1271,7 +1283,7 @@ ASDCP::MXF::OPAtomIndexFooter::PushIndexEntry(const IndexTableSegment::IndexEntr m_CurrentSegment = new IndexTableSegment(m_Dict); assert(m_CurrentSegment); AddChildObject(m_CurrentSegment); - m_CurrentSegment->DeltaEntryArray.push_back(IndexTableSegment::DeltaEntry()); + m_CurrentSegment->DeltaEntryArray.push_back(m_DefaultDeltaEntry); m_CurrentSegment->IndexEditRate = m_EditRate; m_CurrentSegment->IndexStartPosition = StartPosition; } @@ -1427,7 +1439,7 @@ static bool s_TypesInit = false; // void -ASDCP::MXF::SetObjectFactory(ASDCP::UL label, ASDCP::MXF::MXFObjectFactory_t factory) +ASDCP::MXF::SetObjectFactory(const ASDCP::UL& label, ASDCP::MXF::MXFObjectFactory_t factory) { s_FactoryList.Insert(label, factory); } @@ -1460,10 +1472,9 @@ ASDCP::MXF::CreateObject(const Dictionary*& Dict, const UL& label) // bool -ASDCP::MXF::decode_mca_string(const std::string& s, const mca_label_map_t& labels, const Dictionary& dict, const std::string& language, +ASDCP::MXF::decode_mca_string(const std::string& s, const mca_label_map_t& labels, const Dictionary*& dict, const std::string& language, InterchangeObject_list_t& descriptor_list, ui32_t& channel_count) { - const Dictionary *dictp = &dict; std::string symbol_buf; channel_count = 0; ASDCP::MXF::SoundfieldGroupLabelSubDescriptor *current_soundfield = 0; @@ -1475,13 +1486,13 @@ ASDCP::MXF::decode_mca_string(const std::string& s, const mca_label_map_t& label { if ( current_soundfield != 0 ) { - fprintf(stderr, "Encountered '(', already processing a soundfield group.\n"); + DefaultLogSink().Error("Encountered '(', already processing a soundfield group.\n"); return false; } if ( symbol_buf.empty() ) { - fprintf(stderr, "Encountered '(', without leading soundfield group symbol.\n"); + DefaultLogSink().Error("Encountered '(', without leading soundfield group symbol.\n"); return false; } @@ -1489,17 +1500,17 @@ ASDCP::MXF::decode_mca_string(const std::string& s, const mca_label_map_t& label if ( i == labels.end() ) { - fprintf(stderr, "Unknown symbol: '%s'\n", symbol_buf.c_str()); + DefaultLogSink().Error("Unknown symbol: '%s'\n", symbol_buf.c_str()); return false; } if ( i->second.Value()[10] != 2 ) // magic depends on UL "Essence Facet" byte (see ST 428-12) { - fprintf(stderr, "Not a soundfield group symbol: '%s'\n", symbol_buf.c_str()); + DefaultLogSink().Error("Not a soundfield group symbol: '%s'\n", symbol_buf.c_str()); return false; } - current_soundfield = new ASDCP::MXF::SoundfieldGroupLabelSubDescriptor(dictp); + current_soundfield = new ASDCP::MXF::SoundfieldGroupLabelSubDescriptor(dict); GenRandomValue(current_soundfield->InstanceUID); GenRandomValue(current_soundfield->MCALinkID); @@ -1514,13 +1525,13 @@ ASDCP::MXF::decode_mca_string(const std::string& s, const mca_label_map_t& label { if ( current_soundfield == 0 ) { - fprintf(stderr, "Encountered ')', not currently processing a soundfield group.\n"); + DefaultLogSink().Error("Encountered ')', not currently processing a soundfield group.\n"); return false; } if ( symbol_buf.empty() ) { - fprintf(stderr, "Soundfield group description contains no channels.\n"); + DefaultLogSink().Error("Soundfield group description contains no channels.\n"); return false; } @@ -1528,16 +1539,16 @@ ASDCP::MXF::decode_mca_string(const std::string& s, const mca_label_map_t& label if ( i == labels.end() ) { - fprintf(stderr, "Unknown symbol: '%s'\n", symbol_buf.c_str()); + DefaultLogSink().Error("Unknown symbol: '%s'\n", symbol_buf.c_str()); return false; } ASDCP::MXF::AudioChannelLabelSubDescriptor *channel_descr = - new ASDCP::MXF::AudioChannelLabelSubDescriptor(dictp); + new ASDCP::MXF::AudioChannelLabelSubDescriptor(dict); GenRandomValue(channel_descr->InstanceUID); assert(current_soundfield); - channel_descr->MCALinkID = current_soundfield->MCALinkID; + channel_descr->SoundfieldGroupLinkID = current_soundfield->MCALinkID; channel_descr->MCAChannelID = channel_count++; channel_descr->MCATagSymbol = "ch" + i->first; channel_descr->MCATagName = i->first; @@ -1555,24 +1566,24 @@ ASDCP::MXF::decode_mca_string(const std::string& s, const mca_label_map_t& label if ( i == labels.end() ) { - fprintf(stderr, "Unknown symbol: '%s'\n", symbol_buf.c_str()); + DefaultLogSink().Error("Unknown symbol: '%s'\n", symbol_buf.c_str()); return false; } if ( i->second.Value()[10] != 1 ) // magic depends on UL "Essence Facet" byte (see ST 428-12) { - fprintf(stderr, "Not a channel symbol: '%s'\n", symbol_buf.c_str()); + DefaultLogSink().Error("Not a channel symbol: '%s'\n", symbol_buf.c_str()); return false; } ASDCP::MXF::AudioChannelLabelSubDescriptor *channel_descr = - new ASDCP::MXF::AudioChannelLabelSubDescriptor(dictp); + new ASDCP::MXF::AudioChannelLabelSubDescriptor(dict); GenRandomValue(channel_descr->InstanceUID); if ( current_soundfield != 0 ) { - channel_descr->MCALinkID = current_soundfield->MCALinkID; + channel_descr->SoundfieldGroupLinkID = current_soundfield->MCALinkID; } channel_descr->MCAChannelID = channel_count++; @@ -1590,7 +1601,7 @@ ASDCP::MXF::decode_mca_string(const std::string& s, const mca_label_map_t& label } else if ( ! isspace(*i) ) { - fprintf(stderr, "Unexpected character '%c'.\n", *i); + DefaultLogSink().Error("Unexpected character '%c'.\n", *i); return false; } } @@ -1601,18 +1612,18 @@ ASDCP::MXF::decode_mca_string(const std::string& s, const mca_label_map_t& label if ( i == labels.end() ) { - fprintf(stderr, "Unknown symbol: '%s'\n", symbol_buf.c_str()); + DefaultLogSink().Error("Unknown symbol: '%s'\n", symbol_buf.c_str()); return false; } ASDCP::MXF::AudioChannelLabelSubDescriptor *channel_descr = - new ASDCP::MXF::AudioChannelLabelSubDescriptor(dictp); + new ASDCP::MXF::AudioChannelLabelSubDescriptor(dict); GenRandomValue(channel_descr->InstanceUID); if ( current_soundfield != 0 ) { - channel_descr->MCALinkID = current_soundfield->MCALinkID; + channel_descr->SoundfieldGroupLinkID = current_soundfield->MCALinkID; } channel_descr->MCAChannelID = channel_count++; @@ -1626,7 +1637,7 @@ ASDCP::MXF::decode_mca_string(const std::string& s, const mca_label_map_t& label return true; } - +// ASDCP::MXF::ASDCP_MCAConfigParser::ASDCP_MCAConfigParser(const Dictionary*& d) : m_Dict(d), m_ChannelCount(0) { m_LabelMap.insert(mca_label_map_t::value_type("L", m_Dict->ul(MDD_DCAudioChannel_L))); @@ -1662,7 +1673,7 @@ ASDCP::MXF::ASDCP_MCAConfigParser::ChannelCount() const bool ASDCP::MXF::ASDCP_MCAConfigParser::DecodeString(const std::string& s, const std::string& language) { - return decode_mca_string(s, m_LabelMap, *m_Dict, language, *this, m_ChannelCount); + return decode_mca_string(s, m_LabelMap, m_Dict, language, *this, m_ChannelCount); } @@ -47,7 +47,7 @@ namespace ASDCP typedef ASDCP::MXF::InterchangeObject* (*MXFObjectFactory_t)(const Dictionary*&); // - void SetObjectFactory(UL label, MXFObjectFactory_t factory); + void SetObjectFactory(const UL& label, MXFObjectFactory_t factory); // InterchangeObject* CreateObject(const Dictionary*& Dict, const UL& label); @@ -303,6 +303,7 @@ namespace ASDCP // class IndexTableSegment : public InterchangeObject { + IndexTableSegment(); ASDCP_NO_COPY_CONSTRUCT(IndexTableSegment); public: @@ -314,7 +315,7 @@ namespace ASDCP ui8_t Slice; ui32_t ElementData; - DeltaEntry() : PosTableIndex(-1), Slice(0), ElementData(0) {} + DeltaEntry() : PosTableIndex(0), Slice(0), ElementData(0) {} DeltaEntry(i8_t pos, ui8_t slice, ui32_t data) : PosTableIndex(pos), Slice(slice), ElementData(data) {} inline bool HasValue() const { return true; } ui32_t ArchiveLength() const { return sizeof(ui32_t) + 2; } @@ -412,6 +413,7 @@ namespace ASDCP ui32_t m_BytesPerEditUnit; Rational m_EditRate; ui32_t m_BodySID; + IndexTableSegment::DeltaEntry m_DefaultDeltaEntry; ASDCP_NO_COPY_CONSTRUCT(OPAtomIndexFooter); OPAtomIndexFooter(); @@ -435,6 +437,7 @@ namespace ASDCP virtual Result_t Lookup(ui32_t frame_num, IndexTableSegment::IndexEntry&) const; virtual void PushIndexEntry(const IndexTableSegment::IndexEntry&); + virtual void SetDeltaParams(const IndexTableSegment::DeltaEntry&); virtual void SetIndexParamsCBR(IPrimerLookup* lookup, ui32_t size, const Rational& Rate); virtual void SetIndexParamsVBR(IPrimerLookup* lookup, const Rational& Rate, Kumu::fpos_t offset); }; @@ -457,7 +460,8 @@ namespace ASDCP }; typedef std::map<const std::string, const UL, ci_comp> mca_label_map_t; - bool decode_mca_string(const std::string& s, const mca_label_map_t& labels, const Dictionary& dict, const std::string& language, InterchangeObject_list_t&, ui32_t&); + bool decode_mca_string(const std::string& s, const mca_label_map_t& labels, + const Dictionary*& dict, const std::string& language, InterchangeObject_list_t&, ui32_t&); // class ASDCP_MCAConfigParser : public InterchangeObject_list_t diff --git a/src/Makefile.am b/src/Makefile.am index c1bcf00..83f8597 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -129,9 +129,9 @@ libas02_la_SOURCES = \ h__02_Reader.cpp \ h__02_Writer.cpp \ ST2052_TextParser.cpp \ - AS_02_TimedText.cpp \ AS_02_JP2K.cpp \ - AS_02_PCM.cpp + AS_02_PCM.cpp \ + AS_02_TimedText.cpp libas02_la_LDFLAGS = -release @VERSION@ libas02_la_LIBADD = libasdcp.la libkumu.la @@ -161,6 +161,10 @@ libpyasdcp_la_CPPFLAGS = @PYTHON_CPPFLAGS@ libpyasdcp_la_LDFLAGS = @PYTHON_LSPEC@ -release @VERSION@ libpyasdcp_la_LIBADD = libkumu.la libasdcp.la +if USE_AS_02 +libpyasdcp_la_LIBADD += libas02.la +endif + pyexecdir = @PYTHON_EXECDIR@ pyexec_includedir = $(PYTHON_PREFIX)/include/python$(PYTHON_SHORTVERSION) nodist_pyexec_include_HEADERS = kumu_python.h asdcp_python.h asdcp_wrappers.h diff --git a/src/PCMParserList.cpp b/src/PCMParserList.cpp index 2ebdfa0..8b81619 100755 --- a/src/PCMParserList.cpp +++ b/src/PCMParserList.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2004-2012, John Hurst +Copyright (c) 2004-2013, John Hurst All rights reserved. Redistribution and use in source and binary forms, with or without @@ -48,10 +48,8 @@ ASDCP::ParserInstance::~ParserInstance() // PCM::CalcSampleSize(ADesc); Result_t -ASDCP::ParserInstance::OpenRead(const char* filename, const Rational& PictureRate) +ASDCP::ParserInstance::OpenRead(const std::string& filename, const Rational& PictureRate) { - ASDCP_TEST_NULL_STR(filename); - Result_t result = Parser.OpenRead(filename, PictureRate); if ( ASDCP_SUCCESS(result) ) diff --git a/src/PCMParserList.h b/src/PCMParserList.h index 80c1d52..dbacd68 100755 --- a/src/PCMParserList.h +++ b/src/PCMParserList.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2004-2012, John Hurst +Copyright (c) 2004-2013, John Hurst All rights reserved. Redistribution and use in source and binary forms, with or without @@ -54,7 +54,7 @@ namespace ASDCP ParserInstance(); virtual ~ParserInstance(); - Result_t OpenRead(const char* filename, const Rational& PictureRate); + Result_t OpenRead(const std::string& filename, const Rational& PictureRate); Result_t PutSample(byte_t* p); Result_t ReadFrame(); inline ui32_t SampleSize() { return m_SampleSize; } diff --git a/src/PCM_Parser.cpp b/src/PCM_Parser.cpp index e3b693d..30e5d28 100755 --- a/src/PCM_Parser.cpp +++ b/src/PCM_Parser.cpp @@ -69,7 +69,7 @@ public: Close(); } - Result_t OpenRead(const char* filename, const Rational& PictureRate); + Result_t OpenRead(const std::string& filename, const Rational& PictureRate); void Close(); void Reset(); Result_t ReadFrame(FrameBuffer&); @@ -94,10 +94,8 @@ ASDCP::PCM::WAVParser::h__WAVParser::Reset() // ASDCP::Result_t -ASDCP::PCM::WAVParser::h__WAVParser::OpenRead(const char* filename, const Rational& PictureRate) +ASDCP::PCM::WAVParser::h__WAVParser::OpenRead(const std::string& filename, const Rational& PictureRate) { - ASDCP_TEST_NULL_STR(filename); - Result_t result = m_FileReader.OpenRead(filename); if ( ASDCP_SUCCESS(result) ) @@ -203,7 +201,7 @@ ASDCP::PCM::WAVParser::~WAVParser() // Opens the stream for reading, parses enough data to provide a complete // set of stream metadata for the MXFWriter below. ASDCP::Result_t -ASDCP::PCM::WAVParser::OpenRead(const char* filename, const Rational& PictureRate) const +ASDCP::PCM::WAVParser::OpenRead(const std::string& filename, const Rational& PictureRate) const { const_cast<ASDCP::PCM::WAVParser*>(this)->m_Parser = new h__WAVParser; diff --git a/src/TimedText_Parser.cpp b/src/TimedText_Parser.cpp index b7b58c5..3312b58 100644 --- a/src/TimedText_Parser.cpp +++ b/src/TimedText_Parser.cpp @@ -136,8 +136,8 @@ public: return m_DefaultResolver; } - Result_t OpenRead(const char* filename); - Result_t OpenRead(const std::string& xml_doc, const char* filename); + Result_t OpenRead(const std::string& filename); + Result_t OpenRead(const std::string& xml_doc, const std::string& filename); Result_t ReadAncillaryResource(const byte_t* uuid, FrameBuffer& FrameBuf, const IResourceResolver& Resolver) const; }; @@ -178,7 +178,7 @@ decode_rational(const char* str_rat) // Result_t -ASDCP::TimedText::DCSubtitleParser::h__SubtitleParser::OpenRead(const char* filename) +ASDCP::TimedText::DCSubtitleParser::h__SubtitleParser::OpenRead(const std::string& filename) { Result_t result = ReadFileIntoString(filename, m_XMLDoc); @@ -191,14 +191,18 @@ ASDCP::TimedText::DCSubtitleParser::h__SubtitleParser::OpenRead(const char* file // Result_t -ASDCP::TimedText::DCSubtitleParser::h__SubtitleParser::OpenRead(const std::string& xml_doc, const char* filename) +ASDCP::TimedText::DCSubtitleParser::h__SubtitleParser::OpenRead(const std::string& xml_doc, const std::string& filename) { m_XMLDoc = xml_doc; - if ( filename != 0 ) - m_Filename = filename; + if ( filename.empty() ) + { + m_Filename = "<string>"; + } else - m_Filename = "<string>"; + { + m_Filename = filename; + } return OpenRead(); } @@ -394,7 +398,7 @@ ASDCP::TimedText::DCSubtitleParser::~DCSubtitleParser() // Opens the stream for reading, parses enough data to provide a complete // set of stream metadata for the MXFWriter below. ASDCP::Result_t -ASDCP::TimedText::DCSubtitleParser::OpenRead(const char* filename) const +ASDCP::TimedText::DCSubtitleParser::OpenRead(const std::string& filename) const { const_cast<ASDCP::TimedText::DCSubtitleParser*>(this)->m_Parser = new h__SubtitleParser; @@ -408,7 +412,7 @@ ASDCP::TimedText::DCSubtitleParser::OpenRead(const char* filename) const // Parses an XML document to provide a complete set of stream metadata for the MXFWriter below. Result_t -ASDCP::TimedText::DCSubtitleParser::OpenRead(const std::string& xml_doc, const char* filename) const +ASDCP::TimedText::DCSubtitleParser::OpenRead(const std::string& xml_doc, const std::string& filename) const { const_cast<ASDCP::TimedText::DCSubtitleParser*>(this)->m_Parser = new h__SubtitleParser; diff --git a/src/as-02-unwrap.cpp b/src/as-02-unwrap.cpp index b85781d..ae66df7 100755 --- a/src/as-02-unwrap.cpp +++ b/src/as-02-unwrap.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2011-2012, Robert Scheler, Heiko Sparenberg Fraunhofer IIS, +Copyright (c) 2011-2013, Robert Scheler, Heiko Sparenberg Fraunhofer IIS, John Hurst All rights reserved. @@ -420,44 +420,51 @@ read_PCM_file(CommandOptions& Options) Result_t result = Reader.OpenRead(Options.input_filename, Options.edit_rate); - if ( ASDCP_SUCCESS(result) ) + if ( KM_SUCCESS(result) ) { if ( Options.verbose_flag ) { fprintf(stderr, "Frame Buffer size: %u\n", Options.fb_size); } + + ASDCP::MXF::InterchangeObject* tmp_obj = 0; - result = Reader.OP1aHeader().GetMDObjectByType(DefaultCompositeDict().ul(MDD_WaveAudioDescriptor), - reinterpret_cast<MXF::InterchangeObject**>(&wave_descriptor)); + result = Reader.OP1aHeader().GetMDObjectByType(DefaultCompositeDict().ul(MDD_WaveAudioDescriptor), &tmp_obj); if ( KM_SUCCESS(result) ) { - assert(wave_descriptor); - last_frame = wave_descriptor->ContainerDuration; + wave_descriptor = dynamic_cast<ASDCP::MXF::WaveAudioDescriptor*>(tmp_obj); + if ( wave_descriptor == 0 ) + { + fprintf(stderr, "File does not contain an essence descriptor.\n"); + return RESULT_FAIL; + } + if ( Options.verbose_flag ) { wave_descriptor->Dump(); } - } - else - { - fprintf(stderr, "File does not contain an essence descriptor.\n"); - last_frame = Reader.AS02IndexReader().GetDuration(); - } - if ( last_frame == 0 ) - { - fprintf(stderr, "Unable to determine file duration.\n"); - return RESULT_FAIL; - } + if ( wave_descriptor->ContainerDuration.get() == 0 ) + { + fprintf(stderr, "ContainerDuration not set in file descriptor, attempting to use index duration.\n"); + last_frame = Reader.AS02IndexReader().GetDuration(); + } + else + { + last_frame = wave_descriptor->ContainerDuration; + } - FrameBuffer.Capacity(AS_02::MXF::CalcFrameBufferSize(*wave_descriptor, Options.edit_rate)); - last_frame = AS_02::MXF::CalcFramesFromDurationInSamples(last_frame, *wave_descriptor, Options.edit_rate); + if ( last_frame == 0 ) + { + fprintf(stderr, "Unable to determine file duration.\n"); + return RESULT_FAIL; + } - if ( Options.verbose_flag ) - { - wave_descriptor->Dump(); + assert(wave_descriptor); + FrameBuffer.Capacity(AS_02::MXF::CalcFrameBufferSize(*wave_descriptor, Options.edit_rate)); + last_frame = AS_02::MXF::CalcFramesFromDurationInSamples(last_frame, *wave_descriptor, Options.edit_rate); } } @@ -565,12 +572,12 @@ main(int argc, const char** argv) { switch ( EssenceType ) { - case ESS_JPEG_2000: + case ESS_AS02_JPEG_2000: result = read_JP2K_file(Options); break; - case ESS_PCM_24b_48k: - case ESS_PCM_24b_96k: + case ESS_AS02_PCM_24b_48k: + case ESS_AS02_PCM_24b_96k: result = read_PCM_file(Options); break; @@ -584,11 +591,7 @@ main(int argc, const char** argv) { fputs("Program stopped on error.\n", stderr); - if ( result == RESULT_SFORMAT ) - { - fputs("Use option '-3' to force stereoscopic mode.\n", stderr); - } - else if ( result != RESULT_FAIL ) + if ( result != RESULT_FAIL ) { fputs(result, stderr); fputc('\n', stderr); diff --git a/src/asdcp-test.cpp b/src/asdcp-test.cpp index 24d6b1e..a35770a 100755 --- a/src/asdcp-test.cpp +++ b/src/asdcp-test.cpp @@ -241,6 +241,9 @@ decode_channel_fmt(const std::string& label_name) else if ( label_name == "7.1DS" ) return PCM::CF_CFG_5; + else if ( label_name == "MCA" ) + return PCM::CF_CFG_6; + fprintf(stderr, "Error decoding channel format string: %s\n", label_name.c_str()); fprintf(stderr, "Expecting '5.1', '6.1', '7.1', '7.1DS' or 'WTF'\n"); return PCM::CF_NONE; diff --git a/src/asdcp-wrap.cpp b/src/asdcp-wrap.cpp index 3bad03e..fd4a6d9 100755 --- a/src/asdcp-wrap.cpp +++ b/src/asdcp-wrap.cpp @@ -187,6 +187,9 @@ decode_channel_fmt(const std::string& label_name) else if ( label_name == "7.1DS" ) return PCM::CF_CFG_5; + else if ( label_name == "MCA" ) + return PCM::CF_CFG_6; + fprintf(stderr, "Error decoding channel format string: %s\n", label_name.c_str()); fprintf(stderr, "Expecting '5.1', '6.1', '7.1', '7.1DS' or 'WTF'\n"); return PCM::CF_NONE; @@ -475,7 +478,7 @@ write_MPEG2_file(CommandOptions& Options) Kumu::FortunaRNG RNG; // set up essence parser - Result_t result = Parser.OpenRead(Options.filenames.front().c_str()); + Result_t result = Parser.OpenRead(Options.filenames.front()); // set up MXF writer if ( ASDCP_SUCCESS(result) ) @@ -531,7 +534,7 @@ write_MPEG2_file(CommandOptions& Options) } if ( ASDCP_SUCCESS(result) ) - result = Writer.OpenWrite(Options.out_file.c_str(), Info, VDesc); + result = Writer.OpenWrite(Options.out_file, Info, VDesc); } if ( ASDCP_SUCCESS(result) ) @@ -631,12 +634,12 @@ write_JP2K_S_file(CommandOptions& Options) } // set up essence parser - Result_t result = ParserLeft.OpenRead(Options.filenames.front().c_str(), Options.j2c_pedantic); + Result_t result = ParserLeft.OpenRead(Options.filenames.front(), Options.j2c_pedantic); if ( ASDCP_SUCCESS(result) ) { Options.filenames.pop_front(); - result = ParserRight.OpenRead(Options.filenames.front().c_str(), Options.j2c_pedantic); + result = ParserRight.OpenRead(Options.filenames.front(), Options.j2c_pedantic); } // set up MXF writer @@ -696,7 +699,7 @@ write_JP2K_S_file(CommandOptions& Options) } if ( ASDCP_SUCCESS(result) ) - result = Writer.OpenWrite(Options.out_file.c_str(), Info, PDesc); + result = Writer.OpenWrite(Options.out_file, Info, PDesc); if ( ASDCP_SUCCESS(result) && Options.picture_coding.HasValue() ) { @@ -771,7 +774,7 @@ write_JP2K_file(CommandOptions& Options) Kumu::FortunaRNG RNG; // set up essence parser - Result_t result = Parser.OpenRead(Options.filenames.front().c_str(), Options.j2c_pedantic); + Result_t result = Parser.OpenRead(Options.filenames.front(), Options.j2c_pedantic); // set up MXF writer if ( ASDCP_SUCCESS(result) ) @@ -831,7 +834,7 @@ write_JP2K_file(CommandOptions& Options) } if ( ASDCP_SUCCESS(result) ) - result = Writer.OpenWrite(Options.out_file.c_str(), Info, PDesc); + result = Writer.OpenWrite(Options.out_file, Info, PDesc); if ( ASDCP_SUCCESS(result) && Options.picture_coding.HasValue() ) { @@ -915,9 +918,9 @@ write_PCM_file(CommandOptions& Options) FrameBuffer.Capacity(PCM::CalcFrameBufferSize(ADesc)); ADesc.ChannelFormat = Options.channel_fmt; - if ( Options.use_smpte_labels && ADesc.ChannelFormat == PCM::CF_NONE) + if ( Options.use_smpte_labels && ADesc.ChannelFormat == PCM::CF_NONE && Options.mca_config.empty() ) { - fprintf(stderr, "ATTENTION! Writing SMPTE audio without ChannelAssignment property (see option -l)\n"); + fprintf(stderr, "ATTENTION! Writing SMPTE audio without ChannelAssignment property (see options -C, -l and -m)\n"); } if ( Options.verbose_flag ) @@ -971,7 +974,7 @@ write_PCM_file(CommandOptions& Options) } if ( ASDCP_SUCCESS(result) ) - result = Writer.OpenWrite(Options.out_file.c_str(), Info, ADesc); + result = Writer.OpenWrite(Options.out_file, Info, ADesc); if ( ASDCP_SUCCESS(result) && ( Options.channel_assignment.HasValue() @@ -1139,7 +1142,7 @@ write_PCM_with_ATMOS_sync_file(CommandOptions& Options) } if ( ASDCP_SUCCESS(result) ) - result = Writer.OpenWrite(Options.out_file.c_str(), Info, ADesc); + result = Writer.OpenWrite(Options.out_file, Info, ADesc); } if ( ASDCP_SUCCESS(result) ) @@ -1209,7 +1212,7 @@ write_timed_text_file(CommandOptions& Options) Kumu::FortunaRNG RNG; // set up essence parser - Result_t result = Parser.OpenRead(Options.filenames.front().c_str()); + Result_t result = Parser.OpenRead(Options.filenames.front()); // set up MXF writer if ( ASDCP_SUCCESS(result) ) @@ -1262,7 +1265,7 @@ write_timed_text_file(CommandOptions& Options) } if ( ASDCP_SUCCESS(result) ) - result = Writer.OpenWrite(Options.out_file.c_str(), Info, TDesc); + result = Writer.OpenWrite(Options.out_file, Info, TDesc); } if ( ASDCP_FAILURE(result) ) @@ -1324,7 +1327,7 @@ write_dolby_atmos_file(CommandOptions& Options) Kumu::FortunaRNG RNG; // set up essence parser - Result_t result = Parser.OpenRead(Options.filenames.front().c_str()); + Result_t result = Parser.OpenRead(Options.filenames.front()); // set up MXF writer if ( ASDCP_SUCCESS(result) ) @@ -1382,7 +1385,7 @@ write_dolby_atmos_file(CommandOptions& Options) } if ( ASDCP_SUCCESS(result) ) - result = Writer.OpenWrite(Options.out_file.c_str(), Info, ADesc); + result = Writer.OpenWrite(Options.out_file, Info, ADesc); } if ( ASDCP_SUCCESS(result) ) @@ -1460,7 +1463,7 @@ main(int argc, const char** argv) } EssenceType_t EssenceType; - result = ASDCP::RawEssenceType(Options.filenames.front().c_str(), EssenceType); + result = ASDCP::RawEssenceType(Options.filenames.front(), EssenceType); if ( ASDCP_SUCCESS(result) ) { diff --git a/src/h__02_Reader.cpp b/src/h__02_Reader.cpp index 1a0de11..b67f9c8 100644 --- a/src/h__02_Reader.cpp +++ b/src/h__02_Reader.cpp @@ -341,10 +341,10 @@ AS_02::MXF::AS02IndexReader::GetDuration() const Result_t AS_02::MXF::AS02IndexReader::Lookup(ui32_t frame_num, ASDCP::MXF::IndexTableSegment::IndexEntry& Entry) const { - std::list<InterchangeObject*>::iterator li; - for ( li = m_PacketList->m_List.begin(); li != m_PacketList->m_List.end(); li++ ) + std::list<InterchangeObject*>::iterator i; + for ( i = m_PacketList->m_List.begin(); i != m_PacketList->m_List.end(); ++i ) { - IndexTableSegment *segment = dynamic_cast<IndexTableSegment*>(*li); + IndexTableSegment *segment = dynamic_cast<IndexTableSegment*>(*i); if ( segment != 0 ) { @@ -373,6 +373,7 @@ AS_02::MXF::AS02IndexReader::Lookup(ui32_t frame_num, ASDCP::MXF::IndexTableSegm } } + DefaultLogSink().Error("AS_02::MXF::AS02IndexReader::Lookup FAILED: frame_num=%d\n", frame_num); return RESULT_FAIL; } diff --git a/src/h__02_Writer.cpp b/src/h__02_Writer.cpp index c81da5c..1de4392 100644 --- a/src/h__02_Writer.cpp +++ b/src/h__02_Writer.cpp @@ -42,18 +42,18 @@ static const ui32_t CBRIndexEntriesPerSegment = 5000; //------------------------------------------------------------------------------------------ // -AS_02::MXF::AS02IndexWriter::AS02IndexWriter(const ASDCP::Dictionary*& d) : - Partition(d), m_CurrentSegment(0), m_BytesPerEditUnit(0), m_Dict(d), m_Lookup(0) +AS_02::MXF::AS02IndexWriterVBR::AS02IndexWriterVBR(const ASDCP::Dictionary*& d) : + Partition(d), m_CurrentSegment(0), m_Dict(d), m_Lookup(0) { BodySID = 0; IndexSID = 129; } -AS_02::MXF::AS02IndexWriter::~AS02IndexWriter() {} +AS_02::MXF::AS02IndexWriterVBR::~AS02IndexWriterVBR() {} // Result_t -AS_02::MXF::AS02IndexWriter::WriteToFile(Kumu::FileWriter& Writer) +AS_02::MXF::AS02IndexWriterVBR::WriteToFile(Kumu::FileWriter& Writer) { assert(m_Dict); ASDCP::FrameBuffer index_body_buffer; @@ -114,7 +114,7 @@ AS_02::MXF::AS02IndexWriter::WriteToFile(Kumu::FileWriter& Writer) // void -AS_02::MXF::AS02IndexWriter::Dump(FILE* stream) +AS_02::MXF::AS02IndexWriterVBR::Dump(FILE* stream) { if ( stream == 0 ) stream = stderr; @@ -130,7 +130,7 @@ AS_02::MXF::AS02IndexWriter::Dump(FILE* stream) // ui32_t -AS_02::MXF::AS02IndexWriter::GetDuration() const +AS_02::MXF::AS02IndexWriterVBR::GetDuration() const { ui32_t duration = 0; std::list<InterchangeObject*>::const_iterator i; @@ -149,39 +149,8 @@ AS_02::MXF::AS02IndexWriter::GetDuration() const // void -AS_02::MXF::AS02IndexWriter::SetIndexParamsCBR(IPrimerLookup* lookup, ui32_t size, const ASDCP::Rational& Rate) +AS_02::MXF::AS02IndexWriterVBR::PushIndexEntry(const IndexTableSegment::IndexEntry& Entry) { - assert(lookup); - m_Lookup = lookup; - m_BytesPerEditUnit = size; - m_EditRate = Rate; - - IndexTableSegment* Index = new IndexTableSegment(m_Dict); - AddChildObject(Index); - Index->EditUnitByteCount = m_BytesPerEditUnit; - Index->IndexEditRate = Rate; -} - -// -void -AS_02::MXF::AS02IndexWriter::SetIndexParamsVBR(IPrimerLookup* lookup, const ASDCP::Rational& Rate, Kumu::fpos_t offset) -{ - assert(lookup); - m_Lookup = lookup; - m_BytesPerEditUnit = 0; - m_EditRate = Rate; -} - -// -void -AS_02::MXF::AS02IndexWriter::PushIndexEntry(const IndexTableSegment::IndexEntry& Entry) -{ - if ( m_BytesPerEditUnit != 0 ) // are we CBR? that's bad - { - DefaultLogSink().Error("Call to PushIndexEntry() failed: index is CBR\n"); - return; - } - // do we have an available segment? if ( m_CurrentSegment == 0 ) { // no, set up a new segment @@ -192,19 +161,6 @@ AS_02::MXF::AS02IndexWriter::PushIndexEntry(const IndexTableSegment::IndexEntry& m_CurrentSegment->IndexEditRate = m_EditRate; m_CurrentSegment->IndexStartPosition = 0; } - else if ( m_CurrentSegment->IndexEntryArray.size() >= CBRIndexEntriesPerSegment ) - { // no, this one is full, start another - DefaultLogSink().Warn("%s, line %d: This has never been tested.\n", __FILE__, __LINE__); - m_CurrentSegment->IndexDuration = m_CurrentSegment->IndexEntryArray.size(); - ui64_t start_position = 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 = start_position; - } m_CurrentSegment->IndexEntryArray.push_back(Entry); } @@ -214,65 +170,14 @@ AS_02::MXF::AS02IndexWriter::PushIndexEntry(const IndexTableSegment::IndexEntry& // // -AS_02::h__AS02Writer::h__AS02Writer(const ASDCP::Dictionary& d) : ASDCP::MXF::TrackFileWriter<ASDCP::MXF::OP1aHeader>(d), - m_ECStart(0), m_ClipStart(0), m_IndexWriter(m_Dict), m_PartitionSpace(0), - m_IndexStrategy(AS_02::IS_FOLLOW) {} +AS_02::h__AS02WriterFrame::h__AS02WriterFrame(const ASDCP::Dictionary& d) : + h__AS02Writer<AS_02::MXF::AS02IndexWriterVBR>(d), m_IndexStrategy(AS_02::IS_FOLLOW) {} -AS_02::h__AS02Writer::~h__AS02Writer() {} +AS_02::h__AS02WriterFrame::~h__AS02WriterFrame() {} // Result_t -AS_02::h__AS02Writer::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, ui32_t TCFrameRate, ui32_t BytesPerEditUnit) -{ - if ( EditRate.Numerator == 0 || EditRate.Denominator == 0 ) - { - DefaultLogSink().Error("Non-zero edit-rate reqired.\n"); - return RESULT_PARAM; - } - - InitHeader(); - - AddSourceClip(EditRate, EditRate/*TODO: for a moment*/, TCFrameRate, TrackName, EssenceUL, DataDefinition, PackageLabel); - AddEssenceDescriptor(WrappingUL); - m_RIP.PairArray.push_back(RIP::Pair(0, 0)); // Header partition RIP entry - m_IndexWriter.OperationalPattern = m_HeaderPart.OperationalPattern; - m_IndexWriter.EssenceContainers = m_HeaderPart.EssenceContainers; - - Result_t result = m_HeaderPart.WriteToFile(m_File, m_HeaderSize); - - if ( ASDCP_SUCCESS(result) ) - { - m_PartitionSpace *= ceil(EditRate.Quotient()); // convert seconds to edit units - m_ECStart = m_File.Tell(); - m_IndexWriter.IndexSID = 129; - - if ( BytesPerEditUnit == 0 ) - { - m_IndexWriter.SetIndexParamsVBR(&m_HeaderPart.m_Primer, EditRate, m_ECStart); - } - else - { - m_IndexWriter.SetIndexParamsCBR(&m_HeaderPart.m_Primer, BytesPerEditUnit, EditRate); - } - - UL body_ul(m_Dict->ul(MDD_ClosedCompleteBodyPartition)); - Partition body_part(m_Dict); - body_part.BodySID = 1; - body_part.OperationalPattern = m_HeaderPart.OperationalPattern; - body_part.EssenceContainers = m_HeaderPart.EssenceContainers; - body_part.ThisPartition = m_ECStart; - result = body_part.WriteToFile(m_File, body_ul); - m_RIP.PairArray.push_back(RIP::Pair(1, body_part.ThisPartition)); // Second RIP Entry - } - - return result; -} - -// -Result_t -AS_02::h__AS02Writer::WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,const byte_t* EssenceUL, AESEncContext* Ctx, HMACContext* HMAC) +AS_02::h__AS02WriterFrame::WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,const byte_t* EssenceUL, AESEncContext* Ctx, HMACContext* HMAC) { ui64_t this_stream_offset = m_StreamOffset; // m_StreamOffset will be changed by the call to Write_EKLV_Packet @@ -307,16 +212,101 @@ AS_02::h__AS02Writer::WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,const b return result; } + +//------------------------------------------------------------------------------------------ +// + + +AS_02::MXF::AS02IndexWriterCBR::AS02IndexWriterCBR(const ASDCP::Dictionary*& d) : + Partition(d), m_CurrentSegment(0), m_Dict(d), m_Lookup(0), m_Duration(0), m_SampleSize(0) +{ + BodySID = 0; + IndexSID = 129; +} + +AS_02::MXF::AS02IndexWriterCBR::~AS02IndexWriterCBR() {} + +// +Result_t +AS_02::MXF::AS02IndexWriterCBR::WriteToFile(Kumu::FileWriter& Writer) +{ + assert(m_Dict); + ASDCP::FrameBuffer index_body_buffer; + ui32_t index_body_size = MaxIndexSegmentSize; // segment-count * max-segment-size + Result_t result = index_body_buffer.Capacity(index_body_size); + + m_CurrentSegment = new IndexTableSegment(m_Dict); + assert(m_CurrentSegment); + m_CurrentSegment->m_Lookup = m_Lookup; + m_CurrentSegment->IndexEditRate = m_EditRate; + m_CurrentSegment->IndexStartPosition = 0; + m_CurrentSegment->IndexDuration = m_Duration; + m_CurrentSegment->EditUnitByteCount = m_SampleSize; + AddChildObject(m_CurrentSegment); + + ASDCP::FrameBuffer WriteWrapper; + WriteWrapper.SetData(index_body_buffer.Data() + index_body_buffer.Size(), + index_body_buffer.Capacity() - index_body_buffer.Size()); + + result = m_CurrentSegment->WriteToBuffer(WriteWrapper); + index_body_buffer.Size(index_body_buffer.Size() + WriteWrapper.Size()); + delete m_CurrentSegment; + m_CurrentSegment = 0; + m_PacketList->m_List.clear(); + + if ( KM_SUCCESS(result) ) + { + IndexByteCount = index_body_buffer.Size(); + UL body_ul(m_Dict->ul(MDD_ClosedCompleteBodyPartition)); + result = Partition::WriteToFile(Writer, body_ul); + } + + if ( KM_SUCCESS(result) ) + { + ui32_t write_count = 0; + result = Writer.Write(index_body_buffer.RoData(), index_body_buffer.Size(), &write_count); + assert(write_count == index_body_buffer.Size()); + } + + return result; +} + +// +ui32_t +AS_02::MXF::AS02IndexWriterCBR::GetDuration() const +{ + return m_Duration; +} + +// +void +AS_02::MXF::AS02IndexWriterCBR::SetEditRate(const ASDCP::Rational& edit_rate, const ui32_t& sample_size) +{ + m_EditRate = edit_rate; + m_SampleSize = sample_size; +} + + +//------------------------------------------------------------------------------------------ +// + +// +AS_02::h__AS02WriterClip::h__AS02WriterClip(const ASDCP::Dictionary& d) : + h__AS02Writer<AS_02::MXF::AS02IndexWriterCBR>(d), + m_ECStart(0), m_ClipStart(0), m_IndexStrategy(AS_02::IS_FOLLOW) {} + +AS_02::h__AS02WriterClip::~h__AS02WriterClip() {} + // bool -AS_02::h__AS02Writer::HasOpenClip() const +AS_02::h__AS02WriterClip::HasOpenClip() const { return m_ClipStart != 0; } // Result_t -AS_02::h__AS02Writer::StartClip(const byte_t* EssenceUL, AESEncContext* Ctx, HMACContext* HMAC) +AS_02::h__AS02WriterClip::StartClip(const byte_t* EssenceUL, AESEncContext* Ctx, HMACContext* HMAC) { if ( Ctx != 0 ) { @@ -340,7 +330,7 @@ AS_02::h__AS02Writer::StartClip(const byte_t* EssenceUL, AESEncContext* Ctx, HMA // Result_t -AS_02::h__AS02Writer::WriteClipBlock(const ASDCP::FrameBuffer& FrameBuf) +AS_02::h__AS02WriterClip::WriteClipBlock(const ASDCP::FrameBuffer& FrameBuf) { if ( m_ClipStart == 0 ) { @@ -353,7 +343,7 @@ AS_02::h__AS02Writer::WriteClipBlock(const ASDCP::FrameBuffer& FrameBuf) // Result_t -AS_02::h__AS02Writer::FinalizeClip(ui32_t bytes_per_frame) +AS_02::h__AS02WriterClip::FinalizeClip(ui32_t bytes_per_frame) { if ( m_ClipStart == 0 ) { @@ -377,86 +367,7 @@ AS_02::h__AS02Writer::FinalizeClip(ui32_t bytes_per_frame) return result; } -// standard method of writing the header and footer of a completed AS-02 file -// -Result_t -AS_02::h__AS02Writer::WriteAS02Footer() -{ - if ( m_IndexWriter.GetDuration() > 0 ) - { - m_IndexWriter.ThisPartition = m_File.Tell(); - m_IndexWriter.WriteToFile(m_File); - m_RIP.PairArray.push_back(RIP::Pair(0, m_IndexWriter.ThisPartition)); - } - - // update all Duration properties - ASDCP::MXF::Partition footer_part(m_Dict); - DurationElementList_t::iterator dli = m_DurationUpdateList.begin(); - - for (; dli != m_DurationUpdateList.end(); ++dli ) - { - **dli = m_FramesWritten; - } - - m_EssenceDescriptor->ContainerDuration = m_FramesWritten; - footer_part.PreviousPartition = m_RIP.PairArray.back().ByteOffset; - - Kumu::fpos_t here = m_File.Tell(); - m_RIP.PairArray.push_back(RIP::Pair(0, here)); // Last RIP Entry - m_HeaderPart.FooterPartition = here; - - assert(m_Dict); - footer_part.OperationalPattern = m_HeaderPart.OperationalPattern; - footer_part.EssenceContainers = m_HeaderPart.EssenceContainers; - footer_part.FooterPartition = here; - footer_part.ThisPartition = here; - UL footer_ul(m_Dict->ul(MDD_CompleteFooter)); - Result_t result = footer_part.WriteToFile(m_File, footer_ul); - - if ( ASDCP_SUCCESS(result) ) - result = m_RIP.WriteToFile(m_File); - - if ( ASDCP_SUCCESS(result) ) - result = m_File.Seek(0); - - if ( ASDCP_SUCCESS(result) ) - result = m_HeaderPart.WriteToFile(m_File, m_HeaderSize); - - if ( ASDCP_SUCCESS(result) ) - { - ASDCP::MXF::Array<ASDCP::MXF::RIP::Pair>::const_iterator i = m_RIP.PairArray.begin(); - ui64_t header_byte_count = m_HeaderPart.HeaderByteCount; - ui64_t previous_partition = 0; - - for ( i = m_RIP.PairArray.begin(); ASDCP_SUCCESS(result) && i != m_RIP.PairArray.end(); ++i ) - { - ASDCP::MXF::Partition plain_part(m_Dict); - result = m_File.Seek(i->ByteOffset); - - if ( ASDCP_SUCCESS(result) ) - result = plain_part.InitFromFile(m_File); - - if ( KM_SUCCESS(result) - && ( plain_part.IndexSID > 0 || plain_part.BodySID > 0 ) ) - { - plain_part.PreviousPartition = previous_partition; - plain_part.FooterPartition = footer_part.ThisPartition; - previous_partition = plain_part.ThisPartition; - result = m_File.Seek(i->ByteOffset); - - if ( ASDCP_SUCCESS(result) ) - { - UL tmp_ul = plain_part.GetUL(); - result = plain_part.WriteToFile(m_File, tmp_ul); - } - } - } - } - - m_File.Close(); - return result; -} // diff --git a/src/h__Reader.cpp b/src/h__Reader.cpp index b1c0555..a427fb5 100755 --- a/src/h__Reader.cpp +++ b/src/h__Reader.cpp @@ -70,7 +70,7 @@ ASDCP::h__ASDCPReader::~h__ASDCPReader() {} // AS-DCP method of opening an MXF file for read Result_t -ASDCP::h__ASDCPReader::OpenMXFRead(const char* filename) +ASDCP::h__ASDCPReader::OpenMXFRead(const std::string& filename) { Result_t result = ASDCP::MXF::TrackFileReader<OP1aHeader, OPAtomIndexFooter>::OpenMXFRead(filename); |
