a1ece3facc18fc9f98c4439a04adefd854647849
[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::ExtendedCapabilities_t& lhs, const ASDCP::JP2K::ExtendedCapabilities_t& rhs)
255 {
256         if (lhs.Pcap != rhs.Pcap) return false;
257
258         for (ui32_t i = 0; i < JP2K::MaxCapabilities; i++)
259         {
260                 if (lhs.Ccap[i] != rhs.Ccap[i])
261                         return false;
262         }
263
264         return true;
265 }
266
267 //
268 bool
269 operator==(const ASDCP::JP2K::CorrespondingProfile_t& lhs, const ASDCP::JP2K::CorrespondingProfile_t& rhs)
270 {
271         if (lhs.N != rhs.N) return false;
272
273         for (ui32_t i = 0; i < lhs.N; i++)
274         {
275                 if (lhs.Pcpf[i] != rhs.Pcpf[i])
276                         return false;
277         }
278
279         return true;
280 }
281
282 //
283 bool
284 operator==(const ASDCP::JP2K::Profile_t& lhs, const ASDCP::JP2K::Profile_t& rhs)
285 {
286         if (lhs.N != rhs.N) return false;
287
288         for (ui32_t i = 0; i < lhs.N; i++)
289         {
290                 if (lhs.Pprf[i] != rhs.Pprf[i])
291                         return false;
292         }
293
294         return true;
295 }
296
297 //
298 bool
299 operator==(const ASDCP::JP2K::PictureDescriptor& lhs, const ASDCP::JP2K::PictureDescriptor& rhs)
300 {
301   if ( lhs.EditRate != rhs.EditRate ) return false;
302   //  if ( lhs.ContainerDuration != rhs.ContainerDuration ) return false;
303   if ( lhs.SampleRate != rhs.SampleRate ) return false;
304   if ( lhs.StoredWidth != rhs.StoredWidth ) return false;
305   if ( lhs.StoredHeight != rhs.StoredHeight ) return false;
306   if ( lhs.AspectRatio != rhs.AspectRatio ) return false;
307   if ( lhs.Rsize != rhs.Rsize ) return false;
308   if ( lhs.Xsize != rhs.Xsize ) return false;
309   if ( lhs.Ysize != rhs.Ysize ) return false;
310   if ( lhs.XOsize != rhs.XOsize ) return false;
311   if ( lhs.YOsize != rhs.YOsize ) return false;
312   if ( lhs.XTsize != rhs.XTsize ) return false;
313   if ( lhs.YTsize != rhs.YTsize ) return false;
314   if ( lhs.XTOsize != rhs.XTOsize ) return false;
315   if ( lhs.YTOsize != rhs.YTOsize ) return false;
316   if ( lhs.Csize != rhs.Csize ) return false;
317   if ( ! ( lhs.CodingStyleDefault == rhs.CodingStyleDefault ) ) return false;
318   if ( ! ( lhs.QuantizationDefault == rhs.QuantizationDefault ) ) return false;
319   if (!(lhs.Profile == rhs.Profile)) return false;
320   if (!(lhs.CorrespondingProfile == rhs.CorrespondingProfile)) return false;
321   if (!(lhs.ExtendedCapabilities == rhs.ExtendedCapabilities)) return false;
322   
323   for ( ui32_t i = 0; i < JP2K::MaxComponents; i++ )
324     {
325       if ( ! ( lhs.ImageComponents[i] == rhs.ImageComponents[i] ) )
326         return false;
327     }
328
329   return true;
330 }
331
332 //
333 ASDCP::Result_t
334 ASDCP::JP2K::SequenceParser::h__SequenceParser::ReadFrame(FrameBuffer& FB)
335 {
336   if ( m_CurrentFile == m_FileList.end() )
337     return RESULT_ENDOFFILE;
338
339   // open the file
340   Result_t result = m_Parser.OpenReadFrame((*m_CurrentFile).c_str(), FB);
341
342   if ( ASDCP_SUCCESS(result) && m_Pedantic )
343     {
344       PictureDescriptor PDesc;
345       result = m_Parser.FillPictureDescriptor(PDesc);
346
347       if ( ASDCP_SUCCESS(result) && ! ( m_PDesc == PDesc ) )
348         {
349           Kumu::DefaultLogSink().Error("JPEG-2000 codestream parameters do not match at frame %d\n", m_FramesRead + 1);
350           result = RESULT_RAW_FORMAT;
351         }
352     }
353
354   if ( ASDCP_SUCCESS(result) )
355     {
356       FB.FrameNumber(m_FramesRead++);
357       m_CurrentFile++;
358     }
359
360   return result;
361 }
362
363
364 //------------------------------------------------------------------------------------------
365
366 ASDCP::JP2K::SequenceParser::SequenceParser()
367 {
368 }
369
370 ASDCP::JP2K::SequenceParser::~SequenceParser()
371 {
372 }
373
374 // Opens the stream for reading, parses enough data to provide a complete
375 // set of stream metadata for the MXFWriter below.
376 ASDCP::Result_t
377 ASDCP::JP2K::SequenceParser::OpenRead(const std::string& filename, bool pedantic) const
378 {
379   const_cast<ASDCP::JP2K::SequenceParser*>(this)->m_Parser = new h__SequenceParser;
380
381   Result_t result = m_Parser->OpenRead(filename, pedantic);
382
383   if ( ASDCP_FAILURE(result) )
384     const_cast<ASDCP::JP2K::SequenceParser*>(this)->m_Parser.release();
385
386   return result;
387 }
388
389 //
390 Result_t
391 ASDCP::JP2K::SequenceParser::OpenRead(const std::list<std::string>& file_list, bool pedantic) const
392 {
393   const_cast<ASDCP::JP2K::SequenceParser*>(this)->m_Parser = new h__SequenceParser;
394
395   Result_t result = m_Parser->OpenRead(file_list, pedantic);
396
397   if ( ASDCP_FAILURE(result) )
398     const_cast<ASDCP::JP2K::SequenceParser*>(this)->m_Parser.release();
399
400   return result;
401 }
402
403
404 // Rewinds the stream to the beginning.
405 ASDCP::Result_t
406 ASDCP::JP2K::SequenceParser::Reset() const
407 {
408   if ( m_Parser.empty() )
409     return RESULT_INIT;
410
411   return m_Parser->Reset();
412 }
413
414 // Places a frame of data in the frame buffer. Fails if the buffer is too small
415 // or the stream is empty.
416 ASDCP::Result_t
417 ASDCP::JP2K::SequenceParser::ReadFrame(FrameBuffer& FB) const
418 {
419   if ( m_Parser.empty() )
420     return RESULT_INIT;
421
422   return m_Parser->ReadFrame(FB);
423 }
424
425 //
426 ASDCP::Result_t
427 ASDCP::JP2K::SequenceParser::FillPictureDescriptor(PictureDescriptor& PDesc) const
428 {
429   if ( m_Parser.empty() )
430     return RESULT_INIT;
431
432   PDesc = m_Parser->m_PDesc;
433   return RESULT_OK;
434 }
435
436
437 //
438 // end JP2K_Sequence_Parser.cpp
439 //