| /* |
| * Copyright (c) 2011 Intel Corporation. All Rights Reserved. |
| * Copyright (c) Imagination Technologies Limited, UK |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the |
| * "Software"), to deal in the Software without restriction, including |
| * without limitation the rights to use, copy, modify, merge, publish, |
| * distribute, sub license, and/or sell copies of the Software, and to |
| * permit persons to whom the Software is furnished to do so, subject to |
| * the following conditions: |
| * |
| * The above copyright notice and this permission notice (including the |
| * next paragraph) shall be included in all copies or substantial portions |
| * of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. |
| * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR |
| * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
| * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
| * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| * |
| * Authors: |
| * Waldo Bastian <waldo.bastian@intel.com> |
| * |
| */ |
| |
| |
| #include "psb_VC1.h" |
| #include "psb_def.h" |
| #include "psb_surface.h" |
| #include "psb_cmdbuf.h" |
| #include "psb_drv_debug.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> |
| |
| #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; |
| |
| /*! |
| ****************************************************************************** |
| @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 psb_VC1_QueryConfigAttributes( |
| VAProfile profile, |
| VAEntrypoint entrypoint, |
| VAConfigAttrib *attrib_list, |
| int num_attribs) |
| { |
| /* No VC1 specific attributes */ |
| } |
| |
| static VAStatus psb_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; |
| |
| /* 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]; |
| |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "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 psb_VC1_DestroyContext(object_context_p obj_context); |
| |
| static VAStatus psb_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) calloc(1, sizeof(struct context_VC1_s)); |
| if (NULL == ctx) { |
| vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; |
| DEBUG_FAILURE; |
| return vaStatus; |
| } |
| |
| obj_context->format_data = (void*) ctx; |
| ctx->obj_context = obj_context; |
| ctx->pic_params = NULL; |
| |
| ctx->split_buffer_pending = FALSE; |
| |
| ctx->slice_param_list_size = 8; |
| ctx->slice_param_list = (object_buffer_p*) calloc(1, 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) calloc(1, 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) { |
| 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) { |
| vaStatus = psb_buffer_create(obj_context->driver_data, |
| gui16vc1VlcTableSize * sizeof(IMG_UINT16), |
| 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, (unsigned char **)&vlc_packed_data_address)) { |
| psb__VC1_pack_vlc_tables((unsigned short *)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) { |
| psb_VC1_DestroyContext(obj_context); |
| } |
| |
| return vaStatus; |
| } |
| |
| static void psb_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); |
| |
| 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; |
| |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "psb_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) |
| { |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "psb_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; |
| } |
| } |
| } |
| } |
| |
| |
| //#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); |
| } |
| |
| 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; |
| |
| if (psb_video_trace_fp && (psb_video_trace_level & VABUF_TRACE)) |
| psb__VC1_trace_pic_params(pic_params); |
| |
| 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 |
| * 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 |
| |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "Target ref = %08x ID = %08x\n", ctx->obj_context->current_render_target->psb_surface, ctx->obj_context->current_render_target->surface_id); |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "Decoded ref = %08x ID = %08x\n", ctx->decoded_surface->psb_surface, pic_params->inloop_decoded_picture); |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "Forward ref = %08x ID = %08x\n", ctx->forward_ref_surface ? ctx->forward_ref_surface->psb_surface : 0, pic_params->forward_reference_picture); |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "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 * 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; |
| } |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "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) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "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 ***************************/ |
| 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 (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) { |
| unsigned char *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; |
| unsigned 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); |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "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, 0); |
| |
| 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->out_loop_surface; |
| object_context_p obj_context = ctx->obj_context; |
| |
| if (GET_SURFACE_INFO_rotate(rotate_surface) != obj_context->msvdx_rotate) |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "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_chunk(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_chunk(cmdbuf); |
| |
| /* Set the rotation registers */ |
| psb_cmdbuf_rendec_start_chunk(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, GET_SURFACE_INFO_rotate(rotate_surface)); |
| |
| psb_cmdbuf_rendec_write(cmdbuf, cmd); |
| |
| psb_cmdbuf_rendec_end_chunk(cmdbuf); |
| } |
| |
| 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 (CONTEXT_ROTATE(ctx->obj_context)) /* FIXME field coded should not issue */ |
| psb__VC1_setup_alternative_frame(ctx); |
| |
| /* CHUNK: 1 - VC1SEQUENCE00 */ |
| psb_cmdbuf_rendec_start_chunk(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, DISPLAY_PICTURE_SIZE)); |
| |
| /* 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); |
| 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); |
| |
| /* CHROMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES */ |
| psb_cmdbuf_rendec_write_address(cmdbuf, &target_surface->buf, target_surface->buf.buffer_ofs + target_surface->chroma_offset); |
| |
| /* Aux MSB buffer */ |
| psb_cmdbuf_rendec_write_address(cmdbuf, &ctx->aux_msb_buffer, 0); |
| |
| psb_cmdbuf_rendec_end_chunk(cmdbuf); |
| |
| /* CHUNK: 2 - VC1SLICE00 */ |
| psb_cmdbuf_rendec_start_chunk(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_chunk(cmdbuf); |
| |
| /* CHUNK: 3 */ |
| psb_cmdbuf_rendec_start_chunk(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, VC1_LUMA_RANGE_MAPPING_BASE_ADDRESS)); |
| |
| /* VC1 Luma Range Mapping Base Address */ |
| 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, &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); |
| |
| /* 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_chunk(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_chunk(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); |
| |
| /*************** 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_chunk(cmdbuf); |
| } |
| |
| /* CHUNK: 5 - VC1SLICE02 */ |
| psb_cmdbuf_rendec_start_chunk(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, SLICE_PARAMS)); |
| |
| /* 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); |
| 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, 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); |
| 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 */ |
| psb_cmdbuf_rendec_write(cmdbuf, cmd); |
| |
| psb_cmdbuf_rendec_end_chunk(cmdbuf); |
| |
| *ctx->p_slice_params = cmd; |
| |
| /* ------------------------------- Back-End Registers --------------------------------- */ |
| |
| /* CHUNK: 6 (Back-end registers) */ |
| psb_cmdbuf_rendec_start_chunk(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_chunk(cmdbuf); |
| |
| /* CHUNK: 6b (Back-end registers) */ |
| psb_cmdbuf_rendec_start_chunk(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_VEC, VC1_CR_VEC_VC1_BE_PPS2)); |
| |
| /* 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; |
| 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_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_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_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; |
| 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; |
| 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; |
| 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; |
| 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_chunk(cmdbuf); |
| |
| /* CHUNK: 6c (Back-end registers) */ |
| psb_cmdbuf_rendec_start_chunk(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_VEC, VC1_CR_VEC_VC1_BE_PARAM_BASE_ADDR)); |
| |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "psb_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_chunk(cmdbuf); |
| |
| if (!PIC_TYPE_IS_INTRA(pic_params->picture_fields.bits.picture_type)) { |
| /* CHUNK: 6d (Back-end registers) */ |
| psb_cmdbuf_rendec_start_chunk(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) { |
| drv_debug_msg(VIDEO_DEBUG_ERROR, "%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_chunk(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, 0); |
| |
| /* 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); |
| |
| psb_cmdbuf_rendec_start_block(cmdbuf); |
| /* CHUNK: Entdec back-end profile and level */ |
| psb_cmdbuf_rendec_start_chunk(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_VEC, CR_VEC_ENTDEC_BE_CONTROL)); |
| |
| reg_value = 0; |
| REGIO_WRITE_FIELD(reg_value, MSVDX_VEC, CR_VEC_ENTDEC_BE_CONTROL, ENTDEC_BE_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_chunk(cmdbuf); |
| psb_cmdbuf_rendec_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_reg_start_block(cmdbuf, 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); |
| 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_INTERLEAVED_BITPLANE |
| REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS1, VC1_FE_BP_FORMAT, IMG_FALSE); // interleaved format |
| #else |
| REGIO_WRITE_FIELD(reg_value, MSVDX_VEC_VC1, CR_VEC_VC1_FE_PPS1, VC1_FE_BP_FORMAT, IMG_TRUE); // non-interleaved format |
| #endif |
| 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; |
| 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); |
| /* Is this correct? */ |
| // Write to the VC1_FE_VOPDQUANT_PRESENT register according to PowerVR decoder's implementation. |
| 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); |
| 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); |
| 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, 0); |
| |
| /* Bitplanes Data Buffer Base Address */ |
| if (ctx->bitplane_present) { |
| ASSERT(ctx->has_bitplane); |
| psb_cmdbuf_reg_set_address(cmdbuf, REGISTER_OFFSET(MSVDX_VEC_VC1, CR_VEC_VC1_FE_BITPLANES_BASE_ADDR0), |
| ctx->bitplane_buffer, 0); |
| //if (psb_video_trace_fp && (psb_video_trace_level & AUXBUF_TRACE)) |
| //psb__debug_schedule_hexdump("Bitplane buffer", ctx->bitplane_buffer, 0, (ctx->size_mb + 1) / 2); |
| } 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++; |
| } |
| |
| 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)); |
| |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "VC1 process slice\n"); |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, " size = %08x offset = %08x\n", slice_param->slice_data_size, slice_param->slice_data_offset); |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, " vertical pos = %d offset = %d\n", slice_param->slice_vertical_position, slice_param->macroblock_offset); |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, " 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); |
| |
| /* TODO: Optimize? */ |
| 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); |
| |
| 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_VA_RENDER_IS_FIRST_SLICE; |
| } |
| if (ctx->bitplane_present) { |
| ctx->obj_context->flags |= FW_VA_RENDER_VC1_BITPLANE_PRESENT; |
| } |
| ctx->obj_context->last_mb = ((ctx->picture_height_mb - 1) << 8) | (ctx->picture_width_mb - 1); |
| |
| if (psb_video_trace_fp && (psb_video_trace_level & AUXBUF_TRACE)) { |
| 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)); |
| } |
| |
| 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; |
| unsigned 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 psb_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 psb_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: |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "psb_VC1_RenderPicture got VAPictureParameterBuffer\n"); |
| vaStatus = psb__VC1_process_picture_param(ctx, obj_buffer); |
| DEBUG_FAILURE; |
| break; |
| |
| case VABitPlaneBufferType: |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "psb_VC1_RenderPicture got VABitPlaneBuffer\n"); |
| vaStatus = psb__VC1_process_bitplane(ctx, obj_buffer); |
| DEBUG_FAILURE; |
| break; |
| |
| case VASliceParameterBufferType: |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "psb_VC1_RenderPicture got VASliceParameterBufferType\n"); |
| vaStatus = psb__VC1_add_slice_param(ctx, obj_buffer); |
| DEBUG_FAILURE; |
| break; |
| |
| case VASliceDataBufferType: |
| case VAProtectedSliceDataBufferType: |
| |
| drv_debug_msg(VIDEO_DEBUG_GENERAL, "psb_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 psb_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 psb_VC1_vtable = { |
| queryConfigAttributes: |
| psb_VC1_QueryConfigAttributes, |
| validateConfig: |
| psb_VC1_ValidateConfig, |
| createContext: |
| psb_VC1_CreateContext, |
| destroyContext: |
| psb_VC1_DestroyContext, |
| beginPicture: |
| psb_VC1_BeginPicture, |
| renderPicture: |
| psb_VC1_RenderPicture, |
| endPicture: |
| psb_VC1_EndPicture |
| }; |