2 Copyright (c) 2018, Bjoern Stresing, Patrick Bichiou, Wolfgang Ruppel,
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. The name of the author may not be used to endorse or promote products
16 derived from this software without specific prior written permission.
18 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include "AS_02_ACES.h"
31 #include <KM_fileio.h>
36 using Kumu::DefaultLogSink;
39 class FileList : public std::list<std::string>
41 std::string m_DirName;
47 const FileList& operator=(const std::list<std::string>& pathlist)
49 std::list<std::string>::const_iterator i;
50 for(i = pathlist.begin(); i != pathlist.end(); i++)
56 ASDCP::Result_t InitFromDirectory(const std::string& path)
58 char next_file[Kumu::MaxFilePath];
59 Kumu::DirScanner Scanner;
61 ASDCP::Result_t result = Scanner.Open(path);
63 if(ASDCP_SUCCESS(result))
67 while(ASDCP_SUCCESS(Scanner.GetNext(next_file)))
69 if(next_file[0] == '.') // no hidden files or internal links
72 std::string Str(m_DirName);
76 if(!Kumu::PathIsDirectory(Str))
88 class AS_02::ACES::SequenceParser::h__SequenceParser
91 ASDCP::Rational m_PictureRate;
93 FileList::iterator m_CurrentFile;
94 CodestreamParser m_Parser;
99 ASDCP_NO_COPY_CONSTRUCT(h__SequenceParser);
102 PictureDescriptor m_PDesc;
103 ResourceList_t m_ResourceList_t;
105 h__SequenceParser() : m_FramesRead(0), m_Pedantic(false)
107 memset(&m_PDesc, 0, sizeof(m_PDesc));
108 m_PDesc.EditRate = ASDCP::Rational(24, 1);
116 Result_t OpenRead(const std::string& filename, bool pedantic);
117 Result_t OpenRead(const std::list<std::string>& file_list, bool pedantic);
118 // Opens a files sequence for reading. The sequence is expected to contain one or more
119 // PNG or TIFF files which will be added as Ancillary Data.
120 Result_t OpenTargetFrameSequenceRead(const std::list<std::string> &target_frame_file_list);
127 m_CurrentFile = m_FileList.begin();
131 Result_t ReadFrame(FrameBuffer&);
134 AS_02::Result_t AS_02::ACES::SequenceParser::h__SequenceParser::OpenRead()
137 if(m_FileList.empty())
138 return RESULT_ENDOFFILE;
140 m_CurrentFile = m_FileList.begin();
141 CodestreamParser Parser;
142 FrameBuffer TmpBuffer;
144 Kumu::fsize_t file_size = Kumu::FileSize((*m_CurrentFile).c_str());
147 return RESULT_NOT_FOUND;
149 assert(file_size <= 0xFFFFFFFFL);
150 Result_t result = TmpBuffer.Capacity((ui32_t)file_size);
151 if(ASDCP_SUCCESS(result))
152 result = Parser.OpenReadFrame((*m_CurrentFile).c_str(), TmpBuffer);
154 if(ASDCP_SUCCESS(result))
155 result = Parser.FillPictureDescriptor(m_PDesc);
158 if(ASDCP_SUCCESS(result))
159 m_PDesc.ContainerDuration = m_FileList.size();
164 AS_02::Result_t AS_02::ACES::SequenceParser::h__SequenceParser::OpenRead(const std::string& filename, bool pedantic)
167 m_Pedantic = pedantic;
169 Result_t result = m_FileList.InitFromDirectory(filename);
171 if(ASDCP_SUCCESS(result))
177 AS_02::Result_t AS_02::ACES::SequenceParser::h__SequenceParser::OpenRead(const std::list<std::string>& file_list, bool pedantic)
180 m_Pedantic = pedantic;
181 m_FileList = file_list;
185 AS_02::Result_t AS_02::ACES::SequenceParser::h__SequenceParser::OpenTargetFrameSequenceRead(const std::list<std::string> &target_frame_file_list)
187 AS_02::Result_t result = AS_02::RESULT_OK;
188 std::list<std::string>::const_iterator i;
189 byte_t read_buffer[16];
191 for (i = target_frame_file_list.begin(); i != target_frame_file_list.end(); i++)
193 std::string abs_filename = Kumu::PathMakeAbsolute(*i);
194 Kumu::FileReader reader;
195 result = reader.OpenRead(abs_filename);
197 if ( KM_SUCCESS(result) )
199 result = reader.Read(read_buffer, 16);
202 if ( KM_SUCCESS(result) )
204 // is it PNG or TIFF?
205 MIMEType_t media_type = MT_UNDEF;
206 if ( memcmp(read_buffer, PNGMagic, sizeof(PNGMagic)) == 0) media_type = MT_PNG;
207 if ( memcmp(read_buffer, TIFFMagicLE, sizeof(TIFFMagicLE)) == 0) media_type = MT_TIFF;
208 if ( memcmp(read_buffer, TIFFMagicBE, sizeof(TIFFMagicBE)) == 0) media_type = MT_TIFF;
209 if (media_type != MT_UNDEF)
211 AS_02::ACES::AncillaryResourceDescriptor resource_descriptor;
213 result = CreateTargetFrameAssetId(asset_id, abs_filename);
214 memcpy(&resource_descriptor.ResourceID, asset_id.Value(), Kumu::UUID_Length);
215 resource_descriptor.Type = media_type;
216 resource_descriptor.filePath = *i;
217 if ( KM_SUCCESS(result) ) m_ResourceList_t.push_back(resource_descriptor);
226 AS_02::Result_t AS_02::ACES::SequenceParser::h__SequenceParser::ReadFrame(FrameBuffer& FB)
229 if(m_CurrentFile == m_FileList.end())
230 return RESULT_ENDOFFILE;
233 Result_t result = m_Parser.OpenReadFrame((*m_CurrentFile).c_str(), FB);
235 if(ASDCP_SUCCESS(result) && m_Pedantic)
237 PictureDescriptor PDesc;
238 result = m_Parser.FillPictureDescriptor(PDesc);
240 if(ASDCP_SUCCESS(result) && !(m_PDesc == PDesc))
242 Kumu::DefaultLogSink().Error("ACES codestream parameters do not match at frame %d\n", m_FramesRead + 1);
243 result = ASDCP::RESULT_RAW_FORMAT;
247 if(ASDCP_SUCCESS(result))
249 FB.FrameNumber(m_FramesRead++);
256 //------------------------------------------------------------------------------
259 AS_02::ACES::SequenceParser::SequenceParser() {}
261 AS_02::ACES::SequenceParser::~SequenceParser() {}
263 // Opens the stream for reading, parses enough data to provide a complete
264 // set of stream metadata for the MXFWriter below.
265 AS_02::Result_t AS_02::ACES::SequenceParser::OpenRead(const std::string &directory, bool pedantic /*= false*/, const std::list<std::string> &target_frame_file_list /* = std::list<std::string>()*/) const
268 const_cast<AS_02::ACES::SequenceParser*>(this)->m_Parser = new h__SequenceParser;
270 Result_t result = m_Parser->OpenRead(directory, pedantic);
272 if(ASDCP_SUCCESS(result))
273 if (target_frame_file_list.size() > 0 ) result = m_Parser->OpenTargetFrameSequenceRead(target_frame_file_list);
275 if(ASDCP_FAILURE(result))
276 const_cast<AS_02::ACES::SequenceParser*>(this)->m_Parser.release();
281 AS_02::Result_t AS_02::ACES::SequenceParser::OpenRead(const std::list<std::string> &file_list, bool pedantic /*= false*/, const std::list<std::string> &target_frame_file_list /* = std::list<std::string>()*/) const
284 const_cast<AS_02::ACES::SequenceParser*>(this)->m_Parser = new h__SequenceParser;
286 Result_t result = m_Parser->OpenRead(file_list, pedantic);
288 if(ASDCP_SUCCESS(result))
289 if (target_frame_file_list.size() > 0 ) result = m_Parser->OpenTargetFrameSequenceRead(target_frame_file_list);
291 if(ASDCP_FAILURE(result))
292 const_cast<AS_02::ACES::SequenceParser*>(this)->m_Parser.release();
297 AS_02::Result_t AS_02::ACES::SequenceParser::FillPictureDescriptor(PictureDescriptor &PDesc) const
303 PDesc = m_Parser->m_PDesc;
307 AS_02::Result_t AS_02::ACES::SequenceParser::FillResourceList(ResourceList_t &rResourceList_t) const
313 rResourceList_t = m_Parser->m_ResourceList_t;
317 AS_02::Result_t AS_02::ACES::SequenceParser::Reset() const
323 return m_Parser->Reset();
326 AS_02::Result_t AS_02::ACES::SequenceParser::ReadFrame(FrameBuffer &FB) const
332 return m_Parser->ReadFrame(FB);
335 AS_02::Result_t AS_02::ACES::SequenceParser::ReadAncillaryResource(const std::string &filename, FrameBuffer &FB) const
337 if ( m_Parser.empty() )
339 Kumu::FileReader reader;
340 Result_t result = Kumu::RESULT_OK;
341 result = reader.OpenRead(filename);
342 if (KM_SUCCESS(result))
344 FB.Capacity(reader.Size());
346 result = reader.Read(FB.Data(), reader.Size(), &read_count);
348 if (read_count < reader.Size()) result = Kumu::RESULT_FAIL;