2 Copyright (c) 2011-2013, Robert Scheler, Heiko Sparenberg Fraunhofer IIS, John Hurst
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 /*! \file AS_02_JP2K.cpp
29 \brief AS-02 library, JPEG 2000 essence reader and writer implementation
32 #include "AS_02_internal.h"
37 using namespace ASDCP;
38 using namespace ASDCP::JP2K;
39 using Kumu::GenRandomValue;
41 //------------------------------------------------------------------------------------------
43 static std::string JP2K_PACKAGE_LABEL = "File Package: SMPTE ST 422 frame wrapping of JPEG 2000 codestreams";
44 static std::string PICT_DEF_LABEL = "Image Track";
46 //------------------------------------------------------------------------------------------
48 // hidden, internal implementation of JPEG 2000 reader
51 class AS_02::JP2K::MXFReader::h__Reader : public AS_02::h__AS02Reader
53 RGBAEssenceDescriptor* m_EssenceDescriptor;
54 JPEG2000PictureSubDescriptor* m_EssenceSubDescriptor;
55 ASDCP::Rational m_EditRate;
56 ASDCP::Rational m_SampleRate;
57 EssenceType_t m_Format;
59 ASDCP_NO_COPY_CONSTRUCT(h__Reader);
62 PictureDescriptor m_PDesc; // codestream parameter list
64 h__Reader(const Dictionary& d) :
65 AS_02::h__AS02Reader(d), m_EssenceDescriptor(0), m_EssenceSubDescriptor(0), m_Format(ESS_UNKNOWN) {}
67 virtual ~h__Reader() {}
69 Result_t OpenRead(const char*, EssenceType_t);
70 Result_t ReadFrame(ui32_t, ASDCP::JP2K::FrameBuffer&, AESDecContext*, HMACContext*);
71 Result_t MD_to_JP2K_PDesc(ASDCP::JP2K::PictureDescriptor& PDesc);
73 Result_t OpenMXFRead(const char* filename);
74 // positions file before reading
75 Result_t ReadEKLVFrame(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf,
76 const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC);
78 // reads from current position
79 Result_t ReadEKLVPacket(ui32_t FrameNum, ui32_t SequenceNum, ASDCP::FrameBuffer& FrameBuf,
80 const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC);
86 AS_02::JP2K::MXFReader::h__Reader::MD_to_JP2K_PDesc(ASDCP::JP2K::PictureDescriptor& PDesc)
88 memset(&PDesc, 0, sizeof(PDesc));
89 ASDCP::MXF::RGBAEssenceDescriptor* PDescObj = (ASDCP::MXF::RGBAEssenceDescriptor*)m_EssenceDescriptor;
91 PDesc.EditRate = m_EditRate;
92 PDesc.SampleRate = m_SampleRate;
93 assert(PDescObj->ContainerDuration <= 0xFFFFFFFFL);
94 PDesc.ContainerDuration = (ui32_t) PDescObj->ContainerDuration;
95 PDesc.StoredWidth = PDescObj->StoredWidth;
96 PDesc.StoredHeight = PDescObj->StoredHeight;
97 PDesc.AspectRatio = PDescObj->AspectRatio;
99 if ( m_EssenceSubDescriptor != 0 )
101 PDesc.Rsize = m_EssenceSubDescriptor->Rsize;
102 PDesc.Xsize = m_EssenceSubDescriptor->Xsize;
103 PDesc.Ysize = m_EssenceSubDescriptor->Ysize;
104 PDesc.XOsize = m_EssenceSubDescriptor->XOsize;
105 PDesc.YOsize = m_EssenceSubDescriptor->YOsize;
106 PDesc.XTsize = m_EssenceSubDescriptor->XTsize;
107 PDesc.YTsize = m_EssenceSubDescriptor->YTsize;
108 PDesc.XTOsize = m_EssenceSubDescriptor->XTOsize;
109 PDesc.YTOsize = m_EssenceSubDescriptor->YTOsize;
110 PDesc.Csize = m_EssenceSubDescriptor->Csize;
112 // PictureComponentSizing
113 ui32_t tmp_size = m_EssenceSubDescriptor->PictureComponentSizing.Length();
115 if ( tmp_size == 17 ) // ( 2 * sizeof(ui32_t) ) + 3 components * 3 byte each
116 memcpy(&PDesc.ImageComponents, m_EssenceSubDescriptor->PictureComponentSizing.RoData() + 8, tmp_size - 8);
119 DefaultLogSink().Error("Unexpected PictureComponentSizing size: %u, should be 17\n", tmp_size);
121 // CodingStyleDefault
122 memset(&PDesc.CodingStyleDefault, 0, sizeof(CodingStyleDefault_t));
123 memcpy(&PDesc.CodingStyleDefault,
124 m_EssenceSubDescriptor->CodingStyleDefault.RoData(),
125 m_EssenceSubDescriptor->CodingStyleDefault.Length());
127 // QuantizationDefault
128 memset(&PDesc.QuantizationDefault, 0, sizeof(QuantizationDefault_t));
129 memcpy(&PDesc.QuantizationDefault,
130 m_EssenceSubDescriptor->QuantizationDefault.RoData(),
131 m_EssenceSubDescriptor->QuantizationDefault.Length());
133 PDesc.QuantizationDefault.SPqcdLength = m_EssenceSubDescriptor->QuantizationDefault.Length() - 1;
142 AS_02::JP2K::MXFReader::h__Reader::OpenRead(const char* filename, ASDCP::EssenceType_t type)
144 Result_t result = OpenMXFRead(filename);
146 if( ASDCP_SUCCESS(result) )
148 InterchangeObject* tmp_iobj = 0;
149 m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(RGBAEssenceDescriptor), &tmp_iobj);
150 m_EssenceDescriptor = static_cast<RGBAEssenceDescriptor*>(tmp_iobj);
152 m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(JPEG2000PictureSubDescriptor), &tmp_iobj);
153 m_EssenceSubDescriptor = static_cast<JPEG2000PictureSubDescriptor*>(tmp_iobj);
155 std::list<InterchangeObject*> ObjectList;
156 m_HeaderPart.GetMDObjectsByType(OBJ_TYPE_ARGS(Track), ObjectList);
158 if ( ObjectList.empty() )
160 DefaultLogSink().Error("MXF Metadata contains no Track Sets.\n");
161 return RESULT_FORMAT;
164 m_EditRate = ((Track*)ObjectList.front())->EditRate;
165 m_SampleRate = m_EssenceDescriptor->SampleRate;
167 if ( type == ASDCP::ESS_JPEG_2000 )
169 if ( m_EditRate != m_SampleRate )
171 DefaultLogSink().Warn("EditRate and SampleRate do not match (%.03f, %.03f).\n",
172 m_EditRate.Quotient(), m_SampleRate.Quotient());
174 if ( m_EditRate == EditRate_24 && m_SampleRate == EditRate_48 )
176 DefaultLogSink().Debug("File may contain JPEG Interop stereoscopic images.\n");
177 return RESULT_SFORMAT;
180 return RESULT_FORMAT;
185 DefaultLogSink().Error("'type' argument unexpected: %x\n", type);
189 result = MD_to_JP2K_PDesc(m_PDesc);
198 AS_02::JP2K::MXFReader::h__Reader::ReadFrame(ui32_t FrameNum, ASDCP::JP2K::FrameBuffer& FrameBuf,
199 ASDCP::AESDecContext* Ctx, ASDCP::HMACContext* HMAC)
201 if ( ! m_File.IsOpen() )
205 return ReadEKLVFrame(FrameNum, FrameBuf, m_Dict->ul(MDD_JPEG2000Essence), Ctx, HMAC);
208 //------------------------------------------------------------------------------------------
211 AS_02::JP2K::MXFReader::MXFReader()
213 m_Reader = new h__Reader(DefaultCompositeDict());
217 AS_02::JP2K::MXFReader::~MXFReader()
221 // Warning: direct manipulation of MXF structures can interfere
222 // with the normal operation of the wrapper. Caveat emptor!
224 ASDCP::MXF::OP1aHeader&
225 AS_02::JP2K::MXFReader::OP1aHeader()
227 if ( m_Reader.empty() )
229 assert(g_OP1aHeader);
230 return *g_OP1aHeader;
233 return m_Reader->m_HeaderPart;
236 // Warning: direct manipulation of MXF structures can interfere
237 // with the normal operation of the wrapper. Caveat emptor!
239 AS_02::MXF::AS02IndexReader&
240 AS_02::JP2K::MXFReader::AS02IndexReader()
242 if ( m_Reader.empty() )
244 assert(g_AS02IndexReader);
245 return *g_AS02IndexReader;
248 return m_Reader->m_IndexAccess;
251 // Warning: direct manipulation of MXF structures can interfere
252 // with the normal operation of the wrapper. Caveat emptor!
255 AS_02::JP2K::MXFReader::RIP()
257 if ( m_Reader.empty() )
263 return m_Reader->m_RIP;
266 // Open the file for reading. The file must exist. Returns error if the
267 // operation cannot be completed.
269 AS_02::JP2K::MXFReader::OpenRead(const char* filename) const
271 return m_Reader->OpenRead(filename, ASDCP::ESS_JPEG_2000);
276 AS_02::JP2K::MXFReader::ReadFrame(ui32_t FrameNum, ASDCP::JP2K::FrameBuffer& FrameBuf,
277 ASDCP::AESDecContext* Ctx, ASDCP::HMACContext* HMAC) const
279 if ( m_Reader && m_Reader->m_File.IsOpen() )
280 return m_Reader->ReadFrame(FrameNum, FrameBuf, Ctx, HMAC);
286 // Fill the struct with the values from the file's header.
287 // Returns RESULT_INIT if the file is not open.
288 ASDCP::Result_t AS_02::JP2K::MXFReader::FillPictureDescriptor(PictureDescriptor& PDesc) const
290 if ( m_Reader && m_Reader->m_File.IsOpen() )
292 PDesc = m_Reader->m_PDesc;
300 // Fill the struct with the values from the file's header.
301 // Returns RESULT_INIT if the file is not open.
302 ASDCP::Result_t AS_02::JP2K::MXFReader::FillWriterInfo(WriterInfo& Info) const
304 if ( m_Reader && m_Reader->m_File.IsOpen() )
306 Info = m_Reader->m_Info;
314 //------------------------------------------------------------------------------------------
317 class AS_02::JP2K::MXFWriter::h__Writer : public AS_02::h__AS02Writer
319 ASDCP_NO_COPY_CONSTRUCT(h__Writer);
322 JPEG2000PictureSubDescriptor* m_EssenceSubDescriptor;
325 PictureDescriptor m_PDesc;
326 byte_t m_EssenceUL[SMPTE_UL_LENGTH];
328 //new attributes for AS-02 support
329 AS_02::IndexStrategy_t m_IndexStrategy; //Shim parameter index_strategy_frame/clip
330 ui32_t m_PartitionSpace; //Shim parameter partition_spacing
332 h__Writer(const Dictionary& d) : h__AS02Writer(d), m_EssenceSubDescriptor(0), m_IndexStrategy(AS_02::IS_FOLLOW), m_PartitionSpace(60) {
333 memset(m_EssenceUL, 0, SMPTE_UL_LENGTH);
336 virtual ~h__Writer(){}
338 Result_t OpenWrite(const char*, EssenceType_t type, const AS_02::IndexStrategy_t& IndexStrategy,
339 const ui32_t& PartitionSpace, const ui32_t& HeaderSize);
340 Result_t SetSourceStream(const PictureDescriptor&, const std::string& label,
341 ASDCP::Rational LocalEditRate = ASDCP::Rational(0,0));
342 Result_t WriteFrame(const ASDCP::JP2K::FrameBuffer&, bool add_index, ASDCP::AESEncContext*, ASDCP::HMACContext*);
344 Result_t JP2K_PDesc_to_MD(ASDCP::JP2K::PictureDescriptor& PDesc);
346 //void AddSourceClip(const MXF::Rational& EditRate, ui32_t TCFrameRate,
347 // const std::string& TrackName, const UL& EssenceUL,
348 // const UL& DataDefinition, const std::string& PackageLabel);
349 //void AddDMSegment(const MXF::Rational& EditRate, ui32_t TCFrameRate,
350 // const std::string& TrackName, const UL& DataDefinition,
351 // const std::string& PackageLabel);
352 //void AddEssenceDescriptor(const UL& WrappingUL);
353 //Result_t CreateBodyPart(const MXF::Rational& EditRate, ui32_t BytesPerEditUnit = 0);
355 ////new method to create BodyPartition for essence and index
356 //Result_t CreateBodyPartPair();
357 ////new method to finalize BodyPartion(index)
358 //Result_t CompleteIndexBodyPart();
360 // reimplement these functions in AS_02_PCM to support modifications for AS-02
361 //Result_t WriteEKLVPacket(const ASDCP::FrameBuffer& FrameBuf,
362 // const byte_t* EssenceUL, AESEncContext* Ctx, HMACContext* HMAC);
363 Result_t WriteMXFFooter();
368 const int VideoLineMapSize = 16; // See SMPTE 377M D.2.1
369 const int PixelLayoutSize = 8*2; // See SMPTE 377M D.2.3
370 static const byte_t s_PixelLayoutXYZ[PixelLayoutSize] = { 0xd8, 0x0c, 0xd9, 0x0c, 0xda, 0x0c, 0x00 };
374 AS_02::JP2K::MXFWriter::h__Writer::JP2K_PDesc_to_MD(ASDCP::JP2K::PictureDescriptor& PDesc)
376 assert(m_EssenceDescriptor);
377 assert(m_EssenceSubDescriptor);
378 ASDCP::MXF::RGBAEssenceDescriptor* PDescObj = (ASDCP::MXF::RGBAEssenceDescriptor*)m_EssenceDescriptor;
380 PDescObj->ContainerDuration = PDesc.ContainerDuration;
381 PDescObj->SampleRate = PDesc.EditRate;
382 PDescObj->FrameLayout = 0;
383 PDescObj->StoredWidth = PDesc.StoredWidth;
384 PDescObj->StoredHeight = PDesc.StoredHeight;
385 PDescObj->AspectRatio = PDesc.AspectRatio;
387 // if ( m_Info.LabelSetType == LS_MXF_SMPTE )
389 // PictureEssenceCoding UL =
390 // Video Line Map ui32_t[VideoLineMapSize] = { 2, 4, 0, 0 }
392 // ComponentMaxRef ui32_t = 4095
393 // ComponentMinRef ui32_t = 0
394 // PixelLayout byte_t[PixelLayoutSize] = s_PixelLayoutXYZ
398 if ( PDesc.StoredWidth < 2049 )
400 PDescObj->PictureEssenceCoding.Set(m_Dict->ul(MDD_JP2KEssenceCompression_2K));
401 m_EssenceSubDescriptor->Rsize = 3;
405 PDescObj->PictureEssenceCoding.Set(m_Dict->ul(MDD_JP2KEssenceCompression_4K));
406 m_EssenceSubDescriptor->Rsize = 4;
409 m_EssenceSubDescriptor->Xsize = PDesc.Xsize;
410 m_EssenceSubDescriptor->Ysize = PDesc.Ysize;
411 m_EssenceSubDescriptor->XOsize = PDesc.XOsize;
412 m_EssenceSubDescriptor->YOsize = PDesc.YOsize;
413 m_EssenceSubDescriptor->XTsize = PDesc.XTsize;
414 m_EssenceSubDescriptor->YTsize = PDesc.YTsize;
415 m_EssenceSubDescriptor->XTOsize = PDesc.XTOsize;
416 m_EssenceSubDescriptor->YTOsize = PDesc.YTOsize;
417 m_EssenceSubDescriptor->Csize = PDesc.Csize;
419 const ui32_t tmp_buffer_len = 1024;
420 byte_t tmp_buffer[tmp_buffer_len];
422 // slh: this has to be done dynamically since the number of components is not always 3
423 *(ui32_t*)tmp_buffer = KM_i32_BE(m_EssenceSubDescriptor->Csize);
424 *(ui32_t*)(tmp_buffer+4) = KM_i32_BE(sizeof(ASDCP::JP2K::ImageComponent_t));
425 memcpy(tmp_buffer + 8, &PDesc.ImageComponents, sizeof(ASDCP::JP2K::ImageComponent_t) * m_EssenceSubDescriptor->Csize);
426 const ui32_t pcomp_size = (sizeof(int) * 2) + (sizeof(ASDCP::JP2K::ImageComponent_t) * m_EssenceSubDescriptor->Csize);
429 *(ui32_t*)tmp_buffer = KM_i32_BE(MaxComponents); // three components
430 *(ui32_t*)(tmp_buffer+4) = KM_i32_BE(sizeof(ASDCP::JP2K::ImageComponent_t));
431 memcpy(tmp_buffer + 8, &PDesc.ImageComponents, sizeof(ASDCP::JP2K::ImageComponent_t) * MaxComponents);
432 const ui32_t pcomp_size = (sizeof(int) * 2) + (sizeof(ASDCP::JP2K::ImageComponent_t) * MaxComponents);
435 memcpy(m_EssenceSubDescriptor->PictureComponentSizing.Data(), tmp_buffer, pcomp_size);
436 m_EssenceSubDescriptor->PictureComponentSizing.Length(pcomp_size);
438 ui32_t precinct_set_size = 0, i;
439 for ( i = 0; PDesc.CodingStyleDefault.SPcod.PrecinctSize[i] != 0 && i < MaxPrecincts; i++ )
442 ui32_t csd_size = sizeof(CodingStyleDefault_t) - MaxPrecincts + precinct_set_size;
443 memcpy(m_EssenceSubDescriptor->CodingStyleDefault.Data(), &PDesc.CodingStyleDefault, csd_size);
444 m_EssenceSubDescriptor->CodingStyleDefault.Length(csd_size);
446 ui32_t qdflt_size = PDesc.QuantizationDefault.SPqcdLength + 1;
447 memcpy(m_EssenceSubDescriptor->QuantizationDefault.Data(), &PDesc.QuantizationDefault, qdflt_size);
448 m_EssenceSubDescriptor->QuantizationDefault.Length(qdflt_size);
454 // Open the file for writing. The file must not exist. Returns error if
455 // the operation cannot be completed.
457 AS_02::JP2K::MXFWriter::h__Writer::OpenWrite(const char* filename, EssenceType_t type, const AS_02::IndexStrategy_t& IndexStrategy,
458 const ui32_t& PartitionSpace, const ui32_t& HeaderSize)
460 if ( ! m_State.Test_BEGIN() )
463 ASDCP::Result_t result = m_File.OpenWrite(filename);
465 if ( ASDCP_SUCCESS(result) )
467 m_IndexStrategy = IndexStrategy;
468 m_PartitionSpace = PartitionSpace;
469 m_HeaderSize = HeaderSize;
470 RGBAEssenceDescriptor* tmp_rgba = new RGBAEssenceDescriptor(m_Dict);
471 tmp_rgba->ComponentMaxRef = 4095;
472 tmp_rgba->ComponentMinRef = 0;
474 m_EssenceDescriptor = tmp_rgba;
475 m_EssenceSubDescriptor = new JPEG2000PictureSubDescriptor(m_Dict);
476 m_EssenceSubDescriptorList.push_back((InterchangeObject*)m_EssenceSubDescriptor);
478 GenRandomValue(m_EssenceSubDescriptor->InstanceUID);
479 m_EssenceDescriptor->SubDescriptors.push_back(m_EssenceSubDescriptor->InstanceUID);
480 result = m_State.Goto_INIT();
486 // Automatically sets the MXF file's metadata from the first jpeg codestream stream.
488 AS_02::JP2K::MXFWriter::h__Writer::SetSourceStream(const PictureDescriptor& PDesc, const std::string& label, ASDCP::Rational LocalEditRate)
491 if ( ! m_State.Test_INIT() )
494 if ( LocalEditRate == ASDCP::Rational(0,0) )
495 LocalEditRate = PDesc.EditRate;
498 Result_t result = JP2K_PDesc_to_MD(m_PDesc);
500 if ( ASDCP_SUCCESS(result) )
502 memcpy(m_EssenceUL, m_Dict->ul(MDD_JPEG2000Essence), SMPTE_UL_LENGTH);
503 m_EssenceUL[SMPTE_UL_LENGTH-1] = 1; // first (and only) essence container
504 result = m_State.Goto_READY();
507 if ( ASDCP_SUCCESS(result) )
509 ui32_t TCFrameRate = ( m_PDesc.EditRate == EditRate_23_98 ) ? 24 : m_PDesc.EditRate.Numerator;
511 result = WriteAS02Header(label, UL(m_Dict->ul(MDD_JPEG_2000Wrapping)),
512 PICT_DEF_LABEL, UL(m_EssenceUL), UL(m_Dict->ul(MDD_PictureDataDef)),
513 LocalEditRate, TCFrameRate);
519 // Writes a frame of essence to the MXF file. If the optional AESEncContext
520 // argument is present, the essence is encrypted prior to writing.
521 // Fails if the file is not open, is finalized, or an operating system
525 AS_02::JP2K::MXFWriter::h__Writer::WriteFrame(const ASDCP::JP2K::FrameBuffer& FrameBuf, bool add_index,
526 AESEncContext* Ctx, HMACContext* HMAC)
528 Result_t result = RESULT_OK;
530 if ( m_State.Test_READY() ){
531 result = m_State.Goto_RUNNING(); // first time through
533 ui64_t StreamOffset = m_StreamOffset;
535 if ( ASDCP_SUCCESS(result) )
536 result = WriteEKLVPacket(FrameBuf, m_EssenceUL, Ctx, HMAC);
538 if ( ASDCP_SUCCESS(result) && add_index )
540 //create new Index and add it to the IndexTableSegment in the IndexPartition
541 IndexTableSegment::IndexEntry Entry;
542 Entry.StreamOffset = StreamOffset;
543 m_CurrentIndexBodyPartition->m_FramesWritten = m_FramesWritten;
544 m_CurrentIndexBodyPartition->PushIndexEntry(Entry);
546 //here we must check if the number of frames per partition are reached
547 if(m_FramesWritten!=0 &&((m_FramesWritten+1) % m_PartitionSpace) == 0){
548 this->m_BodyOffset += m_StreamOffset;
549 //StreamOffset - Offset in bytes from the start of the Essence
\r
550 //Container of first Essence Element in this Edit Unit of
\r
551 //stored Essence within the Essence Container Stream
552 //this->m_StreamOffset = 0; ???
554 //Complete the Index-BodyPartion
555 result = CompleteIndexBodyPart();
\r
556 //Create new BodyPartions for Essence and Index
557 result = CreateBodyPartPair();
559 //else do nothing, we must only insert the current frame
567 // Closes the MXF file, writing the index and other closing information.
570 AS_02::JP2K::MXFWriter::h__Writer::Finalize()
572 Result_t result = RESULT_OK;
574 if ( ! m_State.Test_RUNNING() )
577 m_State.Goto_FINAL();
579 //the last Frame was written, complete the BodyPartion(Index), after that write the MXF-Footer
580 result = CompleteIndexBodyPart();
582 if ( ASDCP_FAILURE(result) ){
585 return WriteMXFFooter();
588 //------------------------------------------------------------------------------------------
592 AS_02::JP2K::MXFWriter::MXFWriter()
596 AS_02::JP2K::MXFWriter::~MXFWriter()
600 // Warning: direct manipulation of MXF structures can interfere
601 // with the normal operation of the wrapper. Caveat emptor!
603 ASDCP::MXF::OP1aHeader&
604 AS_02::JP2K::MXFWriter::OP1aHeader()
606 if ( m_Writer.empty() )
608 assert(g_OP1aHeader);
609 return *g_OP1aHeader;
612 return m_Writer->m_HeaderPart;
615 // Warning: direct manipulation of MXF structures can interfere
616 // with the normal operation of the wrapper. Caveat emptor!
619 AS_02::JP2K::MXFWriter::RIP()
621 if ( m_Writer.empty() )
627 return m_Writer->m_RIP;
630 // Open the file for writing. The file must not exist. Returns error if
631 // the operation cannot be completed.
633 AS_02::JP2K::MXFWriter::OpenWrite(const char* filename, const ASDCP::WriterInfo& Info,
634 const ASDCP::JP2K::PictureDescriptor& PDesc,
635 const IndexStrategy_t& Strategy,
636 const ui32_t& PartitionSpace,
637 const ui32_t& HeaderSize)
639 m_Writer = new AS_02::JP2K::MXFWriter::h__Writer(DefaultSMPTEDict());
640 m_Writer->m_Info = Info;
642 ASDCP::Result_t result = m_Writer->OpenWrite(filename, ASDCP::ESS_JPEG_2000, Strategy, PartitionSpace, HeaderSize);
644 if ( ASDCP_SUCCESS(result) )
645 result = m_Writer->SetSourceStream(PDesc, JP2K_PACKAGE_LABEL);
647 if ( ASDCP_FAILURE(result) )
654 // Writes a frame of essence to the MXF file. If the optional AESEncContext
655 // argument is present, the essence is encrypted prior to writing.
656 // Fails if the file is not open, is finalized, or an operating system
659 AS_02::JP2K::MXFWriter::WriteFrame(const ASDCP::JP2K::FrameBuffer& FrameBuf, AESEncContext* Ctx, HMACContext* HMAC)
661 if ( m_Writer.empty() )
664 return m_Writer->WriteFrame(FrameBuf, true, Ctx, HMAC);
667 // Closes the MXF file, writing the index and other closing information.
669 AS_02::JP2K::MXFWriter::Finalize()
671 if ( m_Writer.empty() )
674 return m_Writer->Finalize();
679 // end AS_02_JP2K.cpp