Home | History | Annotate | Download | only in decode
      1 /*
      2  * Small jpeg decoder library
      3  *
      4  * Copyright (c) 2006, Luc Saillard <luc (at) 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 
    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 
    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 
    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 
    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 
    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 
    306 int tinyjpeg_parse_SOS(struct jdec_private *priv, const unsigned char *stream)
    307 {
    308     return parse_SOS(priv, stream);
    309 }
    310 
    311 
    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 }
    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 
    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 
    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 
    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  */
    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  */
    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  */
    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 
    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 }
    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 }
    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