/*
-Copyright (c) 2004-2009, John Hurst
+Copyright (c) 2004-2013, John Hurst
All rights reserved.
Redistribution and use in source and binary forms, with or without
}
-//------------------------------------------------------------------------------------------
+const int VideoLineMapSize = 16; // See SMPTE 377M D.2.1
+const int PixelLayoutSize = 8*2; // See SMPTE 377M D.2.3
+static const byte_t s_PixelLayoutXYZ[PixelLayoutSize] = { 0xd8, 0x0c, 0xd9, 0x0c, 0xda, 0x0c, 0x00 };
+
//
-// hidden, internal implementation of JPEG 2000 reader
+ASDCP::Result_t
+ASDCP::JP2K_PDesc_to_MD(const JP2K::PictureDescriptor& PDesc,
+ const ASDCP::Dictionary& dict,
+ ASDCP::MXF::RGBAEssenceDescriptor *EssenceDescriptor,
+ ASDCP::MXF::JPEG2000PictureSubDescriptor *EssenceSubDescriptor)
+{
+ if ( EssenceDescriptor == 0 || EssenceSubDescriptor == 0 )
+ return RESULT_PTR;
+ EssenceDescriptor->ContainerDuration = PDesc.ContainerDuration;
+ EssenceDescriptor->SampleRate = PDesc.EditRate;
+ EssenceDescriptor->FrameLayout = 0;
+ EssenceDescriptor->StoredWidth = PDesc.StoredWidth;
+ EssenceDescriptor->StoredHeight = PDesc.StoredHeight;
+ EssenceDescriptor->AspectRatio = PDesc.AspectRatio;
-class lh__Reader : public ASDCP::h__Reader
-{
- RGBAEssenceDescriptor* m_EssenceDescriptor;
- JPEG2000PictureSubDescriptor* m_EssenceSubDescriptor;
- ASDCP::Rational m_EditRate;
- ASDCP::Rational m_SampleRate;
- EssenceType_t m_Format;
+ // if ( m_Info.LabelSetType == LS_MXF_SMPTE )
+ // {
+ // PictureEssenceCoding UL =
+ // Video Line Map ui32_t[VideoLineMapSize] = { 2, 4, 0, 0 }
+ // CaptureGamma UL =
+ // ComponentMaxRef ui32_t = 4095
+ // ComponentMinRef ui32_t = 0
+ // PixelLayout byte_t[PixelLayoutSize] = s_PixelLayoutXYZ
+ // }
- ASDCP_NO_COPY_CONSTRUCT(lh__Reader);
+ if ( PDesc.StoredWidth < 2049 )
+ {
+ EssenceDescriptor->PictureEssenceCoding.Set(dict.ul(MDD_JP2KEssenceCompression_2K));
+ EssenceSubDescriptor->Rsize = 3;
+ }
+ else
+ {
+ EssenceDescriptor->PictureEssenceCoding.Set(dict.ul(MDD_JP2KEssenceCompression_4K));
+ EssenceSubDescriptor->Rsize = 4;
+ }
-public:
- PictureDescriptor m_PDesc; // codestream parameter list
+ EssenceSubDescriptor->Xsize = PDesc.Xsize;
+ EssenceSubDescriptor->Ysize = PDesc.Ysize;
+ EssenceSubDescriptor->XOsize = PDesc.XOsize;
+ EssenceSubDescriptor->YOsize = PDesc.YOsize;
+ EssenceSubDescriptor->XTsize = PDesc.XTsize;
+ EssenceSubDescriptor->YTsize = PDesc.YTsize;
+ EssenceSubDescriptor->XTOsize = PDesc.XTOsize;
+ EssenceSubDescriptor->YTOsize = PDesc.YTOsize;
+ EssenceSubDescriptor->Csize = PDesc.Csize;
+
+ const ui32_t tmp_buffer_len = 1024;
+ byte_t tmp_buffer[tmp_buffer_len];
+
+ *(ui32_t*)tmp_buffer = KM_i32_BE(MaxComponents); // three components
+ *(ui32_t*)(tmp_buffer+4) = KM_i32_BE(sizeof(ASDCP::JP2K::ImageComponent_t));
+ memcpy(tmp_buffer + 8, &PDesc.ImageComponents, sizeof(ASDCP::JP2K::ImageComponent_t) * MaxComponents);
+
+ const ui32_t pcomp_size = (sizeof(int) * 2) + (sizeof(ASDCP::JP2K::ImageComponent_t) * MaxComponents);
+ memcpy(EssenceSubDescriptor->PictureComponentSizing.Data(), tmp_buffer, pcomp_size);
+ EssenceSubDescriptor->PictureComponentSizing.Length(pcomp_size);
+
+ ui32_t precinct_set_size = 0, i;
+ for ( i = 0; PDesc.CodingStyleDefault.SPcod.PrecinctSize[i] != 0 && i < MaxPrecincts; i++ )
+ precinct_set_size++;
+
+ ui32_t csd_size = sizeof(CodingStyleDefault_t) - MaxPrecincts + precinct_set_size;
+ memcpy(EssenceSubDescriptor->CodingStyleDefault.Data(), &PDesc.CodingStyleDefault, csd_size);
+ EssenceSubDescriptor->CodingStyleDefault.Length(csd_size);
+
+ ui32_t qdflt_size = PDesc.QuantizationDefault.SPqcdLength + 1;
+ memcpy(EssenceSubDescriptor->QuantizationDefault.Data(), &PDesc.QuantizationDefault, qdflt_size);
+ EssenceSubDescriptor->QuantizationDefault.Length(qdflt_size);
+
+ return RESULT_OK;
+}
- lh__Reader(const Dictionary& d) :
- ASDCP::h__Reader(d), m_EssenceDescriptor(0), m_EssenceSubDescriptor(0), m_Format(ESS_UNKNOWN) {}
- Result_t OpenRead(const char*, EssenceType_t);
- Result_t ReadFrame(ui32_t, JP2K::FrameBuffer&, AESDecContext*, HMACContext*);
- Result_t MD_to_JP2K_PDesc(JP2K::PictureDescriptor& PDesc);
-};
//
ASDCP::Result_t
-lh__Reader::MD_to_JP2K_PDesc(JP2K::PictureDescriptor& PDesc)
+ASDCP::MD_to_JP2K_PDesc(const ASDCP::MXF::RGBAEssenceDescriptor& EssenceDescriptor,
+ const ASDCP::MXF::JPEG2000PictureSubDescriptor& EssenceSubDescriptor,
+ const ASDCP::Rational& EditRate, const ASDCP::Rational& SampleRate,
+ ASDCP::JP2K::PictureDescriptor& PDesc)
{
memset(&PDesc, 0, sizeof(PDesc));
- MXF::RGBAEssenceDescriptor* PDescObj = (MXF::RGBAEssenceDescriptor*)m_EssenceDescriptor;
- PDesc.EditRate = m_EditRate;
- PDesc.SampleRate = m_SampleRate;
- assert(PDescObj->ContainerDuration <= 0xFFFFFFFFL);
- PDesc.ContainerDuration = (ui32_t) PDescObj->ContainerDuration;
- PDesc.StoredWidth = PDescObj->StoredWidth;
- PDesc.StoredHeight = PDescObj->StoredHeight;
- PDesc.AspectRatio = PDescObj->AspectRatio;
+ PDesc.EditRate = EditRate;
+ PDesc.SampleRate = SampleRate;
+ assert(EssenceDescriptor.ContainerDuration <= 0xFFFFFFFFL);
+ PDesc.ContainerDuration = (ui32_t) EssenceDescriptor.ContainerDuration;
+ PDesc.StoredWidth = EssenceDescriptor.StoredWidth;
+ PDesc.StoredHeight = EssenceDescriptor.StoredHeight;
+ PDesc.AspectRatio = EssenceDescriptor.AspectRatio;
+
+ PDesc.Rsize = EssenceSubDescriptor.Rsize;
+ PDesc.Xsize = EssenceSubDescriptor.Xsize;
+ PDesc.Ysize = EssenceSubDescriptor.Ysize;
+ PDesc.XOsize = EssenceSubDescriptor.XOsize;
+ PDesc.YOsize = EssenceSubDescriptor.YOsize;
+ PDesc.XTsize = EssenceSubDescriptor.XTsize;
+ PDesc.YTsize = EssenceSubDescriptor.YTsize;
+ PDesc.XTOsize = EssenceSubDescriptor.XTOsize;
+ PDesc.YTOsize = EssenceSubDescriptor.YTOsize;
+ PDesc.Csize = EssenceSubDescriptor.Csize;
+
+ // PictureComponentSizing
+ ui32_t tmp_size = EssenceSubDescriptor.PictureComponentSizing.Length();
+
+ if ( tmp_size == 17 ) // ( 2 * sizeof(ui32_t) ) + 3 components * 3 byte each
+ {
+ memcpy(&PDesc.ImageComponents, EssenceSubDescriptor.PictureComponentSizing.RoData() + 8, tmp_size - 8);
+ }
+ else
+ {
+ DefaultLogSink().Error("Unexpected PictureComponentSizing size: %u, should be 17\n", tmp_size);
+ }
+
+ // CodingStyleDefault
+ memset(&PDesc.CodingStyleDefault, 0, sizeof(CodingStyleDefault_t));
+ memcpy(&PDesc.CodingStyleDefault,
+ EssenceSubDescriptor.CodingStyleDefault.RoData(),
+ EssenceSubDescriptor.CodingStyleDefault.Length());
+
+ // QuantizationDefault
+ memset(&PDesc.QuantizationDefault, 0, sizeof(QuantizationDefault_t));
+ memcpy(&PDesc.QuantizationDefault,
+ EssenceSubDescriptor.QuantizationDefault.RoData(),
+ EssenceSubDescriptor.QuantizationDefault.Length());
+
+ PDesc.QuantizationDefault.SPqcdLength = EssenceSubDescriptor.QuantizationDefault.Length() - 1;
+ return RESULT_OK;
+}
+
+//
+ASDCP::Result_t
+ASDCP::JP2K_PDesc_to_MD(const JP2K::PictureDescriptor& PDesc,
+ const ASDCP::Dictionary& dict,
+ ASDCP::MXF::CDCIEssenceDescriptor *EssenceDescriptor,
+ ASDCP::MXF::JPEG2000PictureSubDescriptor *EssenceSubDescriptor)
+{
+ if ( EssenceDescriptor == 0 || EssenceSubDescriptor == 0 )
+ return RESULT_PTR;
+
+ EssenceDescriptor->ContainerDuration = PDesc.ContainerDuration;
+ EssenceDescriptor->SampleRate = PDesc.EditRate;
+ EssenceDescriptor->FrameLayout = 0;
+ EssenceDescriptor->StoredWidth = PDesc.StoredWidth;
+ EssenceDescriptor->StoredHeight = PDesc.StoredHeight;
+ EssenceDescriptor->AspectRatio = PDesc.AspectRatio;
+
+ // if ( m_Info.LabelSetType == LS_MXF_SMPTE )
+ // {
+ // PictureEssenceCoding UL =
+ // Video Line Map ui32_t[VideoLineMapSize] = { 2, 4, 0, 0 }
+ // CaptureGamma UL =
+ // ComponentMaxRef ui32_t = 4095
+ // ComponentMinRef ui32_t = 0
+ // PixelLayout byte_t[PixelLayoutSize] = s_PixelLayoutXYZ
+ // }
- if ( m_EssenceSubDescriptor != 0 )
+ if ( PDesc.StoredWidth < 2049 )
+ {
+ EssenceDescriptor->PictureEssenceCoding.Set(dict.ul(MDD_JP2KEssenceCompression_2K));
+ EssenceSubDescriptor->Rsize = 3;
+ }
+ else
{
- PDesc.Rsize = m_EssenceSubDescriptor->Rsize;
- PDesc.Xsize = m_EssenceSubDescriptor->Xsize;
- PDesc.Ysize = m_EssenceSubDescriptor->Ysize;
- PDesc.XOsize = m_EssenceSubDescriptor->XOsize;
- PDesc.YOsize = m_EssenceSubDescriptor->YOsize;
- PDesc.XTsize = m_EssenceSubDescriptor->XTsize;
- PDesc.YTsize = m_EssenceSubDescriptor->YTsize;
- PDesc.XTOsize = m_EssenceSubDescriptor->XTOsize;
- PDesc.YTOsize = m_EssenceSubDescriptor->YTOsize;
- PDesc.Csize = m_EssenceSubDescriptor->Csize;
-
- // PictureComponentSizing
- ui32_t tmp_size = m_EssenceSubDescriptor->PictureComponentSizing.Length();
-
- if ( tmp_size == 17 ) // ( 2 * sizeof(ui32_t) ) + 3 components * 3 byte each
- memcpy(&PDesc.ImageComponents, m_EssenceSubDescriptor->PictureComponentSizing.RoData() + 8, tmp_size - 8);
+ EssenceDescriptor->PictureEssenceCoding.Set(dict.ul(MDD_JP2KEssenceCompression_4K));
+ EssenceSubDescriptor->Rsize = 4;
+ }
- else
- DefaultLogSink().Error("Unexpected PictureComponentSizing size: %u, should be 17\n", tmp_size);
+ EssenceSubDescriptor->Xsize = PDesc.Xsize;
+ EssenceSubDescriptor->Ysize = PDesc.Ysize;
+ EssenceSubDescriptor->XOsize = PDesc.XOsize;
+ EssenceSubDescriptor->YOsize = PDesc.YOsize;
+ EssenceSubDescriptor->XTsize = PDesc.XTsize;
+ EssenceSubDescriptor->YTsize = PDesc.YTsize;
+ EssenceSubDescriptor->XTOsize = PDesc.XTOsize;
+ EssenceSubDescriptor->YTOsize = PDesc.YTOsize;
+ EssenceSubDescriptor->Csize = PDesc.Csize;
- // CodingStyleDefault
- memset(&m_PDesc.CodingStyleDefault, 0, sizeof(CodingStyleDefault_t));
- memcpy(&m_PDesc.CodingStyleDefault,
- m_EssenceSubDescriptor->CodingStyleDefault.RoData(),
- m_EssenceSubDescriptor->CodingStyleDefault.Length());
+ const ui32_t tmp_buffer_len = 1024;
+ byte_t tmp_buffer[tmp_buffer_len];
+
+ *(ui32_t*)tmp_buffer = KM_i32_BE(MaxComponents); // three components
+ *(ui32_t*)(tmp_buffer+4) = KM_i32_BE(sizeof(ASDCP::JP2K::ImageComponent_t));
+ memcpy(tmp_buffer + 8, &PDesc.ImageComponents, sizeof(ASDCP::JP2K::ImageComponent_t) * MaxComponents);
+
+ const ui32_t pcomp_size = (sizeof(int) * 2) + (sizeof(ASDCP::JP2K::ImageComponent_t) * MaxComponents);
+ memcpy(EssenceSubDescriptor->PictureComponentSizing.Data(), tmp_buffer, pcomp_size);
+ EssenceSubDescriptor->PictureComponentSizing.Length(pcomp_size);
+
+ ui32_t precinct_set_size = 0, i;
+ for ( i = 0; PDesc.CodingStyleDefault.SPcod.PrecinctSize[i] != 0 && i < MaxPrecincts; i++ )
+ precinct_set_size++;
+
+ ui32_t csd_size = sizeof(CodingStyleDefault_t) - MaxPrecincts + precinct_set_size;
+ memcpy(EssenceSubDescriptor->CodingStyleDefault.Data(), &PDesc.CodingStyleDefault, csd_size);
+ EssenceSubDescriptor->CodingStyleDefault.Length(csd_size);
+
+ ui32_t qdflt_size = PDesc.QuantizationDefault.SPqcdLength + 1;
+ memcpy(EssenceSubDescriptor->QuantizationDefault.Data(), &PDesc.QuantizationDefault, qdflt_size);
+ EssenceSubDescriptor->QuantizationDefault.Length(qdflt_size);
+
+ return RESULT_OK;
+}
- // QuantizationDefault
- memset(&m_PDesc.QuantizationDefault, 0, sizeof(QuantizationDefault_t));
- memcpy(&m_PDesc.QuantizationDefault,
- m_EssenceSubDescriptor->QuantizationDefault.RoData(),
- m_EssenceSubDescriptor->QuantizationDefault.Length());
- m_PDesc.QuantizationDefault.SPqcdLength = m_EssenceSubDescriptor->QuantizationDefault.Length() - 1;
+//
+ASDCP::Result_t
+ASDCP::MD_to_JP2K_PDesc(const ASDCP::MXF::CDCIEssenceDescriptor& EssenceDescriptor,
+ const ASDCP::MXF::JPEG2000PictureSubDescriptor& EssenceSubDescriptor,
+ const ASDCP::Rational& EditRate, const ASDCP::Rational& SampleRate,
+ ASDCP::JP2K::PictureDescriptor& PDesc)
+{
+ memset(&PDesc, 0, sizeof(PDesc));
+
+ PDesc.EditRate = EditRate;
+ PDesc.SampleRate = SampleRate;
+ assert(EssenceDescriptor.ContainerDuration <= 0xFFFFFFFFL);
+ PDesc.ContainerDuration = (ui32_t) EssenceDescriptor.ContainerDuration;
+ PDesc.StoredWidth = EssenceDescriptor.StoredWidth;
+ PDesc.StoredHeight = EssenceDescriptor.StoredHeight;
+ PDesc.AspectRatio = EssenceDescriptor.AspectRatio;
+
+ PDesc.Rsize = EssenceSubDescriptor.Rsize;
+ PDesc.Xsize = EssenceSubDescriptor.Xsize;
+ PDesc.Ysize = EssenceSubDescriptor.Ysize;
+ PDesc.XOsize = EssenceSubDescriptor.XOsize;
+ PDesc.YOsize = EssenceSubDescriptor.YOsize;
+ PDesc.XTsize = EssenceSubDescriptor.XTsize;
+ PDesc.YTsize = EssenceSubDescriptor.YTsize;
+ PDesc.XTOsize = EssenceSubDescriptor.XTOsize;
+ PDesc.YTOsize = EssenceSubDescriptor.YTOsize;
+ PDesc.Csize = EssenceSubDescriptor.Csize;
+
+ // PictureComponentSizing
+ ui32_t tmp_size = EssenceSubDescriptor.PictureComponentSizing.Length();
+
+ if ( tmp_size == 17 ) // ( 2 * sizeof(ui32_t) ) + 3 components * 3 byte each
+ {
+ memcpy(&PDesc.ImageComponents, EssenceSubDescriptor.PictureComponentSizing.RoData() + 8, tmp_size - 8);
+ }
+ else
+ {
+ DefaultLogSink().Error("Unexpected PictureComponentSizing size: %u, should be 17\n", tmp_size);
}
+ // CodingStyleDefault
+ memset(&PDesc.CodingStyleDefault, 0, sizeof(CodingStyleDefault_t));
+ memcpy(&PDesc.CodingStyleDefault,
+ EssenceSubDescriptor.CodingStyleDefault.RoData(),
+ EssenceSubDescriptor.CodingStyleDefault.Length());
+
+ // QuantizationDefault
+ memset(&PDesc.QuantizationDefault, 0, sizeof(QuantizationDefault_t));
+ memcpy(&PDesc.QuantizationDefault,
+ EssenceSubDescriptor.QuantizationDefault.RoData(),
+ EssenceSubDescriptor.QuantizationDefault.Length());
+
+ PDesc.QuantizationDefault.SPqcdLength = EssenceSubDescriptor.QuantizationDefault.Length() - 1;
return RESULT_OK;
}
+// Compares the actual floating point value of the rates.
+// This allows, for example, {300000,1001} and {2997,100) to be considered equivalent.
+// to 29.97.
+bool
+epsilon_compare(const ASDCP::Rational& left, const ASDCP::Rational& right, double epsilon = 0.001)
+{
+ bool result = false;
+ double difference = left.Quotient() - right.Quotient();
+
+ if (fabs(difference) < epsilon)
+ result = true;
+
+ return result;
+}
+// end DOLBY
+
+
+//------------------------------------------------------------------------------------------
+//
+// hidden, internal implementation of JPEG 2000 reader
+
+
+class lh__Reader : public ASDCP::h__ASDCPReader
+{
+ RGBAEssenceDescriptor* m_EssenceDescriptor;
+ JPEG2000PictureSubDescriptor* m_EssenceSubDescriptor;
+ ASDCP::Rational m_EditRate;
+ ASDCP::Rational m_SampleRate;
+ EssenceType_t m_Format;
+
+ ASDCP_NO_COPY_CONSTRUCT(lh__Reader);
+
+public:
+ PictureDescriptor m_PDesc; // codestream parameter list
+
+ lh__Reader(const Dictionary& d) :
+ ASDCP::h__ASDCPReader(d), m_EssenceDescriptor(0), m_EssenceSubDescriptor(0), m_Format(ESS_UNKNOWN) {}
+
+ virtual ~lh__Reader() {}
+
+ Result_t OpenRead(const char*, EssenceType_t);
+ Result_t ReadFrame(ui32_t, JP2K::FrameBuffer&, AESDecContext*, HMACContext*);
+};
+
+
//
//
ASDCP::Result_t
m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(RGBAEssenceDescriptor), &tmp_iobj);
m_EssenceDescriptor = static_cast<RGBAEssenceDescriptor*>(tmp_iobj);
+ if ( m_EssenceDescriptor == 0 )
+ {
+ DefaultLogSink().Error("RGBAEssenceDescriptor object not found.\n");
+ return RESULT_FORMAT;
+ }
+
m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(JPEG2000PictureSubDescriptor), &tmp_iobj);
m_EssenceSubDescriptor = static_cast<JPEG2000PictureSubDescriptor*>(tmp_iobj);
+ if ( m_EssenceSubDescriptor == 0 )
+ {
+ m_EssenceDescriptor = 0;
+ DefaultLogSink().Error("JPEG2000PictureSubDescriptor object not found.\n");
+ return RESULT_FORMAT;
+ }
+
std::list<InterchangeObject*> ObjectList;
m_HeaderPart.GetMDObjectsByType(OBJ_TYPE_ARGS(Track), ObjectList);
DefaultLogSink().Warn("EditRate and SampleRate do not match (%.03f, %.03f).\n",
m_EditRate.Quotient(), m_SampleRate.Quotient());
- if ( m_EditRate == EditRate_24 && m_SampleRate == EditRate_48 )
+ if ( m_EditRate == EditRate_24 && m_SampleRate == EditRate_48 ||
+ m_EditRate == EditRate_25 && m_SampleRate == EditRate_50 ||
+ m_EditRate == EditRate_30 && m_SampleRate == EditRate_60 ||
+ m_EditRate == EditRate_48 && m_SampleRate == EditRate_96 ||
+ m_EditRate == EditRate_50 && m_SampleRate == EditRate_100 ||
+ m_EditRate == EditRate_60 && m_SampleRate == EditRate_120 )
{
DefaultLogSink().Debug("File may contain JPEG Interop stereoscopic images.\n");
return RESULT_SFORMAT;
return RESULT_FORMAT;
}
}
+ else if ( m_EditRate == EditRate_48 )
+ {
+ if ( m_SampleRate != EditRate_96 )
+ {
+ DefaultLogSink().Error("EditRate and SampleRate not correct for 48/96 stereoscopic essence.\n");
+ return RESULT_FORMAT;
+ }
+ }
+ else if ( m_EditRate == EditRate_50 )
+ {
+ if ( m_SampleRate != EditRate_100 )
+ {
+ DefaultLogSink().Error("EditRate and SampleRate not correct for 50/100 stereoscopic essence.\n");
+ return RESULT_FORMAT;
+ }
+ }
+ else if ( m_EditRate == EditRate_60 )
+ {
+ if ( m_SampleRate != EditRate_120 )
+ {
+ DefaultLogSink().Error("EditRate and SampleRate not correct for 60/120 stereoscopic essence.\n");
+ return RESULT_FORMAT;
+ }
+ }
else
{
DefaultLogSink().Error("EditRate not correct for stereoscopic essence: %d/%d.\n",
return RESULT_STATE;
}
- result = MD_to_JP2K_PDesc(m_PDesc);
+ result = MD_to_JP2K_PDesc(*m_EssenceDescriptor, *m_EssenceSubDescriptor, m_EditRate, m_SampleRate, m_PDesc);
}
- if( ASDCP_SUCCESS(result) )
- result = InitMXFIndex();
-
- if( ASDCP_SUCCESS(result) )
- result = InitInfo();
-
return result;
}
ASDCP::JP2K::MXFReader::~MXFReader()
{
+ if ( m_Reader && m_Reader->m_File.IsOpen() )
+ m_Reader->Close();
+}
+
+// Warning: direct manipulation of MXF structures can interfere
+// with the normal operation of the wrapper. Caveat emptor!
+//
+ASDCP::MXF::OP1aHeader&
+ASDCP::JP2K::MXFReader::OP1aHeader()
+{
+ if ( m_Reader.empty() )
+ {
+ assert(g_OP1aHeader);
+ return *g_OP1aHeader;
+ }
+
+ return m_Reader->m_HeaderPart;
+}
+
+// Warning: direct manipulation of MXF structures can interfere
+// with the normal operation of the wrapper. Caveat emptor!
+//
+ASDCP::MXF::OPAtomIndexFooter&
+ASDCP::JP2K::MXFReader::OPAtomIndexFooter()
+{
+ if ( m_Reader.empty() )
+ {
+ assert(g_OPAtomIndexFooter);
+ return *g_OPAtomIndexFooter;
+ }
+
+ return m_Reader->m_IndexAccess;
+}
+
+// Warning: direct manipulation of MXF structures can interfere
+// with the normal operation of the wrapper. Caveat emptor!
+//
+ASDCP::MXF::RIP&
+ASDCP::JP2K::MXFReader::RIP()
+{
+ if ( m_Reader.empty() )
+ {
+ assert(g_RIP);
+ return *g_RIP;
+ }
+
+ return m_Reader->m_RIP;
}
// Open the file for reading. The file must exist. Returns error if the
return RESULT_INIT;
}
+ASDCP::Result_t
+ASDCP::JP2K::MXFReader::LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const
+{
+ return m_Reader->LocateFrame(FrameNum, streamOffset, temporalOffset, keyFrameOffset);
+}
+
// Fill the struct with the values from the file's header.
// Returns RESULT_INIT if the file is not open.
ASDCP::JP2K::MXFReader::DumpIndex(FILE* stream) const
{
if ( m_Reader->m_File.IsOpen() )
- m_Reader->m_FooterPart.Dump(stream);
+ m_Reader->m_IndexAccess.Dump(stream);
+}
+
+//
+ASDCP::Result_t
+ASDCP::JP2K::MXFReader::Close() const
+{
+ if ( m_Reader && m_Reader->m_File.IsOpen() )
+ {
+ m_Reader->Close();
+ return RESULT_OK;
+ }
+
+ return RESULT_INIT;
}
// look up frame index node
IndexTableSegment::IndexEntry TmpEntry;
- if ( ASDCP_FAILURE(m_FooterPart.Lookup(FrameNum, TmpEntry)) )
+ if ( ASDCP_FAILURE(m_IndexAccess.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;
+ Kumu::fpos_t FilePosition = m_HeaderPart.BodyOffset + TmpEntry.StreamOffset;
Result_t result = RESULT_OK;
if ( phase == SP_LEFT )
ASDCP::JP2K::MXFSReader::~MXFSReader()
{
+ if ( m_Reader && m_Reader->m_File.IsOpen() )
+ m_Reader->Close();
+}
+
+// Warning: direct manipulation of MXF structures can interfere
+// with the normal operation of the wrapper. Caveat emptor!
+//
+ASDCP::MXF::OP1aHeader&
+ASDCP::JP2K::MXFSReader::OP1aHeader()
+{
+ if ( m_Reader.empty() )
+ {
+ assert(g_OP1aHeader);
+ return *g_OP1aHeader;
+ }
+
+ return m_Reader->m_HeaderPart;
+}
+
+// Warning: direct manipulation of MXF structures can interfere
+// with the normal operation of the wrapper. Caveat emptor!
+//
+ASDCP::MXF::OPAtomIndexFooter&
+ASDCP::JP2K::MXFSReader::OPAtomIndexFooter()
+{
+ if ( m_Reader.empty() )
+ {
+ assert(g_OPAtomIndexFooter);
+ return *g_OPAtomIndexFooter;
+ }
+
+ return m_Reader->m_IndexAccess;
+}
+
+// Warning: direct manipulation of MXF structures can interfere
+// with the normal operation of the wrapper. Caveat emptor!
+//
+ASDCP::MXF::RIP&
+ASDCP::JP2K::MXFSReader::RIP()
+{
+ if ( m_Reader.empty() )
+ {
+ assert(g_RIP);
+ return *g_RIP;
+ }
+
+ return m_Reader->m_RIP;
}
// Open the file for reading. The file must exist. Returns error if the
return RESULT_INIT;
}
+ASDCP::Result_t
+ASDCP::JP2K::MXFSReader::LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const
+{
+ return m_Reader->LocateFrame(FrameNum, streamOffset, temporalOffset, keyFrameOffset);
+}
+
// 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::DumpIndex(FILE* stream) const
{
if ( m_Reader->m_File.IsOpen() )
- m_Reader->m_FooterPart.Dump(stream);
+ m_Reader->m_IndexAccess.Dump(stream);
+}
+
+//
+ASDCP::Result_t
+ASDCP::JP2K::MXFSReader::Close() const
+{
+ if ( m_Reader && m_Reader->m_File.IsOpen() )
+ {
+ m_Reader->Close();
+ return RESULT_OK;
+ }
+
+ return RESULT_INIT;
}
+
//------------------------------------------------------------------------------------------
//
-class lh__Writer : public ASDCP::h__Writer
+class lh__Writer : public ASDCP::h__ASDCPWriter
{
ASDCP_NO_COPY_CONSTRUCT(lh__Writer);
lh__Writer();
PictureDescriptor m_PDesc;
byte_t m_EssenceUL[SMPTE_UL_LENGTH];
- lh__Writer(const Dictionary& d) : ASDCP::h__Writer(d), m_EssenceSubDescriptor(0) {
+ lh__Writer(const Dictionary& d) : ASDCP::h__ASDCPWriter(d), m_EssenceSubDescriptor(0) {
memset(m_EssenceUL, 0, SMPTE_UL_LENGTH);
}
- ~lh__Writer(){}
+ virtual ~lh__Writer(){}
Result_t OpenWrite(const char*, EssenceType_t type, ui32_t HeaderSize);
Result_t SetSourceStream(const PictureDescriptor&, const std::string& label,
ASDCP::Rational LocalEditRate = ASDCP::Rational(0,0));
Result_t WriteFrame(const JP2K::FrameBuffer&, bool add_index, AESEncContext*, HMACContext*);
Result_t Finalize();
- Result_t JP2K_PDesc_to_MD(JP2K::PictureDescriptor& PDesc);
};
-const int VideoLineMapSize = 16; // See SMPTE 377M D.2.1
-const int PixelLayoutSize = 8*2; // See SMPTE 377M D.2.3
-static const byte_t s_PixelLayoutXYZ[PixelLayoutSize] = { 0xd8, 0x0c, 0xd9, 0x0c, 0xda, 0x0c, 0x00 };
-
-//
-ASDCP::Result_t
-lh__Writer::JP2K_PDesc_to_MD(JP2K::PictureDescriptor& PDesc)
-{
- assert(m_EssenceDescriptor);
- assert(m_EssenceSubDescriptor);
- MXF::RGBAEssenceDescriptor* PDescObj = (MXF::RGBAEssenceDescriptor*)m_EssenceDescriptor;
-
- PDescObj->ContainerDuration = PDesc.ContainerDuration;
- PDescObj->SampleRate = PDesc.EditRate;
- PDescObj->FrameLayout = 0;
- PDescObj->StoredWidth = PDesc.StoredWidth;
- PDescObj->StoredHeight = PDesc.StoredHeight;
- PDescObj->AspectRatio = PDesc.AspectRatio;
-
- // if ( m_Info.LabelSetType == LS_MXF_SMPTE )
- // {
- // PictureEssenceCoding UL =
- // Video Line Map ui32_t[VideoLineMapSize] = { 2, 4, 0, 0 }
- // CaptureGamma UL =
- // ComponentMaxRef ui32_t = 4095
- // ComponentMinRef ui32_t = 0
- // PixelLayout byte_t[PixelLayoutSize] = s_PixelLayoutXYZ
- // }
-
- assert(m_Dict);
- if ( PDesc.StoredWidth < 2049 )
- {
- PDescObj->PictureEssenceCoding.Set(m_Dict->ul(MDD_JP2KEssenceCompression_2K));
- m_EssenceSubDescriptor->Rsize = 3;
- }
- else
- {
- PDescObj->PictureEssenceCoding.Set(m_Dict->ul(MDD_JP2KEssenceCompression_4K));
- m_EssenceSubDescriptor->Rsize = 4;
- }
-
- m_EssenceSubDescriptor->Xsize = PDesc.Xsize;
- m_EssenceSubDescriptor->Ysize = PDesc.Ysize;
- m_EssenceSubDescriptor->XOsize = PDesc.XOsize;
- m_EssenceSubDescriptor->YOsize = PDesc.YOsize;
- m_EssenceSubDescriptor->XTsize = PDesc.XTsize;
- m_EssenceSubDescriptor->YTsize = PDesc.YTsize;
- m_EssenceSubDescriptor->XTOsize = PDesc.XTOsize;
- m_EssenceSubDescriptor->YTOsize = PDesc.YTOsize;
- m_EssenceSubDescriptor->Csize = PDesc.Csize;
-
- const ui32_t tmp_buffer_len = 1024;
- byte_t tmp_buffer[tmp_buffer_len];
-
- *(ui32_t*)tmp_buffer = KM_i32_BE(MaxComponents); // three components
- *(ui32_t*)(tmp_buffer+4) = KM_i32_BE(sizeof(ASDCP::JP2K::ImageComponent_t));
- memcpy(tmp_buffer + 8, &PDesc.ImageComponents, sizeof(ASDCP::JP2K::ImageComponent_t) * MaxComponents);
-
- const ui32_t pcomp_size = (sizeof(int) * 2) + (sizeof(ASDCP::JP2K::ImageComponent_t) * MaxComponents);
- memcpy(m_EssenceSubDescriptor->PictureComponentSizing.Data(), tmp_buffer, pcomp_size);
- m_EssenceSubDescriptor->PictureComponentSizing.Length(pcomp_size);
-
- ui32_t precinct_set_size = 0, i;
- for ( i = 0; PDesc.CodingStyleDefault.SPcod.PrecinctSize[i] != 0 && i < MaxPrecincts; i++ )
- precinct_set_size++;
-
- ui32_t csd_size = sizeof(CodingStyleDefault_t) - MaxPrecincts + precinct_set_size;
- memcpy(m_EssenceSubDescriptor->CodingStyleDefault.Data(), &PDesc.CodingStyleDefault, csd_size);
- m_EssenceSubDescriptor->CodingStyleDefault.Length(csd_size);
-
- ui32_t qdflt_size = PDesc.QuantizationDefault.SPqcdLength + 1;
- memcpy(m_EssenceSubDescriptor->QuantizationDefault.Data(), &PDesc.QuantizationDefault, qdflt_size);
- m_EssenceSubDescriptor->QuantizationDefault.Length(qdflt_size);
-
- return RESULT_OK;
-}
-
-
// Open the file for writing. The file must not exist. Returns error if
// the operation cannot be completed.
ASDCP::Result_t
LocalEditRate = PDesc.EditRate;
m_PDesc = PDesc;
- Result_t result = JP2K_PDesc_to_MD(m_PDesc);
-
- if ( ASDCP_SUCCESS(result) )
- result = WriteMXFHeader(label, UL(m_Dict->ul(MDD_JPEG_2000Wrapping)),
- PICT_DEF_LABEL, UL(m_Dict->ul(MDD_PictureDataDef)),
- LocalEditRate, 24 /* TCFrameRate */);
+ assert(m_Dict);
+ Result_t result = JP2K_PDesc_to_MD(m_PDesc, *m_Dict,
+ (ASDCP::MXF::RGBAEssenceDescriptor*)m_EssenceDescriptor,
+ m_EssenceSubDescriptor);
if ( ASDCP_SUCCESS(result) )
{
result = m_State.Goto_READY();
}
+ if ( ASDCP_SUCCESS(result) )
+ {
+ result = WriteASDCPHeader(label, UL(m_Dict->ul(MDD_JPEG_2000Wrapping)),
+ PICT_DEF_LABEL, UL(m_EssenceUL), UL(m_Dict->ul(MDD_PictureDataDef)),
+ LocalEditRate, derive_timecode_rate_from_edit_rate(m_PDesc.EditRate));
+ }
+
return result;
}
m_State.Goto_FINAL();
- return WriteMXFFooter();
+ return WriteASDCPFooter();
}
{
}
+// Warning: direct manipulation of MXF structures can interfere
+// with the normal operation of the wrapper. Caveat emptor!
+//
+ASDCP::MXF::OP1aHeader&
+ASDCP::JP2K::MXFWriter::OP1aHeader()
+{
+ if ( m_Writer.empty() )
+ {
+ assert(g_OP1aHeader);
+ return *g_OP1aHeader;
+ }
+
+ return m_Writer->m_HeaderPart;
+}
+
+// Warning: direct manipulation of MXF structures can interfere
+// with the normal operation of the wrapper. Caveat emptor!
+//
+ASDCP::MXF::OPAtomIndexFooter&
+ASDCP::JP2K::MXFWriter::OPAtomIndexFooter()
+{
+ if ( m_Writer.empty() )
+ {
+ assert(g_OPAtomIndexFooter);
+ return *g_OPAtomIndexFooter;
+ }
+
+ return m_Writer->m_FooterPart;
+}
+
+// Warning: direct manipulation of MXF structures can interfere
+// with the normal operation of the wrapper. Caveat emptor!
+//
+ASDCP::MXF::RIP&
+ASDCP::JP2K::MXFWriter::RIP()
+{
+ if ( m_Writer.empty() )
+ {
+ assert(g_RIP);
+ return *g_RIP;
+ }
+
+ return m_Writer->m_RIP;
+}
// Open the file for writing. The file must not exist. Returns error if
// the operation cannot be completed.
{
}
+// Warning: direct manipulation of MXF structures can interfere
+// with the normal operation of the wrapper. Caveat emptor!
+//
+ASDCP::MXF::OP1aHeader&
+ASDCP::JP2K::MXFSWriter::OP1aHeader()
+{
+ if ( m_Writer.empty() )
+ {
+ assert(g_OP1aHeader);
+ return *g_OP1aHeader;
+ }
+
+ return m_Writer->m_HeaderPart;
+}
+
+// Warning: direct manipulation of MXF structures can interfere
+// with the normal operation of the wrapper. Caveat emptor!
+//
+ASDCP::MXF::OPAtomIndexFooter&
+ASDCP::JP2K::MXFSWriter::OPAtomIndexFooter()
+{
+ if ( m_Writer.empty() )
+ {
+ assert(g_OPAtomIndexFooter);
+ return *g_OPAtomIndexFooter;
+ }
+
+ return m_Writer->m_FooterPart;
+}
+
+// Warning: direct manipulation of MXF structures can interfere
+// with the normal operation of the wrapper. Caveat emptor!
+//
+ASDCP::MXF::RIP&
+ASDCP::JP2K::MXFSWriter::RIP()
+{
+ if ( m_Writer.empty() )
+ {
+ assert(g_RIP);
+ return *g_RIP;
+ }
+
+ return m_Writer->m_RIP;
+}
// Open the file for writing. The file must not exist. Returns error if
// the operation cannot be completed.
if ( PDesc.EditRate != ASDCP::EditRate_24
&& PDesc.EditRate != ASDCP::EditRate_25
- && PDesc.EditRate != ASDCP::EditRate_30 )
+ && PDesc.EditRate != ASDCP::EditRate_30
+ && PDesc.EditRate != ASDCP::EditRate_48
+ && PDesc.EditRate != ASDCP::EditRate_50
+ && PDesc.EditRate != ASDCP::EditRate_60 )
{
- DefaultLogSink().Error("Stereoscopic wrapping requires 24, 25 or 30 fps input streams.\n");
+ DefaultLogSink().Error("Stereoscopic wrapping requires 24, 25, 30, 48, 50 or 60 fps input streams.\n");
return RESULT_FORMAT;
}
else if ( PDesc.EditRate == ASDCP::EditRate_30 )
TmpPDesc.EditRate = ASDCP::EditRate_60;
+ else if ( PDesc.EditRate == ASDCP::EditRate_48 )
+ TmpPDesc.EditRate = ASDCP::EditRate_96;
+
+ else if ( PDesc.EditRate == ASDCP::EditRate_50 )
+ TmpPDesc.EditRate = ASDCP::EditRate_100;
+
+ else if ( PDesc.EditRate == ASDCP::EditRate_60 )
+ TmpPDesc.EditRate = ASDCP::EditRate_120;
+
result = m_Writer->SetSourceStream(TmpPDesc, JP2K_S_PACKAGE_LABEL, PDesc.EditRate);
}