1/*
2 * Small jpeg decoder library
3 *
4 * Copyright (c) 2006, Luc Saillard <luc@saillard.org>
5 * Copyright (c) 2012 Intel Corporation.
6 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * - Redistributions of source code must retain the above copyright notice,
11 *  this list of conditions and the following disclaimer.
12 *
13 * - Redistributions in binary form must reproduce the above copyright notice,
14 *  this list of conditions and the following disclaimer in the documentation
15 *  and/or other materials provided with the distribution.
16 *
17 * - Neither the name of the author nor the names of its contributors may be
18 *  used to endorse or promote products derived from this software without
19 *  specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 *
33 */
34
35#include <stdio.h>
36#include <stdlib.h>
37#include <string.h>
38#include <stdint.h>
39#include <errno.h>
40
41#include "tinyjpeg.h"
42#include "tinyjpeg-internal.h"
43
44// for libva
45#include <unistd.h>
46#include <sys/types.h>
47#include <sys/stat.h>
48#include <fcntl.h>
49#include <assert.h>
50#include <va/va.h>
51#include <va/va_dec_jpeg.h>
52#include "va_display.h"
53
54
55#define cY	0
56#define cCb	1
57#define cCr	2
58
59#define BLACK_Y 0
60#define BLACK_U 127
61#define BLACK_V 127
62
63#ifndef MIN
64#define MIN(a, b) ((a) < (b) ? (a) : (b))
65#endif
66#ifndef MAX
67#define MAX(a, b) ((a) > (b) ? (a) : (b))
68#endif
69#define ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0]))
70
71#if DEBUG
72#define trace(fmt, args...) do { \
73   fprintf(stderr, fmt, ## args); \
74   fflush(stderr); \
75} while(0)
76#else
77#define trace(fmt, args...) do { } while (0)
78#endif
79#define error(fmt, args...) do { \
80   snprintf(error_string, sizeof(error_string), fmt, ## args); \
81   return -1; \
82} while(0)
83/* The variables for different image scans */
84static int scan_num=0;
85static int next_image_found=0;
86/* Global variable to return the last error found while deconding */
87static char error_string[256];
88static 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
155static 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
174static 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
199static 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
225static 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
274static 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
306int tinyjpeg_parse_SOS(struct jdec_private *priv, const unsigned char *stream)
307{
308    return parse_SOS(priv, stream);
309}
310
311
312static 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}
365static 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
389static 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
400static 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
416static 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 */
511struct 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 */
526void 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 */
537int 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
555int 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}
858const 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}
864void 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