diff options
Diffstat (limited to 'src/pnw_VC1.c')
-rw-r--r-- | src/pnw_VC1.c | 3326 |
1 files changed, 3326 insertions, 0 deletions
diff --git a/src/pnw_VC1.c b/src/pnw_VC1.c new file mode 100644 index 0000000..f12f4d1 --- /dev/null +++ b/src/pnw_VC1.c @@ -0,0 +1,3326 @@ +/* + * Copyright (c) 2007 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. + */ + + +#include "pnw_VC1.h" +#include "psb_def.h" +#include "psb_surface.h" +#include "psb_cmdbuf.h" + +#include "vc1_header.h" +#include "vc1_defs.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_vc1_reg_io2.h" +#include "hwdefs/msvdx_rendec_vc1_reg_io2.h" +#include "hwdefs/dxva_fw_ctrl.h" + +#include <stdlib.h> +#include <stdint.h> +#include <string.h> + +static int VC1_Header_Parser_HW = 1; + +#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 GET_SURFACE_INFO_colocated_index(psb_surface) ((int) (psb_surface->extra_info[3])) +#define SET_SURFACE_INFO_colocated_index(psb_surface, val) psb_surface->extra_info[3] = (uint32_t) val; + +#define SLICEDATA_BUFFER_TYPE(type) ((type==VASliceDataBufferType)?"VASliceDataBufferType":"VAProtectedSliceDataBufferType") + +#define PIXELS_TO_MB(x) ((x + 15) / 16) + +#define PRELOAD_BUFFER_SIZE (4*1024) +#define AUXMSB_BUFFER_SIZE (1024*1024) + + +typedef struct +{ + IMG_UINT32 ui32ContextId; + IMG_UINT32 ui32SliceParams; + IMG_UINT32 ui32MacroblockNumber; +} VC1PRELOAD; + +#define FWPARSER_VC1PRELOAD_SIZE (0x60) + +/*! +****************************************************************************** + @LUTs VLC table selection Look-up Tables +******************************************************************************/ + +typedef enum +{ + VC1_VLC_Code_3x2_2x3_tiles = 0x0, + VC1_VLC_FourMV_Pattern_0, + VC1_VLC_FourMV_Pattern_1, + VC1_VLC_FourMV_Pattern_2, + VC1_VLC_FourMV_Pattern_3, + VC1_VLC_High_Mot_Chroma_DC_Diff_VLC, + VC1_VLC_High_Mot_Inter_VLC, + VC1_VLC_High_Mot_Intra_VLC, + VC1_VLC_High_Mot_Luminance_DC_Diff_VLC, + VC1_VLC_High_Rate_Inter_VLC, + VC1_VLC_High_Rate_Intra_VLC, + VC1_VLC_High_Rate_SUBBLKPAT, + VC1_VLC_High_Rate_TTBLK, + VC1_VLC_High_Rate_TTMB, + VC1_VLC_I_Picture_CBPCY_VLC, + VC1_VLC_Interlace_2_MVP_Pattern_0, + VC1_VLC_Interlace_2_MVP_Pattern_1, + VC1_VLC_Interlace_2_MVP_Pattern_2, + VC1_VLC_Interlace_2_MVP_Pattern_3, + VC1_VLC_Interlace_4MV_MB_0, + VC1_VLC_Interlace_4MV_MB_1, + VC1_VLC_Interlace_4MV_MB_2, + VC1_VLC_Interlace_4MV_MB_3, + VC1_VLC_Interlace_Non_4MV_MB_0, + VC1_VLC_Interlace_Non_4MV_MB_1, + VC1_VLC_Interlace_Non_4MV_MB_2, + VC1_VLC_Interlace_Non_4MV_MB_3, + VC1_VLC_Interlaced_CBPCY_0, + VC1_VLC_Interlaced_CBPCY_1, + VC1_VLC_Interlaced_CBPCY_2, + VC1_VLC_Interlaced_CBPCY_3, + VC1_VLC_Interlaced_CBPCY_4, + VC1_VLC_Interlaced_CBPCY_5, + VC1_VLC_Interlaced_CBPCY_6, + VC1_VLC_Interlaced_CBPCY_7, + VC1_VLC_Low_Mot_Chroma_DC_Diff_VLC, + VC1_VLC_Low_Mot_Inter_VLC, + VC1_VLC_Low_Mot_Intra_VLC, + VC1_VLC_Low_Mot_Luminance_DC_Diff_VLC, + VC1_VLC_Low_Rate_SUBBLKPAT, + VC1_VLC_Low_Rate_TTBLK, + VC1_VLC_Low_Rate_TTMB, + VC1_VLC_Medium_Rate_SUBBLKPAT, + VC1_VLC_Medium_Rate_TTBLK, + VC1_VLC_Medium_Rate_TTMB, + VC1_VLC_Mid_Rate_Inter_VLC, + VC1_VLC_Mid_Rate_Intra_VLC, + VC1_VLC_Mixed_MV_MB_0, + VC1_VLC_Mixed_MV_MB_1, + VC1_VLC_Mixed_MV_MB_2, + VC1_VLC_Mixed_MV_MB_3, + VC1_VLC_Mixed_MV_MB_4, + VC1_VLC_Mixed_MV_MB_5, + VC1_VLC_Mixed_MV_MB_6, + VC1_VLC_Mixed_MV_MB_7, + VC1_VLC_Mot_Vector_Diff_VLC_0, + VC1_VLC_Mot_Vector_Diff_VLC_1, + VC1_VLC_Mot_Vector_Diff_VLC_2, + VC1_VLC_Mot_Vector_Diff_VLC_3, + VC1_VLC_One_Field_Ref_Ilace_MV_0, + VC1_VLC_One_Field_Ref_Ilace_MV_1, + VC1_VLC_One_Field_Ref_Ilace_MV_2, + VC1_VLC_One_Field_Ref_Ilace_MV_3, + VC1_VLC_One_MV_MB_0, + VC1_VLC_One_MV_MB_1, + VC1_VLC_One_MV_MB_2, + VC1_VLC_One_MV_MB_3, + VC1_VLC_One_MV_MB_4, + VC1_VLC_One_MV_MB_5, + VC1_VLC_One_MV_MB_6, + VC1_VLC_One_MV_MB_7, + VC1_VLC_P_Picture_CBPCY_VLC_0, + VC1_VLC_P_Picture_CBPCY_VLC_1, + VC1_VLC_P_Picture_CBPCY_VLC_2, + VC1_VLC_P_Picture_CBPCY_VLC_3, + VC1_VLC_Two_Field_Ref_Ilace_MV_0, + VC1_VLC_Two_Field_Ref_Ilace_MV_1, + VC1_VLC_Two_Field_Ref_Ilace_MV_2, + VC1_VLC_Two_Field_Ref_Ilace_MV_3, + VC1_VLC_Two_Field_Ref_Ilace_MV_4, + VC1_VLC_Two_Field_Ref_Ilace_MV_5, + VC1_VLC_Two_Field_Ref_Ilace_MV_6, + VC1_VLC_Two_Field_Ref_Ilace_MV_7, + +} VC1_eVLCTables; + +static IMG_UINT8 MBMODETableFLDI[][2] = { + {VC1_VLC_One_MV_MB_0, VC1_VLC_Mixed_MV_MB_0}, + {VC1_VLC_One_MV_MB_1, VC1_VLC_Mixed_MV_MB_1}, + {VC1_VLC_One_MV_MB_2, VC1_VLC_Mixed_MV_MB_2}, + {VC1_VLC_One_MV_MB_3, VC1_VLC_Mixed_MV_MB_3}, + {VC1_VLC_One_MV_MB_4, VC1_VLC_Mixed_MV_MB_4}, + {VC1_VLC_One_MV_MB_5, VC1_VLC_Mixed_MV_MB_5}, + {VC1_VLC_One_MV_MB_6, VC1_VLC_Mixed_MV_MB_6}, + {VC1_VLC_One_MV_MB_7, VC1_VLC_Mixed_MV_MB_7}, +}; + +static IMG_UINT8 MBMODETableFRMI[][2] = { + {VC1_VLC_Interlace_4MV_MB_0, VC1_VLC_Interlace_Non_4MV_MB_0}, + {VC1_VLC_Interlace_4MV_MB_1, VC1_VLC_Interlace_Non_4MV_MB_1}, + {VC1_VLC_Interlace_4MV_MB_2, VC1_VLC_Interlace_Non_4MV_MB_2}, + {VC1_VLC_Interlace_4MV_MB_3, VC1_VLC_Interlace_Non_4MV_MB_3}, +}; + +static IMG_UINT8 CBPCYTableProg[] = { + VC1_VLC_P_Picture_CBPCY_VLC_0, + VC1_VLC_P_Picture_CBPCY_VLC_1, + VC1_VLC_P_Picture_CBPCY_VLC_2, + VC1_VLC_P_Picture_CBPCY_VLC_3, +}; + +static IMG_UINT8 CBPCYTableInterlaced[] = { + VC1_VLC_Interlaced_CBPCY_0, + VC1_VLC_Interlaced_CBPCY_1, + VC1_VLC_Interlaced_CBPCY_2, + VC1_VLC_Interlaced_CBPCY_3, + VC1_VLC_Interlaced_CBPCY_4, + VC1_VLC_Interlaced_CBPCY_5, + VC1_VLC_Interlaced_CBPCY_6, + VC1_VLC_Interlaced_CBPCY_7, +}; + +static IMG_UINT8 FourMVTable[] = { + VC1_VLC_FourMV_Pattern_0, + VC1_VLC_FourMV_Pattern_1, + VC1_VLC_FourMV_Pattern_2, + VC1_VLC_FourMV_Pattern_3, +}; + +static IMG_UINT8 Interlace2MVTable[] = { + VC1_VLC_Interlace_2_MVP_Pattern_0, + VC1_VLC_Interlace_2_MVP_Pattern_1, + VC1_VLC_Interlace_2_MVP_Pattern_2, + VC1_VLC_Interlace_2_MVP_Pattern_3, +}; + +static IMG_UINT8 ProgressiveMVTable[] = { + VC1_VLC_Mot_Vector_Diff_VLC_0, + VC1_VLC_Mot_Vector_Diff_VLC_1, + VC1_VLC_Mot_Vector_Diff_VLC_2, + VC1_VLC_Mot_Vector_Diff_VLC_3, +}; + +static IMG_UINT8 Interlaced1RefMVTable[] = { + VC1_VLC_One_Field_Ref_Ilace_MV_0, + VC1_VLC_One_Field_Ref_Ilace_MV_1, + VC1_VLC_One_Field_Ref_Ilace_MV_2, + VC1_VLC_One_Field_Ref_Ilace_MV_3, +}; + +static IMG_UINT8 MVTable2RefIlace[] = { + VC1_VLC_Two_Field_Ref_Ilace_MV_0, + VC1_VLC_Two_Field_Ref_Ilace_MV_1, + VC1_VLC_Two_Field_Ref_Ilace_MV_2, + VC1_VLC_Two_Field_Ref_Ilace_MV_3, + VC1_VLC_Two_Field_Ref_Ilace_MV_4, + VC1_VLC_Two_Field_Ref_Ilace_MV_5, + VC1_VLC_Two_Field_Ref_Ilace_MV_6, + VC1_VLC_Two_Field_Ref_Ilace_MV_7, +}; + +static IMG_UINT8 IntraTablePQIndexLT9[] = { + VC1_VLC_High_Rate_Intra_VLC, + VC1_VLC_High_Mot_Intra_VLC, + VC1_VLC_Mid_Rate_Intra_VLC, +}; + +static IMG_UINT8 InterTablePQIndexLT9[] = { + VC1_VLC_High_Rate_Inter_VLC, + VC1_VLC_High_Mot_Inter_VLC, + VC1_VLC_Mid_Rate_Inter_VLC, +}; + +static IMG_UINT8 IntraTablePQIndexGT8[] = { + VC1_VLC_Low_Mot_Intra_VLC, + VC1_VLC_High_Mot_Intra_VLC, + VC1_VLC_Mid_Rate_Intra_VLC, +}; + +static IMG_UINT8 InterTablePQIndexGT8[] = { + VC1_VLC_Low_Mot_Inter_VLC, + VC1_VLC_High_Mot_Inter_VLC, + VC1_VLC_Mid_Rate_Inter_VLC, +}; + +/* TODO: Make tables const, don't polute namespace */ +extern IMG_UINT16 gaui16vc1VlcTableData[]; +extern const IMG_UINT16 gui16vc1VlcTableSize; +extern IMG_UINT16 gaui16vc1VlcIndexData[VLC_INDEX_TABLE_SIZE][3]; +extern const IMG_UINT8 gui8vc1VlcIndexSize; + + +static IMG_UINT16 gaui16Inverse[] = {256, 128, 85, 64, 51, 43, 37, 32}; /* figure 66 */ +static IMG_BOOL gDMVRANGE_ExtHorizontal_RemapTable[]= {0, 1, 0, 1}; +static IMG_BOOL gDMVRANGE_ExtVertical_RemapTable[]= {0, 0, 1, 1}; +static IMG_BYTE gBFRACTION_DenRemapTable[] = {2,3,3,4,4,5,5,5,5,6,6,7,7,7,7,7,7,8,8,8,8,255,255}; +static IMG_BYTE gBFRACTION_NumRemapTable[] = {1,1,2,1,3,1,2,3,4,1,5,1,2,3,4,5,6,1,3,5,7,255,255}; + + +#define INIT_CONTEXT_VC1 context_VC1_p ctx = (context_VC1_p) obj_context->format_data; + +#define SURFACE(id) ((object_surface_p) object_heap_lookup( &ctx->obj_context->driver_data->surface_heap, id )) + + +static void pnw_VC1_QueryConfigAttributes( + VAProfile profile, + VAEntrypoint entrypoint, + VAConfigAttrib *attrib_list, + int num_attribs ) +{ + /* No VC1 specific attributes */ +} + +static VAStatus pnw_VC1_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 void psb__VC1_pack_vlc_tables(uint16_t *vlc_packed_data, + uint16_t *gaui16vc1VlcTableData, + int gui16vc1VlcTableSize) +{ + int i, j; + /************************************************************************************/ + /* Pack the VLC tables into 32-bit format ready for DMA into 15-bit wide RAM. */ + /************************************************************************************/ + for (i = 0; i < gui16vc1VlcTableSize; i++) + { + j = i * 3; + vlc_packed_data[i] = 0; + /* opcode 14:12 *//* width 11:9 *//* symbol 8:0 */ + vlc_packed_data[i] = ((gaui16vc1VlcTableData[j + 0]) << 12) | + ((gaui16vc1VlcTableData[j + 1]) << 9) | + (gaui16vc1VlcTableData[j + 2]); + } +} + +static void psb__VC1_pack_index_table_info( uint32_t *packed_index_table, + uint16_t index_data[VLC_INDEX_TABLE_SIZE][3]) +{ + uint32_t start = 0, end = 0, length = 0, opcode = 0, width = 0; + int i; + + for (i=0; i<VLC_INDEX_TABLE_SIZE; i++) + { + start = index_data[i][2]; + if( i < (VLC_INDEX_TABLE_SIZE-1)) //Make sure we don't exceed the bound + { + end = index_data[i+1][2]; + } + else + { + end = start + 500; + } + length = end - start; + width = index_data[i][1]; + opcode = index_data[i][0]; + +psb__information_message("packed_index_table[%02d]->start = %08x length = %08x (%d)\n", i, start*2, length*2, length*2); + + packed_index_table[i] = opcode; + packed_index_table[i] <<= 3; + packed_index_table[i] |= width; + packed_index_table[i] <<= 9; + packed_index_table[i] |= length; + packed_index_table[i] <<= 16; + packed_index_table[i] |= start; + } +} + +static VAStatus psb__VC1_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; + } + + /* MSVDX decode capability for VC-1: + * SP@ML + * MP@HL + * AP@L3 + * + * Refer to Table 253 (Limitations of profiles and levels) of SMPTE-421M + */ + switch (obj_config->profile) + { + case VAProfileVC1Simple: + if ((obj_context->picture_width <= 0) || (obj_context->picture_width > 352) + || (obj_context->picture_height <= 0) || (obj_context->picture_height > 288)) + { + vaStatus = VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED; + } + break; + + case VAProfileVC1Main: + if ((obj_context->picture_width <= 0) || (obj_context->picture_width > 1920) + || (obj_context->picture_height <= 0) || (obj_context->picture_height > 1088)) + { + vaStatus = VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED; + } + break; + + case VAProfileVC1Advanced: + if ((obj_context->picture_width <= 0) || (obj_context->picture_width > 2048) + || (obj_context->picture_height <= 0) || (obj_context->picture_height > 2048)) + { + vaStatus = VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED; + } + break; + + default: + vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE; + break; + } + + return vaStatus; +} + +static void pnw_VC1_DestroyContext(object_context_p obj_context); + +static VAStatus pnw_VC1_CreateContext( + object_context_p obj_context, + object_config_p obj_config ) +{ + VAStatus vaStatus = VA_STATUS_SUCCESS; + context_VC1_p ctx; + /* Validate flag */ + /* Validate picture dimensions */ + vaStatus = psb__VC1_check_legal_picture(obj_context, obj_config); + if (VA_STATUS_SUCCESS != vaStatus) + { + DEBUG_FAILURE; + return vaStatus; + } + + ctx = (context_VC1_p) malloc(sizeof(struct context_VC1_s)); + if (NULL == ctx) + { + vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; + DEBUG_FAILURE; + return vaStatus; + } + memset(ctx, 0, sizeof(struct context_VC1_s)); + obj_context->format_data = (void*) ctx; + ctx->obj_context = obj_context; + ctx->pic_params = NULL; + + ctx->split_buffer_pending = FALSE; + + ctx->slice_param_list_size = 8; + ctx->slice_param_list = (object_buffer_p*) malloc(sizeof(object_buffer_p)*ctx->slice_param_list_size); + ctx->slice_param_list_idx = 0; + + if (NULL == ctx->slice_param_list) + { + vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; + DEBUG_FAILURE; + } + + ctx->colocated_buffers_size = obj_context->num_render_targets; + ctx->colocated_buffers_idx = 0; + ctx->colocated_buffers = (psb_buffer_p) malloc(sizeof(struct psb_buffer_s)*ctx->colocated_buffers_size); + if (NULL == ctx->colocated_buffers) + { + vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; + DEBUG_FAILURE; + } + + switch (obj_config->profile ) + { + case VAProfileVC1Simple: + ctx->profile = WMF_PROFILE_SIMPLE; + break; + + case VAProfileVC1Main: + ctx->profile = WMF_PROFILE_MAIN; + break; + + case VAProfileVC1Advanced: + ctx->profile = WMF_PROFILE_ADVANCED; + break; + + default: + ASSERT(0 == 1); + vaStatus = VA_STATUS_ERROR_UNKNOWN; + } + + // TODO + + if (vaStatus == VA_STATUS_SUCCESS) + { + vaStatus = psb_buffer_create( obj_context->driver_data, + PRELOAD_BUFFER_SIZE, + psb_bt_vpu_only, + &ctx->preload_buffer ); + DEBUG_FAILURE; + } + + if (vaStatus == VA_STATUS_SUCCESS) + { + void *preload; + if (0 == psb_buffer_map( &ctx->preload_buffer, &preload )) + { + memset(preload, 0, PRELOAD_BUFFER_SIZE); + psb_buffer_unmap( &ctx->preload_buffer ); + } + else + { + vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; + DEBUG_FAILURE; + } + } + + if (vaStatus == VA_STATUS_SUCCESS) + { + vaStatus = psb_buffer_create( obj_context->driver_data, + AUXMSB_BUFFER_SIZE, + psb_bt_vpu_only, + &ctx->aux_msb_buffer ); + DEBUG_FAILURE; + } + + if (vaStatus == VA_STATUS_SUCCESS) + { + if(VC1_Header_Parser_HW) + { + vaStatus = psb_buffer_create( obj_context->driver_data, + 0xa000*3, //0x8800 + psb_bt_vpu_only, + &ctx->bitplane_hw_buffer ); + DEBUG_FAILURE; + } + else + { + vaStatus = psb_buffer_create( obj_context->driver_data, + 0x8000, + psb_bt_vpu_only, + &ctx->bitplane_hw_buffer ); + DEBUG_FAILURE; + } + + } + + if (vaStatus == VA_STATUS_SUCCESS) + { + vaStatus = psb_buffer_create( obj_context->driver_data, + (gui16vc1VlcTableSize * sizeof(IMG_UINT16) + 0xfff) & ~0xfff, + psb_bt_cpu_vpu, + &ctx->vlc_packed_table ); + DEBUG_FAILURE; + } + if (vaStatus == VA_STATUS_SUCCESS) + { + void *vlc_packed_data_address; + if (0 == psb_buffer_map( &ctx->vlc_packed_table, &vlc_packed_data_address )) + { + psb__VC1_pack_vlc_tables(vlc_packed_data_address, gaui16vc1VlcTableData, gui16vc1VlcTableSize); + psb_buffer_unmap( &ctx->vlc_packed_table ); + psb__VC1_pack_index_table_info( ctx->vlc_packed_index_table, gaui16vc1VlcIndexData); + } + else + { + vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; + DEBUG_FAILURE; + } + } + + if (vaStatus != VA_STATUS_SUCCESS) + { + pnw_VC1_DestroyContext(obj_context); + } + + return vaStatus; +} + +static void pnw_VC1_DestroyContext( + object_context_p obj_context) +{ + INIT_CONTEXT_VC1 + int i; + + psb_buffer_destroy( &ctx->vlc_packed_table ); + psb_buffer_destroy( &ctx->aux_msb_buffer ); + psb_buffer_destroy( &ctx->preload_buffer ); + psb_buffer_destroy( &ctx->bitplane_hw_buffer ); + + if (ctx->pic_params) + { + free(ctx->pic_params); + ctx->pic_params = NULL; + } + + if (ctx->slice_param_list) + { + free(ctx->slice_param_list); + ctx->slice_param_list = NULL; + } + + if (ctx->colocated_buffers) + { + for (i = 0; i < ctx->colocated_buffers_idx; ++i) + psb_buffer_destroy(&(ctx->colocated_buffers[i])); + + free(ctx->colocated_buffers); + ctx->colocated_buffers = NULL; + } + + free(obj_context->format_data); + obj_context->format_data = NULL; +} + +static VAStatus psb__VC1_allocate_colocated_buffer(context_VC1_p ctx, object_surface_p obj_surface, uint32_t size){ + psb_surface_p surface = obj_surface->psb_surface; + + psb__information_message("pnw_VC1: Allocationg colocated buffer for surface %08x\n", surface); + + if (!GET_SURFACE_INFO_colocated_index(surface)) + { + VAStatus vaStatus; + psb_buffer_p buf; + int index = ctx->colocated_buffers_idx; + if (index >= ctx->colocated_buffers_size) + { + return VA_STATUS_ERROR_UNKNOWN; + } + buf = &(ctx->colocated_buffers[index]); + vaStatus = psb_buffer_create( ctx->obj_context->driver_data, size, psb_bt_vpu_only, buf); + if (VA_STATUS_SUCCESS != vaStatus) + { + return vaStatus; + } + ctx->colocated_buffers_idx++; + SET_SURFACE_INFO_colocated_index(surface, index+1); /* 0 means unset, index is offset by 1 */ + } + return VA_STATUS_SUCCESS; +} + +static psb_buffer_p psb__VC1_lookup_colocated_buffer(context_VC1_p ctx, psb_surface_p surface) +{ + psb__information_message("pnw_VC1: Looking up colocated buffer for surface %08x\n", surface); + int index = GET_SURFACE_INFO_colocated_index(surface); + if (!index) + { + return NULL; + } + return &(ctx->colocated_buffers[index-1]); /* 0 means unset, index is offset by 1 */ +} + +static uint32_t psb__vc1_get_izz_scan_index(context_VC1_p ctx) +{ + if(ctx->pic_params->picture_fields.bits.frame_coding_mode == VC1_FCM_FRMI) + { + // P_PICTURE_ADV_FRAME_INTERLACE + return 3; + } + if(PIC_TYPE_IS_INTRA(ctx->pic_params->picture_fields.bits.picture_type)) + { + // I-picture tables + return 4; + } + else + { + /* Assume P frame */ + if((ctx->profile == WMF_PROFILE_SIMPLE) || + (ctx->profile == WMF_PROFILE_MAIN) ) + { + // P-picture Simple/Main tables + return 0; + } + else /* Advanced profile */ + { + if(ctx->pic_params->picture_fields.bits.frame_coding_mode == VC1_FCM_P) + { + // P-picture Advanced Progressive tables + return 1; + } + else /* Interlaced Field */ + { + // P-picture Advanced Field Interlaced tables + return 2; + } + } + } +} + + +#ifdef DEBUG_TRACE +#define psb__trace_message(...) + +#define P(x) psb__trace_message("PARAMS: " #x "\t= %d\n", p->x) +static void psb__VC1_trace_pic_params(VAPictureParameterBufferVC1 *p) +{ +#define P0(x) psb__trace_message("PARAMS: " #x "\t= %d\n", p->sequence_fields.bits.x) + P0(interlace); + P0(syncmarker); + P0(overlap); + + P(coded_width); + P(coded_height); + +#define P2(x) psb__trace_message("PARAMS: " #x "\t= %d\n", p->picture_fields.bits.x) + /* picture_fields */ + P2(picture_type); + P2(frame_coding_mode); + P2(top_field_first); + P2(is_first_field); + P2(intensity_compensation); + +#define P4(x) psb__trace_message("PARAMS: " #x "\t= %d\n", p->entrypoint_fields.bits.x) + P4(closed_entry); + P4(broken_link); + P4(loopfilter); + + P(conditional_overlap_flag); + P(fast_uvmc_flag); + +#define P3(x) psb__trace_message("PARAMS: " #x "\t= %d\n", p->range_mapping_fields.bits.x) + /* range_mapping_fields */ + P3(luma_flag); + P3(luma); + P3(chroma_flag); + P3(chroma); + + P(b_picture_fraction); + P(cbp_table); + P(mb_mode_table); + P(range_reduction_frame); + P(rounding_control); + P(post_processing); + P(picture_resolution_index); + P(luma_scale); + P(luma_shift); + + P(raw_coding.value); + P(bitplane_present.value); + +#define P4(x) psb__trace_message("PARAMS: " #x "\t= %d\n", p->reference_fields.bits.x) + P4(reference_distance_flag); + P4(reference_distance); + P4(num_reference_pictures); + P4(reference_field_pic_indicator); + +#define P5(x) psb__trace_message("PARAMS: " #x "\t= %d\n", p->mv_fields.bits.x) + P5(mv_mode); + P5(mv_mode2); + + P5(mv_table); + P5(two_mv_block_pattern_table); + P5(four_mv_switch); + P5(four_mv_block_pattern_table); + P5(extended_mv_flag); + P5(extended_mv_range); + P5(extended_dmv_flag); + P5(extended_dmv_range); + +#define P6(x) psb__trace_message("PARAMS: " #x "\t= %d\n", p->pic_quantizer_fields.bits.x) + + P6(dquant); + P6(quantizer); + P6(half_qp); + P6(pic_quantizer_scale); + P6(pic_quantizer_type); + P6(dq_frame); + P6(dq_profile); + P6(dq_sb_edge); + P6(dq_db_edge); + P6(dq_binary_level); + P6(alt_pic_quantizer); + +#define P7(x) psb__trace_message("PARAMS: " #x "\t= %d\n", p->transform_fields.bits.x) + + P7(variable_sized_transform_flag); + P7(mb_level_transform_type_flag); + P7(frame_level_transform_type); + P7(transform_ac_codingset_idx1); + P7(transform_ac_codingset_idx2); + P7(intra_transform_dc_table); +} +#endif + +static VAStatus psb__VC1_process_picture_param(context_VC1_p ctx, object_buffer_p obj_buffer) +{ + VAStatus vaStatus; + VAPictureParameterBufferVC1 *pic_params; + IMG_UINT8 ui8LumaScale1 = 0, ui8LumaShift1 = 0, ui8LumaScale2 = 0, ui8LumaShift2 = 0; + + ASSERT(obj_buffer->type == VAPictureParameterBufferType); + ASSERT(obj_buffer->num_elements == 1); + ASSERT(obj_buffer->size == sizeof(VAPictureParameterBufferVC1)); + + if ((obj_buffer->num_elements != 1) || + (obj_buffer->size != sizeof(VAPictureParameterBufferVC1))) + { + vaStatus = VA_STATUS_ERROR_UNKNOWN; + DEBUG_FAILURE; + return vaStatus; + } + + /* Transfer ownership of VAPictureParameterBufferVC1 data */ + pic_params = (VAPictureParameterBufferVC1 *) obj_buffer->buffer_data; + if (ctx->pic_params) + { + free(ctx->pic_params); + } + ctx->pic_params = pic_params; + obj_buffer->buffer_data = NULL; + obj_buffer->size = 0; + +#ifdef DEBUG_TRACE + psb__VC1_trace_pic_params(pic_params); +#endif + + if (pic_params->pic_quantizer_fields.bits.quantizer == 0) + { + /* Non uniform quantizer indicates PQINDEX > 8 */ + ctx->pqindex_gt8 = (pic_params->pic_quantizer_fields.bits.pic_quantizer_type == 0); + } + else + { + /* PQUANT (pic_quantizer_scale) == PQINDEX */ + ctx->pqindex_gt8 = (pic_params->pic_quantizer_fields.bits.pic_quantizer_scale > 8); + } + + /* + * We decode to ctx->decoded_surface This is inloop target + * the out of loop decoded picture is stored in ctx->obj_context->current_render_target + */ + if (pic_params->inloop_decoded_picture == VA_INVALID_SURFACE) + { + /* No out of loop deblocking */ + ctx->decoded_surface = ctx->obj_context->current_render_target; + } + else + { + ctx->decoded_surface = SURFACE(pic_params->inloop_decoded_picture); + if (NULL == ctx->decoded_surface) + { + vaStatus = VA_STATUS_ERROR_INVALID_SURFACE; + DEBUG_FAILURE; + return vaStatus; + } + } + /* Lookup surfaces for backward/forward references */ + ctx->forward_ref_surface = NULL; + ctx->backward_ref_surface = NULL; + if (pic_params->forward_reference_picture != VA_INVALID_SURFACE) + { + ctx->forward_ref_surface = SURFACE(pic_params->forward_reference_picture); + } + if (pic_params->backward_reference_picture != VA_INVALID_SURFACE) + { + ctx->backward_ref_surface = SURFACE(pic_params->backward_reference_picture); + } + +#if 0 + if (NULL == ctx->forward_ref_surface) + { + /* for mmu fault protection */ + ctx->forward_ref_surface = ctx->decoded_surface; + } + if (NULL == ctx->backward_ref_surface) + { + /* for mmu fault protection */ + ctx->backward_ref_surface = ctx->decoded_surface; + } +#endif + + psb__information_message("Target ref = %08x ID = %08x\n", ctx->obj_context->current_render_target->psb_surface, ctx->obj_context->current_render_target->surface_id); + psb__information_message("Decoded ref = %08x ID = %08x\n", ctx->decoded_surface->psb_surface, pic_params->inloop_decoded_picture); + psb__information_message("Forward ref = %08x ID = %08x\n", ctx->forward_ref_surface ? ctx->forward_ref_surface->psb_surface : 0, pic_params->forward_reference_picture); + psb__information_message("Backwrd ref = %08x ID = %08x\n", ctx->backward_ref_surface ? ctx->backward_ref_surface->psb_surface : 0, pic_params->backward_reference_picture); + + // NOTE: coded_width and coded_height do not have to be an exact multiple of MBs + + ctx->display_picture_width = pic_params->coded_width; + ctx->display_picture_height = pic_params->coded_height; + ctx->picture_width_mb = PIXELS_TO_MB(ctx->display_picture_width); + ctx->picture_height_mb = PIXELS_TO_MB(ctx->display_picture_height); + ctx->coded_picture_width = ctx->picture_width_mb * 16; + ctx->coded_picture_height = ctx->picture_height_mb * 16; + if ((WMF_PROFILE_ADVANCED == ctx->profile) && (VC1_FCM_FLDI == pic_params->picture_fields.bits.frame_coding_mode)) + { + ctx->picture_height_mb /= 2; + ctx->coded_picture_height = ctx->picture_height_mb * 16 * 2; + } + + ctx->size_mb = ctx->picture_width_mb * ctx->picture_height_mb; + + uint32_t colocated_size = ((ctx->size_mb + 1) * 2 + 128) * VC1_MB_PARAM_STRIDE; + //uint32_t colocated_size = (ctx->size_mb + 1) * 2 * VC1_MB_PARAM_STRIDE + 0x2000; + + vaStatus = psb__VC1_allocate_colocated_buffer(ctx, ctx->decoded_surface, colocated_size); + vaStatus = psb__VC1_allocate_colocated_buffer(ctx, ctx->obj_context->current_render_target, colocated_size); + + if (VA_STATUS_SUCCESS != vaStatus) + { + DEBUG_FAILURE; + return vaStatus; + } + + /* TODO: Store top_field_first and frame_coding_mode (or even all of pic_params) for the current frame + * so that it can be referenced when the same frame is used as reference frame + */ + + if (ctx->profile != WMF_PROFILE_ADVANCED) + { + /* Simple and Main profiles always use progressive pictures*/ + pic_params->picture_fields.bits.frame_coding_mode = VC1_FCM_P; + } + + if ((pic_params->picture_fields.bits.frame_coding_mode == VC1_FCM_P) || (pic_params->picture_fields.bits.frame_coding_mode == VC1_FCM_FRMI)) + { + pic_params->picture_fields.bits.top_field_first = 1; + } + + ctx->bitplane_present = 0; + switch(pic_params->picture_fields.bits.picture_type) + { + case WMF_PTYPE_I: + case WMF_PTYPE_BI: + ctx->bitplane_present |= (pic_params->bitplane_present.flags.bp_overflags && !pic_params->raw_coding.flags.overflags) ? 0x04 : 0; + ctx->bitplane_present |= (pic_params->bitplane_present.flags.bp_ac_pred && !pic_params->raw_coding.flags.ac_pred) ? 0x02 : 0; + ctx->bitplane_present |= (pic_params->bitplane_present.flags.bp_field_tx && !pic_params->raw_coding.flags.field_tx) ? 0x01 : 0; + break; + + case WMF_PTYPE_P: + ctx->bitplane_present |= (pic_params->bitplane_present.flags.bp_mv_type_mb && !pic_params->raw_coding.flags.mv_type_mb) ? 0x04 : 0; + ctx->bitplane_present |= (pic_params->bitplane_present.flags.bp_skip_mb && !pic_params->raw_coding.flags.skip_mb) ? 0x02 : 0; + break; + + case WMF_PTYPE_B: /* B picture */ + ctx->bitplane_present |= (pic_params->bitplane_present.flags.bp_forward_mb && !pic_params->raw_coding.flags.forward_mb) ? 0x04 : 0; + ctx->bitplane_present |= (pic_params->bitplane_present.flags.bp_skip_mb && !pic_params->raw_coding.flags.skip_mb) ? 0x02 : 0; + ctx->bitplane_present |= (pic_params->bitplane_present.flags.bp_direct_mb && !pic_params->raw_coding.flags.direct_mb) ? 0x01 : 0; + break; + + default: + break; + } + psb__information_message("bitplane_present_flag = %02x raw_coding_flag = %02x bitplane_present = %02x\n", + pic_params->bitplane_present.value, pic_params->raw_coding.value, ctx->bitplane_present); + + if (pic_params->reference_fields.bits.reference_distance_flag == 0) + { + pic_params->reference_fields.bits.reference_distance = 0; + } + + /* conditional_overlap_flag is not always defined, but MSVDX expects it to be set in those cases anyway */ + if (ctx->profile == WMF_PROFILE_ADVANCED) + { + if (pic_params->sequence_fields.bits.overlap == FALSE) + { + ctx->condover = 0; /* No overlap smoothing */ + } + else if (pic_params->pic_quantizer_fields.bits.pic_quantizer_scale < 9) + { + ctx->condover = pic_params->conditional_overlap_flag; + } + else + { + ctx->condover = 2; + } + } + else + { + if ((pic_params->picture_fields.bits.picture_type == WMF_PTYPE_B) || (pic_params->sequence_fields.bits.overlap == FALSE) || (pic_params->pic_quantizer_fields.bits.pic_quantizer_scale < 9)) + { + ctx->condover = 0; /* No overlap smoothing */ + } + else + { + ctx->condover = 2; + } + } + + /************************** Calculate the IZZ scan index ****************************/ + ctx->scan_index = psb__vc1_get_izz_scan_index(ctx); + /************************************************************************************/ + + /**************************** Calculate MVMODE and MVMODE2 **************************/ + ctx->mv_mode = pic_params->mv_fields.bits.mv_mode; + if(ctx->mv_mode == WMF_MVMODE_INTENSITY_COMPENSATION) + { + ctx->mv_mode = pic_params->mv_fields.bits.mv_mode2; + } + + /* Neither MVMODE nor MVMODE2 are signaled at the picture level for interlaced frame pictures, + but MVMODE can be determine for P pictures depending on the value of MV4SWITCH, and for B + pictures it is by default 1MV mode. */ + if((pic_params->picture_fields.bits.frame_coding_mode == VC1_FCM_FRMI) && PIC_TYPE_IS_INTER(pic_params->picture_fields.bits.picture_type)) + { + if((pic_params->picture_fields.bits.picture_type == WMF_PTYPE_P) && (pic_params->mv_fields.bits.four_mv_switch == 1)) + { + ctx->mv_mode = WMF_MVMODE_MIXED_MV; + pic_params->mv_fields.bits.mv_mode = WMF_MVMODE_MIXED_MV; + } + else + { + ctx->mv_mode = WMF_MVMODE_1MV; + pic_params->mv_fields.bits.mv_mode = WMF_MVMODE_1MV; + } + } + /************************************************************************************/ + + + /******************************** Calculate HALFPEL *********************************/ + if((ctx->mv_mode == WMF_MVMODE_1MV) || (ctx->mv_mode == WMF_MVMODE_MIXED_MV)) + { + ctx->half_pel = 0; + } + else + { + ctx->half_pel = 1; + } + /************************************************************************************/ + + /* TODO: Are we using the correct size for this ? */ + ctx->pull_back_x = COMPUTE_PULLBACK(pic_params->coded_width); + ctx->pull_back_y = COMPUTE_PULLBACK(pic_params->coded_height); + + if(pic_params->mv_fields.bits.extended_dmv_flag == 1) + { + ctx->extend_x = gDMVRANGE_ExtHorizontal_RemapTable[pic_params->mv_fields.bits.extended_dmv_range]; + ctx->extend_y = gDMVRANGE_ExtVertical_RemapTable[pic_params->mv_fields.bits.extended_dmv_range]; + } + else + { + ctx->extend_x = IMG_FALSE; + ctx->extend_y = IMG_FALSE; + } + + /* B interlaced field picture and ...?? */ + ctx->ui32ScaleFactor = 0; + ctx->i8FwrdRefFrmDist = 0; + ctx->i8BckwrdRefFrmDist = 0; + if(pic_params->picture_fields.bits.picture_type == WMF_PTYPE_B) + { + IMG_UINT32 ui32BFractionDen; + IMG_UINT32 ui32BFractionNum; + + IMG_UINT32 ui32FrameReciprocal; + + if (pic_params->b_picture_fraction > (sizeof(gBFRACTION_DenRemapTable) / sizeof(IMG_BYTE) - 1)) + pic_params->b_picture_fraction = sizeof(gBFRACTION_DenRemapTable) / sizeof(IMG_BYTE) - 1; + + ui32BFractionDen = gBFRACTION_DenRemapTable[pic_params->b_picture_fraction]; + ui32BFractionNum = gBFRACTION_NumRemapTable[pic_params->b_picture_fraction]; + + if (ui32BFractionDen > (sizeof(gaui16Inverse) / sizeof(IMG_UINT16))) + ui32BFractionDen = sizeof(gaui16Inverse) / sizeof(IMG_UINT16); + + if (ui32BFractionDen == 0) + { + psb__error_message("Invalid ui32BFractionDen value %d\n", ui32BFractionDen); + ui32BFractionDen = 1; + } + + ui32FrameReciprocal = gaui16Inverse[ui32BFractionDen - 1]; + ctx->ui32ScaleFactor = ui32BFractionNum * ui32FrameReciprocal; + + if(pic_params->picture_fields.bits.frame_coding_mode == VC1_FCM_FLDI) + { + ctx->i8FwrdRefFrmDist = (IMG_INT8)((ctx->ui32ScaleFactor * pic_params->reference_fields.bits.reference_distance) >> 8); /* 10.4.6.2 */ + ctx->i8BckwrdRefFrmDist = pic_params->reference_fields.bits.reference_distance - ctx->i8FwrdRefFrmDist - 1; + + if(ctx->i8BckwrdRefFrmDist < 0) + { + ctx->i8BckwrdRefFrmDist = 0; + } + } + } + + /* Compute the mode config parameter */ + /* + MODE_CONFIG[1:0] = + VC-1 intensity compensation flag, derived from MVMODE = Intensity compensation, and INTCOMPFIELD + 00 – No intensity compensation + 01 – Intensity compensation for top field + 10 – Intensity compensation for bottom field + 11 – Intensity compensation for the frame + + MODE_CONFIG[3:2] = + VC-1 reference range scaling, derived from RANGERED, RANGEREDFRM for current frame and reference frame. + 00 – No scaling + 01 – Scale down + 10 – Scale up + 11 – No scaling + */ + + /****************************** INTENSITY COMPENSATION ******************************/ + /* For each NEW reference frame, rotate IC history */ + if (PIC_TYPE_IS_REF(pic_params->picture_fields.bits.picture_type) && + pic_params->picture_fields.bits.is_first_field && + (pic_params->picture_fields.bits.frame_coding_mode == VC1_FCM_FLDI)) + { + /* + This is the first field picture of a new frame, so move the IC params for both field + pictures of the last frame (from position [1][0] for the first field and position [1][1] for + the second field to positions [0][0] and [0][1] respectevely). + */ + memcpy(&ctx->sICparams[0][0], &ctx->sICparams[1][0], sizeof(IC_PARAM)); + memcpy(&ctx->sICparams[0][1], &ctx->sICparams[1][1], sizeof(IC_PARAM)); + + memset(&ctx->sICparams[1][0], 0, sizeof(IC_PARAM)); + memset(&ctx->sICparams[1][1], 0, sizeof(IC_PARAM)); + } + + if(pic_params->picture_fields.bits.picture_type == WMF_PTYPE_P) + { + ctx->ui8CurrLumaScale1 = 0; + ctx->ui8CurrLumaShift1 = 0; + ctx->ui8CurrLumaScale2 = 0; + ctx->ui8CurrLumaShift2 = 0; + + if(pic_params->picture_fields.bits.frame_coding_mode != VC1_FCM_FRMI) + { + if(pic_params->picture_fields.bits.intensity_compensation) + { + /* Intensity compensation of reference */ + if(pic_params->picture_fields.bits.frame_coding_mode != VC1_FCM_FLDI) // progressive picture + { + ctx->mode_config = 0x3; + + ui8LumaScale1 = pic_params->luma_scale & 0x3F; + ui8LumaShift1 = pic_params->luma_shift & 0x3F; + + if(ui8LumaScale1 != 0 || ui8LumaShift1 != 0) + { + ctx->ui8CurrLumaScale1 = ui8LumaScale1; + ctx->ui8CurrLumaShift1 = ui8LumaShift1; + } + } + else // field interlaced picture + { + // top field + ui8LumaScale1 = pic_params->luma_scale & 0x3F; + ui8LumaShift1 = pic_params->luma_shift & 0x3F; + + // bottom field + ui8LumaScale2 = ui8LumaScale1; /* TODO: How to keep track of top/bottom field intensity comp? */ + ui8LumaShift2 = ui8LumaShift1; /* TODO: How to keep track of top/bottom field intensity comp? */ + + /* Check what fields undergo intensity compensation */ + ctx->ui8IntCompField = 0; + if(ui8LumaScale1 != 0 || ui8LumaShift1 != 0) + { + ctx->ui8IntCompField = 1; + } + if(ui8LumaScale2 != 0 || ui8LumaShift2 != 0) + { + ctx->ui8IntCompField |= 2; + } + + switch(ctx->ui8IntCompField) + { + case 0: /* none */ + ctx->mode_config = 0x0; + break; + + case 1: /* top */ + ctx->mode_config = 0x1; + + // IC parameters for top field + ctx->ui8CurrLumaScale1 = ui8LumaScale1; + ctx->ui8CurrLumaShift1 = ui8LumaShift1; + break; + + case 2: /* bottom */ + ctx->mode_config = 0x2; + + // IC parameters for bottom field + ctx->ui8CurrLumaScale2 = ui8LumaScale2; + ctx->ui8CurrLumaShift2 = ui8LumaShift2; + break; + + case 3: /* both */ + ctx->mode_config = 0x3; + + // IC parameters for top field + ctx->ui8CurrLumaScale1 = ui8LumaScale1; + ctx->ui8CurrLumaShift1 = ui8LumaShift1; + + // IC parameters for bottom field + ctx->ui8CurrLumaScale2 = ui8LumaScale2; + ctx->ui8CurrLumaShift2 = ui8LumaShift2; + break; + } + } + } + else + { + ctx->mode_config = 0; + } + } + else // interlaced frame P picture + { + if(pic_params->picture_fields.bits.intensity_compensation) /* iINSO */ + { + ctx->mode_config = 0x3; // intensity compensate whole frame + } + else + { + ctx->mode_config = 0; + } + } + } + else if(PIC_TYPE_IS_INTRA(pic_params->picture_fields.bits.picture_type)) + { + ctx->mode_config = 0; + } + + /* + 10.3.8 Intensity Compensation: + If intensity compensation is performed on a reference field, then after decoding the field, + the post-compensated pixel values shall be retained and shall be used when decoding the next + field. If the next field indicates that the field that was intensity compensated by the + previous field is to have intensity compensation performed again then the post-compensated + field shall be used. Therefore, when a reference field has intensity compensation performed + twice, the result of the first intensity compensation operation shall be used as input + for the second intensity compensation. + */ + /* + Don't forget point 9.1.1.4 in VC1 Spec: + + If the current frame, coded as two interlace field pictures, contains at least one P or B + field, and if this P or B field uses one or both field in another frame as a reference, where + the reference frame was also coded as a interlace field pictue, then the TFF of the current + frame and reference frame shall be the same. + */ + if((pic_params->picture_fields.bits.picture_type == WMF_PTYPE_P) && (pic_params->picture_fields.bits.frame_coding_mode == VC1_FCM_FLDI)) + { + if(pic_params->picture_fields.bits.top_field_first) // top field first + { + if(!pic_params->picture_fields.bits.is_first_field) // this is the second field picture (and bottom) + { + if(ctx->ui8IntCompField & 0x1) + { + /* The second and bottom field picture of the current frame + intensity compensates the top field of the current frame. */ + ctx->sICparams[1][0].ui8LumaScale1 = ui8LumaScale1; + ctx->sICparams[1][0].ui8LumaShift1 = ui8LumaShift1; + ctx->sICparams[1][0].ui8IC1 = 1; + } + if(ctx->ui8IntCompField & 0x2) + { + /* The second and bottom field picture of the current frame + intensity compensates the bottom field of the previous frame. */ + ctx->sICparams[0][1].ui8LumaScale2 = ui8LumaScale2; + ctx->sICparams[0][1].ui8LumaShift2 = ui8LumaShift2; + ctx->sICparams[0][1].ui8IC2 = 2; + } + } + else // first field picture (and top) + { + if(ctx->ui8IntCompField & 0x1) + { + /* The first and top field picture of the current frame + intensity compensates the top field of the previous frame. */ + ctx->sICparams[0][0].ui8LumaScale2 = ui8LumaScale1; + ctx->sICparams[0][0].ui8LumaShift2 = ui8LumaShift1; + ctx->sICparams[0][0].ui8IC2 = 1; + } + if(ctx->ui8IntCompField & 0x2) + { + /* The first and top field picture of the current frame + intensity compensates the bottom field of the previous frame. */ + ctx->sICparams[0][1].ui8LumaScale1 = ui8LumaScale2; + ctx->sICparams[0][1].ui8LumaShift1 = ui8LumaShift2; + ctx->sICparams[0][1].ui8IC1 = 2; + } + } + } + else // bottom field first + { + if(!pic_params->picture_fields.bits.is_first_field) // this is the second field picture (and top) + { + if(ctx->ui8IntCompField & 0x2) + { + /* The second and top field picture of the current frame + intensity compensates the bottom field of the current frame. */ + ctx->sICparams[1][1].ui8LumaScale1 = ui8LumaScale2; + ctx->sICparams[1][1].ui8LumaShift1 = ui8LumaShift2; + ctx->sICparams[1][1].ui8IC1 = 2; + } + if(ctx->ui8IntCompField & 0x1) + { + /* The second and top field picture of the current frame + intensity compensates the top field of the previous frame. */ + ctx->sICparams[0][0].ui8LumaScale2 = ui8LumaScale1; + ctx->sICparams[0][0].ui8LumaShift2 = ui8LumaShift1; + ctx->sICparams[0][0].ui8IC2 = 1; + } + } + else // first field picture (and bottom) + { + if(ctx->ui8IntCompField & 0x1) + { + /* The first and bottom field picture of the current frame + intensity compensates the top field of the previous frame. */ + ctx->sICparams[0][0].ui8LumaScale1 = ui8LumaScale1; + ctx->sICparams[0][0].ui8LumaShift1 = ui8LumaShift1; + ctx->sICparams[0][0].ui8IC1 = 1; + } + if(ctx->ui8IntCompField & 0x2) + { + /* The first and bottom field picture of the current frame + intensity compensates the bottom field of the previous frame. */ + ctx->sICparams[0][1].ui8LumaScale2 = ui8LumaScale2; + ctx->sICparams[0][1].ui8LumaShift2 = ui8LumaShift2; + ctx->sICparams[0][1].ui8IC2 = 2; + } + } + } + } + /************************************************************************************/ + + /********************************* RANGE REDUCTION **********************************/ + /* Determine the difference between the range reduction of current and reference picture */ + if(ctx->profile == WMF_PROFILE_MAIN) + { + /* Range Reduction is only enabled for Main Profile */ + /* The RANGEREDFRM values from the reference pictures are; + psVLDContext->bRef0RangeRed + psVLDContext->bRef1RangeRed */ + + switch(pic_params->picture_fields.bits.picture_type) + { + case WMF_PTYPE_I: + case WMF_PTYPE_BI: + /* no reference picture scaling */ + break; + + case WMF_PTYPE_P: /* P picture */ + /* + 8.3.4.11 also need to scale the previously reconstructed anchor frame prior to using it for MC if: + - RANGEREDFRM == 1 and ref RANGEREDFRM flag is not signalled scale down previous reconstructed frame. + - RANGEREDFRM == 0 and ref RANGEREDFRM flag is set scale up previous reconstructed frame. + */ + if(ctx->pic_params->range_reduction_frame && !ctx->bRef0RangeRed) + { + ctx->mode_config |= (0x1 << 2); // scale down previous reconstructed frame + } + else if(!ctx->pic_params->range_reduction_frame && ctx->bRef0RangeRed) + { + ctx->mode_config |= (0x2 << 2); // scale up previous reconstructed frame + } + else /* neither or both are set */ + { + ctx->mode_config |= (0x0 << 2); // no scaling of reference + } + break; + + case WMF_PTYPE_B: /* B picture */ + /* + 8.4.4.14 RANGEREDFRM shall be the same as for the temporally subsequent anchor frame (display order) + If this is set then the current decoded frame shall be scalled up similar to P frame. + Scaling for the temporally (display order) preceeding frame will be applied as for P frames + */ + if(ctx->bRef0RangeRed && !ctx->bRef1RangeRed) + { + ctx->mode_config |= (0x1 << 2); + } + else if(!ctx->bRef0RangeRed && ctx->bRef1RangeRed) + { + ctx->mode_config |= (0x2 << 2); + } + else /* neither or both are set */ + { + ctx->mode_config |= (0x0 << 2); // no scaling of reference + } + break; + + default: + break; + } + } + else + { + ctx->mode_config |= (0x0 << 2); + } + /************************************************************************************/ + + /********************************** Slice structure *********************************/ + if (VC1_FCM_FLDI == pic_params->picture_fields.bits.frame_coding_mode) + { + if ((pic_params->picture_fields.bits.top_field_first && pic_params->picture_fields.bits.is_first_field) || + (!pic_params->picture_fields.bits.top_field_first && !pic_params->picture_fields.bits.is_first_field)) + { + // Top field + ctx->slice_field_type = 0; + ctx->bottom_field = 0; + } + else + { + // Bottom field + ctx->slice_field_type = 1; + ctx->bottom_field = 1; + } + } + else + { + // progressive or interlaced frame + ctx->slice_field_type = 2; + ctx->bottom_field = 1; + } + /************************************************************************************/ + + /************************* FCM for the reference pictures ***************************/ + ctx->ui8FCM_Ref0Pic = ctx->pic_params->picture_fields.bits.frame_coding_mode; + ctx->ui8FCM_Ref1Pic = ctx->pic_params->picture_fields.bits.frame_coding_mode; + if(ctx->obj_context->frame_count == 0) + ctx->ui8FCM_Ref2Pic = ctx->pic_params->picture_fields.bits.frame_coding_mode; + + if(PIC_TYPE_IS_REF(pic_params->picture_fields.bits.picture_type) || + ((pic_params->picture_fields.bits.picture_type == WMF_PTYPE_B) && /* The second B field picture in an */ + (ctx->pic_params->picture_fields.bits.frame_coding_mode == VC1_FCM_FLDI) && /* interlaced field coded frame shall */ + !pic_params->picture_fields.bits.is_first_field)) /* reference the first field picture. */ + { + if(ctx->pic_params->picture_fields.bits.frame_coding_mode == VC1_FCM_FLDI && !pic_params->picture_fields.bits.is_first_field) + { + /* The current picture is the second field of the frame, then the previous field picture + is in the same frame. Therefore the FCM of the first field is the same as the FCM of the + current field and the first field will be reference 0. */ + ctx->ui8FCM_Ref0Pic = ctx->pic_params->picture_fields.bits.frame_coding_mode; + } + else if(ctx->pic_params->picture_fields.bits.frame_coding_mode == VC1_FCM_FLDI && pic_params->picture_fields.bits.is_first_field) + { + /* The current picture is the first field of the frame, then the previous field picture + is in a different frame and will be reference 1. */ + ctx->ui8FCM_Ref1Pic = ctx->ui8FCM_Ref2Pic; + } + else // progresive or interlaced frame picture + { + ctx->ui8FCM_Ref1Pic = ctx->ui8FCM_Ref2Pic; + } + } + /************************************************************************************/ + + /************************* TFF for the reference pictures ***************************/ + if(ctx->obj_context->frame_count == 0) + { + ctx->bTFF_FwRefFrm = pic_params->picture_fields.bits.top_field_first; + ctx->bTFF_BwRefFrm = pic_params->picture_fields.bits.top_field_first; + } + if(PIC_TYPE_IS_REF(pic_params->picture_fields.bits.picture_type) && + ((ctx->pic_params->picture_fields.bits.frame_coding_mode != VC1_FCM_FLDI) || + pic_params->picture_fields.bits.is_first_field)) + { + ctx->bTFF_FwRefFrm = ctx->bTFF_BwRefFrm; + } + /************************************************************************************/ + + return VA_STATUS_SUCCESS; +} + +static VAStatus psb__VC1_process_bitplane(context_VC1_p ctx, object_buffer_p obj_buffer) +{ + VAStatus vaStatus = VA_STATUS_SUCCESS; + ASSERT(obj_buffer->type == VABitPlaneBufferType); + ASSERT(ctx->pic_params); + + if ((NULL == obj_buffer->psb_buffer) || + (0 == obj_buffer->size)) + { + /* We need to have data in the bitplane buffer */ + vaStatus = VA_STATUS_ERROR_UNKNOWN; + return vaStatus; + } + + ctx->bitplane_buffer = obj_buffer->psb_buffer; + ctx->has_bitplane = TRUE; + return vaStatus; +} + +/* + * Adds a VASliceParameterBuffer to the list of slice params + */ +static VAStatus psb__VC1_add_slice_param(context_VC1_p ctx, object_buffer_p obj_buffer) +{ + ASSERT(obj_buffer->type == VASliceParameterBufferType); + if (ctx->slice_param_list_idx >= ctx->slice_param_list_size) + { + void *new_list; + ctx->slice_param_list_size += 8; + new_list = realloc(ctx->slice_param_list, + sizeof(object_buffer_p)*ctx->slice_param_list_size); + if (NULL == new_list) + { + return VA_STATUS_ERROR_ALLOCATION_FAILED; + } + ctx->slice_param_list = (object_buffer_p*) new_list; + } + ctx->slice_param_list[ctx->slice_param_list_idx] = obj_buffer; + ctx->slice_param_list_idx++; + return VA_STATUS_SUCCESS; +} + + +/* + * This function extracts the information about a given table from the index of VLC tables. + */ +static void psb__VC1_extract_table_info(context_VC1_p ctx, sTableData *psInfo, int idx) +{ + IMG_UINT32 tmp; + + if (idx >= VLC_INDEX_TABLE_SIZE) + idx = VLC_INDEX_TABLE_SIZE - 1; + + tmp = ctx->vlc_packed_index_table[idx]; + psInfo->aui16StartLocation = (IMG_UINT16)(tmp & 0xffff); + psInfo->aui16VLCTableLength = (IMG_UINT16)((tmp >> 16) & 0x1ff); + psInfo->aui16InitialWidth = (IMG_UINT16)((tmp >> 25) & 0x7); + psInfo->aui16InitialOpcode = (IMG_UINT16)((tmp >> 28) & 0x3); +} + +/* + * This function selects the VLD tables from the picture layer parameters. + */ +static void psb__VC1_write_VLC_tables(context_VC1_p ctx) +{ + VAPictureParameterBufferVC1 *pic_params = ctx->pic_params; + IMG_UINT16 ui16Table = 0, ui16IntraTable = 0, ui16InterTable = 0, aui16Table[3]; + IMG_UINT32 i, ui32TableNum = 0; + + /* select the required table from the n different types + A - vc1DEC_I_Picture_CBPCY_VLC (1) ¬ + B - vc1DEC_P_Picture_CBPCY_VLC_N (4) | + C - vc1DEC_Interlaced_CBPCY_N (8) | + D - vc1DEC_FourMV_Pattern_N (4) | + E - vc1DEC_INTERLACE_2_MVP_Pattern_N (4) | + F - vc1DEC_Mot_Vector_Diff_VLC_N (4) | MB Layer + G - vc1DEC_One_Field_Ref_Ilace_MV_N (4) | + H - vc1DEC_Two_Field_Ref_Ilace_MV_N (8) | + I - vc1DEC_Mixed_MV_MB_N (8) | + J - vc1DEC_One_MV_MB_N (8) | + K - vc1DEC_INTERLACE_4MV_MB_N (4) | + L - vc1DEC_INTERLACE_Non_4MV_MB_N (4) | + M - vc1DEC_X_Rate_TTMB (3) - + N - vc1DEC_X_Rate_TTBLK (3) ¬ + O - vc1DEC_X_Rate_SUBBLKPAT (3) | + P - vc1DEC_X_X_Inter_VLC (4) | Block Layer + Q - vc1DEC_X_X_Intra_VLC (4) | + R - vc1DEC_X_Mot_Luminance_DC_Diff_VLC (2) | + S - vc1DEC_X_Mot_Chroma_DC_Diff_VLC (2) - + + X - vc1DEC_Code_3x2_2x3_tiles (1) NOT USED */ + + /*! + *********************************************************************************** + @ Table A,B,C VLC CBPCY Tables + + [VC1] 7.1.3.1 Coded Block Pattern (CBPCY) (Variable size)[I, P,B] + + CBPCY is a variable-sized syntax element that shall be present in all + I and BI picture macroblocks, and may be present in P and B picture + macroblocks. In P and B pictures, CBPCY shall be decoded using + the VLC table specified by the CBPTAB syntax element as described in + section 7.1.1.39. The CBP tables for P and B pictures are listed in + section 11.6. + + + [VC1] 9.1.3.2 Coded Block Pattern (CBPCY) (Variable size)[I, P,B] + + Table 102: ICBPTAB code-table + + A vc1DEC_I_Picture_CBPCY_VLC (1) + B vc1DEC_P_Picture_CBPCY_VLC_N (4) + C vc1DEC_Interlaced_CBPCY_N (8) + + ***********************************************************************************/ + + if((!pic_params->sequence_fields.bits.interlace) || (pic_params->picture_fields.bits.frame_coding_mode == VC1_FCM_P)) + { + if(PIC_TYPE_IS_INTRA(pic_params->picture_fields.bits.picture_type)) + { + ui16Table = VC1_VLC_I_Picture_CBPCY_VLC; + } + else if(PIC_TYPE_IS_INTER(pic_params->picture_fields.bits.picture_type)) + { + psb__bounds_check(pic_params->cbp_table, 4); + ui16Table = CBPCYTableProg[pic_params->cbp_table]; + } + } + else /* Interlaced */ + { + if(PIC_TYPE_IS_INTRA(pic_params->picture_fields.bits.picture_type)) + { + ui16Table = VC1_VLC_I_Picture_CBPCY_VLC; + } + else + { + psb__bounds_check(pic_params->cbp_table, 8); + ui16Table = CBPCYTableInterlaced[pic_params->cbp_table]; /* LUT */ + } + } + + psb__VC1_extract_table_info(ctx, &ctx->sTableInfo[ui32TableNum], ui16Table); + ui32TableNum++; + + /*! + ************************************************************ + @ Table D VLC 4MV Pattern + + [VC1] Table 104: 4MVBP code-table + + Tables 116-119 + + D vc1DEC_FourMV_Pattern_N (4) + ************************************************************/ + psb__bounds_check(pic_params->mv_fields.bits.four_mv_block_pattern_table, 4); + ui16Table = FourMVTable[pic_params->mv_fields.bits.four_mv_block_pattern_table]; + + psb__VC1_extract_table_info(ctx, &ctx->sTableInfo[ui32TableNum], ui16Table); + ui32TableNum++; + + /*! + ************************************************************************************ + @ Table E VLC 2MVBP Tables + + + Table 103: 2MVBP code-table + + for Tables 120-123 + + E vc1DEC_INTERLACE_2_MVP_Pattern_N (4) + ***********************************************************************************/ + psb__bounds_check(pic_params->mv_fields.bits.two_mv_block_pattern_table, 4); + ui16Table = Interlace2MVTable[pic_params->mv_fields.bits.two_mv_block_pattern_table]; + + psb__VC1_extract_table_info(ctx, &ctx->sTableInfo[ui32TableNum], ui16Table); + ui32TableNum++; + + /*! + ************************************************************************************ + @ Table F,G,H VLC MV Tables + + [VC1] MVDATA Variable size vlclbf 7.1.3.8 + + 7.1.3.8 Motion Vector Data (MVDATA)(Variable size)[P] + + MVDATA is a variable sized syntax element that may be present in P picture + macroblocks. This syntax element decodes to the motion vector(s) for the + macroblock. The table used to decode this syntax element is specified by the + MVTAB syntax element in the picture layer as specified in section 7.1.1.38. + + F vc1DEC_Mot_Vector_Diff_VLC_N (4) + + [VC1] 9.1.1.34 INTERLACE Motion Vector Table (IMVTAB) (2 or 3 bits) + + Table 100: IMVTAB code-table for P INTERLACE field picture with NUMREF = 0, + and for P/B INTERLACE frame pictures + + IMVTAB Motion Vector Table + 00 1-Reference Table 0 + 01 1-Reference Table 1 + 10 1-Reference Table 2 + 11 1-Reference Table 3 + + Table 101: IMVTAB code-table for P INTERLACE field pictures with NUMREF = 1, + and for B INTERLACE field pictures + + IMVTAB Motion Vector Table + 000 2-Reference Table 0 + 001 2-Reference Table 1 + 010 2-Reference Table 2 + 011 2-Reference Table 3 + 100 2-Reference Table 4 + 101 2-Reference Table 5 + 110 2-Reference Table 6 + 111 2-Reference Table 7 + + G vc1DEC_One_Field_Ref_Ilace_MV_N (4) + H vc1DEC_Two_Field_Ref_Ilace_MV_N (8) + + ***********************************************************************************/ + if((!pic_params->sequence_fields.bits.interlace) || (pic_params->picture_fields.bits.frame_coding_mode == VC1_FCM_P)) + { + psb__bounds_check(pic_params->mv_fields.bits.mv_table, 4); + ui16Table = ProgressiveMVTable[pic_params->mv_fields.bits.mv_table]; + } + else + { + if( + ( + PIC_TYPE_IS_INTER(pic_params->picture_fields.bits.picture_type) && + (pic_params->picture_fields.bits.frame_coding_mode == VC1_FCM_FRMI) + ) + || + ( + (pic_params->picture_fields.bits.picture_type == WMF_PTYPE_P) && + (pic_params->picture_fields.bits.frame_coding_mode == VC1_FCM_FLDI) && + (pic_params->reference_fields.bits.num_reference_pictures == 0) + ) + ) + { + /* One field */ + psb__bounds_check(pic_params->mv_fields.bits.mv_table, 4); + ui16Table = Interlaced1RefMVTable[pic_params->mv_fields.bits.mv_table]; + } + else /*if (((FCM == VC1_FCM_FLDI) && (NUMREF == 0) && (PTYPE == WMF_PTYPE_P)) || ((PTYPE == WMF_PTYPE_B) && (FCM == VC1_FCM_FLDI))) */ + { + /* two field */ + psb__bounds_check(pic_params->mv_fields.bits.mv_table, 8); + ui16Table = MVTable2RefIlace[pic_params->mv_fields.bits.mv_table]; /* LUT */ + } + } + + psb__VC1_extract_table_info(ctx, &ctx->sTableInfo[ui32TableNum], ui16Table); + ui32TableNum++; + + /*! + ************************************************************************************ + @ Table I,J,K,L VLC MBMODE Tables + + I vc1DEC_Mixed_MV_MB_N (8) + J vc1DEC_One_MV_MB_N (8) + K vc1DEC_INTERLACE_4MV_MB_N (4) + L vc1DEC_INTERLACE_Non_4MV_MB_N (4) + ***********************************************************************************/ + ui16Table = 0; + if(pic_params->sequence_fields.bits.interlace && (pic_params->picture_fields.bits.frame_coding_mode > VC1_FCM_P)) + { + if(PIC_TYPE_IS_INTER(pic_params->picture_fields.bits.picture_type)) + { + if(pic_params->picture_fields.bits.frame_coding_mode == VC1_FCM_FLDI) + { + psb__bounds_check(pic_params->mb_mode_table, 8); + /* 9.1.1.33 use MBMODETAB and MVMODE to select field interlaced tables */ + ui16Table = MBMODETableFLDI[pic_params->mb_mode_table][(pic_params->mv_fields.bits.mv_mode == WMF_MVMODE_MIXED_MV) ? 1 : 0]; + } + else if(pic_params->picture_fields.bits.frame_coding_mode == VC1_FCM_FRMI) + { + psb__bounds_check(pic_params->mb_mode_table, 4); + /* 9.1.1.33 use MBMODETAB and MV4SWITCH to select frame interlaced tables */ + ui16Table = MBMODETableFRMI[pic_params->mb_mode_table][(pic_params->mv_fields.bits.four_mv_switch) ? 0 : 1]; + } + } + } + + psb__VC1_extract_table_info(ctx, &ctx->sTableInfo[ui32TableNum], ui16Table); + ui32TableNum++; + + /*! + ************************************************************************************ + @ Table M,N,O VLC PQUANT Tables + + [WMV9] 3.2.2.10 MB-level Transform Type (TTMB)(Variable size)[P,B] + [WMV9] 3.2.3.15 Block-level Transform Type (TTBLK)(Variable size)[inter] + + [WMV9] 3.2.3.16 Transform sub-block pattern (SUBBLKPAT)(Variable size)[inter] + + M vc1DEC_X_Rate_TTMB (3) + N vc1DEC_X_Rate_TTBLK (3) + O vc1DEC_X_Rate_SUBBLKPAT (3) + + TTBLK and TTMB P and B Pictures only + + ***********************************************************************************/ + aui16Table[0] = 0; aui16Table[1] = 0; aui16Table[2] = 0; + + if(pic_params->pic_quantizer_fields.bits.pic_quantizer_scale <= 4) /* high rate */ + { + aui16Table[2] = VC1_VLC_High_Rate_SUBBLKPAT; + aui16Table[1] = VC1_VLC_High_Rate_TTBLK; + aui16Table[0] = VC1_VLC_High_Rate_TTMB; + } + else if(pic_params->pic_quantizer_fields.bits.pic_quantizer_scale <= 12) /* med rate */ + { + aui16Table[2] = VC1_VLC_Medium_Rate_SUBBLKPAT; + aui16Table[1] = VC1_VLC_Medium_Rate_TTBLK; + aui16Table[0] = VC1_VLC_Medium_Rate_TTMB; + } + else /* low rate */ + { + aui16Table[2] = VC1_VLC_Low_Rate_SUBBLKPAT; + aui16Table[1] = VC1_VLC_Low_Rate_TTBLK; + aui16Table[0] = VC1_VLC_Low_Rate_TTMB; + } + + for(i=ui32TableNum; i<ui32TableNum+3; i++) + { + psb__VC1_extract_table_info(ctx, &ctx->sTableInfo[i], aui16Table[i-ui32TableNum]); + } + + ui32TableNum = ui32TableNum+3; + + { + /*! + *********************************************************************************************** + Inter Coded Blocks + + Table 54: Index/Coding Set Correspondence for PQINDEX <= 7 + Y, Cb and Cr blocks + + Index Table + 0 High Rate Inter + 1 High Motion Inter + 2 Mid Rate Inter + + Table 55: Index/Coding Set Correspondence for PQINDEX > 7 + Y, Cb and Cr blocks + + Index Table + 0 Low Motion Inter + 1 High Motion Inter + 2 Mid Rate Inter + + ---------------------------------------------------------------------------------- + Intra Blocks + + 8 AC Coeff Coding Sets: + 4 x INTRA, 4 x INTER + + Y use Intra, CrCb use Inter + + Table 38: Coding Set Correspondence for PQINDEX <= 7 + + Y blocks Cb and Cr blocks + Index Table Index Table + 0 High Rate Intra 0 High Rate Inter + 1 High Motion Intra 1 High Motion Inter + 2 Mid Rate Intra 2 Mid Rate Inter + + Table 39: Coding Set Correspondence for PQINDEX > 7 + + Y blocks Cb and Cr blocks + Index Table Index Table + 0 Low Motion Intra 0 Low Motion Inter + 1 High Motion Intra 1 High Motion Inter + 2 Mid Rate Intra 2 Mid Rate Inter + + The value decoded from the DCTACFRM2 syntax element shall be used + as the coding set index for Y blocks and the value decoded from the + DCTACFRM syntax element shall be used as the coding set + index for Cb and Cr blocks. + + P vc1DEC_X_X_Inter_VLC + Q vc1DEC_X_X_Intra_VLC + + + for I pictures TRANSACFRM specifies the Inter Coding set + TRANSACFRM2 specifies the Intra Coding set + + for P pictures TRANSACFRM specifies Inter and Intra Coding set + + + ***************************************************************************************************/ + IMG_UINT32 ui32IntraCodingSetIndex = PIC_TYPE_IS_INTRA(pic_params->picture_fields.bits.picture_type) + ? pic_params->transform_fields.bits.transform_ac_codingset_idx2 + : pic_params->transform_fields.bits.transform_ac_codingset_idx1; + + IMG_UINT32 ui32InterCodingSetIndex = pic_params->transform_fields.bits.transform_ac_codingset_idx1; + + /* For PQINDEX < 9 the uniform quantizer should be used, as indicated by PQUANTIZER == 1 */ + if( !ctx->pqindex_gt8 ) + { + ui16IntraTable = IntraTablePQIndexLT9[ui32IntraCodingSetIndex]; + ui16InterTable = InterTablePQIndexLT9[ui32InterCodingSetIndex]; + } + else + { + ui16IntraTable = IntraTablePQIndexGT8[ui32IntraCodingSetIndex]; + ui16InterTable = InterTablePQIndexGT8[ui32InterCodingSetIndex]; + } + + psb__VC1_extract_table_info(ctx, &ctx->sTableInfo[ui32TableNum], ui16IntraTable); + ui32TableNum++; + + psb__VC1_extract_table_info(ctx, &ctx->sTableInfo[ui32TableNum], ui16InterTable); + ui32TableNum++; + } + + /*! + ************************************************************************************ + @ Table R & S VLC TRANSDCTAB Tables + + R vc1DEC_X_Mot_Luminance_DC_Diff_VLC (2) + S vc1DEC_X_Mot_Chroma_DC_Diff_VLC (2) + + [VC1] 8.1.1.2 Intra Transform DC Table + TRANSDCTAB is a one-bit syntax element that shall specify which of two + tables is used to decode the Transform DC coefficients in intra-coded blocks. + If TRANSDCTAB = 0, then the low motion table of Section 11.7 shall be used. + If TRANSDCTAB = 1, then the high motion table of Section 11.7 shall be used. + + [VC1] 8.1.1.2 Intra Transform DC Table + TRANSDCTAB is a one-bit syntax element that shall specify which of two + tables is used to decode the Transform DC coefficients in intra-coded blocks. + If TRANSDCTAB = 0, then the low motion table of Section 11.7 shall be used. + If TRANSDCTAB = 1, then the high motion table of Section 11.7 shall be used. + + ***********************************************************************************/ + if(pic_params->transform_fields.bits.intra_transform_dc_table == 0) + { + /* low motion */ + + /* VC1_VLC_Low_Mot_Luminance_DC_Diff_VLC */ + ui16IntraTable = VC1_VLC_Low_Mot_Luminance_DC_Diff_VLC; + + /* VC1_VLC_Low_Mot_Chroma_DC_Diff_VLC */ + ui16InterTable = VC1_VLC_Low_Mot_Chroma_DC_Diff_VLC; + } + else /* TRANSDCTAB == 1 */ + { + /* high motion */ + /* VC1_VLC_High_Mot_Luminance_DC_Diff_VLC */ + ui16IntraTable = VC1_VLC_High_Mot_Luminance_DC_Diff_VLC; + + /* VC1_VLC_High_Mot_Chroma_DC_Diff_VLC */ + ui16InterTable = VC1_VLC_High_Mot_Chroma_DC_Diff_VLC; + } + + psb__VC1_extract_table_info(ctx, &ctx->sTableInfo[ui32TableNum], ui16IntraTable); + ui32TableNum++; + + psb__VC1_extract_table_info(ctx, &ctx->sTableInfo[ui32TableNum], ui16InterTable); + ui32TableNum++; + + /* at the end determine how many tables have been chosen + this should be constant and equal 12 */ + ctx->ui32NumTables = ui32TableNum; + ASSERT(ctx->ui32NumTables == 12); +} + +static void psb__VC1_build_VLC_tables(context_VC1_p ctx) +{ + psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf; + int i; + uint16_t RAM_location = 0; + uint32_t reg_value; + + for(i = 0; i < ctx->ui32NumTables; i++) + { + if (RAM_location & 0x03) + { + /* Align */ + RAM_location += 4 - (RAM_location & 0x03); + } + ctx->sTableInfo[i].aui16RAMLocation = RAM_location; + + /* VLC Table */ + /* Write a LLDMA Cmd to transfer VLD Table data */ + + psb_cmdbuf_lldma_write_cmdbuf( cmdbuf, &ctx->vlc_packed_table, + ctx->sTableInfo[i].aui16StartLocation * sizeof(IMG_UINT16), /* origin */ + ctx->sTableInfo[i].aui16VLCTableLength * sizeof(IMG_UINT16), /* size */ + RAM_location * sizeof(IMG_UINT32), /* destination */ + LLDMA_TYPE_VLC_TABLE ); +psb__information_message("table[%02d] start_loc = %08x RAM_location = %08x | %08x\n", i, ctx->sTableInfo[i].aui16StartLocation * sizeof(IMG_UINT16), RAM_location, RAM_location * sizeof(IMG_UINT32)); + RAM_location += ctx->sTableInfo[i].aui16VLCTableLength; + } + + /* Write the vec registers with the index data for each of the tables */ + psb_cmdbuf_reg_start_block( cmdbuf ); + + reg_value = 0; + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0, VLC_TABLE_ADDR0, ctx->sTableInfo[0].aui16RAMLocation ); + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0, VLC_TABLE_ADDR1, ctx->sTableInfo[1].aui16RAMLocation ); + psb_cmdbuf_reg_set( cmdbuf, REGISTER_OFFSET (MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0), reg_value ); + + reg_value = 0; + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR1, VLC_TABLE_ADDR2, ctx->sTableInfo[2].aui16RAMLocation ); + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR1, VLC_TABLE_ADDR3, ctx->sTableInfo[3].aui16RAMLocation ); + psb_cmdbuf_reg_set( cmdbuf, REGISTER_OFFSET (MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR1), reg_value ); + + reg_value = 0; + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR2, VLC_TABLE_ADDR4, ctx->sTableInfo[4].aui16RAMLocation ); + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR2, VLC_TABLE_ADDR5, ctx->sTableInfo[5].aui16RAMLocation ); + psb_cmdbuf_reg_set( cmdbuf, REGISTER_OFFSET (MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR2), reg_value ); + + reg_value = 0; + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR3, VLC_TABLE_ADDR6, ctx->sTableInfo[6].aui16RAMLocation ); + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR3, VLC_TABLE_ADDR7, ctx->sTableInfo[7].aui16RAMLocation ); + psb_cmdbuf_reg_set( cmdbuf, REGISTER_OFFSET (MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR3), reg_value ); + + reg_value = 0; + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR4, VLC_TABLE_ADDR8, ctx->sTableInfo[8].aui16RAMLocation ); + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR4, VLC_TABLE_ADDR9, ctx->sTableInfo[9].aui16RAMLocation ); + psb_cmdbuf_reg_set( cmdbuf, REGISTER_OFFSET (MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR4), reg_value ); + + reg_value = 0; + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR5, VLC_TABLE_ADDR10, ctx->sTableInfo[10].aui16RAMLocation ); + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR5, VLC_TABLE_ADDR11, ctx->sTableInfo[11].aui16RAMLocation ); + psb_cmdbuf_reg_set( cmdbuf, REGISTER_OFFSET (MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR5), reg_value ); + + reg_value = 0; + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_WIDTH0, VLC_TABLE_INITIAL_WIDTH0, ctx->sTableInfo[0].aui16InitialWidth ); + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_WIDTH0, VLC_TABLE_INITIAL_WIDTH1, ctx->sTableInfo[1].aui16InitialWidth ); + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_WIDTH0, VLC_TABLE_INITIAL_WIDTH2, ctx->sTableInfo[2].aui16InitialWidth ); + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_WIDTH0, VLC_TABLE_INITIAL_WIDTH3, ctx->sTableInfo[3].aui16InitialWidth ); + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_WIDTH0, VLC_TABLE_INITIAL_WIDTH4, ctx->sTableInfo[4].aui16InitialWidth ); + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_WIDTH0, VLC_TABLE_INITIAL_WIDTH5, ctx->sTableInfo[5].aui16InitialWidth ); + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_WIDTH0, VLC_TABLE_INITIAL_WIDTH6, ctx->sTableInfo[6].aui16InitialWidth ); + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_WIDTH0, VLC_TABLE_INITIAL_WIDTH7, ctx->sTableInfo[7].aui16InitialWidth ); + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_WIDTH0, VLC_TABLE_INITIAL_WIDTH8, ctx->sTableInfo[8].aui16InitialWidth ); + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_WIDTH0, VLC_TABLE_INITIAL_WIDTH9, ctx->sTableInfo[9].aui16InitialWidth ); + psb_cmdbuf_reg_set( cmdbuf, REGISTER_OFFSET (MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_WIDTH0), reg_value ); + + reg_value = 0; + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_WIDTH1, VLC_TABLE_INITIAL_WIDTH10, ctx->sTableInfo[10].aui16InitialWidth ); + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_WIDTH1, VLC_TABLE_INITIAL_WIDTH11, ctx->sTableInfo[11].aui16InitialWidth ); + psb_cmdbuf_reg_set( cmdbuf, REGISTER_OFFSET (MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_WIDTH1), reg_value ); + + reg_value = 0; + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_OPCODE0, VLC_TABLE_INITIAL_OPCODE0, ctx->sTableInfo[0].aui16InitialOpcode ); + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_OPCODE0, VLC_TABLE_INITIAL_OPCODE1, ctx->sTableInfo[1].aui16InitialOpcode ); + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_OPCODE0, VLC_TABLE_INITIAL_OPCODE2, ctx->sTableInfo[2].aui16InitialOpcode ); + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_OPCODE0, VLC_TABLE_INITIAL_OPCODE3, ctx->sTableInfo[3].aui16InitialOpcode ); + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_OPCODE0, VLC_TABLE_INITIAL_OPCODE4, ctx->sTableInfo[4].aui16InitialOpcode ); + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_OPCODE0, VLC_TABLE_INITIAL_OPCODE5, ctx->sTableInfo[5].aui16InitialOpcode ); + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_OPCODE0, VLC_TABLE_INITIAL_OPCODE6, ctx->sTableInfo[6].aui16InitialOpcode ); + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_OPCODE0, VLC_TABLE_INITIAL_OPCODE7, ctx->sTableInfo[7].aui16InitialOpcode ); + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_OPCODE0, VLC_TABLE_INITIAL_OPCODE8, ctx->sTableInfo[8].aui16InitialOpcode ); + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_OPCODE0, VLC_TABLE_INITIAL_OPCODE9, ctx->sTableInfo[9].aui16InitialOpcode ); + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_OPCODE0, VLC_TABLE_INITIAL_OPCODE10, ctx->sTableInfo[10].aui16InitialOpcode ); + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_OPCODE0, VLC_TABLE_INITIAL_OPCODE11, ctx->sTableInfo[11].aui16InitialOpcode ); + psb_cmdbuf_reg_set( cmdbuf, REGISTER_OFFSET (MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_OPCODE0), reg_value ); + + psb_cmdbuf_reg_end_block( cmdbuf ); +} + + +static void psb__VC1_write_kick(context_VC1_p ctx, VASliceParameterBufferVC1 *slice_param) +{ + psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf; + + (void) slice_param; /* Unused for now */ + + *cmdbuf->cmd_idx++ = CMD_COMPLETION; +} + +/* Programme the Alt output if there is a rotation*/ +static void psb__VC1_setup_alternative_frame( context_VC1_p ctx ) +{ + uint32_t cmd; + psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf; + psb_surface_p rotate_surface = ctx->obj_context->current_render_target->psb_surface_rotate; + object_context_p obj_context = ctx->obj_context; + + if(rotate_surface->extra_info[5] != obj_context->rotate) + psb__error_message("Display rotate mode does not match surface rotate mode!\n"); + + + /* CRendecBlock RendecBlk( mCtrlAlloc , RENDEC_REGISTER_OFFSET(MSVDX_CMDS, VC1_LUMA_RANGE_MAPPING_BASE_ADDRESS) ); */ + psb_cmdbuf_rendec_start( cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, VC1_LUMA_RANGE_MAPPING_BASE_ADDRESS) ); + + psb_cmdbuf_rendec_write_address( cmdbuf, &rotate_surface->buf, rotate_surface->buf.buffer_ofs); + psb_cmdbuf_rendec_write_address( cmdbuf, &rotate_surface->buf, rotate_surface->buf.buffer_ofs + rotate_surface->chroma_offset); + + psb_cmdbuf_rendec_end( cmdbuf ); + + /* Set the rotation registers */ + psb_cmdbuf_rendec_start( cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION) ); + cmd = 0; + REGIO_WRITE_FIELD_LITE(cmd, MSVDX_CMDS,ALTERNATIVE_OUTPUT_PICTURE_ROTATION ,ALT_PICTURE_ENABLE,1 ); + REGIO_WRITE_FIELD_LITE(cmd, MSVDX_CMDS,ALTERNATIVE_OUTPUT_PICTURE_ROTATION ,ROTATION_ROW_STRIDE, rotate_surface->stride_mode); + REGIO_WRITE_FIELD_LITE(cmd, MSVDX_CMDS,ALTERNATIVE_OUTPUT_PICTURE_ROTATION ,RECON_WRITE_DISABLE, 0); /* FIXME Always generate Rec */ + REGIO_WRITE_FIELD_LITE(cmd, MSVDX_CMDS,ALTERNATIVE_OUTPUT_PICTURE_ROTATION ,ROTATION_MODE, rotate_surface->extra_info[5]); + + psb_cmdbuf_rendec_write( cmdbuf, cmd ); + + psb_cmdbuf_rendec_end( cmdbuf ); +} + +static void psb__VC1_program_output_register(context_VC1_p ctx, IMG_BOOL first_two_pass) +{ + psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf; + psb_surface_p target_surface = ctx->obj_context->current_render_target->psb_surface; + psb_surface_p rotate_surface = ctx->obj_context->current_render_target->psb_surface_rotate; + object_context_p obj_context = ctx->obj_context; + uint32_t alt_output_flags = 0; + uint32_t cmd; + *ctx->p_range_mapping_base = 0; + *ctx->p_range_mapping_base1 = 0; + //rotate_surface = ctx->decoded_surface->psb_surface_rotate; + + if((first_two_pass == 0) && (obj_context->rotate != VA_ROTATION_NONE) ) + { + psb_cmdbuf_rendec_start( cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, VC1_LUMA_RANGE_MAPPING_BASE_ADDRESS) ); + psb_cmdbuf_rendec_write_address( cmdbuf, &rotate_surface->buf, rotate_surface->buf.buffer_ofs); + psb_cmdbuf_rendec_write_address( cmdbuf, &rotate_surface->buf, rotate_surface->chroma_offset + rotate_surface->buf.buffer_ofs); + psb_cmdbuf_rendec_end( cmdbuf ); + + //target_surface = rotate_surface; + + REGIO_WRITE_FIELD_LITE(alt_output_flags, MSVDX_CMDS,ALTERNATIVE_OUTPUT_PICTURE_ROTATION ,ALT_PICTURE_ENABLE,1 ); + REGIO_WRITE_FIELD_LITE(alt_output_flags, MSVDX_CMDS,ALTERNATIVE_OUTPUT_PICTURE_ROTATION ,ROTATION_ROW_STRIDE, rotate_surface->stride_mode); + REGIO_WRITE_FIELD_LITE(alt_output_flags, MSVDX_CMDS,ALTERNATIVE_OUTPUT_PICTURE_ROTATION ,RECON_WRITE_DISABLE, 0); /* FIXME Always generate Rec */ + REGIO_WRITE_FIELD_LITE(alt_output_flags, MSVDX_CMDS,ALTERNATIVE_OUTPUT_PICTURE_ROTATION ,ROTATION_MODE, rotate_surface->extra_info[5]); + } + + psb_cmdbuf_rendec_start( cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION) ); + psb_cmdbuf_rendec_write(cmdbuf, alt_output_flags); + cmd = 0; + REGIO_WRITE_FIELD_LITE(cmd, MSVDX_CMDS, EXTENDED_ROW_STRIDE, EXT_ROW_STRIDE, target_surface->stride / 64 ); + psb_cmdbuf_rendec_write(cmdbuf, cmd); + psb_cmdbuf_rendec_end(cmdbuf); + *ctx->alt_output_flags = alt_output_flags; +} + +static void psb__VC1_send_rendec_params(context_VC1_p ctx, VASliceParameterBufferVC1 *slice_param) +{ + VAPictureParameterBufferVC1 *pic_params = ctx->pic_params; + psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf; + psb_surface_p deblock_surface = ctx->decoded_surface->psb_surface; + psb_surface_p target_surface = ctx->obj_context->current_render_target->psb_surface; + uint32_t cmd; + IMG_UINT32 ui32MBParamMemOffset; + IMG_UINT8 ui8PrevLumaScale = 0, ui8PrevLumaShift = 0; + IMG_UINT8 ui8BackLumaScale = 0, ui8BackLumaShift = 0; + IMG_UINT8 ui8PrevBotLumaShift = 0, ui8PrevBotLumaScale = 0; + IMG_UINT8 ui8PrevIC = 0, ui8BackIC = 0, ui8PrevBotIC = 0; + + /* Align MB Parameter memory */ + ui32MBParamMemOffset = ((pic_params->picture_fields.bits.frame_coding_mode == VC1_FCM_FLDI) && (!pic_params->picture_fields.bits.is_first_field)) ? + (ctx->size_mb * VC1_MB_PARAM_STRIDE) : 0; + ui32MBParamMemOffset += 0x00000fff; + ui32MBParamMemOffset &= 0xfffff000; + + /****************************** INTENSITY COMPENSATION ******************************/ + if(pic_params->picture_fields.bits.frame_coding_mode == VC1_FCM_FLDI) + { + if(pic_params->picture_fields.bits.picture_type == WMF_PTYPE_P) + { + if(pic_params->picture_fields.bits.top_field_first) // top field first + { + if(!pic_params->picture_fields.bits.is_first_field) // this is the second field picture (and bottom) + { + if(ctx->sICparams[0][1].ui8IC1 == 2) + { + /* The first and top field picture of the current frame + intensity compensates the bottom field of the previous frame. */ + ui8PrevLumaScale = ctx->sICparams[0][1].ui8LumaScale1; + ui8PrevLumaShift = ctx->sICparams[0][1].ui8LumaShift1; + ui8PrevIC = 2; + } + } + else // first field picture (and top) + { + if(ctx->sICparams[0][0].ui8IC1 == 1) + { + /* The second and bottom field picture of the previous frame + intensity compensates the top field of the previous frame. */ + ui8PrevLumaScale = ctx->sICparams[0][0].ui8LumaScale1; + ui8PrevLumaShift = ctx->sICparams[0][0].ui8LumaShift1; + ui8PrevIC = 1; + } + } + } + else // botom field first + { + if(!pic_params->picture_fields.bits.is_first_field) // this is the second field picture (and top) + { + if(ctx->sICparams[0][0].ui8IC1 == 1) + { + /* The first and bottom field picture of the current frame + intensity compensates the top field of the previous frame. */ + ui8PrevLumaScale = ctx->sICparams[0][0].ui8LumaScale1; + ui8PrevLumaShift = ctx->sICparams[0][0].ui8LumaShift1; + ui8PrevIC = 1; + } + } + else // first field picture (and bottom) + { + if(ctx->sICparams[0][1].ui8IC1 == 2) + { + /* The second and top field picture of the previous frame + intensity compensates the bottom field of the previous frame. */ + ui8PrevLumaScale = ctx->sICparams[0][1].ui8LumaScale1; + ui8PrevLumaShift = ctx->sICparams[0][1].ui8LumaShift1; + ui8PrevIC = 2; + } + } + } + } + else if(pic_params->picture_fields.bits.picture_type == WMF_PTYPE_B) + { + /* + First frame - second temporally closest reference frame to the B frame + Second frame - first temporally closest reference frame to the B frame + */ + if(pic_params->picture_fields.bits.top_field_first) // top field first + { + if(ctx->sICparams[0][0].ui8IC1 == 1) + { + /* The second and bottom field of the first reference frame intensity + compensates the first and top field of the first reference frame. */ + ui8PrevLumaScale = ctx->sICparams[0][0].ui8LumaScale1; + ui8PrevLumaShift = ctx->sICparams[0][0].ui8LumaShift1; + ui8PrevIC = 1; + } + if(ctx->sICparams[0][0].ui8IC2 == 1) + { + /* The first and top field of the second reference frame intensity + compensates the first and top field of the first reference frame. */ + ui8BackLumaScale = ctx->sICparams[0][0].ui8LumaScale2; + ui8BackLumaShift = ctx->sICparams[0][0].ui8LumaShift2; + ui8BackIC = 1; + } + if(ctx->sICparams[0][1].ui8IC2 == 2) + { + /* The first and top field of the second reference frame intensity + compensates the second and bottom field of the first reference frame. */ + ui8PrevBotLumaScale = ctx->sICparams[0][1].ui8LumaScale2; + ui8PrevBotLumaShift = ctx->sICparams[0][1].ui8LumaShift2; + ui8PrevBotIC = 2; + } + } + else // botom field first + { + if(ctx->sICparams[0][1].ui8IC1 == 2) + { + /* The second and top field of the first reference frame intensity + compensates the first and bottom field of the first reference frame. */ + ui8BackLumaScale = ctx->sICparams[0][1].ui8LumaScale1; + ui8BackLumaShift = ctx->sICparams[0][1].ui8LumaShift1; + ui8BackIC = 2; + } + if(ctx->sICparams[0][1].ui8IC2 == 2) + { + /* The first and bottom field of the second reference frame intensity + compensates the first and bottom field of the first reference frame. */ + ui8PrevBotLumaScale = ctx->sICparams[0][1].ui8LumaScale2; + ui8PrevBotLumaShift = ctx->sICparams[0][1].ui8LumaShift2; + ui8PrevBotIC = 2; + } + if(ctx->sICparams[0][0].ui8IC1 == 1) + { + /* The first and bottom field of the second reference frame intensity + compensates the second and top field of the first reference frame. */ + ui8PrevLumaScale = ctx->sICparams[0][0].ui8LumaScale1; + ui8PrevLumaShift = ctx->sICparams[0][0].ui8LumaShift1; + ui8PrevIC = 1; + } + } + } + } + /************************************************************************************/ + + /* psb_cmdbuf_rendec_start_block( cmdbuf ); */ + +// if(ctx->obj_context->rotate != VA_ROTATION_NONE) /* FIXME field coded should not issue */ +// psb__VC1_setup_alternative_frame(ctx); + + /* CHUNK: 1 - VC1SEQUENCE00 */ + psb_cmdbuf_rendec_start( cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, DISPLAY_PICTURE_SIZE) ); + *cmdbuf->rendec_chunk_start |= CMD_RENDEC_BLOCK_FLAG_VC1_CMD_PATCH; + + /* VC1SEQUENCE00 Command: Display Picture Size (sequence) */ + cmd = 0; + /* TODO: Can "display size" and "coded size" be different? */ + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SEQUENCE00, PICTURE_HEIGHT, (ctx->display_picture_height - 1)); /* display picture size - 1 */ + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SEQUENCE00, PICTURE_WIDTH, (ctx->display_picture_width - 1)); + psb_cmdbuf_rendec_write(cmdbuf, cmd); + + /* VC1SEQUENCE00 Command: Coded Picture Size (sequence) */ + cmd = 0; + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SEQUENCE00, PICTURE_HEIGHT, (ctx->coded_picture_height - 1)); /* coded picture size - 1 */ + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SEQUENCE00, PICTURE_WIDTH, (ctx->coded_picture_width - 1)); + psb_cmdbuf_rendec_write(cmdbuf, cmd); + + /* VC1SEQUENCE01 Command: Operating Mode (sequence) */ + cmd = 0; + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SEQUENCE01, CHROMA_INTERLEAVED, 0); /* 0 = CbCr - MSVDX default */ + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SEQUENCE01, ROW_STRIDE, target_surface->stride_mode); + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SEQUENCE01, CODEC_MODE, 2); /* MODE_VC1 */ + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SEQUENCE01, CODEC_PROFILE, ctx->profile); + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SEQUENCE01, ASYNC_MODE, 0/*((pPicParams->bPicDeblocked & 0x02) ? 0:1)*/); // @TODO: async mode should be synchronous or pre-load for VC1 + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SEQUENCE01, CHROMA_FORMAT, 1); + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SEQUENCE01, INTERLACED, ((pic_params->picture_fields.bits.frame_coding_mode & 0x02) >> 1)); /* if progressive, INTERLACE is always 0 */ + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SEQUENCE01, VC1_OVERLAP, pic_params->sequence_fields.bits.overlap); + if(!VC1_Header_Parser_HW) + { + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SEQUENCE01, PIC_CONDOVER, ctx->condover); + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SEQUENCE01, PIC_QUANT, pic_params->pic_quantizer_fields.bits.pic_quantizer_scale); + } + ctx->obj_context->operating_mode = cmd; + psb_cmdbuf_rendec_write(cmdbuf, cmd); + + /* LUMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES */ + psb_cmdbuf_rendec_write_address( cmdbuf, &target_surface->buf, target_surface->buf.buffer_ofs); + //psb_cmdbuf_rendec_write_address( cmdbuf, &deblock_surface->buf, deblock_surface->buf.buffer_ofs); + + /* CHROMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES */ + psb_cmdbuf_rendec_write_address( cmdbuf, &target_surface->buf, target_surface->buf.buffer_ofs + target_surface->chroma_offset); + //psb_cmdbuf_rendec_write_address( cmdbuf, &deblock_surface->buf, deblock_surface->buf.buffer_ofs + deblock_surface->chroma_offset); + + /* Aux MSB buffer */ + psb_cmdbuf_rendec_write_address( cmdbuf, &ctx->aux_msb_buffer, 0); + + psb_cmdbuf_rendec_end( cmdbuf ); + + /* CHUNK: 2 - VC1SLICE00 */ + psb_cmdbuf_rendec_start( cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, MC_CACHE_CONFIGURATION) ); + + /* VC1SLICE00 Command: Cache Configuration (picture?) */ + cmd = 0; + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SLICE00, CONFIG_REF_OFFSET, 72); + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SLICE00, CONFIG_ROW_OFFSET, 4); + psb_cmdbuf_rendec_write(cmdbuf, cmd); + + /* VC1SLICE01 Command: VC1 Intensity Compensation Parameter (picture or slice) */ + cmd = 0; + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SLICE01, VC1_LUMSHIFT2, ctx->ui8CurrLumaShift2); /* INTERLACE field P pictures */ + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SLICE01, VC1_LUMSCALE2, ctx->ui8CurrLumaScale2); /* INTERLACE field P pictures */ + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SLICE01, VC1_LUMSHIFT1, ctx->ui8CurrLumaShift1); + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SLICE01, VC1_LUMSCALE1, ctx->ui8CurrLumaScale1); + psb_cmdbuf_rendec_write(cmdbuf, cmd); + + psb_cmdbuf_rendec_end( cmdbuf ); + + psb__VC1_program_output_register(ctx, ctx->pic_params->picture_fields.bits.frame_coding_mode != VC1_FCM_P); + + if( ctx->pic_params->picture_fields.bits.frame_coding_mode == VC1_FCM_P && ctx->obj_context->rotate != VA_ROTATION_NONE) + //deblock_surface = ctx->decoded_surface->psb_surface_rotate; + deblock_surface = ctx->obj_context->current_render_target->psb_surface_rotate; + + /* CHUNK: 3 */ + psb_cmdbuf_rendec_start( cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, VC1_LUMA_RANGE_MAPPING_BASE_ADDRESS) ); + + /* VC1 Luma Range Mapping Base Address */ + //psb_cmdbuf_rendec_write_address( cmdbuf, &target_surface->buf, target_surface->buf.buffer_ofs); + psb_cmdbuf_rendec_write_address( cmdbuf, &deblock_surface->buf, deblock_surface->buf.buffer_ofs); + + /* VC1 Chroma Range Mapping Base Address */ + //psb_cmdbuf_rendec_write_address( cmdbuf, &target_surface->buf, target_surface->chroma_offset + target_surface->buf.buffer_ofs); + psb_cmdbuf_rendec_write_address( cmdbuf, &deblock_surface->buf, deblock_surface->chroma_offset + deblock_surface->buf.buffer_ofs); + + /* VC1SLICE03 Range Map Control (current picture) */ + cmd = 0; + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SLICE03, RANGE_MAPUV_FLAG, pic_params->range_mapping_fields.bits.chroma_flag /*RANGE_MAPUV_FLAG*/); + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SLICE03, RANGE_MAPUV, pic_params->range_mapping_fields.bits.chroma); + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SLICE03, RANGE_MAPY_FLAG, pic_params->range_mapping_fields.bits.luma_flag /*RANGE_MAPY_FLAG*/); + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SLICE03, RANGE_MAPY, pic_params->range_mapping_fields.bits.luma); + psb_cmdbuf_rendec_write(cmdbuf, cmd); + + /* Store VC1SLICE03 bits in lower bits of Range Mapping Base Address */ + /* VC1 Luma Range Mapping Base Address */ + RELOC(*ctx->p_range_mapping_base, /*cmd + */deblock_surface->buf.buffer_ofs, &deblock_surface->buf); + RELOC(*ctx->p_range_mapping_base1, deblock_surface->buf.buffer_ofs + deblock_surface->chroma_offset, &deblock_surface->buf); + //RELOC(*ctx->p_range_mapping_base, /*cmd + */target_surface->buf.buffer_ofs, &target_surface->buf); + //RELOC(*ctx->p_range_mapping_base1, target_surface->buf.buffer_ofs + target_surface->chroma_offset, &target_surface->buf); + *ctx->p_range_mapping_base = (*ctx->p_range_mapping_base) | cmd; /* FIXME If kernel apply reloc, this value may be override */ + + /* VC1 Intensity Compensation Backward/Previous */ + /* + 3.3.10 VC1 Intensity Compensation Backward/Previous: + The parameters applied in VC1 Intensity Compensation Parameters are the Intensity Compensation + applied to forward prediction. In the case of Interlaced P field pictures, the second field can + be Intensity Compensated relative to the first P field picture. If this is done, when decoding + B pictures the first field backward MV reference to P picture needs to be Intensity Compensated + with VC1_LUMSCALE_BACK and VC1_LUMSHIFT_BACK. (The command should contain the Intensity + Compensation parameters that were used for opposite parity field when decoding 2nd P field picture). + + The parameters will only be used if VC1_BACK_INT_COMP in Slice Params command indicates + Backward Intensity Compensation is used. + */ + cmd = 0; + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SLICE04, VC1_LUMSHIFT_PREV, ui8PrevLumaShift); + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SLICE04, VC1_LUMSCALE_PREV, ui8PrevLumaScale); + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SLICE04, VC1_LUMSHIFT_BACK, ui8BackLumaShift); + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SLICE04, VC1_LUMSCALE_BACK, ui8BackLumaScale); + psb_cmdbuf_rendec_write(cmdbuf, cmd); + +#if 0 + /* VC1 Intensity Compensation Previous Bottom */ + if(ui8PrevBotIC) + { + /* + The VDMC dynamically applies intensity compensation when generating reference predicted data + for P/B fields/frames. In the case of Interlaced B field pictures, both the top field and + bottom field could be Intensity Compensated twice (if all previous P field pictures applied + separate top and bottom Intensity Compensation). If this is the case, the VC1 previous field + defined in 3.3.10 should apply to top field, whilst the parameters defined in this register + apply to the bottom field. The VC1_PREV_BOT_INT_COMP field of Slice Params command indicates + if the fields in this register are used. + */ + cmd = 0; + REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, VC1_INTENSITY_COMPENSATION_, VC1_LUMSHIFT_PREV_BOT, ui8PrevBotLumaShift); + REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, VC1_INTENSITY_COMPENSATION_, VC1_LUMSCALE_PREV_BOT, ui8PrevBotLumaScale); + pcmdBuffer[i++] = REGISTER_OFFSET(MSVDX_CMDS, VC1_INTENSITY_COMPENSATION_); + pcmdBuffer[i++] = cmd; + } +#endif + psb_cmdbuf_rendec_end( cmdbuf ); + + /* + Reference Picture Base Addresses + + The reference picture pointers always include the current picture at first location (0) and + the oldest reference in the next location (1). For B pictures the subsequent reference + frame (display order) is 2. + */ + if((pic_params->picture_fields.bits.picture_type != WMF_PTYPE_I) && (pic_params->picture_fields.bits.picture_type != WMF_PTYPE_BI)) + { + /* CHUNK: 4 */ + psb_cmdbuf_rendec_start( cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, REFERENCE_PICTURE_BASE_ADDRESSES) ); + + /********************** CURRENT PICTURE **********************/ + 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 + target_surface->chroma_offset); + //psb_cmdbuf_rendec_write_address( cmdbuf, &deblock_surface->buf, deblock_surface->buf.buffer_ofs); + //psb_cmdbuf_rendec_write_address( cmdbuf, &deblock_surface->buf, deblock_surface->buf.buffer_ofs + deblock_surface->chroma_offset); + + /*************** FORWARD REFERENCE *****************/ + if(ctx->forward_ref_surface) + { + /* + In VC1, if a P field picture references both top field and bottom field, but the two fields + are stored in different frame stores, then the most recently decoded field will use reference + index 0, and the other field will use reference index 1. + + Progressive P pictures use always reference index 1. + */ + psb_cmdbuf_rendec_write_address( cmdbuf, &ctx->forward_ref_surface->psb_surface->buf, ctx->forward_ref_surface->psb_surface->buf.buffer_ofs); + psb_cmdbuf_rendec_write_address( cmdbuf, &ctx->forward_ref_surface->psb_surface->buf, ctx->forward_ref_surface->psb_surface->\ + buf.buffer_ofs + ctx->forward_ref_surface->psb_surface->chroma_offset); + } + + /*************** BACKWARD REFERENCE *****************/ + if (ctx->backward_ref_surface) + { + psb_cmdbuf_rendec_write_address( cmdbuf, &ctx->backward_ref_surface->psb_surface->buf, ctx->backward_ref_surface->psb_surface->buf.buffer_ofs); + psb_cmdbuf_rendec_write_address( cmdbuf, &ctx->backward_ref_surface->psb_surface->buf, ctx->backward_ref_surface->psb_surface\ + ->buf.buffer_ofs + ctx->backward_ref_surface->psb_surface->chroma_offset); + } + psb_cmdbuf_rendec_end( cmdbuf ); + } + + /* CHUNK: 5 - VC1SLICE02 */ + psb_cmdbuf_rendec_start( cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, SLICE_PARAMS) ); + *cmdbuf->rendec_chunk_start |= CMD_RENDEC_BLOCK_FLAG_VC1_SP_PATCH; + + /* VC1SLICE02 Command: Slice Params (picture or slice) */ + cmd = 0; + + //REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, SLICE_PARAMS, VC1_PREV_BOT_INT_COMP, ui8PrevBotIC); + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SLICE02, VC1_PREV_INT_COMP, ui8PrevIC); + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SLICE02, VC1_BACK_INT_COMP, ui8BackIC); + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SLICE02, RND_CTRL_BIT, pic_params->rounding_control); + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SLICE02, MODE_CONFIG, ctx->mode_config); + if(!VC1_Header_Parser_HW) + { + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SLICE02, SUBPEL_FILTER_MODE, ((ctx->mv_mode == WMF_MVMODE_1MV_HALF_PEL_BILINEAR) && !(pic_params->picture_fields.bits.frame_coding_mode == VC1_FCM_FRMI)) ? 0:1); + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SLICE02, SLICE_CODE_TYPE, (pic_params->picture_fields.bits.picture_type == WMF_PTYPE_BI) ? 0 : (pic_params->picture_fields.bits.picture_type & 0x3)); /* BI is sent as I */ + } + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SLICE02, VC1_FASTUVMC, pic_params->fast_uvmc_flag); + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SLICE02, VC1_LOOPFILTER, pic_params->entrypoint_fields.bits.loopfilter); + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SLICE02, SLICE_FIELD_TYPE, ctx->slice_field_type); + psb_cmdbuf_rendec_write(cmdbuf, cmd); + + psb_cmdbuf_rendec_end( cmdbuf ); + if(VC1_Header_Parser_HW) + REGIO_WRITE_FIELD(cmd, VC1_RENDEC_CMD, VC1SLICE02, SLICE_CODE_TYPE, (pic_params->picture_fields.bits.picture_type == WMF_PTYPE_BI) ? 0 : (pic_params->picture_fields.bits.picture_type & 0x3)); + + *ctx->p_slice_params = cmd; + + /* ------------------------------- Back-End Registers --------------------------------- */ + + /* CHUNK: 6 (Back-end registers) */ + psb_cmdbuf_rendec_start( cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_VEC, VC1_CR_VEC_VC1_BE_SPS0) ); + + /* CR_VEC_VC1_BE_SPS0 */ + cmd = 0; + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_SPS0, VC1_BE_EXTENDED_DMV, pic_params->mv_fields.bits.extended_dmv_flag); + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_SPS0, VC1_BE_EXTENDED_MV, pic_params->mv_fields.bits.extended_mv_flag); + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_SPS0, VC1_BE_FASTUVMC, pic_params->fast_uvmc_flag); + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_SPS0, VC1_BE_INTERLACE, pic_params->sequence_fields.bits.interlace); + //REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_SPS0, VC1_BE_PROFILE, ctx->profile); + psb_cmdbuf_rendec_write(cmdbuf, cmd); + + /* CR_VEC_VC1_BE_SPS1 */ + cmd = 0; + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_SPS1, VC1_BE_PIC_HEIGHT_IN_MBS_LESS1, ctx->picture_height_mb - 1); + psb_cmdbuf_rendec_write(cmdbuf, cmd); + + /* CR_VEC_VC1_BE_SPS2 */ + cmd = 0; + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_SPS2, VC1_BE_PIC_WIDTH_IN_MBS_LESS1, ctx->picture_width_mb - 1); + psb_cmdbuf_rendec_write(cmdbuf, cmd); + + psb_cmdbuf_rendec_end( cmdbuf ); + + /* CHUNK: 6b (Back-end registers) */ + psb_cmdbuf_rendec_start( cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_VEC, VC1_CR_VEC_VC1_BE_PPS2) ); + *cmdbuf->rendec_chunk_start |= CMD_RENDEC_BLOCK_FLAG_VC1_BE_PATCH; + + /* CR_VEC_VC1_BE_PPS2 */ + cmd = 0; + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_PPS2, VC1_BE_FCM_REF2, ctx->ui8FCM_Ref2Pic); + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_PPS2, VC1_BE_FCM_REF1, ctx->ui8FCM_Ref1Pic); + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_PPS2, VC1_BE_FCM_REF0, ctx->ui8FCM_Ref0Pic); + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_PPS2, VC1_BE_COLLOCATED_SKIPPED, 0); // @TODO: Really need this? + psb_cmdbuf_rendec_write(cmdbuf, cmd); + + /* CR_VEC_VC1_BE_PPS0 */ + cmd = 0; + if(!VC1_Header_Parser_HW) + { + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_PPS0, VC1_BE_IQ_OVERLAP, ((pic_params->picture_fields.bits.picture_type == WMF_PTYPE_B) || (ctx->condover == 0)) ? 0 : 1); + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_PPS0, VC1_BE_UNIFORM_QUANTIZER, pic_params->pic_quantizer_fields.bits.pic_quantizer_type); + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_PPS0, VC1_BE_HALFQP, pic_params->pic_quantizer_fields.bits.half_qp); + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_PPS0, VC1_BE_BFRACTION, pic_params->b_picture_fraction); + } + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_PPS0, VC1_BE_TFF_FWD, ctx->bTFF_FwRefFrm); + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_PPS0, VC1_BE_TFF_BWD, ctx->bTFF_BwRefFrm); + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_PPS0, VC1_BE_TFF, pic_params->picture_fields.bits.top_field_first); + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_PPS0, VC1_BE_SECOND_FIELD, !pic_params->picture_fields.bits.is_first_field); + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_PPS0, VC1_BE_FCM, pic_params->picture_fields.bits.frame_coding_mode); + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_PPS0, VC1_BE_RNDCTRL, pic_params->rounding_control); + psb_cmdbuf_rendec_write(cmdbuf, cmd); + + /* CR_VEC_VC1_BE_PPS1 */ + cmd = 0; + if(!VC1_Header_Parser_HW) + { + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_PPS1, VC1_BE_EXTEND_Y, ctx->extend_y); + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_PPS1, VC1_BE_EXTEND_X, ctx->extend_x); + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_PPS1, VC1_BE_QUANTIZER, (pic_params->pic_quantizer_fields.bits.pic_quantizer_type ? 0x03 /* uniform */ : 0x02 /* non-uniform */)); + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_PPS1, VC1_BE_PQUANT, pic_params->pic_quantizer_fields.bits.pic_quantizer_scale); + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_PPS1, VC1_BE_MVMODE, pic_params->mv_fields.bits.mv_mode); + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_PPS1, VC1_BE_MVMODE2, pic_params->mv_fields.bits.mv_mode2); + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_PPS1, VC1_BE_PTYPE, pic_params->picture_fields.bits.picture_type); + } + psb_cmdbuf_rendec_write(cmdbuf, cmd); + + /* CR_VEC_VC1_BE_MVD0 */ + cmd = 0; + if(!VC1_Header_Parser_HW) + { + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_MVD0, VC1_BE_BRPD, ctx->i8BckwrdRefFrmDist); /* 10.4.6.2 */ + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_MVD0, VC1_BE_FRPD, ctx->i8FwrdRefFrmDist); + } + psb_cmdbuf_rendec_write(cmdbuf, cmd); + + /* CR_VEC_VC1_BE_MVD1 */ + cmd = 0; + if(!VC1_Header_Parser_HW) + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_MVD1, VC1_BE_SCALEFACTOR, ctx->ui32ScaleFactor); /* figure 66 */ + psb_cmdbuf_rendec_write(cmdbuf, cmd); + + /* CR_VEC_VC1_BE_MVD2 */ + cmd = 0; + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_MVD2, VC1_BE_PULLBACK_X, ctx->pull_back_x); + psb_cmdbuf_rendec_write(cmdbuf, cmd); + + /* CR_VEC_VC1_BE_MVD3 */ + cmd = 0; + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_MVD3, VC1_BE_PULLBACK_Y, ctx->pull_back_y); + psb_cmdbuf_rendec_write(cmdbuf, cmd); + + /* CR_VEC_VC1_BE_MVD4 */ + cmd = 0; + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_MVD4, VC1_BE_FIRST_MB_IN_SLICE_Y, slice_param->slice_vertical_position); + psb_cmdbuf_rendec_write(cmdbuf, cmd); + + /* CR_VEC_VC1_BE_MVD5 */ + cmd = 0; + if(!VC1_Header_Parser_HW) + { + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_MVD5, VC1_BE_REFDIST, pic_params->reference_fields.bits.reference_distance); + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_MVD5, VC1_BE_NUMREF, pic_params->reference_fields.bits.num_reference_pictures); + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_MVD5, VC1_BE_REFFIELD, pic_params->reference_fields.bits.reference_field_pic_indicator); + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_MVD5, VC1_BE_MVRANGE, pic_params->mv_fields.bits.extended_mv_range); + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_MVD5, VC1_BE_HALFPEL_FLAG, ctx->half_pel); + } + //REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_MVD5, VC1_BE_FRAME_CODING_MODE, pic_params->picture_fields.bits.frame_coding_mode); + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_MVD5, VC1_BE_BOTTOM_FIELD_FLAG, ctx->bottom_field); + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_MVD5, VC1_BE_ADVANCED_PROFILE, (ctx->profile == WMF_PROFILE_ADVANCED) ? 1:0); + REGIO_WRITE_FIELD(cmd, MSVDX_VEC_VC1, CR_VEC_VC1_BE_MVD5, VC1_BE_SCAN_INDEX, ctx->scan_index); + psb_cmdbuf_rendec_write(cmdbuf, cmd); + + psb_cmdbuf_rendec_end( cmdbuf ); + + /* CHUNK: 6c (Back-end registers) */ + psb_cmdbuf_rendec_start( cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_VEC, VC1_CR_VEC_VC1_BE_PARAM_BASE_ADDR) ); + + psb__information_message("pnw_VC1: picture_type = %d\n", pic_params->picture_fields.bits.picture_type); + + if(PIC_TYPE_IS_INTRA(pic_params->picture_fields.bits.picture_type) || (pic_params->picture_fields.bits.picture_type == WMF_PTYPE_P)) + { + psb_buffer_p colocated_target_buffer = psb__VC1_lookup_colocated_buffer(ctx, target_surface); + ASSERT(colocated_target_buffer); + if (colocated_target_buffer) + { + psb_cmdbuf_rendec_write_address(cmdbuf, colocated_target_buffer, ui32MBParamMemOffset); + } + else + { + /* This is an error */ + psb_cmdbuf_rendec_write(cmdbuf, 0); + } + } + else if(pic_params->picture_fields.bits.picture_type == WMF_PTYPE_B) + { + ASSERT(ctx->forward_ref_surface); + psb_buffer_p colocated_forward_ref_buffer = ctx->forward_ref_surface ? psb__VC1_lookup_colocated_buffer(ctx, ctx->forward_ref_surface->psb_surface) : 0; + ASSERT(colocated_forward_ref_buffer); + if (colocated_forward_ref_buffer) + { + psb_cmdbuf_rendec_write_address(cmdbuf, colocated_forward_ref_buffer, ui32MBParamMemOffset); + } + else + { + /* This is an error */ + psb_cmdbuf_rendec_write(cmdbuf, 0); + } + } + psb_cmdbuf_rendec_end( cmdbuf ); + + if(!PIC_TYPE_IS_INTRA(pic_params->picture_fields.bits.picture_type)) + { + /* CHUNK: 6d (Back-end registers) */ + psb_cmdbuf_rendec_start( cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_VEC, VC1_CR_VEC_VC1_BE_COLPARAM_BASE_ADDR) ); + + if(pic_params->picture_fields.bits.picture_type == WMF_PTYPE_P) + { + /* CR_VEC_VC1_BE_COLPARAM_BASE_ADDR */ + ASSERT(ctx->forward_ref_surface); + psb_buffer_p colocated_forward_ref_buffer = ctx->forward_ref_surface ? psb__VC1_lookup_colocated_buffer(ctx, ctx->forward_ref_surface->psb_surface) : NULL; + ASSERT(colocated_forward_ref_buffer); + if (colocated_forward_ref_buffer) + { + psb_cmdbuf_rendec_write_address(cmdbuf, colocated_forward_ref_buffer, ui32MBParamMemOffset); + } + else + { + /* This is an error */ + psb_cmdbuf_rendec_write(cmdbuf, 0); + } + } + else if(pic_params->picture_fields.bits.picture_type == WMF_PTYPE_B) + { + /* CR_VEC_VC1_BE_COLPARAM_BASE_ADDR */ + ASSERT(ctx->backward_ref_surface); + psb_buffer_p colocated_backward_ref_buffer; + + if (NULL == ctx->backward_ref_surface) + { + psb__error_message("%s L%d Invalid backward_ref_surface handle\n", __FUNCTION__, __LINE__); + return; + } + + colocated_backward_ref_buffer = ctx->backward_ref_surface->psb_surface ? psb__VC1_lookup_colocated_buffer(ctx, ctx->backward_ref_surface->psb_surface) : NULL; + ASSERT(colocated_backward_ref_buffer); + if (colocated_backward_ref_buffer) + { + psb_cmdbuf_rendec_write_address(cmdbuf, colocated_backward_ref_buffer, ui32MBParamMemOffset); + } + else + { + /* This is an error */ + psb_cmdbuf_rendec_write(cmdbuf, 0); + } + } + + psb_cmdbuf_rendec_end( cmdbuf ); + } + + /* psb_cmdbuf_rendec_end_block( cmdbuf ); */ +} + + +static void psb__VC1_load_sequence_registers(context_VC1_p ctx) +{ + psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf; + uint32_t reg_value; + + psb_cmdbuf_reg_start_block( cmdbuf ); + + /* FE_CONTROL */ + reg_value = 0; + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_ENTDEC_FE_CONTROL, ENTDEC_FE_PROFILE, ctx->profile); + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_ENTDEC_FE_CONTROL, ENTDEC_FE_MODE, 2); /* 2 - VC1 */ + psb_cmdbuf_reg_set( cmdbuf, REGISTER_OFFSET (MSVDX_VEC, CR_VEC_ENTDEC_FE_CONTROL), reg_value ); + + /* FE_SPS0 */ + reg_value = 0; + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_SPS0, VC1_FE_SYNCMARKER, ctx->pic_params->sequence_fields.bits.syncmarker ); + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_SPS0, VC1_FE_VSTRANSFORM, ctx->pic_params->transform_fields.bits.variable_sized_transform_flag); + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_SPS0, VC1_FE_INTERLACE, ctx->pic_params->sequence_fields.bits.interlace ); + psb_cmdbuf_reg_set( cmdbuf, REGISTER_OFFSET (MSVDX_VEC_VC1, CR_VEC_VC1_FE_SPS0), reg_value ); + + psb_cmdbuf_reg_end_block( cmdbuf ); + +} + +static void psb__VC1_load_picture_registers(context_VC1_p ctx, VASliceParameterBufferVC1 *slice_param) +{ + VAPictureParameterBufferVC1 *pic_params = ctx->pic_params; + psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf; + uint32_t reg_value; + int bEnableMVDLite = FALSE; + + psb_cmdbuf_rendec_start( cmdbuf, REG_MSVDX_VEC_OFFSET + MSVDX_VEC_CR_VEC_ENTDEC_BE_CONTROL_OFFSET ); + reg_value = 0; + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_ENTDEC_BE_CONTROL, ENTDEC_BE_PROFILE, ctx->profile); + REGIO_WRITE_FIELD( reg_value, MSVDX_VEC, CR_VEC_ENTDEC_BE_CONTROL, ENTDEC_BE_MODE, 2); /* 2 - VC1 */ + psb_cmdbuf_rendec_write( cmdbuf, reg_value ); + psb_cmdbuf_rendec_end( cmdbuf ); + + psb_cmdbuf_reg_start_block_flag( cmdbuf, (VC1_Header_Parser_HW) ? CMD_REGVALPAIR_FLAG_VC1PATCH : 0); + + /* Enable MVD lite for Progressive or FLDI P */ + if( + ( + (pic_params->sequence_fields.bits.interlace && (pic_params->picture_fields.bits.frame_coding_mode == VC1_FCM_FLDI)) || + (!pic_params->sequence_fields.bits.interlace) || + (pic_params->sequence_fields.bits.interlace && (pic_params->picture_fields.bits.frame_coding_mode == VC1_FCM_P)) + ) && + (pic_params->picture_fields.bits.picture_type == WMF_PTYPE_P) + ) + { + bEnableMVDLite = TRUE; + } + + /* FE_PPS0 */ + reg_value = 0; + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS0, VC1_FE_PIC_WIDTH_IN_MBS_LESS1, ctx->picture_width_mb - 1); + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS0, VC1_FE_PIC_HEIGHT_IN_MBS_LESS1, ctx->picture_height_mb - 1); + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS0, VC1_FE_FIRST_MB_IN_SLICE_Y, slice_param->slice_vertical_position); + if(!VC1_Header_Parser_HW) + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS0, VC1_FE_PTYPE, pic_params->picture_fields.bits.picture_type); + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS0, VC1_FE_FCM, pic_params->picture_fields.bits.frame_coding_mode); + psb_cmdbuf_reg_set( cmdbuf, REGISTER_OFFSET(MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS0), reg_value ); + + /* FE_PPS1 */ + reg_value = 0; + if(!VC1_Header_Parser_HW) + { + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS1, VC1_FE_BP_FORMAT, IMG_FALSE); // interleaved format + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS1, VC1_FE_BP_PRESENT, ctx->bitplane_present); + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS1, VC1_FE_RAWCODINGFLAG, (pic_params->raw_coding.value & 0x7F)); // 7-bits + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS1, VC1_FE_MVMODE, pic_params->mv_fields.bits.mv_mode); + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS1, VC1_FE_MVMODE2, pic_params->mv_fields.bits.mv_mode2); + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS1, VC1_FE_TTMBF, pic_params->transform_fields.bits.mb_level_transform_type_flag); + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS1, VC1_FE_TTFRM, pic_params->transform_fields.bits.frame_level_transform_type); + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS1, VC1_FE_BFRACTION, pic_params->b_picture_fraction); + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS1, VC1_FE_CONDOVER, ctx->condover); + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS1, VC1_FE_EXTEND_X, ctx->extend_x); + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS1, VC1_FE_EXTEND_Y, ctx->extend_y); + } + psb_cmdbuf_reg_set( cmdbuf, REGISTER_OFFSET(MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS1), reg_value ); + + /* FE_PPS2 */ + reg_value = 0; + if(!VC1_Header_Parser_HW) + { + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS2, VC1_FE_DQXBEDGE, (pic_params->pic_quantizer_fields.bits.dq_profile == 1) ? pic_params->pic_quantizer_fields.bits.dq_db_edge : pic_params->pic_quantizer_fields.bits.dq_sb_edge); + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS2, VC1_FE_DQUANT, pic_params->pic_quantizer_fields.bits.dquant); + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS2, VC1_FE_PQUANT, pic_params->pic_quantizer_fields.bits.pic_quantizer_scale); + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS2, VC1_FE_HALFQP, pic_params->pic_quantizer_fields.bits.half_qp); + if (((ctx->profile == WMF_PROFILE_ADVANCED) && (pic_params->pic_quantizer_fields.bits.dquant != 0)) + || ((ctx->profile != WMF_PROFILE_ADVANCED) && ((pic_params->picture_fields.bits.picture_type == WMF_PTYPE_B) || (pic_params->picture_fields.bits.picture_type == WMF_PTYPE_P))) && (pic_params->pic_quantizer_fields.bits.dquant != 0)) + { + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS2, VC1_FE_VOPDQUANT_PRESENT, 1); + } + else + { + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS2, VC1_FE_VOPDQUANT_PRESENT, 0); + } + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS2, VC1_FE_DQUANTFRM, pic_params->pic_quantizer_fields.bits.dq_frame); + { + IMG_BOOL DQUANT_INFRAME = (pic_params->pic_quantizer_fields.bits.dquant == 2) || + ((pic_params->pic_quantizer_fields.bits.dquant == 1) && pic_params->pic_quantizer_fields.bits.dq_frame) || + ((pic_params->pic_quantizer_fields.bits.dquant == 3) && pic_params->pic_quantizer_fields.bits.dq_frame); + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS2, VC1_FE_DQUANT_INFRAME, DQUANT_INFRAME); + } + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS2, VC1_FE_ALTPQUANT, pic_params->pic_quantizer_fields.bits.alt_pic_quantizer); + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS2, VC1_FE_DQPROFILE, pic_params->pic_quantizer_fields.bits.dq_profile); + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS2, VC1_FE_DQBILEVEL, pic_params->pic_quantizer_fields.bits.dq_binary_level); + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS2, VC1_FE_PQINDEX_GT8, ctx->pqindex_gt8 ); + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS2, VC1_FE_TRANSACFRM, pic_params->transform_fields.bits.transform_ac_codingset_idx1); + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS2, VC1_FE_TRANSACFRM2, pic_params->transform_fields.bits.transform_ac_codingset_idx2); + } + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS2, VC1_FE_DQUANT, pic_params->pic_quantizer_fields.bits.dquant); + psb_cmdbuf_reg_set( cmdbuf, REGISTER_OFFSET(MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS2), reg_value ); + + /* MVD_LITE0 */ + reg_value = 0; + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_MVD_LITE0, VC1_FE_MVD_LITE_ENABLE, bEnableMVDLite); + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_MVD_LITE0, VC1_FE_PULLBACK_X, ctx->pull_back_x); + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_MVD_LITE0, VC1_FE_PULLBACK_Y, ctx->pull_back_y); + psb_cmdbuf_reg_set( cmdbuf, REGISTER_OFFSET(MSVDX_VEC_VC1, CR_VEC_VC1_FE_MVD_LITE0), reg_value ); + + /* MVD_LITE1 */ + reg_value = 0; + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_MVD_LITE1, VC1_FE_TFF, pic_params->picture_fields.bits.top_field_first); + if(!VC1_Header_Parser_HW) + { + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_MVD_LITE1, VC1_FE_REFDIST, pic_params->reference_fields.bits.reference_distance); + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_MVD_LITE1, VC1_FE_NUMREF, pic_params->reference_fields.bits.num_reference_pictures); + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_MVD_LITE1, VC1_FE_REFFIELD, pic_params->reference_fields.bits.reference_field_pic_indicator); + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_MVD_LITE1, VC1_FE_MVRANGE, pic_params->mv_fields.bits.extended_mv_range); + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_MVD_LITE1, VC1_FE_HALFPEL_FLAG, ctx->half_pel); + //REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_MVD_LITE1, VC1_FE_FRAME_CODING_MODE, pic_params->picture_fields.bits.frame_coding_mode); + } + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_MVD_LITE1, VC1_FE_BOTTOM_FIELD_FLAG, ctx->bottom_field); + REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_MVD_LITE1, VC1_FE_ADVANCED_PROFILE, (ctx->profile == WMF_PROFILE_ADVANCED) ? 1:0); + psb_cmdbuf_reg_set( cmdbuf, REGISTER_OFFSET(MSVDX_VEC_VC1, CR_VEC_VC1_FE_MVD_LITE1), reg_value ); + + psb_cmdbuf_reg_end_block( cmdbuf ); +} + +static void psb__VC1_setup_bitplane(context_VC1_p ctx) +{ + psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf; + + psb_cmdbuf_reg_start_block( cmdbuf ); + + if(VC1_Header_Parser_HW) + { + psb_cmdbuf_reg_set_address( cmdbuf, REGISTER_OFFSET(MSVDX_VEC_VC1, CR_VEC_VC1_FE_BITPLANES_BASE_ADDR0), + &ctx->bitplane_hw_buffer, 0); + psb_cmdbuf_reg_set_address( cmdbuf, REGISTER_OFFSET(MSVDX_VEC_VC1, CR_VEC_VC1_FE_BITPLANES_BASE_ADDR1), + &ctx->bitplane_hw_buffer, 0xa000); + psb_cmdbuf_reg_set_address( cmdbuf, REGISTER_OFFSET(MSVDX_VEC_VC1, CR_VEC_VC1_FE_BITPLANES_BASE_ADDR2), + &ctx->bitplane_hw_buffer, 0xa000 * 2); + } + else + { + if (ctx->bitplane_present) + psb_cmdbuf_reg_set_address( cmdbuf, REGISTER_OFFSET(MSVDX_VEC_VC1, CR_VEC_VC1_FE_BITPLANES_BASE_ADDR0), + ctx->bitplane_buffer, 0); + else + psb_cmdbuf_reg_set( cmdbuf, REGISTER_OFFSET(MSVDX_VEC_VC1, CR_VEC_VC1_FE_BITPLANES_BASE_ADDR0), 0); + } + psb_cmdbuf_reg_end_block( cmdbuf ); +} + +//static void psb__VC1_FE_state(context_VC1_p ctx) +//{ +// uint32_t lldma_record_offset; +// psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf; +// psb_surface_p deblock_surface = ctx->decoded_surface->psb_surface; + + /* See RENDER_BUFFER_HEADER */ +// *cmdbuf->cmd_idx++ = CMD_HEADER_VC1; + +// ctx->p_range_mapping_base = cmdbuf->cmd_idx++; /* Fill Luma Range Mapping Base later */ + + /* VC1 Chroma Range Mapping Base Address */ +// RELOC(*cmdbuf->cmd_idx++, deblock_surface->buf.buffer_ofs + deblock_surface->chroma_offset, &deblock_surface->buf); + +// ctx->p_slice_params = cmdbuf->cmd_idx; +// *cmdbuf->cmd_idx++ = 0; /* ui32SliceParams */ + +// lldma_record_offset = psb_cmdbuf_lldma_create( cmdbuf, &ctx->preload_buffer, 0, +// sizeof( VC1PRELOAD ), 0, LLDMA_TYPE_VC1_PRELOAD_SAVE ); +// RELOC(*cmdbuf->cmd_idx, lldma_record_offset, &(cmdbuf->buf)); +// cmdbuf->cmd_idx++; + +// lldma_record_offset = psb_cmdbuf_lldma_create( cmdbuf, &ctx->preload_buffer, 0, +// sizeof( VC1PRELOAD ), 0, LLDMA_TYPE_VC1_PRELOAD_RESTORE ); +// RELOC(*cmdbuf->cmd_idx, lldma_record_offset, &(cmdbuf->buf)); +// cmdbuf->cmd_idx++; + +// ctx->slice_first_pic_last = cmdbuf->cmd_idx++; +//} +static void psb__VC1_FE_state(context_VC1_p ctx) +{ + uint32_t lldma_record_offset; + psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf; + uint32_t preload_size; + + if(VC1_Header_Parser_HW) + preload_size = FWPARSER_VC1PRELOAD_SIZE; + else + preload_size = sizeof( VC1PRELOAD ); + //psb_surface_p deblock_surface = ctx->decoded_surface->psb_surface; + + *cmdbuf->cmd_idx++ = CMD_HEADER_VC1; + ctx->p_slice_params = cmdbuf->cmd_idx; + *cmdbuf->cmd_idx++ = 0; + + lldma_record_offset = psb_cmdbuf_lldma_create( cmdbuf, &ctx->preload_buffer, 0, + preload_size, 0, LLDMA_TYPE_VC1_PRELOAD_SAVE ); + RELOC(*cmdbuf->cmd_idx, lldma_record_offset, &(cmdbuf->buf)); + cmdbuf->cmd_idx++; + + lldma_record_offset = psb_cmdbuf_lldma_create( cmdbuf, &ctx->preload_buffer, 0, + preload_size, 0, LLDMA_TYPE_VC1_PRELOAD_RESTORE ); + RELOC(*cmdbuf->cmd_idx, lldma_record_offset, &(cmdbuf->buf)); + cmdbuf->cmd_idx++; + + ctx->slice_first_pic_last = cmdbuf->cmd_idx++; + + ctx->p_range_mapping_base = cmdbuf->cmd_idx++; + ctx->p_range_mapping_base1 = cmdbuf->cmd_idx++; + //RELOC(*cmdbuf->cmd_idx++, deblock_surface->buf.buffer_ofs + deblock_surface->chroma_offset, &deblock_surface->buf); + + ctx->alt_output_flags = cmdbuf->cmd_idx++; + *ctx->alt_output_flags = 0; +} + +static void psb__VC1_Send_Parse_Header_Cmd(context_VC1_p ctx, IMG_BOOL new_pic) +{ + PARSE_HEADER_CMD* pParseHeaderCMD; + VAPictureParameterBufferVC1 *pic_params = ctx->pic_params; + psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf; + + //pParseHeaderCMD = (PARSE_HEADER_CMD*)mCtrlAlloc.AllocateSpace(sizeof(PARSE_HEADER_CMD)); + pParseHeaderCMD = (void *)cmdbuf->cmd_idx; + cmdbuf->cmd_idx += sizeof(PARSE_HEADER_CMD)/sizeof(uint32_t); + + pParseHeaderCMD->ui32Cmd = CMD_PARSE_HEADER; + if(!new_pic) + { + pParseHeaderCMD->ui32Cmd |= CMD_PARSE_HEADER_NEWSLICE; + } + +// pParseHeaderCMD->ui32SeqHdrData = (sVC1HeaderParser.sSeqHdr.EXTENDED_DMV&0x1) << VC1_SEQHDR_EXTENDED_DMV; + pParseHeaderCMD->ui32SeqHdrData = (pic_params->mv_fields.bits.extended_dmv_flag) << VC1_SEQHDR_EXTENDED_DMV; + +// pParseHeaderCMD->ui32SeqHdrData |= (sVC1HeaderParser.sSeqHdr.PSF&0x1) << VC1_SEQHDR_PSF; + pParseHeaderCMD->ui32SeqHdrData |= (pic_params->sequence_fields.bits.psf) << VC1_SEQHDR_PSF; + +// pParseHeaderCMD->ui32SeqHdrData |= (sVC1HeaderParser.sSeqHdr.FINTERPFLAG&0x1) << VC1_SEQHDR_FINTERPFLAG; + pParseHeaderCMD->ui32SeqHdrData |= (pic_params->sequence_fields.bits.finterpflag) << VC1_SEQHDR_FINTERPFLAG; + +// pParseHeaderCMD->ui32SeqHdrData |= (sVC1HeaderParser.sSeqHdr.TFCNTRFLAG&0x1) << VC1_SEQHDR_TFCNTRFLAG; + pParseHeaderCMD->ui32SeqHdrData |= (pic_params->sequence_fields.bits.tfcntrflag) << VC1_SEQHDR_TFCNTRFLAG;; + +// pParseHeaderCMD->ui32SeqHdrData |= (sVC1HeaderParser.sSeqHdr.INTERLACE&0x1) << VC1_SEQHDR_INTERLACE; + pParseHeaderCMD->ui32SeqHdrData |= (pic_params->sequence_fields.bits.interlace) << VC1_SEQHDR_INTERLACE; + +// pParseHeaderCMD->ui32SeqHdrData |= (sVC1HeaderParser.sSeqHdr.PULLDOWN&0x1) << VC1_SEQHDR_PULLDOWN; + pParseHeaderCMD->ui32SeqHdrData |= (pic_params->sequence_fields.bits.pulldown) << VC1_SEQHDR_PULLDOWN; + +// pParseHeaderCMD->ui32SeqHdrData |= (sVC1HeaderParser.sSeqHdr.POSTPROCFLAG&0x1) << VC1_SEQHDR_POSTPROCFLAG; + pParseHeaderCMD->ui32SeqHdrData |= (pic_params->post_processing & 0x1) << VC1_SEQHDR_POSTPROCFLAG; + +// pParseHeaderCMD->ui32SeqHdrData |= (sVC1HeaderParser.sSeqHdr.VSTRANSFORM&0x1) << VC1_SEQHDR_VSTRANSFORM; + pParseHeaderCMD->ui32SeqHdrData |= (pic_params->transform_fields.bits.variable_sized_transform_flag) << VC1_SEQHDR_VSTRANSFORM; + +// pParseHeaderCMD->ui32SeqHdrData |= (rser.sSeqHdr.DQUANT&0x3) << VC1_SEQHDR_DQUANT; + pParseHeaderCMD->ui32SeqHdrData |= (pic_params->pic_quantizer_fields.bits.dquant) << VC1_SEQHDR_DQUANT; + +// pParseHeaderCMD->ui32SeqHdrData |= (sVC1HeaderParser.sSeqHdr.EXTENDED_MV&0x1) << VC1_SEQHDR_EXTENDED_MV; + pParseHeaderCMD->ui32SeqHdrData |= (pic_params->mv_fields.bits.extended_mv_flag)<< VC1_SEQHDR_EXTENDED_MV; + +// pParseHeaderCMD->ui32SeqHdrData |= (sVC1HeaderParser.sSeqHdr.FASTUVMC&0x1) << VC1_SEQHDR_FASTUVMC; + pParseHeaderCMD->ui32SeqHdrData |= (pic_params->fast_uvmc_flag & 0x1) << VC1_SEQHDR_FASTUVMC; + +// pParseHeaderCMD->ui32SeqHdrData |= (sVC1HeaderParser.sSeqHdr.LOOPFILTER&0x1) << VC1_SEQHDR_LOOPFILTER; + pParseHeaderCMD->ui32SeqHdrData |= (pic_params->entrypoint_fields.bits.loopfilter) << VC1_SEQHDR_LOOPFILTER; + +// pParseHeaderCMD->ui32SeqHdrData |= (sVC1HeaderParser.sSeqHdr.REFDIST_FLAG&0x1) << VC1_SEQHDR_REFDIST_FLAG; + pParseHeaderCMD->ui32SeqHdrData |= (pic_params->reference_fields.bits.reference_distance_flag) << VC1_SEQHDR_REFDIST_FLAG; + +// pParseHeaderCMD->ui32SeqHdrData |= (sVC1HeaderParser.sSeqHdr.PANSCAN_FLAG&0x1) << VC1_SEQHDR_PANSCAN_FLAG; + pParseHeaderCMD->ui32SeqHdrData |= (pic_params->entrypoint_fields.bits.panscan_flag) << VC1_SEQHDR_PANSCAN_FLAG; + +// pParseHeaderCMD->ui32SeqHdrData |= (sVC1HeaderParser.sSeqHdr.MAXBFRAMES&0x7) << VC1_SEQHDR_MAXBFRAMES; + pParseHeaderCMD->ui32SeqHdrData |= (pic_params->sequence_fields.bits.max_b_frames) << VC1_SEQHDR_MAXBFRAMES; + +// pParseHeaderCMD->ui32SeqHdrData |= (sVC1HeaderParser.sSeqHdr.RANGERED&0x1) << VC1_SEQHDR_RANGERED; + pParseHeaderCMD->ui32SeqHdrData |= (pic_params->sequence_fields.bits.rangered) << VC1_SEQHDR_RANGERED; + +// pParseHeaderCMD->ui32SeqHdrData |= (sVC1HeaderParser.sSeqHdr.SYNCMARKER&0x1) << VC1_SEQHDR_SYNCMARKER; + pParseHeaderCMD->ui32SeqHdrData |= (pic_params->sequence_fields.bits.syncmarker) << VC1_SEQHDR_SYNCMARKER; + +// pParseHeaderCMD->ui32SeqHdrData |= (sVC1HeaderParser.sSeqHdr.MULTIRES&0x1) << VC1_SEQHDR_MULTIRES; + pParseHeaderCMD->ui32SeqHdrData |= (pic_params->sequence_fields.bits.multires) << VC1_SEQHDR_MULTIRES; + +// pParseHeaderCMD->ui32SeqHdrData |= (sVC1HeaderParser.sSeqHdr.QUANTIZER&0x3) << VC1_SEQHDR_QUANTIZER; + pParseHeaderCMD->ui32SeqHdrData |= (pic_params->pic_quantizer_fields.bits.quantizer) << VC1_SEQHDR_QUANTIZER; + +// pParseHeaderCMD->ui32SeqHdrData |= (sVC1HeaderParser.sSeqHdr.OVERLAP&0x1) << VC1_SEQHDR_OVERLAP; + pParseHeaderCMD->ui32SeqHdrData |= (pic_params->sequence_fields.bits.overlap) << VC1_SEQHDR_OVERLAP; + +// pParseHeaderCMD->ui32SeqHdrData |= (sVC1HeaderParser.sSeqHdr.PROFILE&0x3) << VC1_SEQHDR_PROFILE; + pParseHeaderCMD->ui32SeqHdrData |= (ctx->profile) << VC1_SEQHDR_PROFILE; + +// pParseHeaderCMD->ui32SeqHdrData |= (msPicParam.bSecondField&0x1) << VC1_SEQHDR_SECONDFIELD; + pParseHeaderCMD->ui32SeqHdrData |= (!pic_params->picture_fields.bits.is_first_field) << VC1_SEQHDR_SECONDFIELD; + +// pParseHeaderCMD->ui32SeqHdrData |= (mpDestFrame->FrameCodingMode()&0x3) << VC1_SEQHDR_FCM_CURRPIC; + pParseHeaderCMD->ui32SeqHdrData |= (pic_params->picture_fields.bits.frame_coding_mode & 0x3) << VC1_SEQHDR_FCM_CURRPIC; + +// pParseHeaderCMD->ui32SeqHdrData |= (mui8PicType&0x3) << VC1_SEQHDR_PICTYPE; + pParseHeaderCMD->ui32SeqHdrData |= (pic_params->picture_fields.bits.picture_type & 0x3) << VC1_SEQHDR_PICTYPE; + +// pParseHeaderCMD->ui32SeqHdrData |= ((msPicParam.bBidirectionalAveragingMode>>4)&0x1) << VC1_SEQHDR_ICFLAG; + pParseHeaderCMD->ui32SeqHdrData |= (pic_params->picture_fields.bits.intensity_compensation) << VC1_SEQHDR_ICFLAG; + + pParseHeaderCMD->ui32PicDimensions = ctx->picture_width_mb; + pParseHeaderCMD->ui32PicDimensions |= (ctx->picture_height_mb << 16); + +// pParseHeaderCMD->ui32BitplaneAddr[0] = (psBitplaneHWBuffer[0]->GetTopDeviceMemAlloc())->GetDeviceVirtAddress(); +// pParseHeaderCMD->ui32BitplaneAddr[1] = (psBitplaneHWBuffer[1]->GetTopDeviceMemAlloc())->GetDeviceVirtAddress(); +// pParseHeaderCMD->ui32BitplaneAddr[2] = (psBitplaneHWBuffer[2]->GetTopDeviceMemAlloc())->GetDeviceVirtAddress(); + RELOC(pParseHeaderCMD->ui32BitplaneAddr[0], ctx->bitplane_hw_buffer.buffer_ofs, &ctx->bitplane_hw_buffer); + RELOC(pParseHeaderCMD->ui32BitplaneAddr[1], ctx->bitplane_hw_buffer.buffer_ofs + 0xa000, &ctx->bitplane_hw_buffer); + RELOC(pParseHeaderCMD->ui32BitplaneAddr[2], ctx->bitplane_hw_buffer.buffer_ofs + 0xa000*2, &ctx->bitplane_hw_buffer); + +// pParseHeaderCMD->ui32VLCTableAddr = psVlcPackedTableData->GetTopDeviceMemAlloc()->GetDeviceVirtAddress(); + RELOC(pParseHeaderCMD->ui32VLCTableAddr, ctx->vlc_packed_table.buffer_ofs, &ctx->vlc_packed_table); + /* + pParseHeaderCMD->ui32ICParamData[0] = ((msPicParam.wBitstreamFcodes >> 8) & 0xFF); + pParseHeaderCMD->ui32ICParamData[0] |= ((msPicParam.wBitstreamPCEelements >> 8) & 0xFF) << 8; + if( mpForwardRefFrame->TopFieldFirst() ) + pParseHeaderCMD->ui32ICParamData[0] |= (1 << 16); + */ + pParseHeaderCMD->ui32ICParamData[0] = ((pic_params->luma_scale >> 8) & 0xFF); + pParseHeaderCMD->ui32ICParamData[0] |= ((pic_params->luma_shift >> 8) & 0xFF) << 8; + if( ctx->bTFF_FwRefFrm ) + pParseHeaderCMD->ui32ICParamData[0] |= (1 << 16); + /* + pParseHeaderCMD->ui32ICParamData[1] = (msPicParam.wBitstreamFcodes & 0xFF); + pParseHeaderCMD->ui32ICParamData[1] |= (msPicParam.wBitstreamPCEelements & 0xFF) << 8; + if( mpDestFrame->TopFieldFirst() ) + pParseHeaderCMD->ui32ICParamData[1] |= (1 << 16); + */ + pParseHeaderCMD->ui32ICParamData[1] = (pic_params->luma_scale & 0xFF); + pParseHeaderCMD->ui32ICParamData[1] |= (pic_params->luma_shift & 0xFF) << 8; + if( pic_params->picture_fields.bits.top_field_first ) + pParseHeaderCMD->ui32ICParamData[1] |= (1 << 16); + + pParseHeaderCMD->ui32ICParamData[0] = 0x00010000; + pParseHeaderCMD->ui32ICParamData[1] = 0x00010020; + PARSE_HEADER_CMD tmp = *pParseHeaderCMD; + tmp; + +} + +static VAStatus psb__VC1_process_slice(context_VC1_p ctx, + VASliceParameterBufferVC1 *slice_param, + object_buffer_p obj_buffer) +{ + VAStatus vaStatus = VA_STATUS_SUCCESS; + + ASSERT((obj_buffer->type == VASliceDataBufferType) || (obj_buffer->type == VAProtectedSliceDataBufferType)); + + psb__information_message("VC1 process slice\n"); + psb__information_message(" size = %08x offset = %08x\n", slice_param->slice_data_size, slice_param->slice_data_offset); + psb__information_message(" vertical pos = %d offset = %d\n", slice_param->slice_vertical_position, slice_param->macroblock_offset); + psb__information_message(" slice_data_flag = %d\n", slice_param->slice_data_flag); + + if ((slice_param->slice_data_flag == VA_SLICE_DATA_FLAG_BEGIN) || + (slice_param->slice_data_flag == VA_SLICE_DATA_FLAG_ALL)) + { + if (0 == slice_param->slice_data_size) + { + vaStatus = VA_STATUS_ERROR_UNKNOWN; + DEBUG_FAILURE; + return vaStatus; + } + ASSERT( !ctx->split_buffer_pending ); + + /* Initialise the command buffer */ + /* TODO: Reuse current command buffer until full */ + psb_context_get_next_cmdbuf(ctx->obj_context); + + psb__VC1_FE_state(ctx); +// psb__VC1_write_VLC_tables(ctx); +// psb__VC1_build_VLC_tables(ctx); + + psb_cmdbuf_lldma_write_bitstream(ctx->obj_context->cmdbuf, + obj_buffer->psb_buffer, + obj_buffer->psb_buffer->buffer_ofs + slice_param->slice_data_offset, + (slice_param->slice_data_size), + slice_param->macroblock_offset, + (ctx->profile == WMF_PROFILE_ADVANCED) ? CMD_ENABLE_RBDU_EXTRACTION : 0); + + if (slice_param->slice_data_flag == VA_SLICE_DATA_FLAG_BEGIN) + { + ctx->split_buffer_pending = TRUE; + } + } + else + { + ASSERT( ctx->split_buffer_pending ); + ASSERT(0 == slice_param->slice_data_offset); + /* Create LLDMA chain to continue buffer */ + if (slice_param->slice_data_size) + { + psb_cmdbuf_lldma_write_bitstream_chained(ctx->obj_context->cmdbuf, + obj_buffer->psb_buffer, + slice_param->slice_data_size); + } + } + + if ((slice_param->slice_data_flag == VA_SLICE_DATA_FLAG_ALL) || + (slice_param->slice_data_flag == VA_SLICE_DATA_FLAG_END)) + { + if (slice_param->slice_data_flag == VA_SLICE_DATA_FLAG_END) + { + ASSERT( ctx->split_buffer_pending ); + } + + psb__VC1_load_sequence_registers(ctx); + + if(!VC1_Header_Parser_HW) + { + psb__VC1_write_VLC_tables(ctx); + psb__VC1_build_VLC_tables(ctx); + } + else { + psb__VC1_Send_Parse_Header_Cmd(ctx, ctx->is_first_slice); + } + + psb__VC1_load_picture_registers(ctx, slice_param); + + psb__VC1_setup_bitplane(ctx); + + psb__VC1_send_rendec_params(ctx, slice_param); + + psb__VC1_write_kick(ctx, slice_param); + + ctx->split_buffer_pending = FALSE; + ctx->obj_context->video_op = psb_video_vld; + ctx->obj_context->first_mb = 0; + ctx->obj_context->flags = 0; + if (ctx->is_first_slice) + { + ctx->obj_context->flags |= FW_DXVA_RENDER_IS_FIRST_SLICE; + } + //if (ctx->bitplane_present) + { + ctx->obj_context->flags |= FW_DXVA_RENDER_VC1_BITPLANE_PRESENT; + } + ctx->obj_context->last_mb = ((ctx->picture_height_mb - 1) << 8) | (ctx->picture_width_mb - 1); + + *ctx->slice_first_pic_last = (ctx->obj_context->first_mb << 16) | (ctx->obj_context->last_mb); +#ifdef DEBUG_TRACE_VERBOSE + psb__debug_schedule_hexdump("Preload buffer", &ctx->preload_buffer, 0, PRELOAD_BUFFER_SIZE); + psb__debug_schedule_hexdump("AUXMSB buffer", &ctx->aux_msb_buffer, 0, 0x8000 /* AUXMSB_BUFFER_SIZE */); + psb__debug_schedule_hexdump("VLC Table", &ctx->vlc_packed_table, 0, gui16vc1VlcTableSize * sizeof(IMG_UINT16)); +#endif + + if (psb_context_submit_cmdbuf(ctx->obj_context)) + { + vaStatus = VA_STATUS_ERROR_UNKNOWN; + } + + ctx->is_first_slice = FALSE; /* Reset */ + } + return vaStatus; +} + +static VAStatus psb__VC1_process_slice_data(context_VC1_p ctx, object_buffer_p obj_buffer) +{ + VAStatus vaStatus = VA_STATUS_SUCCESS; + VASliceParameterBufferVC1 *slice_param; + int buffer_idx = 0; + int element_idx = 0; + + ASSERT((obj_buffer->type == VASliceDataBufferType) || (obj_buffer->type == VAProtectedSliceDataBufferType)); + + ASSERT(ctx->pic_params); + ASSERT(ctx->slice_param_list_idx); + + if (!ctx->pic_params) + { + /* Picture params missing */ + vaStatus = VA_STATUS_ERROR_UNKNOWN; + DEBUG_FAILURE; + return vaStatus; + } + if ((NULL == obj_buffer->psb_buffer) || + (0 == obj_buffer->size)) + { + /* We need to have data in the bitstream buffer */ + vaStatus = VA_STATUS_ERROR_UNKNOWN; + DEBUG_FAILURE; + return vaStatus; + } + + while(buffer_idx < ctx->slice_param_list_idx) + { + object_buffer_p slice_buf = ctx->slice_param_list[buffer_idx]; + if (element_idx >= slice_buf->num_elements) + { + /* Move to next buffer */ + element_idx = 0; + buffer_idx++; + continue; + } + + slice_param = (VASliceParameterBufferVC1 *) slice_buf->buffer_data; + slice_param += element_idx; + element_idx++; + vaStatus = psb__VC1_process_slice(ctx, slice_param, obj_buffer); + if (vaStatus != VA_STATUS_SUCCESS) + { + DEBUG_FAILURE; + break; + } + } + ctx->slice_param_list_idx = 0; + + return vaStatus; +} + +static VAStatus pnw_VC1_BeginPicture( + object_context_p obj_context) +{ + INIT_CONTEXT_VC1 + + if (ctx->pic_params) + { + free(ctx->pic_params); + ctx->pic_params = NULL; + } + ctx->is_first_slice = TRUE; + + return VA_STATUS_SUCCESS; +} + +static VAStatus pnw_VC1_RenderPicture( + object_context_p obj_context, + object_buffer_p *buffers, + int num_buffers) +{ + int i; + INIT_CONTEXT_VC1 + VAStatus vaStatus = VA_STATUS_SUCCESS; + + for(i = 0; i < num_buffers; i++) + { + object_buffer_p obj_buffer = buffers[i]; + + switch( obj_buffer->type) + { + case VAPictureParameterBufferType: + psb__information_message("pnw_VC1_RenderPicture got VAPictureParameterBuffer\n"); + vaStatus = psb__VC1_process_picture_param(ctx, obj_buffer); + DEBUG_FAILURE; + break; + + case VABitPlaneBufferType: + psb__information_message("pnw_VC1_RenderPicture got VABitPlaneBuffer\n"); + vaStatus = psb__VC1_process_bitplane(ctx, obj_buffer); + DEBUG_FAILURE; + break; + + case VASliceParameterBufferType: + psb__information_message("pnw_VC1_RenderPicture got VASliceParameterBufferType\n"); + vaStatus = psb__VC1_add_slice_param(ctx, obj_buffer); + DEBUG_FAILURE; + break; + + case VASliceDataBufferType: + case VAProtectedSliceDataBufferType: + + psb__information_message("pnw_VC1_RenderPicture got %s\n", SLICEDATA_BUFFER_TYPE(obj_buffer->type)); + vaStatus = psb__VC1_process_slice_data(ctx, obj_buffer); + DEBUG_FAILURE; + break; + + default: + vaStatus = VA_STATUS_ERROR_UNKNOWN; + DEBUG_FAILURE; + } + if (vaStatus != VA_STATUS_SUCCESS) + { + break; + } + } + + return vaStatus; +} + +static VAStatus pnw_VC1_EndPicture( + object_context_p obj_context) +{ + INIT_CONTEXT_VC1 + + if (psb_context_flush_cmdbuf(ctx->obj_context)) + { + return VA_STATUS_ERROR_UNKNOWN; + } + + ASSERT(ctx->pic_params); + if (!ctx->pic_params) + { + return VA_STATUS_ERROR_UNKNOWN; + } + + /********* Keep some picture parameters of the previously decoded picture ***********/ + if(PIC_TYPE_IS_REF(ctx->pic_params->picture_fields.bits.picture_type)) // I or P + { + /* Assume that the picture that we just decoded (the picture previous to the one that + is about to be decoded) is the backward reference picture for a B picture. */ + /* TODO: Make this more robust */ + ctx->ui8FCM_Ref2Pic = ctx->pic_params->picture_fields.bits.frame_coding_mode; + + /* For interlaced field pictures only */ + if((ctx->pic_params->picture_fields.bits.frame_coding_mode != VC1_FCM_FLDI) || !ctx->pic_params->picture_fields.bits.is_first_field) + { + ctx->bTFF_BwRefFrm = ctx->pic_params->picture_fields.bits.top_field_first; + } + } + + ctx->bRef1RangeRed = ctx->bRef0RangeRed; + if(PIC_TYPE_IS_REF(ctx->pic_params->picture_fields.bits.picture_type)) + { + ctx->bRef0RangeRed = ctx->pic_params->range_reduction_frame; + } + /***********************************************************************************/ + + free(ctx->pic_params); + ctx->pic_params = NULL; + + return VA_STATUS_SUCCESS; +} + +struct format_vtable_s pnw_VC1_vtable = { + queryConfigAttributes: pnw_VC1_QueryConfigAttributes, + validateConfig: pnw_VC1_ValidateConfig, + createContext: pnw_VC1_CreateContext, + destroyContext: pnw_VC1_DestroyContext, + beginPicture: pnw_VC1_BeginPicture, + renderPicture: pnw_VC1_RenderPicture, + endPicture: pnw_VC1_EndPicture +}; |