Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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