+class ASDCP::JP2K::MXFSReader::h__SReader : public lh__Reader
+{
+ ui32_t m_StereoFrameReady;
+
+public:
+ h__SReader(const Dictionary& d) : lh__Reader(d), m_StereoFrameReady(0xffffffff) {}
+
+ //
+ Result_t ReadFrame(ui32_t FrameNum, StereoscopicPhase_t phase, FrameBuffer& FrameBuf,
+ AESDecContext* Ctx, HMACContext* HMAC)
+ {
+ // look up frame index node
+ IndexTableSegment::IndexEntry TmpEntry;
+
+ if ( ASDCP_FAILURE(m_FooterPart.Lookup(FrameNum, TmpEntry)) )
+ {
+ DefaultLogSink().Error("Frame value out of range: %u\n", FrameNum);
+ return RESULT_RANGE;
+ }
+
+ // get frame position
+ Kumu::fpos_t FilePosition = m_EssenceStart + TmpEntry.StreamOffset;
+ Result_t result = RESULT_OK;
+
+ if ( phase == SP_LEFT )
+ {
+ if ( FilePosition != m_LastPosition )
+ {
+ m_LastPosition = FilePosition;
+ result = m_File.Seek(FilePosition);
+ }
+
+ // the call to ReadEKLVPacket() will leave the file on an R frame
+ m_StereoFrameReady = FrameNum;
+ }
+ else if ( phase == SP_RIGHT )
+ {
+ if ( m_StereoFrameReady != FrameNum )
+ {
+ // the file is not already positioned, we must do some work
+ // seek to the companion SP_LEFT frame and read the frame's key and length
+ if ( FilePosition != m_LastPosition )
+ {
+ m_LastPosition = FilePosition;
+ result = m_File.Seek(FilePosition);
+ }
+
+ KLReader Reader;
+ result = Reader.ReadKLFromFile(m_File);
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ // skip over the companion SP_LEFT frame
+ Kumu::fpos_t new_pos = FilePosition + SMPTE_UL_LENGTH + Reader.KLLength() + Reader.Length();
+ result = m_File.Seek(new_pos);
+ }
+ }
+
+ // the call to ReadEKLVPacket() will leave the file not on an R frame
+ m_StereoFrameReady = 0xffffffff;
+ }
+ else
+ {
+ DefaultLogSink().Error("Unexpected stereoscopic phase value: %u\n", phase);
+ return RESULT_STATE;
+ }
+
+ if( ASDCP_SUCCESS(result) )
+ {
+ ui32_t SequenceNum = FrameNum * 2;
+ SequenceNum += ( phase == SP_RIGHT ) ? 2 : 1;
+ assert(m_Dict);
+ result = ReadEKLVPacket(FrameNum, SequenceNum, FrameBuf, m_Dict->ul(MDD_JPEG2000Essence), Ctx, HMAC);
+ }
+
+ return result;
+ }
+};
+
+
+
+ASDCP::JP2K::MXFSReader::MXFSReader()
+{
+ m_Reader = new h__SReader(DefaultCompositeDict());
+}
+
+
+ASDCP::JP2K::MXFSReader::~MXFSReader()
+{
+}
+
+// Open the file for reading. The file must exist. Returns error if the
+// operation cannot be completed.
+ASDCP::Result_t
+ASDCP::JP2K::MXFSReader::OpenRead(const char* filename) const
+{
+ return m_Reader->OpenRead(filename, ASDCP::ESS_JPEG_2000_S);
+}
+
+//
+ASDCP::Result_t
+ASDCP::JP2K::MXFSReader::ReadFrame(ui32_t FrameNum, SFrameBuffer& FrameBuf, AESDecContext* Ctx, HMACContext* HMAC) const
+{
+ Result_t result = RESULT_INIT;
+
+ if ( m_Reader && m_Reader->m_File.IsOpen() )
+ {
+ result = m_Reader->ReadFrame(FrameNum, SP_LEFT, FrameBuf.Left, Ctx, HMAC);
+
+ if ( ASDCP_SUCCESS(result) )
+ result = m_Reader->ReadFrame(FrameNum, SP_RIGHT, FrameBuf.Right, Ctx, HMAC);
+ }
+
+ return result;
+}
+
+//
+ASDCP::Result_t
+ASDCP::JP2K::MXFSReader::ReadFrame(ui32_t FrameNum, StereoscopicPhase_t phase, FrameBuffer& FrameBuf,
+ AESDecContext* Ctx, HMACContext* HMAC) const
+{
+ if ( m_Reader && m_Reader->m_File.IsOpen() )
+ return m_Reader->ReadFrame(FrameNum, phase, FrameBuf, Ctx, HMAC);
+
+ return RESULT_INIT;
+}
+
+// Fill the struct with the values from the file's header.
+// Returns RESULT_INIT if the file is not open.
+ASDCP::Result_t
+ASDCP::JP2K::MXFSReader::FillPictureDescriptor(PictureDescriptor& PDesc) const
+{
+ if ( m_Reader && m_Reader->m_File.IsOpen() )
+ {
+ PDesc = m_Reader->m_PDesc;
+ return RESULT_OK;
+ }
+
+ return RESULT_INIT;
+}
+
+
+// Fill the struct with the values from the file's header.
+// Returns RESULT_INIT if the file is not open.
+ASDCP::Result_t
+ASDCP::JP2K::MXFSReader::FillWriterInfo(WriterInfo& Info) const
+{
+ if ( m_Reader && m_Reader->m_File.IsOpen() )
+ {
+ Info = m_Reader->m_Info;
+ return RESULT_OK;
+ }
+
+ return RESULT_INIT;
+}