X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2FAS_DCP_JP2K.cpp;h=39dceedd72b4e681f93bdfe39f8108911e0dc62d;hb=3e1ee0a500bd0b513db4bdf18a9cb052f42404d4;hp=f5ce3354f9c19d2cc164beb1afa9232f1e8686d0;hpb=deadc1bf01e8bc68905c7d33578ffb77b8317c8f;p=asdcplib.git diff --git a/src/AS_DCP_JP2K.cpp b/src/AS_DCP_JP2K.cpp index f5ce335..39dceed 100755 --- a/src/AS_DCP_JP2K.cpp +++ b/src/AS_DCP_JP2K.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2004-2007, John Hurst +Copyright (c) 2004-2008, John Hurst All rights reserved. Redistribution and use in source and binary forms, with or without @@ -32,7 +32,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "AS_DCP_internal.h" using namespace ASDCP::JP2K; - +using Kumu::GenRandomValue; //------------------------------------------------------------------------------------------ @@ -84,7 +84,8 @@ ASDCP::JP2K::PictureDescriptorDump(const PictureDescriptor& PDesc, FILE* stream) fprintf(stream, " ImageComponents:\n"); fprintf(stream, " bits h-sep v-sep\n"); - for ( ui32_t i = 0; i < PDesc.Csize; i++ ) + ui32_t i; + for ( i = 0; i < PDesc.Csize; i++ ) { fprintf(stream, " %4d %5d %5d\n", PDesc.ImageComponents[i].Ssize + 1, // See ISO 15444-1, Table A11, for the origin of '+1' @@ -106,7 +107,7 @@ ASDCP::JP2K::PictureDescriptorDump(const PictureDescriptor& PDesc, FILE* stream) fprintf(stream, " Transformation: %hd\n", PDesc.CodingStyleDefault.SPcod.Transformation); - ui32_t precinct_set_size = 0, i; + ui32_t precinct_set_size = 0; for ( i = 0; PDesc.CodingStyleDefault.SPcod.PrecinctSize[i] != 0 && i < MaxPrecincts; i++ ) precinct_set_size++; @@ -159,7 +160,8 @@ lh__Reader::MD_to_JP2K_PDesc(JP2K::PictureDescriptor& PDesc) MXF::RGBAEssenceDescriptor* PDescObj = (MXF::RGBAEssenceDescriptor*)m_EssenceDescriptor; PDesc.EditRate = m_EditRate; - PDesc.ContainerDuration = PDescObj->ContainerDuration; + assert(PDescObj->ContainerDuration <= 0xFFFFFFFFL); + PDesc.ContainerDuration = (ui32_t) PDescObj->ContainerDuration; PDesc.StoredWidth = PDescObj->StoredWidth; PDesc.StoredHeight = PDescObj->StoredHeight; PDesc.AspectRatio = PDescObj->AspectRatio; @@ -213,17 +215,19 @@ lh__Reader::OpenRead(const char* filename, EssenceType_t type) if( ASDCP_SUCCESS(result) ) { - m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(RGBAEssenceDescriptor), - (InterchangeObject**)&m_EssenceDescriptor); - m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(JPEG2000PictureSubDescriptor), - (InterchangeObject**)&m_EssenceSubDescriptor); + InterchangeObject* tmp_iobj = 0; + m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(RGBAEssenceDescriptor), &tmp_iobj); + m_EssenceDescriptor = static_cast(tmp_iobj); + + m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(JPEG2000PictureSubDescriptor), &tmp_iobj); + m_EssenceSubDescriptor = static_cast(tmp_iobj); std::list ObjectList; m_HeaderPart.GetMDObjectsByType(OBJ_TYPE_ARGS(Track), ObjectList); if ( ObjectList.empty() ) { - DefaultLogSink().Error("MXF Metadata contains no Track Sets\n"); + DefaultLogSink().Error("MXF Metadata contains no Track Sets.\n"); return RESULT_FORMAT; } @@ -233,16 +237,23 @@ lh__Reader::OpenRead(const char* filename, EssenceType_t type) { if ( m_EditRate != m_EssenceDescriptor->SampleRate ) { - DefaultLogSink().Error("EditRate and SampleRate do not match (%.03f, %.03f)\n", + DefaultLogSink().Error("EditRate and SampleRate do not match (%.03f, %.03f).\n", m_EditRate.Quotient(), m_EssenceDescriptor->SampleRate.Quotient()); - return RESULT_SFORMAT; + + if ( m_EditRate == EditRate_24 && m_EssenceDescriptor->SampleRate == EditRate_48 ) + { + DefaultLogSink().Error("File may contain JPEG Interop stereoscopic images.\n"); + return RESULT_SFORMAT; + } + + return RESULT_FORMAT; } } else if ( type == ASDCP::ESS_JPEG_2000_S ) { if ( ! ( m_EditRate == EditRate_24 && m_EssenceDescriptor->SampleRate == EditRate_48 ) ) { - DefaultLogSink().Error("EditRate and SampleRate not correct for 24/48 stereoscopic essence\n"); + DefaultLogSink().Error("EditRate and SampleRate not correct for 24/48 stereoscopic essence.\n"); return RESULT_FORMAT; } } @@ -452,7 +463,11 @@ public: } if( ASDCP_SUCCESS(result) ) - result = ReadEKLVPacket(FrameNum, FrameBuf, Dict::ul(MDD_JPEG2000Essence), Ctx, HMAC); + { + ui32_t SequenceNum = FrameNum * 2; + SequenceNum += ( phase == SP_RIGHT ) ? 2 : 1; + result = ReadEKLVPacket(FrameNum, SequenceNum, FrameBuf, Dict::ul(MDD_JPEG2000Essence), Ctx, HMAC); + } return result; } @@ -478,6 +493,23 @@ 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, @@ -489,7 +521,6 @@ ASDCP::JP2K::MXFSReader::ReadFrame(ui32_t FrameNum, StereoscopicPhase_t phase, F 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 @@ -564,6 +595,9 @@ public: 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 @@ -573,21 +607,31 @@ lh__Writer::JP2K_PDesc_to_MD(JP2K::PictureDescriptor& PDesc) assert(m_EssenceSubDescriptor); MXF::RGBAEssenceDescriptor* PDescObj = (MXF::RGBAEssenceDescriptor*)m_EssenceDescriptor; - PDescObj->SampleRate = PDesc.EditRate; PDescObj->ContainerDuration = PDesc.ContainerDuration; + PDescObj->SampleRate = PDesc.EditRate; + PDescObj->FrameLayout = 0; PDescObj->StoredWidth = PDesc.StoredWidth; PDescObj->StoredHeight = PDesc.StoredHeight; PDescObj->AspectRatio = PDesc.AspectRatio; - PDescObj->FrameLayout = 0; + + // 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 ( PDesc.StoredWidth < 2049 ) { - PDescObj->Codec.Set(Dict::ul(MDD_JP2KEssenceCompression_2K)); + PDescObj->PictureEssenceCoding.Set(Dict::ul(MDD_JP2KEssenceCompression_2K)); m_EssenceSubDescriptor->Rsize = 3; } else { - PDescObj->Codec.Set(Dict::ul(MDD_JP2KEssenceCompression_4K)); + PDescObj->PictureEssenceCoding.Set(Dict::ul(MDD_JP2KEssenceCompression_4K)); m_EssenceSubDescriptor->Rsize = 4; } @@ -718,9 +762,9 @@ lh__Writer::WriteFrame(const JP2K::FrameBuffer& FrameBuf, bool add_index, IndexTableSegment::IndexEntry Entry; Entry.StreamOffset = StreamOffset; m_FooterPart.PushIndexEntry(Entry); - m_FramesWritten++; } + m_FramesWritten++; return result; } @@ -765,14 +809,12 @@ ASDCP::JP2K::MXFWriter::OpenWrite(const char* filename, const WriterInfo& Info, const PictureDescriptor& PDesc, ui32_t HeaderSize) { m_Writer = new h__Writer; - + m_Writer->m_Info = Info; + Result_t result = m_Writer->OpenWrite(filename, ASDCP::ESS_JPEG_2000, HeaderSize); if ( ASDCP_SUCCESS(result) ) - { - m_Writer->m_Info = Info; - result = m_Writer->SetSourceStream(PDesc, JP2K_PACKAGE_LABEL); - } + result = m_Writer->SetSourceStream(PDesc, JP2K_PACKAGE_LABEL); if ( ASDCP_FAILURE(result) ) m_Writer.release(); @@ -839,6 +881,8 @@ public: if ( m_NextPhase != SP_LEFT ) return RESULT_SPHASE; + assert( m_FramesWritten % 2 == 0 ); + m_FramesWritten /= 2; return lh__Writer::Finalize(); } }; @@ -868,11 +912,15 @@ ASDCP::JP2K::MXFSWriter::OpenWrite(const char* filename, const WriterInfo& Info, 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) ) { - m_Writer->m_Info = Info; PictureDescriptor TmpPDesc = PDesc; TmpPDesc.EditRate = ASDCP::EditRate_48; @@ -885,6 +933,19 @@ ASDCP::JP2K::MXFSWriter::OpenWrite(const char* filename, const WriterInfo& Info, 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.