cd9358353221b82763ff2bcd35d74e22bd73f26a
[asdcplib.git] / src / JP2K_Sequence_Parser.cpp
1 /*
2 Copyright (c) 2004-2005, 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   //
54   Result_t InitFromDirectory(const char* path)
55   {
56     char next_file[Kumu::MaxFilePath];
57     Kumu::DirScanner Scanner;
58
59     Result_t result = Scanner.Open(path);
60
61     if ( ASDCP_SUCCESS(result) )
62       {
63         m_DirName = path;
64
65         while ( ASDCP_SUCCESS(Scanner.GetNext(next_file)) )
66           {
67             if ( next_file[0] == '.' ) // no hidden files or internal links
68               continue;
69
70             std::string Str(m_DirName);
71             Str += "/";
72             Str += next_file;
73             push_back(Str);
74           }
75
76         sort();
77       }
78
79     return result;
80   }
81 };
82
83 //------------------------------------------------------------------------------------------
84
85 class ASDCP::JP2K::SequenceParser::h__SequenceParser
86 {
87   ui32_t             m_FramesRead;
88   Rational           m_PictureRate;
89   FileList           m_FileList;
90   FileList::iterator m_CurrentFile;
91   CodestreamParser   m_Parser;
92
93   ASDCP_NO_COPY_CONSTRUCT(h__SequenceParser);
94
95 public:
96   PictureDescriptor  m_PDesc;
97
98   h__SequenceParser() : m_FramesRead(0)
99   {
100     memset(&m_PDesc, 0, sizeof(m_PDesc));
101     m_PDesc.EditRate = Rational(24,1); 
102   }
103
104   ~h__SequenceParser()
105   {
106     Close();
107   }
108
109   Result_t OpenRead(const char* filename);
110   void     Close() {}
111
112   Result_t Reset()
113   {
114     m_FramesRead = 0;
115     m_CurrentFile = m_FileList.begin();
116     return RESULT_OK;
117   }
118
119   Result_t ReadFrame(FrameBuffer&);
120 };
121
122
123 //
124 ASDCP::Result_t
125 ASDCP::JP2K::SequenceParser::h__SequenceParser::OpenRead(const char* filename)
126 {
127   ASDCP_TEST_NULL_STR(filename);
128
129   Result_t result = m_FileList.InitFromDirectory(filename);
130
131   if ( m_FileList.empty() )
132     return RESULT_ENDOFFILE;
133
134   if ( ASDCP_SUCCESS(result) )
135     {
136       m_CurrentFile = m_FileList.begin();
137
138       CodestreamParser Parser;
139       FrameBuffer TmpBuffer;
140
141       Kumu::fsize_t file_size = Kumu::FileSize((*m_CurrentFile).c_str());
142
143       if ( file_size == 0 )
144         result = RESULT_NOT_FOUND;
145
146       if ( ASDCP_SUCCESS(result) )
147         result = TmpBuffer.Capacity(file_size);
148
149       if ( ASDCP_SUCCESS(result) )
150         result = Parser.OpenReadFrame((*m_CurrentFile).c_str(), TmpBuffer);
151       
152       if ( ASDCP_SUCCESS(result) )
153         result = Parser.FillPictureDescriptor(m_PDesc);
154
155       // how big is it?
156       if ( ASDCP_SUCCESS(result) )
157         m_PDesc.ContainerDuration = m_FileList.size();
158     }
159
160   return result;
161 }
162
163 //
164 //
165 ASDCP::Result_t
166 ASDCP::JP2K::SequenceParser::h__SequenceParser::ReadFrame(FrameBuffer& FB)
167 {
168   if ( m_CurrentFile == m_FileList.end() )
169     return RESULT_ENDOFFILE;
170
171   // open the file
172   Result_t result = m_Parser.OpenReadFrame((*m_CurrentFile).c_str(), FB);
173
174   if ( ASDCP_SUCCESS(result) )
175     {
176       FB.FrameNumber(m_FramesRead++);
177       m_CurrentFile++;
178     }
179
180   return result;
181 }
182
183
184 //------------------------------------------------------------------------------------------
185
186 ASDCP::JP2K::SequenceParser::SequenceParser()
187 {
188 }
189
190 ASDCP::JP2K::SequenceParser::~SequenceParser()
191 {
192 }
193
194 // Opens the stream for reading, parses enough data to provide a complete
195 // set of stream metadata for the MXFWriter below.
196 ASDCP::Result_t
197 ASDCP::JP2K::SequenceParser::OpenRead(const char* filename, bool pedantic) const
198 {
199   const_cast<ASDCP::JP2K::SequenceParser*>(this)->m_Parser = new h__SequenceParser;
200
201   Result_t result = m_Parser->OpenRead(filename);
202
203   if ( ASDCP_FAILURE(result) )
204     const_cast<ASDCP::JP2K::SequenceParser*>(this)->m_Parser.release();
205
206   return result;
207 }
208
209 // Rewinds the stream to the beginning.
210 ASDCP::Result_t
211 ASDCP::JP2K::SequenceParser::Reset() const
212 {
213   if ( m_Parser.empty() )
214     return RESULT_INIT;
215
216   return m_Parser->Reset();
217 }
218
219 // Places a frame of data in the frame buffer. Fails if the buffer is too small
220 // or the stream is empty.
221 ASDCP::Result_t
222 ASDCP::JP2K::SequenceParser::ReadFrame(FrameBuffer& FB) const
223 {
224   if ( m_Parser.empty() )
225     return RESULT_INIT;
226
227   return m_Parser->ReadFrame(FB);
228 }
229
230 ASDCP::Result_t
231 ASDCP::JP2K::SequenceParser::FillPictureDescriptor(PictureDescriptor& PDesc) const
232 {
233   if ( m_Parser.empty() )
234     return RESULT_INIT;
235
236   PDesc = m_Parser->m_PDesc;
237   return RESULT_OK;
238 }
239
240
241 //
242 // end JP2K_Sequence_Parser.cpp
243 //