2 Copyright (c) 2011-2015, 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&);
114 class AS02IndexWriterCBR : public ASDCP::MXF::Partition
116 ASDCP::MXF::IndexTableSegment* m_CurrentSegment;
117 ASDCP::MXF::Rational m_EditRate;
119 KM_NO_COPY_CONSTRUCT(AS02IndexWriterCBR);
120 AS02IndexWriterCBR();
123 const ASDCP::Dictionary*& m_Dict;
124 ASDCP::IPrimerLookup* m_Lookup;
128 AS02IndexWriterCBR(const ASDCP::Dictionary*&);
129 virtual ~AS02IndexWriterCBR();
132 void SetPrimerLookup(ASDCP::IPrimerLookup* lookup) {
137 Result_t WriteToFile(Kumu::FileWriter& Writer);
138 ui32_t GetDuration() const;
139 void SetEditRate(const ASDCP::Rational& edit_rate, const ui32_t& sample_size);
144 template <class IndexWriterType>
145 class h__AS02Writer : public ASDCP::MXF::TrackFileWriter<ASDCP::MXF::OP1aHeader>
147 ASDCP_NO_COPY_CONSTRUCT(h__AS02Writer);
151 ui32_t m_PartitionSpace; // edit units per partition
152 IndexWriterType m_IndexWriter;
153 ui64_t m_ECStart; // offset of the first essence element
156 h__AS02Writer(const ASDCP::Dictionary& d) :
157 ASDCP::MXF::TrackFileWriter<ASDCP::MXF::OP1aHeader>(d), m_IndexWriter(m_Dict), m_ECStart(0) {}
163 // all the above for a single source clip
164 Result_t WriteAS02Header(const std::string& PackageLabel, const ASDCP::UL& WrappingUL,
165 const std::string& TrackName, const ASDCP::UL& EssenceUL,
166 const ASDCP::UL& DataDefinition, const ASDCP::Rational& EditRate,
167 const ui32_t& TCFrameRate)
169 if ( EditRate.Numerator == 0 || EditRate.Denominator == 0 )
171 DefaultLogSink().Error("Non-zero edit-rate reqired.\n");
175 InitHeader(MXFVersion_2011);
177 AddSourceClip(EditRate, EditRate/*TODO: for a moment*/, TCFrameRate, TrackName, EssenceUL, DataDefinition, PackageLabel);
178 AddEssenceDescriptor(WrappingUL);
180 this->m_IndexWriter.SetPrimerLookup(&this->m_HeaderPart.m_Primer);
181 this->m_RIP.PairArray.push_back(RIP::PartitionPair(0, 0)); // Header partition RIP entry
182 this->m_IndexWriter.OperationalPattern = this->m_HeaderPart.OperationalPattern;
183 this->m_IndexWriter.EssenceContainers = this->m_HeaderPart.EssenceContainers;
185 Result_t result = this->m_HeaderPart.WriteToFile(this->m_File, this->m_HeaderSize);
187 if ( KM_SUCCESS(result) )
189 this->m_PartitionSpace *= floor( EditRate.Quotient() + 0.5 ); // convert seconds to edit units
190 this->m_ECStart = this->m_File.Tell();
191 this->m_IndexWriter.IndexSID = 129;
193 UL body_ul(this->m_Dict->ul(MDD_ClosedCompleteBodyPartition));
194 Partition body_part(this->m_Dict);
195 body_part.BodySID = 1;
196 body_part.OperationalPattern = this->m_HeaderPart.OperationalPattern;
197 body_part.EssenceContainers = this->m_HeaderPart.EssenceContainers;
198 body_part.ThisPartition = this->m_ECStart;
199 result = body_part.WriteToFile(this->m_File, body_ul);
200 this->m_RIP.PairArray.push_back(RIP::PartitionPair(1, body_part.ThisPartition)); // Second RIP Entry
206 // standard method of writing the header and footer of a completed AS-02 file
208 Result_t WriteAS02Footer()
210 if ( this->m_IndexWriter.GetDuration() > 0 )
212 this->m_IndexWriter.ThisPartition = this->m_File.Tell();
213 this->m_IndexWriter.WriteToFile(this->m_File);
214 this->m_RIP.PairArray.push_back(RIP::PartitionPair(0, this->m_IndexWriter.ThisPartition));
217 // update all Duration properties
218 ASDCP::MXF::Partition footer_part(this->m_Dict);
219 DurationElementList_t::iterator dli = this->m_DurationUpdateList.begin();
221 for (; dli != this->m_DurationUpdateList.end(); ++dli )
223 **dli = this->m_FramesWritten;
226 this->m_EssenceDescriptor->ContainerDuration = this->m_FramesWritten;
227 footer_part.PreviousPartition = this->m_RIP.PairArray.back().ByteOffset;
229 Kumu::fpos_t here = this->m_File.Tell();
230 this->m_RIP.PairArray.push_back(RIP::PartitionPair(0, here)); // Last RIP Entry
231 this->m_HeaderPart.FooterPartition = here;
233 assert(this->m_Dict);
234 footer_part.OperationalPattern = this->m_HeaderPart.OperationalPattern;
235 footer_part.EssenceContainers = this->m_HeaderPart.EssenceContainers;
236 footer_part.FooterPartition = here;
237 footer_part.ThisPartition = here;
239 UL footer_ul(this->m_Dict->ul(MDD_CompleteFooter));
240 Result_t result = footer_part.WriteToFile(this->m_File, footer_ul);
242 if ( KM_SUCCESS(result) )
243 result = this->m_RIP.WriteToFile(this->m_File);
245 if ( KM_SUCCESS(result) )
246 result = this->m_File.Seek(0);
248 if ( KM_SUCCESS(result) )
249 result = m_HeaderPart.WriteToFile(this->m_File, this->m_HeaderSize);
251 if ( KM_SUCCESS(result) )
253 ASDCP::MXF::RIP::const_pair_iterator i = this->m_RIP.PairArray.begin();
254 ui64_t header_byte_count = this->m_HeaderPart.HeaderByteCount;
255 ui64_t previous_partition = 0;
257 for ( i = this->m_RIP.PairArray.begin(); KM_SUCCESS(result) && i != this->m_RIP.PairArray.end(); ++i )
259 ASDCP::MXF::Partition plain_part(this->m_Dict);
260 result = this->m_File.Seek(i->ByteOffset);
262 if ( KM_SUCCESS(result) )
263 result = plain_part.InitFromFile(this->m_File);
265 if ( KM_SUCCESS(result)
266 && ( plain_part.IndexSID > 0 || plain_part.BodySID > 0 ) )
268 plain_part.PreviousPartition = previous_partition;
269 plain_part.FooterPartition = footer_part.ThisPartition;
270 previous_partition = plain_part.ThisPartition;
271 result = this->m_File.Seek(i->ByteOffset);
273 if ( KM_SUCCESS(result) )
275 UL tmp_ul = plain_part.GetUL();
276 result = plain_part.WriteToFile(this->m_File, tmp_ul);
282 this->m_File.Close();
288 class h__AS02WriterFrame : public h__AS02Writer<AS_02::MXF::AS02IndexWriterVBR>
290 ASDCP_NO_COPY_CONSTRUCT(h__AS02WriterFrame);
291 h__AS02WriterFrame();
294 IndexStrategy_t m_IndexStrategy; // per SMPTE ST 2067-5
296 h__AS02WriterFrame(const Dictionary&);
297 virtual ~h__AS02WriterFrame();
299 Result_t WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,const byte_t* EssenceUL,
300 AESEncContext* Ctx, HMACContext* HMAC);
304 class h__AS02WriterClip : public h__AS02Writer<AS_02::MXF::AS02IndexWriterCBR>
306 ASDCP_NO_COPY_CONSTRUCT(h__AS02WriterClip);
310 ui64_t m_ECStart; // offset of the first essence element
311 ui64_t m_ClipStart; // state variable for clip-wrap-in-progress
312 IndexStrategy_t m_IndexStrategy; // per SMPTE ST 2067-5
314 h__AS02WriterClip(const Dictionary&);
315 virtual ~h__AS02WriterClip();
317 bool HasOpenClip() const;
318 Result_t StartClip(const byte_t* EssenceUL, AESEncContext* Ctx, HMACContext* HMAC);
319 Result_t WriteClipBlock(const ASDCP::FrameBuffer& FrameBuf);
320 Result_t FinalizeClip(ui32_t bytes_per_frame);
325 #endif // _AS_02_INTERNAL_H_
328 // end AS_02_internal.h