Updating Contact email
[BrunelResearch-dirac.git] / libdirac_decoder / dirac_parser.cpp
blobf676063fa4257291a2d0ce1132c44fdea7622970
1 /* ***** BEGIN LICENSE BLOCK *****
3 * $Id$ $Name$
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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.
16 * The Original Code is BBC Research and Development code.
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.
23 * Contributor(s): Anuradha Suraparaju (Original Author)
24 * Andrew Kennedy
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 ***** */
39 #include <cstring>
40 #include <libdirac_common/dirac_assertions.h>
41 #include <libdirac_decoder/dirac_cppparser.h>
42 #include <libdirac_decoder/dirac_parser.h>
43 #include <libdirac_common/dirac_exception.h>
44 #include <libdirac_common/picture.h>
45 #if defined (HAVE_MMX)
46 #include <mmintrin.h>
48 #endif
49 using namespace dirac;
51 #ifdef __cplusplus
52 extern "C" {
53 #endif
55 extern DllExport dirac_decoder_t *dirac_decoder_init(int verbose)
57 dirac_decoder_t* decoder = new dirac_decoder_t;
58 memset (decoder, 0, sizeof(dirac_decoder_t));
60 bool verbosity = verbose > 0 ? true : false;
61 DiracParser *parser = new DiracParser(verbosity);
62 decoder->parser = static_cast<void *>(parser);
64 decoder->fbuf = new dirac_framebuf_t;
65 decoder->fbuf->id = NULL;
66 decoder->fbuf->buf[0] = decoder->fbuf->buf[1] = decoder->fbuf->buf[2] = NULL;
67 return decoder;
70 extern DllExport void dirac_decoder_close(dirac_decoder_t *decoder)
72 TEST (decoder != NULL);
73 TEST (decoder->parser != NULL);
74 DiracParser *parser = static_cast<DiracParser *>(decoder->parser);
76 delete parser;
78 delete decoder->fbuf;
80 delete decoder;
82 decoder = NULL;
85 extern DllExport void dirac_buffer (dirac_decoder_t *decoder, unsigned char *start, unsigned char *end)
87 TEST (decoder != NULL);
88 TEST (decoder->parser != NULL);
89 DiracParser *parser = static_cast<DiracParser *>(decoder->parser);
91 parser->SetBuffer((char *)start, (char *)end);
94 static void set_sequence_params (const DiracParser * const parser, dirac_decoder_t *decoder)
96 TEST (parser != NULL);
97 TEST (decoder != NULL);
99 dirac_sourceparams_t *src_params = &decoder->src_params;
100 dirac_parseparams_t *parse_params = &decoder->parse_params;
101 const SourceParams& srcparams = parser->GetSourceParams();
102 const ParseParams& pparams = parser->GetParseParams();
104 parse_params->major_ver = pparams.MajorVersion();
105 parse_params->minor_ver = pparams.MinorVersion();
106 parse_params->profile = pparams.Profile();
107 parse_params->level = pparams.Level();
109 src_params->width = srcparams.Xl();
110 src_params->height = srcparams.Yl();
112 src_params->chroma = (dirac_chroma_t)srcparams.CFormat();
113 src_params->chroma_width = srcparams.ChromaWidth();
114 src_params->chroma_height = srcparams.ChromaHeight();
116 // set the source parmeters
117 src_params->source_sampling = srcparams.SourceSampling();
118 src_params->topfieldfirst = srcparams.TopFieldFirst() ? 1 : 0;
120 src_params->frame_rate.numerator = srcparams.FrameRate().m_num;
121 src_params->frame_rate.denominator = srcparams.FrameRate().m_denom;
123 src_params->pix_asr.numerator = srcparams.PixelAspectRatio().m_num;
124 src_params->pix_asr.denominator = srcparams.PixelAspectRatio().m_denom;
126 // clean area
127 src_params->clean_area.width = srcparams.CleanWidth();
128 src_params->clean_area.height = srcparams.CleanHeight();
129 src_params->clean_area.left_offset = srcparams.LeftOffset();
130 src_params->clean_area.top_offset = srcparams.TopOffset();
132 // signal range
133 src_params->signal_range.luma_offset = srcparams.LumaOffset();
134 src_params->signal_range.luma_excursion = srcparams.LumaExcursion();
135 src_params->signal_range.chroma_offset = srcparams.ChromaOffset();
136 src_params->signal_range.chroma_excursion = srcparams.ChromaExcursion();
138 // Colour specfication
139 src_params->colour_spec.col_primary = srcparams.ColourPrimariesIndex();
140 src_params->colour_spec.trans_func = srcparams.TransferFunctionIndex();
141 switch(srcparams.ColourMatrixIndex())
143 case CM_SDTV:
144 src_params->colour_spec.col_matrix.kr = 0.299f;
145 src_params->colour_spec.col_matrix.kb = 0.114f;
146 break;
147 case CM_REVERSIBLE:
148 src_params->colour_spec.col_matrix.kr = 0.25f;
149 src_params->colour_spec.col_matrix.kb = 0.25f;
150 break;
151 case CM_HDTV_COMP_INTERNET:
152 default:
153 src_params->colour_spec.col_matrix.kr = 0.2126f;
154 src_params->colour_spec.col_matrix.kb = 0.0722f;
155 break;
159 static void set_frame_component (const PicArray& pic_data, const CompSort cs, dirac_decoder_t *decoder)
161 TEST (decoder->fbuf != NULL);
162 int xl, yl;
164 unsigned char *buf;
166 switch (cs)
168 case U_COMP:
169 xl = decoder->src_params.chroma_width;
170 yl = decoder->src_params.chroma_height;
171 buf = decoder->fbuf->buf[1];
172 break;
173 case V_COMP:
174 xl = decoder->src_params.chroma_width;
175 yl = decoder->src_params.chroma_height;
176 buf = decoder->fbuf->buf[2];
177 break;
179 case Y_COMP:
180 default:
181 xl = decoder->src_params.width;
182 yl = decoder->src_params.height;
183 buf = decoder->fbuf->buf[0];
184 break;
187 TEST (buf != NULL);
189 #if defined HAVE_MMX
190 int last_idx = (xl>>3)<<3;
191 __m64 tmp = _mm_set_pi16(128, 128, 128, 128);
192 for (int j=0 ; j<yl ;++j)
194 for (int i=0 ; i<last_idx ; i+=8 )
196 __m64 pic1 = *(__m64 *)&pic_data[j][i];
197 pic1 = _mm_add_pi16 (pic1, tmp);
198 __m64 pic2 = *(__m64 *)(&pic_data[j][i+4]);
199 pic2 = _mm_add_pi16 (pic2, tmp);
200 __m64 *tmp = (__m64 *)&buf[j*xl+i];
201 *tmp = _mm_packs_pu16 (pic1, pic2);
202 }//i
203 }//j
204 _mm_empty();
206 // mop up remaining pixels
207 for (int j=0 ; j<yl ;++j)
209 for (int i=last_idx ; i<xl ; i++ )
211 buf[j*xl+i]=(unsigned char) (pic_data[j][i]+128);
212 }//i
213 }//j
214 return;
215 #else
217 for (int j=0 ; j<yl ;++j)
219 for (int i=0 ; i<xl ; ++i)
221 buf[j*xl+i]=(unsigned char) (pic_data[j][i]+128);
222 }//i
223 }//j
225 #endif
228 static void set_field_component (const PicArray& pic_data, const CompSort cs, dirac_decoder_t *decoder, unsigned int pic_num)
230 TEST (decoder->fbuf != NULL);
231 int xl, yl;
233 unsigned char *buf;
235 switch (cs)
237 case U_COMP:
238 xl = decoder->src_params.chroma_width;
239 yl = decoder->src_params.chroma_height;
240 buf = decoder->fbuf->buf[1];
241 break;
242 case V_COMP:
243 xl = decoder->src_params.chroma_width;
244 yl = decoder->src_params.chroma_height;
245 buf = decoder->fbuf->buf[2];
246 break;
248 case Y_COMP:
249 default:
250 xl = decoder->src_params.width;
251 yl = decoder->src_params.height;
252 buf = decoder->fbuf->buf[0];
253 break;
256 TEST (buf != NULL);
258 // Seek offset before writing field to store
259 int start = 0;
260 // Seek offset between writing fields to store
261 int skip = 0;
264 bool top_field = decoder->src_params.topfieldfirst ? (!(pic_num%2)) :
265 (pic_num%2);
267 if (top_field) // i.e. top field
269 start = 0;
270 skip = 2 * xl * sizeof(char);
272 else // else bottom field
274 start = xl;
275 skip = 2 * xl * sizeof(char);
278 unsigned char *tempc = buf + start;
280 int field_yl = yl>>1;
281 int field_xl = xl;
283 for (int j=0 ; j<field_yl ;++j)
285 for (int i=0 ; i<field_xl ; ++i)
287 tempc[i] = (unsigned char) (pic_data[j][i]+128);
288 }//I
289 tempc += skip;
293 static void set_frame_data (const DiracParser * const parser, dirac_decoder_t *decoder)
295 TEST (parser != NULL);
296 TEST (decoder != NULL);
297 TEST (decoder->fbuf != NULL);
298 TEST (decoder->state == STATE_PICTURE_AVAIL);
300 const Picture* my_picture = parser->GetNextPicture();
302 if (my_picture)
304 int pic_num = my_picture->GetPparams().PictureNum();
306 if (!parser->GetDecoderParams().FieldCoding())
308 set_frame_component (my_picture->Data(Y_COMP), Y_COMP, decoder);
309 set_frame_component (my_picture->Data(U_COMP), U_COMP, decoder);
310 set_frame_component (my_picture->Data(V_COMP), V_COMP, decoder);
312 else
314 set_field_component (my_picture->Data(Y_COMP), Y_COMP, decoder, pic_num);
315 set_field_component (my_picture->Data(U_COMP), U_COMP, decoder, pic_num);
316 set_field_component (my_picture->Data(V_COMP), V_COMP, decoder, pic_num);
319 return;
322 extern DllExport dirac_decoder_state_t dirac_parse (dirac_decoder_t *decoder)
324 TEST (decoder != NULL);
325 TEST (decoder->parser != NULL);
326 DiracParser *parser = static_cast<DiracParser *>(decoder->parser);
328 unsigned int pic_num;
330 while(true)
334 decoder->state = parser->Parse();
336 switch (decoder->state)
338 case STATE_BUFFER:
339 return decoder->state;
340 break;
342 case STATE_SEQUENCE:
343 set_sequence_params(parser, decoder);
344 decoder->frame_avail = 0;
345 return decoder->state;
346 break;
348 case STATE_PICTURE_AVAIL:
350 const Picture *my_picture = parser->GetNextPicture();
351 if (my_picture)
353 pic_num = parser->GetNextPicture()->GetPparams().PictureNum();
354 decoder->frame_num = pic_num;
355 set_frame_data (parser, decoder);
357 /* A full frame is only available if we're doing
358 * progressive coding or have decoded the second field.
359 * Will only return when a full frame is available
361 if (!parser->GetDecoderParams().FieldCoding() ||
362 pic_num%2)
364 /* Frame number currently available for display */
365 decoder->frame_num = pic_num;
366 if (parser->GetDecoderParams().FieldCoding())
367 decoder->frame_num = pic_num>>1;
368 decoder->frame_avail = 1;
369 return decoder->state;
372 break;
375 case STATE_INVALID:
376 return decoder->state;
377 break;
379 case STATE_SEQUENCE_END:
380 return decoder->state;
381 break;
383 default:
384 break;
386 }//try
387 catch (const DiracException& e)
389 return STATE_INVALID;
393 return decoder->state;
396 extern DllExport void dirac_set_buf (dirac_decoder_t *decoder, unsigned char *buf[3], void *id)
398 TEST (decoder != NULL);
399 TEST (decoder->fbuf != NULL);
401 decoder->fbuf->buf[0] = buf[0];
402 decoder->fbuf->buf[1] = buf[1];
403 decoder->fbuf->buf[2] = buf[2];
404 decoder->fbuf->id = id;
407 #ifdef __cplusplus
409 #endif