X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Fh__02_Writer.cpp;h=1de439214f363b48cf015cda61dc926855173278;hb=620722efa3a2df7857074e36abd751826a61d0e0;hp=c81da5c16c95ddcfbd3a63e2560f4a5eed032411;hpb=7f373b689817ee70fbe5d6a14cb0512b5260f77c;p=asdcplib.git 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::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(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(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(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::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; -} //