1 /* ***** BEGIN LICENSE BLOCK *****
2 *
3 * $Id: dirac_cppparser.cpp,v 1.13 2008/05/02 06:05:04 asuraparaju Exp $ $Name: Dirac_1_0_2 $
4 *
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 *
7 * The contents of this file are subject to the Mozilla Public License
8 * Version 1.1 (the "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
11 *
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
14 * the specific language governing rights and limitations under the License.
15 *
16 * The Original Code is BBC Research and Development code.
17 *
18 * The Initial Developer of the Original Code is the British Broadcasting
19 * Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 2004.
21 * All Rights Reserved.
22 *
23 * Contributor(s): Anuradha Suraparaju (Original Author),
24 *                 Andrew Kennedy
25 *
26 * Alternatively, the contents of this file may be used under the terms of
27 * the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
28 * Public License Version 2.1 (the "LGPL"), in which case the provisions of
29 * the GPL or the LGPL are applicable instead of those above. If you wish to
30 * allow use of your version of this file only under the terms of the either
31 * the GPL or LGPL and not to allow others to use your version of this file
32 * under the MPL, indicate your decision by deleting the provisions above
33 * and replace them with the notice and other provisions required by the GPL
34 * or LGPL. If you do not delete the provisions above, a recipient may use
35 * your version of this file under the terms of any one of the MPL, the GPL
36 * or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
38 
39 #include <sstream>
40 #include <cstdio>
41 #include <cstring>
42 #include <libdirac_common/dirac_assertions.h>
43 #include <libdirac_decoder/dirac_cppparser.h>
44 #include <libdirac_decoder/seq_decompress.h>
45 #include <libdirac_common/picture.h>
46 #include <libdirac_byteio/parseunit_byteio.h>
47 #include <sstream>
48 using namespace dirac;
49 
50 
InputStreamBuffer()51 InputStreamBuffer::InputStreamBuffer()
52 {
53     m_chunk_buffer = new char[m_buffer_size];
54 
55     setg (m_chunk_buffer,  //beginning of read area
56           m_chunk_buffer,  //read position
57           m_chunk_buffer); //end position
58 }
59 
Rewind()60 std::ios::pos_type InputStreamBuffer::Rewind()
61 {
62     return Seek(0, std::ios::beg);
63 }
64 
Tell()65 std::ios::pos_type InputStreamBuffer::Tell()
66 {
67     return gptr() - eback();
68 }
69 
Seek(std::ios::pos_type bytes,std::ios::seekdir dir)70 std::ios::pos_type InputStreamBuffer::Seek(std::ios::pos_type bytes, std::ios::seekdir dir)
71 {
72     char *new_pos;
73 
74     switch (dir)
75     {
76     case std::ios::beg:
77         new_pos  = eback() + bytes;
78         break;
79     case std::ios::end:
80         new_pos  = egptr() + bytes;
81         break;
82     default:
83         new_pos  = gptr() + bytes;
84         break;
85     }
86     if (new_pos > egptr() || new_pos < eback())
87         return -1;
88 
89     setg(eback(), //start of read
90         new_pos, //current read position
91         egptr()); //end of stream positon
92 
93     return 0;
94 }
95 
Copy(char * start,int bytes)96 void InputStreamBuffer::Copy(char *start, int bytes)
97 {
98     //std::cerr << "eback=" << m_chunk_buffer - eback()
99      //         << "gptr=" << gptr() -m_chunk_buffer
100       //        << "egptr=" << egptr() - m_chunk_buffer << endl;
101 
102     int bytes_left = m_buffer_size - (egptr() - m_chunk_buffer);
103     if (bytes_left < bytes)
104     {
105         char *temp =  new char [m_buffer_size + bytes];
106         memcpy (temp, m_chunk_buffer, m_buffer_size);
107         setg (temp, temp+(gptr()-m_chunk_buffer), temp + (egptr() - m_chunk_buffer));
108         delete [] m_chunk_buffer;
109         m_chunk_buffer = temp;
110     }
111     //std::cerr << "eback=" << m_chunk_buffer - eback()
112      //         << "gptr=" << gptr() -m_chunk_buffer
113       //        << "egptr=" << egptr() - m_chunk_buffer << endl;
114 
115     memcpy (egptr(), start, bytes);
116     setg(m_chunk_buffer, gptr(), egptr()+bytes);
117 
118     //std::cerr << "eback=" << m_chunk_buffer - eback()
119      //         << "gptr=" << gptr() -m_chunk_buffer
120       //        << "egptr=" << egptr() - m_chunk_buffer << endl;
121 }
122 
PurgeProcessedData()123 void InputStreamBuffer::PurgeProcessedData()
124 {
125     //std::cerr << "eback=" << m_chunk_buffer - eback()
126      //         << "gptr=" << gptr() -m_chunk_buffer
127       //        << "egptr=" << egptr() - m_chunk_buffer << endl;
128 
129     if (gptr() != m_chunk_buffer)
130     {
131         memmove (m_chunk_buffer, gptr(), egptr() - gptr());
132         setg(m_chunk_buffer, m_chunk_buffer, m_chunk_buffer+(egptr() - gptr()));
133     }
134     //std::cerr << "eback=" << m_chunk_buffer - eback()
135      //         << "gptr=" << gptr() -m_chunk_buffer
136       //        << "egptr=" << egptr() - m_chunk_buffer << endl;
137 }
138 
~InputStreamBuffer()139 InputStreamBuffer::~InputStreamBuffer()
140 {
141     delete [] m_chunk_buffer;
142 }
143 
144 
DiracParser(bool verbose)145 DiracParser::DiracParser(bool verbose) :
146     m_state(STATE_BUFFER),
147     m_next_state(STATE_SEQUENCE),
148     m_show_pnum(-1),
149     m_decomp(0),
150     m_verbose(verbose)
151 {
152 
153 
154 
155 }
156 
~DiracParser()157 DiracParser::~DiracParser()
158 {
159     delete m_decomp;
160 }
161 
SetBuffer(char * start,char * end)162 void DiracParser::SetBuffer (char *start, char *end)
163 {
164     TEST (end > start);
165     m_dirac_byte_stream.AddBytes(start, end-start);
166 }
167 
Parse()168 DecoderState DiracParser::Parse()
169 {
170     while(true)
171     {
172         ParseUnitByteIO *p_parse_unit=NULL;
173         ParseUnitType pu_type=PU_UNDEFINED;
174 
175         // look for end-of-sequence flag
176         if(m_next_state==STATE_SEQUENCE_END)
177         {
178             if (!m_decomp)
179                 return STATE_BUFFER;
180 
181             // look to see if all pictures have been processed
182             if(m_decomp->Finished())
183             {
184                 // if so....delete
185                 delete m_decomp;
186                 m_decomp=NULL;
187                 m_next_state = STATE_BUFFER;
188                 return STATE_SEQUENCE_END;
189             }
190             else
191                 // otherwise....get remaining pictures from buffer
192                 pu_type = PU_CORE_PICTURE;
193         }
194 
195         // get next parse unit from stream
196         if(m_next_state!=STATE_SEQUENCE_END)
197         {
198             p_parse_unit=m_dirac_byte_stream.GetNextParseUnit();
199             if(p_parse_unit==NULL)
200                 return STATE_BUFFER;
201             pu_type=p_parse_unit->GetType();
202         }
203 
204         switch(pu_type)
205         {
206         case PU_SEQ_HEADER:
207 
208             if(!m_decomp)
209             {
210                 m_decomp = new SequenceDecompressor (*p_parse_unit, m_verbose);
211                 m_next_state=STATE_BUFFER;
212                 return STATE_SEQUENCE;
213             }
214 
215             m_decomp->NewAccessUnit(*p_parse_unit);
216             break;
217 
218         case PU_CORE_PICTURE:
219             {
220                if (!m_decomp)
221                    continue;
222 
223                const Picture *my_picture = m_decomp->DecompressNextPicture(p_parse_unit);
224                 if (my_picture)
225                 {
226                     int picturenum_decoded = my_picture->GetPparams().PictureNum();
227                     if (picturenum_decoded != m_show_pnum)
228                     {
229                         m_show_pnum = my_picture->GetPparams().PictureNum();
230                         if (m_verbose)
231                         {
232                             std::cout << std::endl;
233                             std::cout << "Picture ";
234                             std::cout<< m_show_pnum << " available";
235                         }
236                         m_state = STATE_PICTURE_AVAIL;
237                         return m_state;
238                     }
239                 }
240             break;
241             }
242         case PU_END_OF_SEQUENCE:
243             m_next_state = STATE_SEQUENCE_END;
244             break;
245 
246         case PU_AUXILIARY_DATA:
247         case PU_PADDING_DATA:
248             if (m_verbose)
249                 std::cerr << "Ignoring Auxiliary/Padding data" << std::endl;
250             // Ignore auxiliary and padding data and continue parsing
251             break;
252         case PU_LOW_DELAY_PICTURE:
253             if (m_verbose)
254                 std::cerr << "Low delay picture decoding not yet supported" << std::endl;
255             return STATE_INVALID;
256 
257         default:
258             return STATE_INVALID;
259         }
260 
261     }
262 }
263 
GetSourceParams() const264 const SourceParams& DiracParser::GetSourceParams() const
265 {
266     return m_decomp->GetSourceParams();
267 }
268 
GetDecoderParams() const269 const DecoderParams& DiracParser::GetDecoderParams() const
270 {
271     return m_decomp->GetDecoderParams();
272 }
273 
GetParseParams() const274 const ParseParams& DiracParser::GetParseParams() const
275 {
276     return m_decomp->GetParseParams();
277 }
278 
GetNextPictureParams() const279 const PictureParams* DiracParser::GetNextPictureParams() const
280 {
281     return m_decomp->GetNextPictureParams();
282 }
283 
GetNextPicture() const284 const Picture* DiracParser::GetNextPicture() const
285 {
286     return m_decomp->GetNextPicture();
287 }
288