2 * Small jpeg decoder library
4 * Copyright (c) 2006, Luc Saillard <luc@saillard.org>
5 * Copyright (c) 2012 Intel Corporation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
10 * - Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
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.
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.
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.
42 #include "tinyjpeg-internal.h"
46 #include <sys/types.h>
51 #include "va_display.h"
63 #define MIN(a, b) ((a) < (b) ? (a) : (b))
66 #define MAX(a, b) ((a) > (b) ? (a) : (b))
68 #define ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0]))
71 #define trace(fmt, args...) do { \
72 fprintf(stderr, fmt, ## args); \
76 #define trace(fmt, args...) do { } while (0)
78 #define error(fmt, args...) do { \
79 snprintf(error_string, sizeof(error_string), fmt, ## args); \
82 /* The variables for different image scans */
83 static int scan_num=0;
84 static int next_image_found=0;
85 /* Global variable to return the last error found while deconding */
86 static char error_string[256];
87 static VAHuffmanTableBufferJPEGBaseline default_huffman_table_param={
92 num_dc_codes:{0,1,5,1,1,1,1,1,1,0,0,0}, // 12 bits is ok for baseline profile
93 dc_values:{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b},
94 num_ac_codes:{0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,125},
96 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
97 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
98 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
99 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
100 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
101 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
102 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
103 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
104 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
105 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
106 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
107 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
108 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
109 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
110 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
111 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
112 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
113 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
114 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
115 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
117 },/*,0xonly,0xthe,0xfirst,0x162,0xbytes,0xare,0xavailable,0x*/
121 num_dc_codes:{0,3,1,1,1,1,1,1,1,1,1,0}, // 12 bits is ok for baseline profile
122 dc_values:{0,1,2,3,4,5,6,7,8,9,0xa,0xb},
123 num_ac_codes:{0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,119},
125 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
126 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
127 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
128 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
129 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
130 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
131 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
132 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
133 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
134 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
135 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
136 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
137 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
138 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
139 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
140 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
141 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
142 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
143 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
144 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
146 },/*,0xonly,0xthe,0xfirst,0x162,0xbytes,0xare,0xavailable,0x*/
151 #define be16_to_cpu(x) (((x)[0]<<8)|(x)[1])
154 static int build_default_huffman_tables(struct jdec_private *priv)
157 if (priv->default_huffman_table_initialized)
160 for (i = 0; i < 4; i++) {
161 priv->HTDC_valid[i] = 1;
162 memcpy(priv->HTDC[i].bits, default_huffman_table_param.huffman_table[i].num_dc_codes, 16);
163 memcpy(priv->HTDC[i].values, default_huffman_table_param.huffman_table[i].dc_values, 16);
164 priv->HTAC_valid[i] = 1;
165 memcpy(priv->HTAC[i].bits, default_huffman_table_param.huffman_table[i].num_ac_codes, 16);
166 memcpy(priv->HTAC[i].values, default_huffman_table_param.huffman_table[i].ac_values, 256);
168 priv->default_huffman_table_initialized = 1;
173 static void print_SOF(const unsigned char *stream)
175 int width, height, nr_components, precision;
177 const char *nr_components_to_string[] = {
186 precision = stream[2];
187 height = be16_to_cpu(stream+3);
188 width = be16_to_cpu(stream+5);
189 nr_components = stream[7];
191 trace("> SOF marker\n");
192 trace("Size:%dx%d nr_components:%d (%s) precision:%d\n",
194 nr_components, nr_components_to_string[nr_components],
198 static int parse_DQT(struct jdec_private *priv, const unsigned char *stream)
201 const unsigned char *dqt_block_end;
203 trace("> DQT marker\n");
204 dqt_block_end = stream + be16_to_cpu(stream);
205 stream += 2; /* Skip length */
207 while (stream < dqt_block_end)
212 error("16 bits quantization table is not supported\n");
214 error("No more 4 quantization table is supported (got %d)\n", qi);
216 memcpy(priv->Q_tables[qi&0x0F], stream, 64);
217 priv->Q_tables_valid[qi & 0x0f] = 1;
220 trace("< DQT marker\n");
224 static int parse_SOF(struct jdec_private *priv, const unsigned char *stream)
226 int i, width, height, nr_components, cid, sampling_factor;
227 unsigned char Q_table;
230 trace("> SOF marker\n");
233 height = be16_to_cpu(stream+3);
234 width = be16_to_cpu(stream+5);
235 nr_components = stream[7];
236 priv->nf_components = nr_components;
239 error("Precision other than 8 is not supported\n");
240 if (width>JPEG_MAX_WIDTH || height>JPEG_MAX_HEIGHT)
241 printf("WARNING:Width and Height (%dx%d) seems suspicious\n", width, height);
242 if (nr_components != 3)
243 printf("ERROR:We only support YUV images\n");
245 printf("WARNING:Height need to be a multiple of 16 (current height is %d)\n", height);
247 printf("WARNING:Width need to be a multiple of 16 (current Width is %d)\n", width);
250 for (i=0; i<nr_components; i++) {
252 sampling_factor = *stream++;
254 c = &priv->component_infos[i];
256 if (Q_table >= COMPONENTS)
257 error("Bad Quantization table index (got %d, max allowed %d)\n", Q_table, COMPONENTS-1);
258 c->Vfactor = sampling_factor&0xf;
259 c->Hfactor = sampling_factor>>4;
260 c->quant_table_index = Q_table;
261 trace("Component:%d factor:%dx%d Quantization table:%d\n",
262 cid, c->Hfactor, c->Vfactor, Q_table );
265 priv->width[scan_num] = width;
266 priv->height[scan_num] = height;
268 trace("< SOF marker\n");
273 static int parse_SOS(struct jdec_private *priv, const unsigned char *stream)
275 unsigned int i, cid, table;
276 unsigned int nr_components = stream[2];
278 trace("> SOS marker\n");
280 priv->cur_sos.nr_components= nr_components;
283 for (i=0;i<nr_components;i++) {
286 priv->cur_sos.components[i].component_id = cid;
287 priv->cur_sos.components[i].dc_selector = ((table>>4)&0x0F);
288 priv->cur_sos.components[i].ac_selector = (table&0x0F);
291 error("We do not support more than 2 AC Huffman table\n");
293 error("We do not support more than 2 DC Huffman table\n");
294 if (cid != priv->component_infos[i].cid)
295 error("SOS cid order (%d:%d) isn't compatible with the SOF marker (%d:%d)\n",
296 i, cid, i, priv->component_infos[i].cid);
297 trace("ComponentId:%d tableAC:%d tableDC:%d\n", cid, table&0xf, table>>4);
300 priv->stream = stream+3;
301 trace("< SOS marker\n");
305 int tinyjpeg_parse_SOS(struct jdec_private *priv, const unsigned char *stream)
307 return parse_SOS(priv, stream);
311 static int parse_DHT(struct jdec_private *priv, const unsigned char *stream)
313 unsigned int count, i;
315 unsigned char Tc, Th;
317 length = be16_to_cpu(stream) - 2;
318 stream += 2; /* Skip length */
320 trace("> DHT marker (length=%d)\n", length);
325 Tc = index & 0xf0; // it is not important to <<4
328 memcpy(priv->HTAC[index & 0xf].bits, stream, 16);
331 memcpy(priv->HTDC[index & 0xf].bits, stream, 16);
335 for (i=0; i<16; i++) {
340 if (count >= HUFFMAN_BITS_SIZE)
341 error("No more than %d bytes is allowed to describe a huffman table", HUFFMAN_BITS_SIZE);
342 if ( (index &0xf) >= HUFFMAN_TABLES)
343 error("No more than %d Huffman tables is supported (got %d)\n", HUFFMAN_TABLES, index&0xf);
344 trace("Huffman table %s[%d] length=%d\n", (index&0xf0)?"AC":"DC", index&0xf, count);
348 memcpy(priv->HTAC[index & 0xf].values, stream, count);
349 priv->HTAC_valid[index & 0xf] = 1;
352 memcpy(priv->HTDC[index & 0xf].values, stream, count);
353 priv->HTDC_valid[index & 0xf] = 1;
361 trace("< DHT marker\n");
364 static int parse_DRI(struct jdec_private *priv, const unsigned char *stream)
368 trace("> DRI marker\n");
370 length = be16_to_cpu(stream);
374 error("Length of DRI marker need to be 4\n");
377 priv->restart_interval = be16_to_cpu(stream+2);
380 trace("Restart interval = %d\n", priv->restart_interval);
383 trace("< DRI marker\n");
388 static int findEOI(struct jdec_private *priv,const unsigned char *stream)
390 while (!(*stream == 0xff && *(stream+1) == 0xd9 )&& stream<=priv->stream_end) //searching for the end of image marker
395 priv->stream_scan=stream;
399 static int findSOI(struct jdec_private *priv,const unsigned char *stream)
401 while (!(*stream == 0xff && *(stream+1) == 0xd8 ) ) //searching for the start of image marker
403 if(stream<=priv->stream_end)
409 return 0; // No more images in the file.
411 priv->stream=stream+2;
415 static int parse_JFIF(struct jdec_private *priv, const unsigned char *stream)
419 int sos_marker_found = 0;
420 int dht_marker_found = 0;
421 int dqt_marker_found = 0;
422 const unsigned char *next_chunck;
424 next_image_found = findSOI(priv,stream);
427 while (!sos_marker_found && stream<=priv->stream_end)
429 while((*stream == 0xff))
433 chuck_len = be16_to_cpu(stream);
434 next_chunck = stream + chuck_len;
438 if (parse_SOF(priv, stream) < 0)
442 if (parse_DQT(priv, stream) < 0)
444 dqt_marker_found = 1;
447 if (parse_SOS(priv, stream) < 0)
449 sos_marker_found = 1;
452 if (parse_DHT(priv, stream) < 0)
454 dht_marker_found = 1;
457 if (parse_DRI(priv, stream) < 0)
461 trace("> Unknown marker %2.2x\n", marker);
465 stream = next_chunck;
468 if(next_image_found){
469 if (!dht_marker_found) {
470 trace("No Huffman table loaded, using the default one\n");
471 build_default_huffman_tables(priv);
473 if (!dqt_marker_found) {
474 error("ERROR:No Quantization table loaded, using the default one\n");
478 if ( (priv->component_infos[cY].Hfactor < priv->component_infos[cCb].Hfactor)
479 || (priv->component_infos[cY].Hfactor < priv->component_infos[cCr].Hfactor))
480 error("Horizontal sampling factor for Y should be greater than horitontal sampling factor for Cb or Cr\n");
481 if ( (priv->component_infos[cY].Vfactor < priv->component_infos[cCb].Vfactor)
482 || (priv->component_infos[cY].Vfactor < priv->component_infos[cCr].Vfactor))
483 error("Vertical sampling factor for Y should be greater than vertical sampling factor for Cb or Cr\n");
484 if ( (priv->component_infos[cCb].Hfactor!=1)
485 || (priv->component_infos[cCr].Hfactor!=1)
486 || (priv->component_infos[cCb].Vfactor!=1)
487 || (priv->component_infos[cCr].Vfactor!=1))
488 printf("ERROR:Sampling other than 1x1 for Cr and Cb is not supported");
490 findEOI(priv,stream);
491 return next_image_found;
494 /*******************************************************************************
496 * Functions exported of the library.
498 * Note: Some applications can access directly to internal pointer of the
499 * structure. It's is not recommended, but if you have many images to
500 * uncompress with the same parameters, some functions can be called to speedup
503 ******************************************************************************/
506 * Allocate a new tinyjpeg decoder object.
508 * Before calling any other functions, an object need to be called.
510 struct jdec_private *tinyjpeg_init(void)
512 struct jdec_private *priv;
514 priv = (struct jdec_private *)calloc(1, sizeof(struct jdec_private));
521 * Free a tinyjpeg object.
523 * No others function can be called after this one.
525 void tinyjpeg_free(struct jdec_private *priv)
531 * Initialize the tinyjpeg object and prepare the decoding of the stream.
533 * Check if the jpeg can be decoded with this jpeg decoder.
534 * Fill some table used for preprocessing.
536 int tinyjpeg_parse_header(struct jdec_private *priv, const unsigned char *buf, unsigned int size)
540 /* Identify the file */
541 if ((buf[0] != 0xFF) || (buf[1] != SOI))
542 error("Not a JPG file ?\n");
544 priv->stream_begin = buf;
545 priv->stream_length = size;
546 priv->stream_end = priv->stream_begin + priv->stream_length;
548 priv->stream = priv->stream_begin;
549 ret = parse_JFIF(priv, priv->stream);
554 int tinyjpeg_decode(struct jdec_private *priv)
556 #define CHECK_VASTATUS(va_status,func) \
557 if (va_status != VA_STATUS_SUCCESS) { \
558 fprintf(stderr,"%s:%s (%d) failed,exit\n", __func__, func, __LINE__); \
562 VAEntrypoint entrypoints[5];
563 int num_entrypoints,vld_entrypoint;
564 VAConfigAttrib attrib;
565 VAConfigID config_id;
566 VASurfaceID surface_id;
567 VAContextID context_id;
568 VABufferID pic_param_buf,iqmatrix_buf,huffmantable_buf,slice_param_buf,slice_data_buf;
569 int major_ver, minor_ver;
572 int max_h_factor, max_v_factor;
580 VASurfaceAttrib forcc;
581 forcc.type =VASurfaceAttribPixelFormat;
582 forcc.flags=VA_SURFACE_ATTRIB_SETTABLE;
583 forcc.value.type=VAGenericValueTypeInteger;
586 va_dpy = va_open_display();
587 va_status = vaInitialize(va_dpy, &major_ver, &minor_ver);
588 assert(va_status == VA_STATUS_SUCCESS);
590 va_status = vaQueryConfigEntrypoints(va_dpy, VAProfileJPEGBaseline, entrypoints,
592 CHECK_VASTATUS(va_status, "vaQueryConfigEntrypoints");
594 for (vld_entrypoint = 0; vld_entrypoint < num_entrypoints; vld_entrypoint++) {
595 if (entrypoints[vld_entrypoint] == VAEntrypointVLD)
598 if (vld_entrypoint == num_entrypoints) {
599 /* not find VLD entry point */
603 /* Assuming finding VLD, find out the format for the render target */
604 attrib.type = VAConfigAttribRTFormat;
605 vaGetConfigAttributes(va_dpy, VAProfileJPEGBaseline, VAEntrypointVLD,
607 if ((attrib.value & VA_RT_FORMAT_YUV420) == 0) {
608 /* not find desired YUV420 RT format */
612 va_status = vaCreateConfig(va_dpy, VAProfileJPEGBaseline, VAEntrypointVLD,
613 &attrib, 1,&config_id);
614 CHECK_VASTATUS(va_status, "vaQueryConfigEntrypoints");
616 while (next_image_found){
617 VAPictureParameterBufferJPEGBaseline pic_param;
618 memset(&pic_param, 0, sizeof(pic_param));
619 pic_param.picture_width = priv->width[scan_num];
620 pic_param.picture_height = priv->height[scan_num];
621 pic_param.num_components = priv->nf_components;
624 for (i=0; i<pic_param.num_components; i++) { // tinyjpeg support 3 components only, does it match va?
625 pic_param.components[i].component_id = priv->component_infos[i].cid;
626 pic_param.components[i].h_sampling_factor = priv->component_infos[i].Hfactor;
627 pic_param.components[i].v_sampling_factor = priv->component_infos[i].Vfactor;
628 pic_param.components[i].quantiser_table_selector = priv->component_infos[i].quant_table_index;
630 int h1, h2, h3, v1, v2, v3;
631 h1 = pic_param.components[0].h_sampling_factor;
632 h2 = pic_param.components[1].h_sampling_factor;
633 h3 = pic_param.components[2].h_sampling_factor;
634 v1 = pic_param.components[0].v_sampling_factor;
635 v2 = pic_param.components[1].v_sampling_factor;
636 v3 = pic_param.components[2].v_sampling_factor;
638 if (h1 == 2 && h2 == 1 && h3 == 1 &&
639 v1 == 2 && v2 == 1 && v3 == 1) {
640 //surface_type = VA_RT_FORMAT_IMC3;
641 surface_type = VA_RT_FORMAT_YUV420;
642 forcc.value.value.i = VA_FOURCC_IMC3;
644 type = "VA_FOURCC_IMC3";
646 else if (h1 == 2 && h2 == 1 && h3 == 1 &&
647 v1 == 1 && v2 == 1 && v3 == 1) {
648 //surface_type = VA_RT_FORMAT_YUV422H;
649 surface_type = VA_RT_FORMAT_YUV422;
650 forcc.value.value.i = VA_FOURCC_422H;
652 type = "VA_FOURCC_422H";
654 else if (h1 == 1 && h2 == 1 && h3 == 1 &&
655 v1 == 1 && v2 == 1 && v3 == 1) {
656 surface_type = VA_RT_FORMAT_YUV444;
657 forcc.value.value.i = VA_FOURCC_444P;
658 //forcc.value.value.i = VA_FOURCC_RGBP;
660 type = "VA_FOURCC_444P";
662 else if (h1 == 4 && h2 == 1 && h3 == 1 &&
663 v1 == 1 && v2 == 1 && v3 == 1) {
664 surface_type = VA_RT_FORMAT_YUV411;
665 forcc.value.value.i = VA_FOURCC_411P;
667 type = "VA_FOURCC_411P";
669 else if (h1 == 1 && h2 == 1 && h3 == 1 &&
670 v1 == 2 && v2 == 1 && v3 == 1) {
671 //surface_type = VA_RT_FORMAT_YUV422V;
672 surface_type = VA_RT_FORMAT_YUV422;
673 forcc.value.value.i = VA_FOURCC_422V;
675 type = "VA_FOURCC_422V";
677 else if (h1 == 2 && h2 == 1 && h3 == 1 &&
678 v1 == 2 && v2 == 2 && v3 == 2) {
679 //surface_type = VA_RT_FORMAT_YUV422H;
680 surface_type = VA_RT_FORMAT_YUV422;
681 forcc.value.value.i = VA_FOURCC_422H;
683 type = "VA_FOURCC_422H";
685 else if (h2 == 2 && h2 == 2 && h3 == 2 &&
686 v1 == 2 && v2 == 1 && v3 == 1) {
687 //surface_type = VA_RT_FORMAT_YUV422V;
688 surface_type = VA_RT_FORMAT_YUV422;
689 forcc.value.value.i = VA_FOURCC_422V;
691 type = "VA_FOURCC_422V";
695 surface_type = VA_RT_FORMAT_YUV400;
696 forcc.value.value.i = VA_FOURCC('4','0','0','P');
698 type = "Format_400P";
701 va_status = vaCreateSurfaces(va_dpy,VA_RT_FORMAT_YUV420,
702 priv->width[scan_num],priv->height[scan_num], //alignment?
703 &surface_id, 1, &forcc, 1);
704 CHECK_VASTATUS(va_status, "vaCreateSurfaces");
706 /* Create a context for this decode pipe */
707 va_status = vaCreateContext(va_dpy, config_id,
708 priv->width[scan_num], priv->height[scan_num], // alignment?
713 CHECK_VASTATUS(va_status, "vaCreateContext");
715 va_status = vaCreateBuffer(va_dpy, context_id,
716 VAPictureParameterBufferType, // VAPictureParameterBufferJPEGBaseline?
717 sizeof(VAPictureParameterBufferJPEGBaseline),
720 CHECK_VASTATUS(va_status, "vaCreateBuffer");
722 VAIQMatrixBufferJPEGBaseline iq_matrix;
723 const unsigned int num_quant_tables =
724 MIN(COMPONENTS, ARRAY_ELEMS(iq_matrix.load_quantiser_table));
725 // todo, only mask it if non-default quant matrix is used. do we need build default quant matrix?
726 memset(&iq_matrix, 0, sizeof(VAIQMatrixBufferJPEGBaseline));
727 for (i = 0; i < num_quant_tables; i++) {
728 if (!priv->Q_tables_valid[i])
730 iq_matrix.load_quantiser_table[i] = 1;
731 for (j = 0; j < 64; j++)
732 iq_matrix.quantiser_table[i][j] = priv->Q_tables[i][j];
734 va_status = vaCreateBuffer(va_dpy, context_id,
735 VAIQMatrixBufferType, // VAIQMatrixBufferJPEGBaseline?
736 sizeof(VAIQMatrixBufferJPEGBaseline),
739 CHECK_VASTATUS(va_status, "vaCreateBuffer");
741 VAHuffmanTableBufferJPEGBaseline huffman_table;
742 const unsigned int num_huffman_tables =
743 MIN(COMPONENTS, ARRAY_ELEMS(huffman_table.load_huffman_table));
744 memset(&huffman_table, 0, sizeof(VAHuffmanTableBufferJPEGBaseline));
745 assert(sizeof(huffman_table.huffman_table[0].num_dc_codes) ==
746 sizeof(priv->HTDC[0].bits));
747 assert(sizeof(huffman_table.huffman_table[0].dc_values[0]) ==
748 sizeof(priv->HTDC[0].values[0]));
749 for (i = 0; i < num_huffman_tables; i++) {
750 if (!priv->HTDC_valid[i] || !priv->HTAC_valid[i])
752 huffman_table.load_huffman_table[i] = 1;
753 memcpy(huffman_table.huffman_table[i].num_dc_codes, priv->HTDC[i].bits,
754 sizeof(huffman_table.huffman_table[i].num_dc_codes));
755 memcpy(huffman_table.huffman_table[i].dc_values, priv->HTDC[i].values,
756 sizeof(huffman_table.huffman_table[i].dc_values));
757 memcpy(huffman_table.huffman_table[i].num_ac_codes, priv->HTAC[i].bits,
758 sizeof(huffman_table.huffman_table[i].num_ac_codes));
759 memcpy(huffman_table.huffman_table[i].ac_values, priv->HTAC[i].values,
760 sizeof(huffman_table.huffman_table[i].ac_values));
761 memset(huffman_table.huffman_table[i].pad, 0,
762 sizeof(huffman_table.huffman_table[i].pad));
764 va_status = vaCreateBuffer(va_dpy, context_id,
765 VAHuffmanTableBufferType, // VAHuffmanTableBufferJPEGBaseline?
766 sizeof(VAHuffmanTableBufferJPEGBaseline),
769 CHECK_VASTATUS(va_status, "vaCreateBuffer");
771 // one slice for whole image?
772 max_h_factor = priv->component_infos[0].Hfactor;
773 max_v_factor = priv->component_infos[0].Vfactor;
774 static VASliceParameterBufferJPEGBaseline slice_param;
775 slice_param.slice_data_size = (priv->stream_scan - priv->stream);
776 slice_param.slice_data_offset = 0;
777 slice_param.slice_data_flag = VA_SLICE_DATA_FLAG_ALL;
778 slice_param.slice_horizontal_position = 0;
779 slice_param.slice_vertical_position = 0;
780 slice_param.num_components = priv->cur_sos.nr_components;
781 for (i = 0; i < slice_param.num_components; i++) {
782 slice_param.components[i].component_selector = priv->cur_sos.components[i].component_id; /* FIXME: set to values specified in SOS */
783 slice_param.components[i].dc_table_selector = priv->cur_sos.components[i].dc_selector; /* FIXME: set to values specified in SOS */
784 slice_param.components[i].ac_table_selector = priv->cur_sos.components[i].ac_selector; /* FIXME: set to values specified in SOS */
786 slice_param.restart_interval = priv->restart_interval;
787 slice_param.num_mcus = ((priv->width[scan_num]+max_h_factor*8-1)/(max_h_factor*8))*
788 ((priv->height[scan_num]+max_v_factor*8-1)/(max_v_factor*8)); // ?? 720/16?
790 va_status = vaCreateBuffer(va_dpy, context_id,
791 VASliceParameterBufferType, // VASliceParameterBufferJPEGBaseline?
792 sizeof(VASliceParameterBufferJPEGBaseline),
794 &slice_param, &slice_param_buf);
795 CHECK_VASTATUS(va_status, "vaCreateBuffer");
797 va_status = vaCreateBuffer(va_dpy, context_id,
798 VASliceDataBufferType,
799 priv->stream_scan - priv->stream,
801 (void*)priv->stream, // jpeg_clip,
803 CHECK_VASTATUS(va_status, "vaCreateBuffer");
805 va_status = vaBeginPicture(va_dpy, context_id, surface_id);
806 CHECK_VASTATUS(va_status, "vaBeginPicture");
808 va_status = vaRenderPicture(va_dpy,context_id, &pic_param_buf, 1);
809 CHECK_VASTATUS(va_status, "vaRenderPicture");
811 va_status = vaRenderPicture(va_dpy,context_id, &iqmatrix_buf, 1);
812 CHECK_VASTATUS(va_status, "vaRenderPicture");
814 va_status = vaRenderPicture(va_dpy,context_id, &huffmantable_buf, 1);
815 CHECK_VASTATUS(va_status, "vaRenderPicture");
817 va_status = vaRenderPicture(va_dpy,context_id, &slice_param_buf, 1);
818 CHECK_VASTATUS(va_status, "vaRenderPicture");
820 va_status = vaRenderPicture(va_dpy,context_id, &slice_data_buf, 1);
821 CHECK_VASTATUS(va_status, "vaRenderPicture");
823 va_status = vaEndPicture(va_dpy,context_id);
824 CHECK_VASTATUS(va_status, "vaEndPicture");
826 va_status = vaSyncSurface(va_dpy, surface_id);
827 CHECK_VASTATUS(va_status, "vaSyncSurface");
830 VARectangle src_rect, dst_rect;
834 src_rect.width = priv->width[scan_num];
835 src_rect.height = priv->height[scan_num];
838 va_status = va_put_surface(va_dpy, surface_id, &src_rect, &dst_rect);
839 CHECK_VASTATUS(va_status, "vaPutSurface");
843 vaDestroySurfaces(va_dpy,&surface_id,1);
844 vaDestroyConfig(va_dpy,config_id);
845 vaDestroyContext(va_dpy,context_id);
847 parse_JFIF(priv,priv->stream);
848 if(priv->width[scan_num] == 0 && priv->height[scan_num] == 0)
851 // va_close_display(va_dpy);
853 printf("press any key to exit23\n");
857 const char *tinyjpeg_get_errorstring(struct jdec_private *priv)
859 /* FIXME: the error string must be store in the context */
863 void tinyjpeg_get_size(struct jdec_private *priv, unsigned int *width, unsigned int *height)
865 *width = priv->width[scan_num];
866 *height = priv->height[scan_num];