1 // Copyright (c) 2017-2019 Intel Corporation
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in all
11 // copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 // SOFTWARE.
20
21 #include "umc_defs.h"
22 #if defined (MFX_ENABLE_MJPEG_VIDEO_DECODE)
23
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include "jpegbase.h"
28 #include "jpegdec_base.h"
29
30 #include "vm_debug.h"
31
CJPEGDecoderBase(void)32 CJPEGDecoderBase::CJPEGDecoderBase(void)
33 {
34 Reset();
35 return;
36 } // ctor
37
38
~CJPEGDecoderBase(void)39 CJPEGDecoderBase::~CJPEGDecoderBase(void)
40 {
41 Clean();
42 return;
43 } // dtor
44
45
Reset(void)46 void CJPEGDecoderBase::Reset(void)
47 {
48 m_jpeg_width = 0;
49 m_jpeg_height = 0;
50 m_jpeg_ncomp = 0;
51 m_jpeg_precision = 8;
52 m_jpeg_sampling = JS_OTHER;
53 m_jpeg_color = JC_UNKNOWN;
54
55 m_jpeg_mode = JPEG_UNKNOWN;
56
57 m_jfif_app0_detected = 0;
58 m_jfif_app0_major = 0;
59 m_jfif_app0_minor = 0;
60 m_jfif_app0_units = 0;
61 m_jfif_app0_xDensity = 0;
62 m_jfif_app0_yDensity = 0;
63 m_jfif_app0_thumb_width = 0;
64 m_jfif_app0_thumb_height = 0;
65
66 m_jfxx_app0_detected = 0;
67 m_jfxx_thumbnails_type = 0;
68
69 m_avi1_app0_detected = 0;
70 m_avi1_app0_polarity = 0;
71 m_avi1_app0_reserved = 0;
72 m_avi1_app0_field_size = 0;
73 m_avi1_app0_field_size2 = 0;
74
75 m_adobe_app14_detected = 0;
76 m_adobe_app14_version = 0;
77 m_adobe_app14_flags0 = 0;
78 m_adobe_app14_flags1 = 0;
79 m_adobe_app14_transform = 0;
80
81 m_precision = 0;
82 m_max_hsampling = 0;
83 m_max_vsampling = 0;
84 m_sos_len = 0;
85 m_curr_comp_no = 0;
86 m_num_scans = 0;
87 for(int i = 0; i < MAX_SCANS_PER_FRAME; i++)
88 {
89 m_scans[i].scan_no = i;
90 m_scans[i].jpeg_restart_interval = 0;
91 m_scans[i].min_h_factor = 0;
92 m_scans[i].min_v_factor = 0;
93 m_scans[i].numxMCU = 0;
94 m_scans[i].numyMCU = 0;
95 m_scans[i].mcuWidth = 0;
96 m_scans[i].mcuHeight = 0;
97 m_scans[i].xPadding = 0;
98 m_scans[i].yPadding = 0;
99 m_scans[i].ncomps = 0;
100 m_scans[i].first_comp = 0;
101 }
102 m_curr_scan = &m_scans[0];
103 m_ss = 0;
104 m_se = 0;
105 m_al = 0;
106 m_ah = 0;
107 m_marker = JM_NONE;
108
109 m_nblock = 0;
110
111 m_stream_in.Close();
112 return;
113 } // CJPEGDecoderBase::Reset(void)
114
115
Clean(void)116 JERRCODE CJPEGDecoderBase::Clean(void)
117 {
118 int i;
119
120 m_avi1_app0_detected = 0;
121 m_avi1_app0_polarity = 0;
122 m_avi1_app0_reserved = 0;
123 m_avi1_app0_field_size = 0;
124 m_avi1_app0_field_size2 = 0;
125
126 m_jfif_app0_detected = 0;
127 m_jfxx_app0_detected = 0;
128
129 m_adobe_app14_detected = 0;
130
131 m_curr_scan->ncomps = 0;
132
133 for(i = 0; i < MAX_COMPS_PER_SCAN; i++)
134 {
135 if(0 != m_ccomp[i].m_curr_row)
136 {
137 free(m_ccomp[i].m_curr_row);
138 m_ccomp[i].m_curr_row = 0;
139 }
140 if(0 != m_ccomp[i].m_prev_row)
141 {
142 free(m_ccomp[i].m_prev_row);
143 m_ccomp[i].m_prev_row = 0;
144 }
145 }
146
147 for(i = 0; i < MAX_HUFF_TABLES; i++)
148 {
149 m_dctbl[i].Destroy();
150 m_actbl[i].Destroy();
151 }
152
153 return JPEG_OK;
154 } // CJPEGDecoderBase::Clean()
155
156
157 #define BS_BUFLEN 16384
158
SetSource(const uint8_t * pBuf,size_t buflen)159 JERRCODE CJPEGDecoderBase::SetSource(const uint8_t* pBuf, size_t buflen)
160 {
161 JERRCODE jerr = m_stream_in.Open(pBuf, buflen);
162 if(JPEG_OK != jerr)
163 return jerr;
164
165 jerr = m_BitStreamIn.Attach(&m_stream_in);
166 if(JPEG_OK != jerr)
167 return jerr;
168
169 return m_BitStreamIn.Init(BS_BUFLEN);
170 } // CJPEGDecoderBase::SetSource()
171
Seek(long offset,int origin)172 JERRCODE CJPEGDecoderBase::Seek(long offset, int origin)
173 {
174 return m_stream_in.Seek(offset, origin);
175 }// CJPEGDecoderBase::Seek
176
DetectSampling(void)177 JERRCODE CJPEGDecoderBase::DetectSampling(void)
178 {
179 switch(m_jpeg_ncomp)
180 {
181 case 1:
182 if(m_ccomp[0].m_hsampling == 1 && m_ccomp[0].m_vsampling == 1)
183 {
184 m_jpeg_sampling = JS_444;
185 }
186 else
187 {
188 return JPEG_ERR_BAD_DATA;
189 }
190 break;
191
192 case 3:
193 if(m_ccomp[0].m_hsampling == 1 && m_ccomp[0].m_vsampling == 1 &&
194 m_ccomp[1].m_hsampling == 1 && m_ccomp[1].m_vsampling == 1 &&
195 m_ccomp[2].m_hsampling == 1 && m_ccomp[2].m_vsampling == 1)
196 {
197 m_jpeg_sampling = JS_444;
198 }
199 else if(m_ccomp[0].m_hsampling == 2 && m_ccomp[0].m_vsampling == 1 &&
200 m_ccomp[1].m_hsampling == 1 && m_ccomp[1].m_vsampling == 1 &&
201 m_ccomp[2].m_hsampling == 1 && m_ccomp[2].m_vsampling == 1)
202 {
203 m_jpeg_sampling = JS_422H;
204 }
205 else if(m_ccomp[0].m_hsampling == 1 && m_ccomp[0].m_vsampling == 2 &&
206 m_ccomp[1].m_hsampling == 1 && m_ccomp[1].m_vsampling == 1 &&
207 m_ccomp[2].m_hsampling == 1 && m_ccomp[2].m_vsampling == 1)
208 {
209 m_jpeg_sampling = JS_422V;
210 }
211 else if(m_ccomp[0].m_hsampling == 2 && m_ccomp[0].m_vsampling == 2 &&
212 m_ccomp[1].m_hsampling == 1 && m_ccomp[1].m_vsampling == 1 &&
213 m_ccomp[2].m_hsampling == 1 && m_ccomp[2].m_vsampling == 1)
214 {
215 m_jpeg_sampling = JS_420;
216 }
217 else if(m_ccomp[0].m_hsampling == 4 && m_ccomp[0].m_vsampling == 1 &&
218 m_ccomp[1].m_hsampling == 1 && m_ccomp[1].m_vsampling == 1 &&
219 m_ccomp[2].m_hsampling == 1 && m_ccomp[2].m_vsampling == 1)
220 {
221 m_jpeg_sampling = JS_411;
222 }
223 else
224 {
225 m_jpeg_sampling = JS_OTHER;
226 }
227 break;
228
229 case 4:
230 if(m_ccomp[0].m_hsampling == 1 && m_ccomp[0].m_vsampling == 1 &&
231 m_ccomp[1].m_hsampling == 1 && m_ccomp[1].m_vsampling == 1 &&
232 m_ccomp[2].m_hsampling == 1 && m_ccomp[2].m_vsampling == 1 &&
233 m_ccomp[3].m_hsampling == 1 && m_ccomp[3].m_vsampling == 1)
234 {
235 m_jpeg_sampling = JS_444;
236 }
237 else if(m_ccomp[0].m_hsampling == 2 && m_ccomp[0].m_vsampling == 1 &&
238 m_ccomp[1].m_hsampling == 1 && m_ccomp[1].m_vsampling == 1 &&
239 m_ccomp[2].m_hsampling == 1 && m_ccomp[2].m_vsampling == 1 &&
240 m_ccomp[3].m_hsampling == 2 && m_ccomp[3].m_vsampling == 1)
241 {
242 m_jpeg_sampling = JS_422H;
243 }
244 else if(m_ccomp[0].m_hsampling == 1 && m_ccomp[0].m_vsampling == 2 &&
245 m_ccomp[1].m_hsampling == 1 && m_ccomp[1].m_vsampling == 1 &&
246 m_ccomp[2].m_hsampling == 1 && m_ccomp[2].m_vsampling == 1 &&
247 m_ccomp[3].m_hsampling == 1 && m_ccomp[3].m_vsampling == 2)
248 {
249 m_jpeg_sampling = JS_422V;
250 }
251 else if(m_ccomp[0].m_hsampling == 2 && m_ccomp[0].m_vsampling == 2 &&
252 m_ccomp[1].m_hsampling == 1 && m_ccomp[1].m_vsampling == 1 &&
253 m_ccomp[2].m_hsampling == 1 && m_ccomp[2].m_vsampling == 1 &&
254 m_ccomp[3].m_hsampling == 2 && m_ccomp[3].m_vsampling == 2)
255 {
256 m_jpeg_sampling = JS_420;
257 }
258 else if(m_ccomp[0].m_hsampling == 4 && m_ccomp[0].m_vsampling == 1 &&
259 m_ccomp[1].m_hsampling == 1 && m_ccomp[1].m_vsampling == 1 &&
260 m_ccomp[2].m_hsampling == 1 && m_ccomp[2].m_vsampling == 1 &&
261 m_ccomp[3].m_hsampling == 4 && m_ccomp[3].m_vsampling == 1)
262 {
263 m_jpeg_sampling = JS_411;
264 }
265 else
266 {
267 m_jpeg_sampling = JS_OTHER;
268 }
269 break;
270 }
271
272 return JPEG_OK;
273 } // CJPEGDecoderBase::DetectSampling()
274
275
NextMarker(JMARKER * marker)276 JERRCODE CJPEGDecoderBase::NextMarker(JMARKER* marker)
277 {
278 int c;
279 int n;
280 JERRCODE jerr;
281
282 n = 0;
283
284 for(;;)
285 {
286 jerr = m_BitStreamIn.ReadByte(&c);
287 if(JPEG_OK != jerr)
288 return jerr;
289
290 if(c != 0xff)
291 {
292 do
293 {
294 n++;
295
296 jerr = m_BitStreamIn.ReadByte(&c);
297 if(JPEG_OK != jerr)
298 return jerr;
299
300 } while(c != 0xff);
301 }
302
303 do
304 {
305 jerr = m_BitStreamIn.ReadByte(&c);
306 if(JPEG_OK != jerr)
307 return jerr;
308
309 } while(c == 0xff);
310
311 if(c != 0)
312 {
313 *marker = (JMARKER)c;
314 break;
315 }
316 }
317
318 if(n != 0)
319 {
320 TRC1(" skip enormous bytes - ",n);
321 }
322
323 return JPEG_OK;
324 } // CJPEGDecoderBase::NextMarker()
325
326
SkipMarker(void)327 JERRCODE CJPEGDecoderBase::SkipMarker(void)
328 {
329 int len;
330 JERRCODE jerr;
331
332 jerr = m_BitStreamIn.ReadWord(&len);
333 if(JPEG_OK != jerr)
334 return jerr;
335
336 jerr = m_BitStreamIn.Seek(len - 2);
337 if(JPEG_OK != jerr)
338 return jerr;
339
340 m_marker = JM_NONE;
341
342 return JPEG_OK;
343 } // CJPEGDecoderBase::SkipMarker()
344
ParseSOI(void)345 JERRCODE CJPEGDecoderBase::ParseSOI(void)
346 {
347 TRC0("-> SOI");
348 m_marker = JM_NONE;
349 return JPEG_OK;
350 } // CJPEGDecoderBase::ParseSOI()
351
352
ParseEOI(void)353 JERRCODE CJPEGDecoderBase::ParseEOI(void)
354 {
355 TRC0("-> EOI");
356 m_marker = JM_NONE;
357 return JPEG_OK;
358 } // CJPEGDecoderBase::ParseEOI()
359
360
361 const int APP0_JFIF_LENGTH = 14;
362 const int APP0_JFXX_LENGTH = 6;
363 const int APP0_AVI1_LENGTH = 14;
364
ParseAPP0(void)365 JERRCODE CJPEGDecoderBase::ParseAPP0(void)
366 {
367 int b0, b1, b2, b3, b4;
368 int len;
369 JERRCODE jerr;
370
371 TRC0("-> APP0");
372
373 jerr = m_BitStreamIn.ReadWord(&len);
374 if(JPEG_OK != jerr)
375 return jerr;
376
377 len -= 2;
378
379 jerr = m_BitStreamIn.CheckByte(0,&b0);
380 if(JPEG_OK != jerr)
381 return jerr;
382
383 jerr = m_BitStreamIn.CheckByte(1,&b1);
384 if(JPEG_OK != jerr)
385 return jerr;
386
387 jerr = m_BitStreamIn.CheckByte(2,&b2);
388 if(JPEG_OK != jerr)
389 return jerr;
390
391 jerr = m_BitStreamIn.CheckByte(3,&b3);
392 if(JPEG_OK != jerr)
393 return jerr;
394
395 jerr = m_BitStreamIn.CheckByte(4,&b4);
396 if(JPEG_OK != jerr)
397 return jerr;
398
399 if(len >= APP0_JFIF_LENGTH &&
400 b0 == 0x4a && // J
401 b1 == 0x46 && // F
402 b2 == 0x49 && // I
403 b3 == 0x46 && // F
404 b4 == 0)
405 {
406 // we've found JFIF APP0 marker
407 len -= 5;
408
409 jerr = m_BitStreamIn.Seek(5);
410 if(JPEG_OK != jerr)
411 return jerr;
412
413 m_jfif_app0_detected = 1;
414
415 jerr = m_BitStreamIn.ReadByte(&m_jfif_app0_major);
416 if(JPEG_OK != jerr)
417 return jerr;
418
419 jerr = m_BitStreamIn.ReadByte(&m_jfif_app0_minor);
420 if(JPEG_OK != jerr)
421 return jerr;
422
423 jerr = m_BitStreamIn.ReadByte(&m_jfif_app0_units);
424 if(JPEG_OK != jerr)
425 return jerr;
426
427 jerr = m_BitStreamIn.ReadWord(&m_jfif_app0_xDensity);
428 if(JPEG_OK != jerr)
429 return jerr;
430
431 jerr = m_BitStreamIn.ReadWord(&m_jfif_app0_yDensity);
432 if(JPEG_OK != jerr)
433 return jerr;
434
435 jerr = m_BitStreamIn.ReadByte(&m_jfif_app0_thumb_width);
436 if(JPEG_OK != jerr)
437 return jerr;
438
439 jerr = m_BitStreamIn.ReadByte(&m_jfif_app0_thumb_height);
440 if(JPEG_OK != jerr)
441 return jerr;
442
443 len -= 9;
444 }
445
446 jerr = m_BitStreamIn.CheckByte(0,&b0);
447 if(JPEG_OK != jerr)
448 return jerr;
449
450 jerr = m_BitStreamIn.CheckByte(1,&b1);
451 if(JPEG_OK != jerr)
452 return jerr;
453
454 jerr = m_BitStreamIn.CheckByte(2,&b2);
455 if(JPEG_OK != jerr)
456 return jerr;
457
458 jerr = m_BitStreamIn.CheckByte(3,&b3);
459 if(JPEG_OK != jerr)
460 return jerr;
461
462 jerr = m_BitStreamIn.CheckByte(4,&b4);
463 if(JPEG_OK != jerr)
464 return jerr;
465
466 if(len >= APP0_JFXX_LENGTH &&
467 b0 == 0x4a && // J
468 b1 == 0x46 && // F
469 b2 == 0x58 && // X
470 b3 == 0x58 && // X
471 b4 == 0)
472 {
473 // we've found JFXX APP0 extension marker
474 len -= 5;
475
476 jerr = m_BitStreamIn.Seek(5);
477 if(JPEG_OK != jerr)
478 return jerr;
479
480 m_jfxx_app0_detected = 1;
481
482 jerr = m_BitStreamIn.ReadByte(&m_jfxx_thumbnails_type);
483 if(JPEG_OK != jerr)
484 return jerr;
485
486 switch(m_jfxx_thumbnails_type)
487 {
488 case 0x10: break;
489 case 0x11: break;
490 case 0x13: break;
491 default: break;
492 }
493 len -= 1;
494 }
495
496 jerr = m_BitStreamIn.CheckByte(0,&b0);
497 if(JPEG_OK != jerr)
498 return jerr;
499
500 jerr = m_BitStreamIn.CheckByte(1,&b1);
501 if(JPEG_OK != jerr)
502 return jerr;
503
504 jerr = m_BitStreamIn.CheckByte(2,&b2);
505 if(JPEG_OK != jerr)
506 return jerr;
507
508 jerr = m_BitStreamIn.CheckByte(3,&b3);
509 if(JPEG_OK != jerr)
510 return jerr;
511
512 if(len >= APP0_AVI1_LENGTH &&
513 b0 == 0x41 && // A
514 b1 == 0x56 && // V
515 b2 == 0x49 && // I
516 b3 == 0x31) // 1
517 {
518 // we've found AVI1 APP0 marker
519 len -= 4;
520
521 jerr = m_BitStreamIn.Seek(4);
522 if(JPEG_OK != jerr)
523 return jerr;
524
525 m_avi1_app0_detected = 1;
526
527 jerr = m_BitStreamIn.ReadByte(&m_avi1_app0_polarity);
528 if(JPEG_OK != jerr)
529 return jerr;
530
531 len -= 1;
532
533 if(len == 7) // old MJPEG AVI
534 len -= 7;
535
536 if(len == 9) // ODML MJPEG AVI
537 {
538 jerr = m_BitStreamIn.ReadByte(&m_avi1_app0_reserved);
539 if(JPEG_OK != jerr)
540 return jerr;
541
542 jerr = m_BitStreamIn.ReadDword(&m_avi1_app0_field_size);
543 if(JPEG_OK != jerr)
544 return jerr;
545
546 jerr = m_BitStreamIn.ReadDword(&m_avi1_app0_field_size2);
547 if(JPEG_OK != jerr)
548 return jerr;
549
550 len -= 9;
551 }
552 }
553
554 jerr = m_BitStreamIn.Seek(len);
555 if(JPEG_OK != jerr)
556 return jerr;
557
558 m_marker = JM_NONE;
559
560 return JPEG_OK;
561 } // CJPEGDecoderBase::ParseAPP0()
562
563 const int APP14_ADOBE_LENGTH = 12;
564
ParseAPP14(void)565 JERRCODE CJPEGDecoderBase::ParseAPP14(void)
566 {
567 int b0, b1, b2, b3, b4;
568 int len;
569 JERRCODE jerr;
570
571 TRC0("-> APP14");
572
573 jerr = m_BitStreamIn.ReadWord(&len);
574 if(JPEG_OK != jerr)
575 return jerr;
576
577 len -= 2;
578
579 jerr = m_BitStreamIn.CheckByte(0,&b0);
580 if(JPEG_OK != jerr)
581 return jerr;
582
583 jerr = m_BitStreamIn.CheckByte(1,&b1);
584 if(JPEG_OK != jerr)
585 return jerr;
586
587 jerr = m_BitStreamIn.CheckByte(2,&b2);
588 if(JPEG_OK != jerr)
589 return jerr;
590
591 jerr = m_BitStreamIn.CheckByte(3,&b3);
592 if(JPEG_OK != jerr)
593 return jerr;
594
595 jerr = m_BitStreamIn.CheckByte(4,&b4);
596 if(JPEG_OK != jerr)
597 return jerr;
598
599 if(len >= APP14_ADOBE_LENGTH &&
600 b0 == 0x41 && // A
601 b1 == 0x64 && // d
602 b2 == 0x6f && // o
603 b3 == 0x62 && // b
604 b4 == 0x65) // e
605 {
606 // we've found Adobe APP14 marker
607 len -= 5;
608
609 jerr = m_BitStreamIn.Seek(5);
610 if(JPEG_OK != jerr)
611 return jerr;
612
613 m_adobe_app14_detected = 1;
614
615 jerr = m_BitStreamIn.ReadWord(&m_adobe_app14_version);
616 if(JPEG_OK != jerr)
617 return jerr;
618
619 jerr = m_BitStreamIn.ReadWord(&m_adobe_app14_flags0);
620 if(JPEG_OK != jerr)
621 return jerr;
622
623 jerr = m_BitStreamIn.ReadWord(&m_adobe_app14_flags1);
624 if(JPEG_OK != jerr)
625 return jerr;
626
627 jerr = m_BitStreamIn.ReadByte(&m_adobe_app14_transform);
628 if(JPEG_OK != jerr)
629 return jerr;
630
631 TRC1(" adobe_app14_version - ",m_adobe_app14_version);
632 TRC1(" adobe_app14_flags0 - ",m_adobe_app14_flags0);
633 TRC1(" adobe_app14_flags1 - ",m_adobe_app14_flags1);
634 TRC1(" adobe_app14_transform - ",m_adobe_app14_transform);
635
636 len -= 7;
637 }
638
639 jerr = m_BitStreamIn.Seek(len);
640 if(JPEG_OK != jerr)
641 return jerr;
642
643 m_marker = JM_NONE;
644
645 return JPEG_OK;
646 } // CJPEGDecoderBase::ParseAPP14()
647
648
ParseDQT(void)649 JERRCODE CJPEGDecoderBase::ParseDQT(void)
650 {
651 int i;
652 int id;
653 int len;
654 JERRCODE jerr;
655
656 TRC0("-> DQT");
657
658 jerr = m_BitStreamIn.ReadWord(&len);
659 if(JPEG_OK != jerr)
660 return jerr;
661
662 len -= 2;
663
664 while(len > 0)
665 {
666 jerr = m_BitStreamIn.ReadByte(&id);
667 if(JPEG_OK != jerr)
668 return jerr;
669
670 int precision = (id & 0xf0) >> 4;
671
672 TRC1(" id - ",(id & 0x0f));
673 TRC1(" precision - ",precision);
674
675 if((id & 0x0f) >= MAX_QUANT_TABLES)
676 {
677 return JPEG_ERR_DQT_DATA;
678 }
679
680 int q;
681 uint8_t qnt[DCTSIZE2*sizeof(int16_t)];
682 uint8_t* pq8 = (uint8_t*) qnt;
683 uint16_t* pq16 = (uint16_t*)qnt;
684
685 for(i = 0; i < DCTSIZE2; i++)
686 {
687 if(precision)
688 {
689 jerr = m_BitStreamIn.ReadWord(&q);
690 pq16[i] = (uint16_t)q;
691 }
692 else
693 {
694 jerr = m_BitStreamIn.ReadByte(&q);
695 pq8[i] = (uint8_t)q;
696 }
697
698 if(JPEG_OK != jerr)
699 return jerr;
700 }
701
702 if(precision == 1)
703 jerr = m_qntbl[id & 0x0f].Init(id,pq16);
704 else
705 jerr = m_qntbl[id & 0x0f].Init(id,pq8);
706 if(JPEG_OK != jerr)
707 {
708 return jerr;
709 }
710
711 len -= DCTSIZE2 + DCTSIZE2*precision + 1;
712 }
713
714 if(len != 0)
715 {
716 return JPEG_ERR_DQT_DATA;
717 }
718
719 m_marker = JM_NONE;
720
721 return JPEG_OK;
722 } // CJPEGDecoderBase::ParseDQT()
723
724
ParseDHT(void)725 JERRCODE CJPEGDecoderBase::ParseDHT(void)
726 {
727 int i;
728 int len;
729 int index;
730 int count;
731 JERRCODE jerr;
732
733 TRC0("-> DHT");
734
735 jerr = m_BitStreamIn.ReadWord(&len);
736 if(JPEG_OK != jerr)
737 return jerr;
738
739 len -= 2;
740
741 int v;
742 uint8_t bits[MAX_HUFF_BITS];
743 uint8_t vals[MAX_HUFF_VALS];
744
745 memset(bits, 0, sizeof(bits));
746 memset(vals, 0, sizeof(vals));
747
748 while(len > 16)
749 {
750 jerr = m_BitStreamIn.ReadByte(&index);
751 if(JPEG_OK != jerr)
752 return jerr;
753
754 count = 0;
755 for(i = 0; i < MAX_HUFF_BITS; i++)
756 {
757 jerr = m_BitStreamIn.ReadByte(&v);
758 if(JPEG_OK != jerr)
759 return jerr;
760
761 bits[i] = (uint8_t)v;
762 count += bits[i];
763 }
764
765 len -= 16 + 1;
766
767 if(count > MAX_HUFF_VALS || count > len)
768 {
769 return JPEG_ERR_DHT_DATA;
770 }
771
772 for(i = 0; i < count; i++)
773 {
774 jerr = m_BitStreamIn.ReadByte(&v);
775 if(JPEG_OK != jerr)
776 return jerr;
777
778 vals[i] = (uint8_t)v;
779 }
780
781 len -= count;
782
783 if(index >> 4)
784 {
785 // make AC Huffman table
786 if(m_actbl[index & 0x03].IsEmpty())
787 {
788 jerr = m_actbl[index & 0x03].Create();
789 if(JPEG_OK != jerr)
790 {
791 LOG0(" Can't create AC huffman table");
792 return jerr;
793 }
794 }
795
796 TRC1(" AC Huffman Table - ",index & 0x03);
797 jerr = m_actbl[index & 0x03].Init(index & 0x03,index >> 4,bits,vals);
798 if(JPEG_OK != jerr)
799 {
800 LOG0(" Can't build AC huffman table");
801 return jerr;
802 }
803 }
804 else
805 {
806 // make DC Huffman table
807 if(m_dctbl[index & 0x03].IsEmpty())
808 {
809 jerr = m_dctbl[index & 0x03].Create();
810 if(JPEG_OK != jerr)
811 {
812 LOG0(" Can't create DC huffman table");
813 return jerr;
814 }
815 }
816
817 TRC1(" DC Huffman Table - ",index & 0x03);
818 jerr = m_dctbl[index & 0x03].Init(index & 0x03,index >> 4,bits,vals);
819 if(JPEG_OK != jerr)
820 {
821 LOG0(" Can't build DC huffman table");
822 return jerr;
823 }
824 }
825 }
826
827 if(len != 0)
828 {
829 return JPEG_ERR_DHT_DATA;
830 }
831
832 m_marker = JM_NONE;
833
834 return JPEG_OK;
835 } // CJPEGDecoderBase::ParseDHT()
836
837
ParseSOF0(void)838 JERRCODE CJPEGDecoderBase::ParseSOF0(void)
839 {
840 int i;
841 int len;
842 CJPEGColorComponent* curr_comp;
843 JERRCODE jerr;
844
845 TRC0("-> SOF0");
846
847 jerr = m_BitStreamIn.ReadWord(&len);
848 if(JPEG_OK != jerr)
849 return jerr;
850
851 len -= 2;
852
853 jerr = m_BitStreamIn.ReadByte(&m_jpeg_precision);
854 if(JPEG_OK != jerr)
855 return jerr;
856
857 if(m_jpeg_precision != 8 && m_jpeg_precision != 12)
858 {
859 return JPEG_ERR_SOF_DATA;
860 }
861
862 jerr = m_BitStreamIn.ReadWord(&m_jpeg_height);
863 if(JPEG_OK != jerr)
864 return jerr;
865
866 jerr = m_BitStreamIn.ReadWord(&m_jpeg_width);
867 if(JPEG_OK != jerr)
868 return jerr;
869
870 jerr = m_BitStreamIn.ReadByte(&m_jpeg_ncomp);
871 if(JPEG_OK != jerr)
872 return jerr;
873
874 TRC1(" height - ",m_jpeg_height);
875 TRC1(" width - ",m_jpeg_width);
876 TRC1(" nchannels - ",m_jpeg_ncomp);
877
878 if(m_jpeg_ncomp < 0 || m_jpeg_ncomp > MAX_COMPS_PER_SCAN)
879 {
880 return JPEG_ERR_SOF_DATA;
881 }
882
883 len -= 6;
884
885 if(len != m_jpeg_ncomp * 3)
886 {
887 return JPEG_ERR_SOF_DATA;
888 }
889
890 for(m_nblock = 0, i = 0; i < m_jpeg_ncomp; i++)
891 {
892 curr_comp = &m_ccomp[i];
893
894 jerr = m_BitStreamIn.ReadByte(&curr_comp->m_id);
895 if(JPEG_OK != jerr)
896 return jerr;
897
898 int ss;
899
900 jerr = m_BitStreamIn.ReadByte(&ss);
901 if(JPEG_OK != jerr)
902 return jerr;
903
904 curr_comp->m_hsampling = (ss >> 4) & 0x0f;
905 curr_comp->m_vsampling = (ss ) & 0x0f;
906
907 if(m_jpeg_ncomp == 1)
908 {
909 curr_comp->m_hsampling = 1;
910 curr_comp->m_vsampling = 1;
911 }
912
913 jerr = m_BitStreamIn.ReadByte(&curr_comp->m_q_selector);
914 if(JPEG_OK != jerr)
915 return jerr;
916
917 if(curr_comp->m_hsampling <= 0 || curr_comp->m_vsampling <= 0 || curr_comp->m_q_selector >= MAX_QUANT_TABLES)
918 {
919 return JPEG_ERR_SOF_DATA;
920 }
921
922 // num of DU block per component
923 curr_comp->m_nblocks = curr_comp->m_hsampling * curr_comp->m_vsampling;
924
925 // num of DU blocks per frame
926 m_nblock += curr_comp->m_nblocks;
927
928 TRC1(" id ",curr_comp->m_id);
929 TRC1(" hsampling - ",curr_comp->m_hsampling);
930 TRC1(" vsampling - ",curr_comp->m_vsampling);
931 TRC1(" qselector - ",curr_comp->m_q_selector);
932 }
933
934 jerr = DetectSampling();
935 if(JPEG_OK != jerr)
936 {
937 return jerr;
938 }
939
940 m_max_hsampling = m_ccomp[0].m_hsampling;
941 m_max_vsampling = m_ccomp[0].m_vsampling;
942
943 for(i = 0; i < m_jpeg_ncomp; i++)
944 {
945 curr_comp = &m_ccomp[i];
946
947 if(m_max_hsampling < curr_comp->m_hsampling)
948 m_max_hsampling = curr_comp->m_hsampling;
949
950 if(m_max_vsampling < curr_comp->m_vsampling)
951 m_max_vsampling = curr_comp->m_vsampling;
952 }
953
954 for(i = 0; i < m_jpeg_ncomp; i++)
955 {
956 curr_comp = &m_ccomp[i];
957
958 curr_comp->m_h_factor = m_max_hsampling / curr_comp->m_hsampling;
959 curr_comp->m_v_factor = m_max_vsampling / curr_comp->m_vsampling;
960 }
961
962 m_jpeg_mode = JPEG_BASELINE;
963
964 m_marker = JM_NONE;
965
966 return JPEG_OK;
967 } // CJPEGDecoderBase::ParseSOF0()
968
ParseDRI(void)969 JERRCODE CJPEGDecoderBase::ParseDRI(void)
970 {
971 int len, jpeg_restart_interval;
972 JERRCODE jerr;
973
974 TRC0("-> DRI");
975
976 jerr = m_BitStreamIn.ReadWord(&len);
977 if(JPEG_OK != jerr)
978 return jerr;
979
980 len -= 2;
981
982 if(len != 2)
983 {
984 return JPEG_ERR_RST_DATA;
985 }
986
987 jerr = m_BitStreamIn.ReadWord(&jpeg_restart_interval);
988 if(JPEG_OK != jerr)
989 return jerr;
990
991 for(int i=m_curr_scan->scan_no; i<MAX_SCANS_PER_FRAME; i++)
992 {
993 m_scans[i].jpeg_restart_interval = jpeg_restart_interval;
994 }
995
996 TRC1(" restart interval - ", m_curr_scan->jpeg_restart_interval);
997
998 m_marker = JM_NONE;
999
1000 return JPEG_OK;
1001 } // CJPEGDecoderBase::ParseDRI()
1002
ParseSOS(JOPERATION op)1003 JERRCODE CJPEGDecoderBase::ParseSOS(JOPERATION op)
1004 {
1005 int i,j;
1006 int ci;
1007 int len;
1008 int gcd_found;
1009 int hsampling_gcd = 1, vsampling_gcd = 1;
1010 int hsamplings[MAX_COMPS_PER_SCAN], vsamplings[MAX_COMPS_PER_SCAN];
1011 int component_ids[MAX_COMPS_PER_SCAN];
1012 int scan_max_hsampling = 1, scan_max_vsampling = 1;
1013 int du_width, du_height;
1014 int numComps = 0;
1015 JERRCODE jerr;
1016
1017 TRC0("-> SOS");
1018
1019 jerr = m_BitStreamIn.ReadWord(&len);
1020 if(JPEG_OK != jerr)
1021 return jerr;
1022
1023 // store position to return to in subsequent ReadData call
1024 m_sos_len = len;
1025
1026 len -= 2;
1027
1028 jerr = m_BitStreamIn.ReadByte(&(m_curr_scan->ncomps));
1029 if(JPEG_OK != jerr)
1030 return jerr;
1031
1032 if(m_curr_scan->ncomps < 1 || m_curr_scan->ncomps > MAX_COMPS_PER_SCAN)
1033 {
1034 return JPEG_ERR_SOS_DATA;
1035 }
1036
1037 if(len != ((m_curr_scan->ncomps * 2) + 4))
1038 {
1039 return JPEG_ERR_SOS_DATA;
1040 }
1041
1042 TRC1(" ncomps - ",m_scan_ncomps);
1043
1044 for(i = 0; i < m_curr_scan->ncomps; i++)
1045 {
1046 int id;
1047 int huff_sel;
1048
1049 jerr = m_BitStreamIn.ReadByte(&id);
1050 if(JPEG_OK != jerr)
1051 return jerr;
1052
1053 jerr = m_BitStreamIn.ReadByte(&huff_sel);
1054 if(JPEG_OK != jerr)
1055 return jerr;
1056
1057 TRC1(" id - ",id);
1058 TRC1(" dc_selector - ",(huff_sel >> 4) & 0x0f);
1059 TRC1(" ac_selector - ",(huff_sel ) & 0x0f);
1060
1061 for(ci = 0; ci < m_jpeg_ncomp; ci++)
1062 {
1063 if(id == m_ccomp[ci].m_id)
1064 {
1065 m_curr_comp_no = ci;
1066 m_ccomp[ci].m_comp_no = ci;
1067 m_ccomp[ci].m_lastDC = 0;
1068
1069 hsamplings[numComps] = m_ccomp[ci].m_hsampling;
1070 vsamplings[numComps] = m_ccomp[ci].m_vsampling;
1071 component_ids[numComps] = ci;
1072 numComps++;
1073
1074 goto comp_id_match;
1075 }
1076 }
1077
1078 return JPEG_ERR_SOS_DATA;
1079
1080 comp_id_match:
1081
1082 m_ccomp[ci].m_dc_selector = (huff_sel >> 4) & 0x0f;
1083 if (m_ccomp[ci].m_dc_selector >= MAX_HUFF_TABLES)
1084 return JPEG_ERR_SOS_DATA;
1085
1086 m_ccomp[ci].m_ac_selector = (huff_sel ) & 0x0f;
1087 if (m_ccomp[ci].m_ac_selector >= MAX_HUFF_TABLES)
1088 return JPEG_ERR_SOS_DATA;
1089 }
1090
1091 // find greatest common divisor for sampling factors of components in scan
1092 for(i = 2; i < MAX_BLOCKS_PER_MCU; i++)
1093 {
1094 gcd_found = 1;
1095 for(j = 0; j < numComps; j++)
1096 if(hsamplings[j] % i != 0)
1097 gcd_found = 0;
1098 if(gcd_found)
1099 hsampling_gcd = i;
1100
1101 gcd_found = 1;
1102 for(j = 0; j < numComps; j++)
1103 if(vsamplings[j] % i != 0)
1104 gcd_found = 0;
1105 if(gcd_found)
1106 vsampling_gcd = i;
1107 }
1108
1109 m_curr_scan->min_h_factor = MAX_BLOCKS_PER_MCU;
1110 m_curr_scan->min_v_factor = MAX_BLOCKS_PER_MCU;
1111
1112 // setting MCU parameters for current scan
1113 for(i = 0; i < numComps; i++)
1114 {
1115 m_ccomp[component_ids[i]].m_scan_hsampling = m_ccomp[component_ids[i]].m_hsampling / hsampling_gcd;
1116 if(scan_max_hsampling < m_ccomp[component_ids[i]].m_scan_hsampling)
1117 scan_max_hsampling = m_ccomp[component_ids[i]].m_scan_hsampling;
1118
1119 m_ccomp[component_ids[i]].m_scan_vsampling = m_ccomp[component_ids[i]].m_vsampling / vsampling_gcd;
1120 if(scan_max_vsampling < m_ccomp[component_ids[i]].m_scan_vsampling)
1121 scan_max_vsampling = m_ccomp[component_ids[i]].m_scan_vsampling;
1122
1123 if(m_curr_scan->min_h_factor > m_ccomp[component_ids[i]].m_h_factor)
1124 m_curr_scan->min_h_factor = m_ccomp[component_ids[i]].m_h_factor;
1125
1126 if(m_curr_scan->min_v_factor > m_ccomp[component_ids[i]].m_v_factor)
1127 m_curr_scan->min_v_factor = m_ccomp[component_ids[i]].m_v_factor;
1128 }
1129
1130 // DU block dimensions (8x8 for DCT based modes and 1x1 for lossless mode)
1131 du_width = (JPEG_LOSSLESS == m_jpeg_mode) ? 1 : 8;
1132 du_height = (JPEG_LOSSLESS == m_jpeg_mode) ? 1 : 8;
1133
1134 // MCU dimensions
1135 m_curr_scan->mcuWidth = du_width * std::max(scan_max_hsampling, 1);
1136 m_curr_scan->mcuHeight = du_height * std::max(scan_max_vsampling, 1);
1137
1138 // num of MCUs in whole scan
1139 m_curr_scan->numxMCU = (m_jpeg_width + (m_curr_scan->mcuWidth * m_curr_scan->min_h_factor - 1))
1140 / (m_curr_scan->mcuWidth * m_curr_scan->min_h_factor);
1141 m_curr_scan->numyMCU = (m_jpeg_height + (m_curr_scan->mcuHeight * m_curr_scan->min_v_factor - 1))
1142 / (m_curr_scan->mcuHeight * m_curr_scan->min_v_factor);
1143
1144 // not completed MCUs should be padded
1145 m_curr_scan->xPadding = m_curr_scan->numxMCU * m_curr_scan->mcuWidth * m_curr_scan->min_h_factor - m_jpeg_width;
1146 m_curr_scan->yPadding = m_curr_scan->numyMCU * m_curr_scan->mcuHeight * m_curr_scan->min_v_factor - m_jpeg_height;
1147
1148 jerr = m_BitStreamIn.ReadByte(&m_ss);
1149 if(JPEG_OK != jerr)
1150 return jerr;
1151
1152 jerr = m_BitStreamIn.ReadByte(&m_se);
1153 if(JPEG_OK != jerr)
1154 return jerr;
1155
1156 int t;
1157
1158 jerr = m_BitStreamIn.ReadByte(&t);
1159 if(JPEG_OK != jerr)
1160 return jerr;
1161
1162 m_ah = (t >> 4) & 0x0f;
1163 m_al = (t ) & 0x0f;
1164
1165 TRC1(" Ss - ",m_ss);
1166 TRC1(" Se - ",m_se);
1167 TRC1(" Ah - ",m_ah);
1168 TRC1(" Al - ",m_al);
1169
1170 if(JO_READ_HEADER == op)
1171 {
1172 // detect JPEG color space
1173 if(m_jpeg_color == JC_UNKNOWN)
1174 {
1175 if(m_jfif_app0_detected)
1176 {
1177 switch(m_jpeg_ncomp)
1178 {
1179 case 1: m_jpeg_color = JC_GRAY; break;
1180 case 3: m_jpeg_color = JC_YCBCR; break;
1181 default: m_jpeg_color = JC_UNKNOWN; break;
1182 }
1183 }
1184
1185 if(m_adobe_app14_detected)
1186 {
1187 switch(m_adobe_app14_transform)
1188 {
1189 case 0:
1190 switch(m_jpeg_ncomp)
1191 {
1192 case 1: m_jpeg_color = JC_GRAY; break;
1193 case 3: m_jpeg_color = JC_RGB; break;
1194 case 4: m_jpeg_color = JC_CMYK; break;
1195 default: m_jpeg_color = JC_UNKNOWN; break;
1196 }
1197 break;
1198
1199 case 1: m_jpeg_color = JC_YCBCR; break;
1200 case 2: m_jpeg_color = JC_YCCK; break;
1201 default: m_jpeg_color = JC_UNKNOWN; break;
1202 }
1203 }
1204
1205 // try to guess what color space is used...
1206 if(!m_jfif_app0_detected && !m_adobe_app14_detected)
1207 {
1208 switch(m_jpeg_ncomp)
1209 {
1210 case 1: m_jpeg_color = JC_GRAY; break;
1211 case 3: m_jpeg_color = (m_jpeg_mode != JPEG_LOSSLESS && m_jpeg_precision == 8) ? JC_YCBCR : JC_UNKNOWN; break;
1212 default: m_jpeg_color = JC_UNKNOWN; break;
1213 }
1214 }
1215 }
1216 }
1217
1218 m_marker = JM_NONE;
1219
1220 return JPEG_OK;
1221 } // CJPEGDecoderBase::ParseSOS()
1222
ParseJPEGBitStream(JOPERATION op)1223 JERRCODE CJPEGDecoderBase::ParseJPEGBitStream(JOPERATION op)
1224 {
1225 JERRCODE jerr = JPEG_OK;
1226
1227 m_marker = JM_NONE;
1228
1229 for(;;)
1230 {
1231 if(JM_NONE == m_marker)
1232 {
1233 jerr = NextMarker(&m_marker);
1234 if(JPEG_OK != jerr)
1235 {
1236 return jerr;
1237 }
1238 }
1239
1240 switch(m_marker)
1241 {
1242 case JM_SOI:
1243 jerr = ParseSOI();
1244 if(JPEG_OK != jerr)
1245 {
1246 return jerr;
1247 }
1248 break;
1249
1250 case JM_APP0:
1251 jerr = ParseAPP0();
1252 if(JPEG_OK != jerr)
1253 {
1254 return jerr;
1255 }
1256 break;
1257
1258 case JM_APP14:
1259 jerr = ParseAPP14();
1260 if(JPEG_OK != jerr)
1261 {
1262 return jerr;
1263 }
1264 break;
1265
1266 case JM_DQT:
1267 jerr = ParseDQT();
1268 if(JPEG_OK != jerr)
1269 {
1270 return jerr;
1271 }
1272 break;
1273
1274 case JM_SOF0:
1275 jerr = ParseSOF0();
1276 if(JPEG_OK != jerr)
1277 {
1278 return jerr;
1279 }
1280 break;
1281
1282 case JM_SOF1:
1283 case JM_SOF2:
1284 case JM_SOF3:
1285 case JM_SOF5:
1286 case JM_SOF6:
1287 case JM_SOF7:
1288 case JM_SOF9:
1289 case JM_SOFA:
1290 case JM_SOFB:
1291 case JM_SOFD:
1292 case JM_SOFE:
1293 case JM_SOFF:
1294 return JPEG_NOT_IMPLEMENTED;
1295
1296 case JM_DHT:
1297 jerr = ParseDHT();
1298 if(JPEG_OK != jerr)
1299 {
1300 return jerr;
1301 }
1302 break;
1303
1304 case JM_DRI:
1305 jerr = ParseDRI();
1306 if(JPEG_OK != jerr)
1307 {
1308 return jerr;
1309 }
1310 break;
1311
1312 case JM_SOS:
1313 jerr = ParseSOS(op);
1314 if(JPEG_OK != jerr)
1315 {
1316 return jerr;
1317 }
1318
1319 if (JO_READ_HEADER == op)
1320 {
1321 if(m_BitStreamIn.GetCurrPos() - (m_sos_len + 2) != 0)
1322 {
1323 jerr = m_BitStreamIn.Seek(-(m_sos_len + 2));
1324 if(JPEG_OK != jerr)
1325 return jerr;
1326 }
1327 else
1328 {
1329 m_BitStreamIn.SetCurrPos(0);
1330 }
1331
1332 // stop here, when we are reading header
1333 return JPEG_OK;
1334 }
1335 break;
1336
1337 case JM_EOI:
1338 jerr = ParseEOI();
1339 goto Exit;
1340
1341 default:
1342 TRC1("-> Unknown marker ",m_marker);
1343 TRC0("..Skipping");
1344 jerr = SkipMarker();
1345 if(JPEG_OK != jerr)
1346 return jerr;
1347
1348 break;
1349 }
1350 }
1351
1352 Exit:
1353
1354 return jerr;
1355 } // CJPEGDecoderBase::ParseJPEGBitStream()
1356
1357
FindSOI()1358 JERRCODE CJPEGDecoderBase::FindSOI()
1359 {
1360 JERRCODE jerr = JPEG_OK;
1361 m_marker = JM_NONE;
1362
1363 for(;;)
1364 {
1365 jerr = NextMarker(&m_marker);
1366
1367 if(JM_SOI == m_marker)
1368 {
1369 if(m_BitStreamIn.GetCurrPos() - 2 != 0)
1370 {
1371 jerr = m_BitStreamIn.Seek(-2);
1372 if(JPEG_OK != jerr)
1373 return jerr;
1374 }
1375 else
1376 {
1377 m_BitStreamIn.SetCurrPos(0);
1378 }
1379 return JPEG_OK;
1380 }
1381
1382 if(JPEG_ERR_BUFF == jerr)
1383 {
1384 return JPEG_OK;
1385 }
1386
1387 if(JPEG_OK != jerr)
1388 {
1389 return jerr;
1390 }
1391 }
1392 } // CJPEGDecoderBase::ParseJPEGBitStream()
1393
ReadHeader(int * width,int * height,int * nchannels,JCOLOR * color,JSS * sampling,int * precision)1394 JERRCODE CJPEGDecoderBase::ReadHeader(
1395 int* width,
1396 int* height,
1397 int* nchannels,
1398 JCOLOR* color,
1399 JSS* sampling,
1400 int* precision)
1401 {
1402 JERRCODE jerr;
1403
1404 // parse bitstream up to SOS marker
1405 jerr = ParseJPEGBitStream(JO_READ_HEADER);
1406
1407 if(JPEG_OK != jerr)
1408 {
1409 LOG0("Error: ParseJPEGBitStream() failed");
1410 return jerr;
1411 }
1412
1413 if(JPEG_UNKNOWN == m_jpeg_mode)
1414 return JPEG_ERR_BAD_DATA;
1415
1416 *width = m_jpeg_width;
1417 *height = m_jpeg_height;
1418 *nchannels = m_jpeg_ncomp;
1419 *color = m_jpeg_color;
1420 *sampling = m_jpeg_sampling;
1421 *precision = m_jpeg_precision;
1422
1423 return JPEG_OK;
1424 } // CJPEGDecoderBase::ReadHeader()
1425
GetNumQuantTables()1426 uint16_t CJPEGDecoderBase::GetNumQuantTables()
1427 {
1428 uint16_t numTables = 0;
1429
1430 for(int i=0; i<MAX_QUANT_TABLES; i++)
1431 if(m_qntbl[i].m_initialized)
1432 numTables++;
1433
1434 return numTables;
1435 }
1436
FillQuantTable(int numTable,uint16_t * pTable)1437 JERRCODE CJPEGDecoderBase::FillQuantTable(int numTable, uint16_t* pTable)
1438 {
1439 uint8_t* qtbl = m_qntbl[numTable].m_raw8u;
1440
1441 for(int i=0; i<DCTSIZE2; i++)
1442 pTable[i] = (uint16_t)qtbl[i];
1443
1444 return JPEG_OK;
1445 }
1446
GetNumACTables()1447 uint16_t CJPEGDecoderBase::GetNumACTables()
1448 {
1449 uint16_t numTables = 0;
1450
1451 for(int i=0; i<MAX_HUFF_TABLES; i++)
1452 if(m_actbl[i].IsValid())
1453 numTables++;
1454
1455 return numTables;
1456 }
1457
FillACTable(int numTable,uint8_t * pBits,uint8_t * pValues)1458 JERRCODE CJPEGDecoderBase::FillACTable(int numTable, uint8_t* pBits, uint8_t* pValues)
1459 {
1460 const uint8_t* bits = m_actbl[numTable].GetBits();
1461 const uint8_t* values = m_actbl[numTable].GetValues();
1462
1463 MFX_INTERNAL_CPY(pBits, bits, 16);
1464 MFX_INTERNAL_CPY(pValues, values, 162);
1465
1466 return JPEG_OK;
1467 }
1468
GetNumDCTables()1469 uint16_t CJPEGDecoderBase::GetNumDCTables()
1470 {
1471 uint16_t numTables = 0;
1472
1473 for(int i=0; i<MAX_HUFF_TABLES; i++)
1474 if(m_dctbl[i].IsValid())
1475 numTables++;
1476
1477 return numTables;
1478 }
1479
FillDCTable(int numTable,uint8_t * pBits,uint8_t * pValues)1480 JERRCODE CJPEGDecoderBase::FillDCTable(int numTable, uint8_t* pBits, uint8_t* pValues)
1481 {
1482 const uint8_t* bits = m_dctbl[numTable].GetBits();
1483 const uint8_t* values = m_dctbl[numTable].GetValues();
1484
1485 MFX_INTERNAL_CPY(pBits, bits, 16);
1486 MFX_INTERNAL_CPY(pValues, values, 12);
1487
1488 return JPEG_OK;
1489 }
1490
IsInterleavedScan()1491 bool CJPEGDecoderBase::IsInterleavedScan()
1492 {
1493 if(m_curr_scan->ncomps == m_jpeg_ncomp)
1494 return true;
1495
1496 return false;
1497 }
1498
1499 #endif // MFX_ENABLE_MJPEG_VIDEO_DECODE
1500