2 Copyright (c) 2011-2018, Robert Scheler, Heiko Sparenberg Fraunhofer IIS,
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. The name of the author may not be used to endorse or promote products
16 derived from this software without specific prior written permission.
18 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 /*! \file AS_02_internal.h
30 \version $Id: AS_02_internal.h ***
31 \brief AS-02 library, non-public common elements
34 #ifndef _AS_02_INTERNAL_H_
35 #define _AS_02_INTERNAL_H_
38 #include "AS_DCP_internal.h"
41 using Kumu::DefaultLogSink;
43 #ifdef DEFAULT_02_MD_DECL
44 AS_02::MXF::AS02IndexReader *g_AS02IndexReader;
46 extern AS_02::MXF::AS02IndexReader *g_AS02IndexReader;
53 void default_md_object_init();
57 class h__AS02Reader : public ASDCP::MXF::TrackFileReader<ASDCP::MXF::OP1aHeader, AS_02::MXF::AS02IndexReader>
59 ASDCP_NO_COPY_CONSTRUCT(h__AS02Reader);
63 h__AS02Reader(const ASDCP::Dictionary&);
64 virtual ~h__AS02Reader();
66 Result_t OpenMXFRead(const std::string& filename);
68 // USE FRAME WRAPPING...
69 Result_t ReadEKLVFrame(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
70 const byte_t* EssenceUL, ASDCP::AESDecContext* Ctx, ASDCP::HMACContext* HMAC);
72 // OR CLIP WRAPPING...
73 // clip wrapping is handled directly by the essence-specific classes
74 // Result_t ReadyClip(const ui32_t& FrameNum, const byte_t* EssenceUL, ASDCP::AESDecContext* Ctx, ASDCP::HMACContext* HMAC, ui64_t& position);
75 /// Result_t ReadClipBlock(ASDCP::FrameBuffer& FrameBuf, const ui32_t& read_size);
84 class AS02IndexWriterVBR : public ASDCP::MXF::Partition
86 ASDCP::MXF::IndexTableSegment* m_CurrentSegment;
87 ASDCP::MXF::Rational m_EditRate;
89 KM_NO_COPY_CONSTRUCT(AS02IndexWriterVBR);
93 const ASDCP::Dictionary*& m_Dict;
94 ASDCP::IPrimerLookup* m_Lookup;
96 AS02IndexWriterVBR(const ASDCP::Dictionary*&);
97 virtual ~AS02IndexWriterVBR();
100 void SetPrimerLookup(ASDCP::IPrimerLookup* lookup) {
105 Result_t WriteToFile(Kumu::FileWriter& Writer);
106 void Dump(FILE* = 0);
108 ui32_t GetDuration() const;
109 void PushIndexEntry(const ASDCP::MXF::IndexTableSegment::IndexEntry&);
110 void SetEditRate(const ASDCP::Rational& edit_rate);
115 class AS02IndexWriterCBR : public ASDCP::MXF::Partition
117 ASDCP::MXF::IndexTableSegment* m_CurrentSegment;
118 ASDCP::MXF::Rational m_EditRate;
120 KM_NO_COPY_CONSTRUCT(AS02IndexWriterCBR);
121 AS02IndexWriterCBR();
124 const ASDCP::Dictionary*& m_Dict;
125 ASDCP::IPrimerLookup* m_Lookup;
129 AS02IndexWriterCBR(const ASDCP::Dictionary*&);
130 virtual ~AS02IndexWriterCBR();
133 void SetPrimerLookup(ASDCP::IPrimerLookup* lookup) {
138 Result_t WriteToFile(Kumu::FileWriter& Writer);
139 ui32_t GetDuration() const;
140 void SetEditRate(const ASDCP::Rational& edit_rate, const ui32_t& sample_size);
145 template <class IndexWriterType>
146 class h__AS02Writer : public ASDCP::MXF::TrackFileWriter<ASDCP::MXF::OP1aHeader>
148 ASDCP_NO_COPY_CONSTRUCT(h__AS02Writer);
152 ui32_t m_PartitionSpace; // edit units per partition
153 IndexWriterType m_IndexWriter;
154 ui64_t m_ECStart; // offset of the first essence element
157 h__AS02Writer(const ASDCP::Dictionary& d) :
158 ASDCP::MXF::TrackFileWriter<ASDCP::MXF::OP1aHeader>(d), m_IndexWriter(m_Dict), m_ECStart(0) {}
164 // all the above for a single source clip
165 Result_t WriteAS02Header(const std::string& PackageLabel, const ASDCP::UL& WrappingUL,
166 const std::string& TrackName, const ASDCP::UL& EssenceUL,
167 const ASDCP::UL& DataDefinition, const ASDCP::Rational& EditRate,
168 const ui32_t& TCFrameRate)
170 if ( EditRate.Numerator == 0 || EditRate.Denominator == 0 )
172 DefaultLogSink().Error("Non-zero edit-rate reqired.\n");
176 InitHeader(MXFVersion_2011);
178 AddSourceClip(EditRate, EditRate/*TODO: for a moment*/, TCFrameRate, TrackName, EssenceUL, DataDefinition, PackageLabel);
179 AddEssenceDescriptor(WrappingUL);
181 this->m_IndexWriter.SetPrimerLookup(&this->m_HeaderPart.m_Primer);
182 this->m_RIP.PairArray.push_back(RIP::PartitionPair(0, 0)); // Header partition RIP entry
183 this->m_IndexWriter.MajorVersion = m_HeaderPart.MajorVersion;
184 this->m_IndexWriter.MinorVersion = m_HeaderPart.MinorVersion;
185 this->m_IndexWriter.OperationalPattern = this->m_HeaderPart.OperationalPattern;
186 this->m_IndexWriter.EssenceContainers = this->m_HeaderPart.EssenceContainers;
188 Result_t result = this->m_HeaderPart.WriteToFile(this->m_File, this->m_HeaderSize);
190 if ( KM_SUCCESS(result) )
192 this->m_PartitionSpace *= (ui32_t)floor( EditRate.Quotient() + 0.5 ); // convert seconds to edit units
193 this->m_ECStart = this->m_File.Tell();
194 this->m_IndexWriter.IndexSID = 129;
196 UL body_ul(this->m_Dict->ul(MDD_ClosedCompleteBodyPartition));
197 Partition body_part(this->m_Dict);
198 body_part.BodySID = 1;
199 body_part.MajorVersion = this->m_HeaderPart.MajorVersion;
200 body_part.MinorVersion = this->m_HeaderPart.MinorVersion;
201 body_part.OperationalPattern = this->m_HeaderPart.OperationalPattern;
202 body_part.EssenceContainers = this->m_HeaderPart.EssenceContainers;
203 body_part.ThisPartition = this->m_ECStart;
204 result = body_part.WriteToFile(this->m_File, body_ul);
205 this->m_RIP.PairArray.push_back(RIP::PartitionPair(1, body_part.ThisPartition)); // Second RIP Entry
211 void FlushIndexPartition()
213 if ( this->m_IndexWriter.GetDuration() > 0 )
215 this->m_IndexWriter.ThisPartition = this->m_File.Tell();
216 this->m_IndexWriter.WriteToFile(this->m_File);
217 this->m_RIP.PairArray.push_back(RIP::PartitionPair(0, this->m_IndexWriter.ThisPartition));
221 // standard method of writing the header and footer of a completed AS-02 file
223 Result_t WriteAS02Footer()
225 this->FlushIndexPartition();
227 // update all Duration properties
228 ASDCP::MXF::Partition footer_part(this->m_Dict);
229 DurationElementList_t::iterator dli = this->m_DurationUpdateList.begin();
231 for (; dli != this->m_DurationUpdateList.end(); ++dli )
233 **dli = this->m_FramesWritten;
236 this->m_EssenceDescriptor->ContainerDuration = this->m_FramesWritten;
237 footer_part.PreviousPartition = this->m_RIP.PairArray.back().ByteOffset;
239 Kumu::fpos_t here = this->m_File.Tell();
240 this->m_RIP.PairArray.push_back(RIP::PartitionPair(0, here)); // Last RIP Entry
241 this->m_HeaderPart.FooterPartition = here;
243 assert(this->m_Dict);
244 footer_part.MajorVersion = this->m_HeaderPart.MajorVersion;
245 footer_part.MinorVersion = this->m_HeaderPart.MinorVersion;
246 footer_part.OperationalPattern = this->m_HeaderPart.OperationalPattern;
247 footer_part.EssenceContainers = this->m_HeaderPart.EssenceContainers;
248 footer_part.FooterPartition = here;
249 footer_part.ThisPartition = here;
251 UL footer_ul(this->m_Dict->ul(MDD_CompleteFooter));
252 Result_t result = footer_part.WriteToFile(this->m_File, footer_ul);
254 if ( KM_SUCCESS(result) )
255 result = this->m_RIP.WriteToFile(this->m_File);
257 if ( KM_SUCCESS(result) )
258 result = this->m_File.Seek(0);
260 if ( KM_SUCCESS(result) )
261 result = m_HeaderPart.WriteToFile(this->m_File, this->m_HeaderSize);
263 if ( KM_SUCCESS(result) )
265 ASDCP::MXF::RIP::const_pair_iterator i = this->m_RIP.PairArray.begin();
266 ui64_t header_byte_count = this->m_HeaderPart.HeaderByteCount;
267 ui64_t previous_partition = 0;
269 for ( i = this->m_RIP.PairArray.begin(); KM_SUCCESS(result) && i != this->m_RIP.PairArray.end(); ++i )
271 ASDCP::MXF::Partition plain_part(this->m_Dict);
272 result = this->m_File.Seek(i->ByteOffset);
274 if ( KM_SUCCESS(result) )
275 result = plain_part.InitFromFile(this->m_File);
277 if ( KM_SUCCESS(result)
278 && ( plain_part.IndexSID > 0 || plain_part.BodySID > 0 ) )
280 plain_part.PreviousPartition = previous_partition;
281 plain_part.FooterPartition = footer_part.ThisPartition;
282 previous_partition = plain_part.ThisPartition;
283 result = this->m_File.Seek(i->ByteOffset);
285 if ( KM_SUCCESS(result) )
287 UL tmp_ul = plain_part.GetUL();
288 result = plain_part.WriteToFile(this->m_File, tmp_ul);
294 this->m_File.Close();
300 class h__AS02WriterFrame : public h__AS02Writer<AS_02::MXF::AS02IndexWriterVBR>
302 ASDCP_NO_COPY_CONSTRUCT(h__AS02WriterFrame);
303 h__AS02WriterFrame();
306 IndexStrategy_t m_IndexStrategy; // per SMPTE ST 2067-5
308 h__AS02WriterFrame(const Dictionary&);
309 virtual ~h__AS02WriterFrame();
311 Result_t WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,const byte_t* EssenceUL,
312 const ui32_t& MinEssenceElementBerLength,
313 AESEncContext* Ctx, HMACContext* HMAC);
317 class h__AS02WriterClip : public h__AS02Writer<AS_02::MXF::AS02IndexWriterCBR>
319 ASDCP_NO_COPY_CONSTRUCT(h__AS02WriterClip);
323 ui64_t m_ECStart; // offset of the first essence element
324 ui64_t m_ClipStart; // state variable for clip-wrap-in-progress
325 IndexStrategy_t m_IndexStrategy; // per SMPTE ST 2067-5
327 h__AS02WriterClip(const Dictionary&);
328 virtual ~h__AS02WriterClip();
330 bool HasOpenClip() const;
331 Result_t StartClip(const byte_t* EssenceUL, AESEncContext* Ctx, HMACContext* HMAC);
332 Result_t WriteClipBlock(const ASDCP::FrameBuffer& FrameBuf);
333 Result_t FinalizeClip(ui32_t bytes_per_frame);
338 #endif // _AS_02_INTERNAL_H_
341 // end AS_02_internal.h