Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5362 serge 1
/*
2
 * Small jpeg decoder library
3
 *
4
 * Copyright (c) 2006, Luc Saillard 
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 
36
#include 
37
#include 
38
#include 
39
#include 
40
 
41
#include "tinyjpeg.h"
42
#include "tinyjpeg-internal.h"
43
 
44
// for libva
45
#include 
46
#include 
47
#include 
48
#include 
49
#include 
50
#include 
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
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
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
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