diff options
| author | jhurst <jhurst@cinecert.com> | 2007-10-20 19:43:18 +0000 |
|---|---|---|
| committer | jhurst <> | 2007-10-20 19:43:18 +0000 |
| commit | 70bbc088b0b8f079c41b07141bec35447be469c5 (patch) | |
| tree | e49dfeead6921dd637608ee40cbaca8d25c80448 /src | |
| parent | f457a7ea8fa446b71e7802a20f575ae5bcc9926b (diff) | |
3-D love
Diffstat (limited to 'src')
| -rwxr-xr-x | src/AS_DCP.h | 249 | ||||
| -rwxr-xr-x | src/AS_DCP_JP2K.cpp | 273 | ||||
| -rwxr-xr-x | src/AS_DCP_MXF.cpp | 7 | ||||
| -rw-r--r-- | src/AS_DCP_TimedText.cpp | 1 | ||||
| -rwxr-xr-x | src/JP2K.cpp | 4 | ||||
| -rwxr-xr-x | src/JP2K.h | 2 | ||||
| -rwxr-xr-x | src/JP2K_Codestream_Parser.cpp | 27 | ||||
| -rwxr-xr-x | src/KM_util.cpp | 41 | ||||
| -rw-r--r-- | src/MDD.cpp | 5 | ||||
| -rwxr-xr-x | src/MDD.h | 1 | ||||
| -rw-r--r-- | src/TimedText_Parser.cpp | 1 | ||||
| -rwxr-xr-x | src/asdcp-test.cpp | 180 |
12 files changed, 656 insertions, 135 deletions
diff --git a/src/AS_DCP.h b/src/AS_DCP.h index 9878c81..5f75521 100755 --- a/src/AS_DCP.h +++ b/src/AS_DCP.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2003-2006, John Hurst +Copyright (c) 2003-2007, John Hurst All rights reserved. Redistribution and use in source and binary forms, with or without @@ -41,7 +41,7 @@ may not be limited to: o SMPTE 429-4-2006 JPEG 2000 for D-Cinema o SMPTE 429-5-200X Timed Text Track File o SMPTE 429-6-2006 Essence Encryption Specification - o SMPTE 429-10-2006 Stereoscopic Image Track File + o SMPTE 429-10-200X Stereoscopic Image Track File o SMPTE 330M - UMID o SMPTE 336M - KLV o SMPTE 377M - MXF @@ -65,6 +65,11 @@ The following use cases are supported by the library: o Read one or more plaintext JPEG 2000 codestreams from a plaintext ASDCP file o Read one or more plaintext JPEG 2000 codestreams from a ciphertext ASDCP file o Read one or more ciphertext JPEG 2000 codestreams from a ciphertext ASDCP file + o Write one or more plaintext JPEG 2000 stereoscopic codestream pairs to a plaintext ASDCP file + o Write one or more plaintext JPEG 2000 stereoscopic codestream pairs to a ciphertext ASDCP file + o Read one or more plaintext JPEG 2000 stereoscopic codestream pairs from a plaintext ASDCP file + o Read one or more plaintext JPEG 2000 stereoscopic codestream pairs from a ciphertext ASDCP file + o Read one or more ciphertext JPEG 2000 stereoscopic codestream pairs from a ciphertext ASDCP file o Write one or more plaintext PCM audio streams to a plaintext ASDCP file o Write one or more plaintext PCM audio streams to a ciphertext ASDCP file o Read one or more plaintext PCM audio streams from a plaintext ASDCP file @@ -86,6 +91,7 @@ This project depends upon the following library: #include <math.h> #include <iostream> #include <string> +#include <list> //-------------------------------------------------------------------------------- // common integer types @@ -196,6 +202,7 @@ namespace ASDCP { const Kumu::Result_t RESULT_EMPTY_FB (-112, "Empty frame buffer."); const Kumu::Result_t RESULT_KLV_CODING (-113, "KLV coding error."); const Kumu::Result_t RESULT_SPHASE (-114, "Stereoscopic phase mismatch."); + const Kumu::Result_t RESULT_SFORMAT (-115, "Rate mismatch, file may contain stereoscopic essence."); //--------------------------------------------------------------------------------- // file identification @@ -899,15 +906,47 @@ namespace ASDCP { namespace JP2K { const ui32_t MaxComponents = 3; - const ui32_t DefaultCodingDataLength = 64; + const ui32_t MaxPrecincts = 32; // ISO 15444-1 Annex A.6.1 + const ui32_t MaxDefaults = 256; // made up - struct ImageComponent +#pragma pack(1) + struct ImageComponent_t // ISO 15444-1 Annex A.5.1 { - byte_t Ssize; - byte_t XRsize; - byte_t YRsize; + ui8_t Ssize; + ui8_t XRsize; + ui8_t YRsize; }; + struct CodingStyleDefault_t // ISO 15444-1 Annex A.6.1 + { + ui8_t Scod; + + struct + { + ui8_t ProgressionOrder; + ui8_t NumberOfLayers[sizeof(ui16_t)]; + ui8_t MultiCompTransform; + } SGcod; + + struct + { + ui8_t DecompositionLevels; + ui8_t CodeblockWidth; + ui8_t CodeblockHeight; + ui8_t CodeblockStyle; + ui8_t Transformation; + ui8_t PrecinctSize[MaxPrecincts]; + } SPcod; + }; + + struct QuantizationDefault_t // ISO 15444-1 Annex A.6.4 + { + ui8_t Sqcd; + ui8_t SPqcd[MaxDefaults]; + ui8_t SPqcdLength; + }; +#pragma pack() + struct PictureDescriptor { Rational EditRate; @@ -926,11 +965,9 @@ namespace ASDCP { ui32_t XTOsize; ui32_t YTOsize; ui16_t Csize; - ImageComponent ImageComponents[MaxComponents]; - byte_t CodingStyle[DefaultCodingDataLength]; - ui32_t CodingStyleLength; - byte_t QuantDefault[DefaultCodingDataLength]; - ui32_t QuantDefaultLength; + ImageComponent_t ImageComponents[MaxComponents]; + CodingStyleDefault_t CodingStyleDefault; + QuantizationDefault_t QuantizationDefault; }; // Print debugging information to stream (stderr default) @@ -1161,6 +1198,194 @@ namespace ASDCP { void DumpIndex(FILE* = 0) const; }; } // namespace JP2K + + // + namespace TimedText + { + enum MIMEType_t { MT_BIN, MT_PNG, MT_OPENTYPE }; + + struct TimedTextResourceDescriptor + { + byte_t ResourceID[UUIDlen]; + MIMEType_t Type; + + TimedTextResourceDescriptor() : Type(MT_BIN) {} + }; + + typedef std::list<TimedTextResourceDescriptor> ResourceList_t; + + struct TimedTextDescriptor + { + Rational EditRate; // + ui32_t ContainerDuration; + byte_t AssetID[UUIDlen]; + std::string NamespaceName; + std::string EncodingName; + ResourceList_t ResourceList; + + TimedTextDescriptor() : ContainerDuration(0), EncodingName("UTF-8") {} // D-Cinema format is always UTF-8 + }; + + // Print debugging information to stream (stderr default) + void DescriptorDump(const TimedTextDescriptor&, FILE* = 0); + + // + class FrameBuffer : public ASDCP::FrameBuffer + { + ASDCP_NO_COPY_CONSTRUCT(FrameBuffer); // TODO: should have copy construct + + protected: + byte_t m_AssetID[UUIDlen]; + std::string m_MIMEType; + + public: + FrameBuffer() { memset(m_AssetID, 0, UUIDlen); } + FrameBuffer(ui32_t size) { Capacity(size); memset(m_AssetID, 0, UUIDlen); } + virtual ~FrameBuffer() {} + + inline const byte_t* AssetID() const { return m_AssetID; } + inline void AssetID(const byte_t* buf) { memcpy(m_AssetID, buf, UUIDlen); } + inline const char* MIMEType() const { return m_MIMEType.c_str(); } + inline void MIMEType(const std::string& s) { m_MIMEType = s; } + + // Print debugging information to stream (stderr default) + void Dump(FILE* = 0, ui32_t dump_bytes = 0) const; + }; + + // + class IResourceResolver + { + public: + virtual ~IResourceResolver() {} + virtual Result_t ResolveRID(const byte_t* uuid, FrameBuffer&) const = 0; // return data for RID + }; + + // + class DCSubtitleParser + { + class h__SubtitleParser; + mem_ptr<h__SubtitleParser> m_Parser; + ASDCP_NO_COPY_CONSTRUCT(DCSubtitleParser); + + public: + DCSubtitleParser(); + virtual ~DCSubtitleParser(); + + // Opens the XML file for reading, parse data to provide a complete + // set of stream metadata for the MXFWriter below. + Result_t OpenRead(const char* filename) const; + + // Fill a TimedTextDescriptor struct with the values from the file's contents. + // Returns RESULT_INIT if the file is not open. + Result_t FillDescriptor(TimedTextDescriptor&) const; + + // Reads the complete Timed Text Resource into the given string. + Result_t ReadTimedTextResource(std::string&) const; + + // Reads the Ancillary Resource having the given ID. Fails if the buffer + // is too small or the resource does not exist. The optional Resolver + // argument can be provided which will be used to retrieve the resource + // having a particulat UUID. If a Resolver is not supplied, the default + // internal resolver will return the contents of the file having the UUID + // as the filename. The filename must exist in the same directory as the + // XML file opened with OpenRead(). + Result_t ReadAncillaryResource(const byte_t* uuid, FrameBuffer&, + const IResourceResolver* Resolver = 0) const; + }; + + // + class MXFWriter + { + class h__Writer; + mem_ptr<h__Writer> m_Writer; + ASDCP_NO_COPY_CONSTRUCT(MXFWriter); + + public: + MXFWriter(); + virtual ~MXFWriter(); + + // Open the file for writing. The file must not exist. Returns error if + // the operation cannot be completed or if nonsensical data is discovered + // in the essence descriptor. + Result_t OpenWrite(const char* filename, const WriterInfo&, + const TimedTextDescriptor&, ui32_t HeaderSize = 16384); + + // Writes the Timed-Text Resource to the MXF file. The file must be UTF-8 + // encoded. 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. + // This method may only be called once, and it must be called before any + // call to WriteAncillaryResource(). RESULT_STATE will be returned if these + // conditions are not met. + Result_t WriteTimedTextResource(const std::string& XMLDoc, AESEncContext* = 0, HMACContext* = 0); + + // Writes an Ancillary Resource 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. RESULT_STATE will be returned if the method is called before + // WriteTimedTextResource() + Result_t WriteAncillaryResource(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0); + + // Closes the MXF file, writing the index and revised header. + Result_t Finalize(); + }; + + // + class MXFReader + { + class h__Reader; + mem_ptr<h__Reader> m_Reader; + ASDCP_NO_COPY_CONSTRUCT(MXFReader); + + public: + MXFReader(); + virtual ~MXFReader(); + + // Open the file for reading. The file must exist. Returns error if the + // operation cannot be completed. + Result_t OpenRead(const char* filename) const; + + // Returns RESULT_INIT if the file is not open. + Result_t Close() const; + + // Fill a TimedTextDescriptor struct with the values from the file's header. + // Returns RESULT_INIT if the file is not open. + Result_t FillDescriptor(TimedTextDescriptor&) const; + + // Fill a WriterInfo struct with the values from the file's header. + // Returns RESULT_INIT if the file is not open. + Result_t FillWriterInfo(WriterInfo&) const; + + // Reads the complete Timed Text Resource into the given string. Fails if the resource + // is encrypted and AESDecContext is NULL (use the following method to retrieve the + // raw ciphertet block). + Result_t ReadTimedTextResource(std::string&, AESDecContext* = 0, HMACContext* = 0) const; + + // Reads the complete Timed Text Resource from the MXF file. If the optional AESEncContext + // argument is present, the resource is decrypted after reading. If the MXF + // file is encrypted and the AESDecContext argument is NULL, the frame buffer + // will contain the ciphertext frame data. If the HMACContext argument is + // not NULL, the HMAC will be calculated (if the file supports it). + // Returns RESULT_INIT if the file is not open, failure if the frame number is + // out of range, or if optional decrypt or HAMC operations fail. + Result_t ReadTimedTextResource(FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const; + + // Reads the timed-text resource having the given UUID from the MXF file. If the + // optional AESEncContext argument is present, the resource is decrypted after + // reading. If the MXF file is encrypted and the AESDecContext argument is NULL, + // the frame buffer will contain the ciphertext frame data. If the HMACContext + // argument is not NULL, the HMAC will be calculated (if the file supports it). + // Returns RESULT_INIT if the file is not open, failure if the frame number is + // out of range, or if optional decrypt or HAMC operations fail. + Result_t ReadAncillaryResource(const byte_t* uuid, FrameBuffer&, AESDecContext* = 0, HMACContext* = 0) const; + + // Print debugging information to stream + void DumpHeaderMetadata(FILE* = 0) const; + void DumpIndex(FILE* = 0) const; + }; + } // namespace TimedText + + } // namespace ASDCP diff --git a/src/AS_DCP_JP2K.cpp b/src/AS_DCP_JP2K.cpp index a0e8463..b3c4663 100755 --- a/src/AS_DCP_JP2K.cpp +++ b/src/AS_DCP_JP2K.cpp @@ -31,6 +31,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "AS_DCP_internal.h" +using namespace ASDCP::JP2K; + //------------------------------------------------------------------------------------------ @@ -38,6 +40,14 @@ static std::string JP2K_PACKAGE_LABEL = "File Package: SMPTE 429-4 frame wrappin static std::string JP2K_S_PACKAGE_LABEL = "File Package: SMPTE 429-10 frame wrapping of stereoscopic JPEG 2000 codestreams"; static std::string PICT_DEF_LABEL = "Picture Track"; + +//22 + +// 7f18 7f00 7f00 7ebc 76ea 76ea 76bc 6f4c 6f4c 6f64 5803 5803 5845 5fd2 5fd2 5f61 + + +int s_exp_lookup[16] = { 0, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024,2048, 4096, 8192, 16384, 32768 }; + // void ASDCP::JP2K::PictureDescriptorDump(const PictureDescriptor& PDesc, FILE* stream) @@ -60,8 +70,8 @@ ASDCP::JP2K::PictureDescriptorDump(const PictureDescriptor& PDesc, FILE* stream) XTOsize: %u\n\ YTOsize: %u\n\ ContainerDuration: %u\n", - PDesc.AspectRatio.Numerator ,PDesc.AspectRatio.Denominator, - PDesc.EditRate.Numerator ,PDesc.EditRate.Denominator, + PDesc.AspectRatio.Numerator, PDesc.AspectRatio.Denominator, + PDesc.EditRate.Numerator, PDesc.EditRate.Denominator, PDesc.StoredWidth, PDesc.StoredHeight, PDesc.Rsize, @@ -76,61 +86,85 @@ ASDCP::JP2K::PictureDescriptorDump(const PictureDescriptor& PDesc, FILE* stream) PDesc.ContainerDuration ); - fprintf(stream, "Color Components:\n"); + fprintf(stream, "-- JPEG 2000 Metadata --\n"); + fprintf(stream, " ImageComponents:\n"); + fprintf(stream, " bits h-sep v-sep\n"); for ( ui32_t i = 0; i < PDesc.Csize; i++ ) { - fprintf(stream, " %u.%u.%u\n", - PDesc.ImageComponents[i].Ssize, + fprintf(stream, " %4d %5d %5d\n", + PDesc.ImageComponents[i].Ssize + 1, // See ISO 15444-1, Table A11, for the origin of '+1' PDesc.ImageComponents[i].XRsize, PDesc.ImageComponents[i].YRsize ); } + + fprintf(stream, " Scod: %hd\n", PDesc.CodingStyleDefault.Scod); + fprintf(stream, " ProgressionOrder: %hd\n", PDesc.CodingStyleDefault.SGcod.ProgressionOrder); + fprintf(stream, " NumberOfLayers: %hd\n", + KM_i16_BE(Kumu::cp2i<ui16_t>(PDesc.CodingStyleDefault.SGcod.NumberOfLayers))); - const ui32_t tmp_buf_len = 256; - char tmp_buf[tmp_buf_len]; + fprintf(stream, " MultiCompTransform: %hd\n", PDesc.CodingStyleDefault.SGcod.MultiCompTransform); + fprintf(stream, "DecompositionLevels: %hd\n", PDesc.CodingStyleDefault.SPcod.DecompositionLevels); + fprintf(stream, " CodeblockWidth: %hd\n", PDesc.CodingStyleDefault.SPcod.CodeblockWidth); + fprintf(stream, " CodeblockHeight: %hd\n", PDesc.CodingStyleDefault.SPcod.CodeblockHeight); + fprintf(stream, " CodeblockStyle: %hd\n", PDesc.CodingStyleDefault.SPcod.CodeblockStyle); + fprintf(stream, " Transformation: %hd\n", PDesc.CodingStyleDefault.SPcod.Transformation); - if ( PDesc.CodingStyleLength ) - fprintf(stream, "Default Coding (%u): %s\n", - PDesc.CodingStyleLength, - Kumu::bin2hex(PDesc.CodingStyle, PDesc.CodingStyleLength, tmp_buf, tmp_buf_len) - ); - if ( PDesc.QuantDefaultLength ) - fprintf(stream, "Quantization Default (%u): %s\n", - PDesc.QuantDefaultLength, - Kumu::bin2hex(PDesc.QuantDefault, PDesc.QuantDefaultLength, tmp_buf, tmp_buf_len) + ui32_t precinct_set_size = 0, i; + + for ( i = 0; PDesc.CodingStyleDefault.SPcod.PrecinctSize[i] != 0 && i < MaxPrecincts; i++ ) + precinct_set_size++; + + fprintf(stream, " Precincts: %hd\n", precinct_set_size); + fprintf(stream, "precinct dimensions:\n"); + + for ( i = 0; i < precinct_set_size; i++ ) + fprintf(stream, " %d: %d x %d\n", i + 1, + s_exp_lookup[PDesc.CodingStyleDefault.SPcod.PrecinctSize[i]&0x0f], + s_exp_lookup[(PDesc.CodingStyleDefault.SPcod.PrecinctSize[i]>>4)&0x0f] ); + + fprintf(stream, " Sqcd: %hd\n", PDesc.QuantizationDefault.Sqcd); + + char tmp_buf[MaxDefaults*2]; + fprintf(stream, " SPqcd: %s\n", + Kumu::bin2hex(PDesc.QuantizationDefault.SPqcd, PDesc.QuantizationDefault.SPqcdLength, + tmp_buf, MaxDefaults*2) + ); } //------------------------------------------------------------------------------------------ // // hidden, internal implementation of JPEG 2000 reader -class ASDCP::JP2K::MXFReader::h__Reader : public ASDCP::h__Reader +class lh__Reader : public ASDCP::h__Reader { RGBAEssenceDescriptor* m_EssenceDescriptor; JPEG2000PictureSubDescriptor* m_EssenceSubDescriptor; + ASDCP::Rational m_EditRate; + EssenceType_t m_Format; - ASDCP_NO_COPY_CONSTRUCT(h__Reader); + ASDCP_NO_COPY_CONSTRUCT(lh__Reader); public: PictureDescriptor m_PDesc; // codestream parameter list - h__Reader() : m_EssenceDescriptor(0), m_EssenceSubDescriptor(0) {} - Result_t OpenRead(const char*); - Result_t ReadFrame(ui32_t, FrameBuffer&, AESDecContext*, HMACContext*); + lh__Reader() : 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 -ASDCP::JP2K::MXFReader::h__Reader::MD_to_JP2K_PDesc(JP2K::PictureDescriptor& PDesc) +lh__Reader::MD_to_JP2K_PDesc(JP2K::PictureDescriptor& PDesc) { memset(&PDesc, 0, sizeof(PDesc)); MXF::RGBAEssenceDescriptor* PDescObj = (MXF::RGBAEssenceDescriptor*)m_EssenceDescriptor; - PDesc.EditRate = PDescObj->SampleRate; + PDesc.EditRate = m_EditRate; PDesc.ContainerDuration = PDescObj->ContainerDuration; PDesc.StoredWidth = PDescObj->StoredWidth; PDesc.StoredHeight = PDescObj->StoredHeight; @@ -159,12 +193,18 @@ ASDCP::JP2K::MXFReader::h__Reader::MD_to_JP2K_PDesc(JP2K::PictureDescriptor& PDe DefaultLogSink().Error("Unexpected PictureComponentSizing size: %u, should be 17\n", tmp_size); // CodingStyleDefault - if ( ( PDesc.CodingStyleLength = m_EssenceSubDescriptor->CodingStyleDefault.Length() ) != 0 ) - memcpy(PDesc.CodingStyle, m_EssenceSubDescriptor->CodingStyleDefault.RoData(), PDesc.CodingStyleLength); + memset(&m_PDesc.CodingStyleDefault, 0, sizeof(CodingStyleDefault_t)); + memcpy(&m_PDesc.CodingStyleDefault, + m_EssenceSubDescriptor->CodingStyleDefault.RoData(), + m_EssenceSubDescriptor->CodingStyleDefault.Length()); // QuantizationDefault - if ( ( PDesc.QuantDefaultLength = m_EssenceSubDescriptor->QuantizationDefault.Length() ) != 0 ) - memcpy(PDesc.QuantDefault, m_EssenceSubDescriptor->QuantizationDefault.RoData(), PDesc.QuantDefaultLength); + 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; } return RESULT_OK; @@ -173,16 +213,49 @@ ASDCP::JP2K::MXFReader::h__Reader::MD_to_JP2K_PDesc(JP2K::PictureDescriptor& PDe // // ASDCP::Result_t -ASDCP::JP2K::MXFReader::h__Reader::OpenRead(const char* filename) +lh__Reader::OpenRead(const char* filename, EssenceType_t type) { Result_t result = OpenMXFRead(filename); if( ASDCP_SUCCESS(result) ) { - if ( m_EssenceDescriptor == 0 ) + m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(RGBAEssenceDescriptor), + (InterchangeObject**)&m_EssenceDescriptor); + m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(JPEG2000PictureSubDescriptor), + (InterchangeObject**)&m_EssenceSubDescriptor); + + std::list<InterchangeObject*> ObjectList; + m_HeaderPart.GetMDObjectsByType(OBJ_TYPE_ARGS(Track), ObjectList); + + if ( ObjectList.empty() ) + { + DefaultLogSink().Error("MXF Metadata contains no Track Sets\n"); + return RESULT_FORMAT; + } + + m_EditRate = ((Track*)ObjectList.front())->EditRate; + + if ( type == ASDCP::ESS_JPEG_2000 ) { - m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(RGBAEssenceDescriptor), (InterchangeObject**)&m_EssenceDescriptor); - m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(JPEG2000PictureSubDescriptor), (InterchangeObject**)&m_EssenceSubDescriptor); + if ( m_EditRate != m_EssenceDescriptor->SampleRate ) + { + DefaultLogSink().Error("EditRate and SampleRate do not match (%.03f, %.03f)\n", + m_EditRate.Quotient(), m_EssenceDescriptor->SampleRate.Quotient()); + return RESULT_SFORMAT; + } + } + 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"); + return RESULT_FORMAT; + } + } + else + { + DefaultLogSink().Error("'type' argument unexpected: %x\n", type); + return RESULT_STATE; } result = MD_to_JP2K_PDesc(m_PDesc); @@ -200,8 +273,8 @@ ASDCP::JP2K::MXFReader::h__Reader::OpenRead(const char* filename) // // ASDCP::Result_t -ASDCP::JP2K::MXFReader::h__Reader::ReadFrame(ui32_t FrameNum, FrameBuffer& FrameBuf, - AESDecContext* Ctx, HMACContext* HMAC) +lh__Reader::ReadFrame(ui32_t FrameNum, JP2K::FrameBuffer& FrameBuf, + AESDecContext* Ctx, HMACContext* HMAC) { if ( ! m_File.IsOpen() ) return RESULT_INIT; @@ -209,6 +282,14 @@ ASDCP::JP2K::MXFReader::h__Reader::ReadFrame(ui32_t FrameNum, FrameBuffer& Frame return ReadEKLVFrame(FrameNum, FrameBuf, Dict::ul(MDD_JPEG2000Essence), Ctx, HMAC); } + +// +class ASDCP::JP2K::MXFReader::h__Reader : public lh__Reader +{ +}; + + + //------------------------------------------------------------------------------------------ @@ -245,7 +326,7 @@ ASDCP::JP2K::MXFReader::~MXFReader() ASDCP::Result_t ASDCP::JP2K::MXFReader::OpenRead(const char* filename) const { - return m_Reader->OpenRead(filename); + return m_Reader->OpenRead(filename, ASDCP::ESS_JPEG_2000); } // @@ -309,8 +390,101 @@ ASDCP::JP2K::MXFReader::DumpIndex(FILE* stream) const //------------------------------------------------------------------------------------------ +class ASDCP::JP2K::MXFSReader::h__SReader : public lh__Reader +{ + StereoscopicPhase_t m_NextPhase; + +public: + h__SReader() : m_NextPhase(SP_LEFT) {} + + // + Result_t ReadFrame(ui32_t FrameNum, StereoscopicPhase_t phase, FrameBuffer& FrameBuf, + AESDecContext* Ctx, HMACContext* HMAC) const + { + return Kumu::RESULT_NOTIMPL; + } +}; + + + +ASDCP::JP2K::MXFSReader::MXFSReader() +{ + m_Reader = new h__SReader; +} + + +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, 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; +} + +// +void +ASDCP::JP2K::MXFSReader::DumpHeaderMetadata(FILE* stream) const +{ + if ( m_Reader->m_File.IsOpen() ) + m_Reader->m_HeaderPart.Dump(stream); +} + + +// +void +ASDCP::JP2K::MXFSReader::DumpIndex(FILE* stream) const +{ + if ( m_Reader->m_File.IsOpen() ) + m_Reader->m_FooterPart.Dump(stream); +} + +//------------------------------------------------------------------------------------------ -using namespace ASDCP::JP2K; // class lh__Writer : public ASDCP::h__Writer @@ -374,21 +548,28 @@ lh__Writer::JP2K_PDesc_to_MD(JP2K::PictureDescriptor& PDesc) m_EssenceSubDescriptor->YTOsize = PDesc.YTOsize; m_EssenceSubDescriptor->Csize = PDesc.Csize; - const ui32_t tmp_buffer_len = 64; + const ui32_t tmp_buffer_len = 1024; byte_t tmp_buffer[tmp_buffer_len]; - *(ui32_t*)tmp_buffer = KM_i32_BE(3L); // three components - *(ui32_t*)(tmp_buffer+4) = KM_i32_BE(3L); - memcpy(tmp_buffer + 8, &PDesc.ImageComponents, sizeof(ASDCP::JP2K::ImageComponent) * 3L); + *(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); - memcpy(m_EssenceSubDescriptor->PictureComponentSizing.Data(), tmp_buffer, 17); - m_EssenceSubDescriptor->PictureComponentSizing.Length(17); + ui32_t precinct_set_size = 0, i; + for ( i = 0; PDesc.CodingStyleDefault.SPcod.PrecinctSize[i] != 0 && i < MaxPrecincts; i++ ) + precinct_set_size++; - memcpy(m_EssenceSubDescriptor->CodingStyleDefault.Data(), PDesc.CodingStyle, PDesc.CodingStyleLength); - m_EssenceSubDescriptor->CodingStyleDefault.Length(PDesc.CodingStyleLength); + 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); - memcpy(m_EssenceSubDescriptor->QuantizationDefault.Data(), PDesc.QuantDefault, PDesc.QuantDefaultLength); - m_EssenceSubDescriptor->QuantizationDefault.Length(PDesc.QuantDefaultLength); + 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; } @@ -432,7 +613,7 @@ lh__Writer::SetSourceStream(const PictureDescriptor& PDesc, const std::string& l return RESULT_STATE; if ( LocalEditRate == ASDCP::Rational(0,0) ) - LocalEditRate = m_PDesc.EditRate; + LocalEditRate = PDesc.EditRate; m_PDesc = PDesc; Result_t result = JP2K_PDesc_to_MD(m_PDesc); diff --git a/src/AS_DCP_MXF.cpp b/src/AS_DCP_MXF.cpp index 5afd293..1d4f473 100755 --- a/src/AS_DCP_MXF.cpp +++ b/src/AS_DCP_MXF.cpp @@ -148,7 +148,12 @@ ASDCP::EssenceType(const char* filename, EssenceType_t& type) { type = ESS_UNKNOWN; if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(RGBAEssenceDescriptor))) ) - type = ESS_JPEG_2000; + { + if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(StereoscopicPictureSubDescriptor))) ) + type = ESS_JPEG_2000_S; + else + type = ESS_JPEG_2000; + } else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(WaveAudioDescriptor))) ) type = ESS_PCM_24b_48k; else if ( ASDCP_SUCCESS(TestHeader.GetMDObjectByType(OBJ_TYPE_ARGS(MPEG2VideoDescriptor))) ) diff --git a/src/AS_DCP_TimedText.cpp b/src/AS_DCP_TimedText.cpp index 7f434a7..ff68e62 100644 --- a/src/AS_DCP_TimedText.cpp +++ b/src/AS_DCP_TimedText.cpp @@ -31,7 +31,6 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "AS_DCP_internal.h" -#include "AS_DCP_TimedText.h" #include "KM_xml.h" static std::string TIMED_TEXT_PACKAGE_LABEL = "File Package: SMPTE 429-5 frame wrapping of D-Cinema Timed Text data"; diff --git a/src/JP2K.cpp b/src/JP2K.cpp index 14789f1..3dd073f 100755 --- a/src/JP2K.cpp +++ b/src/JP2K.cpp @@ -102,7 +102,7 @@ ASDCP::JP2K::GetNextMarker(const byte_t** buf, JP2K::Marker& Marker) // void -ASDCP::JP2K::Accessor::SIZ::ReadComponent(ui32_t index, ASDCP::JP2K::ImageComponent& IC) +ASDCP::JP2K::Accessor::SIZ::ReadComponent(ui32_t index, ASDCP::JP2K::ImageComponent_t& IC) { assert ( index < Csize() ); const byte_t* p = m_MarkerData + 36 + (index * 3); @@ -136,7 +136,7 @@ ASDCP::JP2K::Accessor::SIZ::Dump(FILE* stream) for ( ui32_t i = 0; i < Csize(); i++ ) { - ImageComponent TmpComp; + ImageComponent_t TmpComp; ReadComponent(i, TmpComp); fprintf(stream, "%u: ", i); fprintf(stream, "%u, %u, %u\n", TmpComp.Ssize, TmpComp.XRsize, TmpComp.YRsize); @@ -123,7 +123,7 @@ namespace JP2K inline ui32_t XTOsize() { return KM_i32_BE(*(ui32_t*)(m_MarkerData + 26)); } inline ui32_t YTOsize() { return KM_i32_BE(*(ui32_t*)(m_MarkerData + 30)); } inline ui16_t Csize() { return KM_i16_BE(*(ui16_t*)(m_MarkerData + 34)); } - void ReadComponent(ui32_t index, ImageComponent& IC); + void ReadComponent(ui32_t index, ImageComponent_t& IC); void Dump(FILE* stream = 0); }; diff --git a/src/JP2K_Codestream_Parser.cpp b/src/JP2K_Codestream_Parser.cpp index 32a5316..f4596a8 100755 --- a/src/JP2K_Codestream_Parser.cpp +++ b/src/JP2K_Codestream_Parser.cpp @@ -96,10 +96,6 @@ public: result = RESULT_RAW_ESS; break; } -#if 0 - fprintf(stderr, "%s Length: %u\n", - GetMarkerString(NextMarker.m_Type), NextMarker.m_DataSize); -#endif switch ( NextMarker.m_Type ) { @@ -137,25 +133,34 @@ public: break; case MRK_COD: - if ( NextMarker.m_DataSize > DefaultCodingDataLength ) + memset(&m_PDesc.CodingStyleDefault, 0, sizeof(CodingStyleDefault_t)); + + if ( NextMarker.m_DataSize > sizeof(CodingStyleDefault_t) ) { DefaultLogSink().Error("Unexpectedly large CodingStyle data: %u\n", NextMarker.m_DataSize); return RESULT_RAW_FORMAT; } - m_PDesc.CodingStyleLength = NextMarker.m_DataSize; - memcpy(m_PDesc.CodingStyle, NextMarker.m_Data, m_PDesc.CodingStyleLength); + memcpy(&m_PDesc.CodingStyleDefault, NextMarker.m_Data, NextMarker.m_DataSize); break; case MRK_QCD: - if ( NextMarker.m_DataSize > DefaultCodingDataLength ) + memset(&m_PDesc.QuantizationDefault, 0, sizeof(QuantizationDefault_t)); + + if ( NextMarker.m_DataSize < 16 ) + { + DefaultLogSink().Error("No quantization signaled\n"); + return RESULT_RAW_FORMAT; + } + + if ( NextMarker.m_DataSize > MaxDefaults ) { - DefaultLogSink().Error("Unexpectedly large QuantDefault data: %u\n", NextMarker.m_DataSize); + DefaultLogSink().Error("Quantization Default length exceeds maximum %d\n", NextMarker.m_DataSize); return RESULT_RAW_FORMAT; } - m_PDesc.QuantDefaultLength = NextMarker.m_DataSize; - memcpy(m_PDesc.QuantDefault, NextMarker.m_Data, m_PDesc.QuantDefaultLength); + memcpy(&m_PDesc.QuantizationDefault, NextMarker.m_Data, NextMarker.m_DataSize); + m_PDesc.QuantizationDefault.SPqcdLength = NextMarker.m_DataSize - 1; break; } } diff --git a/src/KM_util.cpp b/src/KM_util.cpp index 6dd3d33..f9a88cd 100755 --- a/src/KM_util.cpp +++ b/src/KM_util.cpp @@ -849,6 +849,7 @@ Kumu::Timestamp::DecodeString(const char* datestr) || ! ( isdigit(datestr[8]) && isdigit(datestr[9]) ) ) return false; + ui32_t char_count = 10; TmpStamp.Year = atoi(datestr); TmpStamp.Month = atoi(datestr + 5); TmpStamp.Day = atoi(datestr + 8); @@ -861,6 +862,7 @@ Kumu::Timestamp::DecodeString(const char* datestr) || ! ( isdigit(datestr[14]) && isdigit(datestr[15]) ) ) return false; + char_count += 6; TmpStamp.Hour = atoi(datestr + 11); TmpStamp.Minute = atoi(datestr + 14); @@ -869,28 +871,37 @@ Kumu::Timestamp::DecodeString(const char* datestr) if ( ! ( isdigit(datestr[17]) && isdigit(datestr[18]) ) ) return false; + char_count += 3; TmpStamp.Second = atoi(datestr + 17); } - } - if ( datestr[19] == '-' || datestr[19] == '+' ) - { - if ( ! ( isdigit(datestr[20]) && isdigit(datestr[21]) ) - || datestr[22] != ':' - || ! ( isdigit(datestr[23]) && isdigit(datestr[24]) ) ) - return false; + if ( datestr[19] == '-' || datestr[19] == '+' ) + { + if ( ! ( isdigit(datestr[20]) && isdigit(datestr[21]) ) + || datestr[22] != ':' + || ! ( isdigit(datestr[23]) && isdigit(datestr[24]) ) ) + return false; - ui32_t TZ_hh = atoi(datestr + 20); - ui32_t TZ_mm = atoi(datestr + 23); + char_count += 6; + ui32_t TZ_hh = atoi(datestr + 20); + ui32_t TZ_mm = atoi(datestr + 23); - if ( TZ_mm != 0 ) - DefaultLogSink().Error("Ignoring minutes in timezone offset: %u\n", TZ_mm); + if ( TZ_mm != 0 ) + DefaultLogSink().Warn("Ignoring minutes in timezone offset: %u\n", TZ_mm); + + if ( TZ_hh > 12 ) + return false; - if ( TZ_hh > 12 ) - return false; + else + AddHours( (datestr[19] == '-' ? (-TZ_hh) : TZ_hh)); + } + } - else - AddHours( (datestr[19] == '-' ? (-TZ_hh) : TZ_hh)); + if ( datestr[char_count] != 0 ) + { + DefaultLogSink().Error("Unexpected extra characters in string: %s (%ld)\n", + datestr, char_count); + return false; } #ifdef KM_WIN32 diff --git a/src/MDD.cpp b/src/MDD.cpp index 0b50796..2c8353b 100644 --- a/src/MDD.cpp +++ b/src/MDD.cpp @@ -840,10 +840,13 @@ static const ASDCP::MDDEntry s_MDD_Table[] = { { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x02, // 268 0x01, 0x07, 0x01, 0x05, 0x00, 0x00, 0x00, 0x00 }, {0x61, 0x02}, false, "DMSegment_TrackIDList" }, + { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x02, // 269 + 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00 }, + {0x61, 0x02}, false, "StereoscopicPictureSubDescriptor" }, { {0}, {0}, false, 0 } }; -const ui32_t s_MDD_Table_size = 269; +const ui32_t s_MDD_Table_size = 270; // // end MDD.cpp @@ -304,6 +304,7 @@ namespace ASDCP { MDD_DMSegment_DataDefinition, // 266 MDD_DMSegment_Duration, // 267 MDD_DMSegment_TrackIDList, // 268 + MDD_StereoscopicPictureSubDescriptor, // 269 }; // enum MDD_t } // namespaceASDCP diff --git a/src/TimedText_Parser.cpp b/src/TimedText_Parser.cpp index 156c1ab..8595b31 100644 --- a/src/TimedText_Parser.cpp +++ b/src/TimedText_Parser.cpp @@ -31,7 +31,6 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "AS_DCP_internal.h" -#include "AS_DCP_TimedText.h" #include "S12MTimecode.h" #include "KM_xml.h" diff --git a/src/asdcp-test.cpp b/src/asdcp-test.cpp index ba83858..b7dd356 100755 --- a/src/asdcp-test.cpp +++ b/src/asdcp-test.cpp @@ -56,11 +56,6 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <WavFileWriter.h> #include <MXF.h> #include <Metadata.h> - -#ifdef ASDCP_WITH_TIMED_TEXT -#include <AS_DCP_TimedText.h> -#endif - #include <openssl/sha.h> using namespace ASDCP; @@ -707,8 +702,6 @@ write_JP2K_S_file(CommandOptions& Options) byte_t IV_buf[CBC_BLOCK_SIZE]; Kumu::FortunaRNG RNG; - fprintf(stderr, "Hello, stereoscopic world!\n"); - if ( Options.file_count != 2 ) { fprintf(stderr, "Two inputs are required for stereoscopic option.\n"); @@ -823,6 +816,100 @@ write_JP2K_S_file(CommandOptions& Options) return result; } +// Read one or more plaintext JPEG 2000 stereoscopic codestream pairs from a plaintext ASDCP file +// Read one or more plaintext JPEG 2000 stereoscopic codestream pairs from a ciphertext ASDCP file +// Read one or more ciphertext JPEG 2000 stereoscopic codestream pairs from a ciphertext ASDCP file +Result_t +read_JP2K_S_file(CommandOptions& Options) +{ + AESDecContext* Context = 0; + HMACContext* HMAC = 0; + JP2K::MXFSReader Reader; + JP2K::FrameBuffer FrameBuffer(Options.fb_size); + ui32_t frame_count = 0; + + Result_t result = Reader.OpenRead(Options.filenames[0]); + + if ( ASDCP_SUCCESS(result) ) + { + JP2K::PictureDescriptor PDesc; + Reader.FillPictureDescriptor(PDesc); + + frame_count = PDesc.ContainerDuration; + + if ( Options.verbose_flag ) + { + fprintf(stderr, "Frame Buffer size: %u\n", Options.fb_size); + JP2K::PictureDescriptorDump(PDesc); + } + } + + if ( ASDCP_SUCCESS(result) && Options.key_flag ) + { + Context = new AESDecContext; + result = Context->InitKey(Options.key_value); + + if ( ASDCP_SUCCESS(result) && Options.read_hmac ) + { + WriterInfo Info; + Reader.FillWriterInfo(Info); + + if ( Info.UsesHMAC ) + { + HMAC = new HMACContext; + result = HMAC->InitKey(Options.key_value, Info.LabelSetType); + } + else + { + fputs("File does not contain HMAC values, ignoring -m option.\n", stderr); + } + } + } + + const int filename_max = 1024; + char filename[filename_max]; + ui32_t last_frame = Options.start_frame + ( Options.duration ? Options.duration : frame_count); + if ( last_frame > frame_count ) + last_frame = frame_count; + + for ( ui32_t i = Options.start_frame; ASDCP_SUCCESS(result) && i < last_frame; i++ ) + { + result = Reader.ReadFrame(i, JP2K::SP_LEFT, FrameBuffer, Context, HMAC); + + if ( ASDCP_SUCCESS(result) ) + { + Kumu::FileWriter OutFile; + ui32_t write_count; + snprintf(filename, filename_max, "%s%06uL.j2c", Options.file_root, i); + result = OutFile.OpenWrite(filename); + + if ( ASDCP_SUCCESS(result) ) + result = OutFile.Write(FrameBuffer.Data(), FrameBuffer.Size(), &write_count); + + if ( Options.verbose_flag ) + FrameBuffer.Dump(stderr, Options.fb_dump_size); + } + + if ( ASDCP_SUCCESS(result) ) + result = Reader.ReadFrame(i, JP2K::SP_RIGHT, FrameBuffer, Context, HMAC); + + if ( ASDCP_SUCCESS(result) ) + { + Kumu::FileWriter OutFile; + ui32_t write_count; + snprintf(filename, filename_max, "%s%06uR.j2c", Options.file_root, i); + result = OutFile.OpenWrite(filename); + + if ( ASDCP_SUCCESS(result) ) + result = OutFile.Write(FrameBuffer.Data(), FrameBuffer.Size(), &write_count); + } + } + + return result; +} + + + // Write one or more plaintext JPEG 2000 codestreams to a plaintext ASDCP file // Write one or more plaintext JPEG 2000 codestreams to a ciphertext ASDCP file // @@ -1240,8 +1327,6 @@ read_PCM_file(CommandOptions& Options) } -#ifdef ASDCP_WITH_TIMED_TEXT - //------------------------------------------------------------------------------------------ // TimedText essence @@ -1433,7 +1518,6 @@ read_timed_text_file(CommandOptions& Options) return result; } -#endif // ASDCP_WITH_TIMED_TEXT //------------------------------------------------------------------------------------------ // @@ -1467,6 +1551,18 @@ class MyPictureDescriptor : public JP2K::PictureDescriptor } }; +class MyStereoPictureDescriptor : public JP2K::PictureDescriptor +{ + public: + void FillDescriptor(JP2K::MXFSReader& Reader) { + Reader.FillPictureDescriptor(*this); + } + + void Dump(FILE* stream) { + JP2K::PictureDescriptorDump(*this, stream); + } +}; + class MyAudioDescriptor : public PCM::AudioDescriptor { public: @@ -1479,7 +1575,6 @@ class MyAudioDescriptor : public PCM::AudioDescriptor } }; -#ifdef ASDCP_WITH_TIMED_TEXT class MyTextDescriptor : public TimedText::TimedTextDescriptor { public: @@ -1491,15 +1586,16 @@ class MyTextDescriptor : public TimedText::TimedTextDescriptor TimedText::DescriptorDump(*this, stream); } }; -#endif // MSVC didn't like the function template, so now it's a static class method template<class ReaderT, class DescriptorT> class FileInfoWrapper { public: - static void file_info(CommandOptions& Options, FILE* stream = 0) + static void + file_info(CommandOptions& Options, const char* type_string, FILE* stream = 0) { + assert(type_string); if ( stream == 0 ) stream = stdout; @@ -1510,6 +1606,8 @@ public: if ( ASDCP_SUCCESS(result) ) { + fprintf(stdout, "File essence type is %s.\n", type_string); + if ( Options.showheader_flag ) Reader.DumpHeaderMetadata(stream); @@ -1544,32 +1642,28 @@ show_file_info(CommandOptions& Options) return result; if ( EssenceType == ESS_MPEG2_VES ) - { - fputs("File essence type is MPEG2 video.\n", stdout); - FileInfoWrapper<ASDCP::MPEG2::MXFReader, MyVideoDescriptor>::file_info(Options); - } + FileInfoWrapper<ASDCP::MPEG2::MXFReader, MyVideoDescriptor>::file_info(Options, "MPEG2 video"); + else if ( EssenceType == ESS_PCM_24b_48k ) - { - fputs("File essence type is PCM audio.\n", stdout); - FileInfoWrapper<ASDCP::PCM::MXFReader, MyAudioDescriptor>::file_info(Options); - } + FileInfoWrapper<ASDCP::PCM::MXFReader, MyAudioDescriptor>::file_info(Options, "PCM audio"); + else if ( EssenceType == ESS_JPEG_2000 ) { - fputs("File essence type is JPEG 2000 pictures.\n", stdout); - FileInfoWrapper<ASDCP::JP2K::MXFReader, MyPictureDescriptor>::file_info(Options); + if ( Options.stereo_image_flag ) + FileInfoWrapper<ASDCP::JP2K::MXFSReader, + MyStereoPictureDescriptor>::file_info(Options, "JPEG 2000 stereoscopic pictures"); + + else + FileInfoWrapper<ASDCP::JP2K::MXFReader, + MyPictureDescriptor>::file_info(Options, "JPEG 2000 pictures"); } else if ( EssenceType == ESS_JPEG_2000_S ) - { - fputs("File essence type is JPEG 2000 stereoscopic pictures.\n", stdout); - FileInfoWrapper<ASDCP::JP2K::MXFReader, MyPictureDescriptor>::file_info(Options); - } -#ifdef ASDCP_WITH_TIMED_TEXT + FileInfoWrapper<ASDCP::JP2K::MXFSReader, + MyStereoPictureDescriptor>::file_info(Options, "JPEG 2000 stereoscopic pictures"); + else if ( EssenceType == ESS_TIMED_TEXT ) - { - fputs("File essence type is Timed Text.\n", stdout); - FileInfoWrapper<ASDCP::TimedText::MXFReader, MyTextDescriptor>::file_info(Options); - } -#endif + FileInfoWrapper<ASDCP::TimedText::MXFReader, MyTextDescriptor>::file_info(Options, "Timed Text"); + else { fprintf(stderr, "File is not AS-DCP: %s\n", Options.filenames[0]); @@ -1712,7 +1806,14 @@ main(int argc, const char** argv) break; case ESS_JPEG_2000: - result = read_JP2K_file(Options); + if ( Options.stereo_image_flag ) + result = read_JP2K_S_file(Options); + else + result = read_JP2K_file(Options); + break; + + case ESS_JPEG_2000_S: + result = read_JP2K_S_file(Options); break; case ESS_PCM_24b_48k: @@ -1720,13 +1821,9 @@ main(int argc, const char** argv) break; case ESS_TIMED_TEXT: -#ifdef ASDCP_WITH_TIMED_TEXT result = read_timed_text_file(Options); break; -#else - fprintf(stderr, "asdcplib compiled without timed text support.\n"); - return 7; -#endif + default: fprintf(stderr, "%s: Unknown file type, not ASDCP essence.\n", Options.filenames[0]); return 5; @@ -1766,13 +1863,8 @@ main(int argc, const char** argv) break; case ESS_TIMED_TEXT: -#ifdef ASDCP_WITH_TIMED_TEXT result = write_timed_text_file(Options); break; -#else - fprintf(stderr, "asdcplib compiled without timed text support.\n"); - return 7; -#endif default: fprintf(stderr, "%s: Unknown file type, not ASDCP-compatible essence.\n", |
