2 Copyright (c) 2004-2014, 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
28 \version $Id: AS_DCP_JP2K.cpp,v 1.69 2015/10/07 16:41:23 jhurst Exp $
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 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&,
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_ui32 = (ui32_t*) tmp_buffer;
237 *tmp_buffer_ui32 = KM_i32_BE(MaxComponents); // three components
238 *(ui32_t*)(tmp_buffer+4) = KM_i32_BE(sizeof(ASDCP::JP2K::ImageComponent_t));
239 memcpy(tmp_buffer + 8, &PDesc.ImageComponents, sizeof(ASDCP::JP2K::ImageComponent_t) * MaxComponents);
241 const ui32_t pcomp_size = (sizeof(ui32_t) * 2) + (sizeof(ASDCP::JP2K::ImageComponent_t) * MaxComponents);
242 memcpy(EssenceSubDescriptor.PictureComponentSizing.get().Data(), tmp_buffer, pcomp_size);
243 EssenceSubDescriptor.PictureComponentSizing.get().Length(pcomp_size);
244 EssenceSubDescriptor.PictureComponentSizing.set_has_value();
246 ui32_t precinct_set_size = 0;
247 for ( ui32_t i = 0; PDesc.CodingStyleDefault.SPcod.PrecinctSize[i] != 0 && i < MaxPrecincts; ++i )
250 ui32_t csd_size = sizeof(CodingStyleDefault_t) - MaxPrecincts + precinct_set_size;
251 memcpy(EssenceSubDescriptor.CodingStyleDefault.get().Data(), &PDesc.CodingStyleDefault, csd_size);
252 EssenceSubDescriptor.CodingStyleDefault.get().Length(csd_size);
253 EssenceSubDescriptor.CodingStyleDefault.set_has_value();
255 ui32_t qdflt_size = PDesc.QuantizationDefault.SPqcdLength + 1;
256 memcpy(EssenceSubDescriptor.QuantizationDefault.get().Data(), &PDesc.QuantizationDefault, qdflt_size);
257 EssenceSubDescriptor.QuantizationDefault.get().Length(qdflt_size);
258 EssenceSubDescriptor.QuantizationDefault.set_has_value();
266 ASDCP::MD_to_JP2K_PDesc(const ASDCP::MXF::GenericPictureEssenceDescriptor& EssenceDescriptor,
267 const ASDCP::MXF::JPEG2000PictureSubDescriptor& EssenceSubDescriptor,
268 const ASDCP::Rational& EditRate, const ASDCP::Rational& SampleRate,
269 ASDCP::JP2K::PictureDescriptor& PDesc)
271 memset(&PDesc, 0, sizeof(PDesc));
273 PDesc.EditRate = EditRate;
274 PDesc.SampleRate = SampleRate;
275 assert(EssenceDescriptor.ContainerDuration.const_get() <= 0xFFFFFFFFL);
276 PDesc.ContainerDuration = static_cast<ui32_t>(EssenceDescriptor.ContainerDuration.const_get());
277 PDesc.StoredWidth = EssenceDescriptor.StoredWidth;
278 PDesc.StoredHeight = EssenceDescriptor.StoredHeight;
279 PDesc.AspectRatio = EssenceDescriptor.AspectRatio;
281 PDesc.Rsize = EssenceSubDescriptor.Rsize;
282 PDesc.Xsize = EssenceSubDescriptor.Xsize;
283 PDesc.Ysize = EssenceSubDescriptor.Ysize;
284 PDesc.XOsize = EssenceSubDescriptor.XOsize;
285 PDesc.YOsize = EssenceSubDescriptor.YOsize;
286 PDesc.XTsize = EssenceSubDescriptor.XTsize;
287 PDesc.YTsize = EssenceSubDescriptor.YTsize;
288 PDesc.XTOsize = EssenceSubDescriptor.XTOsize;
289 PDesc.YTOsize = EssenceSubDescriptor.YTOsize;
290 PDesc.Csize = EssenceSubDescriptor.Csize;
292 // PictureComponentSizing
293 ui32_t tmp_size = EssenceSubDescriptor.PictureComponentSizing.const_get().Length();
295 if ( tmp_size == 17 ) // ( 2 * sizeof(ui32_t) ) + 3 components * 3 byte each
297 memcpy(&PDesc.ImageComponents, EssenceSubDescriptor.PictureComponentSizing.const_get().RoData() + 8, tmp_size - 8);
301 DefaultLogSink().Warn("Unexpected PictureComponentSizing size: %u, should be 17\n", tmp_size);
304 // CodingStyleDefault
305 memset(&PDesc.CodingStyleDefault, 0, sizeof(CodingStyleDefault_t));
306 memcpy(&PDesc.CodingStyleDefault,
307 EssenceSubDescriptor.CodingStyleDefault.const_get().RoData(),
308 EssenceSubDescriptor.CodingStyleDefault.const_get().Length());
310 // QuantizationDefault
311 memset(&PDesc.QuantizationDefault, 0, sizeof(QuantizationDefault_t));
312 memcpy(&PDesc.QuantizationDefault,
313 EssenceSubDescriptor.QuantizationDefault.const_get().RoData(),
314 EssenceSubDescriptor.QuantizationDefault.const_get().Length());
316 PDesc.QuantizationDefault.SPqcdLength = EssenceSubDescriptor.QuantizationDefault.const_get().Length() - 1;
321 //------------------------------------------------------------------------------------------
323 // hidden, internal implementation of JPEG 2000 reader
326 class lh__Reader : public ASDCP::h__ASDCPReader
328 RGBAEssenceDescriptor* m_EssenceDescriptor;
329 JPEG2000PictureSubDescriptor* m_EssenceSubDescriptor;
330 ASDCP::Rational m_EditRate;
331 ASDCP::Rational m_SampleRate;
332 EssenceType_t m_Format;
334 ASDCP_NO_COPY_CONSTRUCT(lh__Reader);
337 PictureDescriptor m_PDesc; // codestream parameter list
339 lh__Reader(const Dictionary& d) :
340 ASDCP::h__ASDCPReader(d), m_EssenceDescriptor(0), m_EssenceSubDescriptor(0), m_Format(ESS_UNKNOWN) {}
342 virtual ~lh__Reader() {}
344 Result_t OpenRead(const std::string&, EssenceType_t);
345 Result_t ReadFrame(ui32_t, JP2K::FrameBuffer&, AESDecContext*, HMACContext*);
352 lh__Reader::OpenRead(const std::string& filename, EssenceType_t type)
354 Result_t result = OpenMXFRead(filename);
356 if( ASDCP_SUCCESS(result) )
358 InterchangeObject* tmp_iobj = 0;
359 m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(RGBAEssenceDescriptor), &tmp_iobj);
360 m_EssenceDescriptor = static_cast<RGBAEssenceDescriptor*>(tmp_iobj);
362 if ( m_EssenceDescriptor == 0 )
364 DefaultLogSink().Error("RGBAEssenceDescriptor object not found.\n");
365 return RESULT_FORMAT;
368 m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(JPEG2000PictureSubDescriptor), &tmp_iobj);
369 m_EssenceSubDescriptor = static_cast<JPEG2000PictureSubDescriptor*>(tmp_iobj);
371 if ( m_EssenceSubDescriptor == 0 )
373 m_EssenceDescriptor = 0;
374 DefaultLogSink().Error("JPEG2000PictureSubDescriptor object not found.\n");
375 return RESULT_FORMAT;
378 std::list<InterchangeObject*> ObjectList;
379 m_HeaderPart.GetMDObjectsByType(OBJ_TYPE_ARGS(Track), ObjectList);
381 if ( ObjectList.empty() )
383 DefaultLogSink().Error("MXF Metadata contains no Track Sets.\n");
384 return RESULT_FORMAT;
387 m_EditRate = ((Track*)ObjectList.front())->EditRate;
388 m_SampleRate = m_EssenceDescriptor->SampleRate;
390 if ( type == ASDCP::ESS_JPEG_2000 )
392 if ( m_EditRate != m_SampleRate )
394 DefaultLogSink().Warn("EditRate and SampleRate do not match (%.03f, %.03f).\n",
395 m_EditRate.Quotient(), m_SampleRate.Quotient());
397 if ( ( m_EditRate == EditRate_24 && m_SampleRate == EditRate_48 )
398 || ( m_EditRate == EditRate_25 && m_SampleRate == EditRate_50 )
399 || ( m_EditRate == EditRate_30 && m_SampleRate == EditRate_60 )
400 || ( m_EditRate == EditRate_48 && m_SampleRate == EditRate_96 )
401 || ( m_EditRate == EditRate_50 && m_SampleRate == EditRate_100 )
402 || ( m_EditRate == EditRate_60 && m_SampleRate == EditRate_120 ) )
404 DefaultLogSink().Debug("File may contain JPEG Interop stereoscopic images.\n");
405 return RESULT_SFORMAT;
408 return RESULT_FORMAT;
411 else if ( type == ASDCP::ESS_JPEG_2000_S )
413 if ( m_EditRate == EditRate_24 )
415 if ( m_SampleRate != EditRate_48 )
417 DefaultLogSink().Error("EditRate and SampleRate not correct for 24/48 stereoscopic essence.\n");
418 return RESULT_FORMAT;
421 else if ( m_EditRate == EditRate_25 )
423 if ( m_SampleRate != EditRate_50 )
425 DefaultLogSink().Error("EditRate and SampleRate not correct for 25/50 stereoscopic essence.\n");
426 return RESULT_FORMAT;
429 else if ( m_EditRate == EditRate_30 )
431 if ( m_SampleRate != EditRate_60 )
433 DefaultLogSink().Error("EditRate and SampleRate not correct for 30/60 stereoscopic essence.\n");
434 return RESULT_FORMAT;
437 else if ( m_EditRate == EditRate_48 )
439 if ( m_SampleRate != EditRate_96 )
441 DefaultLogSink().Error("EditRate and SampleRate not correct for 48/96 stereoscopic essence.\n");
442 return RESULT_FORMAT;
445 else if ( m_EditRate == EditRate_50 )
447 if ( m_SampleRate != EditRate_100 )
449 DefaultLogSink().Error("EditRate and SampleRate not correct for 50/100 stereoscopic essence.\n");
450 return RESULT_FORMAT;
453 else if ( m_EditRate == EditRate_60 )
455 if ( m_SampleRate != EditRate_120 )
457 DefaultLogSink().Error("EditRate and SampleRate not correct for 60/120 stereoscopic essence.\n");
458 return RESULT_FORMAT;
463 DefaultLogSink().Error("EditRate not correct for stereoscopic essence: %d/%d.\n",
464 m_EditRate.Numerator, m_EditRate.Denominator);
465 return RESULT_FORMAT;
470 DefaultLogSink().Error("'type' argument unexpected: %x\n", type);
474 result = MD_to_JP2K_PDesc(*m_EssenceDescriptor, *m_EssenceSubDescriptor, m_EditRate, m_SampleRate, m_PDesc);
483 lh__Reader::ReadFrame(ui32_t FrameNum, JP2K::FrameBuffer& FrameBuf,
484 AESDecContext* Ctx, HMACContext* HMAC)
486 if ( ! m_File.IsOpen() )
490 return ReadEKLVFrame(FrameNum, FrameBuf, m_Dict->ul(MDD_JPEG2000Essence), Ctx, HMAC);
495 class ASDCP::JP2K::MXFReader::h__Reader : public lh__Reader
497 ASDCP_NO_COPY_CONSTRUCT(h__Reader);
501 h__Reader(const Dictionary& d) : lh__Reader(d) {}
506 //------------------------------------------------------------------------------------------
511 ASDCP::JP2K::FrameBuffer::Dump(FILE* stream, ui32_t dump_len) const
516 fprintf(stream, "Frame: %06u, %7u bytes", m_FrameNumber, m_Size);
521 Kumu::hexdump(m_Data, dump_len, stream);
525 //------------------------------------------------------------------------------------------
527 ASDCP::JP2K::MXFReader::MXFReader()
529 m_Reader = new h__Reader(DefaultCompositeDict());
533 ASDCP::JP2K::MXFReader::~MXFReader()
535 if ( m_Reader && m_Reader->m_File.IsOpen() )
539 // Warning: direct manipulation of MXF structures can interfere
540 // with the normal operation of the wrapper. Caveat emptor!
542 ASDCP::MXF::OP1aHeader&
543 ASDCP::JP2K::MXFReader::OP1aHeader()
545 if ( m_Reader.empty() )
547 assert(g_OP1aHeader);
548 return *g_OP1aHeader;
551 return m_Reader->m_HeaderPart;
554 // Warning: direct manipulation of MXF structures can interfere
555 // with the normal operation of the wrapper. Caveat emptor!
557 ASDCP::MXF::OPAtomIndexFooter&
558 ASDCP::JP2K::MXFReader::OPAtomIndexFooter()
560 if ( m_Reader.empty() )
562 assert(g_OPAtomIndexFooter);
563 return *g_OPAtomIndexFooter;
566 return m_Reader->m_IndexAccess;
569 // Warning: direct manipulation of MXF structures can interfere
570 // with the normal operation of the wrapper. Caveat emptor!
573 ASDCP::JP2K::MXFReader::RIP()
575 if ( m_Reader.empty() )
581 return m_Reader->m_RIP;
584 // Open the file for reading. The file must exist. Returns error if the
585 // operation cannot be completed.
587 ASDCP::JP2K::MXFReader::OpenRead(const std::string& filename) const
589 return m_Reader->OpenRead(filename, ASDCP::ESS_JPEG_2000);
594 ASDCP::JP2K::MXFReader::ReadFrame(ui32_t FrameNum, FrameBuffer& FrameBuf,
595 AESDecContext* Ctx, HMACContext* HMAC) const
597 if ( m_Reader && m_Reader->m_File.IsOpen() )
598 return m_Reader->ReadFrame(FrameNum, FrameBuf, Ctx, HMAC);
604 ASDCP::JP2K::MXFReader::LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const
606 return m_Reader->LocateFrame(FrameNum, streamOffset, temporalOffset, keyFrameOffset);
610 // Fill the struct with the values from the file's header.
611 // Returns RESULT_INIT if the file is not open.
613 ASDCP::JP2K::MXFReader::FillPictureDescriptor(PictureDescriptor& PDesc) const
615 if ( m_Reader && m_Reader->m_File.IsOpen() )
617 PDesc = m_Reader->m_PDesc;
625 // Fill the struct with the values from the file's header.
626 // Returns RESULT_INIT if the file is not open.
628 ASDCP::JP2K::MXFReader::FillWriterInfo(WriterInfo& Info) const
630 if ( m_Reader && m_Reader->m_File.IsOpen() )
632 Info = m_Reader->m_Info;
641 ASDCP::JP2K::MXFReader::DumpHeaderMetadata(FILE* stream) const
643 if ( m_Reader->m_File.IsOpen() )
644 m_Reader->m_HeaderPart.Dump(stream);
650 ASDCP::JP2K::MXFReader::DumpIndex(FILE* stream) const
652 if ( m_Reader->m_File.IsOpen() )
653 m_Reader->m_IndexAccess.Dump(stream);
658 ASDCP::JP2K::MXFReader::Close() const
660 if ( m_Reader && m_Reader->m_File.IsOpen() )
670 //------------------------------------------------------------------------------------------
673 class ASDCP::JP2K::MXFSReader::h__SReader : public lh__Reader
675 ui32_t m_StereoFrameReady;
678 h__SReader(const Dictionary& d) : lh__Reader(d), m_StereoFrameReady(0xffffffff) {}
681 Result_t ReadFrame(ui32_t FrameNum, StereoscopicPhase_t phase, FrameBuffer& FrameBuf,
682 AESDecContext* Ctx, HMACContext* HMAC)
684 // look up frame index node
685 IndexTableSegment::IndexEntry TmpEntry;
687 if ( ASDCP_FAILURE(m_IndexAccess.Lookup(FrameNum, TmpEntry)) )
692 // get frame position
693 Kumu::fpos_t FilePosition = m_HeaderPart.BodyOffset + TmpEntry.StreamOffset;
694 Result_t result = RESULT_OK;
696 if ( phase == SP_LEFT )
698 if ( FilePosition != m_LastPosition )
700 m_LastPosition = FilePosition;
701 result = m_File.Seek(FilePosition);
704 // the call to ReadEKLVPacket() will leave the file on an R frame
705 m_StereoFrameReady = FrameNum;
707 else if ( phase == SP_RIGHT )
709 if ( m_StereoFrameReady != FrameNum )
711 // the file is not already positioned, we must do some work
712 // seek to the companion SP_LEFT frame and read the frame's key and length
713 if ( FilePosition != m_LastPosition )
715 m_LastPosition = FilePosition;
716 result = m_File.Seek(FilePosition);
720 result = Reader.ReadKLFromFile(m_File);
722 if ( ASDCP_SUCCESS(result) )
724 // skip over the companion SP_LEFT frame
725 Kumu::fpos_t new_pos = FilePosition + SMPTE_UL_LENGTH + Reader.KLLength() + Reader.Length();
726 result = m_File.Seek(new_pos);
730 // the call to ReadEKLVPacket() will leave the file not on an R frame
731 m_StereoFrameReady = 0xffffffff;
735 DefaultLogSink().Error("Unexpected stereoscopic phase value: %u\n", phase);
739 if( ASDCP_SUCCESS(result) )
741 ui32_t SequenceNum = FrameNum * 2;
742 SequenceNum += ( phase == SP_RIGHT ) ? 2 : 1;
744 result = ReadEKLVPacket(FrameNum, SequenceNum, FrameBuf, m_Dict->ul(MDD_JPEG2000Essence), Ctx, HMAC);
753 ASDCP::JP2K::MXFSReader::MXFSReader()
755 m_Reader = new h__SReader(DefaultCompositeDict());
759 ASDCP::JP2K::MXFSReader::~MXFSReader()
761 if ( m_Reader && m_Reader->m_File.IsOpen() )
765 // Warning: direct manipulation of MXF structures can interfere
766 // with the normal operation of the wrapper. Caveat emptor!
768 ASDCP::MXF::OP1aHeader&
769 ASDCP::JP2K::MXFSReader::OP1aHeader()
771 if ( m_Reader.empty() )
773 assert(g_OP1aHeader);
774 return *g_OP1aHeader;
777 return m_Reader->m_HeaderPart;
780 // Warning: direct manipulation of MXF structures can interfere
781 // with the normal operation of the wrapper. Caveat emptor!
783 ASDCP::MXF::OPAtomIndexFooter&
784 ASDCP::JP2K::MXFSReader::OPAtomIndexFooter()
786 if ( m_Reader.empty() )
788 assert(g_OPAtomIndexFooter);
789 return *g_OPAtomIndexFooter;
792 return m_Reader->m_IndexAccess;
795 // Warning: direct manipulation of MXF structures can interfere
796 // with the normal operation of the wrapper. Caveat emptor!
799 ASDCP::JP2K::MXFSReader::RIP()
801 if ( m_Reader.empty() )
807 return m_Reader->m_RIP;
810 // Open the file for reading. The file must exist. Returns error if the
811 // operation cannot be completed.
813 ASDCP::JP2K::MXFSReader::OpenRead(const std::string& filename) const
815 return m_Reader->OpenRead(filename, ASDCP::ESS_JPEG_2000_S);
820 ASDCP::JP2K::MXFSReader::ReadFrame(ui32_t FrameNum, SFrameBuffer& FrameBuf, AESDecContext* Ctx, HMACContext* HMAC) const
822 Result_t result = RESULT_INIT;
824 if ( m_Reader && m_Reader->m_File.IsOpen() )
826 result = m_Reader->ReadFrame(FrameNum, SP_LEFT, FrameBuf.Left, Ctx, HMAC);
828 if ( ASDCP_SUCCESS(result) )
829 result = m_Reader->ReadFrame(FrameNum, SP_RIGHT, FrameBuf.Right, Ctx, HMAC);
837 ASDCP::JP2K::MXFSReader::ReadFrame(ui32_t FrameNum, StereoscopicPhase_t phase, FrameBuffer& FrameBuf,
838 AESDecContext* Ctx, HMACContext* HMAC) const
840 if ( m_Reader && m_Reader->m_File.IsOpen() )
841 return m_Reader->ReadFrame(FrameNum, phase, FrameBuf, Ctx, HMAC);
847 ASDCP::JP2K::MXFSReader::LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const
849 return m_Reader->LocateFrame(FrameNum, streamOffset, temporalOffset, keyFrameOffset);
852 // Fill the struct with the values from the file's header.
853 // Returns RESULT_INIT if the file is not open.
855 ASDCP::JP2K::MXFSReader::FillPictureDescriptor(PictureDescriptor& PDesc) const
857 if ( m_Reader && m_Reader->m_File.IsOpen() )
859 PDesc = m_Reader->m_PDesc;
867 // Fill the struct with the values from the file's header.
868 // Returns RESULT_INIT if the file is not open.
870 ASDCP::JP2K::MXFSReader::FillWriterInfo(WriterInfo& Info) const
872 if ( m_Reader && m_Reader->m_File.IsOpen() )
874 Info = m_Reader->m_Info;
883 ASDCP::JP2K::MXFSReader::DumpHeaderMetadata(FILE* stream) const
885 if ( m_Reader->m_File.IsOpen() )
886 m_Reader->m_HeaderPart.Dump(stream);
892 ASDCP::JP2K::MXFSReader::DumpIndex(FILE* stream) const
894 if ( m_Reader->m_File.IsOpen() )
895 m_Reader->m_IndexAccess.Dump(stream);
900 ASDCP::JP2K::MXFSReader::Close() const
902 if ( m_Reader && m_Reader->m_File.IsOpen() )
912 //------------------------------------------------------------------------------------------
916 class lh__Writer : public ASDCP::h__ASDCPWriter
918 ASDCP_NO_COPY_CONSTRUCT(lh__Writer);
921 JPEG2000PictureSubDescriptor* m_EssenceSubDescriptor;
924 PictureDescriptor m_PDesc;
925 byte_t m_EssenceUL[SMPTE_UL_LENGTH];
927 lh__Writer(const Dictionary& d) : ASDCP::h__ASDCPWriter(d), m_EssenceSubDescriptor(0) {
928 memset(m_EssenceUL, 0, SMPTE_UL_LENGTH);
931 virtual ~lh__Writer(){}
933 Result_t OpenWrite(const std::string&, EssenceType_t type, ui32_t HeaderSize, bool);
934 Result_t SetSourceStream(const PictureDescriptor&, const std::string& label,
935 ASDCP::Rational LocalEditRate = ASDCP::Rational(0,0));
936 Result_t WriteFrame(const JP2K::FrameBuffer&, bool add_index, AESEncContext*, HMACContext*, std::string* hash = 0);
937 Result_t FakeWriteFrame(int size, bool add_index);
941 // Open the file for writing. The file must not exist unless overwrite is true. Returns error if
942 // the operation cannot be completed.
944 lh__Writer::OpenWrite(const std::string& filename, EssenceType_t type, ui32_t HeaderSize, bool overwrite)
946 if ( ! m_State.Test_BEGIN() )
949 Result_t result = RESULT_OK;
952 result = m_File.OpenModify(filename);
957 result = m_File.OpenWrite(filename);
960 if ( ASDCP_SUCCESS(result) )
962 m_HeaderSize = HeaderSize;
963 RGBAEssenceDescriptor* tmp_rgba = new RGBAEssenceDescriptor(m_Dict);
964 tmp_rgba->ComponentMaxRef = 4095;
965 tmp_rgba->ComponentMinRef = 0;
967 m_EssenceDescriptor = tmp_rgba;
968 m_EssenceSubDescriptor = new JPEG2000PictureSubDescriptor(m_Dict);
969 m_EssenceSubDescriptorList.push_back((InterchangeObject*)m_EssenceSubDescriptor);
971 GenRandomValue(m_EssenceSubDescriptor->InstanceUID);
972 m_EssenceDescriptor->SubDescriptors.push_back(m_EssenceSubDescriptor->InstanceUID);
974 if ( type == ASDCP::ESS_JPEG_2000_S && m_Info.LabelSetType == LS_MXF_SMPTE )
976 InterchangeObject* StereoSubDesc = new StereoscopicPictureSubDescriptor(m_Dict);
977 m_EssenceSubDescriptorList.push_back(StereoSubDesc);
978 GenRandomValue(StereoSubDesc->InstanceUID);
979 m_EssenceDescriptor->SubDescriptors.push_back(StereoSubDesc->InstanceUID);
982 result = m_State.Goto_INIT();
988 // Automatically sets the MXF file's metadata from the first jpeg codestream stream.
990 lh__Writer::SetSourceStream(const PictureDescriptor& PDesc, const std::string& label, ASDCP::Rational LocalEditRate)
993 if ( ! m_State.Test_INIT() )
996 if ( LocalEditRate == ASDCP::Rational(0,0) )
997 LocalEditRate = PDesc.EditRate;
1001 assert(m_EssenceDescriptor);
1002 assert(m_EssenceSubDescriptor);
1003 Result_t result = JP2K_PDesc_to_MD(m_PDesc, *m_Dict,
1004 *static_cast<ASDCP::MXF::GenericPictureEssenceDescriptor*>(m_EssenceDescriptor),
1005 *m_EssenceSubDescriptor);
1007 if ( ASDCP_SUCCESS(result) )
1009 if ( PDesc.StoredWidth < 2049 )
1011 static_cast<ASDCP::MXF::RGBAEssenceDescriptor*>(m_EssenceDescriptor)->PictureEssenceCoding.Set(m_Dict->ul(MDD_JP2KEssenceCompression_2K));
1012 m_EssenceSubDescriptor->Rsize = 3;
1016 static_cast<ASDCP::MXF::RGBAEssenceDescriptor*>(m_EssenceDescriptor)->PictureEssenceCoding.Set(m_Dict->ul(MDD_JP2KEssenceCompression_4K));
1017 m_EssenceSubDescriptor->Rsize = 4;
1020 memcpy(m_EssenceUL, m_Dict->ul(MDD_JPEG2000Essence), SMPTE_UL_LENGTH);
1021 m_EssenceUL[SMPTE_UL_LENGTH-1] = 1; // first (and only) essence container
1022 result = m_State.Goto_READY();
1025 if ( ASDCP_SUCCESS(result) )
1027 result = WriteASDCPHeader(label, UL(m_Dict->ul(MDD_JPEG_2000WrappingFrame)),
1028 PICT_DEF_LABEL, UL(m_EssenceUL), UL(m_Dict->ul(MDD_PictureDataDef)),
1029 LocalEditRate, derive_timecode_rate_from_edit_rate(m_PDesc.EditRate));
1035 // Writes a frame of essence to the MXF file. If the optional AESEncContext
1036 // argument is present, the essence is encrypted prior to writing.
1037 // Fails if the file is not open, is finalized, or an operating system
1041 lh__Writer::WriteFrame(const JP2K::FrameBuffer& FrameBuf, bool add_index,
1042 AESEncContext* Ctx, HMACContext* HMAC, std::string* hash)
1044 Result_t result = RESULT_OK;
1046 if ( m_State.Test_READY() )
1047 result = m_State.Goto_RUNNING(); // first time through
1049 ui64_t StreamOffset = m_StreamOffset;
1051 if ( ASDCP_SUCCESS(result) )
1052 result = WriteEKLVPacket(FrameBuf, m_EssenceUL, Ctx, HMAC, hash);
1054 if ( ASDCP_SUCCESS(result) && add_index )
1056 IndexTableSegment::IndexEntry Entry;
1057 Entry.StreamOffset = StreamOffset;
1058 m_FooterPart.PushIndexEntry(Entry);
1066 lh__Writer::FakeWriteFrame(int size, bool add_index)
1068 Result_t result = RESULT_OK;
1070 if ( m_State.Test_READY() )
1071 result = m_State.Goto_RUNNING();
1073 ui64_t StreamOffset = m_StreamOffset;
1075 if ( ASDCP_SUCCESS(result) )
1076 result = FakeWriteEKLVPacket(size);
1078 if ( ASDCP_SUCCESS(result) && add_index )
1080 IndexTableSegment::IndexEntry Entry;
1081 Entry.StreamOffset = StreamOffset;
1082 m_FooterPart.PushIndexEntry(Entry);
1089 // Closes the MXF file, writing the index and other closing information.
1092 lh__Writer::Finalize()
1094 if ( ! m_State.Test_RUNNING() )
1095 return RESULT_STATE;
1097 m_State.Goto_FINAL();
1099 return WriteASDCPFooter();
1104 class ASDCP::JP2K::MXFWriter::h__Writer : public lh__Writer
1106 ASDCP_NO_COPY_CONSTRUCT(h__Writer);
1110 h__Writer(const Dictionary& d) : lh__Writer(d) {}
1114 //------------------------------------------------------------------------------------------
1118 ASDCP::JP2K::MXFWriter::MXFWriter()
1122 ASDCP::JP2K::MXFWriter::~MXFWriter()
1126 // Warning: direct manipulation of MXF structures can interfere
1127 // with the normal operation of the wrapper. Caveat emptor!
1129 ASDCP::MXF::OP1aHeader&
1130 ASDCP::JP2K::MXFWriter::OP1aHeader()
1132 if ( m_Writer.empty() )
1134 assert(g_OP1aHeader);
1135 return *g_OP1aHeader;
1138 return m_Writer->m_HeaderPart;
1141 // Warning: direct manipulation of MXF structures can interfere
1142 // with the normal operation of the wrapper. Caveat emptor!
1144 ASDCP::MXF::OPAtomIndexFooter&
1145 ASDCP::JP2K::MXFWriter::OPAtomIndexFooter()
1147 if ( m_Writer.empty() )
1149 assert(g_OPAtomIndexFooter);
1150 return *g_OPAtomIndexFooter;
1153 return m_Writer->m_FooterPart;
1156 // Warning: direct manipulation of MXF structures can interfere
1157 // with the normal operation of the wrapper. Caveat emptor!
1160 ASDCP::JP2K::MXFWriter::RIP()
1162 if ( m_Writer.empty() )
1168 return m_Writer->m_RIP;
1171 // Open the file for writing. The file must not exist unless overwrite is true. Returns error if
1172 // the operation cannot be completed.
1174 ASDCP::JP2K::MXFWriter::OpenWrite(const std::string& filename, const WriterInfo& Info,
1175 const PictureDescriptor& PDesc, ui32_t HeaderSize, bool overwrite)
1177 if ( Info.LabelSetType == LS_MXF_SMPTE )
1178 m_Writer = new h__Writer(DefaultSMPTEDict());
1180 m_Writer = new h__Writer(DefaultInteropDict());
1182 m_Writer->m_Info = Info;
1184 Result_t result = m_Writer->OpenWrite(filename, ASDCP::ESS_JPEG_2000, HeaderSize, overwrite);
1186 if ( ASDCP_SUCCESS(result) )
1187 result = m_Writer->SetSourceStream(PDesc, JP2K_PACKAGE_LABEL);
1189 if ( ASDCP_FAILURE(result) )
1196 // Writes a frame of essence to the MXF file. If the optional AESEncContext
1197 // argument is present, the essence is encrypted prior to writing.
1198 // Fails if the file is not open, is finalized, or an operating system
1201 ASDCP::JP2K::MXFWriter::WriteFrame(const FrameBuffer& FrameBuf, AESEncContext* Ctx, HMACContext* HMAC, std::string* hash)
1203 if ( m_Writer.empty() )
1206 return m_Writer->WriteFrame(FrameBuf, true, Ctx, HMAC, hash);
1210 ASDCP::JP2K::MXFWriter::FakeWriteFrame(int size)
1212 if ( m_Writer.empty() )
1215 return m_Writer->FakeWriteFrame(size, true);
1218 // Closes the MXF file, writing the index and other closing information.
1220 ASDCP::JP2K::MXFWriter::Finalize()
1222 if ( m_Writer.empty() )
1225 return m_Writer->Finalize();
1229 ASDCP::JP2K::MXFWriter::Tell() const
1231 return m_Writer->m_File.Tell();
1234 //------------------------------------------------------------------------------------------
1238 class ASDCP::JP2K::MXFSWriter::h__SWriter : public lh__Writer
1240 ASDCP_NO_COPY_CONSTRUCT(h__SWriter);
1242 StereoscopicPhase_t m_NextPhase;
1245 h__SWriter(const Dictionary& d) : lh__Writer(d), m_NextPhase(SP_LEFT) {}
1248 Result_t WriteFrame(const FrameBuffer& FrameBuf, StereoscopicPhase_t phase,
1249 AESEncContext* Ctx, HMACContext* HMAC, std::string* hash)
1251 if ( m_NextPhase != phase )
1252 return RESULT_SPHASE;
1254 if ( phase == SP_LEFT )
1256 m_NextPhase = SP_RIGHT;
1257 return lh__Writer::WriteFrame(FrameBuf, true, Ctx, HMAC, hash);
1260 m_NextPhase = SP_LEFT;
1261 return lh__Writer::WriteFrame(FrameBuf, false, Ctx, HMAC, hash);
1264 Result_t FakeWriteFrame(int size, StereoscopicPhase_t phase)
1266 if ( m_NextPhase != phase )
1267 return RESULT_SPHASE;
1269 if ( phase == SP_LEFT )
1271 m_NextPhase = SP_RIGHT;
1272 return lh__Writer::FakeWriteFrame(size, true);
1275 m_NextPhase = SP_LEFT;
1276 return lh__Writer::FakeWriteFrame(size, false);
1282 if ( m_NextPhase != SP_LEFT )
1283 return RESULT_SPHASE;
1285 assert( m_FramesWritten % 2 == 0 );
1286 m_FramesWritten /= 2;
1287 return lh__Writer::Finalize();
1293 ASDCP::JP2K::MXFSWriter::MXFSWriter()
1297 ASDCP::JP2K::MXFSWriter::~MXFSWriter()
1301 // Warning: direct manipulation of MXF structures can interfere
1302 // with the normal operation of the wrapper. Caveat emptor!
1304 ASDCP::MXF::OP1aHeader&
1305 ASDCP::JP2K::MXFSWriter::OP1aHeader()
1307 if ( m_Writer.empty() )
1309 assert(g_OP1aHeader);
1310 return *g_OP1aHeader;
1313 return m_Writer->m_HeaderPart;
1316 // Warning: direct manipulation of MXF structures can interfere
1317 // with the normal operation of the wrapper. Caveat emptor!
1319 ASDCP::MXF::OPAtomIndexFooter&
1320 ASDCP::JP2K::MXFSWriter::OPAtomIndexFooter()
1322 if ( m_Writer.empty() )
1324 assert(g_OPAtomIndexFooter);
1325 return *g_OPAtomIndexFooter;
1328 return m_Writer->m_FooterPart;
1331 // Warning: direct manipulation of MXF structures can interfere
1332 // with the normal operation of the wrapper. Caveat emptor!
1335 ASDCP::JP2K::MXFSWriter::RIP()
1337 if ( m_Writer.empty() )
1343 return m_Writer->m_RIP;
1346 // Open the file for writing. The file must not exist. Returns error if
1347 // the operation cannot be completed.
1349 ASDCP::JP2K::MXFSWriter::OpenWrite(const std::string& filename, const WriterInfo& Info,
1350 const PictureDescriptor& PDesc, ui32_t HeaderSize, bool overwrite)
1352 if ( Info.LabelSetType == LS_MXF_SMPTE )
1353 m_Writer = new h__SWriter(DefaultSMPTEDict());
1355 m_Writer = new h__SWriter(DefaultInteropDict());
1357 if ( PDesc.EditRate != ASDCP::EditRate_24
1358 && PDesc.EditRate != ASDCP::EditRate_25
1359 && PDesc.EditRate != ASDCP::EditRate_30
1360 && PDesc.EditRate != ASDCP::EditRate_48
1361 && PDesc.EditRate != ASDCP::EditRate_50
1362 && PDesc.EditRate != ASDCP::EditRate_60 )
1364 DefaultLogSink().Error("Stereoscopic wrapping requires 24, 25, 30, 48, 50 or 60 fps input streams.\n");
1365 return RESULT_FORMAT;
1368 if ( PDesc.StoredWidth > 2048 )
1369 DefaultLogSink().Warn("Wrapping non-standard 4K stereoscopic content. I hope you know what you are doing!\n");
1371 m_Writer->m_Info = Info;
1373 Result_t result = m_Writer->OpenWrite(filename, ASDCP::ESS_JPEG_2000_S, HeaderSize, overwrite);
1375 if ( ASDCP_SUCCESS(result) )
1377 PictureDescriptor TmpPDesc = PDesc;
1379 if ( PDesc.EditRate == ASDCP::EditRate_24 )
1380 TmpPDesc.EditRate = ASDCP::EditRate_48;
1382 else if ( PDesc.EditRate == ASDCP::EditRate_25 )
1383 TmpPDesc.EditRate = ASDCP::EditRate_50;
1385 else if ( PDesc.EditRate == ASDCP::EditRate_30 )
1386 TmpPDesc.EditRate = ASDCP::EditRate_60;
1388 else if ( PDesc.EditRate == ASDCP::EditRate_48 )
1389 TmpPDesc.EditRate = ASDCP::EditRate_96;
1391 else if ( PDesc.EditRate == ASDCP::EditRate_50 )
1392 TmpPDesc.EditRate = ASDCP::EditRate_100;
1394 else if ( PDesc.EditRate == ASDCP::EditRate_60 )
1395 TmpPDesc.EditRate = ASDCP::EditRate_120;
1397 result = m_Writer->SetSourceStream(TmpPDesc, JP2K_S_PACKAGE_LABEL, PDesc.EditRate);
1400 if ( ASDCP_FAILURE(result) )
1407 ASDCP::JP2K::MXFSWriter::WriteFrame(const SFrameBuffer& FrameBuf, AESEncContext* Ctx, HMACContext* HMAC)
1409 if ( m_Writer.empty() )
1412 Result_t result = m_Writer->WriteFrame(FrameBuf.Left, SP_LEFT, Ctx, HMAC, 0);
1414 if ( ASDCP_SUCCESS(result) )
1415 result = m_Writer->WriteFrame(FrameBuf.Right, SP_RIGHT, Ctx, HMAC, 0);
1420 // Writes a frame of essence to the MXF file. If the optional AESEncContext
1421 // argument is present, the essence is encrypted prior to writing.
1422 // Fails if the file is not open, is finalized, or an operating system
1425 ASDCP::JP2K::MXFSWriter::WriteFrame(const FrameBuffer& FrameBuf, StereoscopicPhase_t phase,
1426 AESEncContext* Ctx, HMACContext* HMAC, std::string* hash)
1428 if ( m_Writer.empty() )
1431 return m_Writer->WriteFrame(FrameBuf, phase, Ctx, HMAC, hash);
1435 ASDCP::JP2K::MXFSWriter::FakeWriteFrame(int size, StereoscopicPhase_t phase)
1437 if ( m_Writer.empty() )
1440 return m_Writer->FakeWriteFrame(size, phase);
1443 // Closes the MXF file, writing the index and other closing information.
1445 ASDCP::JP2K::MXFSWriter::Finalize()
1447 if ( m_Writer.empty() )
1450 return m_Writer->Finalize();
1454 ASDCP::JP2K::MXFSWriter::Tell() const
1456 return m_Writer->m_File.Tell();
1460 // end AS_DCP_JP2K.cpp