/*
* Copyright (c) 2011 Intel Corporation. All Rights Reserved.
* Copyright (c) Imagination Technologies Limited, UK
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Guo Nana <nana.n.guo@intel.com>
* Zeng Li <li.zeng@intel.com>
*
*/
#include "va/va_dec_jpeg.h"
#include "tng_jpegdec.h"
#include "tng_vld_dec.h"
#include "psb_def.h"
#include "psb_drv_debug.h"
#include "hwdefs/reg_io2.h"
#include "hwdefs/msvdx_offsets.h"
#include "hwdefs/msvdx_cmds_io2.h"
#include "hwdefs/msvdx_vec_reg_io2.h"
#include "hwdefs/msvdx_vec_jpeg_reg_io2.h"
#include "hwdefs/dxva_fw_ctrl.h"
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#define GET_SURFACE_INFO_is_defined(psb_surface) ((int) (psb_surface->extra_info[0]))
#define SET_SURFACE_INFO_is_defined(psb_surface, val) psb_surface->extra_info[0] = (uint32_t) val;
#define GET_SURFACE_INFO_picture_structure(psb_surface) (psb_surface->extra_info[1])
#define SET_SURFACE_INFO_picture_structure(psb_surface, val) psb_surface->extra_info[1] = val;
#define GET_SURFACE_INFO_picture_coding_type(psb_surface) ((int) (psb_surface->extra_info[2]))
#define SET_SURFACE_INFO_picture_coding_type(psb_surface, val) psb_surface->extra_info[2] = (uint32_t) val;
#define JPEG_MAX_SETS_HUFFMAN_TABLES 2
#define JPEG_MAX_QUANT_TABLES 4
#define TABLE_CLASS_DC 0
#define TABLE_CLASS_AC 1
#define TABLE_CLASS_NUM 2
#define JPEG_PROFILE_BASELINE 0
/************************************/
/* VLC table defines and structures */
/* max number of bits allowed in a VLC code */
#define JPG_VLC_MAX_CODE_LEN (16)
/* max num bits to decode in any one decode direct operation */
#define JPG_VLC_MAX_DIRECT_WIDTH (6)
static const uint8_t inverse_zigzag[64] =
{
0x00, 0x01, 0x05, 0x06, 0x0e, 0x0f, 0x1b, 0x1c,
0x02, 0x04, 0x07, 0x0D, 0x10, 0x1a, 0x1d, 0x2a,
0x03, 0x08, 0x0C, 0x11, 0x19, 0x1e, 0x29, 0x2b,
0x09, 0x0B, 0x12, 0x18, 0x1f, 0x28, 0x2c, 0x35,
0x0A, 0x13, 0x17, 0x20, 0x27, 0x2d, 0x34, 0x36,
0x14, 0x16, 0x21, 0x26, 0x2e, 0x33, 0x37, 0x3c,
0x15, 0x22, 0x25, 0x2f, 0x32, 0x38, 0x3b, 0x3d,
0x23, 0x24, 0x30, 0x31, 0x39, 0x3a, 0x3e, 0x3f
};
/*
******************************************************************************
This structure defines the VLC code used for a partiular symbol
******************************************************************************/
typedef struct
{
uint16_t code; // VLC code with valid data in top-most bits
uint8_t code_length; // VLC code length
uint8_t symbol;
} vlc_symbol_code_jpeg; // VLCSymbolCodeJPEG
/*
******************************************************************************
This structure describes a set of VLC codes for a particular Huffman tree
******************************************************************************/
typedef struct
{
uint32_t num_codes;
uint32_t min_len;
uint32_t max_len;
} vlc_symbol_stats_jpeg; // VLCSymbolStatsJPEG
/*
******************************************************************************
This structure describes the generated VLC code table
******************************************************************************/
typedef struct
{
uint32_t size;
uint32_t initial_width;
uint32_t initial_opcode;
} vlc_table_stats_jpeg; // VLCTableStatsJPEG
/**************************************/
/* JPEG VLC Table defines and OpCodes */
#define JPG_MAKE_MASK(X) ((1<<(X))-1)
#define JPG_INSTR_OP_CODE_WIDTH (3)
#define JPG_INSTR_SHIFT_WIDTH (3)
#define JPG_INSTR_OFFSET_WIDTH (9)
#define JPG_INSTR_OP_CODE_MASK JPG_MAKE_MASK(JPG_JPG_INSTR_OP_CODE_WIDTH)
#define JPG_INSTR_SHIFT_MASK JPG_MAKE_MASK(JPG_INSTR_SHIFT_WIDTH)
#define JPG_INSTR_OFFSET_MASK JPG_MAKE_MASK(JPG_INSTR_OFFSET_WIDTH)
#define JPG_MAKE_OFFSET(code,width,leading) \
(((code<<leading) & JPG_MAKE_MASK(JPG_VLC_MAX_CODE_LEN)) >> (JPG_VLC_MAX_CODE_LEN-width))
typedef enum {
JPG_OP_DECODE_DIRECT = 0,
JPG_OP_DECODE_LEADING_1,
JPG_OP_DECODE_LEADING_0,
JPG_OP_CODE_INVALID,
JPG_OP_VALID_SYMBOL,
JPG_OP_VALID_RANGE_EVEN,
JPG_OP_VALID_RANGE_ODD,
JPG_OP_VALID_RANGE_EVEN_SET_FLAG,
} vlc_op_code_jpeg; // VLCOpCodeJPEG
/**************************************/
struct context_JPEG_s {
struct context_DEC_s dec_ctx;
object_context_p obj_context; /* back reference */
uint32_t profile;
/* Picture parameters */
VAPictureParameterBufferJPEGBaseline *pic_params;
uint32_t display_picture_width; /* in pixels */
uint32_t display_picture_height; /* in pixels */
uint32_t coded_picture_width; /* in pixels */
uint32_t coded_picture_height; /* in pixels */
uint32_t MCU_width;
uint32_t MCU_height;
uint32_t size_mb; /* in macroblocks */
uint32_t picture_width_mb; /* in macroblocks */
uint32_t picture_height_mb; /* in macroblocks */
uint8_t max_scalingH;
uint8_t max_scalingV;
/* VLC packed data */
struct psb_buffer_s vlc_packed_table;
uint32_t vlctable_buffer_size;
uint32_t rendec_qmatrix[JPEG_MAX_QUANT_TABLES][16];
/* Huffman table information as parsed from the bitstream */
vlc_symbol_code_jpeg* symbol_codes[TABLE_CLASS_NUM][JPEG_MAX_SETS_HUFFMAN_TABLES];
vlc_symbol_stats_jpeg symbol_stats[TABLE_CLASS_NUM][JPEG_MAX_SETS_HUFFMAN_TABLES];
/* Huffman table information compiled for the hardware */
uint32_t huffman_table_space;
uint16_t* huffman_table_RAM;
vlc_table_stats_jpeg table_stats[TABLE_CLASS_NUM][JPEG_MAX_SETS_HUFFMAN_TABLES];
};
typedef struct context_JPEG_s *context_JPEG_p;
#define INIT_CONTEXT_JPEG context_JPEG_p ctx = (context_JPEG_p) obj_context->format_data;
#define SURFACE(id) ((object_surface_p) object_heap_lookup( &ctx->obj_context->driver_data->surface_heap, id ))
static void tng_JPEG_QueryConfigAttributes(
VAProfile __maybe_unused profile,
VAEntrypoint __maybe_unused entrypoint,
VAConfigAttrib __maybe_unused * attrib_list,
int __maybe_unused num_attribs) {
/* No JPEG specific attributes */
}
static VAStatus tng_JPEG_ValidateConfig(object_config_p obj_config) {
int i;
/* Check all attributes */
for (i = 0; i < obj_config->attrib_count; i++) {
switch (obj_config->attrib_list[i].type) {
case VAConfigAttribRTFormat:
/* Ignore */
break;
default:
return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED;
}
}
return VA_STATUS_SUCCESS;
}
static VAStatus tng__JPEG_check_legal_picture(object_context_p obj_context, object_config_p obj_config) {
VAStatus vaStatus = VA_STATUS_SUCCESS;
if (NULL == obj_context) {
vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
DEBUG_FAILURE;
return vaStatus;
}
if (NULL == obj_config) {
vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
DEBUG_FAILURE;
return vaStatus;
}
switch (obj_config->profile) {
case VAProfileJPEGBaseline:
if ((obj_context->picture_width <= 0) || (obj_context->picture_height <= 0)) {
vaStatus = VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED;
}
break;
default:
vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
break;
}
return vaStatus;
}
static void tng_JPEG_DestroyContext(object_context_p obj_context);
static void tng__JPEG_process_slice_data(context_DEC_p dec_ctx, VASliceParameterBufferBase *vld_slice_param);
static void tng__JPEG_end_slice(context_DEC_p dec_ctx);
static void tng__JPEG_begin_slice(context_DEC_p dec_ctx, VASliceParameterBufferBase *vld_slice_param);
static VAStatus tng_JPEG_process_buffer(context_DEC_p dec_ctx, object_buffer_p buffer);
static VAStatus tng_JPEG_CreateContext(
object_context_p obj_context,
object_config_p obj_config) {
VAStatus vaStatus = VA_STATUS_SUCCESS;
context_JPEG_p ctx;
/* Validate flag */
/* Validate picture dimensions */
vaStatus = tng__JPEG_check_legal_picture(obj_context, obj_config);
if (VA_STATUS_SUCCESS != vaStatus) {
DEBUG_FAILURE;
return vaStatus;
}
ctx = (context_JPEG_p) calloc(1, sizeof(struct context_JPEG_s));
if (NULL == ctx) {
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
DEBUG_FAILURE;
return vaStatus;
}
obj_context->format_data = (void*) ctx;
ctx->obj_context = obj_context;
ctx->pic_params = NULL;
ctx->dec_ctx.begin_slice = tng__JPEG_begin_slice;
ctx->dec_ctx.process_slice = tng__JPEG_process_slice_data;
ctx->dec_ctx.end_slice = tng__JPEG_end_slice;
ctx->dec_ctx.process_buffer = tng_JPEG_process_buffer;
ctx->dec_ctx.preload_buffer = NULL;
switch (obj_config->profile) {
case VAProfileJPEGBaseline:
drv_debug_msg(VIDEO_DEBUG_GENERAL, "JPEG_PROFILE_BASELINE\n");
ctx->profile = JPEG_PROFILE_BASELINE;
break;
default:
ASSERT(0 == 1);
vaStatus = VA_STATUS_ERROR_UNKNOWN;
}
ctx->vlctable_buffer_size = 1984 * 2;
if (vaStatus == VA_STATUS_SUCCESS) {
vaStatus = psb_buffer_create(obj_context->driver_data,
ctx->vlctable_buffer_size,
psb_bt_cpu_vpu,
&ctx->vlc_packed_table);
DEBUG_FAILURE;
}
if (vaStatus == VA_STATUS_SUCCESS) {
vaStatus = vld_dec_CreateContext(&ctx->dec_ctx, obj_context);
DEBUG_FAILURE;
}
if (vaStatus != VA_STATUS_SUCCESS) {
tng_JPEG_DestroyContext(obj_context);
}
return vaStatus;
}
static void tng_JPEG_DestroyContext(
object_context_p obj_context) {
INIT_CONTEXT_JPEG
int i;
vld_dec_DestroyContext(&ctx->dec_ctx);
psb_buffer_destroy(&ctx->vlc_packed_table);
if (ctx->pic_params) {
free(ctx->pic_params);
ctx->pic_params = NULL;
}
if (ctx->symbol_codes[0][0]) {
free(ctx->symbol_codes[0][0]);
ctx->symbol_codes[0][0] = NULL;
}
if (ctx->symbol_codes[0][1]) {
free(ctx->symbol_codes[0][1]);
ctx->symbol_codes[0][1] = NULL;
}
if (ctx->symbol_codes[1][0]) {
free(ctx->symbol_codes[1][0]);
ctx->symbol_codes[1][0] = NULL;
}
if (ctx->symbol_codes[1][1]) {
free(ctx->symbol_codes[1][1]);
ctx->symbol_codes[1][1] = NULL;
}
free(obj_context->format_data);
obj_context->format_data = NULL;
}
static uint16_t jpg_vlc_valid_symbol(const vlc_symbol_code_jpeg * symbol_code, const uint32_t leading) {
uint16_t entry = 0;
IMG_ASSERT( (symbol_code->code_length - leading - 1) >= 0 );
/* VLC microcode entry for a valid symbol */
entry |= (JPG_OP_VALID_SYMBOL << (JPG_INSTR_SHIFT_WIDTH+JPG_INSTR_OFFSET_WIDTH));
entry |= ((symbol_code->code_length - leading - 1) << JPG_INSTR_OFFSET_WIDTH);
entry |= symbol_code->symbol;
return entry;
}
static uint32_t
jpg_vlc_write_direct_command(uint16_t * const vlc_ram, uint32_t result_offset) {
uint32_t width = 0x7fff & *vlc_ram;
uint16_t entry = 0;
/* check that the max width read from the VLC entry is valid */
IMG_ASSERT( 0x8000 & *vlc_ram );
/* limit to the maximum width for this algorithm */
width = (width > JPG_VLC_MAX_DIRECT_WIDTH)? JPG_VLC_MAX_DIRECT_WIDTH: width;
/* VLC microcode for decode direct command */
entry |= (JPG_OP_DECODE_DIRECT << (JPG_INSTR_SHIFT_WIDTH+JPG_INSTR_OFFSET_WIDTH));
entry |= ((width - 1) << JPG_INSTR_OFFSET_WIDTH);
entry |= result_offset;
/* write command */
*vlc_ram = entry;
return width;
}
static uint32_t
jpg_vlc_get_offset(const vlc_symbol_code_jpeg * symbol_code, uint32_t width, uint32_t leading) {
uint32_t offset;
/* lose bits already decoded */
offset = symbol_code->code << leading;
offset &= JPG_MAKE_MASK(JPG_VLC_MAX_CODE_LEN);
/* convert truncated code to offset */
offset >>= (JPG_VLC_MAX_CODE_LEN - width);
return offset;
}
static uint32_t
jpg_vlc_decode_direct_symbols(const vlc_symbol_code_jpeg * symbol_code, uint16_t * const table_ram, const uint32_t width,
const uint32_t leading) {
uint32_t offset, limit;
uint16_t entry;
/* this function is only for codes short enough to produce valid symbols */
IMG_ASSERT( symbol_code->code_length <= leading + width );
IMG_ASSERT( symbol_code->code_length > leading );
/* lose bits already decoded */
offset = symbol_code->code << leading;
offset &= JPG_MAKE_MASK(JPG_VLC_MAX_CODE_LEN);
/* convert truncated code to offset */
offset >>= (JPG_VLC_MAX_CODE_LEN - width);
/* expand offset to encorporate undefined code bits */
limit = offset + (1 << (width - (symbol_code->code_length - leading)));
/* for all code variants - insert symbol into the decode direct result table */
entry = jpg_vlc_valid_symbol( symbol_code, leading );
for (; offset < limit; offset++) {
table_ram[offset] = entry;
}
/* return the number of entries written */
return limit - offset - 1;
}
static uint32_t
jpg_vlc_decode_direct(
const vlc_symbol_code_jpeg * symbol_codes,
const uint32_t num_codes,
uint16_t * const table_ram,
const uint32_t direct_width,
const uint32_t leading_width,
const uint32_t leading_pattern) {
const uint32_t next_leading_width = leading_width + direct_width;
const uint32_t next_leading_mask = JPG_MAKE_MASK(next_leading_width) << (JPG_VLC_MAX_CODE_LEN-next_leading_width);
const uint32_t leading_mask = JPG_MAKE_MASK(leading_width) << (JPG_VLC_MAX_CODE_LEN-leading_width);
uint32_t num_vlc_ops = 1 << direct_width;
uint32_t next_section, next_width, next_leading_pattern;
uint32_t offset;
uint32_t i;
/* sanity - check this decode direct will not exceed the max code len */
IMG_ASSERT(next_leading_width <= JPG_VLC_MAX_CODE_LEN);
/* set all VLC ops for this decode direct to invalid */
for (i = 0; i < num_vlc_ops; i++) {
table_ram[i] = (JPG_OP_CODE_INVALID << (JPG_INSTR_SHIFT_WIDTH+JPG_INSTR_OFFSET_WIDTH));
}
/* iterate over code table and insert VLC ops until */
/* codes become too long for this iteration or we run out of codes */
for (i = 0; symbol_codes[i].code_length <= next_leading_width && i < num_codes; i++) {
/* only use codes that match the specified leading portion */
if ((((uint32_t)symbol_codes[i].code) & leading_mask) == leading_pattern) {
jpg_vlc_decode_direct_symbols(&symbol_codes[i], table_ram, direct_width, leading_width );
}
}
next_section = i;
/* assign the longest code length for each remaining entry */
for (i = next_section; i < num_codes; i++) {
/* only use codes that match the specified leading portion */
if ((((uint32_t)symbol_codes[i].code) & leading_mask) == leading_pattern) {
/* enable the unused VLC bit to indicate this is not a command */
offset = jpg_vlc_get_offset(&symbol_codes[i], direct_width, leading_width);
table_ram[offset] = 0x8000 | (symbol_codes[i].code_length - next_leading_width);
}
}
/* for the remaining (long) codes */
for (i = next_section; i < num_codes; i++) {
/* only use codes that match the specified leading portion */
if ((((uint32_t)symbol_codes[i].code) & leading_mask) == leading_pattern) {
/* if a command has not been written for this direct offset */
offset = jpg_vlc_get_offset(&symbol_codes[i], direct_width, leading_width);
if (table_ram[offset] & 0x8000) {
/* write command the decode direct command */
next_width = jpg_vlc_write_direct_command(
&table_ram[offset],
num_vlc_ops - offset );
next_leading_pattern = (uint32_t)symbol_codes[i].code & next_leading_mask;
/* decode direct recursive call */
num_vlc_ops += jpg_vlc_decode_direct(
&symbol_codes[i],
num_codes - i,
&table_ram[num_vlc_ops],
next_width,
next_leading_width,
next_leading_pattern);
}
}
}
return num_vlc_ops;
}
static void JPG_VLC_CompileTable(
const vlc_symbol_code_jpeg * symbol_codes,
const vlc_symbol_stats_jpeg * psSymbolStats,
const uint32_t __maybe_unused ram_size,
uint16_t * table_ram,
vlc_table_stats_jpeg * ptable_stats)
{
ptable_stats->initial_width = 5;
ptable_stats->initial_opcode = JPG_OP_DECODE_DIRECT;
ptable_stats->size = jpg_vlc_decode_direct(
symbol_codes,
psSymbolStats->num_codes,
table_ram,
JPG_VLC_MAX_DIRECT_WIDTH,
0,
0);
IMG_ASSERT( ptable_stats->size <= ram_size );
}
static void compile_huffman_tables(context_JPEG_p ctx) {
VAStatus vaStatus = VA_STATUS_SUCCESS;
ctx->huffman_table_space = 1984;
if (0 == psb_buffer_map(&ctx->vlc_packed_table, (unsigned char **)&ctx->huffman_table_RAM)) {
// Compile Tables
uint32_t table_class;
uint32_t table_id;
for (table_class = 0; table_class < TABLE_CLASS_NUM; table_class++) {
for (table_id = 0; table_id < JPEG_MAX_SETS_HUFFMAN_TABLES; table_id++) {
if (ctx->symbol_stats[table_class][table_id].num_codes) {
JPG_VLC_CompileTable(ctx->symbol_codes[table_class][table_id],
&ctx->symbol_stats[table_class][table_id], ctx->huffman_table_space, ctx->huffman_table_RAM,
&ctx->table_stats[table_class][table_id]);
ctx->huffman_table_space -= ctx->table_stats[table_class][table_id].size;
ctx->huffman_table_RAM += ctx->table_stats[table_class][table_id].size;
}
}
}
psb_buffer_unmap(&ctx->vlc_packed_table);
} else {
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
DEBUG_FAILURE;
}
}
static VAStatus tng__JPEG_process_picture_param(context_JPEG_p ctx, object_buffer_p obj_buffer) {
VAStatus vaStatus;
ASSERT(obj_buffer->type == VAPictureParameterBufferType);
ASSERT(obj_buffer->num_elements == 1);
ASSERT(obj_buffer->size == sizeof(VAPictureParameterBufferJPEGBaseline));
if ((obj_buffer->num_elements != 1) ||
(obj_buffer->size != sizeof(VAPictureParameterBufferJPEGBaseline))) {
return VA_STATUS_ERROR_UNKNOWN;
}
/* Transfer ownership of VAPictureParameterBufferJPEGBaseline data */
if (ctx->pic_params) {
free(ctx->pic_params);
}
ctx->pic_params = (VAPictureParameterBufferJPEGBaseline *) obj_buffer->buffer_data;
ctx->display_picture_width = ctx->pic_params->picture_width;
ctx->display_picture_height = ctx->pic_params->picture_height;
ctx->coded_picture_width = ( ctx->display_picture_width + 7 ) & ( ~7 );
ctx->coded_picture_height = ( ctx->display_picture_height + 7 ) & ( ~7 );
ctx->max_scalingH = 0;
ctx->max_scalingV = 0;
uint8_t component_id;
for (component_id = 0; component_id < ctx->pic_params->num_components; component_id++) {
if (ctx->max_scalingH < ctx->pic_params->components->h_sampling_factor)
ctx->max_scalingH = ctx->pic_params->components->h_sampling_factor;
if (ctx->max_scalingV < ctx->pic_params->components->v_sampling_factor)
ctx->max_scalingV = ctx->pic_params->components->v_sampling_factor;
}
ctx->MCU_width = (ctx->coded_picture_width + (8 * ctx->max_scalingH) - 1) / (8 * ctx->max_scalingH);
ctx->MCU_height = (ctx->coded_picture_height + (8 * ctx->max_scalingV) - 1) / (8 * ctx->max_scalingV);
ctx->picture_width_mb = (ctx->coded_picture_width + 15) / 16;
ctx->picture_height_mb = (ctx->coded_picture_height + 15) / 16;
ctx->size_mb = ctx->picture_width_mb * ctx->picture_height_mb;
obj_buffer->buffer_data = NULL;
obj_buffer->size = 0;
return VA_STATUS_SUCCESS;
}
static void tng__JPEG_write_qmatrices(context_JPEG_p ctx) {
psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
int i;
psb_cmdbuf_rendec_start(cmdbuf, REG_MSVDX_VEC_IQRAM_OFFSET);
for (i = 0; i < 16; i++) {
psb_cmdbuf_rendec_write(cmdbuf, ctx->rendec_qmatrix[0][i]);
}
for (i = 0; i < 16; i++) {
psb_cmdbuf_rendec_write(cmdbuf, ctx->rendec_qmatrix[1][i]);
}
for (i = 0; i < 16; i++) {
psb_cmdbuf_rendec_write(cmdbuf, ctx->rendec_qmatrix[2][i]);
}
for (i = 0; i < 16; i++) {
psb_cmdbuf_rendec_write(cmdbuf, ctx->rendec_qmatrix[3][i]);
}
psb_cmdbuf_rendec_end(cmdbuf);
}
static VAStatus tng__JPEG_process_iq_matrix(context_JPEG_p ctx, object_buffer_p obj_buffer) {
VAIQMatrixBufferJPEGBaseline *qmatrix_data = (VAIQMatrixBufferJPEGBaseline *) obj_buffer->buffer_data;
ASSERT(obj_buffer->type == VAIQMatrixBufferType);
ASSERT(obj_buffer->num_elements == 1);
ASSERT(obj_buffer->size == sizeof(VAIQMatrixBufferJPEGBaseline));
uint32_t dqt_ind;
for (dqt_ind = 0; dqt_ind < 4; dqt_ind++) {
// Reorder Quant table for hardware
uint32_t table_ind = 0;
uint32_t rendec_table_ind = 0;
if (qmatrix_data->load_quantiser_table[dqt_ind]) {
while(table_ind < 64) {
ctx->rendec_qmatrix[dqt_ind][rendec_table_ind] =
(qmatrix_data->quantiser_table[dqt_ind][inverse_zigzag[table_ind+3]] << 24) |
(qmatrix_data->quantiser_table[dqt_ind][inverse_zigzag[table_ind+2]] << 16) |
(qmatrix_data->quantiser_table[dqt_ind][inverse_zigzag[table_ind+1]] << 8) |
(qmatrix_data->quantiser_table[dqt_ind][inverse_zigzag[table_ind]]);
table_ind += 4;
rendec_table_ind++;
}
}
}
return VA_STATUS_SUCCESS;
}
static void tng__JPEG_write_huffman_tables(context_JPEG_p ctx) {
uint32_t reg_value;
psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
// VLC Table
// Write a LLDMA Cmd to transfer VLD Table data
psb_cmdbuf_dma_write_cmdbuf(cmdbuf, &ctx->vlc_packed_table, 0,
ctx->vlctable_buffer_size, 0,
DMA_TYPE_VLC_TABLE);
// Write Table addresses
psb_cmdbuf_reg_start_block(cmdbuf, 0);
reg_value = 0;
uint32_t table_address = 0;
REGIO_WRITE_FIELD_LITE( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0, VLC_TABLE_ADDR0, table_address );
table_address += ctx->table_stats[0][0].size;
REGIO_WRITE_FIELD_LITE( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0, VLC_TABLE_ADDR1, table_address );
psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET( MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0 ), reg_value);
reg_value = 0;
table_address += ctx->table_stats[0][1].size;
REGIO_WRITE_FIELD_LITE( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR2, VLC_TABLE_ADDR4, table_address );
table_address += ctx->table_stats[1][0].size;
REGIO_WRITE_FIELD_LITE( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR2, VLC_TABLE_ADDR5, table_address );
psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET( MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR2 ), reg_value);
psb_cmdbuf_reg_end_block(cmdbuf);
// Write Initial Widths
psb_cmdbuf_reg_start_block(cmdbuf, 0);
reg_value = 0;
REGIO_WRITE_FIELD_LITE( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_WIDTH0, VLC_TABLE_INITIAL_WIDTH0,
ctx->table_stats[0][0].initial_width );
REGIO_WRITE_FIELD_LITE( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_WIDTH0, VLC_TABLE_INITIAL_WIDTH1,
ctx->table_stats[0][1].initial_width );
REGIO_WRITE_FIELD_LITE( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_WIDTH0, VLC_TABLE_INITIAL_WIDTH4,
ctx->table_stats[1][0].initial_width );
REGIO_WRITE_FIELD_LITE( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_WIDTH0, VLC_TABLE_INITIAL_WIDTH5,
ctx->table_stats[1][1].initial_width );
psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET( MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_WIDTH0 ), reg_value);
psb_cmdbuf_reg_end_block(cmdbuf);
// Write Initial Opcodes
psb_cmdbuf_reg_start_block(cmdbuf, 0);
reg_value = 0;
REGIO_WRITE_FIELD_LITE( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_OPCODE0, VLC_TABLE_INITIAL_OPCODE0,
ctx->table_stats[0][0].initial_opcode );
REGIO_WRITE_FIELD_LITE( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_OPCODE0, VLC_TABLE_INITIAL_OPCODE1,
ctx->table_stats[0][1].initial_opcode );
REGIO_WRITE_FIELD_LITE( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_OPCODE0, VLC_TABLE_INITIAL_OPCODE4,
ctx->table_stats[1][0].initial_opcode );
REGIO_WRITE_FIELD_LITE( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_OPCODE0, VLC_TABLE_INITIAL_OPCODE5,
ctx->table_stats[1][1].initial_opcode );
psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET( MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_OPCODE0 ), reg_value);
psb_cmdbuf_reg_end_block(cmdbuf);
}
static VAStatus tng__JPEG_process_huffman_tables(context_JPEG_p ctx, object_buffer_p obj_buffer) {
VAHuffmanTableBufferJPEGBaseline *huff = (VAHuffmanTableBufferJPEGBaseline *) obj_buffer->buffer_data;
ASSERT(obj_buffer->type == VAHuffmanTableBufferType);
ASSERT(obj_buffer->num_elements == 1);
ASSERT(obj_buffer->size == sizeof(VAHuffmanTableBufferJPEGBaseline));
uint32_t table_id;
for (table_id = 0; table_id < JPEG_MAX_SETS_HUFFMAN_TABLES; table_id++) {
// Find out the number of entries in the table
uint32_t table_entries = 0;
uint32_t bit_ind;
for (bit_ind = 0; bit_ind < 16; bit_ind++) {
table_entries += huff->huffman_table[table_id].num_dc_codes[bit_ind];
}
ctx->symbol_codes[0][table_id] =(vlc_symbol_code_jpeg *)malloc(sizeof(vlc_symbol_code_jpeg) * table_entries);
// Parse huffman code sizes
uint32_t huff_ind = 0;
for (bit_ind = 0; bit_ind < 16; bit_ind++) {
uint32_t num_codes = huff->huffman_table[table_id].num_dc_codes[bit_ind];
while (num_codes) {
ctx->symbol_codes[0][table_id][huff_ind].code_length = bit_ind + 1;
num_codes--;
huff_ind++;
}
}
// Calculate huffman codes
uint16_t code = 0;
uint8_t code_size = ctx->symbol_codes[0][table_id][0].code_length;
huff_ind = 0;
while (huff_ind < table_entries) {
if (ctx->symbol_codes[0][table_id][huff_ind].code_length == code_size) {
ctx->symbol_codes[0][table_id][huff_ind].code = code << ( 16 - code_size );
huff_ind++;
code++;
} else {
code <<= 1;
code_size++;
}
}
// Create table of code values
uint32_t table_ind;
for (table_ind = 0; table_ind < table_entries; table_ind++) {
ctx->symbol_codes[0][table_id][table_ind].symbol = huff->huffman_table[table_id].dc_values[table_ind];
}
// Store the number of codes in the table
ctx->symbol_stats[0][table_id].num_codes = table_entries;
// for AC table
// Find out the number of entries in the table
table_entries = 0;
for (bit_ind = 0; bit_ind < 16; bit_ind++) {
table_entries += huff->huffman_table[table_id].num_ac_codes[bit_ind];
}
// Allocate memory for huffman table codes
ctx->symbol_codes[1][table_id] = (vlc_symbol_code_jpeg *)malloc(sizeof(vlc_symbol_code_jpeg) * table_entries);
// Parse huffman code sizes
huff_ind = 0;
for (bit_ind = 0; bit_ind < 16; bit_ind++) {
uint32_t num_codes = huff->huffman_table[table_id].num_ac_codes[bit_ind];
while (num_codes) {
ctx->symbol_codes[1][table_id][huff_ind].code_length = bit_ind + 1;
num_codes--;
huff_ind++;
}
}
// Calculate huffman codes
code = 0;
code_size = ctx->symbol_codes[1][table_id][0].code_length;
huff_ind = 0;
while (huff_ind < table_entries) {
if (ctx->symbol_codes[1][table_id][huff_ind].code_length == code_size) {
ctx->symbol_codes[1][table_id][huff_ind].code = code << ( 16 - code_size );
huff_ind++;
code++;
} else {
code <<= 1;
code_size++;
}
}
// Create table of code values
for (table_ind = 0; table_ind < table_entries; table_ind++) {
ctx->symbol_codes[1][table_id][table_ind].symbol = huff->huffman_table[table_id].ac_values[table_ind];;
}
// Store the number of codes in the table
ctx->symbol_stats[1][table_id].num_codes = table_entries;
}
compile_huffman_tables(ctx);
return VA_STATUS_SUCCESS;
}
static void tng__JPEG_set_operating_mode(context_JPEG_p ctx) {
psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
ctx->obj_context->operating_mode = 0;
REGIO_WRITE_FIELD_LITE(ctx->obj_context->operating_mode, MSVDX_CMDS, OPERATING_MODE, USE_EXT_ROW_STRIDE, 1 );
REGIO_WRITE_FIELD_LITE(ctx->obj_context->operating_mode, MSVDX_CMDS, OPERATING_MODE, ASYNC_MODE, 1 );
REGIO_WRITE_FIELD_LITE(ctx->obj_context->operating_mode, MSVDX_CMDS, OPERATING_MODE, CHROMA_FORMAT, 1);
psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET( MSVDX_CMDS, OPERATING_MODE ));
psb_cmdbuf_rendec_write(cmdbuf, ctx->obj_context->operating_mode);
psb_cmdbuf_rendec_end(cmdbuf);
}
static void tng__JPEG_set_reference_pictures(context_JPEG_p ctx)
{
psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
psb_surface_p target_surface = ctx->obj_context->current_render_target->psb_surface;
psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, REFERENCE_PICTURE_BASE_ADDRESSES));
uint32_t planr_size = target_surface->chroma_offset;
psb_cmdbuf_rendec_write_address(cmdbuf, &target_surface->buf, target_surface->buf.buffer_ofs);
psb_cmdbuf_rendec_write_address(cmdbuf, &target_surface->buf, target_surface->buf.buffer_ofs + planr_size);
psb_cmdbuf_rendec_write_address(cmdbuf, &target_surface->buf, target_surface->buf.buffer_ofs + planr_size * 2);
// psb_cmdbuf_rendec_write_address(cmdbuf, &target_surface->buf, target_surface->buf.buffer_ofs + planr_size * 3);
psb_cmdbuf_rendec_end(cmdbuf);
}
static void tng__JPEG_set_ent_dec(context_JPEG_p ctx) {
psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
uint32_t reg_value;
psb_cmdbuf_reg_start_block(cmdbuf, 0);
reg_value = 0;
REGIO_WRITE_FIELD_LITE( reg_value, MSVDX_VEC, CR_VEC_ENTDEC_FE_CONTROL, ENTDEC_FE_MODE, 0 );
psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET( MSVDX_VEC, CR_VEC_ENTDEC_FE_CONTROL ), reg_value);
psb_cmdbuf_reg_end_block(cmdbuf);
psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET( MSVDX_VEC, CR_VEC_ENTDEC_BE_CONTROL ));
reg_value = 0;
REGIO_WRITE_FIELD(reg_value, MSVDX_VEC, CR_VEC_ENTDEC_BE_CONTROL, ENTDEC_BE_MODE, 0);
psb_cmdbuf_rendec_write(cmdbuf, reg_value);
psb_cmdbuf_rendec_end(cmdbuf);
}
static void tng__JPEG_set_register(context_JPEG_p ctx, VASliceParameterBufferJPEGBaseline *slice_param) {
psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf;
uint32_t reg_value;
const uint32_t num_MCUs = ctx->MCU_width * ctx->MCU_height;
const uint32_t num_MCUs_dec = slice_param->restart_interval ? min(slice_param->restart_interval, num_MCUs) : num_MCUs;
psb_cmdbuf_reg_start_block(cmdbuf, 0);
// CR_VEC_JPEG_FE_COMPONENTS
reg_value = 0;
REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_COMPONENTS, MAX_V, ctx->max_scalingV);
REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_COMPONENTS, MAX_H, ctx->max_scalingH);
REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_COMPONENTS, FE_COMPONENTS,
slice_param->num_components);
psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_COMPONENTS ), reg_value);
// CR_VEC_JPEG_FE_HEIGHT
reg_value = 0;
REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_HEIGHT, FE_HEIGHT_MINUS1,
ctx->coded_picture_height - 1);
psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_HEIGHT ), reg_value);
// CR_VEC_JPEG_FE_RESTART_POS
reg_value = 0;
psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_RESTART_POS), reg_value);
// CR_VEC_JPEG_FE_WIDTH
reg_value = 0;
REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_WIDTH, FE_WIDTH_MINUS1,
ctx->coded_picture_width - 1 );
psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_WIDTH), reg_value);
// CR_VEC_JPEG_FE_ENTROPY_CODING
reg_value = 0;
REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_ENTROPY_CODING, NUM_MCUS_LESS1, num_MCUs_dec - 1);
REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_ENTROPY_CODING, TA3,
slice_param->components[3].ac_table_selector);
REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_ENTROPY_CODING, TD3,
slice_param->components[3].dc_table_selector);
REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_ENTROPY_CODING, TA2,
slice_param->components[2].ac_table_selector);
REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_ENTROPY_CODING, TD2,
slice_param->components[2].dc_table_selector);
REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_ENTROPY_CODING, TA1,
slice_param->components[1].ac_table_selector);
REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_ENTROPY_CODING, TD1,
slice_param->components[1].dc_table_selector );
REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_ENTROPY_CODING, TA0,
slice_param->components[0].ac_table_selector);
REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_ENTROPY_CODING, TD0,
slice_param->components[0].dc_table_selector);
psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET( MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_ENTROPY_CODING ), reg_value);
// CR_VEC_JPEG_FE_SCALING
reg_value = 0;
REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_SCALING, FE_V3,
ctx->pic_params->components[3].v_sampling_factor);
REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_SCALING, FE_H3,
ctx->pic_params->components[3].h_sampling_factor );
REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_SCALING, FE_V2,
ctx->pic_params->components[2].v_sampling_factor);
REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_SCALING, FE_H2,
ctx->pic_params->components[2].h_sampling_factor );
REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_SCALING, FE_V1,
ctx->pic_params->components[1].v_sampling_factor );
REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_SCALING, FE_H1,
ctx->pic_params->components[1].h_sampling_factor );
REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_SCALING, FE_V0,
ctx->pic_params->components[0].v_sampling_factor );
REGIO_WRITE_FIELD_LITE(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_SCALING, FE_H0,
ctx->pic_params->components[0].h_sampling_factor );
psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET( MSVDX_VEC_JPEG, CR_VEC_JPEG_FE_SCALING ), reg_value);
psb_cmdbuf_reg_end_block(cmdbuf);
psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET( MSVDX_VEC_JPEG, CR_VEC_JPEG_BE_HEIGHT ));
// CR_VEC_JPEG_BE_HEIGHT
reg_value = 0;
REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_BE_HEIGHT, BE_HEIGHT_MINUS1,
ctx->coded_picture_height - 1);
psb_cmdbuf_rendec_write(cmdbuf, reg_value);
// CR_VEC_JPEG_BE_WIDTH
reg_value = 0;
REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_BE_WIDTH, BE_WIDTH_MINUS1, ctx->coded_picture_width - 1);
psb_cmdbuf_rendec_write(cmdbuf, reg_value);
// CR_VEC_JPEG_BE_QUANTISATION
reg_value = 0;
REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_BE_QUANTISATION, TQ3,
ctx->pic_params->components[3].quantiser_table_selector);
REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_BE_QUANTISATION, TQ2,
ctx->pic_params->components[2].quantiser_table_selector);
REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_BE_QUANTISATION, TQ1,
ctx->pic_params->components[1].quantiser_table_selector);
REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_BE_QUANTISATION, TQ0,
ctx->pic_params->components[0].quantiser_table_selector );
psb_cmdbuf_rendec_write(cmdbuf, reg_value);
// CR_VEC_JPEG_BE_CONTROL
reg_value = 0;
REGIO_WRITE_FIELD( reg_value, MSVDX_VEC_JPEG, CR_VEC_JPEG_BE_CONTROL, RGB, 0 );
psb_cmdbuf_rendec_write(cmdbuf, reg_value);
psb_cmdbuf_rendec_end(cmdbuf);
}
static void tng__JPEG_begin_slice(context_DEC_p dec_ctx, VASliceParameterBufferBase __maybe_unused * vld_slice_param)
{
context_JPEG_p ctx = (context_JPEG_p)dec_ctx;
dec_ctx->bits_offset = 0;
dec_ctx->SR_flags = CMD_ENABLE_RBDU_EXTRACTION;
*dec_ctx->cmd_params |=ctx->MCU_width * ctx->MCU_height;
*dec_ctx->slice_first_pic_last &= 0xfefe;
tng__JPEG_write_huffman_tables(ctx);
tng__JPEG_write_qmatrices(ctx);
}
static void tng__JPEG_process_slice_data(context_DEC_p dec_ctx, VASliceParameterBufferBase *vld_slice_param)
{
VASliceParameterBufferJPEGBaseline *slice_param = (VASliceParameterBufferJPEGBaseline *) vld_slice_param;
context_JPEG_p ctx = (context_JPEG_p)dec_ctx;
tng__JPEG_set_operating_mode(ctx);
tng__JPEG_set_reference_pictures(ctx);
vld_dec_setup_alternative_frame(ctx->obj_context);
tng__JPEG_set_ent_dec(ctx);
tng__JPEG_set_register(ctx, slice_param);
}
static void tng__JPEG_end_slice(context_DEC_p dec_ctx)
{
context_JPEG_p ctx = (context_JPEG_p)dec_ctx;
ctx->obj_context->flags = FW_VA_RENDER_IS_FIRST_SLICE | FW_VA_RENDER_IS_LAST_SLICE | FW_INTERNAL_CONTEXT_SWITCH;
ctx->obj_context->first_mb = 0;
ctx->obj_context->last_mb = ((ctx->picture_height_mb - 1) << 8) | (ctx->picture_width_mb - 1);
*(dec_ctx->slice_first_pic_last) = (ctx->obj_context->first_mb << 16) | ((ctx->obj_context->last_mb) & 0xfefe);
}
static VAStatus tng_JPEG_BeginPicture(
object_context_p obj_context) {
INIT_CONTEXT_JPEG
if (ctx->pic_params) {
free(ctx->pic_params);
ctx->pic_params = NULL;
}
return VA_STATUS_SUCCESS;
}
static VAStatus tng_JPEG_process_buffer(
context_DEC_p dec_ctx,
object_buffer_p buffer) {
context_JPEG_p ctx = (context_JPEG_p)dec_ctx;
VAStatus vaStatus = VA_STATUS_SUCCESS;
object_buffer_p obj_buffer = buffer;
switch (obj_buffer->type) {
case VAPictureParameterBufferType:
drv_debug_msg(VIDEO_DEBUG_GENERAL, "tng_JPEG_RenderPicture got VAPictureParameterBuffer\n");
vaStatus = tng__JPEG_process_picture_param(ctx, obj_buffer);
DEBUG_FAILURE;
break;
case VAIQMatrixBufferType:
drv_debug_msg(VIDEO_DEBUG_GENERAL, "tng_JPEG_RenderPicture got VAIQMatrixBufferType\n");
vaStatus = tng__JPEG_process_iq_matrix(ctx, obj_buffer);
DEBUG_FAILURE;
break;
case VAHuffmanTableBufferType:
drv_debug_msg(VIDEO_DEBUG_GENERAL, "tng_JPEG_RenderPicture got VAIQMatrixBufferType\n");
vaStatus = tng__JPEG_process_huffman_tables(ctx, obj_buffer);
DEBUG_FAILURE;
break;
default:
vaStatus = VA_STATUS_ERROR_UNKNOWN;
DEBUG_FAILURE;
}
return vaStatus;
}
static VAStatus tng_JPEG_EndPicture(
object_context_p obj_context) {
INIT_CONTEXT_JPEG
if (psb_context_flush_cmdbuf(ctx->obj_context)) {
return VA_STATUS_ERROR_UNKNOWN;
}
if (ctx->pic_params) {
free(ctx->pic_params);
ctx->pic_params = NULL;
}
return VA_STATUS_SUCCESS;
}
struct format_vtable_s tng_JPEG_vtable = {
queryConfigAttributes:
tng_JPEG_QueryConfigAttributes,
validateConfig:
tng_JPEG_ValidateConfig,
createContext:
tng_JPEG_CreateContext,
destroyContext:
tng_JPEG_DestroyContext,
beginPicture:
tng_JPEG_BeginPicture,
renderPicture:
vld_dec_RenderPicture,
endPicture:
tng_JPEG_EndPicture
};