1/*
2 * Copyright (c) 2011 Intel Corporation. All Rights Reserved.
3 * Copyright (c) Imagination Technologies Limited, UK
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Authors:
26 *    Guo Nana <nana.n.guo@intel.com>
27 *    Zeng Li <li.zeng@intel.com>
28 *
29 */
30
31#include "va/va_dec_jpeg.h"
32#include "tng_jpegdec.h"
33#include "tng_vld_dec.h"
34#include "psb_def.h"
35#include "psb_drv_debug.h"
36
37#include "hwdefs/reg_io2.h"
38#include "hwdefs/msvdx_offsets.h"
39#include "hwdefs/msvdx_cmds_io2.h"
40#include "hwdefs/msvdx_vec_reg_io2.h"
41#include "hwdefs/msvdx_vec_jpeg_reg_io2.h"
42#include "hwdefs/dxva_fw_ctrl.h"
43
44#include <stdlib.h>
45#include <stdint.h>
46#include <string.h>
47#include <stdio.h>
48
49#define GET_SURFACE_INFO_is_defined(psb_surface) ((int) (psb_surface->extra_info[0]))
50#define SET_SURFACE_INFO_is_defined(psb_surface, val) psb_surface->extra_info[0] = (uint32_t) val;
51#define GET_SURFACE_INFO_picture_structure(psb_surface) (psb_surface->extra_info[1])
52#define SET_SURFACE_INFO_picture_structure(psb_surface, val) psb_surface->extra_info[1] = val;
53#define GET_SURFACE_INFO_picture_coding_type(psb_surface) ((int) (psb_surface->extra_info[2]))
54#define SET_SURFACE_INFO_picture_coding_type(psb_surface, val) psb_surface->extra_info[2] = (uint32_t) val;
55
56#define JPEG_MAX_SETS_HUFFMAN_TABLES 2
57#define JPEG_MAX_QUANT_TABLES 4
58
59#define TABLE_CLASS_DC  0
60#define TABLE_CLASS_AC  1
61#define TABLE_CLASS_NUM 2
62
63#define JPEG_PROFILE_BASELINE 0
64
65/************************************/
66/* VLC table defines and structures */
67
68/* max number of bits allowed in a VLC code */
69#define JPG_VLC_MAX_CODE_LEN        (16)
70
71/* max num bits to decode in any one decode direct operation */
72#define JPG_VLC_MAX_DIRECT_WIDTH    (6)
73
74static const uint8_t inverse_zigzag[64] =
75{
76    0x00, 0x01, 0x05, 0x06, 0x0e, 0x0f, 0x1b, 0x1c,
77    0x02, 0x04, 0x07, 0x0D, 0x10, 0x1a, 0x1d, 0x2a,
78    0x03, 0x08, 0x0C, 0x11, 0x19, 0x1e, 0x29, 0x2b,
79    0x09, 0x0B, 0x12, 0x18, 0x1f, 0x28, 0x2c, 0x35,
80    0x0A, 0x13, 0x17, 0x20, 0x27, 0x2d, 0x34, 0x36,
81    0x14, 0x16, 0x21, 0x26, 0x2e, 0x33, 0x37, 0x3c,
82    0x15, 0x22, 0x25, 0x2f, 0x32, 0x38, 0x3b, 0x3d,
83    0x23, 0x24, 0x30, 0x31, 0x39, 0x3a, 0x3e, 0x3f
84};
85
86
87/*
88******************************************************************************
89
90 This structure defines the VLC code used for a partiular symbol
91
92******************************************************************************/
93typedef struct
94{
95    uint16_t code;    // VLC code with valid data in top-most bits
96    uint8_t code_length;   // VLC code length
97    uint8_t symbol;
98
99} vlc_symbol_code_jpeg; // VLCSymbolCodeJPEG
100
101
102/*
103******************************************************************************
104
105 This structure describes a set of VLC codes for a particular Huffman tree
106
107******************************************************************************/
108typedef struct
109{
110    uint32_t num_codes;
111    uint32_t min_len;
112    uint32_t max_len;
113
114} vlc_symbol_stats_jpeg; // VLCSymbolStatsJPEG
115
116
117/*
118******************************************************************************
119
120 This structure describes the generated VLC code table
121
122******************************************************************************/
123typedef struct
124{
125    uint32_t size;
126    uint32_t initial_width;
127    uint32_t initial_opcode;
128
129} vlc_table_stats_jpeg; // VLCTableStatsJPEG
130
131
132/**************************************/
133/* JPEG VLC Table defines and OpCodes */
134
135#define JPG_MAKE_MASK(X) ((1<<(X))-1)
136
137#define JPG_INSTR_OP_CODE_WIDTH (3)
138#define JPG_INSTR_SHIFT_WIDTH   (3)
139#define JPG_INSTR_OFFSET_WIDTH  (9)
140
141#define JPG_INSTR_OP_CODE_MASK  JPG_MAKE_MASK(JPG_JPG_INSTR_OP_CODE_WIDTH)
142#define JPG_INSTR_SHIFT_MASK    JPG_MAKE_MASK(JPG_INSTR_SHIFT_WIDTH)
143#define JPG_INSTR_OFFSET_MASK   JPG_MAKE_MASK(JPG_INSTR_OFFSET_WIDTH)
144
145
146#define JPG_MAKE_OFFSET(code,width,leading) \
147(((code<<leading) & JPG_MAKE_MASK(JPG_VLC_MAX_CODE_LEN)) >> (JPG_VLC_MAX_CODE_LEN-width))
148
149typedef enum {
150    JPG_OP_DECODE_DIRECT = 0,
151    JPG_OP_DECODE_LEADING_1,
152    JPG_OP_DECODE_LEADING_0,
153
154    JPG_OP_CODE_INVALID,
155
156    JPG_OP_VALID_SYMBOL,
157    JPG_OP_VALID_RANGE_EVEN,
158    JPG_OP_VALID_RANGE_ODD,
159    JPG_OP_VALID_RANGE_EVEN_SET_FLAG,
160
161} vlc_op_code_jpeg; // VLCOpCodeJPEG
162
163/**************************************/
164
165struct context_JPEG_s {
166    struct context_DEC_s dec_ctx;
167    object_context_p obj_context; /* back reference */
168
169    uint32_t profile;
170
171    /* Picture parameters */
172    VAPictureParameterBufferJPEGBaseline *pic_params;
173
174    uint32_t display_picture_width;    /* in pixels */
175    uint32_t display_picture_height;    /* in pixels */
176
177    uint32_t coded_picture_width;    /* in pixels */
178    uint32_t coded_picture_height;    /* in pixels */
179
180    uint32_t MCU_width;
181    uint32_t MCU_height;
182    uint32_t size_mb;                /* in macroblocks */
183    uint32_t picture_width_mb;        /* in macroblocks */
184    uint32_t picture_height_mb;        /* in macroblocks */
185
186    uint8_t max_scalingH;
187    uint8_t max_scalingV;
188
189    /* VLC packed data */
190    struct psb_buffer_s vlc_packed_table;
191
192    uint32_t vlctable_buffer_size;
193    uint32_t rendec_qmatrix[JPEG_MAX_QUANT_TABLES][16];
194
195    /* Huffman table information as parsed from the bitstream */
196    vlc_symbol_code_jpeg* symbol_codes[TABLE_CLASS_NUM][JPEG_MAX_SETS_HUFFMAN_TABLES];
197    vlc_symbol_stats_jpeg symbol_stats[TABLE_CLASS_NUM][JPEG_MAX_SETS_HUFFMAN_TABLES];
198
199    /*  Huffman table information compiled for the hardware */
200    uint32_t huffman_table_space;
201    uint16_t* huffman_table_RAM;
202    vlc_table_stats_jpeg table_stats[TABLE_CLASS_NUM][JPEG_MAX_SETS_HUFFMAN_TABLES];
203};
204
205typedef struct context_JPEG_s *context_JPEG_p;
206
207#define INIT_CONTEXT_JPEG    context_JPEG_p ctx = (context_JPEG_p) obj_context->format_data;
208
209#define SURFACE(id)    ((object_surface_p) object_heap_lookup( &ctx->obj_context->driver_data->surface_heap, id ))
210
211static void tng_JPEG_QueryConfigAttributes(
212    VAProfile __maybe_unused profile,
213    VAEntrypoint __maybe_unused entrypoint,
214    VAConfigAttrib __maybe_unused * attrib_list,
215    int __maybe_unused num_attribs) {
216    /* No JPEG specific attributes */
217}
218
219static VAStatus tng_JPEG_ValidateConfig(object_config_p obj_config) {
220    int i;
221    /* Check all attributes */
222    for (i = 0; i < obj_config->attrib_count; i++) {
223        switch (obj_config->attrib_list[i].type) {
224        case VAConfigAttribRTFormat:
225            /* Ignore */
226            break;
227
228        default:
229            return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED;
230        }
231    }
232
233    return VA_STATUS_SUCCESS;
234}
235
236static VAStatus tng__JPEG_check_legal_picture(object_context_p obj_context, object_config_p obj_config) {
237    VAStatus vaStatus = VA_STATUS_SUCCESS;
238
239    if (NULL == obj_context) {
240        vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
241        DEBUG_FAILURE;
242        return vaStatus;
243    }
244
245    if (NULL == obj_config) {
246        vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
247        DEBUG_FAILURE;
248        return vaStatus;
249    }
250
251    switch (obj_config->profile) {
252    case VAProfileJPEGBaseline:
253        if ((obj_context->picture_width <= 0) || (obj_context->picture_height <= 0)) {
254            vaStatus = VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED;
255        }
256        break;
257
258    default:
259        vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
260        break;
261    }
262
263    return vaStatus;
264}
265
266static void tng_JPEG_DestroyContext(object_context_p obj_context);
267
268static void tng__JPEG_process_slice_data(context_DEC_p dec_ctx, VASliceParameterBufferBase *vld_slice_param);
269static void tng__JPEG_end_slice(context_DEC_p dec_ctx);
270static void tng__JPEG_begin_slice(context_DEC_p dec_ctx, VASliceParameterBufferBase *vld_slice_param);
271static VAStatus tng_JPEG_process_buffer(context_DEC_p dec_ctx, object_buffer_p buffer);
272
273static VAStatus tng_JPEG_CreateContext(
274    object_context_p obj_context,
275    object_config_p obj_config) {
276    VAStatus vaStatus = VA_STATUS_SUCCESS;
277    context_JPEG_p ctx;
278
279    /* Validate flag */
280    /* Validate picture dimensions */
281    vaStatus = tng__JPEG_check_legal_picture(obj_context, obj_config);
282    if (VA_STATUS_SUCCESS != vaStatus) {
283        DEBUG_FAILURE;
284        return vaStatus;
285    }
286
287    ctx = (context_JPEG_p) calloc(1, sizeof(struct context_JPEG_s));
288    if (NULL == ctx) {
289        vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
290        DEBUG_FAILURE;
291        return vaStatus;
292    }
293    obj_context->format_data = (void*) ctx;
294    ctx->obj_context = obj_context;
295    ctx->pic_params = NULL;
296
297    ctx->dec_ctx.begin_slice = tng__JPEG_begin_slice;
298    ctx->dec_ctx.process_slice = tng__JPEG_process_slice_data;
299    ctx->dec_ctx.end_slice = tng__JPEG_end_slice;
300    ctx->dec_ctx.process_buffer = tng_JPEG_process_buffer;
301    ctx->dec_ctx.preload_buffer = NULL;
302
303    switch (obj_config->profile) {
304    case VAProfileJPEGBaseline:
305        drv_debug_msg(VIDEO_DEBUG_GENERAL, "JPEG_PROFILE_BASELINE\n");
306        ctx->profile = JPEG_PROFILE_BASELINE;
307        break;
308
309    default:
310        ASSERT(0 == 1);
311        vaStatus = VA_STATUS_ERROR_UNKNOWN;
312    }
313
314    ctx->vlctable_buffer_size = 1984 * 2;
315    if (vaStatus == VA_STATUS_SUCCESS) {
316        vaStatus = psb_buffer_create(obj_context->driver_data,
317                                     ctx->vlctable_buffer_size,
318                                     psb_bt_cpu_vpu,
319                                     &ctx->vlc_packed_table);
320        DEBUG_FAILURE;
321    }
322
323    if (vaStatus == VA_STATUS_SUCCESS) {
324        vaStatus = vld_dec_CreateContext(&ctx->dec_ctx, obj_context);
325        DEBUG_FAILURE;
326    }
327
328    if (vaStatus != VA_STATUS_SUCCESS) {
329        tng_JPEG_DestroyContext(obj_context);
330    }
331
332    return vaStatus;
333}
334
335static void tng_JPEG_DestroyContext(
336    object_context_p obj_context) {
337    INIT_CONTEXT_JPEG
338    int i;
339
340    vld_dec_DestroyContext(&ctx->dec_ctx);
341
342    psb_buffer_destroy(&ctx->vlc_packed_table);
343
344    if (ctx->pic_params) {
345        free(ctx->pic_params);
346        ctx->pic_params = NULL;
347    }
348
349    if (ctx->symbol_codes[0][0]) {
350        free(ctx->symbol_codes[0][0]);
351        ctx->symbol_codes[0][0] = NULL;
352    }
353    if (ctx->symbol_codes[0][1]) {
354        free(ctx->symbol_codes[0][1]);
355        ctx->symbol_codes[0][1] = NULL;
356    }
357    if (ctx->symbol_codes[1][0]) {
358        free(ctx->symbol_codes[1][0]);
359        ctx->symbol_codes[1][0] = NULL;
360    }
361    if (ctx->symbol_codes[1][1]) {
362        free(ctx->symbol_codes[1][1]);
363        ctx->symbol_codes[1][1] = NULL;
364    }
365    free(obj_context->format_data);
366    obj_context->format_data = NULL;
367}
368
369static uint16_t jpg_vlc_valid_symbol(const vlc_symbol_code_jpeg * symbol_code, const uint32_t leading) {
370    uint16_t entry = 0;
371    IMG_ASSERT( (symbol_code->code_length - leading - 1) >= 0 );
372
373    /* VLC microcode entry for a valid symbol */
374    entry |= (JPG_OP_VALID_SYMBOL << (JPG_INSTR_SHIFT_WIDTH+JPG_INSTR_OFFSET_WIDTH));
375    entry |= ((symbol_code->code_length - leading - 1) << JPG_INSTR_OFFSET_WIDTH);
376    entry |= symbol_code->symbol;
377    return entry;
378}
379
380static uint32_t
381jpg_vlc_write_direct_command(uint16_t * const vlc_ram, uint32_t result_offset) {
382    uint32_t width = 0x7fff & *vlc_ram;
383    uint16_t entry = 0;
384
385    /* check that the max width read from the VLC entry is valid */
386    IMG_ASSERT( 0x8000 & *vlc_ram );
387
388    /* limit to the maximum width for this algorithm */
389    width = (width > JPG_VLC_MAX_DIRECT_WIDTH)? JPG_VLC_MAX_DIRECT_WIDTH: width;
390
391    /* VLC microcode for decode direct command */
392    entry |= (JPG_OP_DECODE_DIRECT << (JPG_INSTR_SHIFT_WIDTH+JPG_INSTR_OFFSET_WIDTH));
393    entry |= ((width - 1) << JPG_INSTR_OFFSET_WIDTH);
394    entry |= result_offset;
395
396    /* write command */
397    *vlc_ram = entry;
398
399    return width;
400}
401
402static uint32_t
403jpg_vlc_get_offset(const vlc_symbol_code_jpeg * symbol_code, uint32_t width, uint32_t leading) {
404    uint32_t offset;
405
406    /* lose bits already decoded */
407    offset = symbol_code->code << leading;
408    offset &= JPG_MAKE_MASK(JPG_VLC_MAX_CODE_LEN);
409    /* convert truncated code to offset */
410    offset >>= (JPG_VLC_MAX_CODE_LEN - width);
411    return offset;
412}
413
414static uint32_t
415jpg_vlc_decode_direct_symbols(const vlc_symbol_code_jpeg * symbol_code, uint16_t * const table_ram, const uint32_t width,
416    const uint32_t leading) {
417    uint32_t offset, limit;
418    uint16_t entry;
419
420    /* this function is only for codes short enough to produce valid symbols */
421    IMG_ASSERT( symbol_code->code_length <= leading + width );
422    IMG_ASSERT( symbol_code->code_length > leading );
423
424    /* lose bits already decoded */
425    offset = symbol_code->code << leading;
426    offset &= JPG_MAKE_MASK(JPG_VLC_MAX_CODE_LEN);
427
428    /* convert truncated code to offset */
429    offset >>= (JPG_VLC_MAX_CODE_LEN - width);
430    /* expand offset to encorporate undefined code bits */
431    limit = offset + (1 << (width - (symbol_code->code_length - leading)));
432
433    /* for all code variants - insert symbol into the decode direct result table */
434    entry = jpg_vlc_valid_symbol( symbol_code, leading );
435    for (; offset < limit; offset++) {
436        table_ram[offset] = entry;
437    }
438
439    /* return the number of entries written */
440    return limit - offset - 1;
441}
442
443static uint32_t
444jpg_vlc_decode_direct(
445    const vlc_symbol_code_jpeg * symbol_codes,
446    const uint32_t num_codes,
447    uint16_t * const table_ram,
448    const uint32_t direct_width,
449    const uint32_t leading_width,
450    const uint32_t leading_pattern) {
451    const uint32_t next_leading_width = leading_width + direct_width;
452    const uint32_t next_leading_mask = JPG_MAKE_MASK(next_leading_width) << (JPG_VLC_MAX_CODE_LEN-next_leading_width);
453    const uint32_t leading_mask = JPG_MAKE_MASK(leading_width) << (JPG_VLC_MAX_CODE_LEN-leading_width);
454
455    uint32_t num_vlc_ops = 1 << direct_width;
456    uint32_t next_section, next_width, next_leading_pattern;
457    uint32_t offset;
458    uint32_t i;
459
460    /* sanity - check this decode direct will not exceed the max code len */
461    IMG_ASSERT(next_leading_width <= JPG_VLC_MAX_CODE_LEN);
462
463    /* set all VLC ops for this decode direct to invalid */
464    for (i = 0; i < num_vlc_ops; i++) {
465        table_ram[i] = (JPG_OP_CODE_INVALID << (JPG_INSTR_SHIFT_WIDTH+JPG_INSTR_OFFSET_WIDTH));
466    }
467
468    /* iterate over code table and insert VLC ops until */
469    /* codes become too long for this iteration or we run out of codes */
470    for (i = 0; symbol_codes[i].code_length <= next_leading_width && i < num_codes; i++) {
471        /* only use codes that match the specified leading portion */
472        if ((((uint32_t)symbol_codes[i].code) & leading_mask) == leading_pattern) {
473            jpg_vlc_decode_direct_symbols(&symbol_codes[i], table_ram, direct_width, leading_width );
474        }
475    }
476    next_section = i;
477
478    /* assign the longest code length for each remaining entry */
479    for (i = next_section; i < num_codes; i++) {
480        /* only use codes that match the specified leading portion */
481        if ((((uint32_t)symbol_codes[i].code) & leading_mask) == leading_pattern) {
482            /* enable the unused VLC bit to indicate this is not a command */
483            offset = jpg_vlc_get_offset(&symbol_codes[i], direct_width, leading_width);
484            table_ram[offset] = 0x8000 | (symbol_codes[i].code_length - next_leading_width);
485        }
486    }
487
488    /* for the remaining (long) codes */
489    for (i = next_section; i < num_codes; i++) {
490        /* only use codes that match the specified leading portion */
491        if ((((uint32_t)symbol_codes[i].code) & leading_mask) == leading_pattern) {
492            /* if a command has not been written for this direct offset */
493            offset = jpg_vlc_get_offset(&symbol_codes[i], direct_width, leading_width);
494            if (table_ram[offset] & 0x8000) {
495                /* write command the decode direct command */
496                next_width = jpg_vlc_write_direct_command(
497                        &table_ram[offset],
498                        num_vlc_ops - offset );
499
500                next_leading_pattern = (uint32_t)symbol_codes[i].code & next_leading_mask;
501
502                /* decode direct recursive call */
503                num_vlc_ops += jpg_vlc_decode_direct(
504                    &symbol_codes[i],
505                    num_codes - i,
506                    &table_ram[num_vlc_ops],
507                    next_width,
508                    next_leading_width,
509                    next_leading_pattern);
510            }
511        }
512    }
513    return num_vlc_ops;
514}
515
516static void JPG_VLC_CompileTable(
517    const vlc_symbol_code_jpeg * symbol_codes,
518    const vlc_symbol_stats_jpeg * psSymbolStats,
519    const uint32_t __maybe_unused ram_size,
520    uint16_t * table_ram,
521    vlc_table_stats_jpeg * ptable_stats)
522{
523    ptable_stats->initial_width = 5;
524    ptable_stats->initial_opcode = JPG_OP_DECODE_DIRECT;
525
526    ptable_stats->size = jpg_vlc_decode_direct(
527        symbol_codes,
528        psSymbolStats->num_codes,
529        table_ram,
530        JPG_VLC_MAX_DIRECT_WIDTH,
531        0,
532        0);
533
534    IMG_ASSERT( ptable_stats->size <= ram_size );
535}
536
537static void compile_huffman_tables(context_JPEG_p ctx) {
538    VAStatus vaStatus = VA_STATUS_SUCCESS;
539    ctx->huffman_table_space = 1984;
540
541    if (0 == psb_buffer_map(&ctx->vlc_packed_table, (unsigned char **)&ctx->huffman_table_RAM)) {
542        // Compile Tables
543        uint32_t table_class;
544        uint32_t table_id;
545        for (table_class = 0; table_class < TABLE_CLASS_NUM; table_class++) {
546            for (table_id = 0; table_id < JPEG_MAX_SETS_HUFFMAN_TABLES; table_id++) {
547                if (ctx->symbol_stats[table_class][table_id].num_codes) {
548                    JPG_VLC_CompileTable(ctx->symbol_codes[table_class][table_id],
549                        &ctx->symbol_stats[table_class][table_id], ctx->huffman_table_space, ctx->huffman_table_RAM,
550                        &ctx->table_stats[table_class][table_id]);
551                    ctx->huffman_table_space -= ctx->table_stats[table_class][table_id].size;
552                    ctx->huffman_table_RAM += ctx->table_stats[table_class][table_id].size;
553                }
554
555            }
556        }
557        psb_buffer_unmap(&ctx->vlc_packed_table);
558    } else {
559        vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
560        DEBUG_FAILURE;
561    }
562
563}
564
565static VAStatus tng__JPEG_process_picture_param(context_JPEG_p ctx, object_buffer_p obj_buffer) {
566    VAStatus vaStatus;
567    ASSERT(obj_buffer->type == VAPictureParameterBufferType);
568    ASSERT(obj_buffer->num_elements == 1);
569    ASSERT(obj_buffer->size == sizeof(VAPictureParameterBufferJPEGBaseline));
570
571    if ((obj_buffer->num_elements != 1) ||
572        (obj_buffer->size != sizeof(VAPictureParameterBufferJPEGBaseline))) {
573        return VA_STATUS_ERROR_UNKNOWN;
574    }
575
576    /* Transfer ownership of VAPictureParameterBufferJPEGBaseline data */
577    if (ctx->pic_params) {
578        free(ctx->pic_params);
579    }
580    ctx->pic_params = (VAPictureParameterBufferJPEGBaseline *) obj_buffer->buffer_data;
581    ctx->display_picture_width = ctx->pic_params->picture_width;
582    ctx->display_picture_height = ctx->pic_params->picture_height;
583
584    ctx->coded_picture_width = ( ctx->display_picture_width + 7 ) & ( ~7 );
585    ctx->coded_picture_height = ( ctx->display_picture_height + 7 ) & ( ~7 );
586    ctx->max_scalingH = 0;
587    ctx->max_scalingV = 0;
588
589    uint8_t component_id;
590    for (component_id = 0; component_id < ctx->pic_params->num_components; component_id++) {
591        if (ctx->max_scalingH < ctx->pic_params->components->h_sampling_factor)
592            ctx->max_scalingH = ctx->pic_params->components->h_sampling_factor;
593        if (ctx->max_scalingV < ctx->pic_params->components->v_sampling_factor)
594            ctx->max_scalingV = ctx->pic_params->components->v_sampling_factor;
595    }
596
597    ctx->MCU_width = (ctx->coded_picture_width + (8 * ctx->max_scalingH) - 1) / (8 * ctx->max_scalingH);
598    ctx->MCU_height = (ctx->coded_picture_height + (8 * ctx->max_scalingV) - 1) / (8 * ctx->max_scalingV);
599
600    ctx->picture_width_mb = (ctx->coded_picture_width  + 15) / 16;
601    ctx->picture_height_mb = (ctx->coded_picture_height  + 15) / 16;
602    ctx->size_mb = ctx->picture_width_mb * ctx->picture_height_mb;
603
604
605    obj_buffer->buffer_data = NULL;
606    obj_buffer->size = 0;
607
608
609    return VA_STATUS_SUCCESS;
610}
611
612static void tng__JPEG_write_qmatrices(context_JPEG_p ctx) {
613    psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
614    int i;
615
616    psb_cmdbuf_rendec_start(cmdbuf, REG_MSVDX_VEC_IQRAM_OFFSET);
617
618    for (i = 0; i < 16; i++) {
619        psb_cmdbuf_rendec_write(cmdbuf, ctx->rendec_qmatrix[0][i]);
620    }
621    for (i = 0; i < 16; i++) {
622        psb_cmdbuf_rendec_write(cmdbuf, ctx->rendec_qmatrix[1][i]);
623    }
624    for (i = 0; i < 16; i++) {
625        psb_cmdbuf_rendec_write(cmdbuf, ctx->rendec_qmatrix[2][i]);
626    }
627    for (i = 0; i < 16; i++) {
628        psb_cmdbuf_rendec_write(cmdbuf, ctx->rendec_qmatrix[3][i]);
629    }
630
631    psb_cmdbuf_rendec_end(cmdbuf);
632}
633
634static VAStatus tng__JPEG_process_iq_matrix(context_JPEG_p ctx, object_buffer_p obj_buffer) {
635    VAIQMatrixBufferJPEGBaseline *qmatrix_data = (VAIQMatrixBufferJPEGBaseline *) obj_buffer->buffer_data;
636    ASSERT(obj_buffer->type == VAIQMatrixBufferType);
637    ASSERT(obj_buffer->num_elements == 1);
638    ASSERT(obj_buffer->size == sizeof(VAIQMatrixBufferJPEGBaseline));
639
640    uint32_t dqt_ind;
641
642    for (dqt_ind = 0; dqt_ind < 4; dqt_ind++) {
643        // Reorder Quant table for hardware
644        uint32_t table_ind = 0;
645        uint32_t rendec_table_ind = 0;
646        if (qmatrix_data->load_quantiser_table[dqt_ind]) {
647            while(table_ind < 64) {
648                ctx->rendec_qmatrix[dqt_ind][rendec_table_ind] =
649                        (qmatrix_data->quantiser_table[dqt_ind][inverse_zigzag[table_ind+3]] << 24) |
650                        (qmatrix_data->quantiser_table[dqt_ind][inverse_zigzag[table_ind+2]] << 16) |
651                        (qmatrix_data->quantiser_table[dqt_ind][inverse_zigzag[table_ind+1]] << 8) |
652                        (qmatrix_data->quantiser_table[dqt_ind][inverse_zigzag[table_ind]]);
653
654                table_ind += 4;
655                rendec_table_ind++;
656            }
657        }
658    }
659
660    return VA_STATUS_SUCCESS;
661}
662
663
664static void tng__JPEG_write_huffman_tables(context_JPEG_p ctx) {
665    uint32_t reg_value;
666    psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
667
668    // VLC Table
669    // Write a LLDMA Cmd to transfer VLD Table data
670    psb_cmdbuf_dma_write_cmdbuf(cmdbuf, &ctx->vlc_packed_table, 0,
671                                  ctx->vlctable_buffer_size, 0,
672                                  DMA_TYPE_VLC_TABLE);
673
674    // Write Table addresses
675    psb_cmdbuf_reg_start_block(cmdbuf, 0);
676    reg_value = 0;
677    uint32_t table_address = 0;
678    REGIO_WRITE_FIELD_LITE( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0, VLC_TABLE_ADDR0, table_address );
679    table_address += ctx->table_stats[0][0].size;
680    REGIO_WRITE_FIELD_LITE( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0, VLC_TABLE_ADDR1, table_address );
681    psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET( MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0 ), reg_value);
682
683    reg_value = 0;
684    table_address += ctx->table_stats[0][1].size;
685    REGIO_WRITE_FIELD_LITE( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR2, VLC_TABLE_ADDR4, table_address );
686    table_address += ctx->table_stats[1][0].size;
687    REGIO_WRITE_FIELD_LITE( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR2, VLC_TABLE_ADDR5, table_address );
688    psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET( MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR2 ), reg_value);
689    psb_cmdbuf_reg_end_block(cmdbuf);
690
691    // Write Initial Widths
692    psb_cmdbuf_reg_start_block(cmdbuf, 0);
693    reg_value = 0;
694    REGIO_WRITE_FIELD_LITE( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_WIDTH0, VLC_TABLE_INITIAL_WIDTH0,
695        ctx->table_stats[0][0].initial_width );
696    REGIO_WRITE_FIELD_LITE( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_WIDTH0, VLC_TABLE_INITIAL_WIDTH1,
697        ctx->table_stats[0][1].initial_width );
698    REGIO_WRITE_FIELD_LITE( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_WIDTH0, VLC_TABLE_INITIAL_WIDTH4,
699        ctx->table_stats[1][0].initial_width );
700    REGIO_WRITE_FIELD_LITE( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_WIDTH0, VLC_TABLE_INITIAL_WIDTH5,
701        ctx->table_stats[1][1].initial_width );
702    psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET( MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_WIDTH0 ), reg_value);
703    psb_cmdbuf_reg_end_block(cmdbuf);
704
705    // Write Initial Opcodes
706    psb_cmdbuf_reg_start_block(cmdbuf, 0);
707    reg_value = 0;
708    REGIO_WRITE_FIELD_LITE( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_OPCODE0, VLC_TABLE_INITIAL_OPCODE0,
709        ctx->table_stats[0][0].initial_opcode );
710    REGIO_WRITE_FIELD_LITE( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_OPCODE0, VLC_TABLE_INITIAL_OPCODE1,
711        ctx->table_stats[0][1].initial_opcode );
712    REGIO_WRITE_FIELD_LITE( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_OPCODE0, VLC_TABLE_INITIAL_OPCODE4,
713        ctx->table_stats[1][0].initial_opcode );
714    REGIO_WRITE_FIELD_LITE( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_OPCODE0, VLC_TABLE_INITIAL_OPCODE5,
715        ctx->table_stats[1][1].initial_opcode );
716    psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET( MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_OPCODE0 ), reg_value);
717    psb_cmdbuf_reg_end_block(cmdbuf);
718
719}
720
721static VAStatus tng__JPEG_process_huffman_tables(context_JPEG_p ctx, object_buffer_p obj_buffer) {
722
723    VAHuffmanTableBufferJPEGBaseline *huff = (VAHuffmanTableBufferJPEGBaseline *) obj_buffer->buffer_data;
724    ASSERT(obj_buffer->type == VAHuffmanTableBufferType);
725    ASSERT(obj_buffer->num_elements == 1);
726    ASSERT(obj_buffer->size == sizeof(VAHuffmanTableBufferJPEGBaseline));
727
728    uint32_t table_id;
729    for (table_id = 0; table_id < JPEG_MAX_SETS_HUFFMAN_TABLES; table_id++) {
730        // Find out the number of entries in the table
731        uint32_t table_entries = 0;
732        uint32_t bit_ind;
733        for (bit_ind = 0; bit_ind < 16; bit_ind++) {
734            table_entries += huff->huffman_table[table_id].num_dc_codes[bit_ind];
735        }
736
737        ctx->symbol_codes[0][table_id] =(vlc_symbol_code_jpeg *)malloc(sizeof(vlc_symbol_code_jpeg) * table_entries);
738        // Parse huffman code sizes
739        uint32_t huff_ind = 0;
740        for (bit_ind = 0; bit_ind < 16; bit_ind++) {
741            uint32_t num_codes = huff->huffman_table[table_id].num_dc_codes[bit_ind];
742            while (num_codes) {
743                ctx->symbol_codes[0][table_id][huff_ind].code_length = bit_ind + 1;
744                num_codes--;
745                huff_ind++;
746            }
747        }
748
749        // Calculate huffman codes
750
751        uint16_t code = 0;
752        uint8_t code_size = ctx->symbol_codes[0][table_id][0].code_length;
753        huff_ind = 0;
754
755        while (huff_ind < table_entries) {
756            if (ctx->symbol_codes[0][table_id][huff_ind].code_length == code_size) {
757                ctx->symbol_codes[0][table_id][huff_ind].code = code << ( 16 - code_size );
758                huff_ind++;
759                code++;
760            } else {
761                code <<= 1;
762                code_size++;
763            }
764        }
765
766        // Create table of code values
767        uint32_t table_ind;
768        for (table_ind = 0; table_ind < table_entries; table_ind++) {
769            ctx->symbol_codes[0][table_id][table_ind].symbol = huff->huffman_table[table_id].dc_values[table_ind];
770        }
771
772        // Store the number of codes in the table
773        ctx->symbol_stats[0][table_id].num_codes = table_entries;
774
775        // for AC table
776        // Find out the number of entries in the table
777        table_entries = 0;
778        for (bit_ind = 0; bit_ind < 16; bit_ind++) {
779            table_entries += huff->huffman_table[table_id].num_ac_codes[bit_ind];
780        }
781
782        // Allocate memory for huffman table codes
783        ctx->symbol_codes[1][table_id] = (vlc_symbol_code_jpeg *)malloc(sizeof(vlc_symbol_code_jpeg) * table_entries);
784
785        // Parse huffman code sizes
786        huff_ind = 0;
787        for (bit_ind = 0; bit_ind < 16; bit_ind++) {
788            uint32_t num_codes = huff->huffman_table[table_id].num_ac_codes[bit_ind];
789            while (num_codes) {
790                ctx->symbol_codes[1][table_id][huff_ind].code_length = bit_ind + 1;
791                num_codes--;
792                huff_ind++;
793            }
794        }
795
796        // Calculate huffman codes
797        code = 0;
798        code_size = ctx->symbol_codes[1][table_id][0].code_length;
799        huff_ind = 0;
800        while (huff_ind < table_entries) {
801            if (ctx->symbol_codes[1][table_id][huff_ind].code_length == code_size) {
802                ctx->symbol_codes[1][table_id][huff_ind].code = code << ( 16 - code_size );
803                huff_ind++;
804                code++;
805            } else {
806                code <<= 1;
807                code_size++;
808            }
809        }
810
811        // Create table of code values
812        for (table_ind = 0; table_ind < table_entries; table_ind++) {
813            ctx->symbol_codes[1][table_id][table_ind].symbol = huff->huffman_table[table_id].ac_values[table_ind];;
814        }
815        // Store the number of codes in the table
816        ctx->symbol_stats[1][table_id].num_codes = table_entries;
817    }
818
819    compile_huffman_tables(ctx);
820
821    return VA_STATUS_SUCCESS;
822}
823
824
825static void tng__JPEG_set_operating_mode(context_JPEG_p ctx) {
826    psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
827    ctx->obj_context->operating_mode = 0;
828
829    REGIO_WRITE_FIELD_LITE(ctx->obj_context->operating_mode, MSVDX_CMDS, OPERATING_MODE, USE_EXT_ROW_STRIDE, 1 );
830    REGIO_WRITE_FIELD_LITE(ctx->obj_context->operating_mode, MSVDX_CMDS, OPERATING_MODE, ASYNC_MODE, 1 );
831    REGIO_WRITE_FIELD_LITE(ctx->obj_context->operating_mode, MSVDX_CMDS, OPERATING_MODE, CHROMA_FORMAT,	1);
832
833    psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET( MSVDX_CMDS, OPERATING_MODE ));
834
835    psb_cmdbuf_rendec_write(cmdbuf, ctx->obj_context->operating_mode);
836
837    psb_cmdbuf_rendec_end(cmdbuf);
838
839}
840
841static void tng__JPEG_set_reference_pictures(context_JPEG_p ctx)
842{
843    psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
844    psb_surface_p target_surface = ctx->obj_context->current_render_target->psb_surface;
845
846    psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, REFERENCE_PICTURE_BASE_ADDRESSES));
847
848    uint32_t planr_size =  target_surface->chroma_offset;
849    psb_cmdbuf_rendec_write_address(cmdbuf, &target_surface->buf, target_surface->buf.buffer_ofs);
850    psb_cmdbuf_rendec_write_address(cmdbuf, &target_surface->buf, target_surface->buf.buffer_ofs + planr_size);
851    psb_cmdbuf_rendec_write_address(cmdbuf, &target_surface->buf, target_surface->buf.buffer_ofs + planr_size * 2);
852    // psb_cmdbuf_rendec_write_address(cmdbuf, &target_surface->buf, target_surface->buf.buffer_ofs + planr_size * 3);
853    psb_cmdbuf_rendec_end(cmdbuf);
854}
855
856static void tng__JPEG_set_ent_dec(context_JPEG_p ctx) {
857    psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
858    uint32_t reg_value;
859
860    psb_cmdbuf_reg_start_block(cmdbuf, 0);
861    reg_value = 0;
862    REGIO_WRITE_FIELD_LITE( reg_value, MSVDX_VEC, CR_VEC_ENTDEC_FE_CONTROL, ENTDEC_FE_MODE, 0 );
863    psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET( MSVDX_VEC, CR_VEC_ENTDEC_FE_CONTROL ), reg_value);
864    psb_cmdbuf_reg_end_block(cmdbuf);
865
866    psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET( MSVDX_VEC, CR_VEC_ENTDEC_BE_CONTROL ));
867    reg_value = 0;
868    REGIO_WRITE_FIELD(reg_value, MSVDX_VEC, CR_VEC_ENTDEC_BE_CONTROL, ENTDEC_BE_MODE, 0);
869    psb_cmdbuf_rendec_write(cmdbuf, reg_value);
870    psb_cmdbuf_rendec_end(cmdbuf);
871
872}
873
874static void tng__JPEG_set_register(context_JPEG_p ctx, VASliceParameterBufferJPEGBaseline *slice_param) {
875    psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
876    uint32_t reg_value;
877    const uint32_t num_MCUs = ctx->MCU_width * ctx->MCU_height;
878    const uint32_t num_MCUs_dec = slice_param->restart_interval ? min(slice_param->restart_interval, num_MCUs) :  num_MCUs;
879
880    psb_cmdbuf_reg_start_block(cmdbuf, 0);
881    // CR_VEC_JPEG_FE_COMPONENTS
882    reg_value = 0;
883    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_COMPONENTS, MAX_V, ctx->max_scalingV);
884    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_COMPONENTS, MAX_H, ctx->max_scalingH);
885    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_COMPONENTS, FE_COMPONENTS,
886        slice_param->num_components);
887    psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_COMPONENTS ), reg_value);
888
889    // CR_VEC_JPEG_FE_HEIGHT
890    reg_value = 0;
891    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_HEIGHT, FE_HEIGHT_MINUS1,
892        ctx->coded_picture_height - 1);
893    psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_HEIGHT ), reg_value);
894
895    // CR_VEC_JPEG_FE_RESTART_POS
896    reg_value = 0;
897    psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_RESTART_POS), reg_value);
898
899    // CR_VEC_JPEG_FE_WIDTH
900    reg_value = 0;
901    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_WIDTH, FE_WIDTH_MINUS1,
902        ctx->coded_picture_width - 1 );
903    psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_WIDTH), reg_value);
904
905    // CR_VEC_JPEG_FE_ENTROPY_CODING
906    reg_value = 0;
907    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_ENTROPY_CODING, NUM_MCUS_LESS1, num_MCUs_dec - 1);
908
909    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_ENTROPY_CODING, TA3,
910        slice_param->components[3].ac_table_selector);
911    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_ENTROPY_CODING, TD3,
912        slice_param->components[3].dc_table_selector);
913    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_ENTROPY_CODING, TA2,
914        slice_param->components[2].ac_table_selector);
915    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_ENTROPY_CODING, TD2,
916        slice_param->components[2].dc_table_selector);
917    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_ENTROPY_CODING, TA1,
918        slice_param->components[1].ac_table_selector);
919    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_ENTROPY_CODING, TD1,
920        slice_param->components[1].dc_table_selector );
921    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_ENTROPY_CODING, TA0,
922        slice_param->components[0].ac_table_selector);
923    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_ENTROPY_CODING, TD0,
924        slice_param->components[0].dc_table_selector);
925
926    psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET( MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_ENTROPY_CODING ), reg_value);
927
928    // CR_VEC_JPEG_FE_SCALING
929    reg_value = 0;
930    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_SCALING, FE_V3,
931        ctx->pic_params->components[3].v_sampling_factor);
932    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_SCALING, FE_H3,
933        ctx->pic_params->components[3].h_sampling_factor );
934    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_SCALING, FE_V2,
935        ctx->pic_params->components[2].v_sampling_factor);
936    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_SCALING, FE_H2,
937        ctx->pic_params->components[2].h_sampling_factor );
938    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_SCALING, FE_V1,
939        ctx->pic_params->components[1].v_sampling_factor );
940    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_SCALING, FE_H1,
941        ctx->pic_params->components[1].h_sampling_factor );
942    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_SCALING, FE_V0,
943        ctx->pic_params->components[0].v_sampling_factor );
944    REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_SCALING, FE_H0,
945        ctx->pic_params->components[0].h_sampling_factor );
946
947    psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET( MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_SCALING ), reg_value);
948    psb_cmdbuf_reg_end_block(cmdbuf);
949
950    psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET( MSVDX_VEC_JPEG, CR_VEC_JPEG_BE_HEIGHT ));
951    // CR_VEC_JPEG_BE_HEIGHT
952    reg_value = 0;
953    REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_BE_HEIGHT, BE_HEIGHT_MINUS1,
954        ctx->coded_picture_height - 1);
955    psb_cmdbuf_rendec_write(cmdbuf, reg_value);
956
957    // CR_VEC_JPEG_BE_WIDTH
958    reg_value = 0;
959    REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_BE_WIDTH, BE_WIDTH_MINUS1, ctx->coded_picture_width - 1);
960    psb_cmdbuf_rendec_write(cmdbuf, reg_value);
961
962    // CR_VEC_JPEG_BE_QUANTISATION
963    reg_value = 0;
964    REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_BE_QUANTISATION, TQ3,
965        ctx->pic_params->components[3].quantiser_table_selector);
966    REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_BE_QUANTISATION, TQ2,
967        ctx->pic_params->components[2].quantiser_table_selector);
968    REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_BE_QUANTISATION, TQ1,
969        ctx->pic_params->components[1].quantiser_table_selector);
970    REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_BE_QUANTISATION, TQ0,
971        ctx->pic_params->components[0].quantiser_table_selector );
972    psb_cmdbuf_rendec_write(cmdbuf, reg_value);
973
974    // CR_VEC_JPEG_BE_CONTROL
975    reg_value = 0;
976    REGIO_WRITE_FIELD( reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_BE_CONTROL, RGB, 0 );
977    psb_cmdbuf_rendec_write(cmdbuf, reg_value);
978
979    psb_cmdbuf_rendec_end(cmdbuf);
980}
981
982static void tng__JPEG_begin_slice(context_DEC_p dec_ctx, VASliceParameterBufferBase __maybe_unused * vld_slice_param)
983{
984    context_JPEG_p ctx = (context_JPEG_p)dec_ctx;
985
986    dec_ctx->bits_offset = 0;
987    dec_ctx->SR_flags = CMD_ENABLE_RBDU_EXTRACTION;
988    *dec_ctx->cmd_params |=ctx->MCU_width * ctx->MCU_height;
989    *dec_ctx->slice_first_pic_last &= 0xfefe;
990    tng__JPEG_write_huffman_tables(ctx);
991    tng__JPEG_write_qmatrices(ctx);
992}
993
994static void tng__JPEG_process_slice_data(context_DEC_p dec_ctx, VASliceParameterBufferBase *vld_slice_param)
995{
996    VASliceParameterBufferJPEGBaseline *slice_param = (VASliceParameterBufferJPEGBaseline *) vld_slice_param;
997    context_JPEG_p ctx = (context_JPEG_p)dec_ctx;
998
999    tng__JPEG_set_operating_mode(ctx);
1000    tng__JPEG_set_reference_pictures(ctx);
1001    vld_dec_setup_alternative_frame(ctx->obj_context);
1002    tng__JPEG_set_ent_dec(ctx);
1003    tng__JPEG_set_register(ctx, slice_param);
1004}
1005
1006static void tng__JPEG_end_slice(context_DEC_p dec_ctx)
1007{
1008    context_JPEG_p ctx = (context_JPEG_p)dec_ctx;
1009
1010    ctx->obj_context->flags = FW_VA_RENDER_IS_FIRST_SLICE | FW_VA_RENDER_IS_LAST_SLICE | FW_INTERNAL_CONTEXT_SWITCH;
1011    ctx->obj_context->first_mb = 0;
1012    ctx->obj_context->last_mb = ((ctx->picture_height_mb - 1) << 8) | (ctx->picture_width_mb - 1);
1013    *(dec_ctx->slice_first_pic_last) = (ctx->obj_context->first_mb << 16) | ((ctx->obj_context->last_mb) & 0xfefe);
1014
1015}
1016
1017static VAStatus tng_JPEG_BeginPicture(
1018    object_context_p obj_context) {
1019    INIT_CONTEXT_JPEG
1020
1021    if (ctx->pic_params) {
1022        free(ctx->pic_params);
1023        ctx->pic_params = NULL;
1024    }
1025
1026    return VA_STATUS_SUCCESS;
1027}
1028
1029static VAStatus tng_JPEG_process_buffer(
1030    context_DEC_p dec_ctx,
1031    object_buffer_p buffer) {
1032    context_JPEG_p ctx = (context_JPEG_p)dec_ctx;
1033    VAStatus vaStatus = VA_STATUS_SUCCESS;
1034    object_buffer_p obj_buffer = buffer;
1035
1036    switch (obj_buffer->type) {
1037    case VAPictureParameterBufferType:
1038        drv_debug_msg(VIDEO_DEBUG_GENERAL, "tng_JPEG_RenderPicture got VAPictureParameterBuffer\n");
1039        vaStatus = tng__JPEG_process_picture_param(ctx, obj_buffer);
1040        DEBUG_FAILURE;
1041        break;
1042
1043    case VAIQMatrixBufferType:
1044        drv_debug_msg(VIDEO_DEBUG_GENERAL, "tng_JPEG_RenderPicture got VAIQMatrixBufferType\n");
1045        vaStatus = tng__JPEG_process_iq_matrix(ctx, obj_buffer);
1046        DEBUG_FAILURE;
1047        break;
1048
1049    case VAHuffmanTableBufferType:
1050        drv_debug_msg(VIDEO_DEBUG_GENERAL, "tng_JPEG_RenderPicture got VAIQMatrixBufferType\n");
1051        vaStatus = tng__JPEG_process_huffman_tables(ctx, obj_buffer);
1052        DEBUG_FAILURE;
1053        break;
1054
1055    default:
1056        vaStatus = VA_STATUS_ERROR_UNKNOWN;
1057        DEBUG_FAILURE;
1058    }
1059
1060    return vaStatus;
1061}
1062
1063static VAStatus tng_JPEG_EndPicture(
1064    object_context_p obj_context) {
1065    INIT_CONTEXT_JPEG
1066
1067    if (psb_context_flush_cmdbuf(ctx->obj_context)) {
1068        return VA_STATUS_ERROR_UNKNOWN;
1069    }
1070
1071    if (ctx->pic_params) {
1072        free(ctx->pic_params);
1073        ctx->pic_params = NULL;
1074    }
1075
1076    return VA_STATUS_SUCCESS;
1077}
1078
1079struct format_vtable_s tng_JPEG_vtable = {
1080queryConfigAttributes:
1081    tng_JPEG_QueryConfigAttributes,
1082validateConfig:
1083    tng_JPEG_ValidateConfig,
1084createContext:
1085    tng_JPEG_CreateContext,
1086destroyContext:
1087    tng_JPEG_DestroyContext,
1088beginPicture:
1089    tng_JPEG_BeginPicture,
1090renderPicture:
1091    vld_dec_RenderPicture,
1092endPicture:
1093    tng_JPEG_EndPicture
1094};
1095