rrrrr
[asdcplib.git] / src / JP2K_Sequence_Parser.cpp
1 /*
2 Copyright (c) 2004-2009, 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 char* 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             push_back(Str);
82           }
83
84         sort();
85       }
86
87     return result;
88   }
89 };
90
91 //------------------------------------------------------------------------------------------
92
93 class ASDCP::JP2K::SequenceParser::h__SequenceParser
94 {
95   ui32_t             m_FramesRead;
96   Rational           m_PictureRate;
97   FileList           m_FileList;
98   FileList::iterator m_CurrentFile;
99   CodestreamParser   m_Parser;
100   bool               m_Pedantic;
101
102   Result_t OpenRead();
103
104   ASDCP_NO_COPY_CONSTRUCT(h__SequenceParser);
105
106 public:
107   PictureDescriptor  m_PDesc;
108
109   h__SequenceParser() : m_FramesRead(0), m_Pedantic(false)
110   {
111     memset(&m_PDesc, 0, sizeof(m_PDesc));
112     m_PDesc.EditRate = Rational(24,1); 
113   }
114
115   ~h__SequenceParser()
116   {
117     Close();
118   }
119
120   Result_t OpenRead(const char* filename, bool pedantic);
121   Result_t OpenRead(const std::list<std::string>& file_list, bool pedantic);
122   void     Close() {}
123
124   Result_t Reset()
125   {
126     m_FramesRead = 0;
127     m_CurrentFile = m_FileList.begin();
128     return RESULT_OK;
129   }
130
131   Result_t ReadFrame(FrameBuffer&);
132 };
133
134
135 //
136 ASDCP::Result_t
137 ASDCP::JP2K::SequenceParser::h__SequenceParser::OpenRead()
138 {
139   if ( m_FileList.empty() )
140     return RESULT_ENDOFFILE;
141
142   m_CurrentFile = m_FileList.begin();
143   CodestreamParser Parser;
144   FrameBuffer TmpBuffer;
145
146   Kumu::fsize_t file_size = Kumu::FileSize((*m_CurrentFile).c_str());
147
148   if ( file_size == 0 )
149     return RESULT_NOT_FOUND;
150
151   assert(file_size <= 0xFFFFFFFFL);
152   Result_t result = TmpBuffer.Capacity((ui32_t) file_size);
153
154   if ( ASDCP_SUCCESS(result) )
155     result = Parser.OpenReadFrame((*m_CurrentFile).c_str(), TmpBuffer);
156       
157   if ( ASDCP_SUCCESS(result) )
158     result = Parser.FillPictureDescriptor(m_PDesc);
159
160   // how big is it?
161   if ( ASDCP_SUCCESS(result) )
162     m_PDesc.ContainerDuration = m_FileList.size();
163
164   return result;
165 }
166
167 //
168 ASDCP::Result_t
169 ASDCP::JP2K::SequenceParser::h__SequenceParser::OpenRead(const char* filename, bool pedantic)
170 {
171   ASDCP_TEST_NULL_STR(filename);
172   m_Pedantic = pedantic;
173
174   Result_t result = m_FileList.InitFromDirectory(filename);
175
176   if ( ASDCP_SUCCESS(result) )
177     result = OpenRead();
178
179   return result;
180 }
181
182
183 //
184 ASDCP::Result_t
185 ASDCP::JP2K::SequenceParser::h__SequenceParser::OpenRead(const std::list<std::string>& file_list, bool pedantic)
186 {
187   m_Pedantic = pedantic;
188   m_FileList = file_list;
189   return OpenRead();
190 }
191
192
193 //
194 bool
195 operator==(const ASDCP::JP2K::ImageComponent_t& lhs, const ASDCP::JP2K::ImageComponent_t& rhs)
196 {
197   if ( lhs.Ssize != rhs.Ssize ) return false;
198   if ( lhs.XRsize != rhs.XRsize ) return false;
199   if ( lhs.YRsize != rhs.YRsize ) return false;
200   return true;
201 }
202
203 //
204 bool
205 operator==(const ASDCP::JP2K::QuantizationDefault_t& lhs, const ASDCP::JP2K::QuantizationDefault_t& rhs)
206 {
207   if ( lhs.Sqcd != rhs.Sqcd ) return false;
208   if ( lhs.SPqcdLength != rhs.SPqcdLength ) return false;
209   
210   for ( ui32_t i = 0; i < JP2K::MaxDefaults; i++ )
211     {
212       if ( lhs.SPqcd[i] != rhs.SPqcd[i]  )
213         return false;
214     }
215
216   return true;
217 }
218
219 //
220 bool
221 operator==(const ASDCP::JP2K::CodingStyleDefault_t& lhs, const ASDCP::JP2K::CodingStyleDefault_t& rhs)
222 {
223   if ( lhs.Scod != rhs.Scod ) return false;
224
225   // SGcod
226   if ( lhs.SGcod.ProgressionOrder != rhs.SGcod.ProgressionOrder ) return false;
227   if ( lhs.SGcod.MultiCompTransform != rhs.SGcod.MultiCompTransform ) return false;
228
229   for ( ui32_t i = 0; i < sizeof(ui16_t); i++ )
230     {
231       if ( lhs.SGcod.NumberOfLayers[i] != lhs.SGcod.NumberOfLayers[i]  )
232         return false;
233     }
234
235   // SPcod
236   if ( lhs.SPcod.DecompositionLevels != rhs.SPcod.DecompositionLevels ) return false;
237   if ( lhs.SPcod.CodeblockWidth != rhs.SPcod.CodeblockWidth ) return false;
238   if ( lhs.SPcod.CodeblockHeight != rhs.SPcod.CodeblockHeight ) return false;
239   if ( lhs.SPcod.CodeblockStyle != rhs.SPcod.CodeblockStyle ) return false;
240   if ( lhs.SPcod.Transformation != rhs.SPcod.Transformation ) return false;
241   
242   for ( ui32_t i = 0; i < JP2K::MaxPrecincts; i++ )
243     {
244       if ( lhs.SPcod.PrecinctSize[i] != rhs.SPcod.PrecinctSize[i]  )
245         return false;
246     }
247
248   return true;
249 }
250
251 //
252 bool
253 operator==(const ASDCP::JP2K::PictureDescriptor& lhs, const ASDCP::JP2K::PictureDescriptor& rhs)
254 {
255   if ( lhs.EditRate != rhs.EditRate ) return false;
256   //  if ( lhs.ContainerDuration != rhs.ContainerDuration ) return false;
257   if ( lhs.SampleRate != rhs.SampleRate ) return false;
258   if ( lhs.StoredWidth != rhs.StoredWidth ) return false;
259   if ( lhs.StoredHeight != rhs.StoredHeight ) return false;
260   if ( lhs.AspectRatio != rhs.AspectRatio ) return false;
261   if ( lhs.Rsize != rhs.Rsize ) return false;
262   if ( lhs.Xsize != rhs.Xsize ) return false;
263   if ( lhs.Ysize != rhs.Ysize ) return false;
264   if ( lhs.XOsize != rhs.XOsize ) return false;
265   if ( lhs.YOsize != rhs.YOsize ) return false;
266   if ( lhs.XTsize != rhs.XTsize ) return false;
267   if ( lhs.YTsize != rhs.YTsize ) return false;
268   if ( lhs.XTOsize != rhs.XTOsize ) return false;
269   if ( lhs.YTOsize != rhs.YTOsize ) return false;
270   if ( lhs.Csize != rhs.Csize ) return false;
271   if ( ! ( lhs.CodingStyleDefault == rhs.CodingStyleDefault ) ) return false;
272   if ( ! ( lhs.QuantizationDefault == rhs.QuantizationDefault ) ) return false;
273   
274   for ( ui32_t i = 0; i < JP2K::MaxComponents; i++ )
275     {
276       if ( ! ( lhs.ImageComponents[i] == rhs.ImageComponents[i] ) )
277         return false;
278     }
279
280   return true;
281 }
282
283 //
284 ASDCP::Result_t
285 ASDCP::JP2K::SequenceParser::h__SequenceParser::ReadFrame(FrameBuffer& FB)
286 {
287   if ( m_CurrentFile == m_FileList.end() )
288     return RESULT_ENDOFFILE;
289
290   // open the file
291   Result_t result = m_Parser.OpenReadFrame((*m_CurrentFile).c_str(), FB);
292
293   if ( ASDCP_SUCCESS(result) && m_Pedantic )
294     {
295       PictureDescriptor PDesc;
296       result = m_Parser.FillPictureDescriptor(PDesc);
297
298       if ( ASDCP_SUCCESS(result) && ! ( m_PDesc == PDesc ) )
299         {
300           Kumu::DefaultLogSink().Error("JPEG-2000 codestream parameters do not match at frame %d\n", m_FramesRead + 1);
301           result = RESULT_RAW_FORMAT;
302         }
303     }
304
305   if ( ASDCP_SUCCESS(result) )
306     {
307       FB.FrameNumber(m_FramesRead++);
308       m_CurrentFile++;
309     }
310
311   return result;
312 }
313
314
315 //------------------------------------------------------------------------------------------
316
317 ASDCP::JP2K::SequenceParser::SequenceParser()
318 {
319 }
320
321 ASDCP::JP2K::SequenceParser::~SequenceParser()
322 {
323 }
324
325 // Opens the stream for reading, parses enough data to provide a complete
326 // set of stream metadata for the MXFWriter below.
327 ASDCP::Result_t
328 ASDCP::JP2K::SequenceParser::OpenRead(const char* filename, bool pedantic) const
329 {
330   const_cast<ASDCP::JP2K::SequenceParser*>(this)->m_Parser = new h__SequenceParser;
331
332   Result_t result = m_Parser->OpenRead(filename, pedantic);
333
334   if ( ASDCP_FAILURE(result) )
335     const_cast<ASDCP::JP2K::SequenceParser*>(this)->m_Parser.release();
336
337   return result;
338 }
339
340 //
341 Result_t
342 ASDCP::JP2K::SequenceParser::OpenRead(const std::list<std::string>& file_list, bool pedantic) const
343 {
344   const_cast<ASDCP::JP2K::SequenceParser*>(this)->m_Parser = new h__SequenceParser;
345
346   Result_t result = m_Parser->OpenRead(file_list, pedantic);
347
348   if ( ASDCP_FAILURE(result) )
349     const_cast<ASDCP::JP2K::SequenceParser*>(this)->m_Parser.release();
350
351   return result;
352 }
353
354
355 // Rewinds the stream to the beginning.
356 ASDCP::Result_t
357 ASDCP::JP2K::SequenceParser::Reset() const
358 {
359   if ( m_Parser.empty() )
360     return RESULT_INIT;
361
362   return m_Parser->Reset();
363 }
364
365 // Places a frame of data in the frame buffer. Fails if the buffer is too small
366 // or the stream is empty.
367 ASDCP::Result_t
368 ASDCP::JP2K::SequenceParser::ReadFrame(FrameBuffer& FB) const
369 {
370   if ( m_Parser.empty() )
371     return RESULT_INIT;
372
373   return m_Parser->ReadFrame(FB);
374 }
375
376 //
377 ASDCP::Result_t
378 ASDCP::JP2K::SequenceParser::FillPictureDescriptor(PictureDescriptor& PDesc) const
379 {
380   if ( m_Parser.empty() )
381     return RESULT_INIT;
382
383   PDesc = m_Parser->m_PDesc;
384   return RESULT_OK;
385 }
386
387
388 //
389 // end JP2K_Sequence_Parser.cpp
390 //