diff options
| author | mschroffel <mschroffel@cinecert.com> | 2014-08-07 19:14:00 +0000 |
|---|---|---|
| committer | mschroffel <> | 2014-08-07 19:14:00 +0000 |
| commit | 8d24b6effb0377fc3041c2e024e7c5593caecc52 (patch) | |
| tree | 7d07981e634d09698933c680a1d55b5bbc2db8b0 /src/PHDR_Sequence_Parser.cpp | |
| parent | 7f3035721a09a68106454a53be4fe7f967543195 (diff) | |
version bump
Diffstat (limited to 'src/PHDR_Sequence_Parser.cpp')
| -rwxr-xr-x | src/PHDR_Sequence_Parser.cpp | 405 |
1 files changed, 405 insertions, 0 deletions
diff --git a/src/PHDR_Sequence_Parser.cpp b/src/PHDR_Sequence_Parser.cpp new file mode 100755 index 0000000..47d7fde --- /dev/null +++ b/src/PHDR_Sequence_Parser.cpp @@ -0,0 +1,405 @@ +/* +Copyright (c) 2004-2014, John Hurst +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 PHDR_Sequence_Parser.cpp + \version $Id$ + \brief AS-DCP library, JPEG 2000 codestream essence reader implementation +*/ + +#include <AS_02_PHDR.h> +#include <KM_fileio.h> +#include <KM_log.h> +#include <list> +#include <string> +#include <algorithm> +#include <string.h> +#include <assert.h> + +using namespace Kumu; +using namespace ASDCP; + + +//------------------------------------------------------------------------------------------ + +class FileList : public std::list<std::string> +{ + std::string m_DirName; + +public: + FileList() {} + ~FileList() {} + + const FileList& operator=(const std::list<std::string>& pathlist) { + std::list<std::string>::const_iterator i; + for ( i = pathlist.begin(); i != pathlist.end(); i++ ) + push_back(*i); + return *this; + } + + // + Result_t InitFromDirectory(const std::string& path) + { + char next_file[Kumu::MaxFilePath]; + Kumu::DirScanner Scanner; + + Result_t result = Scanner.Open(path); + + if ( ASDCP_SUCCESS(result) ) + { + m_DirName = path; + + while ( ASDCP_SUCCESS(Scanner.GetNext(next_file)) ) + { + if ( PathGetExtension(next_file) == "j2c" ) + { + std::string path = PathJoin(m_DirName, next_file); + + if ( ! Kumu::PathIsDirectory(path) ) + push_back(path); + } + } + + sort(); + } + + return result; + } +}; + +//------------------------------------------------------------------------------------------ + +class AS_02::PHDR::SequenceParser::h__SequenceParser +{ + ui32_t m_FramesRead; + Rational m_PictureRate; + FileList m_FileList; + FileList::iterator m_CurrentFile; + ASDCP::JP2K::CodestreamParser m_Parser; + bool m_Pedantic; + + Result_t OpenRead(); + + ASDCP_NO_COPY_CONSTRUCT(h__SequenceParser); + +public: + ASDCP::JP2K::PictureDescriptor m_PDesc; + + h__SequenceParser() : m_FramesRead(0), m_Pedantic(false) + { + memset(&m_PDesc, 0, sizeof(m_PDesc)); + m_PDesc.EditRate = Rational(24,1); + } + + ~h__SequenceParser() + { + Close(); + } + + Result_t OpenRead(const std::string& filename, bool pedantic); + Result_t OpenRead(const std::list<std::string>& file_list, bool pedantic); + void Close() {} + + Result_t Reset() + { + m_FramesRead = 0; + m_CurrentFile = m_FileList.begin(); + return RESULT_OK; + } + + Result_t ReadFrame(FrameBuffer&); +}; + + +// +ASDCP::Result_t +AS_02::PHDR::SequenceParser::h__SequenceParser::OpenRead() +{ + if ( m_FileList.empty() ) + return RESULT_ENDOFFILE; + + m_CurrentFile = m_FileList.begin(); + ASDCP::JP2K::CodestreamParser Parser; + AS_02::PHDR::FrameBuffer TmpBuffer; + + Kumu::fsize_t file_size = Kumu::FileSize(*m_CurrentFile); + + if ( file_size == 0 ) + return RESULT_NOT_FOUND; + + assert(file_size <= 0xFFFFFFFFL); + Result_t result = TmpBuffer.Capacity((ui32_t) file_size); + + if ( ASDCP_SUCCESS(result) ) + result = Parser.OpenReadFrame(*m_CurrentFile, TmpBuffer); + + if ( ASDCP_SUCCESS(result) ) + result = Parser.FillPictureDescriptor(m_PDesc); + + // how big is it? + if ( ASDCP_SUCCESS(result) ) + m_PDesc.ContainerDuration = m_FileList.size(); + + return result; +} + +// +ASDCP::Result_t +AS_02::PHDR::SequenceParser::h__SequenceParser::OpenRead(const std::string& filename, bool pedantic) +{ + m_Pedantic = pedantic; + + Result_t result = m_FileList.InitFromDirectory(filename); + + if ( ASDCP_SUCCESS(result) ) + result = OpenRead(); + + return result; +} + + +// +ASDCP::Result_t +AS_02::PHDR::SequenceParser::h__SequenceParser::OpenRead(const std::list<std::string>& file_list, bool pedantic) +{ + m_Pedantic = pedantic; + m_FileList = file_list; + return OpenRead(); +} + + +// +bool +operator==(const ASDCP::JP2K::ImageComponent_t& lhs, const ASDCP::JP2K::ImageComponent_t& rhs) +{ + if ( lhs.Ssize != rhs.Ssize ) return false; + if ( lhs.XRsize != rhs.XRsize ) return false; + if ( lhs.YRsize != rhs.YRsize ) return false; + return true; +} + +// +bool +operator==(const ASDCP::JP2K::QuantizationDefault_t& lhs, const ASDCP::JP2K::QuantizationDefault_t& rhs) +{ + if ( lhs.Sqcd != rhs.Sqcd ) return false; + if ( lhs.SPqcdLength != rhs.SPqcdLength ) return false; + + for ( ui32_t i = 0; i < JP2K::MaxDefaults; i++ ) + { + if ( lhs.SPqcd[i] != rhs.SPqcd[i] ) + return false; + } + + return true; +} + +// +bool +operator==(const ASDCP::JP2K::CodingStyleDefault_t& lhs, const ASDCP::JP2K::CodingStyleDefault_t& rhs) +{ + if ( lhs.Scod != rhs.Scod ) return false; + + // SGcod + if ( lhs.SGcod.ProgressionOrder != rhs.SGcod.ProgressionOrder ) return false; + if ( lhs.SGcod.MultiCompTransform != rhs.SGcod.MultiCompTransform ) return false; + + for ( ui32_t i = 0; i < sizeof(ui16_t); i++ ) + { + if ( lhs.SGcod.NumberOfLayers[i] != lhs.SGcod.NumberOfLayers[i] ) + return false; + } + + // SPcod + if ( lhs.SPcod.DecompositionLevels != rhs.SPcod.DecompositionLevels ) return false; + if ( lhs.SPcod.CodeblockWidth != rhs.SPcod.CodeblockWidth ) return false; + if ( lhs.SPcod.CodeblockHeight != rhs.SPcod.CodeblockHeight ) return false; + if ( lhs.SPcod.CodeblockStyle != rhs.SPcod.CodeblockStyle ) return false; + if ( lhs.SPcod.Transformation != rhs.SPcod.Transformation ) return false; + + for ( ui32_t i = 0; i < JP2K::MaxPrecincts; i++ ) + { + if ( lhs.SPcod.PrecinctSize[i] != rhs.SPcod.PrecinctSize[i] ) + return false; + } + + return true; +} + +// +bool +operator==(const ASDCP::JP2K::PictureDescriptor& lhs, const ASDCP::JP2K::PictureDescriptor& rhs) +{ + if ( lhs.EditRate != rhs.EditRate ) return false; + // if ( lhs.ContainerDuration != rhs.ContainerDuration ) return false; + if ( lhs.SampleRate != rhs.SampleRate ) return false; + if ( lhs.StoredWidth != rhs.StoredWidth ) return false; + if ( lhs.StoredHeight != rhs.StoredHeight ) return false; + if ( lhs.AspectRatio != rhs.AspectRatio ) return false; + if ( lhs.Rsize != rhs.Rsize ) return false; + if ( lhs.Xsize != rhs.Xsize ) return false; + if ( lhs.Ysize != rhs.Ysize ) return false; + if ( lhs.XOsize != rhs.XOsize ) return false; + if ( lhs.YOsize != rhs.YOsize ) return false; + if ( lhs.XTsize != rhs.XTsize ) return false; + if ( lhs.YTsize != rhs.YTsize ) return false; + if ( lhs.XTOsize != rhs.XTOsize ) return false; + if ( lhs.YTOsize != rhs.YTOsize ) return false; + if ( lhs.Csize != rhs.Csize ) return false; + if ( ! ( lhs.CodingStyleDefault == rhs.CodingStyleDefault ) ) return false; + if ( ! ( lhs.QuantizationDefault == rhs.QuantizationDefault ) ) return false; + + for ( ui32_t i = 0; i < JP2K::MaxComponents; i++ ) + { + if ( ! ( lhs.ImageComponents[i] == rhs.ImageComponents[i] ) ) + return false; + } + + return true; +} + +// +ASDCP::Result_t +AS_02::PHDR::SequenceParser::h__SequenceParser::ReadFrame(FrameBuffer& FB) +{ + if ( m_CurrentFile == m_FileList.end() ) + return RESULT_ENDOFFILE; + + // open the file + Result_t result = m_Parser.OpenReadFrame(*m_CurrentFile, FB); + std::string metadata_path = PathJoin(PathDirname(*m_CurrentFile), PathSetExtension(*m_CurrentFile, "xml")); + + if ( KM_SUCCESS(result) ) + { + result = ReadFileIntoString(metadata_path, FB.OpaqueMetadata); + + if ( KM_FAILURE(result) ) + { + DefaultLogSink().Error("%s: %s\n", metadata_path.c_str(), result.Label()); + } + } + else + { + DefaultLogSink().Error("%s: %s\n", m_CurrentFile->c_str(), result.Label()); + } + + if ( KM_SUCCESS(result) && m_Pedantic ) + { + ASDCP::JP2K::PictureDescriptor PDesc; + result = m_Parser.FillPictureDescriptor(PDesc); + + if ( KM_SUCCESS(result) && ! ( m_PDesc == PDesc ) ) + { + Kumu::DefaultLogSink().Error("JPEG-2000 codestream parameters do not match at frame %d\n", m_FramesRead + 1); + result = RESULT_RAW_FORMAT; + } + } + + if ( KM_SUCCESS(result) ) + { + FB.FrameNumber(m_FramesRead++); + m_CurrentFile++; + } + + return result; +} + + +//------------------------------------------------------------------------------------------ + +AS_02::PHDR::SequenceParser::SequenceParser() +{ +} + +AS_02::PHDR::SequenceParser::~SequenceParser() +{ +} + +// Opens the stream for reading, parses enough data to provide a complete +// set of stream metadata for the MXFWriter below. +ASDCP::Result_t +AS_02::PHDR::SequenceParser::OpenRead(const std::string& filename, bool pedantic) const +{ + const_cast<AS_02::PHDR::SequenceParser*>(this)->m_Parser = new h__SequenceParser; + + Result_t result = m_Parser->OpenRead(filename, pedantic); + + if ( ASDCP_FAILURE(result) ) + const_cast<AS_02::PHDR::SequenceParser*>(this)->m_Parser.release(); + + return result; +} + +// +Result_t +AS_02::PHDR::SequenceParser::OpenRead(const std::list<std::string>& file_list, bool pedantic) const +{ + const_cast<AS_02::PHDR::SequenceParser*>(this)->m_Parser = new h__SequenceParser; + + Result_t result = m_Parser->OpenRead(file_list, pedantic); + + if ( ASDCP_FAILURE(result) ) + const_cast<AS_02::PHDR::SequenceParser*>(this)->m_Parser.release(); + + return result; +} + + +// Rewinds the stream to the beginning. +ASDCP::Result_t +AS_02::PHDR::SequenceParser::Reset() const +{ + if ( m_Parser.empty() ) + return RESULT_INIT; + + return m_Parser->Reset(); +} + +// Places a frame of data in the frame buffer. Fails if the buffer is too small +// or the stream is empty. +ASDCP::Result_t +AS_02::PHDR::SequenceParser::ReadFrame(AS_02::PHDR::FrameBuffer& FB) const +{ + if ( m_Parser.empty() ) + return RESULT_INIT; + + return m_Parser->ReadFrame(FB); +} + +// +ASDCP::Result_t +AS_02::PHDR::SequenceParser::FillPictureDescriptor(ASDCP::JP2K::PictureDescriptor& PDesc) const +{ + if ( m_Parser.empty() ) + return RESULT_INIT; + + PDesc = m_Parser->m_PDesc; + return RESULT_OK; +} + + +// +// end PHDR_Sequence_Parser.cpp +// |
