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