2 Copyright (c) 2011-2014, John Hurst
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
9 1. Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 2. Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
14 3. The name of the author may not be used to endorse or promote products
15 derived from this software without specific prior written permission.
17 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 /*! \file AS_02_PHDR.cpp
30 \brief AS-02 library, JPEG 2000 P-HDR essence reader and writer implementation
33 #include "AS_02_internal.h"
34 #include "AS_02_PHDR.h"
39 using namespace ASDCP;
40 using namespace ASDCP::JP2K;
41 using Kumu::GenRandomValue;
43 //------------------------------------------------------------------------------------------
45 static std::string JP2K_PACKAGE_LABEL = "File Package: PROTOTYPE SMPTE ST 422 / ST 2067-5 frame wrapping of JPEG 2000 codestreams with HDR metadata";
46 static std::string PICT_DEF_LABEL = "PHDR Image Track";
47 static std::string MD_DEF_LABEL = "PHDR Metadata Track";
51 //------------------------------------------------------------------------------------------
55 AS_02::PHDR::FrameBuffer::Dump(FILE* stream, ui32_t dump_bytes) const
60 fprintf(stream, "Hello, HDR world!\n");
64 //------------------------------------------------------------------------------------------
66 // hidden, internal implementation of JPEG 2000 reader
69 class AS_02::PHDR::MXFReader::h__Reader : public AS_02::h__AS02Reader
71 ASDCP_NO_COPY_CONSTRUCT(h__Reader);
74 h__Reader(const Dictionary& d) :
75 AS_02::h__AS02Reader(d) {}
77 virtual ~h__Reader() {}
79 Result_t OpenRead(const std::string& filename, std::string& PHDR_master_metadata);
80 Result_t ReadFrame(ui32_t, AS_02::PHDR::FrameBuffer&, AESDecContext*, HMACContext*);
85 AS_02::PHDR::MXFReader::h__Reader::OpenRead(const std::string& filename, std::string& PHDR_master_metadata)
87 Result_t result = OpenMXFRead(filename.c_str());
88 ui32_t SimplePayloadSID = 0;
90 if( KM_SUCCESS(result) )
92 InterchangeObject* tmp_iobj = 0;
94 m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(CDCIEssenceDescriptor), &tmp_iobj);
98 m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(RGBAEssenceDescriptor), &tmp_iobj);
103 DefaultLogSink().Error("RGBAEssenceDescriptor nor CDCIEssenceDescriptor found.\n");
104 return RESULT_AS02_FORMAT;
107 m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(JPEG2000PictureSubDescriptor), &tmp_iobj);
111 DefaultLogSink().Error("JPEG2000PictureSubDescriptor not found.\n");
112 return RESULT_AS02_FORMAT;
115 m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(PHDRMetadataTrackSubDescriptor), &tmp_iobj);
119 DefaultLogSink().Error("PHDRMetadataTrackSubDescriptor not found.\n");
120 return RESULT_AS02_FORMAT;
124 PHDRMetadataTrackSubDescriptor *tmp_desc = dynamic_cast<PHDRMetadataTrackSubDescriptor*>(tmp_iobj);
126 SimplePayloadSID = tmp_desc->SimplePayloadSID;
129 std::list<InterchangeObject*> ObjectList;
130 m_HeaderPart.GetMDObjectsByType(OBJ_TYPE_ARGS(Track), ObjectList);
132 if ( ObjectList.empty() )
134 DefaultLogSink().Error("MXF Metadata contains no Track Sets.\n");
135 return RESULT_AS02_FORMAT;
139 // if PHDRSimplePayload exists, go get it
140 if ( KM_SUCCESS(result) && SimplePayloadSID )
142 Array<RIP::Pair>::const_iterator pi;
145 // Look up the partition start in the RIP using the SID.
146 for ( pi = m_RIP.PairArray.begin(); pi != m_RIP.PairArray.end(); ++pi )
148 if ( (*pi).BodySID == SimplePayloadSID )
155 if ( TmpPair.ByteOffset == 0 )
157 DefaultLogSink().Error("Body SID not found in RIP set: %d\n", SimplePayloadSID);
158 return RESULT_AS02_FORMAT;
161 // seek to the start of the partition
162 if ( (Kumu::fpos_t)TmpPair.ByteOffset != m_LastPosition )
164 m_LastPosition = TmpPair.ByteOffset;
165 result = m_File.Seek(TmpPair.ByteOffset);
168 // read the partition header
169 ASDCP::MXF::Partition GSPart(m_Dict);
170 result = GSPart.InitFromFile(m_File);
172 if ( KM_SUCCESS(result) )
174 // read the generic stream packet
175 if ( KM_SUCCESS(result) )
177 ASDCP::FrameBuffer tmp_buf;
178 tmp_buf.Capacity(Kumu::Megabyte);
180 result = Read_EKLV_Packet(m_File, *m_Dict, m_Info, m_LastPosition, m_CtFrameBuf,
181 0, 0, tmp_buf, m_Dict->ul(MDD_GenericStream_DataElement), 0, 0);
183 if ( KM_SUCCESS(result) )
185 PHDR_master_metadata.assign((const char*)tmp_buf.RoData(), tmp_buf.Size());
191 m_IndexAccess.Dump();
199 AS_02::PHDR::MXFReader::h__Reader::ReadFrame(ui32_t FrameNum, AS_02::PHDR::FrameBuffer& FrameBuf,
200 ASDCP::AESDecContext* Ctx, ASDCP::HMACContext* HMAC)
202 if ( ! m_File.IsOpen() )
206 Result_t result = ReadEKLVFrame(FrameNum, FrameBuf, m_Dict->ul(MDD_JPEG2000Essence), Ctx, HMAC);
208 if ( KM_SUCCESS(result) )
210 ASDCP::FrameBuffer tmp_metadata_buffer;
211 tmp_metadata_buffer.Capacity(8192);
213 result = Read_EKLV_Packet(m_File, *m_Dict, m_Info, m_LastPosition, m_CtFrameBuf,
214 FrameNum, FrameNum + 1, tmp_metadata_buffer, m_Dict->ul(MDD_PHDRImageMetadataItem), Ctx, HMAC);
216 if ( KM_SUCCESS(result) )
218 FrameBuf.OpaqueMetadata.assign((const char*)tmp_metadata_buffer.RoData(), tmp_metadata_buffer.Size());
225 //------------------------------------------------------------------------------------------
228 AS_02::PHDR::MXFReader::MXFReader()
230 m_Reader = new h__Reader(DefaultCompositeDict());
234 AS_02::PHDR::MXFReader::~MXFReader()
238 // Warning: direct manipulation of MXF structures can interfere
239 // with the normal operation of the wrapper. Caveat emptor!
241 ASDCP::MXF::OP1aHeader&
242 AS_02::PHDR::MXFReader::OP1aHeader()
244 if ( m_Reader.empty() )
246 assert(g_OP1aHeader);
247 return *g_OP1aHeader;
250 return m_Reader->m_HeaderPart;
253 // Warning: direct manipulation of MXF structures can interfere
254 // with the normal operation of the wrapper. Caveat emptor!
256 AS_02::MXF::AS02IndexReader&
257 AS_02::PHDR::MXFReader::AS02IndexReader()
259 if ( m_Reader.empty() )
261 assert(g_AS02IndexReader);
262 return *g_AS02IndexReader;
265 return m_Reader->m_IndexAccess;
268 // Warning: direct manipulation of MXF structures can interfere
269 // with the normal operation of the wrapper. Caveat emptor!
272 AS_02::PHDR::MXFReader::RIP()
274 if ( m_Reader.empty() )
280 return m_Reader->m_RIP;
283 // Open the file for reading. The file must exist. Returns error if the
284 // operation cannot be completed.
286 AS_02::PHDR::MXFReader::OpenRead(const std::string& filename, std::string& PHDR_master_metadata) const
288 return m_Reader->OpenRead(filename, PHDR_master_metadata);
293 AS_02::PHDR::MXFReader::Close() const
295 if ( m_Reader && m_Reader->m_File.IsOpen() )
306 AS_02::PHDR::MXFReader::ReadFrame(ui32_t FrameNum, AS_02::PHDR::FrameBuffer& FrameBuf,
307 ASDCP::AESDecContext* Ctx, ASDCP::HMACContext* HMAC) const
309 if ( m_Reader && m_Reader->m_File.IsOpen() )
310 return m_Reader->ReadFrame(FrameNum, FrameBuf, Ctx, HMAC);
315 // Fill the struct with the values from the file's header.
316 // Returns RESULT_INIT if the file is not open.
318 AS_02::PHDR::MXFReader::FillWriterInfo(WriterInfo& Info) const
320 if ( m_Reader && m_Reader->m_File.IsOpen() )
322 Info = m_Reader->m_Info;
330 //------------------------------------------------------------------------------------------
333 class AS_02::PHDR::MXFWriter::h__Writer : public AS_02::h__AS02WriterFrame
335 PHDRMetadataTrackSubDescriptor *m_MetadataTrackSubDescriptor;
337 ASDCP_NO_COPY_CONSTRUCT(h__Writer);
340 JPEG2000PictureSubDescriptor* m_EssenceSubDescriptor;
342 Result_t WritePHDRHeader(const std::string& PackageLabel, const ASDCP::UL& WrappingUL,
343 const std::string& TrackName, const ASDCP::UL& EssenceUL,
344 const ASDCP::UL& DataDefinition, const ASDCP::Rational& EditRate,
345 const ui32_t& TCFrameRate);
348 byte_t m_EssenceUL[SMPTE_UL_LENGTH];
349 byte_t m_MetadataUL[SMPTE_UL_LENGTH];
351 h__Writer(const Dictionary& d) : h__AS02WriterFrame(d), m_EssenceSubDescriptor(0), m_MetadataTrackSubDescriptor(0) {
352 memset(m_EssenceUL, 0, SMPTE_UL_LENGTH);
353 memset(m_MetadataUL, 0, SMPTE_UL_LENGTH);
356 virtual ~h__Writer(){}
358 Result_t OpenWrite(const std::string&, ASDCP::MXF::FileDescriptor* essence_descriptor,
359 ASDCP::MXF::InterchangeObject_list_t& essence_sub_descriptor_list,
360 const AS_02::IndexStrategy_t& IndexStrategy,
361 const ui32_t& PartitionSpace, const ui32_t& HeaderSize);
362 Result_t SetSourceStream(const std::string& label, const ASDCP::Rational& edit_rate);
363 Result_t WriteFrame(const AS_02::PHDR::FrameBuffer&, ASDCP::AESEncContext*, ASDCP::HMACContext*);
364 Result_t Finalize(const std::string& PHDR_master_metadata);
368 // Open the file for writing. The file must not exist. Returns error if
369 // the operation cannot be completed.
371 AS_02::PHDR::MXFWriter::h__Writer::OpenWrite(const std::string& filename,
372 ASDCP::MXF::FileDescriptor* essence_descriptor,
373 ASDCP::MXF::InterchangeObject_list_t& essence_sub_descriptor_list,
374 const AS_02::IndexStrategy_t& IndexStrategy,
375 const ui32_t& PartitionSpace_sec, const ui32_t& HeaderSize)
377 if ( ! m_State.Test_BEGIN() )
382 if ( m_IndexStrategy != AS_02::IS_FOLLOW )
384 DefaultLogSink().Error("Only strategy IS_FOLLOW is supported at this time.\n");
385 return Kumu::RESULT_NOTIMPL;
388 Result_t result = m_File.OpenWrite(filename);
390 if ( KM_SUCCESS(result) )
392 m_IndexStrategy = IndexStrategy;
393 m_PartitionSpace = PartitionSpace_sec; // later converted to edit units by SetSourceStream()
394 m_HeaderSize = HeaderSize;
396 if ( essence_descriptor->GetUL() != UL(m_Dict->ul(MDD_RGBAEssenceDescriptor))
397 && essence_descriptor->GetUL() != UL(m_Dict->ul(MDD_CDCIEssenceDescriptor)) )
399 DefaultLogSink().Error("Essence descriptor is not a RGBAEssenceDescriptor or CDCIEssenceDescriptor.\n");
400 essence_descriptor->Dump();
401 return RESULT_AS02_FORMAT;
404 m_EssenceDescriptor = essence_descriptor;
406 ASDCP::MXF::InterchangeObject_list_t::iterator i;
407 for ( i = essence_sub_descriptor_list.begin(); i != essence_sub_descriptor_list.end(); ++i )
409 if ( (*i)->GetUL() != UL(m_Dict->ul(MDD_JPEG2000PictureSubDescriptor)) )
411 DefaultLogSink().Error("Essence sub-descriptor is not a JPEG2000PictureSubDescriptor.\n");
415 m_EssenceSubDescriptorList.push_back(*i);
416 GenRandomValue((*i)->InstanceUID);
417 m_EssenceDescriptor->SubDescriptors.push_back((*i)->InstanceUID);
418 *i = 0; // parent will only free the ones we don't keep
421 result = m_State.Goto_INIT();
427 // all the above for a single source clip
429 AS_02::PHDR::MXFWriter::h__Writer::WritePHDRHeader(const std::string& PackageLabel, const ASDCP::UL& WrappingUL,
430 const std::string& TrackName, const ASDCP::UL& EssenceUL,
431 const ASDCP::UL& DataDefinition, const ASDCP::Rational& EditRate,
432 const ui32_t& TCFrameRate)
434 if ( EditRate.Numerator == 0 || EditRate.Denominator == 0 )
436 DefaultLogSink().Error("Non-zero edit-rate reqired.\n");
442 AddSourceClip(EditRate, EditRate/*TODO: for a moment*/, TCFrameRate, TrackName, EssenceUL, DataDefinition, PackageLabel);
444 // add metadata track
445 TrackSet<SourceClip> metdata_track =
446 CreateTrackAndSequence<SourcePackage, SourceClip>(m_HeaderPart, *m_FilePackage,
447 MD_DEF_LABEL, EditRate,
448 UL(m_Dict->ul(MDD_PHDRImageMetadataItem)),
451 metdata_track.Sequence->Duration.set_has_value();
452 m_DurationUpdateList.push_back(&(metdata_track.Sequence->Duration.get()));
453 // Consult ST 379:2004 Sec. 6.3, "Element to track relationship" to see where "12" comes from.
454 metdata_track.Track->TrackNumber = KM_i32_BE(Kumu::cp2i<ui32_t>((UL(m_MetadataUL).Value() + 12)));
456 metdata_track.Clip = new SourceClip(m_Dict);
457 m_HeaderPart.AddChildObject(metdata_track.Clip);
458 metdata_track.Sequence->StructuralComponents.push_back(metdata_track.Clip->InstanceUID);
459 metdata_track.Clip->DataDefinition = UL(m_Dict->ul(MDD_PHDRImageMetadataWrappingFrame));
461 // for now we do not allow setting this value, so all files will be 'original'
462 metdata_track.Clip->SourceTrackID = 0;
463 metdata_track.Clip->SourcePackageID = NilUMID;
465 metdata_track.Clip->Duration.set_has_value();
466 m_DurationUpdateList.push_back(&(metdata_track.Clip->Duration.get()));
468 // add PHDR subdescriptor
469 m_MetadataTrackSubDescriptor = new PHDRMetadataTrackSubDescriptor(m_Dict);
470 m_EssenceSubDescriptorList.push_back(m_MetadataTrackSubDescriptor);
471 GenRandomValue(m_MetadataTrackSubDescriptor->InstanceUID);
472 m_EssenceDescriptor->SubDescriptors.push_back(m_MetadataTrackSubDescriptor->InstanceUID);
473 m_MetadataTrackSubDescriptor->DataDefinition = UL(m_Dict->ul(MDD_PHDRImageMetadataWrappingFrame));
474 m_MetadataTrackSubDescriptor->SourceTrackID = 3;
475 m_MetadataTrackSubDescriptor->SimplePayloadSID = 0;
477 AddEssenceDescriptor(WrappingUL);
479 m_IndexWriter.SetPrimerLookup(&m_HeaderPart.m_Primer);
480 m_RIP.PairArray.push_back(RIP::Pair(0, 0)); // Header partition RIP entry
481 m_IndexWriter.OperationalPattern = m_HeaderPart.OperationalPattern;
482 m_IndexWriter.EssenceContainers = m_HeaderPart.EssenceContainers;
484 Result_t result = m_HeaderPart.WriteToFile(m_File, m_HeaderSize);
486 if ( KM_SUCCESS(result) )
488 m_PartitionSpace *= floor( EditRate.Quotient() + 0.5 ); // convert seconds to edit units
489 m_ECStart = m_File.Tell();
490 m_IndexWriter.IndexSID = 129;
492 UL body_ul(m_Dict->ul(MDD_ClosedCompleteBodyPartition));
493 Partition body_part(m_Dict);
494 body_part.BodySID = 1;
495 body_part.OperationalPattern = m_HeaderPart.OperationalPattern;
496 body_part.EssenceContainers = m_HeaderPart.EssenceContainers;
497 body_part.ThisPartition = m_ECStart;
498 result = body_part.WriteToFile(m_File, body_ul);
499 m_RIP.PairArray.push_back(RIP::Pair(1, body_part.ThisPartition)); // Second RIP Entry
505 // Automatically sets the MXF file's metadata from the first jpeg codestream stream.
507 AS_02::PHDR::MXFWriter::h__Writer::SetSourceStream(const std::string& label, const ASDCP::Rational& edit_rate)
510 if ( ! m_State.Test_INIT() )
515 memcpy(m_EssenceUL, m_Dict->ul(MDD_JPEG2000Essence), SMPTE_UL_LENGTH);
516 m_EssenceUL[SMPTE_UL_LENGTH-1] = 1; // first track of the essence container
518 memcpy(m_MetadataUL, m_Dict->ul(MDD_PHDRImageMetadataItem), SMPTE_UL_LENGTH);
519 m_MetadataUL[SMPTE_UL_LENGTH-1] = 3; // third track of the essence container
521 Result_t result = m_State.Goto_READY();
523 if ( KM_SUCCESS(result) )
525 result = WritePHDRHeader(label, UL(m_Dict->ul(MDD_JPEG_2000WrappingFrame)),
526 PICT_DEF_LABEL, UL(m_EssenceUL), UL(m_Dict->ul(MDD_PictureDataDef)),
527 edit_rate, derive_timecode_rate_from_edit_rate(edit_rate));
529 if ( KM_SUCCESS(result) )
531 this->m_IndexWriter.SetPrimerLookup(&this->m_HeaderPart.m_Primer);
538 // Writes a frame of essence to the MXF file. If the optional AESEncContext
539 // argument is present, the essence is encrypted prior to writing.
540 // Fails if the file is not open, is finalized, or an operating system
544 AS_02::PHDR::MXFWriter::h__Writer::WriteFrame(const AS_02::PHDR::FrameBuffer& FrameBuf,
545 AESEncContext* Ctx, HMACContext* HMAC)
547 if ( FrameBuf.Size() == 0 )
549 DefaultLogSink().Error("The frame buffer size is zero.\n");
553 Result_t result = RESULT_OK;
555 if ( m_State.Test_READY() )
557 result = m_State.Goto_RUNNING(); // first time through
560 if ( KM_SUCCESS(result) )
562 result = WriteEKLVPacket(FrameBuf, m_EssenceUL, Ctx, HMAC);
565 if ( KM_SUCCESS(result) )
567 ASDCP::FrameBuffer metadata_buffer_wrapper;
568 metadata_buffer_wrapper.SetData((byte_t*)(FrameBuf.OpaqueMetadata.c_str()), FrameBuf.OpaqueMetadata.size());
569 metadata_buffer_wrapper.Size(FrameBuf.OpaqueMetadata.size());
572 result = Write_EKLV_Packet(m_File, *m_Dict, m_HeaderPart, m_Info, m_CtFrameBuf, m_FramesWritten,
573 m_StreamOffset, metadata_buffer_wrapper, m_MetadataUL, Ctx, HMAC);
576 if ( KM_SUCCESS(result) )
584 // Closes the MXF file, writing the index and other closing information.
587 AS_02::PHDR::MXFWriter::h__Writer::Finalize(const std::string& PHDR_master_metadata)
589 if ( ! m_State.Test_RUNNING() )
592 Result_t result = m_State.Goto_FINAL();
594 if ( KM_SUCCESS(result) )
596 if ( m_IndexWriter.GetDuration() > 0 )
598 m_IndexWriter.ThisPartition = this->m_File.Tell();
599 m_IndexWriter.WriteToFile(this->m_File);
600 m_RIP.PairArray.push_back(RIP::Pair(0, this->m_IndexWriter.ThisPartition));
603 if ( ! PHDR_master_metadata.empty() )
605 // write PHDRSimplePayload
606 Kumu::fpos_t here = m_File.Tell();
608 // create generic stream partition header
609 static UL GenericStream_DataElement(m_Dict->ul(MDD_GenericStream_DataElement));
610 ASDCP::MXF::Partition GSPart(m_Dict);
612 GSPart.ThisPartition = here;
613 GSPart.PreviousPartition = m_RIP.PairArray.back().ByteOffset;
614 GSPart.OperationalPattern = m_HeaderPart.OperationalPattern;
616 m_MetadataTrackSubDescriptor->SimplePayloadSID = 2;
618 m_RIP.PairArray.push_back(RIP::Pair(2, here));
619 GSPart.EssenceContainers = m_HeaderPart.EssenceContainers;
621 static UL gs_part_ul(m_Dict->ul(MDD_GenericStreamPartition));
622 Result_t result = GSPart.WriteToFile(m_File, gs_part_ul);
624 if ( KM_SUCCESS(result) )
626 ASDCP::FrameBuffer tmp_buf;
627 tmp_buf.SetData((byte_t*)PHDR_master_metadata.c_str(), PHDR_master_metadata.size());
628 tmp_buf.Size(PHDR_master_metadata.size());
630 result = Write_EKLV_Packet(m_File, *m_Dict, m_HeaderPart, m_Info, m_CtFrameBuf, m_FramesWritten,
631 m_StreamOffset, tmp_buf, GenericStream_DataElement.Value(), 0, 0);
637 result = WriteAS02Footer();
644 //------------------------------------------------------------------------------------------
648 AS_02::PHDR::MXFWriter::MXFWriter()
652 AS_02::PHDR::MXFWriter::~MXFWriter()
656 // Warning: direct manipulation of MXF structures can interfere
657 // with the normal operation of the wrapper. Caveat emptor!
659 ASDCP::MXF::OP1aHeader&
660 AS_02::PHDR::MXFWriter::OP1aHeader()
662 if ( m_Writer.empty() )
664 assert(g_OP1aHeader);
665 return *g_OP1aHeader;
668 return m_Writer->m_HeaderPart;
671 // Warning: direct manipulation of MXF structures can interfere
672 // with the normal operation of the wrapper. Caveat emptor!
675 AS_02::PHDR::MXFWriter::RIP()
677 if ( m_Writer.empty() )
683 return m_Writer->m_RIP;
686 // Open the file for writing. The file must not exist. Returns error if
687 // the operation cannot be completed.
689 AS_02::PHDR::MXFWriter::OpenWrite(const std::string& filename, const ASDCP::WriterInfo& Info,
690 ASDCP::MXF::FileDescriptor* essence_descriptor,
691 ASDCP::MXF::InterchangeObject_list_t& essence_sub_descriptor_list,
692 const ASDCP::Rational& edit_rate, const ui32_t& header_size,
693 const IndexStrategy_t& strategy, const ui32_t& partition_space)
695 if ( essence_descriptor == 0 )
697 DefaultLogSink().Error("Essence descriptor object required.\n");
701 m_Writer = new AS_02::PHDR::MXFWriter::h__Writer(DefaultSMPTEDict());
702 m_Writer->m_Info = Info;
704 Result_t result = m_Writer->OpenWrite(filename, essence_descriptor, essence_sub_descriptor_list,
705 strategy, partition_space, header_size);
707 if ( KM_SUCCESS(result) )
708 result = m_Writer->SetSourceStream(JP2K_PACKAGE_LABEL, edit_rate);
710 if ( KM_FAILURE(result) )
716 // Writes a frame of essence to the MXF file. If the optional AESEncContext
717 // argument is present, the essence is encrypted prior to writing.
718 // Fails if the file is not open, is finalized, or an operating system
721 AS_02::PHDR::MXFWriter::WriteFrame(const AS_02::PHDR::FrameBuffer& FrameBuf, AESEncContext* Ctx, HMACContext* HMAC)
723 if ( m_Writer.empty() )
726 return m_Writer->WriteFrame(FrameBuf, Ctx, HMAC);
729 // Closes the MXF file, writing the index and other closing information.
731 AS_02::PHDR::MXFWriter::Finalize(const std::string& PHDR_master_metadata)
733 if ( m_Writer.empty() )
736 return m_Writer->Finalize(PHDR_master_metadata);
741 // end AS_02_PHDR.cpp