OSDN Git Service

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