Explicitly set the DirScanner handle to NULL (-1 for Windows) on instantiation.
[asdcplib.git] / src / AS_DCP_JP2K.cpp
1 /*
2 Copyright (c) 2004-2009, 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_DCP_JP2k.cpp
28     \version $Id$
29     \brief   AS-DCP library, JPEG 2000 essence reader and writer implementation
30 */
31
32 #include "AS_DCP_internal.h"
33 #include <iostream>
34 #include <iomanip>
35
36 using namespace ASDCP::JP2K;
37 using Kumu::GenRandomValue;
38
39 //------------------------------------------------------------------------------------------
40
41 static std::string JP2K_PACKAGE_LABEL = "File Package: SMPTE 429-4 frame wrapping of JPEG 2000 codestreams";
42 static std::string JP2K_S_PACKAGE_LABEL = "File Package: SMPTE 429-10 frame wrapping of stereoscopic JPEG 2000 codestreams";
43 static std::string PICT_DEF_LABEL = "Picture Track";
44
45 int s_exp_lookup[16] = { 0, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024,2048, 4096, 8192, 16384, 32768 };
46
47 //
48 std::ostream&
49 ASDCP::JP2K::operator << (std::ostream& strm, const PictureDescriptor& PDesc)
50 {
51   strm << "       AspectRatio: " << PDesc.AspectRatio.Numerator << "/" << PDesc.AspectRatio.Denominator << std::endl;
52   strm << "          EditRate: " << PDesc.EditRate.Numerator << "/" << PDesc.EditRate.Denominator << std::endl;
53   strm << "        SampleRate: " << PDesc.SampleRate.Numerator << "/" << PDesc.SampleRate.Denominator << std::endl;
54   strm << "       StoredWidth: " << (unsigned) PDesc.StoredWidth << std::endl;
55   strm << "      StoredHeight: " << (unsigned) PDesc.StoredHeight << std::endl;
56   strm << "             Rsize: " << (unsigned) PDesc.Rsize << std::endl;
57   strm << "             Xsize: " << (unsigned) PDesc.Xsize << std::endl;
58   strm << "             Ysize: " << (unsigned) PDesc.Ysize << std::endl;
59   strm << "            XOsize: " << (unsigned) PDesc.XOsize << std::endl;
60   strm << "            YOsize: " << (unsigned) PDesc.YOsize << std::endl;
61   strm << "            XTsize: " << (unsigned) PDesc.XTsize << std::endl;
62   strm << "            YTsize: " << (unsigned) PDesc.YTsize << std::endl;
63   strm << "           XTOsize: " << (unsigned) PDesc.XTOsize << std::endl;
64   strm << "           YTOsize: " << (unsigned) PDesc.YTOsize << std::endl;
65   strm << " ContainerDuration: " << (unsigned) PDesc.ContainerDuration << std::endl;
66
67   strm << "-- JPEG 2000 Metadata --" << std::endl;
68   strm << "    ImageComponents:" << std::endl;
69   strm << "  bits  h-sep v-sep" << std::endl;
70
71   ui32_t i;
72   for ( i = 0; i < PDesc.Csize; i++ )
73     {
74       strm << "  " << std::setw(4) << PDesc.ImageComponents[i].Ssize + 1 /* See ISO 15444-1, Table A11, for the origin of '+1' */
75            << "  " << std::setw(5) << PDesc.ImageComponents[i].XRsize
76            << " " << std::setw(5) << PDesc.ImageComponents[i].YRsize
77            << std::endl;
78     }
79
80   strm << "               Scod: " << (short) PDesc.CodingStyleDefault.Scod << std::endl;
81   strm << "   ProgressionOrder: " << (short) PDesc.CodingStyleDefault.SGcod.ProgressionOrder << std::endl;
82   strm << "     NumberOfLayers: " << (short) KM_i16_BE(Kumu::cp2i<ui16_t>(PDesc.CodingStyleDefault.SGcod.NumberOfLayers)) << std::endl;
83   strm << " MultiCompTransform: " << (short) PDesc.CodingStyleDefault.SGcod.MultiCompTransform << std::endl;
84   strm << "DecompositionLevels: " << (short) PDesc.CodingStyleDefault.SPcod.DecompositionLevels << std::endl;
85   strm << "     CodeblockWidth: " << (short) PDesc.CodingStyleDefault.SPcod.CodeblockWidth << std::endl;
86   strm << "    CodeblockHeight: " << (short) PDesc.CodingStyleDefault.SPcod.CodeblockHeight << std::endl;
87   strm << "     CodeblockStyle: " << (short) PDesc.CodingStyleDefault.SPcod.CodeblockStyle << std::endl;
88   strm << "     Transformation: " << (short) PDesc.CodingStyleDefault.SPcod.Transformation << std::endl;
89
90
91   ui32_t precinct_set_size = 0;
92
93   for ( i = 0; PDesc.CodingStyleDefault.SPcod.PrecinctSize[i] != 0 && i < MaxPrecincts; i++ )
94     precinct_set_size++;
95
96   strm << "          Precincts: " << (short) precinct_set_size << std::endl;
97   strm << "precinct dimensions:" << std::endl;
98
99   for ( i = 0; i < precinct_set_size; i++ )
100     strm << "    " << i + 1 << ": " << s_exp_lookup[PDesc.CodingStyleDefault.SPcod.PrecinctSize[i]&0x0f] << " x "
101          << s_exp_lookup[(PDesc.CodingStyleDefault.SPcod.PrecinctSize[i]>>4)&0x0f] << std::endl;
102
103   strm << "               Sqcd: " << (short) PDesc.QuantizationDefault.Sqcd << std::endl;
104
105   char tmp_buf[MaxDefaults*2];
106   strm << "              SPqcd: " << Kumu::bin2hex(PDesc.QuantizationDefault.SPqcd, PDesc.QuantizationDefault.SPqcdLength, tmp_buf, MaxDefaults*2)
107        << std::endl;
108
109   return strm;
110 }
111
112 //
113 void
114 ASDCP::JP2K::PictureDescriptorDump(const PictureDescriptor& PDesc, FILE* stream)
115 {
116   if ( stream == 0 )
117     stream = stderr;
118
119   fprintf(stream, "\
120        AspectRatio: %d/%d\n\
121           EditRate: %d/%d\n\
122         SampleRate: %d/%d\n\
123        StoredWidth: %u\n\
124       StoredHeight: %u\n\
125              Rsize: %u\n\
126              Xsize: %u\n\
127              Ysize: %u\n\
128             XOsize: %u\n\
129             YOsize: %u\n\
130             XTsize: %u\n\
131             YTsize: %u\n\
132            XTOsize: %u\n\
133            YTOsize: %u\n\
134  ContainerDuration: %u\n",
135           PDesc.AspectRatio.Numerator, PDesc.AspectRatio.Denominator,
136           PDesc.EditRate.Numerator, PDesc.EditRate.Denominator,
137           PDesc.SampleRate.Numerator, PDesc.SampleRate.Denominator,
138           PDesc.StoredWidth,
139           PDesc.StoredHeight,
140           PDesc.Rsize,
141           PDesc.Xsize,
142           PDesc.Ysize,
143           PDesc.XOsize,
144           PDesc.YOsize,
145           PDesc.XTsize,
146           PDesc.YTsize,
147           PDesc.XTOsize,
148           PDesc.YTOsize,
149           PDesc.ContainerDuration
150           );
151
152   fprintf(stream, "-- JPEG 2000 Metadata --\n");
153   fprintf(stream, "    ImageComponents:\n");
154   fprintf(stream, "  bits  h-sep v-sep\n");
155
156   ui32_t i;
157   for ( i = 0; i < PDesc.Csize; i++ )
158     {
159       fprintf(stream, "  %4d  %5d %5d\n",
160               PDesc.ImageComponents[i].Ssize + 1, // See ISO 15444-1, Table A11, for the origin of '+1'
161               PDesc.ImageComponents[i].XRsize,
162               PDesc.ImageComponents[i].YRsize
163               );
164     }
165   
166   fprintf(stream, "               Scod: %hd\n", PDesc.CodingStyleDefault.Scod);
167   fprintf(stream, "   ProgressionOrder: %hd\n", PDesc.CodingStyleDefault.SGcod.ProgressionOrder);
168   fprintf(stream, "     NumberOfLayers: %hd\n",
169           KM_i16_BE(Kumu::cp2i<ui16_t>(PDesc.CodingStyleDefault.SGcod.NumberOfLayers)));
170
171   fprintf(stream, " MultiCompTransform: %hd\n", PDesc.CodingStyleDefault.SGcod.MultiCompTransform);
172   fprintf(stream, "DecompositionLevels: %hd\n", PDesc.CodingStyleDefault.SPcod.DecompositionLevels);
173   fprintf(stream, "     CodeblockWidth: %hd\n", PDesc.CodingStyleDefault.SPcod.CodeblockWidth);
174   fprintf(stream, "    CodeblockHeight: %hd\n", PDesc.CodingStyleDefault.SPcod.CodeblockHeight);
175   fprintf(stream, "     CodeblockStyle: %hd\n", PDesc.CodingStyleDefault.SPcod.CodeblockStyle);
176   fprintf(stream, "     Transformation: %hd\n", PDesc.CodingStyleDefault.SPcod.Transformation);
177
178
179   ui32_t precinct_set_size = 0;
180
181   for ( i = 0; PDesc.CodingStyleDefault.SPcod.PrecinctSize[i] != 0 && i < MaxPrecincts; i++ )
182     precinct_set_size++;
183
184   fprintf(stream, "          Precincts: %hd\n", precinct_set_size);
185   fprintf(stream, "precinct dimensions:\n");
186
187   for ( i = 0; i < precinct_set_size; i++ )
188     fprintf(stream, "    %d: %d x %d\n", i + 1,
189             s_exp_lookup[PDesc.CodingStyleDefault.SPcod.PrecinctSize[i]&0x0f],
190             s_exp_lookup[(PDesc.CodingStyleDefault.SPcod.PrecinctSize[i]>>4)&0x0f]
191             );
192
193   fprintf(stream, "               Sqcd: %hd\n", PDesc.QuantizationDefault.Sqcd);
194
195   char tmp_buf[MaxDefaults*2];
196   fprintf(stream, "              SPqcd: %s\n",
197           Kumu::bin2hex(PDesc.QuantizationDefault.SPqcd, PDesc.QuantizationDefault.SPqcdLength,
198                         tmp_buf, MaxDefaults*2)
199           );
200 }
201
202
203 //------------------------------------------------------------------------------------------
204 //
205 // hidden, internal implementation of JPEG 2000 reader
206
207 class lh__Reader : public ASDCP::h__Reader
208 {
209   RGBAEssenceDescriptor*        m_EssenceDescriptor;
210   JPEG2000PictureSubDescriptor* m_EssenceSubDescriptor;
211   ASDCP::Rational               m_EditRate;
212   ASDCP::Rational               m_SampleRate;
213   EssenceType_t                 m_Format;
214
215   ASDCP_NO_COPY_CONSTRUCT(lh__Reader);
216
217 public:
218   PictureDescriptor m_PDesc;        // codestream parameter list
219
220   lh__Reader() : m_EssenceDescriptor(0), m_EssenceSubDescriptor(0), m_Format(ESS_UNKNOWN) {}
221   Result_t    OpenRead(const char*, EssenceType_t);
222   Result_t    ReadFrame(ui32_t, JP2K::FrameBuffer&, AESDecContext*, HMACContext*);
223   Result_t    MD_to_JP2K_PDesc(JP2K::PictureDescriptor& PDesc);
224 };
225
226 //
227 ASDCP::Result_t
228 lh__Reader::MD_to_JP2K_PDesc(JP2K::PictureDescriptor& PDesc)
229 {
230   memset(&PDesc, 0, sizeof(PDesc));
231   MXF::RGBAEssenceDescriptor* PDescObj = (MXF::RGBAEssenceDescriptor*)m_EssenceDescriptor;
232
233   PDesc.EditRate           = m_EditRate;
234   PDesc.SampleRate         = m_SampleRate;
235   assert(PDescObj->ContainerDuration <= 0xFFFFFFFFL);
236   PDesc.ContainerDuration  = (ui32_t) PDescObj->ContainerDuration;
237   PDesc.StoredWidth        = PDescObj->StoredWidth;
238   PDesc.StoredHeight       = PDescObj->StoredHeight;
239   PDesc.AspectRatio        = PDescObj->AspectRatio;
240
241   if ( m_EssenceSubDescriptor != 0 )
242     {
243       PDesc.Rsize   = m_EssenceSubDescriptor->Rsize;
244       PDesc.Xsize   = m_EssenceSubDescriptor->Xsize;
245       PDesc.Ysize   = m_EssenceSubDescriptor->Ysize;
246       PDesc.XOsize  = m_EssenceSubDescriptor->XOsize;
247       PDesc.YOsize  = m_EssenceSubDescriptor->YOsize;
248       PDesc.XTsize  = m_EssenceSubDescriptor->XTsize;
249       PDesc.YTsize  = m_EssenceSubDescriptor->YTsize;
250       PDesc.XTOsize = m_EssenceSubDescriptor->XTOsize;
251       PDesc.YTOsize = m_EssenceSubDescriptor->YTOsize;
252       PDesc.Csize   = m_EssenceSubDescriptor->Csize;
253
254       // PictureComponentSizing
255       ui32_t tmp_size = m_EssenceSubDescriptor->PictureComponentSizing.Length();
256
257       if ( tmp_size == 17 ) // ( 2 * sizeof(ui32_t) ) + 3 components * 3 byte each
258         memcpy(&PDesc.ImageComponents, m_EssenceSubDescriptor->PictureComponentSizing.RoData() + 8, tmp_size - 8);
259
260       else
261         DefaultLogSink().Error("Unexpected PictureComponentSizing size: %u, should be 17\n", tmp_size);
262
263       // CodingStyleDefault
264       memset(&m_PDesc.CodingStyleDefault, 0, sizeof(CodingStyleDefault_t));
265       memcpy(&m_PDesc.CodingStyleDefault,
266              m_EssenceSubDescriptor->CodingStyleDefault.RoData(),
267              m_EssenceSubDescriptor->CodingStyleDefault.Length());
268
269       // QuantizationDefault
270       memset(&m_PDesc.QuantizationDefault, 0, sizeof(QuantizationDefault_t));
271       memcpy(&m_PDesc.QuantizationDefault,
272              m_EssenceSubDescriptor->QuantizationDefault.RoData(),
273              m_EssenceSubDescriptor->QuantizationDefault.Length());
274
275       m_PDesc.QuantizationDefault.SPqcdLength = m_EssenceSubDescriptor->QuantizationDefault.Length() - 1;
276     }
277
278   return RESULT_OK;
279 }
280
281 //
282 //
283 ASDCP::Result_t
284 lh__Reader::OpenRead(const char* filename, EssenceType_t type)
285 {
286   Result_t result = OpenMXFRead(filename);
287
288   if( ASDCP_SUCCESS(result) )
289     {
290       InterchangeObject* tmp_iobj = 0;
291       m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(RGBAEssenceDescriptor), &tmp_iobj);
292       m_EssenceDescriptor = static_cast<RGBAEssenceDescriptor*>(tmp_iobj);
293
294       m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(JPEG2000PictureSubDescriptor), &tmp_iobj);
295       m_EssenceSubDescriptor = static_cast<JPEG2000PictureSubDescriptor*>(tmp_iobj);
296
297       std::list<InterchangeObject*> ObjectList;
298       m_HeaderPart.GetMDObjectsByType(OBJ_TYPE_ARGS(Track), ObjectList);
299
300       if ( ObjectList.empty() )
301         {
302           DefaultLogSink().Error("MXF Metadata contains no Track Sets.\n");
303           return RESULT_FORMAT;
304         }
305
306       m_EditRate = ((Track*)ObjectList.front())->EditRate;
307       m_SampleRate = m_EssenceDescriptor->SampleRate;
308
309       if ( type == ASDCP::ESS_JPEG_2000 )
310         {
311           if ( m_EditRate != m_SampleRate )
312             {
313               DefaultLogSink().Error("EditRate and SampleRate do not match (%.03f, %.03f).\n",
314                                      m_EditRate.Quotient(), m_SampleRate.Quotient());
315               
316               if ( m_EditRate == EditRate_24 && m_SampleRate == EditRate_48 )
317                 {
318                   DefaultLogSink().Debug("File may contain JPEG Interop stereoscopic images.\n");
319                   return RESULT_SFORMAT;
320                 }
321
322               return RESULT_FORMAT;
323             }
324         }
325       else if ( type == ASDCP::ESS_JPEG_2000_S )
326         {
327           if ( ! ( m_EditRate == EditRate_24 && m_SampleRate == EditRate_48 ) )
328             {
329               DefaultLogSink().Error("EditRate and SampleRate not correct for 24/48 stereoscopic essence.\n");
330               return RESULT_FORMAT;
331             }
332         }
333       else
334         {
335           DefaultLogSink().Error("'type' argument unexpected: %x\n", type);
336           return RESULT_STATE;
337         }
338
339       result = MD_to_JP2K_PDesc(m_PDesc);
340     }
341
342   if( ASDCP_SUCCESS(result) )
343     result = InitMXFIndex();
344
345   if( ASDCP_SUCCESS(result) )
346     result = InitInfo();
347
348   return result;
349 }
350
351 //
352 //
353 ASDCP::Result_t
354 lh__Reader::ReadFrame(ui32_t FrameNum, JP2K::FrameBuffer& FrameBuf,
355                       AESDecContext* Ctx, HMACContext* HMAC)
356 {
357   if ( ! m_File.IsOpen() )
358     return RESULT_INIT;
359
360   return ReadEKLVFrame(FrameNum, FrameBuf, Dict::ul(MDD_JPEG2000Essence), Ctx, HMAC);
361 }
362
363
364 //
365 class ASDCP::JP2K::MXFReader::h__Reader : public lh__Reader
366 {
367 };
368
369
370
371 //------------------------------------------------------------------------------------------
372
373
374 //
375 void
376 ASDCP::JP2K::FrameBuffer::Dump(FILE* stream, ui32_t dump_len) const
377 {
378   if ( stream == 0 )
379     stream = stderr;
380
381   fprintf(stream, "Frame: %06u, %7u bytes", m_FrameNumber, m_Size);
382   
383   fputc('\n', stream);
384
385   if ( dump_len > 0 )
386     Kumu::hexdump(m_Data, dump_len, stream);
387 }
388
389
390 //------------------------------------------------------------------------------------------
391
392 ASDCP::JP2K::MXFReader::MXFReader()
393 {
394   m_Reader = new h__Reader;
395 }
396
397
398 ASDCP::JP2K::MXFReader::~MXFReader()
399 {
400 }
401
402 // Open the file for reading. The file must exist. Returns error if the
403 // operation cannot be completed.
404 ASDCP::Result_t
405 ASDCP::JP2K::MXFReader::OpenRead(const char* filename) const
406 {
407   return m_Reader->OpenRead(filename, ASDCP::ESS_JPEG_2000);
408 }
409
410 //
411 ASDCP::Result_t
412 ASDCP::JP2K::MXFReader::ReadFrame(ui32_t FrameNum, FrameBuffer& FrameBuf,
413                                    AESDecContext* Ctx, HMACContext* HMAC) const
414 {
415   if ( m_Reader && m_Reader->m_File.IsOpen() )
416     return m_Reader->ReadFrame(FrameNum, FrameBuf, Ctx, HMAC);
417
418   return RESULT_INIT;
419 }
420
421
422 // Fill the struct with the values from the file's header.
423 // Returns RESULT_INIT if the file is not open.
424 ASDCP::Result_t
425 ASDCP::JP2K::MXFReader::FillPictureDescriptor(PictureDescriptor& PDesc) const
426 {
427   if ( m_Reader && m_Reader->m_File.IsOpen() )
428     {
429       PDesc = m_Reader->m_PDesc;
430       return RESULT_OK;
431     }
432
433   return RESULT_INIT;
434 }
435
436
437 // Fill the struct with the values from the file's header.
438 // Returns RESULT_INIT if the file is not open.
439 ASDCP::Result_t
440 ASDCP::JP2K::MXFReader::FillWriterInfo(WriterInfo& Info) const
441 {
442   if ( m_Reader && m_Reader->m_File.IsOpen() )
443     {
444       Info = m_Reader->m_Info;
445       return RESULT_OK;
446     }
447
448   return RESULT_INIT;
449 }
450
451 //
452 void
453 ASDCP::JP2K::MXFReader::DumpHeaderMetadata(FILE* stream) const
454 {
455   if ( m_Reader->m_File.IsOpen() )
456     m_Reader->m_HeaderPart.Dump(stream);
457 }
458
459
460 //
461 void
462 ASDCP::JP2K::MXFReader::DumpIndex(FILE* stream) const
463 {
464   if ( m_Reader->m_File.IsOpen() )
465     m_Reader->m_FooterPart.Dump(stream);
466 }
467
468
469 //------------------------------------------------------------------------------------------
470
471 class ASDCP::JP2K::MXFSReader::h__SReader : public lh__Reader
472 {
473   ui32_t m_StereoFrameReady;
474
475 public:
476   h__SReader() : m_StereoFrameReady(0xffffffff) {}
477
478   //
479   Result_t ReadFrame(ui32_t FrameNum, StereoscopicPhase_t phase, FrameBuffer& FrameBuf,
480                      AESDecContext* Ctx, HMACContext* HMAC)
481   {
482     // look up frame index node
483     IndexTableSegment::IndexEntry TmpEntry;
484
485     if ( ASDCP_FAILURE(m_FooterPart.Lookup(FrameNum, TmpEntry)) )
486       {
487         DefaultLogSink().Error("Frame value out of range: %u\n", FrameNum);
488         return RESULT_RANGE;
489       }
490
491     // get frame position
492     Kumu::fpos_t FilePosition = m_EssenceStart + TmpEntry.StreamOffset;
493     Result_t result = RESULT_OK;
494
495     if ( phase == SP_LEFT )
496       {    
497         if ( FilePosition != m_LastPosition )
498           {
499             m_LastPosition = FilePosition;
500             result = m_File.Seek(FilePosition);
501           }
502
503         // the call to ReadEKLVPacket() will leave the file on an R frame
504         m_StereoFrameReady = FrameNum;
505       }
506     else if ( phase == SP_RIGHT )
507       {
508         if ( m_StereoFrameReady != FrameNum )
509           {
510             // the file is not already positioned, we must do some work
511             // seek to the companion SP_LEFT frame and read the frame's key and length
512             if ( FilePosition != m_LastPosition )
513               {
514                 m_LastPosition = FilePosition;
515                 result = m_File.Seek(FilePosition);
516               }
517
518             KLReader Reader;
519             result = Reader.ReadKLFromFile(m_File);
520
521             if ( ASDCP_SUCCESS(result) )
522               {
523                 // skip over the companion SP_LEFT frame
524                 Kumu::fpos_t new_pos = FilePosition + SMPTE_UL_LENGTH + Reader.KLLength() + Reader.Length();
525                 result = m_File.Seek(new_pos);
526               }
527           }
528
529         // the call to ReadEKLVPacket() will leave the file not on an R frame
530         m_StereoFrameReady = 0xffffffff;
531       }
532     else
533       {
534         DefaultLogSink().Error("Unexpected stereoscopic phase value: %u\n", phase);
535         return RESULT_STATE;
536       }
537
538     if( ASDCP_SUCCESS(result) )
539       {
540         ui32_t SequenceNum = FrameNum * 2;
541         SequenceNum += ( phase == SP_RIGHT ) ? 2 : 1;
542         result = ReadEKLVPacket(FrameNum, SequenceNum, FrameBuf, Dict::ul(MDD_JPEG2000Essence), Ctx, HMAC);
543       }
544
545     return result;
546   }
547 };
548
549
550
551 ASDCP::JP2K::MXFSReader::MXFSReader()
552 {
553   m_Reader = new h__SReader;
554 }
555
556
557 ASDCP::JP2K::MXFSReader::~MXFSReader()
558 {
559 }
560
561 // Open the file for reading. The file must exist. Returns error if the
562 // operation cannot be completed.
563 ASDCP::Result_t
564 ASDCP::JP2K::MXFSReader::OpenRead(const char* filename) const
565 {
566   return m_Reader->OpenRead(filename, ASDCP::ESS_JPEG_2000_S);
567 }
568
569 //
570 ASDCP::Result_t
571 ASDCP::JP2K::MXFSReader::ReadFrame(ui32_t FrameNum, SFrameBuffer& FrameBuf, AESDecContext* Ctx, HMACContext* HMAC) const
572 {
573   Result_t result = RESULT_INIT;
574
575   if ( m_Reader && m_Reader->m_File.IsOpen() )
576     {
577       result = m_Reader->ReadFrame(FrameNum, SP_LEFT, FrameBuf.Left, Ctx, HMAC);
578
579       if ( ASDCP_SUCCESS(result) )
580         result = m_Reader->ReadFrame(FrameNum, SP_RIGHT, FrameBuf.Right, Ctx, HMAC);
581     }
582
583   return result;
584 }
585
586 //
587 ASDCP::Result_t
588 ASDCP::JP2K::MXFSReader::ReadFrame(ui32_t FrameNum, StereoscopicPhase_t phase, FrameBuffer& FrameBuf,
589                                    AESDecContext* Ctx, HMACContext* HMAC) const
590 {
591   if ( m_Reader && m_Reader->m_File.IsOpen() )
592     return m_Reader->ReadFrame(FrameNum, phase, FrameBuf, Ctx, HMAC);
593
594   return RESULT_INIT;
595 }
596
597 // Fill the struct with the values from the file's header.
598 // Returns RESULT_INIT if the file is not open.
599 ASDCP::Result_t
600 ASDCP::JP2K::MXFSReader::FillPictureDescriptor(PictureDescriptor& PDesc) const
601 {
602   if ( m_Reader && m_Reader->m_File.IsOpen() )
603     {
604       PDesc = m_Reader->m_PDesc;
605       return RESULT_OK;
606     }
607
608   return RESULT_INIT;
609 }
610
611
612 // Fill the struct with the values from the file's header.
613 // Returns RESULT_INIT if the file is not open.
614 ASDCP::Result_t
615 ASDCP::JP2K::MXFSReader::FillWriterInfo(WriterInfo& Info) const
616 {
617   if ( m_Reader && m_Reader->m_File.IsOpen() )
618     {
619       Info = m_Reader->m_Info;
620       return RESULT_OK;
621     }
622
623   return RESULT_INIT;
624 }
625
626 //
627 void
628 ASDCP::JP2K::MXFSReader::DumpHeaderMetadata(FILE* stream) const
629 {
630   if ( m_Reader->m_File.IsOpen() )
631     m_Reader->m_HeaderPart.Dump(stream);
632 }
633
634
635 //
636 void
637 ASDCP::JP2K::MXFSReader::DumpIndex(FILE* stream) const
638 {
639   if ( m_Reader->m_File.IsOpen() )
640     m_Reader->m_FooterPart.Dump(stream);
641 }
642
643 //------------------------------------------------------------------------------------------
644
645
646 //
647 class lh__Writer : public ASDCP::h__Writer
648 {
649   JPEG2000PictureSubDescriptor* m_EssenceSubDescriptor;
650
651 public:
652   PictureDescriptor m_PDesc;
653   byte_t            m_EssenceUL[SMPTE_UL_LENGTH];
654
655   ASDCP_NO_COPY_CONSTRUCT(lh__Writer);
656
657   lh__Writer() : m_EssenceSubDescriptor(0) {
658     memset(m_EssenceUL, 0, SMPTE_UL_LENGTH);
659   }
660
661   ~lh__Writer(){}
662
663   Result_t OpenWrite(const char*, EssenceType_t type, ui32_t HeaderSize);
664   Result_t SetSourceStream(const PictureDescriptor&, const std::string& label,
665                            ASDCP::Rational LocalEditRate = ASDCP::Rational(0,0));
666   Result_t WriteFrame(const JP2K::FrameBuffer&, bool add_index, AESEncContext*, HMACContext*);
667   Result_t Finalize();
668   Result_t JP2K_PDesc_to_MD(JP2K::PictureDescriptor& PDesc);
669 };
670
671 const int VideoLineMapSize = 16; // See SMPTE 377M D.2.1
672 const int PixelLayoutSize = 8*2; // See SMPTE 377M D.2.3
673 static const byte_t s_PixelLayoutXYZ[PixelLayoutSize] = { 0xd8, 0x0c, 0xd9, 0x0c, 0xda, 0x0c, 0x00 };
674
675 //
676 ASDCP::Result_t
677 lh__Writer::JP2K_PDesc_to_MD(JP2K::PictureDescriptor& PDesc)
678 {
679   assert(m_EssenceDescriptor);
680   assert(m_EssenceSubDescriptor);
681   MXF::RGBAEssenceDescriptor* PDescObj = (MXF::RGBAEssenceDescriptor*)m_EssenceDescriptor;
682
683   PDescObj->ContainerDuration = PDesc.ContainerDuration;
684   PDescObj->SampleRate = PDesc.EditRate;
685   PDescObj->FrameLayout = 0;
686   PDescObj->StoredWidth = PDesc.StoredWidth;
687   PDescObj->StoredHeight = PDesc.StoredHeight;
688   PDescObj->AspectRatio = PDesc.AspectRatio;
689
690   //  if ( m_Info.LabelSetType == LS_MXF_SMPTE )
691   //    {
692   // PictureEssenceCoding UL = 
693   // Video Line Map       ui32_t[VideoLineMapSize] = { 2, 4, 0, 0 }
694   // CaptureGamma         UL = 
695   // ComponentMaxRef      ui32_t = 4095
696   // ComponentMinRef      ui32_t = 0
697   // PixelLayout          byte_t[PixelLayoutSize] = s_PixelLayoutXYZ
698   //    }
699
700   if ( PDesc.StoredWidth < 2049 )
701     {
702       PDescObj->PictureEssenceCoding.Set(Dict::ul(MDD_JP2KEssenceCompression_2K));
703       m_EssenceSubDescriptor->Rsize = 3;
704     }
705   else
706     {
707       PDescObj->PictureEssenceCoding.Set(Dict::ul(MDD_JP2KEssenceCompression_4K));
708       m_EssenceSubDescriptor->Rsize = 4;
709     }
710
711   m_EssenceSubDescriptor->Xsize = PDesc.Xsize;
712   m_EssenceSubDescriptor->Ysize = PDesc.Ysize;
713   m_EssenceSubDescriptor->XOsize = PDesc.XOsize;
714   m_EssenceSubDescriptor->YOsize = PDesc.YOsize;
715   m_EssenceSubDescriptor->XTsize = PDesc.XTsize;
716   m_EssenceSubDescriptor->YTsize = PDesc.YTsize;
717   m_EssenceSubDescriptor->XTOsize = PDesc.XTOsize;
718   m_EssenceSubDescriptor->YTOsize = PDesc.YTOsize;
719   m_EssenceSubDescriptor->Csize = PDesc.Csize;
720
721   const ui32_t tmp_buffer_len = 1024;
722   byte_t tmp_buffer[tmp_buffer_len];
723
724   *(ui32_t*)tmp_buffer = KM_i32_BE(MaxComponents); // three components
725   *(ui32_t*)(tmp_buffer+4) = KM_i32_BE(sizeof(ASDCP::JP2K::ImageComponent_t));
726   memcpy(tmp_buffer + 8, &PDesc.ImageComponents, sizeof(ASDCP::JP2K::ImageComponent_t) * MaxComponents);
727
728   const ui32_t pcomp_size = (sizeof(int) * 2) + (sizeof(ASDCP::JP2K::ImageComponent_t) * MaxComponents);
729   memcpy(m_EssenceSubDescriptor->PictureComponentSizing.Data(), tmp_buffer, pcomp_size);
730   m_EssenceSubDescriptor->PictureComponentSizing.Length(pcomp_size);
731
732   ui32_t precinct_set_size = 0, i;
733   for ( i = 0; PDesc.CodingStyleDefault.SPcod.PrecinctSize[i] != 0 && i < MaxPrecincts; i++ )
734     precinct_set_size++;
735
736   ui32_t csd_size = sizeof(CodingStyleDefault_t) - MaxPrecincts + precinct_set_size;
737   memcpy(m_EssenceSubDescriptor->CodingStyleDefault.Data(), &PDesc.CodingStyleDefault, csd_size);
738   m_EssenceSubDescriptor->CodingStyleDefault.Length(csd_size);
739
740   ui32_t qdflt_size = PDesc.QuantizationDefault.SPqcdLength + 1;
741   memcpy(m_EssenceSubDescriptor->QuantizationDefault.Data(), &PDesc.QuantizationDefault, qdflt_size);
742   m_EssenceSubDescriptor->QuantizationDefault.Length(qdflt_size);
743
744   return RESULT_OK;
745 }
746
747
748 // Open the file for writing. The file must not exist. Returns error if
749 // the operation cannot be completed.
750 ASDCP::Result_t
751 lh__Writer::OpenWrite(const char* filename, EssenceType_t type, ui32_t HeaderSize)
752 {
753   if ( ! m_State.Test_BEGIN() )
754     return RESULT_STATE;
755
756   Result_t result = m_File.OpenWrite(filename);
757
758   if ( ASDCP_SUCCESS(result) )
759     {
760       m_HeaderSize = HeaderSize;
761       RGBAEssenceDescriptor* tmp_rgba = new RGBAEssenceDescriptor;
762       tmp_rgba->ComponentMaxRef = 4095;
763       tmp_rgba->ComponentMinRef = 0;
764
765       m_EssenceDescriptor = tmp_rgba;
766       m_EssenceSubDescriptor = new JPEG2000PictureSubDescriptor;
767       m_EssenceSubDescriptorList.push_back((InterchangeObject*)m_EssenceSubDescriptor);
768
769       GenRandomValue(m_EssenceSubDescriptor->InstanceUID);
770       m_EssenceDescriptor->SubDescriptors.push_back(m_EssenceSubDescriptor->InstanceUID);
771
772       if ( type == ASDCP::ESS_JPEG_2000_S && m_Info.LabelSetType == LS_MXF_SMPTE )
773         {
774           InterchangeObject* StereoSubDesc = new StereoscopicPictureSubDescriptor;
775           m_EssenceSubDescriptorList.push_back(StereoSubDesc);
776           GenRandomValue(StereoSubDesc->InstanceUID);
777           m_EssenceDescriptor->SubDescriptors.push_back(StereoSubDesc->InstanceUID);
778         }
779
780       result = m_State.Goto_INIT();
781     }
782
783   return result;
784 }
785
786 // Automatically sets the MXF file's metadata from the first jpeg codestream stream.
787 ASDCP::Result_t
788 lh__Writer::SetSourceStream(const PictureDescriptor& PDesc, const std::string& label, ASDCP::Rational LocalEditRate)
789 {
790   if ( ! m_State.Test_INIT() )
791     return RESULT_STATE;
792
793   if ( LocalEditRate == ASDCP::Rational(0,0) )
794     LocalEditRate = PDesc.EditRate;
795
796   m_PDesc = PDesc;
797   Result_t result = JP2K_PDesc_to_MD(m_PDesc);
798
799   if ( ASDCP_SUCCESS(result) )
800       result = WriteMXFHeader(label, UL(Dict::ul(MDD_JPEG_2000Wrapping)),
801                               PICT_DEF_LABEL,     UL(Dict::ul(MDD_PictureDataDef)),
802                               LocalEditRate, 24 /* TCFrameRate */);
803
804   if ( ASDCP_SUCCESS(result) )
805     {
806       memcpy(m_EssenceUL, Dict::ul(MDD_JPEG2000Essence), SMPTE_UL_LENGTH);
807       m_EssenceUL[SMPTE_UL_LENGTH-1] = 1; // first (and only) essence container
808       result = m_State.Goto_READY();
809     }
810
811   return result;
812 }
813
814 // Writes a frame of essence to the MXF file. If the optional AESEncContext
815 // argument is present, the essence is encrypted prior to writing.
816 // Fails if the file is not open, is finalized, or an operating system
817 // error occurs.
818 //
819 ASDCP::Result_t
820 lh__Writer::WriteFrame(const JP2K::FrameBuffer& FrameBuf, bool add_index,
821                        AESEncContext* Ctx, HMACContext* HMAC)
822 {
823   Result_t result = RESULT_OK;
824
825   if ( m_State.Test_READY() )
826     result = m_State.Goto_RUNNING(); // first time through
827  
828   ui64_t StreamOffset = m_StreamOffset;
829
830   if ( ASDCP_SUCCESS(result) )
831     result = WriteEKLVPacket(FrameBuf, m_EssenceUL, Ctx, HMAC);
832
833   if ( ASDCP_SUCCESS(result) && add_index )
834     {  
835       IndexTableSegment::IndexEntry Entry;
836       Entry.StreamOffset = StreamOffset;
837       m_FooterPart.PushIndexEntry(Entry);
838     }
839
840   m_FramesWritten++;
841   return result;
842 }
843
844
845 // Closes the MXF file, writing the index and other closing information.
846 //
847 ASDCP::Result_t
848 lh__Writer::Finalize()
849 {
850   if ( ! m_State.Test_RUNNING() )
851     return RESULT_STATE;
852
853   m_State.Goto_FINAL();
854
855   return WriteMXFFooter();
856 }
857
858
859 //
860 class ASDCP::JP2K::MXFWriter::h__Writer : public lh__Writer
861 {
862 };
863
864
865 //------------------------------------------------------------------------------------------
866
867
868
869 ASDCP::JP2K::MXFWriter::MXFWriter()
870 {
871 }
872
873 ASDCP::JP2K::MXFWriter::~MXFWriter()
874 {
875 }
876
877
878 // Open the file for writing. The file must not exist. Returns error if
879 // the operation cannot be completed.
880 ASDCP::Result_t
881 ASDCP::JP2K::MXFWriter::OpenWrite(const char* filename, const WriterInfo& Info,
882                                   const PictureDescriptor& PDesc, ui32_t HeaderSize)
883 {
884   m_Writer = new h__Writer;
885   m_Writer->m_Info = Info;
886
887   Result_t result = m_Writer->OpenWrite(filename, ASDCP::ESS_JPEG_2000, HeaderSize);
888
889   if ( ASDCP_SUCCESS(result) )
890     result = m_Writer->SetSourceStream(PDesc, JP2K_PACKAGE_LABEL);
891
892   if ( ASDCP_FAILURE(result) )
893     m_Writer.release();
894
895   return result;
896 }
897
898
899 // Writes a frame of essence to the MXF file. If the optional AESEncContext
900 // argument is present, the essence is encrypted prior to writing.
901 // Fails if the file is not open, is finalized, or an operating system
902 // error occurs.
903 ASDCP::Result_t
904 ASDCP::JP2K::MXFWriter::WriteFrame(const FrameBuffer& FrameBuf, AESEncContext* Ctx, HMACContext* HMAC)
905 {
906   if ( m_Writer.empty() )
907     return RESULT_INIT;
908
909   return m_Writer->WriteFrame(FrameBuf, true, Ctx, HMAC);
910 }
911
912 // Closes the MXF file, writing the index and other closing information.
913 ASDCP::Result_t
914 ASDCP::JP2K::MXFWriter::Finalize()
915 {
916   if ( m_Writer.empty() )
917     return RESULT_INIT;
918
919   return m_Writer->Finalize();
920 }
921
922
923 //------------------------------------------------------------------------------------------
924 //
925
926 //
927 class ASDCP::JP2K::MXFSWriter::h__SWriter : public lh__Writer
928 {
929   StereoscopicPhase_t m_NextPhase;
930
931 public:
932   h__SWriter() : m_NextPhase(SP_LEFT) {}
933
934   //
935   Result_t WriteFrame(const FrameBuffer& FrameBuf, StereoscopicPhase_t phase,
936                       AESEncContext* Ctx, HMACContext* HMAC)
937   {
938     if ( m_NextPhase != phase )
939       return RESULT_SPHASE;
940
941     if ( phase == SP_LEFT )
942       {
943         m_NextPhase = SP_RIGHT;
944         return lh__Writer::WriteFrame(FrameBuf, true, Ctx, HMAC);
945       }
946
947     m_NextPhase = SP_LEFT;
948     return lh__Writer::WriteFrame(FrameBuf, false, Ctx, HMAC);
949   }
950
951   //
952   Result_t Finalize()
953   {
954     if ( m_NextPhase != SP_LEFT )
955       return RESULT_SPHASE;
956
957     assert( m_FramesWritten % 2 == 0 );
958     m_FramesWritten /= 2;
959     return lh__Writer::Finalize();
960   }
961 };
962
963
964 //
965 ASDCP::JP2K::MXFSWriter::MXFSWriter()
966 {
967 }
968
969 ASDCP::JP2K::MXFSWriter::~MXFSWriter()
970 {
971 }
972
973
974 // Open the file for writing. The file must not exist. Returns error if
975 // the operation cannot be completed.
976 ASDCP::Result_t
977 ASDCP::JP2K::MXFSWriter::OpenWrite(const char* filename, const WriterInfo& Info,
978                                    const PictureDescriptor& PDesc, ui32_t HeaderSize)
979 {
980   m_Writer = new h__SWriter;
981   
982   if ( PDesc.EditRate != ASDCP::EditRate_24 )
983     {
984       DefaultLogSink().Error("Stereoscopic wrapping requires 24 fps input streams.\n");
985       return RESULT_FORMAT;
986     }
987
988   if ( PDesc.StoredWidth > 2048 )
989     DefaultLogSink().Warn("Wrapping non-standard 4K stereoscopic content. I hope you know what you are doing!\n");
990
991   m_Writer->m_Info = Info;
992
993   Result_t result = m_Writer->OpenWrite(filename, ASDCP::ESS_JPEG_2000_S, HeaderSize);
994
995   if ( ASDCP_SUCCESS(result) )
996     {
997       PictureDescriptor TmpPDesc = PDesc;
998       TmpPDesc.EditRate = ASDCP::EditRate_48;
999
1000       result = m_Writer->SetSourceStream(TmpPDesc, JP2K_S_PACKAGE_LABEL, ASDCP::EditRate_24);
1001     }
1002
1003   if ( ASDCP_FAILURE(result) )
1004     m_Writer.release();
1005
1006   return result;
1007 }
1008
1009 ASDCP::Result_t
1010 ASDCP::JP2K::MXFSWriter::WriteFrame(const SFrameBuffer& FrameBuf, AESEncContext* Ctx, HMACContext* HMAC)
1011 {
1012   if ( m_Writer.empty() )
1013     return RESULT_INIT;
1014
1015   Result_t result = m_Writer->WriteFrame(FrameBuf.Left, SP_LEFT, Ctx, HMAC);
1016
1017   if ( ASDCP_SUCCESS(result) )
1018     result = m_Writer->WriteFrame(FrameBuf.Right, SP_RIGHT, Ctx, HMAC);
1019
1020   return result;
1021 }
1022
1023 // Writes a frame of essence to the MXF file. If the optional AESEncContext
1024 // argument is present, the essence is encrypted prior to writing.
1025 // Fails if the file is not open, is finalized, or an operating system
1026 // error occurs.
1027 ASDCP::Result_t
1028 ASDCP::JP2K::MXFSWriter::WriteFrame(const FrameBuffer& FrameBuf, StereoscopicPhase_t phase,
1029                                     AESEncContext* Ctx, HMACContext* HMAC)
1030 {
1031   if ( m_Writer.empty() )
1032     return RESULT_INIT;
1033
1034   return m_Writer->WriteFrame(FrameBuf, phase, Ctx, HMAC);
1035 }
1036
1037 // Closes the MXF file, writing the index and other closing information.
1038 ASDCP::Result_t
1039 ASDCP::JP2K::MXFSWriter::Finalize()
1040 {
1041   if ( m_Writer.empty() )
1042     return RESULT_INIT;
1043
1044   return m_Writer->Finalize();
1045 }
1046
1047 //
1048 // end AS_DCP_JP2K.cpp
1049 //