diff options
| author | mschroffel <mschroffel@cinecert.com> | 2016-03-17 23:58:13 +0000 |
|---|---|---|
| committer | mschroffel <> | 2016-03-17 23:58:13 +0000 |
| commit | ed84256d7687b8255991308361e26013b7071dd9 (patch) | |
| tree | 58090552a149397f61944daf6cabf7208025f915 /src | |
| parent | e10177793b42db5b9a8671dcff9e7c9cbc6a676a (diff) | |
included CMakelists.txt into dist
Diffstat (limited to 'src')
| -rw-r--r-- | src/AS_02.h | 4 | ||||
| -rw-r--r-- | src/AS_02_JP2K.cpp | 22 | ||||
| -rw-r--r-- | src/AS_02_PCM.cpp | 13 | ||||
| -rw-r--r-- | src/AS_02_TimedText.cpp | 4 | ||||
| -rwxr-xr-x | src/AS_DCP.h | 3 | ||||
| -rwxr-xr-x | src/AS_DCP_JP2K.cpp | 4 | ||||
| -rw-r--r-- | src/AS_DCP_TimedText.cpp | 9 | ||||
| -rw-r--r-- | src/KM_fileio.cpp | 32 | ||||
| -rw-r--r-- | src/MDD.cpp | 18 | ||||
| -rwxr-xr-x | src/MXF.h | 12 | ||||
| -rw-r--r-- | src/Makefile.am | 10 | ||||
| -rwxr-xr-x | src/PCMParserList.cpp | 16 | ||||
| -rwxr-xr-x | src/PCMParserList.h | 3 | ||||
| -rwxr-xr-x | src/PCM_Parser.cpp | 16 | ||||
| -rw-r--r-- | src/as-02-info.cpp | 858 | ||||
| -rwxr-xr-x | src/as-02-unwrap.cpp | 14 | ||||
| -rw-r--r-- | src/h__02_Reader.cpp | 4 |
17 files changed, 1008 insertions, 34 deletions
diff --git a/src/AS_02.h b/src/AS_02.h index 17561fd..874f686 100644 --- a/src/AS_02.h +++ b/src/AS_02.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2011-2014, Robert Scheler, Heiko Sparenberg Fraunhofer IIS, +Copyright (c) 2011-2016, Robert Scheler, Heiko Sparenberg Fraunhofer IIS, John Hurst All rights reserved. @@ -301,7 +301,7 @@ namespace AS_02 // Open the file for reading. The file must exist. Returns error if the // operation cannot be completed. - Result_t OpenRead(const std::string& filename, const ASDCP::Rational& EditRate); + Result_t OpenRead(const std::string& filename, const ASDCP::Rational& EditRate) const; // Returns RESULT_INIT if the file is not open. Result_t Close() const; diff --git a/src/AS_02_JP2K.cpp b/src/AS_02_JP2K.cpp index a2027d3..b553da3 100644 --- a/src/AS_02_JP2K.cpp +++ b/src/AS_02_JP2K.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2011-2013, Robert Scheler, Heiko Sparenberg Fraunhofer IIS, +Copyright (c) 2011-2016, Robert Scheler, Heiko Sparenberg Fraunhofer IIS, John Hurst All rights reserved. @@ -223,6 +223,26 @@ AS_02::JP2K::MXFReader::FillWriterInfo(WriterInfo& Info) const return RESULT_INIT; } +// +void +AS_02::JP2K::MXFReader::DumpHeaderMetadata(FILE* stream) const +{ + if ( m_Reader && m_Reader->m_File.IsOpen() ) + { + m_Reader->m_HeaderPart.Dump(stream); + } +} + + +// +void +AS_02::JP2K::MXFReader::DumpIndex(FILE* stream) const +{ + if ( m_Reader && m_Reader->m_File.IsOpen() ) + { + m_Reader->m_IndexAccess.Dump(stream); + } +} //------------------------------------------------------------------------------------------ diff --git a/src/AS_02_PCM.cpp b/src/AS_02_PCM.cpp index 183f424..e58690a 100644 --- a/src/AS_02_PCM.cpp +++ b/src/AS_02_PCM.cpp @@ -255,7 +255,7 @@ AS_02::PCM::MXFReader::RIP() // Open the file for reading. The file must exist. Returns error if the // operation cannot be completed. ASDCP::Result_t -AS_02::PCM::MXFReader::OpenRead(const std::string& filename, const ASDCP::Rational& edit_rate) +AS_02::PCM::MXFReader::OpenRead(const std::string& filename, const ASDCP::Rational& edit_rate) const { return m_Reader->OpenRead(filename, edit_rate); } @@ -307,16 +307,19 @@ void AS_02::PCM::MXFReader::DumpHeaderMetadata(FILE* stream) const { if ( m_Reader && m_Reader->m_File.IsOpen() ) - m_Reader->m_HeaderPart.Dump(stream); + { + m_Reader->m_HeaderPart.Dump(stream); + } } - // void AS_02::PCM::MXFReader::DumpIndex(FILE* stream) const { - if ( m_Reader->m_File.IsOpen() ) - m_Reader->m_IndexAccess.Dump(stream); + if ( m_Reader && m_Reader->m_File.IsOpen() ) + { + m_Reader->m_IndexAccess.Dump(stream); + } } diff --git a/src/AS_02_TimedText.cpp b/src/AS_02_TimedText.cpp index 5361029..c404d9b 100644 --- a/src/AS_02_TimedText.cpp +++ b/src/AS_02_TimedText.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2008-2015, John Hurst +Copyright (c) 2008-2016, John Hurst All rights reserved. Redistribution and use in source and binary forms, with or without @@ -43,7 +43,7 @@ static std::string TIMED_TEXT_DEF_LABEL = "Timed Text Track"; //------------------------------------------------------------------------------------------ -const char* +static const char* MIME2str(TimedText::MIMEType_t m) { if ( m == TimedText::MT_PNG ) diff --git a/src/AS_DCP.h b/src/AS_DCP.h index cb78dbc..75ca97f 100755 --- a/src/AS_DCP.h +++ b/src/AS_DCP.h @@ -222,6 +222,7 @@ namespace ASDCP { ESS_AS02_PCM_24b_96k, // the file contains one or more PCM audio pairs, clip wrapped ESS_AS02_TIMED_TEXT, // the file contains a TTML document and zero or more resources + ESS_ACES, // the file contains one ACES codestream ESS_MAX }; @@ -946,6 +947,8 @@ namespace ASDCP { // Reads the next sequential frame in the input file and places it in the // frame buffer. Fails if the buffer is too small or the stream is empty. Result_t ReadFrame(FrameBuffer&) const; + + Result_t Seek(ui32_t frame_number) const; }; diff --git a/src/AS_DCP_JP2K.cpp b/src/AS_DCP_JP2K.cpp index 35929c6..acb8f4e 100755 --- a/src/AS_DCP_JP2K.cpp +++ b/src/AS_DCP_JP2K.cpp @@ -42,7 +42,7 @@ 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"; -int s_exp_lookup[16] = { 0, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024,2048, 4096, 8192, 16384, 32768 }; +static int s_exp_lookup[16] = { 0, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024,2048, 4096, 8192, 16384, 32768 }; // std::ostream& @@ -296,7 +296,7 @@ ASDCP::MD_to_JP2K_PDesc(const ASDCP::MXF::GenericPictureEssenceDescriptor& Esse } else { - DefaultLogSink().Warn("Unexpected PictureComponentSizing size: %u, should be 17\n", tmp_size); + DefaultLogSink().Warn("Unexpected PictureComponentSizing size: %u, should be 17.\n", tmp_size); } // CodingStyleDefault diff --git a/src/AS_DCP_TimedText.cpp b/src/AS_DCP_TimedText.cpp index f738a59..e6f3869 100644 --- a/src/AS_DCP_TimedText.cpp +++ b/src/AS_DCP_TimedText.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2008-2015, John Hurst +Copyright (c) 2008-2016, John Hurst All rights reserved. Redistribution and use in source and binary forms, with or without @@ -43,15 +43,16 @@ static std::string TIMED_TEXT_DEF_LABEL = "Timed Text Track"; //------------------------------------------------------------------------------------------ -const char* +// +static const char* MIME2str(TimedText::MIMEType_t m) { if ( m == TimedText::MT_PNG ) return "image/png"; - else if ( m == TimedText::MT_OPENTYPE ) + else if( m == TimedText::MT_OPENTYPE ) return "application/x-font-opentype"; - + return "application/octet-stream"; } diff --git a/src/KM_fileio.cpp b/src/KM_fileio.cpp index 0e52cbe..2a217af 100644 --- a/src/KM_fileio.cpp +++ b/src/KM_fileio.cpp @@ -670,6 +670,11 @@ Kumu::GetExecutablePath(const std::string& default_path) size_t size = X_BUFSIZE; ssize_t rc = readlink("/proc/curproc/file", path, size); success = ( rc != -1 ); +#elif defined(__sun) && defined(__SVR4) + size_t size = X_BUFSIZE; + char program[MAXPATHLEN]; + snprintf(program, MAXPATHLEN, "/proc/%d/path/a.out", getpid()); + ssize_t rc = readlink(program, path, size); #else #error GetExecutablePath --> Create a method for obtaining the executable name #endif @@ -1396,6 +1401,33 @@ Kumu::DirScanner::GetNext(char* filename) } +// +Kumu::DirScannerEx::DirScannerEx() : m_Handle(0) {} + +// +Result_t +Kumu::DirScannerEx::Open(const std::string& dirname) +{ + Kumu::DefaultLogSink().Critical("Kumu::DirScannerEx unimplemented for Win32 API.\n"); + return RESULT_NOTIMPL; +} + +// +Result_t +Kumu::DirScannerEx::Close() +{ + Kumu::DefaultLogSink().Critical("Kumu::DirScannerEx unimplemented for Win32 API.\n"); + return RESULT_NOTIMPL; +} + +// +Result_t +Kumu::DirScannerEx::GetNext(std::string& next_item_name, DirectoryEntryType_t& next_item_type) +{ + Kumu::DefaultLogSink().Critical("Kumu::DirScannerEx unimplemented for Win32 API.\n"); + return RESULT_NOTIMPL; +} + #else // KM_WIN32 // POSIX directory scanner diff --git a/src/MDD.cpp b/src/MDD.cpp index d8e2ee9..7ccbf66 100644 --- a/src/MDD.cpp +++ b/src/MDD.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2006-2015, John Hurst +Copyright (c) 2006-2016, John Hurst All rights reserved. Redistribution and use in source and binary forms, with or without @@ -665,7 +665,7 @@ static const ASDCP::MDDEntry s_MDD_Table[] = { { { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x53, 0x01, 0x01, // 209 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x43, 0x00 }, {0}, false, "GenericDataEssenceDescriptor" }, - { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x05, // 210 + { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x03, // 210 0x04, 0x03, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00 }, {0x3e, 0x01}, false, "GenericDataEssenceDescriptor_DataEssenceCoding" }, { { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x53, 0x01, 0x01, // 211 @@ -1090,10 +1090,10 @@ static const ASDCP::MDDEntry s_MDD_Table[] = { {0}, false, "MaterialPackage_PackageMarker" }, { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x02, // 351 0x04, 0x01, 0x02, 0x01, 0x01, 0x03, 0x01, 0x00 }, - {0}, false, "GenericPictureEssenceDescriptor_CodingEquations" }, + {0x32, 0x1a}, false, "GenericPictureEssenceDescriptor_CodingEquations" }, { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x09, // 352 0x04, 0x01, 0x02, 0x01, 0x01, 0x06, 0x01, 0x00 }, - {0}, false, "GenericPictureEssenceDescriptor_ColorPrimaries" }, + {0x32, 0x19}, false, "GenericPictureEssenceDescriptor_ColorPrimaries" }, { { 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x0d, // 353 0x04, 0x01, 0x02, 0x02, 0x03, 0x01, 0x01, 0x11 }, {0}, false, "JP2KEssenceCompression_BroadcastProfile_1" }, @@ -1126,16 +1126,16 @@ static const ASDCP::MDDEntry s_MDD_Table[] = { {0}, false, "GenericPictureEssenceDescriptor_AlternativeCenterCuts" }, { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x0e, // 363 0x04, 0x01, 0x05, 0x01, 0x13, 0x00, 0x00, 0x00 }, - {0x32, 0x05}, true, "GenericPictureEssenceDescriptor_ActiveHeight" }, + {0}, true, "GenericPictureEssenceDescriptor_ActiveHeight" }, { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x0e, // 364 0x04, 0x01, 0x05, 0x01, 0x14, 0x00, 0x00, 0x00 }, - {0x32, 0x04}, true, "GenericPictureEssenceDescriptor_ActiveWidth" }, + {0}, true, "GenericPictureEssenceDescriptor_ActiveWidth" }, { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x0e, // 365 0x04, 0x01, 0x05, 0x01, 0x15, 0x00, 0x00, 0x00 }, - {0x32, 0x06}, true, "GenericPictureEssenceDescriptor_ActiveXOffset" }, + {0}, true, "GenericPictureEssenceDescriptor_ActiveXOffset" }, { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x0e, // 366 0x04, 0x01, 0x05, 0x01, 0x16, 0x00, 0x00, 0x00 }, - {0x32, 0x07}, true, "GenericPictureEssenceDescriptor_ActiveYOffset" }, + {0}, true, "GenericPictureEssenceDescriptor_ActiveYOffset" }, { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x0e, // 367 0x03, 0x01, 0x01, 0x02, 0x02, 0x16, 0x00, 0x00 }, {0}, false, "TimedTextDescriptor_RFC5646LanguageTagList" }, @@ -1182,11 +1182,9 @@ static const ASDCP::MDDEntry s_MDD_Table[] = { { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x05, // 379 0x0e, 0x09, 0x06, 0x07, 0x01, 0x01, 0x01, 0x06 }, {0}, false, "PHDRMetadataTrackSubDescriptor_SimplePayloadSID" }, - { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x0e, // 380 0x04, 0x01, 0x06, 0x03, 0x0e, 0x00, 0x00, 0x00 }, {0}, true, "JPEG2000PictureSubDescriptor_J2CLayout" }, - { {0}, {0}, false, 0 } }; @@ -185,7 +185,17 @@ namespace ASDCP LocalTagEntry(const TagValue& tag, ASDCP::UL& ul) : Tag(tag), UL(ul) {} bool operator<(const LocalTagEntry& rhs) const { - return ( ( Tag.a < rhs.Tag.a ) || ( Tag.b < rhs.Tag.b ) ); + if ( Tag.a < rhs.Tag.a ) + { + return true; + } + + if ( Tag.a == rhs.Tag.a && Tag.b < rhs.Tag.b ) + { + return true; + } + + return false; } inline const char* EncodeString(char* str_buf, ui32_t buf_len) const { diff --git a/src/Makefile.am b/src/Makefile.am index 2f84f6e..306d5ca 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,7 +2,7 @@ # # $Id$ # -# Copyright (c) 2007-2013 John Hurst. All rights reserved. +# Copyright (c) 2007-2016 John Hurst. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -227,7 +227,8 @@ bin_PROGRAMS = \ if USE_AS_02 bin_PROGRAMS += \ as-02-wrap \ - as-02-unwrap + as-02-unwrap \ + as-02-info endif if USE_PHDR @@ -285,6 +286,9 @@ as_02_wrap_LDADD = libas02.la libasdcp.la libkumu.la as_02_unwrap_SOURCES = as-02-unwrap.cpp as_02_unwrap_LDADD = libas02.la libasdcp.la libkumu.la + +as_02_info_SOURCES = as-02-info.cpp +as_02_info_LDADD = libas02.la libasdcp.la libkumu.la endif if USE_PHDR @@ -333,7 +337,7 @@ TESTS_ENVIRONMENT = BUILD_DIR="." TEST_FILES=../tests TEST_FILE_PREFIX=DCPd1-M1 JP2K_PREFIX=MM_2k_XYZ_ # files to include in the distribution that automake doesn't automatically include -EXTRA_DIST = fips-186-test-harness.pl $(TESTS) +EXTRA_DIST = fips-186-test-harness.pl $(TESTS) ../CMakeLists.txt if !FREEDIST if DEV_HEADERS EXTRA_DIST += $(nodist_libasdcp_la_SOURCES) $(nodist_tt_xform_SOURCES) diff --git a/src/PCMParserList.cpp b/src/PCMParserList.cpp index 0ae22cc..c073e3f 100755 --- a/src/PCMParserList.cpp +++ b/src/PCMParserList.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2004-2015, John Hurst +Copyright (c) 2004-2016, John Hurst All rights reserved. Redistribution and use in source and binary forms, with or without @@ -301,5 +301,19 @@ ASDCP::PCMParserList::ReadFrame(PCM::FrameBuffer& OutFB) } // +ASDCP::Result_t ASDCP::PCMParserList::Seek(ui32_t frame_number) +{ + Result_t result = RESULT_OK; + PCMParserList::iterator self_i; + + for( self_i = begin(); self_i != end() && ASDCP_SUCCESS(result); self_i++ ) + { + result = (*self_i)->Parser.Seek(frame_number); + } + + return result; +} + +// // end PCMParserList.cpp // diff --git a/src/PCMParserList.h b/src/PCMParserList.h index dbacd68..0af1627 100755 --- a/src/PCMParserList.h +++ b/src/PCMParserList.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2004-2013, John Hurst +Copyright (c) 2004-2016, John Hurst All rights reserved. Redistribution and use in source and binary forms, with or without @@ -78,6 +78,7 @@ namespace ASDCP Result_t FillAudioDescriptor(PCM::AudioDescriptor& ADesc) const; Result_t Reset(); Result_t ReadFrame(PCM::FrameBuffer& OutFB); + Result_t Seek(ui32_t frame_number); }; } diff --git a/src/PCM_Parser.cpp b/src/PCM_Parser.cpp index 2700aa4..072c235 100755 --- a/src/PCM_Parser.cpp +++ b/src/PCM_Parser.cpp @@ -73,6 +73,7 @@ public: void Close(); void Reset(); Result_t ReadFrame(FrameBuffer&); + Result_t Seek(ui32_t frame_number); }; @@ -196,6 +197,14 @@ ASDCP::PCM::WAVParser::h__WAVParser::ReadFrame(FrameBuffer& FB) return result; } +// +ASDCP::Result_t ASDCP::PCM::WAVParser::h__WAVParser::Seek(ui32_t frame_number) +{ + m_FramesRead = frame_number - 1; + m_ReadCount = 0; + return m_FileReader.Seek(m_DataStart + m_FrameBufferSize * frame_number); +} + //------------------------------------------------------------------------------------------ @@ -254,6 +263,13 @@ ASDCP::PCM::WAVParser::FillAudioDescriptor(AudioDescriptor& ADesc) const return RESULT_OK; } +ASDCP::Result_t ASDCP::PCM::WAVParser::Seek(ui32_t frame_number) const +{ + if ( m_Parser.empty() ) + return RESULT_INIT; + + return m_Parser->Seek(frame_number);; +} // // end PCM_Parser.cpp diff --git a/src/as-02-info.cpp b/src/as-02-info.cpp new file mode 100644 index 0000000..7c68c41 --- /dev/null +++ b/src/as-02-info.cpp @@ -0,0 +1,858 @@ +/* +Copyright (c) 2003-2016, John Hurst, Wolfgang Ruppel +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*! \file as-02-info.cpp + \version $Id$ + \brief AS-02 file metadata utility + + This program provides metadata information about an AS-02 file. + + For more information about asdcplib, please refer to the header file AS_DCP.h +*/ + +#include <KM_fileio.h> +#include <KM_log.h> +#include <AS_DCP.h> +#include <AS_02.h> +#include <JP2K.h> +#include <MXF.h> +#include <Metadata.h> +#include <cfloat> + +using namespace Kumu; +using namespace ASDCP; + +const ui32_t FRAME_BUFFER_SIZE = 4 * Kumu::Megabyte; + +//------------------------------------------------------------------------------------------ +// +// command line option parser class + +static const char* PROGRAM_NAME = "as-02-info"; // program name for messages + + +// Increment the iterator, test for an additional non-option command line argument. +// Causes the caller to return if there are no remaining arguments or if the next +// argument begins with '-'. +#define TEST_EXTRA_ARG(i,c) \ + if ( ++i >= argc || argv[(i)][0] == '-' ) { \ + fprintf(stderr, "Argument not found for option -%c.\n", (c)); \ + return; \ + } + +// +void +banner(FILE* stream = stdout) +{ + fprintf(stream, "\n\ +%s (asdcplib %s)\n\n\ +Copyright (c) 2003-2015 John Hurst\n\n\ +asdcplib may be copied only under the terms of the license found at\n\ +the top of every file in the asdcplib distribution kit.\n\n\ +Specify the -h (help) option for further information about %s\n\n", + PROGRAM_NAME, ASDCP::Version(), PROGRAM_NAME); +} + +// +void +usage(FILE* stream = stdout) +{ + fprintf(stream, "\ +USAGE:%s [-h|-help] [-V]\n\ +\n\ + %s [options] <input-file>+\n\ +\n\ +Options:\n\ + -c - Show essence coding UL\n\ + -d - Show essence descriptor info\n\ + -h | -help - Show help\n\ + -H - Show MXF header metadata\n\ + -i - Show identity info\n\ + -n - Show index\n\ + -r - Show bit-rate (Mb/s)\n\ + -t <int> - Set high-bitrate threshold (Mb/s)\n\ + -V - Show version information\n\ +\n\ + NOTES: o There is no option grouping, all options must be distinct arguments.\n\ + o All option arguments must be separated from the option by whitespace.\n\n", + PROGRAM_NAME, PROGRAM_NAME); + +} + +// +class CommandOptions +{ + CommandOptions(); + +public: + bool error_flag; // true if the given options are in error or not complete + bool version_flag; // true if the version display option was selected + bool help_flag; // true if the help display option was selected + bool verbose_flag; // true if the verbose option was selected + PathList_t filenames; // list of filenames to be processed + bool showindex_flag; // true if index is to be displayed + bool showheader_flag; // true if MXF file header is to be displayed + bool showid_flag; // if true, show file identity info (the WriterInfo struct) + bool showdescriptor_flag; // if true, show the essence descriptor + bool showcoding_flag; // if true, show the coding UL + bool showrate_flag; // if true and is image file, show bit rate + bool max_bitrate_flag; // true if -t option given + double max_bitrate; // if true and is image file, max bit rate for rate test + + // + CommandOptions(int argc, const char** argv) : + error_flag(true), version_flag(false), help_flag(false), verbose_flag(false), + showindex_flag(false), showheader_flag(false), + showid_flag(false), showdescriptor_flag(false), showcoding_flag(false), + showrate_flag(false), max_bitrate_flag(false), max_bitrate(0.0) + { + for ( int i = 1; i < argc; ++i ) + { + + if ( (strcmp( argv[i], "-help") == 0) ) + { + help_flag = true; + continue; + } + + if ( argv[i][0] == '-' + && ( isalpha(argv[i][1]) || isdigit(argv[i][1]) ) + && argv[i][2] == 0 ) + { + switch ( argv[i][1] ) + { + case 'c': showcoding_flag = true; break; + case 'd': showdescriptor_flag = true; break; + case 'H': showheader_flag = true; break; + case 'h': help_flag = true; break; + case 'i': showid_flag = true; break; + case 'n': showindex_flag = true; break; + case 'r': showrate_flag = true; break; + + case 't': + TEST_EXTRA_ARG(i, 't'); + max_bitrate = Kumu::xabs(strtol(argv[i], 0, 10)); + max_bitrate_flag = true; + break; + + case 'V': version_flag = true; break; + case 'v': verbose_flag = true; break; + + default: + fprintf(stderr, "Unrecognized option: %s\n", argv[i]); + return; + } + } + else + { + if ( argv[i][0] != '-' ) + { + filenames.push_back(argv[i]); + } + else + { + fprintf(stderr, "Unrecognized argument: %s\n", argv[i]); + return; + } + } + } + + if ( help_flag || version_flag ) + return; + + if ( filenames.empty() ) + { + fputs("At least one filename argument is required.\n", stderr); + return; + } + + error_flag = false; + } +}; + +//------------------------------------------------------------------------------------------ +// + +// +// These classes wrap the irregular names in the asdcplib API +// so that I can use a template to simplify the implementation +// of show_file_info() + +static int s_exp_lookup[16] = { 0, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024,2048, 4096, 8192, 16384, 32768 }; + +using namespace ASDCP::MXF; + +template <class ReaderType, class DescriptorType> +DescriptorType *get_descriptor_by_type(ReaderType& reader, const UL& type_ul) +{ + InterchangeObject *obj = 0; + reader.OP1aHeader().GetMDObjectByType(type_ul.Value(), &obj); + return dynamic_cast<DescriptorType*>(obj); +} + +class MyPictureDescriptor : public JP2K::PictureDescriptor +{ + RGBAEssenceDescriptor *m_RGBADescriptor; + CDCIEssenceDescriptor *m_CDCIDescriptor; + JPEG2000PictureSubDescriptor *m_JP2KSubDescriptor; + + public: + MyPictureDescriptor() : + m_RGBADescriptor(0), + m_CDCIDescriptor(0), + m_JP2KSubDescriptor(0) {} + + void FillDescriptor(AS_02::JP2K::MXFReader& Reader) + { + m_CDCIDescriptor = get_descriptor_by_type<AS_02::JP2K::MXFReader, CDCIEssenceDescriptor> + (Reader, DefaultCompositeDict().ul(MDD_CDCIEssenceDescriptor)); + + m_RGBADescriptor = get_descriptor_by_type<AS_02::JP2K::MXFReader, RGBAEssenceDescriptor> + (Reader, DefaultCompositeDict().ul(MDD_RGBAEssenceDescriptor)); + + if ( m_RGBADescriptor != 0 ) + { + SampleRate = m_RGBADescriptor->SampleRate; + ContainerDuration = m_RGBADescriptor->ContainerDuration; + } + else if ( m_CDCIDescriptor != 0 ) + { + SampleRate = m_CDCIDescriptor->SampleRate; + ContainerDuration = m_CDCIDescriptor->ContainerDuration; + } + else + { + DefaultLogSink().Error("Picture descriptor not found.\n"); + } + + m_JP2KSubDescriptor = get_descriptor_by_type<AS_02::JP2K::MXFReader, JPEG2000PictureSubDescriptor> + (Reader, DefaultCompositeDict().ul(MDD_JPEG2000PictureSubDescriptor)); + + if ( m_JP2KSubDescriptor == 0 ) + { + DefaultLogSink().Error("JPEG2000PictureSubDescriptor not found.\n"); + } + + std::list<InterchangeObject*> ObjectList; + Reader.OP1aHeader().GetMDObjectsByType(DefaultCompositeDict().ul(MDD_Track), ObjectList); + + if ( ObjectList.empty() ) + { + DefaultLogSink().Error("MXF Metadata contains no Track Sets.\n"); + } + + EditRate = ((Track*)ObjectList.front())->EditRate; + } + + void MyDump(FILE* stream) { + if ( stream == 0 ) + { + stream = stderr; + } + + if ( m_CDCIDescriptor != 0 ) + { + m_CDCIDescriptor->Dump(stream); + } + else if ( m_RGBADescriptor != 0 ) + { + m_RGBADescriptor->Dump(stream); + } + else + { + return; + } + + if ( m_JP2KSubDescriptor != 0 ) + { + m_JP2KSubDescriptor->Dump(stream); + + fprintf(stream, " ImageComponents: (max=%d)\n", JP2K::MaxComponents); + + // + ui32_t component_sizing = m_JP2KSubDescriptor->PictureComponentSizing.const_get().Length(); + JP2K::ImageComponent_t image_components[JP2K::MaxComponents]; + + if ( component_sizing == 17 ) // ( 2 * sizeof(ui32_t) ) + 3 components * 3 byte each + { + memcpy(&image_components, + m_JP2KSubDescriptor->PictureComponentSizing.const_get().RoData() + 8, + component_sizing - 8); + } + else + { + DefaultLogSink().Warn("Unexpected PictureComponentSizing size: %u, should be 17.\n", component_sizing); + } + + fprintf(stream, " bits h-sep v-sep\n"); + + for ( int i = 0; i < m_JP2KSubDescriptor->Csize && i < JP2K::MaxComponents; i++ ) + { + fprintf(stream, " %4d %5d %5d\n", + image_components[i].Ssize + 1, // See ISO 15444-1, Table A11, for the origin of '+1' + image_components[i].XRsize, + image_components[i].YRsize + ); + } + + // + JP2K::CodingStyleDefault_t coding_style_default; + + memcpy(&coding_style_default, + m_JP2KSubDescriptor->CodingStyleDefault.const_get().RoData(), + m_JP2KSubDescriptor->CodingStyleDefault.const_get().Length()); + + fprintf(stream, " Scod: %hhu\n", coding_style_default.Scod); + fprintf(stream, " ProgressionOrder: %hhu\n", coding_style_default.SGcod.ProgressionOrder); + fprintf(stream, " NumberOfLayers: %hd\n", + KM_i16_BE(Kumu::cp2i<ui16_t>(coding_style_default.SGcod.NumberOfLayers))); + + fprintf(stream, " MultiCompTransform: %hhu\n", coding_style_default.SGcod.MultiCompTransform); + fprintf(stream, "DecompositionLevels: %hhu\n", coding_style_default.SPcod.DecompositionLevels); + fprintf(stream, " CodeblockWidth: %hhu\n", coding_style_default.SPcod.CodeblockWidth); + fprintf(stream, " CodeblockHeight: %hhu\n", coding_style_default.SPcod.CodeblockHeight); + fprintf(stream, " CodeblockStyle: %hhu\n", coding_style_default.SPcod.CodeblockStyle); + fprintf(stream, " Transformation: %hhu\n", coding_style_default.SPcod.Transformation); + + ui32_t precinct_set_size = 0; + + for ( int i = 0; coding_style_default.SPcod.PrecinctSize[i] != 0 && i < JP2K::MaxPrecincts; ++i ) + { + ++precinct_set_size; + } + + fprintf(stream, " Precincts: %u\n", precinct_set_size); + fprintf(stream, "precinct dimensions:\n"); + + for ( int i = 0; i < precinct_set_size && i < JP2K::MaxPrecincts; i++ ) + fprintf(stream, " %d: %d x %d\n", i + 1, + s_exp_lookup[coding_style_default.SPcod.PrecinctSize[i]&0x0f], + s_exp_lookup[(coding_style_default.SPcod.PrecinctSize[i]>>4)&0x0f] + ); + } + } +}; + +class MyAudioDescriptor : public PCM::AudioDescriptor +{ + WaveAudioDescriptor *m_WaveAudioDescriptor; + std::list<MCALabelSubDescriptor*> m_ChannelDescriptorList; + + public: + MyAudioDescriptor() : m_WaveAudioDescriptor(0) {} + void FillDescriptor(AS_02::PCM::MXFReader& Reader) + { + m_WaveAudioDescriptor = get_descriptor_by_type<AS_02::PCM::MXFReader, WaveAudioDescriptor> + (Reader, DefaultCompositeDict().ul(MDD_WaveAudioDescriptor)); + + if ( m_WaveAudioDescriptor != 0 ) + { + AudioSamplingRate = m_WaveAudioDescriptor->SampleRate; + } + else + { + DefaultLogSink().Error("Audio descriptor not found.\n"); + } + + std::list<InterchangeObject*> object_list; + Reader.OP1aHeader().GetMDObjectsByType(DefaultCompositeDict().ul(MDD_AudioChannelLabelSubDescriptor), object_list); + Reader.OP1aHeader().GetMDObjectsByType(DefaultCompositeDict().ul(MDD_SoundfieldGroupLabelSubDescriptor), object_list); + Reader.OP1aHeader().GetMDObjectsByType(DefaultCompositeDict().ul(MDD_GroupOfSoundfieldGroupsLabelSubDescriptor), object_list); + + std::list<InterchangeObject*>::iterator i = object_list.begin(); + for ( ; i != object_list.end(); ++i ) + { + MCALabelSubDescriptor *p = dynamic_cast<MCALabelSubDescriptor*>(*i); + + if ( p ) + { + m_ChannelDescriptorList.push_back(p); + } + else + { + char buf[64]; + DefaultLogSink().Error("Audio sub-descriptor type error.\n", (**i).InstanceUID.EncodeHex(buf, 64)); + } + } + + object_list.clear(); + Reader.OP1aHeader().GetMDObjectsByType(DefaultCompositeDict().ul(MDD_Track), object_list); + + if ( object_list.empty() ) + { + DefaultLogSink().Error("MXF Metadata contains no Track Sets.\n"); + } + + EditRate = ((Track*)object_list.front())->EditRate; + } + + void MyDump(FILE* stream) { + if ( stream == 0 ) + { + stream = stderr; + } + + if ( m_WaveAudioDescriptor != 0 ) + { + m_WaveAudioDescriptor->Dump(stream); + } + + if ( ! m_ChannelDescriptorList.empty() ) + { + fprintf(stream, "Audio Channel Subdescriptors:\n"); + + std::list<MCALabelSubDescriptor*>::const_iterator i = m_ChannelDescriptorList.begin(); + for ( ; i != m_ChannelDescriptorList.end(); ++i ) + { + (**i).Dump(stream); + } + } + } +}; + +class MyTextDescriptor : public TimedText::TimedTextDescriptor +{ + public: + void FillDescriptor(TimedText::MXFReader& Reader) { + Reader.FillTimedTextDescriptor(*this); + } + + void Dump(FILE* stream) { + TimedText::DescriptorDump(*this, stream); + } +}; + +struct RateInfo +{ + UL ul; + double bitrate; + std::string label; + + RateInfo(const UL& u, const double& b, const std::string& l) { + ul = u; bitrate = b; label = l; + } + +}; + +static const double dci_max_bitrate = 250.0; +static const double p_hfr_max_bitrate = 400.0; +typedef std::map<const UL, const RateInfo> rate_info_map; +static rate_info_map g_rate_info; + +// +void +init_rate_info() +{ + UL rate_ul = DefaultCompositeDict().ul(MDD_JP2KEssenceCompression_BroadcastProfile_1); + g_rate_info.insert(rate_info_map::value_type(rate_ul, RateInfo(rate_ul, 200.0, "ISO/IEC 15444-1 Amendment 3 Level 1"))); + + rate_ul = DefaultCompositeDict().ul(MDD_JP2KEssenceCompression_BroadcastProfile_2); + g_rate_info.insert(rate_info_map::value_type(rate_ul, RateInfo(rate_ul, 200.0, "ISO/IEC 15444-1 Amendment 3 Level 2"))); + + rate_ul = DefaultCompositeDict().ul(MDD_JP2KEssenceCompression_BroadcastProfile_3); + g_rate_info.insert(rate_info_map::value_type(rate_ul, RateInfo(rate_ul, 200.0, "ISO/IEC 15444-1 Amendment 3 Level 3"))); + + rate_ul = DefaultCompositeDict().ul(MDD_JP2KEssenceCompression_BroadcastProfile_4); + g_rate_info.insert(rate_info_map::value_type(rate_ul, RateInfo(rate_ul, 400.0, "ISO/IEC 15444-1 Amendment 3 Level 4"))); + + rate_ul = DefaultCompositeDict().ul(MDD_JP2KEssenceCompression_BroadcastProfile_5); + g_rate_info.insert(rate_info_map::value_type(rate_ul, RateInfo(rate_ul, 800.0, "ISO/IEC 15444-1 Amendment 3 Level 5"))); + + rate_ul = DefaultCompositeDict().ul(MDD_JP2KEssenceCompression_BroadcastProfile_6); + g_rate_info.insert(rate_info_map::value_type(rate_ul, RateInfo(rate_ul, 1600.0, "ISO/IEC 15444-1 Amendment 3 Level 6"))); + + rate_ul = DefaultCompositeDict().ul(MDD_JP2KEssenceCompression_BroadcastProfile_7); + g_rate_info.insert(rate_info_map::value_type(rate_ul, RateInfo(rate_ul, DBL_MAX, "ISO/IEC 15444-1 Amendment 3 Level 7"))); +} + + +// +// +template<class ReaderT, class DescriptorT> +class FileInfoWrapper +{ + ReaderT m_Reader; + DescriptorT m_Desc; + WriterInfo m_WriterInfo; + double m_MaxBitrate, m_AvgBitrate; + UL m_PictureEssenceCoding; + + KM_NO_COPY_CONSTRUCT(FileInfoWrapper); + + template <class T> + Result_t OpenRead(const T& m, const CommandOptions& Options) + { + return m.OpenRead(Options.filenames.front().c_str()); + }; + Result_t OpenRead(const AS_02::PCM::MXFReader& m, const CommandOptions& Options) + { + return m.OpenRead(Options.filenames.front().c_str(), EditRate_24); + //Result_t OpenRead(const std::string& filename, const ASDCP::Rational& EditRate); + }; + +public: + FileInfoWrapper() : m_MaxBitrate(0.0), m_AvgBitrate(0.0) {} + virtual ~FileInfoWrapper() {} + + Result_t + file_info(CommandOptions& Options, const char* type_string, FILE* stream = 0) + { + assert(type_string); + if ( stream == 0 ) + { + stream = stdout; + } + + Result_t result = RESULT_OK; + result = OpenRead(m_Reader, Options); + + if ( ASDCP_SUCCESS(result) ) + { + m_Desc.FillDescriptor(m_Reader); + m_Reader.FillWriterInfo(m_WriterInfo); + + fprintf(stdout, "%s file essence type is %s, (%d edit unit%s).\n", + ( m_WriterInfo.LabelSetType == LS_MXF_SMPTE ? "SMPTE 2067-5" : "Unknown" ), + type_string, + (m_Desc.ContainerDuration != 0 ? m_Desc.ContainerDuration : m_Reader.AS02IndexReader().GetDuration()), + (m_Desc.ContainerDuration == 1 ? "":"s")); + + if ( Options.showheader_flag ) + { + m_Reader.DumpHeaderMetadata(stream); + } + + if ( Options.showid_flag ) + { + WriterInfoDump(m_WriterInfo, stream); + } + + if ( Options.showdescriptor_flag ) + { + m_Desc.MyDump(stream); + } + + if ( Options.showindex_flag ) + { + m_Reader.DumpIndex(stream); + } + } + else if ( result == RESULT_FORMAT && Options.showheader_flag ) + { + m_Reader.DumpHeaderMetadata(stream); + } + + return result; + } + + // + void get_PictureEssenceCoding(FILE* stream = 0) + { + const Dictionary& Dict = DefaultCompositeDict(); + MXF::RGBAEssenceDescriptor *rgba_descriptor = 0; + MXF::CDCIEssenceDescriptor *cdci_descriptor = 0; + + Result_t result = m_Reader.OP1aHeader().GetMDObjectByType(DefaultCompositeDict().ul(MDD_RGBAEssenceDescriptor), + reinterpret_cast<MXF::InterchangeObject**>(&rgba_descriptor)); + + if ( KM_SUCCESS(result) && rgba_descriptor) + m_PictureEssenceCoding = rgba_descriptor->PictureEssenceCoding; + else{ + result = m_Reader.OP1aHeader().GetMDObjectByType(DefaultCompositeDict().ul(MDD_CDCIEssenceDescriptor), + reinterpret_cast<MXF::InterchangeObject**>(&cdci_descriptor)); + if ( KM_SUCCESS(result) && cdci_descriptor) + m_PictureEssenceCoding = cdci_descriptor->PictureEssenceCoding; + } + } + + + // + void dump_PictureEssenceCoding(FILE* stream = 0) + { + char buf[64]; + + if ( m_PictureEssenceCoding.HasValue() ) + { + std::string encoding_ul_type = "**UNKNOWN**"; + + rate_info_map::const_iterator rate_i = g_rate_info.find(m_PictureEssenceCoding); + if ( rate_i == g_rate_info.end() ) + { + fprintf(stderr, "Unknown PictureEssenceCoding UL: %s\n", m_PictureEssenceCoding.EncodeString(buf, 64)); + } + else + { + encoding_ul_type = rate_i->second.label; + } + + fprintf(stream, "PictureEssenceCoding: %s (%s)\n", + m_PictureEssenceCoding.EncodeString(buf, 64), + encoding_ul_type.c_str()); + } + } + + // + Result_t + test_rates(CommandOptions& Options, FILE* stream = 0) + { + double max_bitrate = 0; //Options.max_bitrate_flag ? Options.max_bitrate : dci_max_bitrate; + ui32_t errors = 0; + char buf[64]; + + rate_info_map::const_iterator rate_i = g_rate_info.find(m_PictureEssenceCoding); + if ( rate_i == g_rate_info.end() ) + { + fprintf(stderr, "Unknown PictureEssenceCoding UL: %s\n", m_PictureEssenceCoding.EncodeString(buf, 64)); + } + else + { + max_bitrate = rate_i->second.bitrate; + } + + max_bitrate = Options.max_bitrate_flag ? Options.max_bitrate : max_bitrate; + + if ( m_MaxBitrate > max_bitrate ) + { + fprintf(stream, "Bitrate %0.0f Mb/s exceeds maximum %0.0f Mb/s\n", m_MaxBitrate, max_bitrate); + ++errors; + } + + return errors ? RESULT_FAIL : RESULT_OK; + } + + // + void + calc_Bitrate(FILE* stream = 0) + { + //MXF::OP1aHeader& footer = m_Reader.OP1aHeader(); + AS_02::MXF::AS02IndexReader& footer = m_Reader.AS02IndexReader(); + ui64_t total_frame_bytes = 0, last_stream_offset = 0; + ui32_t largest_frame = 0; + Result_t result = RESULT_OK; + ui64_t duration = 0; + + if ( m_Desc.EditRate.Numerator == 0 || m_Desc.EditRate.Denominator == 0 ) + { + fprintf(stderr, "Broken edit rate, unable to calculate essence bitrate.\n"); + return; + } + + duration = m_Desc.ContainerDuration; + if ( duration == 0 ) + { + fprintf(stderr, "ContainerDuration not set in file descriptor, attempting to use index duration.\n"); + duration = m_Reader.AS02IndexReader().GetDuration(); + } + + for ( ui32_t i = 0; KM_SUCCESS(result) && i < duration; ++i ) + { + MXF::IndexTableSegment::IndexEntry entry; + result = footer.Lookup(i, entry); + + if ( KM_SUCCESS(result) ) + { + if ( last_stream_offset != 0 ) + { + ui64_t this_frame_size = entry.StreamOffset - last_stream_offset - 20; // do not count the bytes that represent the KLV wrapping + total_frame_bytes += this_frame_size; + + if ( this_frame_size > largest_frame ) + largest_frame = this_frame_size; + } + + last_stream_offset = entry.StreamOffset; + } + } + + if ( KM_SUCCESS(result) ) + { + // scale bytes to megabits + static const double mega_const = 1.0 / ( 1000000 / 8.0 ); + + // we did not accumulate the last, so duration -= 1 + double avg_bytes_frame = total_frame_bytes / ( duration - 1 ); + + m_MaxBitrate = largest_frame * mega_const * m_Desc.EditRate.Quotient(); + m_AvgBitrate = avg_bytes_frame * mega_const * m_Desc.EditRate.Quotient(); + } + } + + // + void + dump_Bitrate(FILE* stream = 0) + { + fprintf(stream, "Max BitRate: %0.2f Mb/s\n", m_MaxBitrate); + fprintf(stream, "Average BitRate: %0.2f Mb/s\n", m_AvgBitrate); + } + + // + void dump_WaveAudioDescriptor(FILE* stream = 0) + { + const Dictionary& Dict = DefaultCompositeDict(); + MXF::WaveAudioDescriptor *descriptor = 0; + + Result_t result = m_Reader.OP1aHeader().GetMDObjectByType(DefaultCompositeDict().ul(MDD_WaveAudioDescriptor), + reinterpret_cast<MXF::InterchangeObject**>(&descriptor)); + + if ( KM_SUCCESS(result) ) + { + char buf[64]; + fprintf(stream, "ChannelAssignment: %s\n", descriptor->ChannelAssignment.const_get().EncodeString(buf, 64)); + } + } + +}; + + +// Read header metadata from an ASDCP file +// +Result_t +show_file_info(CommandOptions& Options) +{ + EssenceType_t EssenceType; + Result_t result = ASDCP::EssenceType(Options.filenames.front().c_str(), EssenceType); + + if ( ASDCP_FAILURE(result) ) + return result; + + if ( EssenceType == ESS_AS02_JPEG_2000 ) + { + FileInfoWrapper<AS_02::JP2K::MXFReader, MyPictureDescriptor> wrapper; + result = wrapper.file_info(Options, "JPEG 2000 pictures"); + + if ( KM_SUCCESS(result) ) + { + wrapper.get_PictureEssenceCoding(); + wrapper.calc_Bitrate(stdout); + + if ( Options.showcoding_flag ) + { + wrapper.dump_PictureEssenceCoding(stdout); + } + + if ( Options.showrate_flag ) + { + wrapper.dump_Bitrate(stdout); + } + + result = wrapper.test_rates(Options, stdout); + } + } + + else if ( EssenceType == ESS_AS02_PCM_24b_48k || EssenceType == ESS_AS02_PCM_24b_96k ) + { + FileInfoWrapper<AS_02::PCM::MXFReader, MyAudioDescriptor> wrapper; + result = wrapper.file_info(Options, "PCM audio"); + + if ( ASDCP_SUCCESS(result) && Options.showcoding_flag ) + wrapper.dump_WaveAudioDescriptor(stdout); + } + else + { + fprintf(stderr, "Unknown/unsupported essence type: %s\n", Options.filenames.front().c_str()); + Kumu::FileReader Reader; + const Dictionary* Dict = &DefaultCompositeDict(); + MXF::OP1aHeader TestHeader(Dict); + + result = Reader.OpenRead(Options.filenames.front().c_str()); + + if ( ASDCP_SUCCESS(result) ) + result = TestHeader.InitFromFile(Reader); // test UL and OP + + if ( ASDCP_SUCCESS(result) ) + { + TestHeader.Partition::Dump(stdout); + + if ( MXF::Identification* ID = TestHeader.GetIdentification() ) + ID->Dump(stdout); + else + fputs("File contains no Identification object.\n", stdout); + + if ( MXF::SourcePackage* SP = TestHeader.GetSourcePackage() ) + SP->Dump(stdout); + else + fputs("File contains no SourcePackage object.\n", stdout); + } + else + { + fputs("File is not MXF.\n", stdout); + } + } + + return result; +} + +// +int +main(int argc, const char** argv) +{ + Result_t result = RESULT_OK; + char str_buf[64]; + CommandOptions Options(argc, argv); + + if ( Options.version_flag ) + banner(); + + if ( Options.help_flag ) + usage(); + + if ( Options.version_flag || Options.help_flag ) + return 0; + + if ( Options.error_flag ) + { + fprintf(stderr, "There was a problem. Type %s -h for help.\n", PROGRAM_NAME); + return 3; + } + + init_rate_info(); + + while ( ! Options.filenames.empty() && ASDCP_SUCCESS(result) ) + { + result = show_file_info(Options); + Options.filenames.pop_front(); + } + + if ( ASDCP_FAILURE(result) ) + { + fputs("Program stopped on error.\n", stderr); + + if ( result != RESULT_FAIL ) + { + fputs(result, stderr); + fputc('\n', stderr); + } + + return 1; + } + + return 0; +} + + +// +// end as-02-info.cpp +// diff --git a/src/as-02-unwrap.cpp b/src/as-02-unwrap.cpp index 688656b..43fe12f 100755 --- a/src/as-02-unwrap.cpp +++ b/src/as-02-unwrap.cpp @@ -473,6 +473,20 @@ read_PCM_file(CommandOptions& Options) if ( last_frame == 0 ) { + fprintf(stderr, "ContainerDuration not set in index, attempting to use Duration from SourceClip.\n"); + result = Reader.OP1aHeader().GetMDObjectByType(DefaultCompositeDict().ul(MDD_SourceClip), &tmp_obj); + if ( KM_SUCCESS(result)) + { + ASDCP::MXF::SourceClip *sourceClip = dynamic_cast<ASDCP::MXF::SourceClip*>(tmp_obj); + if ( ! sourceClip->Duration.empty() ) + { + last_frame = sourceClip->Duration; + } + } + } + + if ( last_frame == 0 ) + { fprintf(stderr, "Unable to determine file duration.\n"); return RESULT_FAIL; } diff --git a/src/h__02_Reader.cpp b/src/h__02_Reader.cpp index a81d1ae..45825f0 100644 --- a/src/h__02_Reader.cpp +++ b/src/h__02_Reader.cpp @@ -228,8 +228,8 @@ AS_02::MXF::AS02IndexReader::InitFromFile(const Kumu::FileReader& reader, const fprintf(stderr, " EditUnitByteCount = %u\n", segment->EditUnitByteCount); fprintf(stderr, " IndexSID = %u\n", segment->IndexSID); fprintf(stderr, " BodySID = %u\n", segment->BodySID); - fprintf(stderr, " SliceCount = %hu\n", segment->SliceCount); - fprintf(stderr, " PosTableCount = %hu\n", segment->PosTableCount); + fprintf(stderr, " SliceCount = %hhu\n", segment->SliceCount); + fprintf(stderr, " PosTableCount = %hhu\n", segment->PosTableCount); fprintf(stderr, " RtFileOffset = %s\n", i64sz(segment->RtFileOffset, identbuf)); fprintf(stderr, " RtEntryOffset = %s\n", i64sz(segment->RtEntryOffset, identbuf)); fprintf(stderr, " IndexEntryArray:\n"); |
