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