Simplify time representation; better in-tree DCP subtitle parser.
[libsub.git] / asdcplib / src / JP2K_Codestream_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    Codestream_Parser.cpp
28     \version $Id: JP2K_Codestream_Parser.cpp,v 1.7 2009/04/09 19:16:49 msheby Exp $
29     \brief   AS-DCP library, JPEG 2000 codestream essence reader implementation
30 */
31
32 #include <KM_fileio.h>
33 #include <AS_DCP.h>
34 #include <JP2K.h>
35 #include <assert.h>
36 #include <KM_log.h>
37 using Kumu::DefaultLogSink;
38
39 //------------------------------------------------------------------------------------------
40
41 class ASDCP::JP2K::CodestreamParser::h__CodestreamParser
42 {
43   ASDCP_NO_COPY_CONSTRUCT(h__CodestreamParser);
44
45 public:
46   PictureDescriptor  m_PDesc;
47   Kumu::FileReader   m_File;
48
49   h__CodestreamParser()
50   {
51     memset(&m_PDesc, 0, sizeof(m_PDesc));
52     m_PDesc.EditRate = Rational(24,1);
53     m_PDesc.SampleRate = m_PDesc.EditRate;
54   }
55
56   ~h__CodestreamParser() {}
57
58   Result_t OpenReadFrame(const char* filename, FrameBuffer& FB)
59   {
60     ASDCP_TEST_NULL_STR(filename);
61     m_File.Close();
62     Result_t result = m_File.OpenRead(filename);
63
64     if ( ASDCP_SUCCESS(result) )
65       {
66         Kumu::fsize_t file_size = m_File.Size();
67
68         if ( FB.Capacity() < file_size )
69           {
70             DefaultLogSink().Error("FrameBuf.Capacity: %u frame length: %u\n", FB.Capacity(), (ui32_t)file_size);
71             return RESULT_SMALLBUF;
72           }
73       }
74
75     ui32_t read_count;
76
77     if ( ASDCP_SUCCESS(result) )
78       result = m_File.Read(FB.Data(), FB.Capacity(), &read_count);
79
80     if ( ASDCP_SUCCESS(result) )
81       FB.Size(read_count);
82
83     if ( ASDCP_SUCCESS(result) )
84       {
85         byte_t start_of_data = 0; // out param
86         result = ParseMetadataIntoDesc(FB, m_PDesc, &start_of_data);
87
88         if ( ASDCP_SUCCESS(result) )
89           FB.PlaintextOffset(start_of_data);
90       }
91
92     return result;
93   }
94
95   Result_t OpenReadFrame(const unsigned char * data, unsigned int size, FrameBuffer& FB)
96   {
97     if ( FB.Capacity() < size )
98       {
99         DefaultLogSink().Error("FrameBuf.Capacity: %u frame length: %u\n", FB.Capacity(), (ui32_t) size);
100         return RESULT_SMALLBUF;
101       }
102
103     memcpy (FB.Data(), data, size);
104     FB.Size(size);
105
106     byte_t start_of_data = 0; // out param
107     const Result_t result = ParseMetadataIntoDesc(FB, m_PDesc, &start_of_data);
108
109     if ( ASDCP_SUCCESS(result) )
110       FB.PlaintextOffset(start_of_data);
111
112     return result;
113   }     
114 };
115
116 ASDCP::Result_t
117 ASDCP::JP2K::ParseMetadataIntoDesc(const FrameBuffer& FB, PictureDescriptor& PDesc, byte_t* start_of_data)
118 {
119   Result_t result = RESULT_OK;
120   Marker NextMarker;
121   ui32_t i;
122   const byte_t* p = FB.RoData();
123   const byte_t* end_p = p + FB.Size();
124
125   while ( p < end_p && ASDCP_SUCCESS(result) )
126     {
127       result = GetNextMarker(&p, NextMarker);
128
129       if ( ASDCP_FAILURE(result) )
130         {
131           result = RESULT_RAW_ESS;
132           break;
133         }
134
135       switch ( NextMarker.m_Type )
136         {
137         case MRK_SOD:
138           if ( start_of_data != 0 )
139             *start_of_data = p - FB.RoData();
140
141           p = end_p;
142           break;
143
144         case MRK_SIZ:
145           {
146             Accessor::SIZ SIZ_(NextMarker);
147             PDesc.StoredWidth = SIZ_.Xsize();
148             PDesc.StoredHeight = SIZ_.Ysize();
149             PDesc.AspectRatio = Rational(SIZ_.Xsize(), SIZ_.Ysize());
150             PDesc.Rsize = SIZ_.Rsize();
151             PDesc.Xsize = SIZ_.Xsize();
152             PDesc.Ysize = SIZ_.Ysize();
153             PDesc.XOsize = SIZ_.XOsize();
154             PDesc.YOsize = SIZ_.YOsize();
155             PDesc.XTsize = SIZ_.XTsize();
156             PDesc.YTsize = SIZ_.YTsize();
157             PDesc.XTOsize = SIZ_.XTOsize();
158             PDesc.YTOsize = SIZ_.YTOsize();
159             PDesc.Csize = SIZ_.Csize();
160
161             if ( PDesc.Csize != 3 )
162               {
163                 DefaultLogSink().Error("Unexpected number of components: %u\n", PDesc.Csize);
164                 return RESULT_RAW_FORMAT;
165               }
166             
167             for ( i = 0; i < PDesc.Csize; i++ )
168               SIZ_.ReadComponent(i, PDesc.ImageComponents[i]);
169           }
170           break;
171
172         case MRK_COD:
173           memset(&PDesc.CodingStyleDefault, 0, sizeof(CodingStyleDefault_t));
174
175           if ( NextMarker.m_DataSize > sizeof(CodingStyleDefault_t) )
176             {
177               DefaultLogSink().Error("Unexpectedly large CodingStyle data: %u\n", NextMarker.m_DataSize);
178               return RESULT_RAW_FORMAT;
179             }
180           
181           memcpy(&PDesc.CodingStyleDefault, NextMarker.m_Data, NextMarker.m_DataSize);
182           break;
183
184         case MRK_QCD:
185           memset(&PDesc.QuantizationDefault, 0, sizeof(QuantizationDefault_t));
186
187           if ( NextMarker.m_DataSize < 16 )
188             {
189               DefaultLogSink().Error("No quantization signaled\n");
190               return RESULT_RAW_FORMAT;
191             }
192           
193           if ( NextMarker.m_DataSize > MaxDefaults )
194             {
195               DefaultLogSink().Error("Quantization Default length exceeds maximum %d\n", NextMarker.m_DataSize);
196               return RESULT_RAW_FORMAT;
197             }
198
199           memcpy(&PDesc.QuantizationDefault, NextMarker.m_Data, NextMarker.m_DataSize);
200           PDesc.QuantizationDefault.SPqcdLength = NextMarker.m_DataSize - 1;
201           break;
202
203         case MRK_NIL:
204         case MRK_SOC:
205         case MRK_SOT:
206         case MRK_EOC:
207         case MRK_COC:
208         case MRK_RGN:
209         case MRK_QCC:
210         case MRK_POC:
211         case MRK_TLM:
212         case MRK_PLM:
213         case MRK_PLT:
214         case MRK_PPM:
215         case MRK_PPT:
216         case MRK_SOP:
217         case MRK_EPH:
218         case MRK_CRG:
219         case MRK_COM:
220           /* Keep gcc quiet */
221           break;
222         }
223     }
224
225   return result;
226 }
227
228 //------------------------------------------------------------------------------------------
229
230 ASDCP::JP2K::CodestreamParser::CodestreamParser()
231 {
232 }
233
234 ASDCP::JP2K::CodestreamParser::~CodestreamParser()
235 {
236 }
237
238 // Opens the stream for reading, parses enough data to provide a complete
239 // set of stream metadata for the MXFWriter below.
240 ASDCP::Result_t
241 ASDCP::JP2K::CodestreamParser::OpenReadFrame(const char* filename, FrameBuffer& FB) const
242 {
243   const_cast<ASDCP::JP2K::CodestreamParser*>(this)->m_Parser = new h__CodestreamParser;
244   return m_Parser->OpenReadFrame(filename, FB);
245 }
246
247 // Opens the stream for reading, parses enough data to provide a complete
248 // set of stream metadata for the MXFWriter below.
249 ASDCP::Result_t
250 ASDCP::JP2K::CodestreamParser::OpenReadFrame(const unsigned char* data, unsigned int size, FrameBuffer& FB) const
251 {
252   const_cast<ASDCP::JP2K::CodestreamParser*>(this)->m_Parser = new h__CodestreamParser;
253   return m_Parser->OpenReadFrame(data, size, FB);
254 }
255
256 //
257 ASDCP::Result_t
258 ASDCP::JP2K::CodestreamParser::FillPictureDescriptor(PictureDescriptor& PDesc) const
259 {
260   if ( m_Parser.empty() )
261     return RESULT_INIT;
262
263   PDesc = m_Parser->m_PDesc;
264   return RESULT_OK;
265 }
266
267
268 //
269 // end Codestream_Parser.cpp
270 //