2 Copyright (c) 2004-2007, 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_DCP_JP2k.cpp
29 \brief AS-DCP library, JPEG 2000 essence reader and writer implementation
32 #include "AS_DCP_internal.h"
34 using namespace ASDCP::JP2K;
37 //------------------------------------------------------------------------------------------
39 static std::string JP2K_PACKAGE_LABEL = "File Package: SMPTE 429-4 frame wrapping of JPEG 2000 codestreams";
40 static std::string JP2K_S_PACKAGE_LABEL = "File Package: SMPTE 429-10 frame wrapping of stereoscopic JPEG 2000 codestreams";
41 static std::string PICT_DEF_LABEL = "Picture Track";
43 int s_exp_lookup[16] = { 0, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024,2048, 4096, 8192, 16384, 32768 };
47 ASDCP::JP2K::PictureDescriptorDump(const PictureDescriptor& PDesc, FILE* stream)
66 ContainerDuration: %u\n",
67 PDesc.AspectRatio.Numerator, PDesc.AspectRatio.Denominator,
68 PDesc.EditRate.Numerator, PDesc.EditRate.Denominator,
80 PDesc.ContainerDuration
83 fprintf(stream, "-- JPEG 2000 Metadata --\n");
84 fprintf(stream, " ImageComponents:\n");
85 fprintf(stream, " bits h-sep v-sep\n");
87 for ( ui32_t i = 0; i < PDesc.Csize; i++ )
89 fprintf(stream, " %4d %5d %5d\n",
90 PDesc.ImageComponents[i].Ssize + 1, // See ISO 15444-1, Table A11, for the origin of '+1'
91 PDesc.ImageComponents[i].XRsize,
92 PDesc.ImageComponents[i].YRsize
96 fprintf(stream, " Scod: %hd\n", PDesc.CodingStyleDefault.Scod);
97 fprintf(stream, " ProgressionOrder: %hd\n", PDesc.CodingStyleDefault.SGcod.ProgressionOrder);
98 fprintf(stream, " NumberOfLayers: %hd\n",
99 KM_i16_BE(Kumu::cp2i<ui16_t>(PDesc.CodingStyleDefault.SGcod.NumberOfLayers)));
101 fprintf(stream, " MultiCompTransform: %hd\n", PDesc.CodingStyleDefault.SGcod.MultiCompTransform);
102 fprintf(stream, "DecompositionLevels: %hd\n", PDesc.CodingStyleDefault.SPcod.DecompositionLevels);
103 fprintf(stream, " CodeblockWidth: %hd\n", PDesc.CodingStyleDefault.SPcod.CodeblockWidth);
104 fprintf(stream, " CodeblockHeight: %hd\n", PDesc.CodingStyleDefault.SPcod.CodeblockHeight);
105 fprintf(stream, " CodeblockStyle: %hd\n", PDesc.CodingStyleDefault.SPcod.CodeblockStyle);
106 fprintf(stream, " Transformation: %hd\n", PDesc.CodingStyleDefault.SPcod.Transformation);
109 ui32_t precinct_set_size = 0, i;
111 for ( i = 0; PDesc.CodingStyleDefault.SPcod.PrecinctSize[i] != 0 && i < MaxPrecincts; i++ )
114 fprintf(stream, " Precincts: %hd\n", precinct_set_size);
115 fprintf(stream, "precinct dimensions:\n");
117 for ( i = 0; i < precinct_set_size; i++ )
118 fprintf(stream, " %d: %d x %d\n", i + 1,
119 s_exp_lookup[PDesc.CodingStyleDefault.SPcod.PrecinctSize[i]&0x0f],
120 s_exp_lookup[(PDesc.CodingStyleDefault.SPcod.PrecinctSize[i]>>4)&0x0f]
123 fprintf(stream, " Sqcd: %hd\n", PDesc.QuantizationDefault.Sqcd);
125 char tmp_buf[MaxDefaults*2];
126 fprintf(stream, " SPqcd: %s\n",
127 Kumu::bin2hex(PDesc.QuantizationDefault.SPqcd, PDesc.QuantizationDefault.SPqcdLength,
128 tmp_buf, MaxDefaults*2)
132 //------------------------------------------------------------------------------------------
134 // hidden, internal implementation of JPEG 2000 reader
136 class lh__Reader : public ASDCP::h__Reader
138 RGBAEssenceDescriptor* m_EssenceDescriptor;
139 JPEG2000PictureSubDescriptor* m_EssenceSubDescriptor;
140 ASDCP::Rational m_EditRate;
141 EssenceType_t m_Format;
143 ASDCP_NO_COPY_CONSTRUCT(lh__Reader);
146 PictureDescriptor m_PDesc; // codestream parameter list
148 lh__Reader() : m_EssenceDescriptor(0), m_EssenceSubDescriptor(0), m_Format(ESS_UNKNOWN) {}
149 Result_t OpenRead(const char*, EssenceType_t);
150 Result_t ReadFrame(ui32_t, JP2K::FrameBuffer&, AESDecContext*, HMACContext*);
151 Result_t MD_to_JP2K_PDesc(JP2K::PictureDescriptor& PDesc);
156 lh__Reader::MD_to_JP2K_PDesc(JP2K::PictureDescriptor& PDesc)
158 memset(&PDesc, 0, sizeof(PDesc));
159 MXF::RGBAEssenceDescriptor* PDescObj = (MXF::RGBAEssenceDescriptor*)m_EssenceDescriptor;
161 PDesc.EditRate = m_EditRate;
162 PDesc.ContainerDuration = PDescObj->ContainerDuration;
163 PDesc.StoredWidth = PDescObj->StoredWidth;
164 PDesc.StoredHeight = PDescObj->StoredHeight;
165 PDesc.AspectRatio = PDescObj->AspectRatio;
167 if ( m_EssenceSubDescriptor != 0 )
169 PDesc.Rsize = m_EssenceSubDescriptor->Rsize;
170 PDesc.Xsize = m_EssenceSubDescriptor->Xsize;
171 PDesc.Ysize = m_EssenceSubDescriptor->Ysize;
172 PDesc.XOsize = m_EssenceSubDescriptor->XOsize;
173 PDesc.YOsize = m_EssenceSubDescriptor->YOsize;
174 PDesc.XTsize = m_EssenceSubDescriptor->XTsize;
175 PDesc.YTsize = m_EssenceSubDescriptor->YTsize;
176 PDesc.XTOsize = m_EssenceSubDescriptor->XTOsize;
177 PDesc.YTOsize = m_EssenceSubDescriptor->YTOsize;
178 PDesc.Csize = m_EssenceSubDescriptor->Csize;
180 // PictureComponentSizing
181 ui32_t tmp_size = m_EssenceSubDescriptor->PictureComponentSizing.Length();
183 if ( tmp_size == 17 ) // ( 2 * sizeof(ui32_t) ) + 3 components * 3 byte each
184 memcpy(&PDesc.ImageComponents, m_EssenceSubDescriptor->PictureComponentSizing.RoData() + 8, tmp_size - 8);
187 DefaultLogSink().Error("Unexpected PictureComponentSizing size: %u, should be 17\n", tmp_size);
189 // CodingStyleDefault
190 memset(&m_PDesc.CodingStyleDefault, 0, sizeof(CodingStyleDefault_t));
191 memcpy(&m_PDesc.CodingStyleDefault,
192 m_EssenceSubDescriptor->CodingStyleDefault.RoData(),
193 m_EssenceSubDescriptor->CodingStyleDefault.Length());
195 // QuantizationDefault
196 memset(&m_PDesc.QuantizationDefault, 0, sizeof(QuantizationDefault_t));
197 memcpy(&m_PDesc.QuantizationDefault,
198 m_EssenceSubDescriptor->QuantizationDefault.RoData(),
199 m_EssenceSubDescriptor->QuantizationDefault.Length());
201 m_PDesc.QuantizationDefault.SPqcdLength = m_EssenceSubDescriptor->QuantizationDefault.Length() - 1;
210 lh__Reader::OpenRead(const char* filename, EssenceType_t type)
212 Result_t result = OpenMXFRead(filename);
214 if( ASDCP_SUCCESS(result) )
216 m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(RGBAEssenceDescriptor),
217 (InterchangeObject**)&m_EssenceDescriptor);
218 m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(JPEG2000PictureSubDescriptor),
219 (InterchangeObject**)&m_EssenceSubDescriptor);
221 std::list<InterchangeObject*> ObjectList;
222 m_HeaderPart.GetMDObjectsByType(OBJ_TYPE_ARGS(Track), ObjectList);
224 if ( ObjectList.empty() )
226 DefaultLogSink().Error("MXF Metadata contains no Track Sets\n");
227 return RESULT_FORMAT;
230 m_EditRate = ((Track*)ObjectList.front())->EditRate;
232 if ( type == ASDCP::ESS_JPEG_2000 )
234 if ( m_EditRate != m_EssenceDescriptor->SampleRate )
236 DefaultLogSink().Error("EditRate and SampleRate do not match (%.03f, %.03f)\n",
237 m_EditRate.Quotient(), m_EssenceDescriptor->SampleRate.Quotient());
238 return RESULT_SFORMAT;
241 else if ( type == ASDCP::ESS_JPEG_2000_S )
243 if ( ! ( m_EditRate == EditRate_24 && m_EssenceDescriptor->SampleRate == EditRate_48 ) )
245 DefaultLogSink().Error("EditRate and SampleRate not correct for 24/48 stereoscopic essence\n");
246 return RESULT_FORMAT;
251 DefaultLogSink().Error("'type' argument unexpected: %x\n", type);
255 result = MD_to_JP2K_PDesc(m_PDesc);
258 if( ASDCP_SUCCESS(result) )
259 result = InitMXFIndex();
261 if( ASDCP_SUCCESS(result) )
270 lh__Reader::ReadFrame(ui32_t FrameNum, JP2K::FrameBuffer& FrameBuf,
271 AESDecContext* Ctx, HMACContext* HMAC)
273 if ( ! m_File.IsOpen() )
276 return ReadEKLVFrame(FrameNum, FrameBuf, Dict::ul(MDD_JPEG2000Essence), Ctx, HMAC);
281 class ASDCP::JP2K::MXFReader::h__Reader : public lh__Reader
287 //------------------------------------------------------------------------------------------
292 ASDCP::JP2K::FrameBuffer::Dump(FILE* stream, ui32_t dump_len) const
297 fprintf(stream, "Frame: %06u, %7u bytes", m_FrameNumber, m_Size);
302 Kumu::hexdump(m_Data, dump_len, stream);
306 //------------------------------------------------------------------------------------------
308 ASDCP::JP2K::MXFReader::MXFReader()
310 m_Reader = new h__Reader;
314 ASDCP::JP2K::MXFReader::~MXFReader()
318 // Open the file for reading. The file must exist. Returns error if the
319 // operation cannot be completed.
321 ASDCP::JP2K::MXFReader::OpenRead(const char* filename) const
323 return m_Reader->OpenRead(filename, ASDCP::ESS_JPEG_2000);
328 ASDCP::JP2K::MXFReader::ReadFrame(ui32_t FrameNum, FrameBuffer& FrameBuf,
329 AESDecContext* Ctx, HMACContext* HMAC) const
331 if ( m_Reader && m_Reader->m_File.IsOpen() )
332 return m_Reader->ReadFrame(FrameNum, FrameBuf, Ctx, HMAC);
338 // Fill the struct with the values from the file's header.
339 // Returns RESULT_INIT if the file is not open.
341 ASDCP::JP2K::MXFReader::FillPictureDescriptor(PictureDescriptor& PDesc) const
343 if ( m_Reader && m_Reader->m_File.IsOpen() )
345 PDesc = m_Reader->m_PDesc;
353 // Fill the struct with the values from the file's header.
354 // Returns RESULT_INIT if the file is not open.
356 ASDCP::JP2K::MXFReader::FillWriterInfo(WriterInfo& Info) const
358 if ( m_Reader && m_Reader->m_File.IsOpen() )
360 Info = m_Reader->m_Info;
369 ASDCP::JP2K::MXFReader::DumpHeaderMetadata(FILE* stream) const
371 if ( m_Reader->m_File.IsOpen() )
372 m_Reader->m_HeaderPart.Dump(stream);
378 ASDCP::JP2K::MXFReader::DumpIndex(FILE* stream) const
380 if ( m_Reader->m_File.IsOpen() )
381 m_Reader->m_FooterPart.Dump(stream);
385 //------------------------------------------------------------------------------------------
387 class ASDCP::JP2K::MXFSReader::h__SReader : public lh__Reader
389 StereoscopicPhase_t m_NextPhase;
392 h__SReader() : m_NextPhase(SP_LEFT) {}
395 Result_t ReadFrame(ui32_t FrameNum, StereoscopicPhase_t phase, FrameBuffer& FrameBuf,
396 AESDecContext* Ctx, HMACContext* HMAC) const
398 return Kumu::RESULT_NOTIMPL;
404 ASDCP::JP2K::MXFSReader::MXFSReader()
406 m_Reader = new h__SReader;
410 ASDCP::JP2K::MXFSReader::~MXFSReader()
414 // Open the file for reading. The file must exist. Returns error if the
415 // operation cannot be completed.
417 ASDCP::JP2K::MXFSReader::OpenRead(const char* filename) const
419 return m_Reader->OpenRead(filename, ASDCP::ESS_JPEG_2000_S);
424 ASDCP::JP2K::MXFSReader::ReadFrame(ui32_t FrameNum, StereoscopicPhase_t phase, FrameBuffer& FrameBuf,
425 AESDecContext* Ctx, HMACContext* HMAC) const
427 if ( m_Reader && m_Reader->m_File.IsOpen() )
428 return m_Reader->ReadFrame(FrameNum, phase, FrameBuf, Ctx, HMAC);
434 // Fill the struct with the values from the file's header.
435 // Returns RESULT_INIT if the file is not open.
437 ASDCP::JP2K::MXFSReader::FillPictureDescriptor(PictureDescriptor& PDesc) const
439 if ( m_Reader && m_Reader->m_File.IsOpen() )
441 PDesc = m_Reader->m_PDesc;
449 // Fill the struct with the values from the file's header.
450 // Returns RESULT_INIT if the file is not open.
452 ASDCP::JP2K::MXFSReader::FillWriterInfo(WriterInfo& Info) const
454 if ( m_Reader && m_Reader->m_File.IsOpen() )
456 Info = m_Reader->m_Info;
465 ASDCP::JP2K::MXFSReader::DumpHeaderMetadata(FILE* stream) const
467 if ( m_Reader->m_File.IsOpen() )
468 m_Reader->m_HeaderPart.Dump(stream);
474 ASDCP::JP2K::MXFSReader::DumpIndex(FILE* stream) const
476 if ( m_Reader->m_File.IsOpen() )
477 m_Reader->m_FooterPart.Dump(stream);
480 //------------------------------------------------------------------------------------------
484 class lh__Writer : public ASDCP::h__Writer
486 JPEG2000PictureSubDescriptor* m_EssenceSubDescriptor;
489 PictureDescriptor m_PDesc;
490 byte_t m_EssenceUL[SMPTE_UL_LENGTH];
492 ASDCP_NO_COPY_CONSTRUCT(lh__Writer);
494 lh__Writer() : m_EssenceSubDescriptor(0) {
495 memset(m_EssenceUL, 0, SMPTE_UL_LENGTH);
500 Result_t OpenWrite(const char*, EssenceType_t type, ui32_t HeaderSize);
501 Result_t SetSourceStream(const PictureDescriptor&, const std::string& label,
502 ASDCP::Rational LocalEditRate = ASDCP::Rational(0,0));
503 Result_t WriteFrame(const JP2K::FrameBuffer&, bool add_index, AESEncContext*, HMACContext*);
505 Result_t JP2K_PDesc_to_MD(JP2K::PictureDescriptor& PDesc);
511 lh__Writer::JP2K_PDesc_to_MD(JP2K::PictureDescriptor& PDesc)
513 assert(m_EssenceDescriptor);
514 assert(m_EssenceSubDescriptor);
515 MXF::RGBAEssenceDescriptor* PDescObj = (MXF::RGBAEssenceDescriptor*)m_EssenceDescriptor;
517 PDescObj->SampleRate = PDesc.EditRate;
518 PDescObj->ContainerDuration = PDesc.ContainerDuration;
519 PDescObj->StoredWidth = PDesc.StoredWidth;
520 PDescObj->StoredHeight = PDesc.StoredHeight;
521 PDescObj->AspectRatio = PDesc.AspectRatio;
522 PDescObj->FrameLayout = 0;
524 if ( PDesc.StoredWidth < 2049 )
526 PDescObj->Codec.Set(Dict::ul(MDD_JP2KEssenceCompression_2K));
527 m_EssenceSubDescriptor->Rsize = 3;
531 PDescObj->Codec.Set(Dict::ul(MDD_JP2KEssenceCompression_4K));
532 m_EssenceSubDescriptor->Rsize = 4;
535 m_EssenceSubDescriptor->Xsize = PDesc.Xsize;
536 m_EssenceSubDescriptor->Ysize = PDesc.Ysize;
537 m_EssenceSubDescriptor->XOsize = PDesc.XOsize;
538 m_EssenceSubDescriptor->YOsize = PDesc.YOsize;
539 m_EssenceSubDescriptor->XTsize = PDesc.XTsize;
540 m_EssenceSubDescriptor->YTsize = PDesc.YTsize;
541 m_EssenceSubDescriptor->XTOsize = PDesc.XTOsize;
542 m_EssenceSubDescriptor->YTOsize = PDesc.YTOsize;
543 m_EssenceSubDescriptor->Csize = PDesc.Csize;
545 const ui32_t tmp_buffer_len = 1024;
546 byte_t tmp_buffer[tmp_buffer_len];
548 *(ui32_t*)tmp_buffer = KM_i32_BE(MaxComponents); // three components
549 *(ui32_t*)(tmp_buffer+4) = KM_i32_BE(sizeof(ASDCP::JP2K::ImageComponent_t));
550 memcpy(tmp_buffer + 8, &PDesc.ImageComponents, sizeof(ASDCP::JP2K::ImageComponent_t) * MaxComponents);
552 const ui32_t pcomp_size = (sizeof(int) * 2) + (sizeof(ASDCP::JP2K::ImageComponent_t) * MaxComponents);
553 memcpy(m_EssenceSubDescriptor->PictureComponentSizing.Data(), tmp_buffer, pcomp_size);
554 m_EssenceSubDescriptor->PictureComponentSizing.Length(pcomp_size);
556 ui32_t precinct_set_size = 0, i;
557 for ( i = 0; PDesc.CodingStyleDefault.SPcod.PrecinctSize[i] != 0 && i < MaxPrecincts; i++ )
560 ui32_t csd_size = sizeof(CodingStyleDefault_t) - MaxPrecincts + precinct_set_size;
561 memcpy(m_EssenceSubDescriptor->CodingStyleDefault.Data(), &PDesc.CodingStyleDefault, csd_size);
562 m_EssenceSubDescriptor->CodingStyleDefault.Length(csd_size);
564 ui32_t qdflt_size = PDesc.QuantizationDefault.SPqcdLength + 1;
565 memcpy(m_EssenceSubDescriptor->QuantizationDefault.Data(), &PDesc.QuantizationDefault, qdflt_size);
566 m_EssenceSubDescriptor->QuantizationDefault.Length(qdflt_size);
572 // Open the file for writing. The file must not exist. Returns error if
573 // the operation cannot be completed.
575 lh__Writer::OpenWrite(const char* filename, EssenceType_t type, ui32_t HeaderSize)
577 if ( ! m_State.Test_BEGIN() )
580 Result_t result = m_File.OpenWrite(filename);
582 if ( ASDCP_SUCCESS(result) )
584 m_HeaderSize = HeaderSize;
585 RGBAEssenceDescriptor* tmp_rgba = new RGBAEssenceDescriptor;
586 tmp_rgba->ComponentMaxRef = 4095;
587 tmp_rgba->ComponentMinRef = 0;
589 m_EssenceDescriptor = tmp_rgba;
590 m_EssenceSubDescriptor = new JPEG2000PictureSubDescriptor;
591 m_EssenceSubDescriptorList.push_back((InterchangeObject*)m_EssenceSubDescriptor);
593 GenRandomValue(m_EssenceSubDescriptor->InstanceUID);
594 m_EssenceDescriptor->SubDescriptors.push_back(m_EssenceSubDescriptor->InstanceUID);
596 if ( type == ASDCP::ESS_JPEG_2000_S )
598 InterchangeObject* StereoSubDesc = new StereoscopicPictureSubDescriptor;
599 m_EssenceSubDescriptorList.push_back(StereoSubDesc);
600 GenRandomValue(StereoSubDesc->InstanceUID);
601 m_EssenceDescriptor->SubDescriptors.push_back(StereoSubDesc->InstanceUID);
604 result = m_State.Goto_INIT();
610 // Automatically sets the MXF file's metadata from the first jpeg codestream stream.
612 lh__Writer::SetSourceStream(const PictureDescriptor& PDesc, const std::string& label, ASDCP::Rational LocalEditRate)
614 if ( ! m_State.Test_INIT() )
617 if ( LocalEditRate == ASDCP::Rational(0,0) )
618 LocalEditRate = PDesc.EditRate;
621 Result_t result = JP2K_PDesc_to_MD(m_PDesc);
623 if ( ASDCP_SUCCESS(result) )
624 result = WriteMXFHeader(label, UL(Dict::ul(MDD_JPEG_2000Wrapping)),
625 PICT_DEF_LABEL, UL(Dict::ul(MDD_PictureDataDef)),
626 LocalEditRate, 24 /* TCFrameRate */);
628 if ( ASDCP_SUCCESS(result) )
630 memcpy(m_EssenceUL, Dict::ul(MDD_JPEG2000Essence), SMPTE_UL_LENGTH);
631 m_EssenceUL[SMPTE_UL_LENGTH-1] = 1; // first (and only) essence container
632 result = m_State.Goto_READY();
638 // Writes a frame of essence to the MXF file. If the optional AESEncContext
639 // argument is present, the essence is encrypted prior to writing.
640 // Fails if the file is not open, is finalized, or an operating system
644 lh__Writer::WriteFrame(const JP2K::FrameBuffer& FrameBuf, bool add_index,
645 AESEncContext* Ctx, HMACContext* HMAC)
647 Result_t result = RESULT_OK;
649 if ( m_State.Test_READY() )
650 result = m_State.Goto_RUNNING(); // first time through
652 ui64_t StreamOffset = m_StreamOffset;
654 if ( ASDCP_SUCCESS(result) )
655 result = WriteEKLVPacket(FrameBuf, m_EssenceUL, Ctx, HMAC);
657 if ( ASDCP_SUCCESS(result) && add_index )
659 IndexTableSegment::IndexEntry Entry;
660 Entry.StreamOffset = StreamOffset;
661 m_FooterPart.PushIndexEntry(Entry);
669 // Closes the MXF file, writing the index and other closing information.
672 lh__Writer::Finalize()
674 if ( ! m_State.Test_RUNNING() )
677 m_State.Goto_FINAL();
679 return WriteMXFFooter();
684 class ASDCP::JP2K::MXFWriter::h__Writer : public lh__Writer
689 //------------------------------------------------------------------------------------------
693 ASDCP::JP2K::MXFWriter::MXFWriter()
697 ASDCP::JP2K::MXFWriter::~MXFWriter()
702 // Open the file for writing. The file must not exist. Returns error if
703 // the operation cannot be completed.
705 ASDCP::JP2K::MXFWriter::OpenWrite(const char* filename, const WriterInfo& Info,
706 const PictureDescriptor& PDesc, ui32_t HeaderSize)
708 m_Writer = new h__Writer;
710 Result_t result = m_Writer->OpenWrite(filename, ASDCP::ESS_JPEG_2000, HeaderSize);
712 if ( ASDCP_SUCCESS(result) )
714 m_Writer->m_Info = Info;
715 result = m_Writer->SetSourceStream(PDesc, JP2K_PACKAGE_LABEL);
718 if ( ASDCP_FAILURE(result) )
725 // Writes a frame of essence to the MXF file. If the optional AESEncContext
726 // argument is present, the essence is encrypted prior to writing.
727 // Fails if the file is not open, is finalized, or an operating system
730 ASDCP::JP2K::MXFWriter::WriteFrame(const FrameBuffer& FrameBuf, AESEncContext* Ctx, HMACContext* HMAC)
732 if ( m_Writer.empty() )
735 return m_Writer->WriteFrame(FrameBuf, true, Ctx, HMAC);
738 // Closes the MXF file, writing the index and other closing information.
740 ASDCP::JP2K::MXFWriter::Finalize()
742 if ( m_Writer.empty() )
745 return m_Writer->Finalize();
749 //------------------------------------------------------------------------------------------
753 class ASDCP::JP2K::MXFSWriter::h__SWriter : public lh__Writer
755 StereoscopicPhase_t m_NextPhase;
758 h__SWriter() : m_NextPhase(SP_LEFT) {}
761 Result_t WriteFrame(const FrameBuffer& FrameBuf, StereoscopicPhase_t phase,
762 AESEncContext* Ctx, HMACContext* HMAC)
764 if ( m_NextPhase != phase )
765 return RESULT_SPHASE;
767 if ( phase == SP_LEFT )
769 m_NextPhase = SP_RIGHT;
770 return lh__Writer::WriteFrame(FrameBuf, true, Ctx, HMAC);
773 m_NextPhase = SP_LEFT;
774 return lh__Writer::WriteFrame(FrameBuf, false, Ctx, HMAC);
780 if ( m_NextPhase != SP_LEFT )
781 return RESULT_SPHASE;
783 return lh__Writer::Finalize();
789 ASDCP::JP2K::MXFSWriter::MXFSWriter()
793 ASDCP::JP2K::MXFSWriter::~MXFSWriter()
798 // Open the file for writing. The file must not exist. Returns error if
799 // the operation cannot be completed.
801 ASDCP::JP2K::MXFSWriter::OpenWrite(const char* filename, const WriterInfo& Info,
802 const PictureDescriptor& PDesc, ui32_t HeaderSize)
804 m_Writer = new h__SWriter;
806 if ( PDesc.EditRate != ASDCP::EditRate_24 )
808 DefaultLogSink().Error("Stereoscopic wrapping requires 24 fps input streams.\n");
809 return RESULT_FORMAT;
812 Result_t result = m_Writer->OpenWrite(filename, ASDCP::ESS_JPEG_2000_S, HeaderSize);
814 if ( ASDCP_SUCCESS(result) )
816 m_Writer->m_Info = Info;
817 PictureDescriptor TmpPDesc = PDesc;
818 TmpPDesc.EditRate = ASDCP::EditRate_48;
820 result = m_Writer->SetSourceStream(TmpPDesc, JP2K_S_PACKAGE_LABEL, ASDCP::EditRate_24);
823 if ( ASDCP_FAILURE(result) )
830 // Writes a frame of essence to the MXF file. If the optional AESEncContext
831 // argument is present, the essence is encrypted prior to writing.
832 // Fails if the file is not open, is finalized, or an operating system
835 ASDCP::JP2K::MXFSWriter::WriteFrame(const FrameBuffer& FrameBuf, StereoscopicPhase_t phase,
836 AESEncContext* Ctx, HMACContext* HMAC)
838 if ( m_Writer.empty() )
841 return m_Writer->WriteFrame(FrameBuf, phase, Ctx, HMAC);
844 // Closes the MXF file, writing the index and other closing information.
846 ASDCP::JP2K::MXFSWriter::Finalize()
848 if ( m_Writer.empty() )
851 return m_Writer->Finalize();
855 // end AS_DCP_JP2K.cpp