ISXDDataEssenceDescriptor_NamespaceURI UL fixed
[asdcplib.git] / src / JP2K_Sequence_Parser.cpp
1 /*
2 Copyright (c) 2004-2011, John Hurst
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 1. Redistributions of source code must retain the above copyright
9    notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11    notice, this list of conditions and the following disclaimer in the
12    documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14    derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 /*! \file    JP2K_Sequence_Parser.cpp
28     \version $Id$
29     \brief   AS-DCP library, JPEG 2000 codestream essence reader implementation
30 */
31
32 #include <AS_DCP.h>
33 #include <KM_fileio.h>
34 #include <KM_log.h>
35 #include <list>
36 #include <string>
37 #include <algorithm>
38 #include <string.h>
39 #include <assert.h>
40
41 using namespace ASDCP;
42
43
44 //------------------------------------------------------------------------------------------
45   
46 class FileList : public std::list<std::string>
47 {
48   std::string m_DirName;
49
50 public:
51   FileList() {}
52   ~FileList() {}
53
54   const FileList& operator=(const std::list<std::string>& pathlist) {
55     std::list<std::string>::const_iterator i;
56     for ( i = pathlist.begin(); i != pathlist.end(); i++ )
57       push_back(*i);
58     return *this;
59   }
60
61   //
62   Result_t InitFromDirectory(const std::string& path)
63   {
64     char next_file[Kumu::MaxFilePath];
65     Kumu::DirScanner Scanner;
66
67     Result_t result = Scanner.Open(path);
68
69     if ( ASDCP_SUCCESS(result) )
70       {
71         m_DirName = path;
72
73         while ( ASDCP_SUCCESS(Scanner.GetNext(next_file)) )
74           {
75             if ( next_file[0] == '.' ) // no hidden files or internal links
76               continue;
77
78             std::string Str(m_DirName);
79             Str += "/";
80             Str += next_file;
81
82             if ( ! Kumu::PathIsDirectory(Str) )
83               push_back(Str);
84           }
85
86         sort();
87       }
88
89     return result;
90   }
91 };
92
93 //------------------------------------------------------------------------------------------
94
95 class ASDCP::JP2K::SequenceParser::h__SequenceParser
96 {
97   ui32_t             m_FramesRead;
98   Rational           m_PictureRate;
99   FileList           m_FileList;
100   FileList::iterator m_CurrentFile;
101   CodestreamParser   m_Parser;
102   bool               m_Pedantic;
103
104   Result_t OpenRead();
105
106   ASDCP_NO_COPY_CONSTRUCT(h__SequenceParser);
107
108 public:
109   PictureDescriptor  m_PDesc;
110
111   h__SequenceParser() : m_FramesRead(0), m_Pedantic(false)
112   {
113     memset(&m_PDesc, 0, sizeof(m_PDesc));
114     m_PDesc.EditRate = Rational(24,1); 
115   }
116
117   ~h__SequenceParser()
118   {
119     Close();
120   }
121
122   Result_t OpenRead(const std::string& filename, bool pedantic);
123   Result_t OpenRead(const std::list<std::string>& file_list, bool pedantic);
124   void     Close() {}
125
126   Result_t Reset()
127   {
128     m_FramesRead = 0;
129     m_CurrentFile = m_FileList.begin();
130     return RESULT_OK;
131   }
132
133   Result_t ReadFrame(FrameBuffer&);
134 };
135
136
137 //
138 ASDCP::Result_t
139 ASDCP::JP2K::SequenceParser::h__SequenceParser::OpenRead()
140 {
141   if ( m_FileList.empty() )
142     return RESULT_ENDOFFILE;
143
144   m_CurrentFile = m_FileList.begin();
145   CodestreamParser Parser;
146   FrameBuffer TmpBuffer;
147
148   Kumu::fsize_t file_size = Kumu::FileSize((*m_CurrentFile).c_str());
149
150   if ( file_size == 0 )
151     return RESULT_NOT_FOUND;
152
153   assert(file_size <= 0xFFFFFFFFL);
154   Result_t result = TmpBuffer.Capacity((ui32_t) file_size);
155
156   if ( ASDCP_SUCCESS(result) )
157     result = Parser.OpenReadFrame((*m_CurrentFile).c_str(), TmpBuffer);
158       
159   if ( ASDCP_SUCCESS(result) )
160     result = Parser.FillPictureDescriptor(m_PDesc);
161
162   // how big is it?
163   if ( ASDCP_SUCCESS(result) )
164     m_PDesc.ContainerDuration = m_FileList.size();
165
166   return result;
167 }
168
169 //
170 ASDCP::Result_t
171 ASDCP::JP2K::SequenceParser::h__SequenceParser::OpenRead(const std::string& filename, bool pedantic)
172 {
173   m_Pedantic = pedantic;
174
175   Result_t result = m_FileList.InitFromDirectory(filename);
176
177   if ( ASDCP_SUCCESS(result) )
178     result = OpenRead();
179
180   return result;
181 }
182
183
184 //
185 ASDCP::Result_t
186 ASDCP::JP2K::SequenceParser::h__SequenceParser::OpenRead(const std::list<std::string>& file_list, bool pedantic)
187 {
188   m_Pedantic = pedantic;
189   m_FileList = file_list;
190   return OpenRead();
191 }
192
193
194 //
195 bool
196 operator==(const ASDCP::JP2K::ImageComponent_t& lhs, const ASDCP::JP2K::ImageComponent_t& rhs)
197 {
198   if ( lhs.Ssize != rhs.Ssize ) return false;
199   if ( lhs.XRsize != rhs.XRsize ) return false;
200   if ( lhs.YRsize != rhs.YRsize ) return false;
201   return true;
202 }
203
204 //
205 bool
206 operator==(const ASDCP::JP2K::QuantizationDefault_t& lhs, const ASDCP::JP2K::QuantizationDefault_t& rhs)
207 {
208   if ( lhs.Sqcd != rhs.Sqcd ) return false;
209   if ( lhs.SPqcdLength != rhs.SPqcdLength ) return false;
210   
211   for ( ui32_t i = 0; i < JP2K::MaxDefaults; i++ )
212     {
213       if ( lhs.SPqcd[i] != rhs.SPqcd[i]  )
214         return false;
215     }
216
217   return true;
218 }
219
220 //
221 bool
222 operator==(const ASDCP::JP2K::CodingStyleDefault_t& lhs, const ASDCP::JP2K::CodingStyleDefault_t& rhs)
223 {
224   if ( lhs.Scod != rhs.Scod ) return false;
225
226   // SGcod
227   if ( lhs.SGcod.ProgressionOrder != rhs.SGcod.ProgressionOrder ) return false;
228   if ( lhs.SGcod.MultiCompTransform != rhs.SGcod.MultiCompTransform ) return false;
229
230   for ( ui32_t i = 0; i < sizeof(ui16_t); i++ )
231     {
232       if ( lhs.SGcod.NumberOfLayers[i] != lhs.SGcod.NumberOfLayers[i]  )
233         return false;
234     }
235
236   // SPcod
237   if ( lhs.SPcod.DecompositionLevels != rhs.SPcod.DecompositionLevels ) return false;
238   if ( lhs.SPcod.CodeblockWidth != rhs.SPcod.CodeblockWidth ) return false;
239   if ( lhs.SPcod.CodeblockHeight != rhs.SPcod.CodeblockHeight ) return false;
240   if ( lhs.SPcod.CodeblockStyle != rhs.SPcod.CodeblockStyle ) return false;
241   if ( lhs.SPcod.Transformation != rhs.SPcod.Transformation ) return false;
242   
243   for ( ui32_t i = 0; i < JP2K::MaxPrecincts; i++ )
244     {
245       if ( lhs.SPcod.PrecinctSize[i] != rhs.SPcod.PrecinctSize[i]  )
246         return false;
247     }
248
249   return true;
250 }
251
252 //
253 bool
254 operator==(const ASDCP::JP2K::PictureDescriptor& lhs, const ASDCP::JP2K::PictureDescriptor& rhs)
255 {
256   if ( lhs.EditRate != rhs.EditRate ) return false;
257   //  if ( lhs.ContainerDuration != rhs.ContainerDuration ) return false;
258   if ( lhs.SampleRate != rhs.SampleRate ) return false;
259   if ( lhs.StoredWidth != rhs.StoredWidth ) return false;
260   if ( lhs.StoredHeight != rhs.StoredHeight ) return false;
261   if ( lhs.AspectRatio != rhs.AspectRatio ) return false;
262   if ( lhs.Rsize != rhs.Rsize ) return false;
263   if ( lhs.Xsize != rhs.Xsize ) return false;
264   if ( lhs.Ysize != rhs.Ysize ) return false;
265   if ( lhs.XOsize != rhs.XOsize ) return false;
266   if ( lhs.YOsize != rhs.YOsize ) return false;
267   if ( lhs.XTsize != rhs.XTsize ) return false;
268   if ( lhs.YTsize != rhs.YTsize ) return false;
269   if ( lhs.XTOsize != rhs.XTOsize ) return false;
270   if ( lhs.YTOsize != rhs.YTOsize ) return false;
271   if ( lhs.Csize != rhs.Csize ) return false;
272   if ( ! ( lhs.CodingStyleDefault == rhs.CodingStyleDefault ) ) return false;
273   if ( ! ( lhs.QuantizationDefault == rhs.QuantizationDefault ) ) return false;
274   
275   for ( ui32_t i = 0; i < JP2K::MaxComponents; i++ )
276     {
277       if ( ! ( lhs.ImageComponents[i] == rhs.ImageComponents[i] ) )
278         return false;
279     }
280
281   return true;
282 }
283
284 //
285 ASDCP::Result_t
286 ASDCP::JP2K::SequenceParser::h__SequenceParser::ReadFrame(FrameBuffer& FB)
287 {
288   if ( m_CurrentFile == m_FileList.end() )
289     return RESULT_ENDOFFILE;
290
291   // open the file
292   Result_t result = m_Parser.OpenReadFrame((*m_CurrentFile).c_str(), FB);
293
294   if ( ASDCP_SUCCESS(result) && m_Pedantic )
295     {
296       PictureDescriptor PDesc;
297       result = m_Parser.FillPictureDescriptor(PDesc);
298
299       if ( ASDCP_SUCCESS(result) && ! ( m_PDesc == PDesc ) )
300         {
301           Kumu::DefaultLogSink().Error("JPEG-2000 codestream parameters do not match at frame %d\n", m_FramesRead + 1);
302           result = RESULT_RAW_FORMAT;
303         }
304     }
305
306   if ( ASDCP_SUCCESS(result) )
307     {
308       FB.FrameNumber(m_FramesRead++);
309       m_CurrentFile++;
310     }
311
312   return result;
313 }
314
315
316 //------------------------------------------------------------------------------------------
317
318 ASDCP::JP2K::SequenceParser::SequenceParser()
319 {
320 }
321
322 ASDCP::JP2K::SequenceParser::~SequenceParser()
323 {
324 }
325
326 // Opens the stream for reading, parses enough data to provide a complete
327 // set of stream metadata for the MXFWriter below.
328 ASDCP::Result_t
329 ASDCP::JP2K::SequenceParser::OpenRead(const std::string& filename, bool pedantic) const
330 {
331   const_cast<ASDCP::JP2K::SequenceParser*>(this)->m_Parser = new h__SequenceParser;
332
333   Result_t result = m_Parser->OpenRead(filename, pedantic);
334
335   if ( ASDCP_FAILURE(result) )
336     const_cast<ASDCP::JP2K::SequenceParser*>(this)->m_Parser.release();
337
338   return result;
339 }
340
341 //
342 Result_t
343 ASDCP::JP2K::SequenceParser::OpenRead(const std::list<std::string>& file_list, bool pedantic) const
344 {
345   const_cast<ASDCP::JP2K::SequenceParser*>(this)->m_Parser = new h__SequenceParser;
346
347   Result_t result = m_Parser->OpenRead(file_list, pedantic);
348
349   if ( ASDCP_FAILURE(result) )
350     const_cast<ASDCP::JP2K::SequenceParser*>(this)->m_Parser.release();
351
352   return result;
353 }
354
355
356 // Rewinds the stream to the beginning.
357 ASDCP::Result_t
358 ASDCP::JP2K::SequenceParser::Reset() const
359 {
360   if ( m_Parser.empty() )
361     return RESULT_INIT;
362
363   return m_Parser->Reset();
364 }
365
366 // Places a frame of data in the frame buffer. Fails if the buffer is too small
367 // or the stream is empty.
368 ASDCP::Result_t
369 ASDCP::JP2K::SequenceParser::ReadFrame(FrameBuffer& FB) const
370 {
371   if ( m_Parser.empty() )
372     return RESULT_INIT;
373
374   return m_Parser->ReadFrame(FB);
375 }
376
377 //
378 ASDCP::Result_t
379 ASDCP::JP2K::SequenceParser::FillPictureDescriptor(PictureDescriptor& PDesc) const
380 {
381   if ( m_Parser.empty() )
382     return RESULT_INIT;
383
384   PDesc = m_Parser->m_PDesc;
385   return RESULT_OK;
386 }
387
388
389 //
390 // end JP2K_Sequence_Parser.cpp
391 //