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";
46 // 7f18 7f00 7f00 7ebc 76ea 76ea 76bc 6f4c 6f4c 6f64 5803 5803 5845 5fd2 5fd2 5f61
49 int s_exp_lookup[16] = { 0, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024,2048, 4096, 8192, 16384, 32768 };
53 ASDCP::JP2K::PictureDescriptorDump(const PictureDescriptor& PDesc, FILE* stream)
72 ContainerDuration: %u\n",
73 PDesc.AspectRatio.Numerator, PDesc.AspectRatio.Denominator,
74 PDesc.EditRate.Numerator, PDesc.EditRate.Denominator,
86 PDesc.ContainerDuration
89 fprintf(stream, "-- JPEG 2000 Metadata --\n");
90 fprintf(stream, " ImageComponents:\n");
91 fprintf(stream, " bits h-sep v-sep\n");
93 for ( ui32_t i = 0; i < PDesc.Csize; i++ )
95 fprintf(stream, " %4d %5d %5d\n",
96 PDesc.ImageComponents[i].Ssize + 1, // See ISO 15444-1, Table A11, for the origin of '+1'
97 PDesc.ImageComponents[i].XRsize,
98 PDesc.ImageComponents[i].YRsize
102 fprintf(stream, " Scod: %hd\n", PDesc.CodingStyleDefault.Scod);
103 fprintf(stream, " ProgressionOrder: %hd\n", PDesc.CodingStyleDefault.SGcod.ProgressionOrder);
104 fprintf(stream, " NumberOfLayers: %hd\n",
105 KM_i16_BE(Kumu::cp2i<ui16_t>(PDesc.CodingStyleDefault.SGcod.NumberOfLayers)));
107 fprintf(stream, " MultiCompTransform: %hd\n", PDesc.CodingStyleDefault.SGcod.MultiCompTransform);
108 fprintf(stream, "DecompositionLevels: %hd\n", PDesc.CodingStyleDefault.SPcod.DecompositionLevels);
109 fprintf(stream, " CodeblockWidth: %hd\n", PDesc.CodingStyleDefault.SPcod.CodeblockWidth);
110 fprintf(stream, " CodeblockHeight: %hd\n", PDesc.CodingStyleDefault.SPcod.CodeblockHeight);
111 fprintf(stream, " CodeblockStyle: %hd\n", PDesc.CodingStyleDefault.SPcod.CodeblockStyle);
112 fprintf(stream, " Transformation: %hd\n", PDesc.CodingStyleDefault.SPcod.Transformation);
115 ui32_t precinct_set_size = 0, i;
117 for ( i = 0; PDesc.CodingStyleDefault.SPcod.PrecinctSize[i] != 0 && i < MaxPrecincts; i++ )
120 fprintf(stream, " Precincts: %hd\n", precinct_set_size);
121 fprintf(stream, "precinct dimensions:\n");
123 for ( i = 0; i < precinct_set_size; i++ )
124 fprintf(stream, " %d: %d x %d\n", i + 1,
125 s_exp_lookup[PDesc.CodingStyleDefault.SPcod.PrecinctSize[i]&0x0f],
126 s_exp_lookup[(PDesc.CodingStyleDefault.SPcod.PrecinctSize[i]>>4)&0x0f]
129 fprintf(stream, " Sqcd: %hd\n", PDesc.QuantizationDefault.Sqcd);
131 char tmp_buf[MaxDefaults*2];
132 fprintf(stream, " SPqcd: %s\n",
133 Kumu::bin2hex(PDesc.QuantizationDefault.SPqcd, PDesc.QuantizationDefault.SPqcdLength,
134 tmp_buf, MaxDefaults*2)
138 //------------------------------------------------------------------------------------------
140 // hidden, internal implementation of JPEG 2000 reader
142 class lh__Reader : public ASDCP::h__Reader
144 RGBAEssenceDescriptor* m_EssenceDescriptor;
145 JPEG2000PictureSubDescriptor* m_EssenceSubDescriptor;
146 ASDCP::Rational m_EditRate;
147 EssenceType_t m_Format;
149 ASDCP_NO_COPY_CONSTRUCT(lh__Reader);
152 PictureDescriptor m_PDesc; // codestream parameter list
154 lh__Reader() : m_EssenceDescriptor(0), m_EssenceSubDescriptor(0), m_Format(ESS_UNKNOWN) {}
155 Result_t OpenRead(const char*, EssenceType_t);
156 Result_t ReadFrame(ui32_t, JP2K::FrameBuffer&, AESDecContext*, HMACContext*);
157 Result_t MD_to_JP2K_PDesc(JP2K::PictureDescriptor& PDesc);
162 lh__Reader::MD_to_JP2K_PDesc(JP2K::PictureDescriptor& PDesc)
164 memset(&PDesc, 0, sizeof(PDesc));
165 MXF::RGBAEssenceDescriptor* PDescObj = (MXF::RGBAEssenceDescriptor*)m_EssenceDescriptor;
167 PDesc.EditRate = m_EditRate;
168 PDesc.ContainerDuration = PDescObj->ContainerDuration;
169 PDesc.StoredWidth = PDescObj->StoredWidth;
170 PDesc.StoredHeight = PDescObj->StoredHeight;
171 PDesc.AspectRatio = PDescObj->AspectRatio;
173 if ( m_EssenceSubDescriptor != 0 )
175 PDesc.Rsize = m_EssenceSubDescriptor->Rsize;
176 PDesc.Xsize = m_EssenceSubDescriptor->Xsize;
177 PDesc.Ysize = m_EssenceSubDescriptor->Ysize;
178 PDesc.XOsize = m_EssenceSubDescriptor->XOsize;
179 PDesc.YOsize = m_EssenceSubDescriptor->YOsize;
180 PDesc.XTsize = m_EssenceSubDescriptor->XTsize;
181 PDesc.YTsize = m_EssenceSubDescriptor->YTsize;
182 PDesc.XTOsize = m_EssenceSubDescriptor->XTOsize;
183 PDesc.YTOsize = m_EssenceSubDescriptor->YTOsize;
184 PDesc.Csize = m_EssenceSubDescriptor->Csize;
186 // PictureComponentSizing
187 ui32_t tmp_size = m_EssenceSubDescriptor->PictureComponentSizing.Length();
189 if ( tmp_size == 17 ) // ( 2 * sizeof(ui32_t) ) + 3 components * 3 byte each
190 memcpy(&PDesc.ImageComponents, m_EssenceSubDescriptor->PictureComponentSizing.RoData() + 8, tmp_size - 8);
193 DefaultLogSink().Error("Unexpected PictureComponentSizing size: %u, should be 17\n", tmp_size);
195 // CodingStyleDefault
196 memset(&m_PDesc.CodingStyleDefault, 0, sizeof(CodingStyleDefault_t));
197 memcpy(&m_PDesc.CodingStyleDefault,
198 m_EssenceSubDescriptor->CodingStyleDefault.RoData(),
199 m_EssenceSubDescriptor->CodingStyleDefault.Length());
201 // QuantizationDefault
202 memset(&m_PDesc.QuantizationDefault, 0, sizeof(QuantizationDefault_t));
203 memcpy(&m_PDesc.QuantizationDefault,
204 m_EssenceSubDescriptor->QuantizationDefault.RoData(),
205 m_EssenceSubDescriptor->QuantizationDefault.Length());
207 m_PDesc.QuantizationDefault.SPqcdLength = m_EssenceSubDescriptor->QuantizationDefault.Length() - 1;
216 lh__Reader::OpenRead(const char* filename, EssenceType_t type)
218 Result_t result = OpenMXFRead(filename);
220 if( ASDCP_SUCCESS(result) )
222 m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(RGBAEssenceDescriptor),
223 (InterchangeObject**)&m_EssenceDescriptor);
224 m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(JPEG2000PictureSubDescriptor),
225 (InterchangeObject**)&m_EssenceSubDescriptor);
227 std::list<InterchangeObject*> ObjectList;
228 m_HeaderPart.GetMDObjectsByType(OBJ_TYPE_ARGS(Track), ObjectList);
230 if ( ObjectList.empty() )
232 DefaultLogSink().Error("MXF Metadata contains no Track Sets\n");
233 return RESULT_FORMAT;
236 m_EditRate = ((Track*)ObjectList.front())->EditRate;
238 if ( type == ASDCP::ESS_JPEG_2000 )
240 if ( m_EditRate != m_EssenceDescriptor->SampleRate )
242 DefaultLogSink().Error("EditRate and SampleRate do not match (%.03f, %.03f)\n",
243 m_EditRate.Quotient(), m_EssenceDescriptor->SampleRate.Quotient());
244 return RESULT_SFORMAT;
247 else if ( type == ASDCP::ESS_JPEG_2000_S )
249 if ( ! ( m_EditRate == EditRate_24 && m_EssenceDescriptor->SampleRate == EditRate_48 ) )
251 DefaultLogSink().Error("EditRate and SampleRate not correct for 24/48 stereoscopic essence\n");
252 return RESULT_FORMAT;
257 DefaultLogSink().Error("'type' argument unexpected: %x\n", type);
261 result = MD_to_JP2K_PDesc(m_PDesc);
264 if( ASDCP_SUCCESS(result) )
265 result = InitMXFIndex();
267 if( ASDCP_SUCCESS(result) )
276 lh__Reader::ReadFrame(ui32_t FrameNum, JP2K::FrameBuffer& FrameBuf,
277 AESDecContext* Ctx, HMACContext* HMAC)
279 if ( ! m_File.IsOpen() )
282 return ReadEKLVFrame(FrameNum, FrameBuf, Dict::ul(MDD_JPEG2000Essence), Ctx, HMAC);
287 class ASDCP::JP2K::MXFReader::h__Reader : public lh__Reader
293 //------------------------------------------------------------------------------------------
298 ASDCP::JP2K::FrameBuffer::Dump(FILE* stream, ui32_t dump_len) const
303 fprintf(stream, "Frame: %06u, %7u bytes", m_FrameNumber, m_Size);
308 Kumu::hexdump(m_Data, dump_len, stream);
312 //------------------------------------------------------------------------------------------
314 ASDCP::JP2K::MXFReader::MXFReader()
316 m_Reader = new h__Reader;
320 ASDCP::JP2K::MXFReader::~MXFReader()
324 // Open the file for reading. The file must exist. Returns error if the
325 // operation cannot be completed.
327 ASDCP::JP2K::MXFReader::OpenRead(const char* filename) const
329 return m_Reader->OpenRead(filename, ASDCP::ESS_JPEG_2000);
334 ASDCP::JP2K::MXFReader::ReadFrame(ui32_t FrameNum, FrameBuffer& FrameBuf,
335 AESDecContext* Ctx, HMACContext* HMAC) const
337 if ( m_Reader && m_Reader->m_File.IsOpen() )
338 return m_Reader->ReadFrame(FrameNum, FrameBuf, Ctx, HMAC);
344 // Fill the struct with the values from the file's header.
345 // Returns RESULT_INIT if the file is not open.
347 ASDCP::JP2K::MXFReader::FillPictureDescriptor(PictureDescriptor& PDesc) const
349 if ( m_Reader && m_Reader->m_File.IsOpen() )
351 PDesc = m_Reader->m_PDesc;
359 // Fill the struct with the values from the file's header.
360 // Returns RESULT_INIT if the file is not open.
362 ASDCP::JP2K::MXFReader::FillWriterInfo(WriterInfo& Info) const
364 if ( m_Reader && m_Reader->m_File.IsOpen() )
366 Info = m_Reader->m_Info;
375 ASDCP::JP2K::MXFReader::DumpHeaderMetadata(FILE* stream) const
377 if ( m_Reader->m_File.IsOpen() )
378 m_Reader->m_HeaderPart.Dump(stream);
384 ASDCP::JP2K::MXFReader::DumpIndex(FILE* stream) const
386 if ( m_Reader->m_File.IsOpen() )
387 m_Reader->m_FooterPart.Dump(stream);
391 //------------------------------------------------------------------------------------------
393 class ASDCP::JP2K::MXFSReader::h__SReader : public lh__Reader
395 StereoscopicPhase_t m_NextPhase;
398 h__SReader() : m_NextPhase(SP_LEFT) {}
401 Result_t ReadFrame(ui32_t FrameNum, StereoscopicPhase_t phase, FrameBuffer& FrameBuf,
402 AESDecContext* Ctx, HMACContext* HMAC) const
404 return Kumu::RESULT_NOTIMPL;
410 ASDCP::JP2K::MXFSReader::MXFSReader()
412 m_Reader = new h__SReader;
416 ASDCP::JP2K::MXFSReader::~MXFSReader()
420 // Open the file for reading. The file must exist. Returns error if the
421 // operation cannot be completed.
423 ASDCP::JP2K::MXFSReader::OpenRead(const char* filename) const
425 return m_Reader->OpenRead(filename, ASDCP::ESS_JPEG_2000_S);
430 ASDCP::JP2K::MXFSReader::ReadFrame(ui32_t FrameNum, StereoscopicPhase_t phase, FrameBuffer& FrameBuf,
431 AESDecContext* Ctx, HMACContext* HMAC) const
433 if ( m_Reader && m_Reader->m_File.IsOpen() )
434 return m_Reader->ReadFrame(FrameNum, phase, FrameBuf, Ctx, HMAC);
440 // Fill the struct with the values from the file's header.
441 // Returns RESULT_INIT if the file is not open.
443 ASDCP::JP2K::MXFSReader::FillPictureDescriptor(PictureDescriptor& PDesc) const
445 if ( m_Reader && m_Reader->m_File.IsOpen() )
447 PDesc = m_Reader->m_PDesc;
455 // Fill the struct with the values from the file's header.
456 // Returns RESULT_INIT if the file is not open.
458 ASDCP::JP2K::MXFSReader::FillWriterInfo(WriterInfo& Info) const
460 if ( m_Reader && m_Reader->m_File.IsOpen() )
462 Info = m_Reader->m_Info;
471 ASDCP::JP2K::MXFSReader::DumpHeaderMetadata(FILE* stream) const
473 if ( m_Reader->m_File.IsOpen() )
474 m_Reader->m_HeaderPart.Dump(stream);
480 ASDCP::JP2K::MXFSReader::DumpIndex(FILE* stream) const
482 if ( m_Reader->m_File.IsOpen() )
483 m_Reader->m_FooterPart.Dump(stream);
486 //------------------------------------------------------------------------------------------
490 class lh__Writer : public ASDCP::h__Writer
492 JPEG2000PictureSubDescriptor* m_EssenceSubDescriptor;
495 PictureDescriptor m_PDesc;
496 byte_t m_EssenceUL[SMPTE_UL_LENGTH];
498 ASDCP_NO_COPY_CONSTRUCT(lh__Writer);
500 lh__Writer() : m_EssenceSubDescriptor(0) {
501 memset(m_EssenceUL, 0, SMPTE_UL_LENGTH);
506 Result_t OpenWrite(const char*, ui32_t HeaderSize);
507 Result_t SetSourceStream(const PictureDescriptor&, const std::string& label,
508 ASDCP::Rational LocalEditRate = ASDCP::Rational(0,0));
509 Result_t WriteFrame(const JP2K::FrameBuffer&, bool add_index, AESEncContext*, HMACContext*);
511 Result_t JP2K_PDesc_to_MD(JP2K::PictureDescriptor& PDesc);
517 lh__Writer::JP2K_PDesc_to_MD(JP2K::PictureDescriptor& PDesc)
519 assert(m_EssenceDescriptor);
520 assert(m_EssenceSubDescriptor);
521 MXF::RGBAEssenceDescriptor* PDescObj = (MXF::RGBAEssenceDescriptor*)m_EssenceDescriptor;
523 PDescObj->SampleRate = PDesc.EditRate;
524 PDescObj->ContainerDuration = PDesc.ContainerDuration;
525 PDescObj->StoredWidth = PDesc.StoredWidth;
526 PDescObj->StoredHeight = PDesc.StoredHeight;
527 PDescObj->AspectRatio = PDesc.AspectRatio;
528 PDescObj->FrameLayout = 0;
530 if ( PDesc.StoredWidth < 2049 )
532 PDescObj->Codec.Set(Dict::ul(MDD_JP2KEssenceCompression_2K));
533 m_EssenceSubDescriptor->Rsize = 3;
537 PDescObj->Codec.Set(Dict::ul(MDD_JP2KEssenceCompression_4K));
538 m_EssenceSubDescriptor->Rsize = 4;
541 m_EssenceSubDescriptor->Xsize = PDesc.Xsize;
542 m_EssenceSubDescriptor->Ysize = PDesc.Ysize;
543 m_EssenceSubDescriptor->XOsize = PDesc.XOsize;
544 m_EssenceSubDescriptor->YOsize = PDesc.YOsize;
545 m_EssenceSubDescriptor->XTsize = PDesc.XTsize;
546 m_EssenceSubDescriptor->YTsize = PDesc.YTsize;
547 m_EssenceSubDescriptor->XTOsize = PDesc.XTOsize;
548 m_EssenceSubDescriptor->YTOsize = PDesc.YTOsize;
549 m_EssenceSubDescriptor->Csize = PDesc.Csize;
551 const ui32_t tmp_buffer_len = 1024;
552 byte_t tmp_buffer[tmp_buffer_len];
554 *(ui32_t*)tmp_buffer = KM_i32_BE(MaxComponents); // three components
555 *(ui32_t*)(tmp_buffer+4) = KM_i32_BE(sizeof(ASDCP::JP2K::ImageComponent_t));
556 memcpy(tmp_buffer + 8, &PDesc.ImageComponents, sizeof(ASDCP::JP2K::ImageComponent_t) * MaxComponents);
558 const ui32_t pcomp_size = (sizeof(int) * 2) + (sizeof(ASDCP::JP2K::ImageComponent_t) * MaxComponents);
559 memcpy(m_EssenceSubDescriptor->PictureComponentSizing.Data(), tmp_buffer, pcomp_size);
560 m_EssenceSubDescriptor->PictureComponentSizing.Length(pcomp_size);
562 ui32_t precinct_set_size = 0, i;
563 for ( i = 0; PDesc.CodingStyleDefault.SPcod.PrecinctSize[i] != 0 && i < MaxPrecincts; i++ )
566 ui32_t csd_size = sizeof(CodingStyleDefault_t) - MaxPrecincts + precinct_set_size;
567 memcpy(m_EssenceSubDescriptor->CodingStyleDefault.Data(), &PDesc.CodingStyleDefault, csd_size);
568 m_EssenceSubDescriptor->CodingStyleDefault.Length(csd_size);
570 ui32_t qdflt_size = PDesc.QuantizationDefault.SPqcdLength + 1;
571 memcpy(m_EssenceSubDescriptor->QuantizationDefault.Data(), &PDesc.QuantizationDefault, qdflt_size);
572 m_EssenceSubDescriptor->QuantizationDefault.Length(qdflt_size);
578 // Open the file for writing. The file must not exist. Returns error if
579 // the operation cannot be completed.
581 lh__Writer::OpenWrite(const char* filename, ui32_t HeaderSize)
583 if ( ! m_State.Test_BEGIN() )
586 Result_t result = m_File.OpenWrite(filename);
588 if ( ASDCP_SUCCESS(result) )
590 m_HeaderSize = HeaderSize;
591 RGBAEssenceDescriptor* tmp_rgba = new RGBAEssenceDescriptor;
592 tmp_rgba->ComponentMaxRef = 4095;
593 tmp_rgba->ComponentMinRef = 0;
595 m_EssenceDescriptor = tmp_rgba;
596 m_EssenceSubDescriptor = new JPEG2000PictureSubDescriptor;
597 m_EssenceSubDescriptorList.push_back((FileDescriptor*)m_EssenceSubDescriptor);
599 GenRandomValue(m_EssenceSubDescriptor->InstanceUID);
600 m_EssenceDescriptor->SubDescriptors.push_back(m_EssenceSubDescriptor->InstanceUID);
602 result = m_State.Goto_INIT();
608 // Automatically sets the MXF file's metadata from the first jpeg codestream stream.
610 lh__Writer::SetSourceStream(const PictureDescriptor& PDesc, const std::string& label, ASDCP::Rational LocalEditRate)
612 if ( ! m_State.Test_INIT() )
615 if ( LocalEditRate == ASDCP::Rational(0,0) )
616 LocalEditRate = PDesc.EditRate;
619 Result_t result = JP2K_PDesc_to_MD(m_PDesc);
621 if ( ASDCP_SUCCESS(result) )
622 result = WriteMXFHeader(label, UL(Dict::ul(MDD_JPEG_2000Wrapping)),
623 PICT_DEF_LABEL, UL(Dict::ul(MDD_PictureDataDef)),
624 LocalEditRate, 24 /* TCFrameRate */);
626 if ( ASDCP_SUCCESS(result) )
628 memcpy(m_EssenceUL, Dict::ul(MDD_JPEG2000Essence), SMPTE_UL_LENGTH);
629 m_EssenceUL[SMPTE_UL_LENGTH-1] = 1; // first (and only) essence container
630 result = m_State.Goto_READY();
636 // Writes a frame of essence to the MXF file. If the optional AESEncContext
637 // argument is present, the essence is encrypted prior to writing.
638 // Fails if the file is not open, is finalized, or an operating system
642 lh__Writer::WriteFrame(const JP2K::FrameBuffer& FrameBuf, bool add_index,
643 AESEncContext* Ctx, HMACContext* HMAC)
645 Result_t result = RESULT_OK;
647 if ( m_State.Test_READY() )
648 result = m_State.Goto_RUNNING(); // first time through
650 ui64_t StreamOffset = m_StreamOffset;
652 if ( ASDCP_SUCCESS(result) )
653 result = WriteEKLVPacket(FrameBuf, m_EssenceUL, Ctx, HMAC);
655 if ( ASDCP_SUCCESS(result) && add_index )
657 IndexTableSegment::IndexEntry Entry;
658 Entry.StreamOffset = StreamOffset;
659 m_FooterPart.PushIndexEntry(Entry);
667 // Closes the MXF file, writing the index and other closing information.
670 lh__Writer::Finalize()
672 if ( ! m_State.Test_RUNNING() )
675 m_State.Goto_FINAL();
677 return WriteMXFFooter();
682 class ASDCP::JP2K::MXFWriter::h__Writer : public lh__Writer
687 //------------------------------------------------------------------------------------------
691 ASDCP::JP2K::MXFWriter::MXFWriter()
695 ASDCP::JP2K::MXFWriter::~MXFWriter()
700 // Open the file for writing. The file must not exist. Returns error if
701 // the operation cannot be completed.
703 ASDCP::JP2K::MXFWriter::OpenWrite(const char* filename, const WriterInfo& Info,
704 const PictureDescriptor& PDesc, ui32_t HeaderSize)
706 m_Writer = new h__Writer;
708 Result_t result = m_Writer->OpenWrite(filename, HeaderSize);
710 if ( ASDCP_SUCCESS(result) )
712 m_Writer->m_Info = Info;
713 result = m_Writer->SetSourceStream(PDesc, JP2K_PACKAGE_LABEL);
716 if ( ASDCP_FAILURE(result) )
723 // Writes a frame of essence to the MXF file. If the optional AESEncContext
724 // argument is present, the essence is encrypted prior to writing.
725 // Fails if the file is not open, is finalized, or an operating system
728 ASDCP::JP2K::MXFWriter::WriteFrame(const FrameBuffer& FrameBuf, AESEncContext* Ctx, HMACContext* HMAC)
730 if ( m_Writer.empty() )
733 return m_Writer->WriteFrame(FrameBuf, true, Ctx, HMAC);
736 // Closes the MXF file, writing the index and other closing information.
738 ASDCP::JP2K::MXFWriter::Finalize()
740 if ( m_Writer.empty() )
743 return m_Writer->Finalize();
747 //------------------------------------------------------------------------------------------
751 class ASDCP::JP2K::MXFSWriter::h__SWriter : public lh__Writer
753 StereoscopicPhase_t m_NextPhase;
756 h__SWriter() : m_NextPhase(SP_LEFT) {}
759 Result_t WriteFrame(const FrameBuffer& FrameBuf, StereoscopicPhase_t phase,
760 AESEncContext* Ctx, HMACContext* HMAC)
762 if ( m_NextPhase != phase )
763 return RESULT_SPHASE;
765 if ( phase == SP_LEFT )
767 m_NextPhase = SP_RIGHT;
768 return lh__Writer::WriteFrame(FrameBuf, true, Ctx, HMAC);
771 m_NextPhase = SP_LEFT;
772 return lh__Writer::WriteFrame(FrameBuf, false, Ctx, HMAC);
778 if ( m_NextPhase != SP_LEFT )
779 return RESULT_SPHASE;
781 return lh__Writer::Finalize();
787 ASDCP::JP2K::MXFSWriter::MXFSWriter()
791 ASDCP::JP2K::MXFSWriter::~MXFSWriter()
796 // Open the file for writing. The file must not exist. Returns error if
797 // the operation cannot be completed.
799 ASDCP::JP2K::MXFSWriter::OpenWrite(const char* filename, const WriterInfo& Info,
800 const PictureDescriptor& PDesc, ui32_t HeaderSize)
802 m_Writer = new h__SWriter;
804 if ( PDesc.EditRate != ASDCP::EditRate_24 )
806 DefaultLogSink().Error("Stereoscopic wrapping requires 24 fps input streams.\n");
807 return RESULT_FORMAT;
810 Result_t result = m_Writer->OpenWrite(filename, HeaderSize);
812 if ( ASDCP_SUCCESS(result) )
814 m_Writer->m_Info = Info;
815 PictureDescriptor TmpPDesc = PDesc;
816 TmpPDesc.EditRate = ASDCP::EditRate_48;
818 result = m_Writer->SetSourceStream(TmpPDesc, JP2K_S_PACKAGE_LABEL, ASDCP::EditRate_24);
821 if ( ASDCP_FAILURE(result) )
828 // Writes a frame of essence to the MXF file. If the optional AESEncContext
829 // argument is present, the essence is encrypted prior to writing.
830 // Fails if the file is not open, is finalized, or an operating system
833 ASDCP::JP2K::MXFSWriter::WriteFrame(const FrameBuffer& FrameBuf, StereoscopicPhase_t phase,
834 AESEncContext* Ctx, HMACContext* HMAC)
836 if ( m_Writer.empty() )
839 return m_Writer->WriteFrame(FrameBuf, phase, Ctx, HMAC);
842 // Closes the MXF file, writing the index and other closing information.
844 ASDCP::JP2K::MXFSWriter::Finalize()
846 if ( m_Writer.empty() )
849 return m_Writer->Finalize();
853 // end AS_DCP_JP2K.cpp