Home | History | Annotate | Download | only in src
      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 (at) intel.com>
     27  *    Zeng Li <li.zeng (at) 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 
     74 static 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 ******************************************************************************/
     93 typedef 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 ******************************************************************************/
    108 typedef 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 ******************************************************************************/
    123 typedef 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 
    149 typedef 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 
    165 struct 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 
    205 typedef 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 
    211 static 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 
    219 static 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 
    236 static 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 
    266 static void tng_JPEG_DestroyContext(object_context_p obj_context);
    267 
    268 static void tng__JPEG_process_slice_data(context_DEC_p dec_ctx, VASliceParameterBufferBase *vld_slice_param);
    269 static void tng__JPEG_end_slice(context_DEC_p dec_ctx);
    270 static void tng__JPEG_begin_slice(context_DEC_p dec_ctx, VASliceParameterBufferBase *vld_slice_param);
    271 static VAStatus tng_JPEG_process_buffer(context_DEC_p dec_ctx, object_buffer_p buffer);
    272 
    273 static 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 
    335 static 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 
    369 static 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 
    380 static uint32_t
    381 jpg_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 
    402 static uint32_t
    403 jpg_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 
    414 static uint32_t
    415 jpg_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 
    443 static uint32_t
    444 jpg_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 
    516 static 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 
    537 static 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 
    565 static 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 
    612 static 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 
    634 static 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 
    664 static 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 
    721 static 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 
    825 static 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 
    841 static 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 
    856 static 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 
    874 static 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 
    982 static 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 
    994 static 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 
   1006 static 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 
   1017 static 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 
   1029 static 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 
   1063 static 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 
   1079 struct format_vtable_s tng_JPEG_vtable = {
   1080 queryConfigAttributes:
   1081     tng_JPEG_QueryConfigAttributes,
   1082 validateConfig:
   1083     tng_JPEG_ValidateConfig,
   1084 createContext:
   1085     tng_JPEG_CreateContext,
   1086 destroyContext:
   1087     tng_JPEG_DestroyContext,
   1088 beginPicture:
   1089     tng_JPEG_BeginPicture,
   1090 renderPicture:
   1091     vld_dec_RenderPicture,
   1092 endPicture:
   1093     tng_JPEG_EndPicture
   1094 };
   1095