2 Copyright (c) 2004-2016, 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"
36 using namespace ASDCP::JP2K;
37 using Kumu::GenRandomValue;
39 //------------------------------------------------------------------------------------------
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";
45 static int s_exp_lookup[16] = { 0, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024,2048, 4096, 8192, 16384, 32768 };
49 ASDCP::JP2K::operator << (std::ostream& strm, const PictureDescriptor& PDesc)
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;
67 strm << "-- JPEG 2000 Metadata --" << std::endl;
68 strm << " ImageComponents:" << std::endl;
69 strm << " bits h-sep v-sep" << std::endl;
72 for ( i = 0; i < PDesc.Csize && i < MaxComponents; ++i )
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
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;
91 ui32_t precinct_set_size = 0;
93 for ( i = 0; PDesc.CodingStyleDefault.SPcod.PrecinctSize[i] != 0 && i < MaxPrecincts; ++i )
96 strm << " Precincts: " << (short) precinct_set_size << std::endl;
97 strm << "precinct dimensions:" << std::endl;
99 for ( i = 0; i < precinct_set_size && i < MaxPrecincts; ++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;
103 strm << " Sqcd: " << (short) PDesc.QuantizationDefault.Sqcd << std::endl;
105 char tmp_buf[MaxDefaults*2];
106 strm << " SPqcd: " << Kumu::bin2hex(PDesc.QuantizationDefault.SPqcd, PDesc.QuantizationDefault.SPqcdLength, tmp_buf, MaxDefaults*2)
114 ASDCP::JP2K::PictureDescriptorDump(const PictureDescriptor& PDesc, FILE* stream)
120 AspectRatio: %d/%d\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,
149 PDesc.ContainerDuration
152 fprintf(stream, "-- JPEG 2000 Metadata --\n");
153 fprintf(stream, " ImageComponents:\n");
154 fprintf(stream, " bits h-sep v-sep\n");
157 for ( i = 0; i < PDesc.Csize && i < MaxComponents; i++ )
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
166 fprintf(stream, " Scod: %hhu\n", PDesc.CodingStyleDefault.Scod);
167 fprintf(stream, " ProgressionOrder: %hhu\n", PDesc.CodingStyleDefault.SGcod.ProgressionOrder);
168 fprintf(stream, " NumberOfLayers: %hd\n",
169 KM_i16_BE(Kumu::cp2i<ui16_t>(PDesc.CodingStyleDefault.SGcod.NumberOfLayers)));
171 fprintf(stream, " MultiCompTransform: %hhu\n", PDesc.CodingStyleDefault.SGcod.MultiCompTransform);
172 fprintf(stream, "DecompositionLevels: %hhu\n", PDesc.CodingStyleDefault.SPcod.DecompositionLevels);
173 fprintf(stream, " CodeblockWidth: %hhu\n", PDesc.CodingStyleDefault.SPcod.CodeblockWidth);
174 fprintf(stream, " CodeblockHeight: %hhu\n", PDesc.CodingStyleDefault.SPcod.CodeblockHeight);
175 fprintf(stream, " CodeblockStyle: %hhu\n", PDesc.CodingStyleDefault.SPcod.CodeblockStyle);
176 fprintf(stream, " Transformation: %hhu\n", PDesc.CodingStyleDefault.SPcod.Transformation);
179 ui32_t precinct_set_size = 0;
181 for ( i = 0; PDesc.CodingStyleDefault.SPcod.PrecinctSize[i] != 0 && i < MaxPrecincts; ++i )
184 fprintf(stream, " Precincts: %u\n", precinct_set_size);
185 fprintf(stream, "precinct dimensions:\n");
187 for ( i = 0; i < precinct_set_size && i < MaxPrecincts; 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]
193 fprintf(stream, " Sqcd: %hhu\n", PDesc.QuantizationDefault.Sqcd);
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)
203 const int VideoLineMapSize = 16; // See SMPTE 377M D.2.1
204 const int PixelLayoutSize = 8*2; // See SMPTE 377M D.2.3
205 static const byte_t s_PixelLayoutXYZ[PixelLayoutSize] = { 0xd8, 0x0c, 0xd9, 0x0c, 0xda, 0x0c, 0x00 };
209 ASDCP::JP2K_PDesc_to_MD(const JP2K::PictureDescriptor& PDesc,
210 const ASDCP::Dictionary& dict,
211 ASDCP::MXF::GenericPictureEssenceDescriptor& EssenceDescriptor,
212 ASDCP::MXF::JPEG2000PictureSubDescriptor& EssenceSubDescriptor)
214 EssenceDescriptor.ContainerDuration = PDesc.ContainerDuration;
215 EssenceDescriptor.SampleRate = PDesc.EditRate;
216 EssenceDescriptor.FrameLayout = 0;
217 EssenceDescriptor.StoredWidth = PDesc.StoredWidth;
218 EssenceDescriptor.StoredHeight = PDesc.StoredHeight;
219 EssenceDescriptor.AspectRatio = PDesc.AspectRatio;
221 EssenceSubDescriptor.Rsize = PDesc.Rsize;
222 EssenceSubDescriptor.Xsize = PDesc.Xsize;
223 EssenceSubDescriptor.Ysize = PDesc.Ysize;
224 EssenceSubDescriptor.XOsize = PDesc.XOsize;
225 EssenceSubDescriptor.YOsize = PDesc.YOsize;
226 EssenceSubDescriptor.XTsize = PDesc.XTsize;
227 EssenceSubDescriptor.YTsize = PDesc.YTsize;
228 EssenceSubDescriptor.XTOsize = PDesc.XTOsize;
229 EssenceSubDescriptor.YTOsize = PDesc.YTOsize;
230 EssenceSubDescriptor.Csize = PDesc.Csize;
232 const ui32_t tmp_buffer_len = 1024;
233 byte_t tmp_buffer[tmp_buffer_len];
235 *(ui32_t*)tmp_buffer = KM_i32_BE(MaxComponents); // three components
236 *(ui32_t*)(tmp_buffer+4) = KM_i32_BE(sizeof(ASDCP::JP2K::ImageComponent_t));
237 memcpy(tmp_buffer + 8, &PDesc.ImageComponents, sizeof(ASDCP::JP2K::ImageComponent_t) * MaxComponents);
239 const ui32_t pcomp_size = (sizeof(ui32_t) * 2) + (sizeof(ASDCP::JP2K::ImageComponent_t) * MaxComponents);
240 memcpy(EssenceSubDescriptor.PictureComponentSizing.get().Data(), tmp_buffer, pcomp_size);
241 EssenceSubDescriptor.PictureComponentSizing.get().Length(pcomp_size);
242 EssenceSubDescriptor.PictureComponentSizing.set_has_value();
244 ui32_t precinct_set_size = 0;
245 for ( ui32_t i = 0; PDesc.CodingStyleDefault.SPcod.PrecinctSize[i] != 0 && i < MaxPrecincts; ++i )
248 ui32_t csd_size = sizeof(CodingStyleDefault_t) - MaxPrecincts + precinct_set_size;
249 memcpy(EssenceSubDescriptor.CodingStyleDefault.get().Data(), &PDesc.CodingStyleDefault, csd_size);
250 EssenceSubDescriptor.CodingStyleDefault.get().Length(csd_size);
251 EssenceSubDescriptor.CodingStyleDefault.set_has_value();
253 ui32_t qdflt_size = PDesc.QuantizationDefault.SPqcdLength + 1;
254 memcpy(EssenceSubDescriptor.QuantizationDefault.get().Data(), &PDesc.QuantizationDefault, qdflt_size);
255 EssenceSubDescriptor.QuantizationDefault.get().Length(qdflt_size);
256 EssenceSubDescriptor.QuantizationDefault.set_has_value();
264 ASDCP::MD_to_JP2K_PDesc(const ASDCP::MXF::GenericPictureEssenceDescriptor& EssenceDescriptor,
265 const ASDCP::MXF::JPEG2000PictureSubDescriptor& EssenceSubDescriptor,
266 const ASDCP::Rational& EditRate, const ASDCP::Rational& SampleRate,
267 ASDCP::JP2K::PictureDescriptor& PDesc)
269 memset(&PDesc, 0, sizeof(PDesc));
271 PDesc.EditRate = EditRate;
272 PDesc.SampleRate = SampleRate;
273 assert(EssenceDescriptor.ContainerDuration.const_get() <= 0xFFFFFFFFL);
274 PDesc.ContainerDuration = static_cast<ui32_t>(EssenceDescriptor.ContainerDuration.const_get());
275 PDesc.StoredWidth = EssenceDescriptor.StoredWidth;
276 PDesc.StoredHeight = EssenceDescriptor.StoredHeight;
277 PDesc.AspectRatio = EssenceDescriptor.AspectRatio;
279 PDesc.Rsize = EssenceSubDescriptor.Rsize;
280 PDesc.Xsize = EssenceSubDescriptor.Xsize;
281 PDesc.Ysize = EssenceSubDescriptor.Ysize;
282 PDesc.XOsize = EssenceSubDescriptor.XOsize;
283 PDesc.YOsize = EssenceSubDescriptor.YOsize;
284 PDesc.XTsize = EssenceSubDescriptor.XTsize;
285 PDesc.YTsize = EssenceSubDescriptor.YTsize;
286 PDesc.XTOsize = EssenceSubDescriptor.XTOsize;
287 PDesc.YTOsize = EssenceSubDescriptor.YTOsize;
288 PDesc.Csize = EssenceSubDescriptor.Csize;
290 // PictureComponentSizing
291 ui32_t tmp_size = EssenceSubDescriptor.PictureComponentSizing.const_get().Length();
293 if ( tmp_size == 17 ) // ( 2 * sizeof(ui32_t) ) + 3 components * 3 byte each
295 memcpy(&PDesc.ImageComponents, EssenceSubDescriptor.PictureComponentSizing.const_get().RoData() + 8, tmp_size - 8);
299 DefaultLogSink().Warn("Unexpected PictureComponentSizing size: %u, should be 17.\n", tmp_size);
302 // CodingStyleDefault
303 memset(&PDesc.CodingStyleDefault, 0, sizeof(CodingStyleDefault_t));
304 memcpy(&PDesc.CodingStyleDefault,
305 EssenceSubDescriptor.CodingStyleDefault.const_get().RoData(),
306 EssenceSubDescriptor.CodingStyleDefault.const_get().Length());
308 // QuantizationDefault
309 memset(&PDesc.QuantizationDefault, 0, sizeof(QuantizationDefault_t));
310 memcpy(&PDesc.QuantizationDefault,
311 EssenceSubDescriptor.QuantizationDefault.const_get().RoData(),
312 EssenceSubDescriptor.QuantizationDefault.const_get().Length());
314 PDesc.QuantizationDefault.SPqcdLength = EssenceSubDescriptor.QuantizationDefault.const_get().Length() - 1;
319 //------------------------------------------------------------------------------------------
321 // hidden, internal implementation of JPEG 2000 reader
324 class lh__Reader : public ASDCP::h__ASDCPReader
326 RGBAEssenceDescriptor* m_EssenceDescriptor;
327 JPEG2000PictureSubDescriptor* m_EssenceSubDescriptor;
328 ASDCP::Rational m_EditRate;
329 ASDCP::Rational m_SampleRate;
330 EssenceType_t m_Format;
332 ASDCP_NO_COPY_CONSTRUCT(lh__Reader);
335 PictureDescriptor m_PDesc; // codestream parameter list
337 lh__Reader(const Dictionary& d) :
338 ASDCP::h__ASDCPReader(d), m_EssenceDescriptor(0), m_EssenceSubDescriptor(0), m_Format(ESS_UNKNOWN) {}
340 virtual ~lh__Reader() {}
342 Result_t OpenRead(const std::string&, EssenceType_t);
343 Result_t ReadFrame(ui32_t, JP2K::FrameBuffer&, AESDecContext*, HMACContext*);
350 lh__Reader::OpenRead(const std::string& filename, EssenceType_t type)
352 Result_t result = OpenMXFRead(filename);
354 if( ASDCP_SUCCESS(result) )
356 InterchangeObject* tmp_iobj = 0;
357 m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(RGBAEssenceDescriptor), &tmp_iobj);
358 m_EssenceDescriptor = static_cast<RGBAEssenceDescriptor*>(tmp_iobj);
360 if ( m_EssenceDescriptor == 0 )
362 DefaultLogSink().Error("RGBAEssenceDescriptor object not found.\n");
363 return RESULT_FORMAT;
366 m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(JPEG2000PictureSubDescriptor), &tmp_iobj);
367 m_EssenceSubDescriptor = static_cast<JPEG2000PictureSubDescriptor*>(tmp_iobj);
369 if ( m_EssenceSubDescriptor == 0 )
371 m_EssenceDescriptor = 0;
372 DefaultLogSink().Error("JPEG2000PictureSubDescriptor object not found.\n");
373 return RESULT_FORMAT;
376 std::list<InterchangeObject*> ObjectList;
377 m_HeaderPart.GetMDObjectsByType(OBJ_TYPE_ARGS(Track), ObjectList);
379 if ( ObjectList.empty() )
381 DefaultLogSink().Error("MXF Metadata contains no Track Sets.\n");
382 return RESULT_FORMAT;
385 m_EditRate = ((Track*)ObjectList.front())->EditRate;
386 m_SampleRate = m_EssenceDescriptor->SampleRate;
388 if ( type == ASDCP::ESS_JPEG_2000 )
390 if ( m_EditRate != m_SampleRate )
392 DefaultLogSink().Warn("EditRate and SampleRate do not match (%.03f, %.03f).\n",
393 m_EditRate.Quotient(), m_SampleRate.Quotient());
395 if ( ( m_EditRate == EditRate_24 && m_SampleRate == EditRate_48 )
396 || ( m_EditRate == EditRate_25 && m_SampleRate == EditRate_50 )
397 || ( m_EditRate == EditRate_30 && m_SampleRate == EditRate_60 )
398 || ( m_EditRate == EditRate_48 && m_SampleRate == EditRate_96 )
399 || ( m_EditRate == EditRate_50 && m_SampleRate == EditRate_100 )
400 || ( m_EditRate == EditRate_60 && m_SampleRate == EditRate_120 )
401 || ( m_EditRate == EditRate_96 && m_SampleRate == EditRate_192 )
402 || ( m_EditRate == EditRate_100 && m_SampleRate == EditRate_200 )
403 || ( m_EditRate == EditRate_120 && m_SampleRate == EditRate_240 ) )
405 DefaultLogSink().Debug("File may contain JPEG Interop stereoscopic images.\n");
406 return RESULT_SFORMAT;
409 return RESULT_FORMAT;
412 else if ( type == ASDCP::ESS_JPEG_2000_S )
414 if ( m_EditRate == EditRate_24 )
416 if ( m_SampleRate != EditRate_48 )
418 DefaultLogSink().Error("EditRate and SampleRate not correct for 24/48 stereoscopic essence.\n");
419 return RESULT_FORMAT;
422 else if ( m_EditRate == EditRate_25 )
424 if ( m_SampleRate != EditRate_50 )
426 DefaultLogSink().Error("EditRate and SampleRate not correct for 25/50 stereoscopic essence.\n");
427 return RESULT_FORMAT;
430 else if ( m_EditRate == EditRate_30 )
432 if ( m_SampleRate != EditRate_60 )
434 DefaultLogSink().Error("EditRate and SampleRate not correct for 30/60 stereoscopic essence.\n");
435 return RESULT_FORMAT;
438 else if ( m_EditRate == EditRate_48 )
440 if ( m_SampleRate != EditRate_96 )
442 DefaultLogSink().Error("EditRate and SampleRate not correct for 48/96 stereoscopic essence.\n");
443 return RESULT_FORMAT;
446 else if ( m_EditRate == EditRate_50 )
448 if ( m_SampleRate != EditRate_100 )
450 DefaultLogSink().Error("EditRate and SampleRate not correct for 50/100 stereoscopic essence.\n");
451 return RESULT_FORMAT;
454 else if ( m_EditRate == EditRate_60 )
456 if ( m_SampleRate != EditRate_120 )
458 DefaultLogSink().Error("EditRate and SampleRate not correct for 60/120 stereoscopic essence.\n");
459 return RESULT_FORMAT;
462 else if ( m_EditRate == EditRate_96 )
464 if ( m_SampleRate != EditRate_192 )
466 DefaultLogSink().Error("EditRate and SampleRate not correct for 96/192 stereoscopic essence.\n");
467 return RESULT_FORMAT;
470 else if ( m_EditRate == EditRate_100 )
472 if ( m_SampleRate != EditRate_200 )
474 DefaultLogSink().Error("EditRate and SampleRate not correct for 100/200 stereoscopic essence.\n");
475 return RESULT_FORMAT;
478 else if ( m_EditRate == EditRate_120 )
480 if ( m_SampleRate != EditRate_240 )
482 DefaultLogSink().Error("EditRate and SampleRate not correct for 120/240 stereoscopic essence.\n");
483 return RESULT_FORMAT;
488 DefaultLogSink().Error("EditRate not correct for stereoscopic essence: %d/%d.\n",
489 m_EditRate.Numerator, m_EditRate.Denominator);
490 return RESULT_FORMAT;
495 DefaultLogSink().Error("'type' argument unexpected: %x\n", type);
499 result = MD_to_JP2K_PDesc(*m_EssenceDescriptor, *m_EssenceSubDescriptor, m_EditRate, m_SampleRate, m_PDesc);
508 lh__Reader::ReadFrame(ui32_t FrameNum, JP2K::FrameBuffer& FrameBuf,
509 AESDecContext* Ctx, HMACContext* HMAC)
511 if ( ! m_File.IsOpen() )
515 return ReadEKLVFrame(FrameNum, FrameBuf, m_Dict->ul(MDD_JPEG2000Essence), Ctx, HMAC);
520 class ASDCP::JP2K::MXFReader::h__Reader : public lh__Reader
522 ASDCP_NO_COPY_CONSTRUCT(h__Reader);
526 h__Reader(const Dictionary& d) : lh__Reader(d) {}
531 //------------------------------------------------------------------------------------------
536 ASDCP::JP2K::FrameBuffer::Dump(FILE* stream, ui32_t dump_len) const
541 fprintf(stream, "Frame: %06u, %7u bytes", m_FrameNumber, m_Size);
546 Kumu::hexdump(m_Data, dump_len, stream);
550 //------------------------------------------------------------------------------------------
552 ASDCP::JP2K::MXFReader::MXFReader()
554 m_Reader = new h__Reader(DefaultCompositeDict());
558 ASDCP::JP2K::MXFReader::~MXFReader()
560 if ( m_Reader && m_Reader->m_File.IsOpen() )
564 // Warning: direct manipulation of MXF structures can interfere
565 // with the normal operation of the wrapper. Caveat emptor!
567 ASDCP::MXF::OP1aHeader&
568 ASDCP::JP2K::MXFReader::OP1aHeader()
570 if ( m_Reader.empty() )
572 assert(g_OP1aHeader);
573 return *g_OP1aHeader;
576 return m_Reader->m_HeaderPart;
579 // Warning: direct manipulation of MXF structures can interfere
580 // with the normal operation of the wrapper. Caveat emptor!
582 ASDCP::MXF::OPAtomIndexFooter&
583 ASDCP::JP2K::MXFReader::OPAtomIndexFooter()
585 if ( m_Reader.empty() )
587 assert(g_OPAtomIndexFooter);
588 return *g_OPAtomIndexFooter;
591 return m_Reader->m_IndexAccess;
594 // Warning: direct manipulation of MXF structures can interfere
595 // with the normal operation of the wrapper. Caveat emptor!
598 ASDCP::JP2K::MXFReader::RIP()
600 if ( m_Reader.empty() )
606 return m_Reader->m_RIP;
609 // Open the file for reading. The file must exist. Returns error if the
610 // operation cannot be completed.
612 ASDCP::JP2K::MXFReader::OpenRead(const std::string& filename) const
614 return m_Reader->OpenRead(filename, ASDCP::ESS_JPEG_2000);
619 ASDCP::JP2K::MXFReader::ReadFrame(ui32_t FrameNum, FrameBuffer& FrameBuf,
620 AESDecContext* Ctx, HMACContext* HMAC) const
622 if ( m_Reader && m_Reader->m_File.IsOpen() )
623 return m_Reader->ReadFrame(FrameNum, FrameBuf, Ctx, HMAC);
629 ASDCP::JP2K::MXFReader::LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const
631 return m_Reader->LocateFrame(FrameNum, streamOffset, temporalOffset, keyFrameOffset);
635 // Fill the struct with the values from the file's header.
636 // Returns RESULT_INIT if the file is not open.
638 ASDCP::JP2K::MXFReader::FillPictureDescriptor(PictureDescriptor& PDesc) const
640 if ( m_Reader && m_Reader->m_File.IsOpen() )
642 PDesc = m_Reader->m_PDesc;
650 // Fill the struct with the values from the file's header.
651 // Returns RESULT_INIT if the file is not open.
653 ASDCP::JP2K::MXFReader::FillWriterInfo(WriterInfo& Info) const
655 if ( m_Reader && m_Reader->m_File.IsOpen() )
657 Info = m_Reader->m_Info;
666 ASDCP::JP2K::MXFReader::DumpHeaderMetadata(FILE* stream) const
668 if ( m_Reader->m_File.IsOpen() )
669 m_Reader->m_HeaderPart.Dump(stream);
675 ASDCP::JP2K::MXFReader::DumpIndex(FILE* stream) const
677 if ( m_Reader->m_File.IsOpen() )
678 m_Reader->m_IndexAccess.Dump(stream);
683 ASDCP::JP2K::MXFReader::Close() const
685 if ( m_Reader && m_Reader->m_File.IsOpen() )
695 //------------------------------------------------------------------------------------------
698 class ASDCP::JP2K::MXFSReader::h__SReader : public lh__Reader
700 ui32_t m_StereoFrameReady;
703 h__SReader(const Dictionary& d) : lh__Reader(d), m_StereoFrameReady(0xffffffff) {}
706 Result_t ReadFrame(ui32_t FrameNum, StereoscopicPhase_t phase, FrameBuffer& FrameBuf,
707 AESDecContext* Ctx, HMACContext* HMAC)
709 // look up frame index node
710 IndexTableSegment::IndexEntry TmpEntry;
712 if ( ASDCP_FAILURE(m_IndexAccess.Lookup(FrameNum, TmpEntry)) )
717 // get frame position
718 Kumu::fpos_t FilePosition = m_HeaderPart.BodyOffset + TmpEntry.StreamOffset;
719 Result_t result = RESULT_OK;
721 if ( phase == SP_LEFT )
723 if ( FilePosition != m_LastPosition )
725 m_LastPosition = FilePosition;
726 result = m_File.Seek(FilePosition);
729 // the call to ReadEKLVPacket() will leave the file on an R frame
730 m_StereoFrameReady = FrameNum;
732 else if ( phase == SP_RIGHT )
734 if ( m_StereoFrameReady != FrameNum )
736 // the file is not already positioned, we must do some work
737 // seek to the companion SP_LEFT frame and read the frame's key and length
738 if ( FilePosition != m_LastPosition )
740 m_LastPosition = FilePosition;
741 result = m_File.Seek(FilePosition);
745 result = Reader.ReadKLFromFile(m_File);
747 if ( ASDCP_SUCCESS(result) )
749 // skip over the companion SP_LEFT frame
750 Kumu::fpos_t new_pos = FilePosition + SMPTE_UL_LENGTH + Reader.KLLength() + Reader.Length();
751 result = m_File.Seek(new_pos);
755 // the call to ReadEKLVPacket() will leave the file not on an R frame
756 m_StereoFrameReady = 0xffffffff;
760 DefaultLogSink().Error("Unexpected stereoscopic phase value: %u\n", phase);
764 if( ASDCP_SUCCESS(result) )
766 ui32_t SequenceNum = FrameNum * 2;
767 SequenceNum += ( phase == SP_RIGHT ) ? 2 : 1;
769 result = ReadEKLVPacket(FrameNum, SequenceNum, FrameBuf, m_Dict->ul(MDD_JPEG2000Essence), Ctx, HMAC);
778 ASDCP::JP2K::MXFSReader::MXFSReader()
780 m_Reader = new h__SReader(DefaultCompositeDict());
784 ASDCP::JP2K::MXFSReader::~MXFSReader()
786 if ( m_Reader && m_Reader->m_File.IsOpen() )
790 // Warning: direct manipulation of MXF structures can interfere
791 // with the normal operation of the wrapper. Caveat emptor!
793 ASDCP::MXF::OP1aHeader&
794 ASDCP::JP2K::MXFSReader::OP1aHeader()
796 if ( m_Reader.empty() )
798 assert(g_OP1aHeader);
799 return *g_OP1aHeader;
802 return m_Reader->m_HeaderPart;
805 // Warning: direct manipulation of MXF structures can interfere
806 // with the normal operation of the wrapper. Caveat emptor!
808 ASDCP::MXF::OPAtomIndexFooter&
809 ASDCP::JP2K::MXFSReader::OPAtomIndexFooter()
811 if ( m_Reader.empty() )
813 assert(g_OPAtomIndexFooter);
814 return *g_OPAtomIndexFooter;
817 return m_Reader->m_IndexAccess;
820 // Warning: direct manipulation of MXF structures can interfere
821 // with the normal operation of the wrapper. Caveat emptor!
824 ASDCP::JP2K::MXFSReader::RIP()
826 if ( m_Reader.empty() )
832 return m_Reader->m_RIP;
835 // Open the file for reading. The file must exist. Returns error if the
836 // operation cannot be completed.
838 ASDCP::JP2K::MXFSReader::OpenRead(const std::string& filename) const
840 return m_Reader->OpenRead(filename, ASDCP::ESS_JPEG_2000_S);
845 ASDCP::JP2K::MXFSReader::ReadFrame(ui32_t FrameNum, SFrameBuffer& FrameBuf, AESDecContext* Ctx, HMACContext* HMAC) const
847 Result_t result = RESULT_INIT;
849 if ( m_Reader && m_Reader->m_File.IsOpen() )
851 result = m_Reader->ReadFrame(FrameNum, SP_LEFT, FrameBuf.Left, Ctx, HMAC);
853 if ( ASDCP_SUCCESS(result) )
854 result = m_Reader->ReadFrame(FrameNum, SP_RIGHT, FrameBuf.Right, Ctx, HMAC);
862 ASDCP::JP2K::MXFSReader::ReadFrame(ui32_t FrameNum, StereoscopicPhase_t phase, FrameBuffer& FrameBuf,
863 AESDecContext* Ctx, HMACContext* HMAC) const
865 if ( m_Reader && m_Reader->m_File.IsOpen() )
866 return m_Reader->ReadFrame(FrameNum, phase, FrameBuf, Ctx, HMAC);
872 ASDCP::JP2K::MXFSReader::LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const
874 return m_Reader->LocateFrame(FrameNum, streamOffset, temporalOffset, keyFrameOffset);
877 // Fill the struct with the values from the file's header.
878 // Returns RESULT_INIT if the file is not open.
880 ASDCP::JP2K::MXFSReader::FillPictureDescriptor(PictureDescriptor& PDesc) const
882 if ( m_Reader && m_Reader->m_File.IsOpen() )
884 PDesc = m_Reader->m_PDesc;
892 // Fill the struct with the values from the file's header.
893 // Returns RESULT_INIT if the file is not open.
895 ASDCP::JP2K::MXFSReader::FillWriterInfo(WriterInfo& Info) const
897 if ( m_Reader && m_Reader->m_File.IsOpen() )
899 Info = m_Reader->m_Info;
908 ASDCP::JP2K::MXFSReader::DumpHeaderMetadata(FILE* stream) const
910 if ( m_Reader->m_File.IsOpen() )
911 m_Reader->m_HeaderPart.Dump(stream);
917 ASDCP::JP2K::MXFSReader::DumpIndex(FILE* stream) const
919 if ( m_Reader->m_File.IsOpen() )
920 m_Reader->m_IndexAccess.Dump(stream);
925 ASDCP::JP2K::MXFSReader::Close() const
927 if ( m_Reader && m_Reader->m_File.IsOpen() )
937 //------------------------------------------------------------------------------------------
941 class lh__Writer : public ASDCP::h__ASDCPWriter
943 ASDCP_NO_COPY_CONSTRUCT(lh__Writer);
946 JPEG2000PictureSubDescriptor* m_EssenceSubDescriptor;
949 PictureDescriptor m_PDesc;
950 byte_t m_EssenceUL[SMPTE_UL_LENGTH];
952 lh__Writer(const Dictionary& d) : ASDCP::h__ASDCPWriter(d), m_EssenceSubDescriptor(0) {
953 memset(m_EssenceUL, 0, SMPTE_UL_LENGTH);
956 virtual ~lh__Writer(){}
958 Result_t OpenWrite(const std::string&, EssenceType_t type, ui32_t HeaderSize);
959 Result_t SetSourceStream(const PictureDescriptor&, const std::string& label,
960 ASDCP::Rational LocalEditRate = ASDCP::Rational(0,0));
961 Result_t WriteFrame(const JP2K::FrameBuffer&, bool add_index, AESEncContext*, HMACContext*);
965 // Open the file for writing. The file must not exist. Returns error if
966 // the operation cannot be completed.
968 lh__Writer::OpenWrite(const std::string& filename, EssenceType_t type, ui32_t HeaderSize)
970 if ( ! m_State.Test_BEGIN() )
973 Result_t result = m_File.OpenWrite(filename);
975 if ( ASDCP_SUCCESS(result) )
977 m_HeaderSize = HeaderSize;
978 RGBAEssenceDescriptor* tmp_rgba = new RGBAEssenceDescriptor(m_Dict);
979 tmp_rgba->ComponentMaxRef = 4095;
980 tmp_rgba->ComponentMinRef = 0;
982 m_EssenceDescriptor = tmp_rgba;
983 m_EssenceSubDescriptor = new JPEG2000PictureSubDescriptor(m_Dict);
984 m_EssenceSubDescriptorList.push_back((InterchangeObject*)m_EssenceSubDescriptor);
986 GenRandomValue(m_EssenceSubDescriptor->InstanceUID);
987 m_EssenceDescriptor->SubDescriptors.push_back(m_EssenceSubDescriptor->InstanceUID);
989 if ( type == ASDCP::ESS_JPEG_2000_S && m_Info.LabelSetType == LS_MXF_SMPTE )
991 InterchangeObject* StereoSubDesc = new StereoscopicPictureSubDescriptor(m_Dict);
992 m_EssenceSubDescriptorList.push_back(StereoSubDesc);
993 GenRandomValue(StereoSubDesc->InstanceUID);
994 m_EssenceDescriptor->SubDescriptors.push_back(StereoSubDesc->InstanceUID);
997 result = m_State.Goto_INIT();
1003 // Automatically sets the MXF file's metadata from the first jpeg codestream stream.
1005 lh__Writer::SetSourceStream(const PictureDescriptor& PDesc, const std::string& label, ASDCP::Rational LocalEditRate)
1008 if ( ! m_State.Test_INIT() )
1009 return RESULT_STATE;
1011 if ( LocalEditRate == ASDCP::Rational(0,0) )
1012 LocalEditRate = PDesc.EditRate;
1016 assert(m_EssenceDescriptor);
1017 assert(m_EssenceSubDescriptor);
1018 Result_t result = JP2K_PDesc_to_MD(m_PDesc, *m_Dict,
1019 *static_cast<ASDCP::MXF::GenericPictureEssenceDescriptor*>(m_EssenceDescriptor),
1020 *m_EssenceSubDescriptor);
1022 if ( ASDCP_SUCCESS(result) )
1024 if ( PDesc.StoredWidth < 2049 )
1026 static_cast<ASDCP::MXF::RGBAEssenceDescriptor*>(m_EssenceDescriptor)->PictureEssenceCoding.Set(m_Dict->ul(MDD_JP2KEssenceCompression_2K));
1027 m_EssenceSubDescriptor->Rsize = 3;
1031 static_cast<ASDCP::MXF::RGBAEssenceDescriptor*>(m_EssenceDescriptor)->PictureEssenceCoding.Set(m_Dict->ul(MDD_JP2KEssenceCompression_4K));
1032 m_EssenceSubDescriptor->Rsize = 4;
1035 memcpy(m_EssenceUL, m_Dict->ul(MDD_JPEG2000Essence), SMPTE_UL_LENGTH);
1036 m_EssenceUL[SMPTE_UL_LENGTH-1] = 1; // first (and only) essence container
1037 result = m_State.Goto_READY();
1040 if ( ASDCP_SUCCESS(result) )
1042 result = WriteASDCPHeader(label, UL(m_Dict->ul(MDD_MXFGCFUFrameWrappedPictureElement)),
1043 PICT_DEF_LABEL, UL(m_EssenceUL), UL(m_Dict->ul(MDD_PictureDataDef)),
1044 LocalEditRate, derive_timecode_rate_from_edit_rate(m_PDesc.EditRate));
1050 // Writes a frame of essence to the MXF file. If the optional AESEncContext
1051 // argument is present, the essence is encrypted prior to writing.
1052 // Fails if the file is not open, is finalized, or an operating system
1056 lh__Writer::WriteFrame(const JP2K::FrameBuffer& FrameBuf, bool add_index,
1057 AESEncContext* Ctx, HMACContext* HMAC)
1059 Result_t result = RESULT_OK;
1061 if ( m_State.Test_READY() )
1062 result = m_State.Goto_RUNNING(); // first time through
1064 ui64_t StreamOffset = m_StreamOffset;
1066 if ( ASDCP_SUCCESS(result) )
1067 result = WriteEKLVPacket(FrameBuf, m_EssenceUL, Ctx, HMAC);
1069 if ( ASDCP_SUCCESS(result) && add_index )
1071 IndexTableSegment::IndexEntry Entry;
1072 Entry.StreamOffset = StreamOffset;
1073 m_FooterPart.PushIndexEntry(Entry);
1081 // Closes the MXF file, writing the index and other closing information.
1084 lh__Writer::Finalize()
1086 if ( ! m_State.Test_RUNNING() )
1087 return RESULT_STATE;
1089 m_State.Goto_FINAL();
1091 return WriteASDCPFooter();
1096 class ASDCP::JP2K::MXFWriter::h__Writer : public lh__Writer
1098 ASDCP_NO_COPY_CONSTRUCT(h__Writer);
1102 h__Writer(const Dictionary& d) : lh__Writer(d) {}
1106 //------------------------------------------------------------------------------------------
1110 ASDCP::JP2K::MXFWriter::MXFWriter()
1114 ASDCP::JP2K::MXFWriter::~MXFWriter()
1118 // Warning: direct manipulation of MXF structures can interfere
1119 // with the normal operation of the wrapper. Caveat emptor!
1121 ASDCP::MXF::OP1aHeader&
1122 ASDCP::JP2K::MXFWriter::OP1aHeader()
1124 if ( m_Writer.empty() )
1126 assert(g_OP1aHeader);
1127 return *g_OP1aHeader;
1130 return m_Writer->m_HeaderPart;
1133 // Warning: direct manipulation of MXF structures can interfere
1134 // with the normal operation of the wrapper. Caveat emptor!
1136 ASDCP::MXF::OPAtomIndexFooter&
1137 ASDCP::JP2K::MXFWriter::OPAtomIndexFooter()
1139 if ( m_Writer.empty() )
1141 assert(g_OPAtomIndexFooter);
1142 return *g_OPAtomIndexFooter;
1145 return m_Writer->m_FooterPart;
1148 // Warning: direct manipulation of MXF structures can interfere
1149 // with the normal operation of the wrapper. Caveat emptor!
1152 ASDCP::JP2K::MXFWriter::RIP()
1154 if ( m_Writer.empty() )
1160 return m_Writer->m_RIP;
1163 // Open the file for writing. The file must not exist. Returns error if
1164 // the operation cannot be completed.
1166 ASDCP::JP2K::MXFWriter::OpenWrite(const std::string& filename, const WriterInfo& Info,
1167 const PictureDescriptor& PDesc, ui32_t HeaderSize)
1169 if ( Info.LabelSetType == LS_MXF_SMPTE )
1170 m_Writer = new h__Writer(DefaultSMPTEDict());
1172 m_Writer = new h__Writer(DefaultInteropDict());
1174 m_Writer->m_Info = Info;
1176 Result_t result = m_Writer->OpenWrite(filename, ASDCP::ESS_JPEG_2000, HeaderSize);
1178 if ( ASDCP_SUCCESS(result) )
1179 result = m_Writer->SetSourceStream(PDesc, JP2K_PACKAGE_LABEL);
1181 if ( ASDCP_FAILURE(result) )
1188 // Writes a frame of essence to the MXF file. If the optional AESEncContext
1189 // argument is present, the essence is encrypted prior to writing.
1190 // Fails if the file is not open, is finalized, or an operating system
1193 ASDCP::JP2K::MXFWriter::WriteFrame(const FrameBuffer& FrameBuf, AESEncContext* Ctx, HMACContext* HMAC)
1195 if ( m_Writer.empty() )
1198 return m_Writer->WriteFrame(FrameBuf, true, Ctx, HMAC);
1201 // Closes the MXF file, writing the index and other closing information.
1203 ASDCP::JP2K::MXFWriter::Finalize()
1205 if ( m_Writer.empty() )
1208 return m_Writer->Finalize();
1212 //------------------------------------------------------------------------------------------
1216 class ASDCP::JP2K::MXFSWriter::h__SWriter : public lh__Writer
1218 ASDCP_NO_COPY_CONSTRUCT(h__SWriter);
1220 StereoscopicPhase_t m_NextPhase;
1223 h__SWriter(const Dictionary& d) : lh__Writer(d), m_NextPhase(SP_LEFT) {}
1226 Result_t WriteFrame(const FrameBuffer& FrameBuf, StereoscopicPhase_t phase,
1227 AESEncContext* Ctx, HMACContext* HMAC)
1229 if ( m_NextPhase != phase )
1230 return RESULT_SPHASE;
1232 if ( phase == SP_LEFT )
1234 m_NextPhase = SP_RIGHT;
1235 return lh__Writer::WriteFrame(FrameBuf, true, Ctx, HMAC);
1238 m_NextPhase = SP_LEFT;
1239 return lh__Writer::WriteFrame(FrameBuf, false, Ctx, HMAC);
1245 if ( m_NextPhase != SP_LEFT )
1246 return RESULT_SPHASE;
1248 assert( m_FramesWritten % 2 == 0 );
1249 m_FramesWritten /= 2;
1250 return lh__Writer::Finalize();
1256 ASDCP::JP2K::MXFSWriter::MXFSWriter()
1260 ASDCP::JP2K::MXFSWriter::~MXFSWriter()
1264 // Warning: direct manipulation of MXF structures can interfere
1265 // with the normal operation of the wrapper. Caveat emptor!
1267 ASDCP::MXF::OP1aHeader&
1268 ASDCP::JP2K::MXFSWriter::OP1aHeader()
1270 if ( m_Writer.empty() )
1272 assert(g_OP1aHeader);
1273 return *g_OP1aHeader;
1276 return m_Writer->m_HeaderPart;
1279 // Warning: direct manipulation of MXF structures can interfere
1280 // with the normal operation of the wrapper. Caveat emptor!
1282 ASDCP::MXF::OPAtomIndexFooter&
1283 ASDCP::JP2K::MXFSWriter::OPAtomIndexFooter()
1285 if ( m_Writer.empty() )
1287 assert(g_OPAtomIndexFooter);
1288 return *g_OPAtomIndexFooter;
1291 return m_Writer->m_FooterPart;
1294 // Warning: direct manipulation of MXF structures can interfere
1295 // with the normal operation of the wrapper. Caveat emptor!
1298 ASDCP::JP2K::MXFSWriter::RIP()
1300 if ( m_Writer.empty() )
1306 return m_Writer->m_RIP;
1309 // Open the file for writing. The file must not exist. Returns error if
1310 // the operation cannot be completed.
1312 ASDCP::JP2K::MXFSWriter::OpenWrite(const std::string& filename, const WriterInfo& Info,
1313 const PictureDescriptor& PDesc, ui32_t HeaderSize)
1315 if ( Info.LabelSetType == LS_MXF_SMPTE )
1316 m_Writer = new h__SWriter(DefaultSMPTEDict());
1318 m_Writer = new h__SWriter(DefaultInteropDict());
1320 if ( PDesc.EditRate != ASDCP::EditRate_24
1321 && PDesc.EditRate != ASDCP::EditRate_25
1322 && PDesc.EditRate != ASDCP::EditRate_30
1323 && PDesc.EditRate != ASDCP::EditRate_48
1324 && PDesc.EditRate != ASDCP::EditRate_50
1325 && PDesc.EditRate != ASDCP::EditRate_60 )
1327 DefaultLogSink().Error("Stereoscopic wrapping requires 24, 25, 30, 48, 50 or 60 fps input streams.\n");
1328 return RESULT_FORMAT;
1331 if ( PDesc.StoredWidth > 2048 )
1332 DefaultLogSink().Warn("Wrapping non-standard 4K stereoscopic content. I hope you know what you are doing!\n");
1334 m_Writer->m_Info = Info;
1336 Result_t result = m_Writer->OpenWrite(filename, ASDCP::ESS_JPEG_2000_S, HeaderSize);
1338 if ( ASDCP_SUCCESS(result) )
1340 PictureDescriptor TmpPDesc = PDesc;
1342 if ( PDesc.EditRate == ASDCP::EditRate_24 )
1343 TmpPDesc.EditRate = ASDCP::EditRate_48;
1345 else if ( PDesc.EditRate == ASDCP::EditRate_25 )
1346 TmpPDesc.EditRate = ASDCP::EditRate_50;
1348 else if ( PDesc.EditRate == ASDCP::EditRate_30 )
1349 TmpPDesc.EditRate = ASDCP::EditRate_60;
1351 else if ( PDesc.EditRate == ASDCP::EditRate_48 )
1352 TmpPDesc.EditRate = ASDCP::EditRate_96;
1354 else if ( PDesc.EditRate == ASDCP::EditRate_50 )
1355 TmpPDesc.EditRate = ASDCP::EditRate_100;
1357 else if ( PDesc.EditRate == ASDCP::EditRate_60 )
1358 TmpPDesc.EditRate = ASDCP::EditRate_120;
1360 else if ( PDesc.EditRate == ASDCP::EditRate_96 )
1361 TmpPDesc.EditRate = ASDCP::EditRate_192;
1363 else if ( PDesc.EditRate == ASDCP::EditRate_100 )
1364 TmpPDesc.EditRate = ASDCP::EditRate_200;
1366 else if ( PDesc.EditRate == ASDCP::EditRate_120 )
1367 TmpPDesc.EditRate = ASDCP::EditRate_240;
1369 result = m_Writer->SetSourceStream(TmpPDesc, JP2K_S_PACKAGE_LABEL, PDesc.EditRate);
1372 if ( ASDCP_FAILURE(result) )
1379 ASDCP::JP2K::MXFSWriter::WriteFrame(const SFrameBuffer& FrameBuf, AESEncContext* Ctx, HMACContext* HMAC)
1381 if ( m_Writer.empty() )
1384 Result_t result = m_Writer->WriteFrame(FrameBuf.Left, SP_LEFT, Ctx, HMAC);
1386 if ( ASDCP_SUCCESS(result) )
1387 result = m_Writer->WriteFrame(FrameBuf.Right, SP_RIGHT, Ctx, HMAC);
1392 // Writes a frame of essence to the MXF file. If the optional AESEncContext
1393 // argument is present, the essence is encrypted prior to writing.
1394 // Fails if the file is not open, is finalized, or an operating system
1397 ASDCP::JP2K::MXFSWriter::WriteFrame(const FrameBuffer& FrameBuf, StereoscopicPhase_t phase,
1398 AESEncContext* Ctx, HMACContext* HMAC)
1400 if ( m_Writer.empty() )
1403 return m_Writer->WriteFrame(FrameBuf, phase, Ctx, HMAC);
1406 // Closes the MXF file, writing the index and other closing information.
1408 ASDCP::JP2K::MXFSWriter::Finalize()
1410 if ( m_Writer.empty() )
1413 return m_Writer->Finalize();
1417 // end AS_DCP_JP2K.cpp