+//------------------------------------------------------------------------------------------
+//
+
+//
+class ASDCP::JP2K::MXFSWriter::h__SWriter : public lh__Writer
+{
+ ASDCP_NO_COPY_CONSTRUCT(h__SWriter);
+ h__SWriter();
+ StereoscopicPhase_t m_NextPhase;
+
+public:
+ h__SWriter(const Dictionary& d) : lh__Writer(d), m_NextPhase(SP_LEFT) {}
+
+ //
+ Result_t WriteFrame(const FrameBuffer& FrameBuf, StereoscopicPhase_t phase,
+ AESEncContext* Ctx, HMACContext* HMAC)
+ {
+ if ( m_NextPhase != phase )
+ return RESULT_SPHASE;
+
+ if ( phase == SP_LEFT )
+ {
+ m_NextPhase = SP_RIGHT;
+ return lh__Writer::WriteFrame(FrameBuf, true, Ctx, HMAC);
+ }
+
+ m_NextPhase = SP_LEFT;
+ return lh__Writer::WriteFrame(FrameBuf, false, Ctx, HMAC);
+ }
+
+ //
+ Result_t Finalize()
+ {
+ if ( m_NextPhase != SP_LEFT )
+ return RESULT_SPHASE;
+
+ assert( m_FramesWritten % 2 == 0 );
+ m_FramesWritten /= 2;
+ return lh__Writer::Finalize();
+ }
+};
+
+
+//
+ASDCP::JP2K::MXFSWriter::MXFSWriter()
+{
+}
+
+ASDCP::JP2K::MXFSWriter::~MXFSWriter()
+{
+}
+
+
+// Open the file for writing. The file must not exist. Returns error if
+// the operation cannot be completed.
+ASDCP::Result_t
+ASDCP::JP2K::MXFSWriter::OpenWrite(const char* filename, const WriterInfo& Info,
+ const PictureDescriptor& PDesc, ui32_t HeaderSize)
+{
+ if ( Info.LabelSetType == LS_MXF_SMPTE )
+ m_Writer = new h__SWriter(DefaultSMPTEDict());
+ else
+ m_Writer = new h__SWriter(DefaultInteropDict());
+
+ if ( PDesc.EditRate != ASDCP::EditRate_24 )
+ {
+ DefaultLogSink().Error("Stereoscopic wrapping requires 24 fps input streams.\n");
+ return RESULT_FORMAT;
+ }
+
+ if ( PDesc.StoredWidth > 2048 )
+ DefaultLogSink().Warn("Wrapping non-standard 4K stereoscopic content. I hope you know what you are doing!\n");
+
+ m_Writer->m_Info = Info;
+
+ Result_t result = m_Writer->OpenWrite(filename, ASDCP::ESS_JPEG_2000_S, HeaderSize);
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ PictureDescriptor TmpPDesc = PDesc;
+ TmpPDesc.EditRate = ASDCP::EditRate_48;
+
+ result = m_Writer->SetSourceStream(TmpPDesc, JP2K_S_PACKAGE_LABEL, ASDCP::EditRate_24);
+ }
+
+ if ( ASDCP_FAILURE(result) )
+ m_Writer.release();
+
+ return result;
+}
+
+ASDCP::Result_t
+ASDCP::JP2K::MXFSWriter::WriteFrame(const SFrameBuffer& FrameBuf, AESEncContext* Ctx, HMACContext* HMAC)
+{
+ if ( m_Writer.empty() )
+ return RESULT_INIT;
+
+ Result_t result = m_Writer->WriteFrame(FrameBuf.Left, SP_LEFT, Ctx, HMAC);
+
+ if ( ASDCP_SUCCESS(result) )
+ result = m_Writer->WriteFrame(FrameBuf.Right, SP_RIGHT, Ctx, HMAC);
+
+ return result;
+}
+
+// Writes a frame of essence to the MXF file. If the optional AESEncContext
+// argument is present, the essence is encrypted prior to writing.
+// Fails if the file is not open, is finalized, or an operating system
+// error occurs.
+ASDCP::Result_t
+ASDCP::JP2K::MXFSWriter::WriteFrame(const FrameBuffer& FrameBuf, StereoscopicPhase_t phase,
+ AESEncContext* Ctx, HMACContext* HMAC)
+{
+ if ( m_Writer.empty() )
+ return RESULT_INIT;
+
+ return m_Writer->WriteFrame(FrameBuf, phase, Ctx, HMAC);
+}
+
+// Closes the MXF file, writing the index and other closing information.
+ASDCP::Result_t
+ASDCP::JP2K::MXFSWriter::Finalize()
+{
+ if ( m_Writer.empty() )
+ return RESULT_INIT;
+
+ return m_Writer->Finalize();
+}
+