the big-pre-as-02-refactor
[asdcplib.git] / src / AS_02_JP2K.cpp
1 /*
2   Copyright (c) 2011-2013, Robert Scheler, Heiko Sparenberg Fraunhofer IIS, John Hurst
3   All rights reserved.
4
5   Redistribution and use in source and binary forms, with or without
6   modification, are permitted provided that the following conditions
7   are met:
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.
15
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.
26 */ 
27 /*! \file    AS_02_JP2K.cpp
28   \version $Id$
29   \brief   AS-02 library, JPEG 2000 essence reader and writer implementation
30 */
31
32 #include "AS_02_internal.h"
33
34 #include <iostream>
35 #include <iomanip>
36
37 using namespace ASDCP;
38 using namespace ASDCP::JP2K;
39 using Kumu::GenRandomValue;
40
41 //------------------------------------------------------------------------------------------
42
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";
45
46 //------------------------------------------------------------------------------------------
47 //
48 // hidden, internal implementation of JPEG 2000 reader
49
50
51 class AS_02::JP2K::MXFReader::h__Reader : public AS_02::h__AS02Reader
52 {
53   RGBAEssenceDescriptor*        m_EssenceDescriptor;
54   JPEG2000PictureSubDescriptor* m_EssenceSubDescriptor;
55   ASDCP::Rational               m_EditRate;
56   ASDCP::Rational               m_SampleRate;
57   EssenceType_t                 m_Format;
58
59   ASDCP_NO_COPY_CONSTRUCT(h__Reader);
60
61 public:
62   PictureDescriptor m_PDesc;        // codestream parameter list
63
64   h__Reader(const Dictionary& d) :
65     AS_02::h__AS02Reader(d), m_EssenceDescriptor(0), m_EssenceSubDescriptor(0), m_Format(ESS_UNKNOWN) {}
66
67   virtual ~h__Reader() {}
68
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);
72
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);
77
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);
81
82 };
83
84 //
85 ASDCP::Result_t
86 AS_02::JP2K::MXFReader::h__Reader::MD_to_JP2K_PDesc(ASDCP::JP2K::PictureDescriptor& PDesc)
87 {
88   memset(&PDesc, 0, sizeof(PDesc));
89   ASDCP::MXF::RGBAEssenceDescriptor* PDescObj = (ASDCP::MXF::RGBAEssenceDescriptor*)m_EssenceDescriptor;
90
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;
98
99   if ( m_EssenceSubDescriptor != 0 )
100     {
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;
111
112       // PictureComponentSizing
113       ui32_t tmp_size = m_EssenceSubDescriptor->PictureComponentSizing.Length();
114
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);
117
118       else
119         DefaultLogSink().Error("Unexpected PictureComponentSizing size: %u, should be 17\n", tmp_size);
120
121       // CodingStyleDefault
122       memset(&PDesc.CodingStyleDefault, 0, sizeof(CodingStyleDefault_t));
123       memcpy(&PDesc.CodingStyleDefault,
124              m_EssenceSubDescriptor->CodingStyleDefault.RoData(),
125              m_EssenceSubDescriptor->CodingStyleDefault.Length());
126
127       // QuantizationDefault
128       memset(&PDesc.QuantizationDefault, 0, sizeof(QuantizationDefault_t));
129       memcpy(&PDesc.QuantizationDefault,
130              m_EssenceSubDescriptor->QuantizationDefault.RoData(),
131              m_EssenceSubDescriptor->QuantizationDefault.Length());
132
133       PDesc.QuantizationDefault.SPqcdLength = m_EssenceSubDescriptor->QuantizationDefault.Length() - 1;
134     }
135
136   return RESULT_OK;
137 }
138
139 //
140 //
141 ASDCP::Result_t
142 AS_02::JP2K::MXFReader::h__Reader::OpenRead(const char* filename, ASDCP::EssenceType_t type)
143 {
144   Result_t result = OpenMXFRead(filename);
145
146   if( ASDCP_SUCCESS(result) )
147     {
148       InterchangeObject* tmp_iobj = 0;
149       m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(RGBAEssenceDescriptor), &tmp_iobj);
150       m_EssenceDescriptor = static_cast<RGBAEssenceDescriptor*>(tmp_iobj);
151
152       m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(JPEG2000PictureSubDescriptor), &tmp_iobj);
153       m_EssenceSubDescriptor = static_cast<JPEG2000PictureSubDescriptor*>(tmp_iobj);
154
155       std::list<InterchangeObject*> ObjectList;
156       m_HeaderPart.GetMDObjectsByType(OBJ_TYPE_ARGS(Track), ObjectList);
157
158       if ( ObjectList.empty() )
159         {
160           DefaultLogSink().Error("MXF Metadata contains no Track Sets.\n");
161           return RESULT_FORMAT;
162         }
163
164       m_EditRate = ((Track*)ObjectList.front())->EditRate;
165       m_SampleRate = m_EssenceDescriptor->SampleRate;
166
167       if ( type == ASDCP::ESS_JPEG_2000 )
168         {
169           if ( m_EditRate != m_SampleRate )
170             {
171               DefaultLogSink().Warn("EditRate and SampleRate do not match (%.03f, %.03f).\n",
172                                     m_EditRate.Quotient(), m_SampleRate.Quotient());
173
174               if ( m_EditRate == EditRate_24 && m_SampleRate == EditRate_48 )
175                 {
176                   DefaultLogSink().Debug("File may contain JPEG Interop stereoscopic images.\n");
177                   return RESULT_SFORMAT;
178                 }
179
180               return RESULT_FORMAT;
181             }
182         }
183       else
184         {
185           DefaultLogSink().Error("'type' argument unexpected: %x\n", type);
186           return RESULT_STATE;
187         }
188
189       result = MD_to_JP2K_PDesc(m_PDesc);
190     }
191
192   return result;
193 }
194
195 //
196 //
197 ASDCP::Result_t
198 AS_02::JP2K::MXFReader::h__Reader::ReadFrame(ui32_t FrameNum, ASDCP::JP2K::FrameBuffer& FrameBuf,
199                       ASDCP::AESDecContext* Ctx, ASDCP::HMACContext* HMAC)
200 {
201   if ( ! m_File.IsOpen() )
202     return RESULT_INIT;
203
204   assert(m_Dict);
205   return ReadEKLVFrame(FrameNum, FrameBuf, m_Dict->ul(MDD_JPEG2000Essence), Ctx, HMAC);
206 }
207
208 //------------------------------------------------------------------------------------------
209 //
210
211 AS_02::JP2K::MXFReader::MXFReader()
212 {
213   m_Reader = new h__Reader(DefaultCompositeDict());
214 }
215
216
217 AS_02::JP2K::MXFReader::~MXFReader()
218 {
219 }
220
221 // Warning: direct manipulation of MXF structures can interfere
222 // with the normal operation of the wrapper.  Caveat emptor!
223 //
224 ASDCP::MXF::OP1aHeader&
225 AS_02::JP2K::MXFReader::OP1aHeader()
226 {
227   if ( m_Reader.empty() )
228     {
229       assert(g_OP1aHeader);
230       return *g_OP1aHeader;
231     }
232
233   return m_Reader->m_HeaderPart;
234 }
235
236 // Warning: direct manipulation of MXF structures can interfere
237 // with the normal operation of the wrapper.  Caveat emptor!
238 //
239 AS_02::MXF::AS02IndexReader&
240 AS_02::JP2K::MXFReader::AS02IndexReader()
241 {
242   if ( m_Reader.empty() )
243     {
244       assert(g_AS02IndexReader);
245       return *g_AS02IndexReader;
246     }
247
248   return m_Reader->m_IndexAccess;
249 }
250
251 // Warning: direct manipulation of MXF structures can interfere
252 // with the normal operation of the wrapper.  Caveat emptor!
253 //
254 ASDCP::MXF::RIP&
255 AS_02::JP2K::MXFReader::RIP()
256 {
257   if ( m_Reader.empty() )
258     {
259       assert(g_RIP);
260       return *g_RIP;
261     }
262
263   return m_Reader->m_RIP;
264 }
265
266 // Open the file for reading. The file must exist. Returns error if the
267 // operation cannot be completed.
268 Result_t
269 AS_02::JP2K::MXFReader::OpenRead(const char* filename) const
270 {
271   return m_Reader->OpenRead(filename, ASDCP::ESS_JPEG_2000);
272 }
273
274 //
275 Result_t
276 AS_02::JP2K::MXFReader::ReadFrame(ui32_t FrameNum, ASDCP::JP2K::FrameBuffer& FrameBuf,
277                                            ASDCP::AESDecContext* Ctx, ASDCP::HMACContext* HMAC) const
278 {
279   if ( m_Reader && m_Reader->m_File.IsOpen() )
280     return m_Reader->ReadFrame(FrameNum, FrameBuf, Ctx, HMAC);
281
282   return RESULT_INIT;
283 }
284
285
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
289 {
290   if ( m_Reader && m_Reader->m_File.IsOpen() )
291     {
292       PDesc = m_Reader->m_PDesc;
293       return RESULT_OK;
294     }
295
296   return RESULT_INIT;
297 }
298
299
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
303 {
304   if ( m_Reader && m_Reader->m_File.IsOpen() )
305     {
306       Info = m_Reader->m_Info;
307       return RESULT_OK;
308     }
309
310   return RESULT_INIT;
311 }
312
313
314 //------------------------------------------------------------------------------------------
315
316 //
317 class AS_02::JP2K::MXFWriter::h__Writer : public AS_02::h__AS02Writer
318 {
319   ASDCP_NO_COPY_CONSTRUCT(h__Writer);
320   h__Writer();
321
322   JPEG2000PictureSubDescriptor* m_EssenceSubDescriptor;
323
324 public:
325   PictureDescriptor m_PDesc;
326   byte_t            m_EssenceUL[SMPTE_UL_LENGTH];
327
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
331
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);
334   }
335
336   virtual ~h__Writer(){}
337
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*);
343   Result_t Finalize();
344   Result_t JP2K_PDesc_to_MD(ASDCP::JP2K::PictureDescriptor& PDesc);
345
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);
354
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();
359
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();
364
365
366 };
367
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 };
371
372 //
373 ASDCP::Result_t
374 AS_02::JP2K::MXFWriter::h__Writer::JP2K_PDesc_to_MD(ASDCP::JP2K::PictureDescriptor& PDesc)
375 {
376   assert(m_EssenceDescriptor);
377   assert(m_EssenceSubDescriptor);
378   ASDCP::MXF::RGBAEssenceDescriptor* PDescObj = (ASDCP::MXF::RGBAEssenceDescriptor*)m_EssenceDescriptor;
379
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;
386
387   //  if ( m_Info.LabelSetType == LS_MXF_SMPTE )
388   //    {
389   // PictureEssenceCoding UL = 
390   // Video Line Map       ui32_t[VideoLineMapSize] = { 2, 4, 0, 0 }
391   // CaptureGamma         UL = 
392   // ComponentMaxRef      ui32_t = 4095
393   // ComponentMinRef      ui32_t = 0
394   // PixelLayout          byte_t[PixelLayoutSize] = s_PixelLayoutXYZ
395   //    }
396
397   assert(m_Dict);
398   if ( PDesc.StoredWidth < 2049 )
399     {
400       PDescObj->PictureEssenceCoding.Set(m_Dict->ul(MDD_JP2KEssenceCompression_2K));
401       m_EssenceSubDescriptor->Rsize = 3;
402     }
403   else
404     {
405       PDescObj->PictureEssenceCoding.Set(m_Dict->ul(MDD_JP2KEssenceCompression_4K));
406       m_EssenceSubDescriptor->Rsize = 4;
407     }
408
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;
418
419   const ui32_t tmp_buffer_len = 1024;
420   byte_t tmp_buffer[tmp_buffer_len];
421
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);
427
428   /*
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);
433   */
434
435   memcpy(m_EssenceSubDescriptor->PictureComponentSizing.Data(), tmp_buffer, pcomp_size);
436   m_EssenceSubDescriptor->PictureComponentSizing.Length(pcomp_size);
437
438   ui32_t precinct_set_size = 0, i;
439   for ( i = 0; PDesc.CodingStyleDefault.SPcod.PrecinctSize[i] != 0 && i < MaxPrecincts; i++ )
440     precinct_set_size++;
441
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);
445
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);
449
450   return RESULT_OK;
451 }
452
453
454 // Open the file for writing. The file must not exist. Returns error if
455 // the operation cannot be completed.
456 ASDCP::Result_t
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)
459 {
460   if ( ! m_State.Test_BEGIN() )
461     return RESULT_STATE;
462
463   ASDCP::Result_t result = m_File.OpenWrite(filename);
464
465   if ( ASDCP_SUCCESS(result) )
466     {
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;
473
474       m_EssenceDescriptor = tmp_rgba;
475       m_EssenceSubDescriptor = new JPEG2000PictureSubDescriptor(m_Dict);
476       m_EssenceSubDescriptorList.push_back((InterchangeObject*)m_EssenceSubDescriptor);
477
478       GenRandomValue(m_EssenceSubDescriptor->InstanceUID);
479       m_EssenceDescriptor->SubDescriptors.push_back(m_EssenceSubDescriptor->InstanceUID);
480       result = m_State.Goto_INIT();
481     }
482
483   return result;
484 }
485
486 // Automatically sets the MXF file's metadata from the first jpeg codestream stream.
487 ASDCP::Result_t
488 AS_02::JP2K::MXFWriter::h__Writer::SetSourceStream(const PictureDescriptor& PDesc, const std::string& label, ASDCP::Rational LocalEditRate)
489 {
490   assert(m_Dict);
491   if ( ! m_State.Test_INIT() )
492     return RESULT_STATE;
493
494   if ( LocalEditRate == ASDCP::Rational(0,0) )
495     LocalEditRate = PDesc.EditRate;
496
497   m_PDesc = PDesc;
498   Result_t result = JP2K_PDesc_to_MD(m_PDesc);
499
500   if ( ASDCP_SUCCESS(result) )
501     {
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();
505     }
506
507   if ( ASDCP_SUCCESS(result) )
508     {
509       ui32_t TCFrameRate = ( m_PDesc.EditRate == EditRate_23_98  ) ? 24 : m_PDesc.EditRate.Numerator;
510
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);
514     }
515
516   return result;
517 }
518
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
522 // error occurs.
523 //
524 ASDCP::Result_t
525 AS_02::JP2K::MXFWriter::h__Writer::WriteFrame(const ASDCP::JP2K::FrameBuffer& FrameBuf, bool add_index,
526                        AESEncContext* Ctx, HMACContext* HMAC)
527 {
528   Result_t result = RESULT_OK;
529
530   if ( m_State.Test_READY() ){
531     result = m_State.Goto_RUNNING(); // first time through
532   }
533   ui64_t StreamOffset = m_StreamOffset;
534
535   if ( ASDCP_SUCCESS(result) )
536     result = WriteEKLVPacket(FrameBuf, m_EssenceUL, Ctx, HMAC);
537
538   if ( ASDCP_SUCCESS(result) && add_index )
539     {
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);
545
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; ???
553
554         //Complete the Index-BodyPartion
555         result = CompleteIndexBodyPart();\r
556           //Create new BodyPartions for Essence and Index
557           result = CreateBodyPartPair();                 
558       }
559       //else do nothing, we must only insert the current frame
560       //else{}
561     }
562   m_FramesWritten++;
563   return result;
564 }
565
566
567 // Closes the MXF file, writing the index and other closing information.
568 //
569 ASDCP::Result_t
570 AS_02::JP2K::MXFWriter::h__Writer::Finalize()
571 {
572   Result_t result = RESULT_OK;
573
574   if ( ! m_State.Test_RUNNING() )
575     return RESULT_STATE;
576
577   m_State.Goto_FINAL();
578
579   //the last Frame was written, complete the BodyPartion(Index), after that write the MXF-Footer
580   result = CompleteIndexBodyPart();
581
582   if ( ASDCP_FAILURE(result) ){
583     return result;
584   }
585   return WriteMXFFooter();
586 }
587
588 //------------------------------------------------------------------------------------------
589
590
591
592 AS_02::JP2K::MXFWriter::MXFWriter()
593 {
594 }
595
596 AS_02::JP2K::MXFWriter::~MXFWriter()
597 {
598 }
599
600 // Warning: direct manipulation of MXF structures can interfere
601 // with the normal operation of the wrapper.  Caveat emptor!
602 //
603 ASDCP::MXF::OP1aHeader&
604 AS_02::JP2K::MXFWriter::OP1aHeader()
605 {
606   if ( m_Writer.empty() )
607     {
608       assert(g_OP1aHeader);
609       return *g_OP1aHeader;
610     }
611
612   return m_Writer->m_HeaderPart;
613 }
614
615 // Warning: direct manipulation of MXF structures can interfere
616 // with the normal operation of the wrapper.  Caveat emptor!
617 //
618 ASDCP::MXF::RIP&
619 AS_02::JP2K::MXFWriter::RIP()
620 {
621   if ( m_Writer.empty() )
622     {
623       assert(g_RIP);
624       return *g_RIP;
625     }
626
627   return m_Writer->m_RIP;
628 }
629
630 // Open the file for writing. The file must not exist. Returns error if
631 // the operation cannot be completed.
632 ASDCP::Result_t
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)
638 {
639   m_Writer = new AS_02::JP2K::MXFWriter::h__Writer(DefaultSMPTEDict());
640   m_Writer->m_Info = Info;
641
642   ASDCP::Result_t result = m_Writer->OpenWrite(filename, ASDCP::ESS_JPEG_2000, Strategy, PartitionSpace, HeaderSize);
643
644   if ( ASDCP_SUCCESS(result) )
645     result = m_Writer->SetSourceStream(PDesc, JP2K_PACKAGE_LABEL);
646
647   if ( ASDCP_FAILURE(result) )
648     m_Writer.release();
649
650   return result;
651 }
652
653
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
657 // error occurs.
658 ASDCP::Result_t 
659 AS_02::JP2K::MXFWriter::WriteFrame(const ASDCP::JP2K::FrameBuffer& FrameBuf, AESEncContext* Ctx, HMACContext* HMAC)
660 {
661   if ( m_Writer.empty() )
662     return RESULT_INIT;
663
664   return m_Writer->WriteFrame(FrameBuf, true, Ctx, HMAC);
665 }
666
667 // Closes the MXF file, writing the index and other closing information.
668 ASDCP::Result_t
669 AS_02::JP2K::MXFWriter::Finalize()
670 {
671   if ( m_Writer.empty() )
672     return RESULT_INIT;
673
674   return m_Writer->Finalize();
675 }
676
677
678 //
679 // end AS_02_JP2K.cpp
680 //