build JP2K parsers with file lists
[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 <list>
35 #include <string>
36 #include <algorithm>
37 #include <string.h>
38 #include <assert.h>
39
40 using namespace ASDCP;
41
42
43 //------------------------------------------------------------------------------------------
44   
45 class FileList : public std::list<std::string>
46 {
47   std::string m_DirName;
48
49 public:
50   FileList() {}
51   ~FileList() {}
52
53   const FileList& operator=(const std::list<std::string>& pathlist) {
54     std::list<std::string>::const_iterator i;
55     for ( i = pathlist.begin(); i != pathlist.end(); i++ )
56       push_back(*i);
57   }
58
59   //
60   Result_t InitFromDirectory(const char* path)
61   {
62     char next_file[Kumu::MaxFilePath];
63     Kumu::DirScanner Scanner;
64
65     Result_t result = Scanner.Open(path);
66
67     if ( ASDCP_SUCCESS(result) )
68       {
69         m_DirName = path;
70
71         while ( ASDCP_SUCCESS(Scanner.GetNext(next_file)) )
72           {
73             if ( next_file[0] == '.' ) // no hidden files or internal links
74               continue;
75
76             std::string Str(m_DirName);
77             Str += "/";
78             Str += next_file;
79             push_back(Str);
80           }
81
82         sort();
83       }
84
85     return result;
86   }
87 };
88
89 //------------------------------------------------------------------------------------------
90
91 class ASDCP::JP2K::SequenceParser::h__SequenceParser
92 {
93   ui32_t             m_FramesRead;
94   Rational           m_PictureRate;
95   FileList           m_FileList;
96   FileList::iterator m_CurrentFile;
97   CodestreamParser   m_Parser;
98   bool               m_Pedantic;
99
100   Result_t OpenRead();
101
102   ASDCP_NO_COPY_CONSTRUCT(h__SequenceParser);
103
104 public:
105   PictureDescriptor  m_PDesc;
106
107   h__SequenceParser() : m_FramesRead(0), m_Pedantic(false)
108   {
109     memset(&m_PDesc, 0, sizeof(m_PDesc));
110     m_PDesc.EditRate = Rational(24,1); 
111   }
112
113   ~h__SequenceParser()
114   {
115     Close();
116   }
117
118   Result_t OpenRead(const char* filename, bool pedantic);
119   Result_t OpenRead(const std::list<std::string>& file_list, bool pedantic);
120   void     Close() {}
121
122   Result_t Reset()
123   {
124     m_FramesRead = 0;
125     m_CurrentFile = m_FileList.begin();
126     return RESULT_OK;
127   }
128
129   Result_t ReadFrame(FrameBuffer&);
130 };
131
132
133 //
134 ASDCP::Result_t
135 ASDCP::JP2K::SequenceParser::h__SequenceParser::OpenRead()
136 {
137   if ( m_FileList.empty() )
138     return RESULT_ENDOFFILE;
139
140   m_CurrentFile = m_FileList.begin();
141   CodestreamParser Parser;
142   FrameBuffer TmpBuffer;
143
144   Kumu::fsize_t file_size = Kumu::FileSize((*m_CurrentFile).c_str());
145
146   if ( file_size == 0 )
147     return RESULT_NOT_FOUND;
148
149   assert(file_size <= 0xFFFFFFFFL);
150   Result_t result = TmpBuffer.Capacity((ui32_t) file_size);
151
152   if ( ASDCP_SUCCESS(result) )
153     result = Parser.OpenReadFrame((*m_CurrentFile).c_str(), TmpBuffer);
154       
155   if ( ASDCP_SUCCESS(result) )
156     result = Parser.FillPictureDescriptor(m_PDesc);
157
158   // how big is it?
159   if ( ASDCP_SUCCESS(result) )
160     m_PDesc.ContainerDuration = m_FileList.size();
161
162   return result;
163 }
164
165 //
166 ASDCP::Result_t
167 ASDCP::JP2K::SequenceParser::h__SequenceParser::OpenRead(const char* filename, bool pedantic)
168 {
169   ASDCP_TEST_NULL_STR(filename);
170   m_Pedantic = pedantic;
171
172   Result_t result = m_FileList.InitFromDirectory(filename);
173
174   if ( ASDCP_SUCCESS(result) )
175     result = OpenRead();
176
177   return result;
178 }
179
180
181 //
182 ASDCP::Result_t
183 ASDCP::JP2K::SequenceParser::h__SequenceParser::OpenRead(const std::list<std::string>& file_list, bool pedantic)
184 {
185   m_Pedantic = pedantic;
186   m_FileList = file_list;
187   return OpenRead();
188 }
189
190 //
191 ASDCP::Result_t
192 ASDCP::JP2K::SequenceParser::h__SequenceParser::ReadFrame(FrameBuffer& FB)
193 {
194   if ( m_CurrentFile == m_FileList.end() )
195     return RESULT_ENDOFFILE;
196
197   // open the file
198   Result_t result = m_Parser.OpenReadFrame((*m_CurrentFile).c_str(), FB);
199
200   if ( ASDCP_SUCCESS(result) )
201     {
202       FB.FrameNumber(m_FramesRead++);
203       m_CurrentFile++;
204     }
205
206   return result;
207 }
208
209
210 //------------------------------------------------------------------------------------------
211
212 ASDCP::JP2K::SequenceParser::SequenceParser()
213 {
214 }
215
216 ASDCP::JP2K::SequenceParser::~SequenceParser()
217 {
218 }
219
220 // Opens the stream for reading, parses enough data to provide a complete
221 // set of stream metadata for the MXFWriter below.
222 ASDCP::Result_t
223 ASDCP::JP2K::SequenceParser::OpenRead(const char* filename, bool pedantic) const
224 {
225   const_cast<ASDCP::JP2K::SequenceParser*>(this)->m_Parser = new h__SequenceParser;
226
227   Result_t result = m_Parser->OpenRead(filename, pedantic);
228
229   if ( ASDCP_FAILURE(result) )
230     const_cast<ASDCP::JP2K::SequenceParser*>(this)->m_Parser.release();
231
232   return result;
233 }
234
235 //
236 Result_t
237 ASDCP::JP2K::SequenceParser::OpenRead(const std::list<std::string>& file_list, bool pedantic) const
238 {
239   const_cast<ASDCP::JP2K::SequenceParser*>(this)->m_Parser = new h__SequenceParser;
240
241   Result_t result = m_Parser->OpenRead(file_list, pedantic);
242
243   if ( ASDCP_FAILURE(result) )
244     const_cast<ASDCP::JP2K::SequenceParser*>(this)->m_Parser.release();
245
246   return result;
247 }
248
249
250 // Rewinds the stream to the beginning.
251 ASDCP::Result_t
252 ASDCP::JP2K::SequenceParser::Reset() const
253 {
254   if ( m_Parser.empty() )
255     return RESULT_INIT;
256
257   return m_Parser->Reset();
258 }
259
260 // Places a frame of data in the frame buffer. Fails if the buffer is too small
261 // or the stream is empty.
262 ASDCP::Result_t
263 ASDCP::JP2K::SequenceParser::ReadFrame(FrameBuffer& FB) const
264 {
265   if ( m_Parser.empty() )
266     return RESULT_INIT;
267
268   return m_Parser->ReadFrame(FB);
269 }
270
271 //
272 ASDCP::Result_t
273 ASDCP::JP2K::SequenceParser::FillPictureDescriptor(PictureDescriptor& PDesc) const
274 {
275   if ( m_Parser.empty() )
276     return RESULT_INIT;
277
278   PDesc = m_Parser->m_PDesc;
279   return RESULT_OK;
280 }
281
282
283 //
284 // end JP2K_Sequence_Parser.cpp
285 //