1 /*
2  * Small jpeg decoder library
3  *
4  * Copyright (c) 2006, Luc Saillard <luc@saillard.org>
5  * Copyright (c) 2012 Intel Corporation.
6  * All rights reserved.
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * - Redistributions of source code must retain the above copyright notice,
11  *  this list of conditions and the following disclaimer.
12  *
13  * - Redistributions in binary form must reproduce the above copyright notice,
14  *  this list of conditions and the following disclaimer in the documentation
15  *  and/or other materials provided with the distribution.
16  *
17  * - Neither the name of the author nor the names of its contributors may be
18  *  used to endorse or promote products derived from this software without
19  *  specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  */
34 
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <stdint.h>
39 #include <errno.h>
40 
41 #include "tinyjpeg.h"
42 #include "tinyjpeg-internal.h"
43 
44 // for libva
45 #include <unistd.h>
46 #include <sys/types.h>
47 #include <sys/stat.h>
48 #include <fcntl.h>
49 #include <assert.h>
50 #include <va/va.h>
51 #include <va/va_dec_jpeg.h>
52 #include "va_display.h"
53 
54 
55 #define cY	0
56 #define cCb	1
57 #define cCr	2
58 
59 #define BLACK_Y 0
60 #define BLACK_U 127
61 #define BLACK_V 127
62 
63 #ifndef MIN
64 #define MIN(a, b) ((a) < (b) ? (a) : (b))
65 #endif
66 #ifndef MAX
67 #define MAX(a, b) ((a) > (b) ? (a) : (b))
68 #endif
69 #define ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0]))
70 
71 #if DEBUG
72 #define trace(fmt, args...) do { \
73    fprintf(stderr, fmt, ## args); \
74    fflush(stderr); \
75 } while(0)
76 #else
77 #define trace(fmt, args...) do { } while (0)
78 #endif
79 #define error(fmt, args...) do { \
80    snprintf(error_string, sizeof(error_string), fmt, ## args); \
81    return -1; \
82 } while(0)
83 /* The variables for different image scans */
84 static int scan_num=0;
85 static int next_image_found=0;
86 /* Global variable to return the last error found while deconding */
87 static char error_string[256];
88 static VAHuffmanTableBufferJPEGBaseline default_huffman_table_param={
89     huffman_table:
90     {
91         // lumiance component
92         {
93             num_dc_codes:{0,1,5,1,1,1,1,1,1,0,0,0}, // 12 bits is ok for baseline profile
94             dc_values:{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b},
95             num_ac_codes:{0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,125},
96             ac_values:{
97               0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
98               0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
99               0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
100               0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
101               0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
102               0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
103               0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
104               0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
105               0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
106               0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
107               0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
108               0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
109               0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
110               0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
111               0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
112               0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
113               0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
114               0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
115               0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
116               0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
117               0xf9, 0xfa
118            },/*,0xonly,0xthe,0xfirst,0x162,0xbytes,0xare,0xavailable,0x*/
119         },
120         // chrom component
121         {
122             num_dc_codes:{0,3,1,1,1,1,1,1,1,1,1,0}, // 12 bits is ok for baseline profile
123             dc_values:{0,1,2,3,4,5,6,7,8,9,0xa,0xb},
124             num_ac_codes:{0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,119},
125             ac_values:{
126               0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
127               0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
128               0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
129               0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
130               0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
131               0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
132               0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
133               0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
134               0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
135               0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
136               0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
137               0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
138               0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
139               0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
140               0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
141               0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
142               0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
143               0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
144               0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
145               0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
146               0xf9, 0xfa
147             },/*,0xonly,0xthe,0xfirst,0x162,0xbytes,0xare,0xavailable,0x*/
148         },
149     }
150 };
151 
152 #define be16_to_cpu(x) (((x)[0]<<8)|(x)[1])
153 
154 
build_default_huffman_tables(struct jdec_private * priv)155 static int build_default_huffman_tables(struct jdec_private *priv)
156 {
157     int i = 0;
158 	if (priv->default_huffman_table_initialized)
159 		return 0;
160 
161     for (i = 0; i < 4; i++) {
162         priv->HTDC_valid[i] = 1;
163         memcpy(priv->HTDC[i].bits, default_huffman_table_param.huffman_table[i].num_dc_codes, 16);
164         memcpy(priv->HTDC[i].values, default_huffman_table_param.huffman_table[i].dc_values, 16);
165         priv->HTAC_valid[i] = 1;
166         memcpy(priv->HTAC[i].bits, default_huffman_table_param.huffman_table[i].num_ac_codes, 16);
167         memcpy(priv->HTAC[i].values, default_huffman_table_param.huffman_table[i].ac_values, 256);
168     }
169 	priv->default_huffman_table_initialized = 1;
170 	return 0;
171 }
172 
173 
print_SOF(const unsigned char * stream)174 static void print_SOF(const unsigned char *stream)
175 {
176   int width, height, nr_components, precision;
177 #if DEBUG
178   const char *nr_components_to_string[] = {
179      "????",
180      "Grayscale",
181      "????",
182      "YCbCr",
183      "CYMK"
184   };
185 #endif
186 
187   precision = stream[2];
188   height = be16_to_cpu(stream+3);
189   width  = be16_to_cpu(stream+5);
190   nr_components = stream[7];
191 
192   trace("> SOF marker\n");
193   trace("Size:%dx%d nr_components:%d (%s)  precision:%d\n",
194       width, height,
195       nr_components, nr_components_to_string[nr_components],
196       precision);
197 }
198 
parse_DQT(struct jdec_private * priv,const unsigned char * stream)199 static int parse_DQT(struct jdec_private *priv, const unsigned char *stream)
200 {
201   int qi;
202   const unsigned char *dqt_block_end;
203 
204   trace("> DQT marker\n");
205   dqt_block_end = stream + be16_to_cpu(stream);
206   stream += 2;	/* Skip length */
207 
208   while (stream < dqt_block_end)
209    {
210      qi = *stream++;
211 #if SANITY_CHECK
212      if (qi>>4)
213        error("16 bits quantization table is not supported\n");
214      if (qi>4)
215        error("No more 4 quantization table is supported (got %d)\n", qi);
216 #endif
217      memcpy(priv->Q_tables[qi&0x0F], stream, 64);
218      priv->Q_tables_valid[qi & 0x0f] = 1;
219      stream += 64;
220    }
221   trace("< DQT marker\n");
222   return 0;
223 }
224 
parse_SOF(struct jdec_private * priv,const unsigned char * stream)225 static int parse_SOF(struct jdec_private *priv, const unsigned char *stream)
226 {
227   int i, width, height, nr_components, cid, sampling_factor;
228   unsigned char Q_table;
229   struct component *c;
230 
231   trace("> SOF marker\n");
232   print_SOF(stream);
233 
234   height = be16_to_cpu(stream+3);
235   width  = be16_to_cpu(stream+5);
236   nr_components = stream[7];
237   priv->nf_components = nr_components;
238 #if SANITY_CHECK
239   if (stream[2] != 8)
240     error("Precision other than 8 is not supported\n");
241   if (width>JPEG_MAX_WIDTH || height>JPEG_MAX_HEIGHT)
242     printf("WARNING:Width and Height (%dx%d) seems suspicious\n", width, height);
243   if (nr_components != 3)
244     printf("ERROR:We only support YUV images\n");
245   if (height%16)
246     printf("WARNING:Height need to be a multiple of 16 (current height is %d)\n", height);
247   if (width%16)
248     printf("WARNING:Width need to be a multiple of 16 (current Width is %d)\n", width);
249 #endif
250   stream += 8;
251   for (i=0; i<nr_components; i++) {
252      cid = *stream++;
253      sampling_factor = *stream++;
254      Q_table = *stream++;
255      c = &priv->component_infos[i];
256      c->cid = cid;
257      if (Q_table >= COMPONENTS)
258        error("Bad Quantization table index (got %d, max allowed %d)\n", Q_table, COMPONENTS-1);
259      c->Vfactor = sampling_factor&0xf;
260      c->Hfactor = sampling_factor>>4;
261      c->quant_table_index = Q_table;
262      trace("Component:%d  factor:%dx%d  Quantization table:%d\n",
263            cid, c->Hfactor, c->Vfactor, Q_table );
264 
265   }
266   priv->width[scan_num] = width;
267   priv->height[scan_num] = height;
268 
269   trace("< SOF marker\n");
270 
271   return 0;
272 }
273 
parse_SOS(struct jdec_private * priv,const unsigned char * stream)274 static int parse_SOS(struct jdec_private *priv, const unsigned char *stream)
275 {
276   unsigned int i, cid, table;
277   unsigned int nr_components = stream[2];
278 
279   trace("> SOS marker\n");
280 
281   priv->cur_sos.nr_components= nr_components;
282 
283   stream += 3;
284   for (i=0;i<nr_components;i++) {
285      cid = *stream++;
286      table = *stream++;
287      priv->cur_sos.components[i].component_id = cid;
288      priv->cur_sos.components[i].dc_selector = ((table>>4)&0x0F);
289      priv->cur_sos.components[i].ac_selector = (table&0x0F);
290 #if SANITY_CHECK
291      if ((table&0xf)>=4)
292 	error("We do not support more than 2 AC Huffman table\n");
293      if ((table>>4)>=4)
294 	error("We do not support more than 2 DC Huffman table\n");
295      if (cid != priv->component_infos[i].cid)
296         error("SOS cid order (%d:%d) isn't compatible with the SOF marker (%d:%d)\n",
297 	      i, cid, i, priv->component_infos[i].cid);
298      trace("ComponentId:%d  tableAC:%d tableDC:%d\n", cid, table&0xf, table>>4);
299 #endif
300   }
301   priv->stream = stream+3;
302   trace("< SOS marker\n");
303   return 0;
304 }
305 
tinyjpeg_parse_SOS(struct jdec_private * priv,const unsigned char * stream)306 int tinyjpeg_parse_SOS(struct jdec_private *priv, const unsigned char *stream)
307 {
308     return parse_SOS(priv, stream);
309 }
310 
311 
parse_DHT(struct jdec_private * priv,const unsigned char * stream)312 static int parse_DHT(struct jdec_private *priv, const unsigned char *stream)
313 {
314   unsigned int count, i;
315   int length, index;
316   unsigned char Tc, Th;
317 
318   length = be16_to_cpu(stream) - 2;
319   stream += 2;	/* Skip length */
320 
321   trace("> DHT marker (length=%d)\n", length);
322 
323   while (length>0) {
324      index = *stream++;
325 
326      Tc = index & 0xf0; // it is not important to <<4
327      Th = index & 0x0f;
328      if (Tc) {
329         memcpy(priv->HTAC[index & 0xf].bits, stream, 16);
330      }
331      else {
332          memcpy(priv->HTDC[index & 0xf].bits, stream, 16);
333      }
334 
335      count = 0;
336      for (i=0; i<16; i++) {
337         count += *stream++;
338      }
339 
340 #if SANITY_CHECK
341      if (count >= HUFFMAN_BITS_SIZE)
342        error("No more than %d bytes is allowed to describe a huffman table", HUFFMAN_BITS_SIZE);
343      if ( (index &0xf) >= HUFFMAN_TABLES)
344        error("No more than %d Huffman tables is supported (got %d)\n", HUFFMAN_TABLES, index&0xf);
345      trace("Huffman table %s[%d] length=%d\n", (index&0xf0)?"AC":"DC", index&0xf, count);
346 #endif
347 
348      if (Tc) {
349         memcpy(priv->HTAC[index & 0xf].values, stream, count);
350         priv->HTAC_valid[index & 0xf] = 1;
351      }
352      else {
353         memcpy(priv->HTDC[index & 0xf].values, stream, count);
354         priv->HTDC_valid[index & 0xf] = 1;
355      }
356 
357      length -= 1;
358      length -= 16;
359      length -= count;
360      stream += count;
361   }
362   trace("< DHT marker\n");
363   return 0;
364 }
parse_DRI(struct jdec_private * priv,const unsigned char * stream)365 static int parse_DRI(struct jdec_private *priv, const unsigned char *stream)
366 {
367   unsigned int length;
368 
369   trace("> DRI marker\n");
370 
371   length = be16_to_cpu(stream);
372 
373 #if SANITY_CHECK
374   if (length != 4)
375     error("Length of DRI marker need to be 4\n");
376 #endif
377 
378   priv->restart_interval = be16_to_cpu(stream+2);
379 
380 #if DEBUG
381   trace("Restart interval = %d\n", priv->restart_interval);
382 #endif
383 
384   trace("< DRI marker\n");
385 
386   return 0;
387 }
388 
findEOI(struct jdec_private * priv,const unsigned char * stream)389 static int findEOI(struct jdec_private *priv,const unsigned char *stream)
390 {
391    while (!(*stream == 0xff  && *(stream+1) == 0xd9 )&& stream<=priv->stream_end) //searching for the end of image marker
392    {
393       stream++;
394       continue;
395    }
396   priv->stream_scan=stream;
397   return 0;
398 }
399 
findSOI(struct jdec_private * priv,const unsigned char * stream)400 static int findSOI(struct jdec_private *priv,const unsigned char *stream)
401 {
402    while (!(*stream == 0xff  && *(stream+1) == 0xd8 ) ) //searching for the start of image marker
403    {
404       if(stream<=priv->stream_end)
405         {
406            stream++;
407            continue;
408          }
409       else
410          return 0;  // No more images in the file.
411    }
412    priv->stream=stream+2;
413    return 1;
414 }
415 
parse_JFIF(struct jdec_private * priv,const unsigned char * stream)416 static int parse_JFIF(struct jdec_private *priv, const unsigned char *stream)
417 {
418   int chuck_len;
419   int marker;
420   int sos_marker_found = 0;
421   int dht_marker_found = 0;
422   int dqt_marker_found = 0;
423   const unsigned char *next_chunck;
424 
425   next_image_found = findSOI(priv,stream);
426   stream=priv->stream;
427 
428    while (!sos_marker_found  && stream<=priv->stream_end)
429    {
430      while((*stream == 0xff))
431         stream++;
432 
433      marker = *stream++;
434      chuck_len = be16_to_cpu(stream);
435      next_chunck = stream + chuck_len;
436      switch (marker)
437       {
438        case SOF:
439 	 if (parse_SOF(priv, stream) < 0)
440 	   return -1;
441 	 break;
442        case DQT:
443 	 if (parse_DQT(priv, stream) < 0)
444 	   return -1;
445 	 dqt_marker_found = 1;
446 	 break;
447        case SOS:
448 	 if (parse_SOS(priv, stream) < 0)
449 	   return -1;
450 	 sos_marker_found = 1;
451 	 break;
452        case DHT:
453 	 if (parse_DHT(priv, stream) < 0)
454 	   return -1;
455 	 dht_marker_found = 1;
456 	 break;
457        case DRI:
458 	 if (parse_DRI(priv, stream) < 0)
459 	   return -1;
460 	 break;
461        default:
462 	 trace("> Unknown marker %2.2x\n", marker);
463 	 break;
464       }
465 
466      stream = next_chunck;
467    }
468 
469    if(next_image_found){
470       if (!dht_marker_found) {
471         trace("No Huffman table loaded, using the default one\n");
472         build_default_huffman_tables(priv);
473       }
474       if (!dqt_marker_found) {
475         error("ERROR:No Quantization table loaded, using the default one\n");
476       }
477    }
478 #ifdef SANITY_CHECK
479   if (   (priv->component_infos[cY].Hfactor < priv->component_infos[cCb].Hfactor)
480       || (priv->component_infos[cY].Hfactor < priv->component_infos[cCr].Hfactor))
481     error("Horizontal sampling factor for Y should be greater than horitontal sampling factor for Cb or Cr\n");
482   if (   (priv->component_infos[cY].Vfactor < priv->component_infos[cCb].Vfactor)
483       || (priv->component_infos[cY].Vfactor < priv->component_infos[cCr].Vfactor))
484     error("Vertical sampling factor for Y should be greater than vertical sampling factor for Cb or Cr\n");
485   if (   (priv->component_infos[cCb].Hfactor!=1)
486       || (priv->component_infos[cCr].Hfactor!=1)
487       || (priv->component_infos[cCb].Vfactor!=1)
488       || (priv->component_infos[cCr].Vfactor!=1))
489     printf("ERROR:Sampling other than 1x1 for Cr and Cb is not supported");
490 #endif
491   findEOI(priv,stream);
492   return next_image_found;
493 }
494 
495 /*******************************************************************************
496  *
497  * Functions exported of the library.
498  *
499  * Note: Some applications can access directly to internal pointer of the
500  * structure. It's is not recommended, but if you have many images to
501  * uncompress with the same parameters, some functions can be called to speedup
502  * the decoding.
503  *
504  ******************************************************************************/
505 
506 /**
507  * Allocate a new tinyjpeg decoder object.
508  *
509  * Before calling any other functions, an object need to be called.
510  */
tinyjpeg_init(void)511 struct jdec_private *tinyjpeg_init(void)
512 {
513   struct jdec_private *priv;
514 
515   priv = (struct jdec_private *)calloc(1, sizeof(struct jdec_private));
516   if (priv == NULL)
517     return NULL;
518   return priv;
519 }
520 
521 /**
522  * Free a tinyjpeg object.
523  *
524  * No others function can be called after this one.
525  */
tinyjpeg_free(struct jdec_private * priv)526 void tinyjpeg_free(struct jdec_private *priv)
527 {
528   free(priv);
529 }
530 
531 /**
532  * Initialize the tinyjpeg object and prepare the decoding of the stream.
533  *
534  * Check if the jpeg can be decoded with this jpeg decoder.
535  * Fill some table used for preprocessing.
536  */
tinyjpeg_parse_header(struct jdec_private * priv,const unsigned char * buf,unsigned int size)537 int tinyjpeg_parse_header(struct jdec_private *priv, const unsigned char *buf, unsigned int size)
538 {
539   int ret;
540 
541   /* Identify the file */
542   if ((buf[0] != 0xFF) || (buf[1] != SOI))
543     error("Not a JPG file ?\n");
544 
545   priv->stream_begin = buf;
546   priv->stream_length = size;
547   priv->stream_end = priv->stream_begin + priv->stream_length;
548 
549   priv->stream = priv->stream_begin;
550   ret = parse_JFIF(priv, priv->stream);
551   return ret;
552 }
553 
554 
tinyjpeg_decode(struct jdec_private * priv)555 int tinyjpeg_decode(struct jdec_private *priv)
556 {
557 #define CHECK_VASTATUS(va_status,func)                                  \
558     if (va_status != VA_STATUS_SUCCESS) {                                   \
559         fprintf(stderr,"%s:%s (%d) failed,exit\n", __func__, func, __LINE__); \
560         exit(1);                                                            \
561     }
562 
563     VAEntrypoint entrypoints[5];
564     int num_entrypoints,vld_entrypoint;
565     VAConfigAttrib attrib;
566     VAConfigID config_id;
567     VASurfaceID surface_id;
568     VAContextID context_id;
569     VABufferID pic_param_buf,iqmatrix_buf,huffmantable_buf,slice_param_buf,slice_data_buf;
570     int major_ver, minor_ver;
571     VADisplay	va_dpy;
572     VAStatus va_status;
573     int max_h_factor, max_v_factor;
574     int putsurface=1;
575     unsigned int i, j;
576 
577     int surface_type;
578     char *type;
579     int ChromaTypeIndex;
580 
581     VASurfaceAttrib forcc;
582     forcc.type =VASurfaceAttribPixelFormat;
583     forcc.flags=VA_SURFACE_ATTRIB_SETTABLE;
584     forcc.value.type=VAGenericValueTypeInteger;
585 
586 
587     va_dpy = va_open_display();
588     va_status = vaInitialize(va_dpy, &major_ver, &minor_ver);
589     assert(va_status == VA_STATUS_SUCCESS);
590 
591     va_status = vaQueryConfigEntrypoints(va_dpy, VAProfileJPEGBaseline, entrypoints,
592                              &num_entrypoints);
593     CHECK_VASTATUS(va_status, "vaQueryConfigEntrypoints");
594 
595     for	(vld_entrypoint = 0; vld_entrypoint < num_entrypoints; vld_entrypoint++) {
596         if (entrypoints[vld_entrypoint] == VAEntrypointVLD)
597             break;
598     }
599     if (vld_entrypoint == num_entrypoints) {
600         /* not find VLD entry point */
601         assert(0);
602     }
603 
604     /* Assuming finding VLD, find out the format for the render target */
605     attrib.type = VAConfigAttribRTFormat;
606     vaGetConfigAttributes(va_dpy, VAProfileJPEGBaseline, VAEntrypointVLD,
607                           &attrib, 1);
608     if ((attrib.value & VA_RT_FORMAT_YUV420) == 0) {
609         /* not find desired YUV420 RT format */
610         assert(0);
611     }
612 
613     va_status = vaCreateConfig(va_dpy, VAProfileJPEGBaseline, VAEntrypointVLD,
614                               &attrib, 1,&config_id);
615     CHECK_VASTATUS(va_status, "vaQueryConfigEntrypoints");
616 
617     while (next_image_found){
618        VAPictureParameterBufferJPEGBaseline pic_param;
619        memset(&pic_param, 0, sizeof(pic_param));
620        pic_param.picture_width = priv->width[scan_num];
621        pic_param.picture_height = priv->height[scan_num];
622        pic_param.num_components = priv->nf_components;
623 
624 
625        for (i=0; i<pic_param.num_components; i++) { // tinyjpeg support 3 components only, does it match va?
626            pic_param.components[i].component_id = priv->component_infos[i].cid;
627            pic_param.components[i].h_sampling_factor = priv->component_infos[i].Hfactor;
628            pic_param.components[i].v_sampling_factor = priv->component_infos[i].Vfactor;
629            pic_param.components[i].quantiser_table_selector = priv->component_infos[i].quant_table_index;
630        }
631        int h1, h2, h3, v1, v2, v3;
632        h1 = pic_param.components[0].h_sampling_factor;
633        h2 = pic_param.components[1].h_sampling_factor;
634        h3 = pic_param.components[2].h_sampling_factor;
635        v1 = pic_param.components[0].v_sampling_factor;
636        v2 = pic_param.components[1].v_sampling_factor;
637        v3 = pic_param.components[2].v_sampling_factor;
638 
639        if (h1 == 2 && h2 == 1 && h3 == 1 &&
640                v1 == 2 && v2 == 1 && v3 == 1) {
641            //surface_type = VA_RT_FORMAT_IMC3;
642            surface_type = VA_RT_FORMAT_YUV420;
643            forcc.value.value.i = VA_FOURCC_IMC3;
644            ChromaTypeIndex = 1;
645            type = "VA_FOURCC_IMC3";
646        }
647        else if (h1 == 2 && h2 == 1 && h3 == 1 &&
648                v1 == 1 && v2 == 1 && v3 == 1) {
649            //surface_type = VA_RT_FORMAT_YUV422H;
650            surface_type = VA_RT_FORMAT_YUV422;
651            forcc.value.value.i = VA_FOURCC_422H;
652            ChromaTypeIndex = 2;
653            type = "VA_FOURCC_422H";
654        }
655        else if (h1 == 1 && h2 == 1 && h3 == 1 &&
656                v1 == 1 && v2 == 1 && v3 == 1) {
657            surface_type = VA_RT_FORMAT_YUV444;
658            forcc.value.value.i = VA_FOURCC_444P;
659            //forcc.value.value.i = VA_FOURCC_RGBP;
660            ChromaTypeIndex = 3;
661            type = "VA_FOURCC_444P";
662        }
663        else if (h1 == 4 && h2 == 1 && h3 == 1 &&
664                v1 == 1 && v2 == 1 && v3 == 1) {
665            surface_type = VA_RT_FORMAT_YUV411;
666            forcc.value.value.i = VA_FOURCC_411P;
667            ChromaTypeIndex = 4;
668            type = "VA_FOURCC_411P";
669        }
670        else if (h1 == 1 && h2 == 1 && h3 == 1 &&
671                v1 == 2 && v2 == 1 && v3 == 1) {
672            //surface_type = VA_RT_FORMAT_YUV422V;
673            surface_type = VA_RT_FORMAT_YUV422;
674            forcc.value.value.i = VA_FOURCC_422V;
675            ChromaTypeIndex = 5;
676            type = "VA_FOURCC_422V";
677        }
678        else if (h1 == 2 && h2 == 1 && h3 == 1 &&
679                v1 == 2 && v2 == 2 && v3 == 2) {
680            //surface_type = VA_RT_FORMAT_YUV422H;
681            surface_type = VA_RT_FORMAT_YUV422;
682            forcc.value.value.i = VA_FOURCC_422H;
683            ChromaTypeIndex = 6;
684            type = "VA_FOURCC_422H";
685        }
686        else if (h2 == 2 && h2 == 2 && h3 == 2 &&
687                v1 == 2 && v2 == 1 && v3 == 1) {
688            //surface_type = VA_RT_FORMAT_YUV422V;
689            surface_type = VA_RT_FORMAT_YUV422;
690            forcc.value.value.i = VA_FOURCC_422V;
691            ChromaTypeIndex = 7;
692            type = "VA_FOURCC_422V";
693        }
694        else
695        {
696            surface_type = VA_RT_FORMAT_YUV400;
697            forcc.value.value.i = VA_FOURCC('Y','8','0','0');
698            ChromaTypeIndex = 0;
699            type = "Format_400P";
700        }
701 
702        va_status = vaCreateSurfaces(va_dpy,surface_type,
703                                     priv->width[scan_num],priv->height[scan_num], //alignment?
704                                     &surface_id, 1, &forcc, 1);
705        CHECK_VASTATUS(va_status, "vaCreateSurfaces");
706 
707        /* Create a context for this decode pipe */
708        va_status = vaCreateContext(va_dpy, config_id,
709                                   priv->width[scan_num], priv->height[scan_num], // alignment?
710                                   VA_PROGRESSIVE,
711                                   &surface_id,
712                                   1,
713                                   &context_id);
714        CHECK_VASTATUS(va_status, "vaCreateContext");
715 
716        va_status = vaCreateBuffer(va_dpy, context_id,
717                                  VAPictureParameterBufferType, // VAPictureParameterBufferJPEGBaseline?
718                                  sizeof(VAPictureParameterBufferJPEGBaseline),
719                                  1, &pic_param,
720                                  &pic_param_buf);
721        CHECK_VASTATUS(va_status, "vaCreateBuffer");
722 
723        VAIQMatrixBufferJPEGBaseline iq_matrix;
724        const unsigned int num_quant_tables =
725            MIN(COMPONENTS, ARRAY_ELEMS(iq_matrix.load_quantiser_table));
726        // todo, only mask it if non-default quant matrix is used. do we need build default quant matrix?
727        memset(&iq_matrix, 0, sizeof(VAIQMatrixBufferJPEGBaseline));
728        for (i = 0; i < num_quant_tables; i++) {
729            if (!priv->Q_tables_valid[i])
730                continue;
731            iq_matrix.load_quantiser_table[i] = 1;
732            for (j = 0; j < 64; j++)
733                iq_matrix.quantiser_table[i][j] = priv->Q_tables[i][j];
734        }
735        va_status = vaCreateBuffer(va_dpy, context_id,
736                                  VAIQMatrixBufferType, // VAIQMatrixBufferJPEGBaseline?
737                                  sizeof(VAIQMatrixBufferJPEGBaseline),
738                                  1, &iq_matrix,
739                                  &iqmatrix_buf );
740        CHECK_VASTATUS(va_status, "vaCreateBuffer");
741 
742        VAHuffmanTableBufferJPEGBaseline huffman_table;
743        const unsigned int num_huffman_tables =
744            MIN(COMPONENTS, ARRAY_ELEMS(huffman_table.load_huffman_table));
745        memset(&huffman_table, 0, sizeof(VAHuffmanTableBufferJPEGBaseline));
746        assert(sizeof(huffman_table.huffman_table[0].num_dc_codes) ==
747            sizeof(priv->HTDC[0].bits));
748           assert(sizeof(huffman_table.huffman_table[0].dc_values[0]) ==
749            sizeof(priv->HTDC[0].values[0]));
750        for (i = 0; i < num_huffman_tables; i++) {
751            if (!priv->HTDC_valid[i] || !priv->HTAC_valid[i])
752                continue;
753            huffman_table.load_huffman_table[i] = 1;
754            memcpy(huffman_table.huffman_table[i].num_dc_codes, priv->HTDC[i].bits,
755                   sizeof(huffman_table.huffman_table[i].num_dc_codes));
756            memcpy(huffman_table.huffman_table[i].dc_values, priv->HTDC[i].values,
757                   sizeof(huffman_table.huffman_table[i].dc_values));
758            memcpy(huffman_table.huffman_table[i].num_ac_codes, priv->HTAC[i].bits,
759                   sizeof(huffman_table.huffman_table[i].num_ac_codes));
760            memcpy(huffman_table.huffman_table[i].ac_values, priv->HTAC[i].values,
761                   sizeof(huffman_table.huffman_table[i].ac_values));
762            memset(huffman_table.huffman_table[i].pad, 0,
763                   sizeof(huffman_table.huffman_table[i].pad));
764        }
765        va_status = vaCreateBuffer(va_dpy, context_id,
766                                  VAHuffmanTableBufferType, // VAHuffmanTableBufferJPEGBaseline?
767                                  sizeof(VAHuffmanTableBufferJPEGBaseline),
768                                  1, &huffman_table,
769                                  &huffmantable_buf );
770        CHECK_VASTATUS(va_status, "vaCreateBuffer");
771 
772        // one slice for whole image?
773        max_h_factor = priv->component_infos[0].Hfactor;
774        max_v_factor = priv->component_infos[0].Vfactor;
775        static VASliceParameterBufferJPEGBaseline slice_param;
776        slice_param.slice_data_size = (priv->stream_scan - priv->stream);
777        slice_param.slice_data_offset = 0;
778        slice_param.slice_data_flag = VA_SLICE_DATA_FLAG_ALL;
779        slice_param.slice_horizontal_position = 0;
780        slice_param.slice_vertical_position = 0;
781        slice_param.num_components = priv->cur_sos.nr_components;
782        for (i = 0; i < slice_param.num_components; i++) {
783            slice_param.components[i].component_selector = priv->cur_sos.components[i].component_id; /* FIXME: set to values specified in SOS  */
784            slice_param.components[i].dc_table_selector = priv->cur_sos.components[i].dc_selector;  /* FIXME: set to values specified in SOS  */
785            slice_param.components[i].ac_table_selector = priv->cur_sos.components[i].ac_selector;  /* FIXME: set to values specified in SOS  */
786        }
787        slice_param.restart_interval = priv->restart_interval;
788        slice_param.num_mcus = ((priv->width[scan_num]+max_h_factor*8-1)/(max_h_factor*8))*
789                              ((priv->height[scan_num]+max_v_factor*8-1)/(max_v_factor*8)); // ?? 720/16?
790 
791        va_status = vaCreateBuffer(va_dpy, context_id,
792                                  VASliceParameterBufferType, // VASliceParameterBufferJPEGBaseline?
793                                  sizeof(VASliceParameterBufferJPEGBaseline),
794                                  1,
795                                  &slice_param, &slice_param_buf);
796        CHECK_VASTATUS(va_status, "vaCreateBuffer");
797 
798        va_status = vaCreateBuffer(va_dpy, context_id,
799                                  VASliceDataBufferType,
800                                  priv->stream_scan - priv->stream,
801                                  1,
802                                  (void*)priv->stream, // jpeg_clip,
803                                  &slice_data_buf);
804        CHECK_VASTATUS(va_status, "vaCreateBuffer");
805 
806        va_status = vaBeginPicture(va_dpy, context_id, surface_id);
807        CHECK_VASTATUS(va_status, "vaBeginPicture");
808 
809        va_status = vaRenderPicture(va_dpy,context_id, &pic_param_buf, 1);
810        CHECK_VASTATUS(va_status, "vaRenderPicture");
811 
812        va_status = vaRenderPicture(va_dpy,context_id, &iqmatrix_buf, 1);
813        CHECK_VASTATUS(va_status, "vaRenderPicture");
814 
815        va_status = vaRenderPicture(va_dpy,context_id, &huffmantable_buf, 1);
816        CHECK_VASTATUS(va_status, "vaRenderPicture");
817 
818        va_status = vaRenderPicture(va_dpy,context_id, &slice_param_buf, 1);
819        CHECK_VASTATUS(va_status, "vaRenderPicture");
820 
821        va_status = vaRenderPicture(va_dpy,context_id, &slice_data_buf, 1);
822        CHECK_VASTATUS(va_status, "vaRenderPicture");
823 
824        va_status = vaEndPicture(va_dpy,context_id);
825        CHECK_VASTATUS(va_status, "vaEndPicture");
826 
827        va_status = vaSyncSurface(va_dpy, surface_id);
828        CHECK_VASTATUS(va_status, "vaSyncSurface");
829 
830        if (putsurface) {
831            VARectangle src_rect, dst_rect;
832 
833            src_rect.x      = 0;
834            src_rect.y      = 0;
835            src_rect.width  = priv->width[scan_num];
836            src_rect.height = priv->height[scan_num];
837            dst_rect        = src_rect;
838 
839            va_status = va_put_surface(va_dpy, surface_id, &src_rect, &dst_rect);
840            CHECK_VASTATUS(va_status, "vaPutSurface");
841        }
842        scan_num++;
843 
844        vaDestroySurfaces(va_dpy,&surface_id,1);
845        vaDestroyConfig(va_dpy,config_id);
846        vaDestroyContext(va_dpy,context_id);
847 
848        parse_JFIF(priv,priv->stream);
849        if(priv->width[scan_num] == 0 && priv->height[scan_num] == 0)
850           break;
851     }
852    // va_close_display(va_dpy);
853     vaTerminate(va_dpy);
854     printf("press any key to exit23\n");
855     getchar();
856     return 0;
857 }
tinyjpeg_get_errorstring(struct jdec_private * priv)858 const char *tinyjpeg_get_errorstring(struct jdec_private *priv)
859 {
860   /* FIXME: the error string must be store in the context */
861   priv = priv;
862   return error_string;
863 }
tinyjpeg_get_size(struct jdec_private * priv,unsigned int * width,unsigned int * height)864 void tinyjpeg_get_size(struct jdec_private *priv, unsigned int *width, unsigned int *height)
865 {
866   *width = priv->width[scan_num];
867   *height = priv->height[scan_num];
868 }
869 
870 
871