diff options
Diffstat (limited to 'src/pnw_MPEG2.c')
-rw-r--r-- | src/pnw_MPEG2.c | 1644 |
1 files changed, 1644 insertions, 0 deletions
diff --git a/src/pnw_MPEG2.c b/src/pnw_MPEG2.c new file mode 100644 index 0000000..d745ea8 --- /dev/null +++ b/src/pnw_MPEG2.c @@ -0,0 +1,1644 @@ +/* + * Copyright (c) 2011 Intel Corporation. All Rights Reserved. + * Copyright (c) Imagination Technologies Limited, UK + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Waldo Bastian <waldo.bastian@intel.com> + * Zeng Li <zeng.li@intel.com> + * + */ + +#include "pnw_MPEG2.h" +#include "psb_def.h" +#include "psb_surface.h" +#include "psb_cmdbuf.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_mpeg2_reg_io2.h" +#include "hwdefs/dxva_fw_ctrl.h" + +#include <stdlib.h> +#include <stdint.h> +#include <string.h> + +#define GET_SURFACE_INFO_is_defined(psb_surface) ((int) (psb_surface->extra_info[0])) +#define SET_SURFACE_INFO_is_defined(psb_surface, val) psb_surface->extra_info[0] = (uint32_t) val; +#define GET_SURFACE_INFO_picture_structure(psb_surface) (psb_surface->extra_info[1]) +#define SET_SURFACE_INFO_picture_structure(psb_surface, val) psb_surface->extra_info[1] = val; +#define GET_SURFACE_INFO_picture_coding_type(psb_surface) ((int) (psb_surface->extra_info[2])) +#define SET_SURFACE_INFO_picture_coding_type(psb_surface, val) psb_surface->extra_info[2] = (uint32_t) val; + + +#define SLICEDATA_BUFFER_TYPE(type) ((type==VASliceDataBufferType)?"VASliceDataBufferType":"VAProtectedSliceDataBufferType") + +/* + * Frame types - format dependant! + */ +#define PICTURE_CODING_I 0x01 +#define PICTURE_CODING_P 0x02 +#define PICTURE_CODING_B 0x03 +/* A special syntax is defined for D-pictures (picture_coding_type = 4). D-pictures are like I-pictures with only Intra-DC coefficients, + no End of Block, and a special end_of_macroblock code '1'. PICTURE_CODING_D is not allowed in MPEG2 */ +#define PICTURE_CODING_D 0x04 + +/************************************************************************************/ +/* Variable length codes in 'packed' format */ +/************************************************************************************/ + +/* Format is: opcode, width, symbol. All VLC tables are concatenated. Index */ +/* infomation is stored in gui16mpeg2VlcIndexData[] */ +#define VLC_PACK(a,b,c) ( ( (a) << 12 ) | ( (b) << 9 ) | (c) ) +const static IMG_UINT16 gaui16mpeg2VlcTableDataPacked[] = { + VLC_PACK(6 , 0 , 0) , + VLC_PACK(0 , 0 , 6) , + VLC_PACK(4 , 2 , 4) , + VLC_PACK(4 , 3 , 5) , + VLC_PACK(4 , 4 , 6) , + VLC_PACK(4 , 5 , 7) , + VLC_PACK(1 , 1 , 3) , + VLC_PACK(4 , 0 , 0) , + VLC_PACK(4 , 0 , 3) , + VLC_PACK(4 , 0 , 8) , + VLC_PACK(4 , 1 , 9) , + VLC_PACK(5 , 0 , 5) , + VLC_PACK(5 , 0 , 0) , + VLC_PACK(4 , 1 , 2) , + VLC_PACK(4 , 2 , 3) , + VLC_PACK(4 , 3 , 4) , + VLC_PACK(4 , 4 , 5) , + VLC_PACK(4 , 5 , 6) , + VLC_PACK(1 , 2 , 1) , + VLC_PACK(4 , 0 , 7) , + VLC_PACK(4 , 1 , 8) , + VLC_PACK(4 , 2 , 9) , + VLC_PACK(5 , 0 , 5) , + VLC_PACK(0 , 2 , 16) , + VLC_PACK(0 , 1 , 87) , + VLC_PACK(2 , 3 , 90) , + VLC_PACK(0 , 0 , 98) , + VLC_PACK(5 , 0 , 253) , + VLC_PACK(5 , 0 , 366) , + VLC_PACK(4 , 3 , 380) , + VLC_PACK(4 , 3 , 381) , + VLC_PACK(4 , 1 , 508) , + VLC_PACK(4 , 1 , 508) , + VLC_PACK(4 , 1 , 508) , + VLC_PACK(4 , 1 , 508) , + VLC_PACK(4 , 1 , 509) , + VLC_PACK(4 , 1 , 509) , + VLC_PACK(4 , 1 , 509) , + VLC_PACK(4 , 1 , 509) , + VLC_PACK(0 , 4 , 8) , + VLC_PACK(0 , 2 , 63) , + VLC_PACK(4 , 1 , 255) , + VLC_PACK(4 , 1 , 255) , + VLC_PACK(5 , 0 , 365) , + VLC_PACK(5 , 0 , 470) , + VLC_PACK(5 , 0 , 251) , + VLC_PACK(5 , 0 , 471) , + VLC_PACK(3 , 4 , 0) , + VLC_PACK(0 , 1 , 31) , + VLC_PACK(0 , 0 , 40) , + VLC_PACK(2 , 2 , 41) , + VLC_PACK(5 , 2 , 224) , + VLC_PACK(5 , 2 , 228) , + VLC_PACK(5 , 2 , 232) , + VLC_PACK(5 , 2 , 236) , + VLC_PACK(5 , 1 , 437) , + VLC_PACK(0 , 0 , 39) , + VLC_PACK(0 , 0 , 40) , + VLC_PACK(0 , 0 , 41) , + VLC_PACK(5 , 1 , 241) , + VLC_PACK(0 , 0 , 41) , + VLC_PACK(5 , 1 , 454) , + VLC_PACK(5 , 1 , 456) , + VLC_PACK(5 , 0 , 244) , + VLC_PACK(5 , 0 , 439) , + VLC_PACK(5 , 0 , 348) , + VLC_PACK(5 , 0 , 245) , + VLC_PACK(5 , 0 , 363) , + VLC_PACK(5 , 0 , 325) , + VLC_PACK(5 , 0 , 458) , + VLC_PACK(5 , 0 , 459) , + VLC_PACK(5 , 0 , 246) , + VLC_PACK(5 , 0 , 460) , + VLC_PACK(5 , 0 , 461) , + VLC_PACK(5 , 0 , 186) , + VLC_PACK(5 , 0 , 356) , + VLC_PACK(5 , 0 , 247) , + VLC_PACK(5 , 0 , 333) , + VLC_PACK(5 , 0 , 462) , + VLC_PACK(5 , 2 , 173) , + VLC_PACK(2 , 1 , 3) , + VLC_PACK(1 , 1 , 5) , + VLC_PACK(5 , 2 , 449) , + VLC_PACK(5 , 1 , 432) , + VLC_PACK(5 , 0 , 431) , + VLC_PACK(5 , 0 , 332) , + VLC_PACK(5 , 1 , 434) , + VLC_PACK(5 , 0 , 436) , + VLC_PACK(5 , 0 , 448) , + VLC_PACK(5 , 2 , 215) , + VLC_PACK(5 , 2 , 219) , + VLC_PACK(5 , 2 , 180) , + VLC_PACK(5 , 1 , 178) , + VLC_PACK(5 , 0 , 177) , + VLC_PACK(5 , 0 , 223) , + VLC_PACK(5 , 0 , 340) , + VLC_PACK(5 , 0 , 355) , + VLC_PACK(5 , 0 , 362) , + VLC_PACK(5 , 0 , 184) , + VLC_PACK(5 , 0 , 185) , + VLC_PACK(5 , 0 , 240) , + VLC_PACK(5 , 0 , 243) , + VLC_PACK(5 , 0 , 453) , + VLC_PACK(5 , 0 , 463) , + VLC_PACK(5 , 0 , 341) , + VLC_PACK(5 , 0 , 248) , + VLC_PACK(5 , 0 , 364) , + VLC_PACK(5 , 0 , 187) , + VLC_PACK(5 , 0 , 464) , + VLC_PACK(5 , 0 , 465) , + VLC_PACK(5 , 0 , 349) , + VLC_PACK(5 , 0 , 326) , + VLC_PACK(5 , 0 , 334) , + VLC_PACK(5 , 0 , 189) , + VLC_PACK(5 , 0 , 342) , + VLC_PACK(5 , 0 , 252) , + VLC_PACK(0 , 1 , 4) , + VLC_PACK(5 , 1 , 467) , + VLC_PACK(5 , 0 , 249) , + VLC_PACK(5 , 0 , 466) , + VLC_PACK(5 , 0 , 357) , + VLC_PACK(5 , 0 , 188) , + VLC_PACK(5 , 0 , 250) , + VLC_PACK(5 , 0 , 469) , + VLC_PACK(5 , 0 , 350) , + VLC_PACK(5 , 0 , 358) , + VLC_PACK(0 , 2 , 16) , + VLC_PACK(0 , 1 , 87) , + VLC_PACK(2 , 3 , 90) , + VLC_PACK(0 , 0 , 98) , + VLC_PACK(5 , 0 , 253) , + VLC_PACK(5 , 0 , 366) , + VLC_PACK(4 , 3 , 380) , + VLC_PACK(4 , 3 , 381) , + VLC_PACK(4 , 1 , 254) , + VLC_PACK(4 , 1 , 254) , + VLC_PACK(4 , 1 , 254) , + VLC_PACK(4 , 1 , 254) , + VLC_PACK(4 , 2 , 508) , + VLC_PACK(4 , 2 , 508) , + VLC_PACK(4 , 2 , 509) , + VLC_PACK(4 , 2 , 509) , + VLC_PACK(0 , 4 , 8) , + VLC_PACK(0 , 2 , 63) , + VLC_PACK(4 , 1 , 255) , + VLC_PACK(4 , 1 , 255) , + VLC_PACK(5 , 0 , 365) , + VLC_PACK(5 , 0 , 470) , + VLC_PACK(5 , 0 , 251) , + VLC_PACK(5 , 0 , 471) , + VLC_PACK(3 , 4 , 0) , + VLC_PACK(0 , 1 , 31) , + VLC_PACK(0 , 0 , 40) , + VLC_PACK(2 , 2 , 41) , + VLC_PACK(5 , 2 , 224) , + VLC_PACK(5 , 2 , 228) , + VLC_PACK(5 , 2 , 232) , + VLC_PACK(5 , 2 , 236) , + VLC_PACK(5 , 1 , 437) , + VLC_PACK(0 , 0 , 39) , + VLC_PACK(0 , 0 , 40) , + VLC_PACK(0 , 0 , 41) , + VLC_PACK(5 , 1 , 241) , + VLC_PACK(0 , 0 , 41) , + VLC_PACK(5 , 1 , 454) , + VLC_PACK(5 , 1 , 456) , + VLC_PACK(5 , 0 , 244) , + VLC_PACK(5 , 0 , 439) , + VLC_PACK(5 , 0 , 348) , + VLC_PACK(5 , 0 , 245) , + VLC_PACK(5 , 0 , 363) , + VLC_PACK(5 , 0 , 325) , + VLC_PACK(5 , 0 , 458) , + VLC_PACK(5 , 0 , 459) , + VLC_PACK(5 , 0 , 246) , + VLC_PACK(5 , 0 , 460) , + VLC_PACK(5 , 0 , 461) , + VLC_PACK(5 , 0 , 186) , + VLC_PACK(5 , 0 , 356) , + VLC_PACK(5 , 0 , 247) , + VLC_PACK(5 , 0 , 333) , + VLC_PACK(5 , 0 , 462) , + VLC_PACK(5 , 2 , 173) , + VLC_PACK(2 , 1 , 3) , + VLC_PACK(1 , 1 , 5) , + VLC_PACK(5 , 2 , 449) , + VLC_PACK(5 , 1 , 432) , + VLC_PACK(5 , 0 , 431) , + VLC_PACK(5 , 0 , 332) , + VLC_PACK(5 , 1 , 434) , + VLC_PACK(5 , 0 , 436) , + VLC_PACK(5 , 0 , 448) , + VLC_PACK(5 , 2 , 215) , + VLC_PACK(5 , 2 , 219) , + VLC_PACK(5 , 2 , 180) , + VLC_PACK(5 , 1 , 178) , + VLC_PACK(5 , 0 , 177) , + VLC_PACK(5 , 0 , 223) , + VLC_PACK(5 , 0 , 340) , + VLC_PACK(5 , 0 , 355) , + VLC_PACK(5 , 0 , 362) , + VLC_PACK(5 , 0 , 184) , + VLC_PACK(5 , 0 , 185) , + VLC_PACK(5 , 0 , 240) , + VLC_PACK(5 , 0 , 243) , + VLC_PACK(5 , 0 , 453) , + VLC_PACK(5 , 0 , 463) , + VLC_PACK(5 , 0 , 341) , + VLC_PACK(5 , 0 , 248) , + VLC_PACK(5 , 0 , 364) , + VLC_PACK(5 , 0 , 187) , + VLC_PACK(5 , 0 , 464) , + VLC_PACK(5 , 0 , 465) , + VLC_PACK(5 , 0 , 349) , + VLC_PACK(5 , 0 , 326) , + VLC_PACK(5 , 0 , 334) , + VLC_PACK(5 , 0 , 189) , + VLC_PACK(5 , 0 , 342) , + VLC_PACK(5 , 0 , 252) , + VLC_PACK(0 , 1 , 4) , + VLC_PACK(5 , 1 , 467) , + VLC_PACK(5 , 0 , 249) , + VLC_PACK(5 , 0 , 466) , + VLC_PACK(5 , 0 , 357) , + VLC_PACK(5 , 0 , 188) , + VLC_PACK(5 , 0 , 250) , + VLC_PACK(5 , 0 , 469) , + VLC_PACK(5 , 0 , 350) , + VLC_PACK(5 , 0 , 358) , + VLC_PACK(2 , 2 , 32) , + VLC_PACK(0 , 1 , 87) , + VLC_PACK(5 , 1 , 248) , + VLC_PACK(0 , 0 , 89) , + VLC_PACK(1 , 2 , 90) , + VLC_PACK(5 , 0 , 366) , + VLC_PACK(5 , 0 , 189) , + VLC_PACK(5 , 0 , 358) , + VLC_PACK(4 , 3 , 380) , + VLC_PACK(4 , 3 , 380) , + VLC_PACK(4 , 3 , 381) , + VLC_PACK(4 , 3 , 381) , + VLC_PACK(4 , 3 , 254) , + VLC_PACK(4 , 3 , 254) , + VLC_PACK(4 , 4 , 504) , + VLC_PACK(4 , 4 , 505) , + VLC_PACK(4 , 2 , 508) , + VLC_PACK(4 , 2 , 508) , + VLC_PACK(4 , 2 , 508) , + VLC_PACK(4 , 2 , 508) , + VLC_PACK(4 , 2 , 509) , + VLC_PACK(4 , 2 , 509) , + VLC_PACK(4 , 2 , 509) , + VLC_PACK(4 , 2 , 509) , + VLC_PACK(4 , 3 , 506) , + VLC_PACK(4 , 3 , 506) , + VLC_PACK(4 , 3 , 507) , + VLC_PACK(4 , 3 , 507) , + VLC_PACK(5 , 0 , 251) , + VLC_PACK(5 , 0 , 250) , + VLC_PACK(0 , 1 , 71) , + VLC_PACK(0 , 2 , 74) , + VLC_PACK(4 , 0 , 255) , + VLC_PACK(0 , 1 , 3) , + VLC_PACK(0 , 2 , 8) , + VLC_PACK(0 , 3 , 17) , + VLC_PACK(5 , 0 , 341) , + VLC_PACK(5 , 0 , 465) , + VLC_PACK(0 , 0 , 2) , + VLC_PACK(5 , 0 , 464) , + VLC_PACK(5 , 0 , 363) , + VLC_PACK(5 , 0 , 463) , + VLC_PACK(5 , 1 , 438) , + VLC_PACK(5 , 1 , 348) , + VLC_PACK(5 , 1 , 324) , + VLC_PACK(5 , 1 , 458) , + VLC_PACK(5 , 1 , 459) , + VLC_PACK(5 , 1 , 461) , + VLC_PACK(5 , 1 , 356) , + VLC_PACK(0 , 0 , 1) , + VLC_PACK(5 , 0 , 333) , + VLC_PACK(5 , 0 , 462) , + VLC_PACK(3 , 3 , 0) , + VLC_PACK(0 , 1 , 15) , + VLC_PACK(0 , 0 , 24) , + VLC_PACK(2 , 2 , 25) , + VLC_PACK(5 , 2 , 224) , + VLC_PACK(5 , 2 , 228) , + VLC_PACK(5 , 2 , 232) , + VLC_PACK(5 , 2 , 236) , + VLC_PACK(5 , 1 , 437) , + VLC_PACK(0 , 0 , 23) , + VLC_PACK(0 , 0 , 24) , + VLC_PACK(5 , 1 , 185) , + VLC_PACK(3 , 3 , 0) , + VLC_PACK(5 , 1 , 452) , + VLC_PACK(5 , 1 , 454) , + VLC_PACK(5 , 1 , 456) , + VLC_PACK(5 , 2 , 173) , + VLC_PACK(2 , 1 , 3) , + VLC_PACK(1 , 1 , 5) , + VLC_PACK(5 , 2 , 449) , + VLC_PACK(5 , 1 , 432) , + VLC_PACK(5 , 0 , 431) , + VLC_PACK(5 , 0 , 332) , + VLC_PACK(5 , 1 , 434) , + VLC_PACK(5 , 0 , 436) , + VLC_PACK(5 , 0 , 448) , + VLC_PACK(5 , 2 , 215) , + VLC_PACK(5 , 2 , 219) , + VLC_PACK(5 , 2 , 180) , + VLC_PACK(5 , 1 , 178) , + VLC_PACK(5 , 0 , 177) , + VLC_PACK(5 , 0 , 223) , + VLC_PACK(5 , 0 , 340) , + VLC_PACK(5 , 0 , 355) , + VLC_PACK(5 , 0 , 362) , + VLC_PACK(5 , 0 , 184) , + VLC_PACK(5 , 0 , 326) , + VLC_PACK(5 , 0 , 471) , + VLC_PACK(5 , 0 , 334) , + VLC_PACK(5 , 0 , 365) , + VLC_PACK(5 , 0 , 350) , + VLC_PACK(5 , 0 , 342) , + VLC_PACK(2 , 1 , 4) , + VLC_PACK(5 , 1 , 466) , + VLC_PACK(5 , 0 , 357) , + VLC_PACK(5 , 0 , 187) , + VLC_PACK(5 , 1 , 244) , + VLC_PACK(5 , 0 , 468) , + VLC_PACK(5 , 0 , 186) , + VLC_PACK(5 , 0 , 470) , + VLC_PACK(5 , 0 , 188) , + VLC_PACK(5 , 0 , 469) , + VLC_PACK(5 , 0 , 247) , + VLC_PACK(4 , 2 , 492) , + VLC_PACK(4 , 2 , 493) , + VLC_PACK(5 , 0 , 243) , + VLC_PACK(5 , 0 , 242) , + VLC_PACK(5 , 0 , 364) , + VLC_PACK(5 , 0 , 349) , + VLC_PACK(5 , 0 , 241) , + VLC_PACK(5 , 0 , 240) , + VLC_PACK(4 , 0 , 30) , + VLC_PACK(5 , 0 , 14) , + VLC_PACK(5 , 0 , 13) , + VLC_PACK(5 , 0 , 12) , + VLC_PACK(0 , 0 , 3) , + VLC_PACK(2 , 2 , 4) , + VLC_PACK(0 , 1 , 7) , + VLC_PACK(5 , 1 , 9) , + VLC_PACK(5 , 0 , 11) , + VLC_PACK(5 , 0 , 8) , + VLC_PACK(5 , 1 , 6) , + VLC_PACK(5 , 0 , 5) , + VLC_PACK(5 , 1 , 3) , + VLC_PACK(3 , 1 , 0) , + VLC_PACK(2 , 2 , 3) , + VLC_PACK(3 , 1 , 0) , + VLC_PACK(2 , 1 , 5) , + VLC_PACK(3 , 2 , 0) , + VLC_PACK(3 , 2 , 0) , + VLC_PACK(3 , 2 , 0) , + VLC_PACK(4 , 2 , 226) , + VLC_PACK(5 , 1 , 1) , + VLC_PACK(5 , 0 , 0) , + VLC_PACK(5 , 0 , 31) , + VLC_PACK(4 , 0 , 62) , + VLC_PACK(5 , 0 , 30) , + VLC_PACK(5 , 0 , 29) , + VLC_PACK(5 , 0 , 28) , + VLC_PACK(0 , 0 , 3) , + VLC_PACK(2 , 2 , 4) , + VLC_PACK(1 , 1 , 7) , + VLC_PACK(5 , 1 , 25) , + VLC_PACK(5 , 0 , 27) , + VLC_PACK(5 , 0 , 24) , + VLC_PACK(5 , 1 , 22) , + VLC_PACK(5 , 0 , 21) , + VLC_PACK(5 , 1 , 19) , + VLC_PACK(3 , 1 , 0) , + VLC_PACK(3 , 1 , 0) , + VLC_PACK(5 , 2 , 15) +}; + +#define MAX_QUANT_TABLES (2) /* only 2 tables for 4:2:0 decode */ + +static int scan0[64] = { // spec, fig 7-2 + /*u 0 ..... 7*/ + 0, 1, 5, 6, 14, 15, 27, 28, /* v = 0 */ + 2, 4, 7, 13, 16, 26, 29, 42, + 3, 8, 12, 17, 25, 30, 41, 43, + 9, 11, 18, 24, 31, 40, 44, 53, + 10, 19, 23, 32, 39, 45, 52, 54, + 20, 22, 33, 38, 46, 51, 55, 60, + 21, 34, 37, 47, 50, 56, 59, 61, + 35, 36, 48, 49, 57, 58, 62, 63 /* v = 7 */ +}; + +typedef enum { + NONINTRA_LUMA_Q = 0, + INTRA_LUMA_Q = 1 +} QUANT_IDX; + +struct context_MPEG2_s { + object_context_p obj_context; /* back reference */ + + /* Picture parameters */ + VAPictureParameterBufferMPEG2 *pic_params; + object_surface_p forward_ref_surface; + object_surface_p backward_ref_surface; + + uint32_t coded_picture_width; /* in pixels */ + uint32_t coded_picture_height; /* in pixels */ + + uint32_t picture_width_mb; /* in macroblocks */ + uint32_t picture_height_mb; /* in macroblocks */ + uint32_t size_mb; /* in macroblocks */ + + uint32_t coded_picture_size; /* MSVDX format */ + uint32_t display_picture_size; /* MSVDX format */ + + uint32_t BE_PPS0; + uint32_t BE_PPS1; + uint32_t BE_PPS2; + uint32_t BE_SPS0; + uint32_t BE_SPS1; + uint32_t FE_PPS0; + uint32_t FE_PPS1; + + /* IQ Matrix */ + uint32_t qmatrix_data[MAX_QUANT_TABLES][16]; + int got_iq_matrix; + + /* Split buffers */ + int split_buffer_pending; + + /* List of VASliceParameterBuffers */ + object_buffer_p *slice_param_list; + int slice_param_list_size; + int slice_param_list_idx; + + /* VLC packed data */ + struct psb_buffer_s vlc_packed_table; + + /* Misc */ + unsigned int previous_slice_vertical_position; + + uint32_t *p_range_mapping_base0; + uint32_t *p_range_mapping_base1; + uint32_t *p_slice_params; /* pointer to ui32SliceParams in CMD_HEADER */ + uint32_t *slice_first_pic_last; +}; + +typedef struct context_MPEG2_s *context_MPEG2_p; + +#define INIT_CONTEXT_MPEG2 context_MPEG2_p ctx = (context_MPEG2_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_MPEG2_QueryConfigAttributes( + VAProfile profile, + VAEntrypoint entrypoint, + VAConfigAttrib *attrib_list, + int num_attribs) +{ + /* No MPEG2 specific attributes */ +} + +static VAStatus pnw_MPEG2_ValidateConfig( + object_config_p obj_config) +{ + int i; + /* Check all attributes */ + for (i = 0; i < obj_config->attrib_count; i++) { + switch (obj_config->attrib_list[i].type) { + case VAConfigAttribRTFormat: + /* Ignore */ + break; + + default: + return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED; + } + } + + return VA_STATUS_SUCCESS; +} + +static VAStatus psb__MPEG2_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 MPEG2: + * MP@HL + * + * Refer to Table 8-11 (Upper bounds for luminance sample rate) of ISO/IEC 13818-2: 1995(E), + * and the "MSVDX MPEG2 decode capability" table of "Poulsbo Media Software Overview" + */ + + switch (obj_config->profile) { + case VAProfileMPEG2Simple: + 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 VAProfileMPEG2Main: + 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; + + default: + vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE; + break; + } + + return vaStatus; +} + +static void pnw_MPEG2_DestroyContext(object_context_p obj_context); + +static VAStatus pnw_MPEG2_CreateContext( + object_context_p obj_context, + object_config_p obj_config) +{ + VAStatus vaStatus = VA_STATUS_SUCCESS; + context_MPEG2_p ctx; + /* Validate flag */ + /* Validate picture dimensions */ + vaStatus = psb__MPEG2_check_legal_picture(obj_context, obj_config); + if (VA_STATUS_SUCCESS != vaStatus) { + DEBUG_FAILURE; + return vaStatus; + } + + if (obj_context->num_render_targets < 1) { + vaStatus = VA_STATUS_ERROR_UNKNOWN; + DEBUG_FAILURE; + return vaStatus; + } + ctx = (context_MPEG2_p) calloc(1, sizeof(struct context_MPEG2_s)); + if (NULL == ctx) { + vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; + DEBUG_FAILURE; + return vaStatus; + } + + obj_context->format_data = (void*) ctx; + ctx->obj_context = obj_context; + ctx->pic_params = NULL; + ctx->got_iq_matrix = FALSE; + ctx->previous_slice_vertical_position = ~1; + + ctx->split_buffer_pending = FALSE; + + ctx->slice_param_list_size = 8; + ctx->slice_param_list = (object_buffer_p*) calloc(1, sizeof(object_buffer_p) * ctx->slice_param_list_size); + ctx->slice_param_list_idx = 0; + + if (NULL == ctx->slice_param_list) { + vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; + DEBUG_FAILURE; + } + + if (vaStatus == VA_STATUS_SUCCESS) { + vaStatus = psb_buffer_create(obj_context->driver_data, + sizeof(gaui16mpeg2VlcTableDataPacked), + 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)) { + memcpy(vlc_packed_data_address, gaui16mpeg2VlcTableDataPacked, sizeof(gaui16mpeg2VlcTableDataPacked)); + psb_buffer_unmap(&ctx->vlc_packed_table); + } else { + vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; + DEBUG_FAILURE; + } + } + + if (vaStatus != VA_STATUS_SUCCESS) { + pnw_MPEG2_DestroyContext(obj_context); + } + + return vaStatus; +} + +static void pnw_MPEG2_DestroyContext( + object_context_p obj_context) +{ + INIT_CONTEXT_MPEG2 + + psb_buffer_destroy(&ctx->vlc_packed_table); + + 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; + } + + free(obj_context->format_data); + obj_context->format_data = NULL; +} + +static VAStatus psb__MPEG2_process_picture_param(context_MPEG2_p ctx, object_buffer_p obj_buffer) +{ + ASSERT(obj_buffer->type == VAPictureParameterBufferType); + ASSERT(obj_buffer->num_elements == 1); + ASSERT(obj_buffer->size == sizeof(VAPictureParameterBufferMPEG2)); + + if ((obj_buffer->num_elements != 1) || + (obj_buffer->size != sizeof(VAPictureParameterBufferMPEG2))) { + return VA_STATUS_ERROR_UNKNOWN; + } + + /* Transfer ownership of VAPictureParameterBufferMPEG2 data */ + if (ctx->pic_params) { + free(ctx->pic_params); + } + ctx->pic_params = (VAPictureParameterBufferMPEG2 *) obj_buffer->buffer_data; + obj_buffer->buffer_data = NULL; + obj_buffer->size = 0; + + /* Lookup surfaces for backward/forward references */ + switch (ctx->pic_params->picture_coding_type) { + case PICTURE_CODING_I: + ctx->forward_ref_surface = NULL; + ctx->backward_ref_surface = NULL; + break; + + case PICTURE_CODING_P: + ctx->forward_ref_surface = SURFACE(ctx->pic_params->forward_reference_picture); + ctx->backward_ref_surface = NULL; + if (NULL == ctx->forward_ref_surface) { + return VA_STATUS_ERROR_INVALID_SURFACE; + } + break; + + case PICTURE_CODING_B: + ctx->forward_ref_surface = SURFACE(ctx->pic_params->forward_reference_picture); + ctx->backward_ref_surface = SURFACE(ctx->pic_params->backward_reference_picture); + if ((NULL == ctx->forward_ref_surface) || + (NULL == ctx->backward_ref_surface)) { + return VA_STATUS_ERROR_INVALID_SURFACE; + } + break; + + default: + return VA_STATUS_ERROR_UNKNOWN; + } + + ctx->picture_width_mb = (ctx->pic_params->horizontal_size + 15) / 16; + if (ctx->obj_context->va_flags & VA_PROGRESSIVE) { + ctx->picture_height_mb = (ctx->pic_params->vertical_size + 15) / 16; + } else { + ctx->picture_height_mb = (ctx->pic_params->vertical_size + 31) / 32; + ctx->picture_height_mb *= 2; + } + ctx->coded_picture_width = ctx->picture_width_mb * 16; + ctx->coded_picture_height = ctx->picture_height_mb * 16; + + ctx->size_mb = ctx->picture_width_mb * ctx->picture_height_mb; + + /* Display picture size */ + ctx->display_picture_size = 0; + /* + * coded_picture_width/height is aligned to the size of a macroblock.. + * Both coded_picture_height or vertical_size can be used for DISPLAY_SIZE and both give correct results, + * however Vista driver / test app uses the aligned value that's in coded_picture_height so we do too. + * See e.g. low4.m2v for an example clip where vertical_size will differ from coded_picture_height + */ +#if 0 + REGIO_WRITE_FIELD_LITE(ctx->display_picture_size, MSVDX_CMDS, DISPLAY_PICTURE_SIZE, DISPLAY_PICTURE_HEIGHT, ctx->pic_params->vertical_size - 1); + REGIO_WRITE_FIELD_LITE(ctx->display_picture_size, MSVDX_CMDS, DISPLAY_PICTURE_SIZE, DISPLAY_PICTURE_WIDTH, ctx->pic_params->horizontal_size - 1); +#else + REGIO_WRITE_FIELD_LITE(ctx->display_picture_size, MSVDX_CMDS, DISPLAY_PICTURE_SIZE, DISPLAY_PICTURE_HEIGHT, ctx->coded_picture_height - 1); + REGIO_WRITE_FIELD_LITE(ctx->display_picture_size, MSVDX_CMDS, DISPLAY_PICTURE_SIZE, DISPLAY_PICTURE_WIDTH, ctx->coded_picture_width - 1); +#endif + + /* Coded picture size */ + ctx->coded_picture_size = 0; + REGIO_WRITE_FIELD_LITE(ctx->coded_picture_size, MSVDX_CMDS, CODED_PICTURE_SIZE, CODED_PICTURE_HEIGHT, ctx->coded_picture_height - 1); + REGIO_WRITE_FIELD_LITE(ctx->coded_picture_size, MSVDX_CMDS, CODED_PICTURE_SIZE, CODED_PICTURE_WIDTH, ctx->coded_picture_width - 1); + + ctx->BE_SPS0 = 0; + REGIO_WRITE_FIELD_LITE(ctx->BE_SPS0, MSVDX_VEC_MPEG2, CR_VEC_MPEG2_BE_SPS0, BE_HORIZONTAL_SIZE_MINUS1, ctx->picture_width_mb - 1); + + ctx->BE_SPS1 = 0; + REGIO_WRITE_FIELD_LITE(ctx->BE_SPS1, MSVDX_VEC_MPEG2, CR_VEC_MPEG2_BE_SPS1, BE_VERTICAL_SIZE_MINUS1, ctx->picture_height_mb); + + ctx->FE_PPS0 = 0; + REGIO_WRITE_FIELD_LITE(ctx->FE_PPS0, MSVDX_VEC_MPEG2, CR_VEC_MPEG2_FE_PPS0, FE_ALTERNATE_SCAN, !!(ctx->pic_params->picture_coding_extension.bits.alternate_scan)); + REGIO_WRITE_FIELD_LITE(ctx->FE_PPS0, MSVDX_VEC_MPEG2, CR_VEC_MPEG2_FE_PPS0, FE_Q_SCALE_TYPE, !!(ctx->pic_params->picture_coding_extension.bits.q_scale_type)); + REGIO_WRITE_FIELD_LITE(ctx->FE_PPS0, MSVDX_VEC_MPEG2, CR_VEC_MPEG2_FE_PPS0, FE_INTRA_DC_PRECISION, ctx->pic_params->picture_coding_extension.bits.intra_dc_precision); + REGIO_WRITE_FIELD_LITE(ctx->FE_PPS0, MSVDX_VEC_MPEG2, CR_VEC_MPEG2_FE_PPS0, FE_TOP_FIELD_FIRST, !!(ctx->pic_params->picture_coding_extension.bits.top_field_first)); + REGIO_WRITE_FIELD_LITE(ctx->FE_PPS0, MSVDX_VEC_MPEG2, CR_VEC_MPEG2_FE_PPS0, FE_CONCEALMENT_MOTION_VECTORS, !!(ctx->pic_params->picture_coding_extension.bits.concealment_motion_vectors)); + REGIO_WRITE_FIELD_LITE(ctx->FE_PPS0, MSVDX_VEC_MPEG2, CR_VEC_MPEG2_FE_PPS0, FE_FRAME_PRED_FRAME_DCT, !!(ctx->pic_params->picture_coding_extension.bits.frame_pred_frame_dct)); + REGIO_WRITE_FIELD_LITE(ctx->FE_PPS0, MSVDX_VEC_MPEG2, CR_VEC_MPEG2_FE_PPS0, FE_PICTURE_STRUCTURE, ctx->pic_params->picture_coding_extension.bits.picture_structure); + REGIO_WRITE_FIELD_LITE(ctx->FE_PPS0, MSVDX_VEC_MPEG2, CR_VEC_MPEG2_FE_PPS0, FE_INTRA_VLC_FORMAT, !!(ctx->pic_params->picture_coding_extension.bits.intra_vlc_format)); + + ctx->FE_PPS1 = 0; + REGIO_WRITE_FIELD_LITE(ctx->FE_PPS1, MSVDX_VEC_MPEG2, CR_VEC_MPEG2_FE_PPS1, FE_PICTURE_CODING_TYPE, ctx->pic_params->picture_coding_type); + REGIO_WRITE_FIELD_LITE(ctx->FE_PPS1, MSVDX_VEC_MPEG2, CR_VEC_MPEG2_FE_PPS1, FE_F_CODE00, (ctx->pic_params->f_code >> 12) & 0x0F); + REGIO_WRITE_FIELD_LITE(ctx->FE_PPS1, MSVDX_VEC_MPEG2, CR_VEC_MPEG2_FE_PPS1, FE_F_CODE01, (ctx->pic_params->f_code >> 8) & 0x0F); + REGIO_WRITE_FIELD_LITE(ctx->FE_PPS1, MSVDX_VEC_MPEG2, CR_VEC_MPEG2_FE_PPS1, FE_F_CODE10, (ctx->pic_params->f_code >> 4) & 0x0F); + REGIO_WRITE_FIELD_LITE(ctx->FE_PPS1, MSVDX_VEC_MPEG2, CR_VEC_MPEG2_FE_PPS1, FE_F_CODE11, (ctx->pic_params->f_code >> 0) & 0x0F); + + /* VEC Control register: Back-End MPEG2 PPS0 */ + ctx->BE_PPS0 = 0; + REGIO_WRITE_FIELD_LITE(ctx->BE_PPS0, MSVDX_VEC_MPEG2, CR_VEC_MPEG2_BE_PPS0, BE_FRAME_PRED_FRAME_DCT, !!(ctx->pic_params->picture_coding_extension.bits.frame_pred_frame_dct)); + REGIO_WRITE_FIELD_LITE(ctx->BE_PPS0, MSVDX_VEC_MPEG2, CR_VEC_MPEG2_BE_PPS0, BE_INTRA_DC_PRECISION, ctx->pic_params->picture_coding_extension.bits.intra_dc_precision); + REGIO_WRITE_FIELD_LITE(ctx->BE_PPS0, MSVDX_VEC_MPEG2, CR_VEC_MPEG2_BE_PPS0, BE_Q_SCALE_TYPE, !!(ctx->pic_params->picture_coding_extension.bits.q_scale_type)); + REGIO_WRITE_FIELD_LITE(ctx->BE_PPS0, MSVDX_VEC_MPEG2, CR_VEC_MPEG2_BE_PPS0, BE_ALTERNATE_SCAN, !!(ctx->pic_params->picture_coding_extension.bits.alternate_scan)); + + ctx->BE_PPS1 = 0; + REGIO_WRITE_FIELD_LITE(ctx->BE_PPS1, MSVDX_VEC_MPEG2, CR_VEC_MPEG2_BE_PPS1, BE_F_CODE00, (ctx->pic_params->f_code >> 12) & 0x0F); + REGIO_WRITE_FIELD_LITE(ctx->BE_PPS1, MSVDX_VEC_MPEG2, CR_VEC_MPEG2_BE_PPS1, BE_F_CODE01, (ctx->pic_params->f_code >> 8) & 0x0F); + REGIO_WRITE_FIELD_LITE(ctx->BE_PPS1, MSVDX_VEC_MPEG2, CR_VEC_MPEG2_BE_PPS1, BE_F_CODE10, (ctx->pic_params->f_code >> 4) & 0x0F); + REGIO_WRITE_FIELD_LITE(ctx->BE_PPS1, MSVDX_VEC_MPEG2, CR_VEC_MPEG2_BE_PPS1, BE_F_CODE11, (ctx->pic_params->f_code >> 0) & 0x0F); + + /* VEC Control register: Back-End MPEG2 PPS2 */ + ctx->BE_PPS2 = 0; + REGIO_WRITE_FIELD_LITE(ctx->BE_PPS2, MSVDX_VEC_MPEG2, CR_VEC_MPEG2_BE_PPS2, BE_PICTURE_CODING_TYPE, ctx->pic_params->picture_coding_type); + REGIO_WRITE_FIELD_LITE(ctx->BE_PPS2, MSVDX_VEC_MPEG2, CR_VEC_MPEG2_BE_PPS2, BE_TOP_FIELD_FIRST, !!(ctx->pic_params->picture_coding_extension.bits.top_field_first)); + REGIO_WRITE_FIELD_LITE(ctx->BE_PPS2, MSVDX_VEC_MPEG2, CR_VEC_MPEG2_BE_PPS2, BE_CONCEALMENT_MOTION_VECTORS, !!(ctx->pic_params->picture_coding_extension.bits.concealment_motion_vectors)); + REGIO_WRITE_FIELD_LITE(ctx->BE_PPS2, MSVDX_VEC_MPEG2, CR_VEC_MPEG2_BE_PPS2, BE_PICTURE_STRUCTURE, ctx->pic_params->picture_coding_extension.bits.picture_structure); + + ctx->obj_context->operating_mode = 0; + REGIO_WRITE_FIELD_LITE(ctx->obj_context->operating_mode, MSVDX_CMDS, OPERATING_MODE, CHROMA_INTERLEAVED, 0); + REGIO_WRITE_FIELD_LITE(ctx->obj_context->operating_mode, MSVDX_CMDS, OPERATING_MODE, ROW_STRIDE, ctx->obj_context->current_render_target->psb_surface->stride_mode); + REGIO_WRITE_FIELD_LITE(ctx->obj_context->operating_mode, MSVDX_CMDS, OPERATING_MODE, CODEC_PROFILE, 1); /* MPEG2 profile */ + REGIO_WRITE_FIELD_LITE(ctx->obj_context->operating_mode, MSVDX_CMDS, OPERATING_MODE, CODEC_MODE, 3); /* MPEG2 mode */ + REGIO_WRITE_FIELD_LITE(ctx->obj_context->operating_mode, MSVDX_CMDS, OPERATING_MODE, ASYNC_MODE, 1); /* VDMC only */ + REGIO_WRITE_FIELD_LITE(ctx->obj_context->operating_mode, MSVDX_CMDS, OPERATING_MODE, CHROMA_FORMAT, 1); + + return VA_STATUS_SUCCESS; +} + +static void psb__MPEG2_convert_iq_matrix(uint32_t *dest32, unsigned char *src) +{ + int i; + int *idx = scan0; + uint8_t *dest8 = (uint8_t*) dest32; + + for (i = 0; i < 64; i++) { + *dest8++ = src[*idx++]; + } +} + +static VAStatus psb__MPEG2_process_iq_matrix(context_MPEG2_p ctx, object_buffer_p obj_buffer) +{ + VAIQMatrixBufferMPEG2 *iq_matrix = (VAIQMatrixBufferMPEG2 *) obj_buffer->buffer_data; + ASSERT(obj_buffer->type == VAIQMatrixBufferType); + ASSERT(obj_buffer->num_elements == 1); + ASSERT(obj_buffer->size == sizeof(VAIQMatrixBufferMPEG2)); + + if ((obj_buffer->num_elements != 1) || + (obj_buffer->size != sizeof(VAIQMatrixBufferMPEG2))) { + return VA_STATUS_ERROR_UNKNOWN; + } + + /* Only update the qmatrix data if the load flag is set */ + if (iq_matrix->load_non_intra_quantiser_matrix) { + psb__MPEG2_convert_iq_matrix(ctx->qmatrix_data[NONINTRA_LUMA_Q], iq_matrix->non_intra_quantiser_matrix); + } + if (iq_matrix->load_intra_quantiser_matrix) { + psb__MPEG2_convert_iq_matrix(ctx->qmatrix_data[INTRA_LUMA_Q], iq_matrix->intra_quantiser_matrix); + } + /* We ignore the Chroma tables because those are not supported with VA_RT_FORMAT_YUV420 */ + ctx->got_iq_matrix = TRUE; + + return VA_STATUS_SUCCESS; +} + +/* + * Adds a VASliceParameterBuffer to the list of slice params + */ +static VAStatus psb__MPEG2_add_slice_param(context_MPEG2_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; +} + +/* Precalculated values */ +#define ADDR0 (0x00006000) +#define ADDR1 (0x0003f017) +#define ADDR2 (0x000ab0e5) +#define ADDR3 (0x0000016e) +#define WIDTH0 (0x0016c6ed) +#define OPCODE0 (0x00002805) + +static void psb__MPEG2_write_VLC_tables(context_MPEG2_p ctx) +{ + psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf; + + psb_cmdbuf_skip_start_block(cmdbuf, SKIP_ON_CONTEXT_SWITCH); + /* VLC Table */ + /* Write a LLDMA Cmd to transfer VLD Table data */ + psb_cmdbuf_lldma_write_cmdbuf(cmdbuf, &ctx->vlc_packed_table, 0, + sizeof(gaui16mpeg2VlcTableDataPacked), + 0, LLDMA_TYPE_VLC_TABLE); + + /* Write the vec registers with the index data for each of the tables and then write */ + /* the actual table data. */ + psb_cmdbuf_reg_start_block(cmdbuf); + psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0), ADDR0); + psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR1), ADDR1); + psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR2), ADDR2); + psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR3), ADDR3); + psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_WIDTH0), WIDTH0); + psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_OPCODE0), OPCODE0); + psb_cmdbuf_reg_end_block(cmdbuf); + + psb_cmdbuf_skip_end_block(cmdbuf); +} + +/* Programme the Alt output if there is a rotation*/ +static void psb__MPEG2_setup_alternative_frame(context_MPEG2_p ctx, IMG_BOOL write_reg) +{ + 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); + + RELOC(*ctx->p_range_mapping_base0, rotate_surface->buf.buffer_ofs, &rotate_surface->buf); + RELOC(*ctx->p_range_mapping_base1, rotate_surface->buf.buffer_ofs + rotate_surface->chroma_offset, &rotate_surface->buf); + + psb_cmdbuf_rendec_end(cmdbuf); + + if (write_reg) { + /* 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 has 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__MPEG2_set_operating_mode(context_MPEG2_p ctx) +{ + psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf; + psb_surface_p target_surface = ctx->obj_context->current_render_target->psb_surface; + + if (ctx->obj_context->rotate != VA_ROTATION_NONE) + psb__MPEG2_setup_alternative_frame(ctx, ctx->pic_params->picture_coding_extension.bits.progressive_frame); + + psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, DISPLAY_PICTURE_SIZE)); + psb_cmdbuf_rendec_write(cmdbuf, ctx->display_picture_size); + psb_cmdbuf_rendec_write(cmdbuf, ctx->coded_picture_size); + psb_cmdbuf_rendec_write(cmdbuf, ctx->obj_context->operating_mode); + + /* LUMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES */ + psb_cmdbuf_rendec_write_address(cmdbuf, &target_surface->buf, target_surface->buf.buffer_ofs); + + /* CHROMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES */ + psb_cmdbuf_rendec_write_address(cmdbuf, &target_surface->buf, target_surface->buf.buffer_ofs + target_surface->chroma_offset); + + psb_cmdbuf_rendec_end(cmdbuf); +} + +static void psb__MPEG2_set_reference_pictures(context_MPEG2_p ctx) +{ + psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf; + psb_surface_p target_surface = ctx->obj_context->current_render_target->psb_surface; + + psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, REFERENCE_PICTURE_BASE_ADDRESSES)); + + /* In MPEG2, the registers at N=0 are always used to store the base address of the luma and chroma buffers + of the most recently decoded reference picture. The registers at N=1 are used to store the base address + of the luma and chroma buffers of the older reference picture, if more than one reference picture is used. + This means that when decoding a P picture the forward reference picture’s address is at index 0. + When decoding a B-picture the backward reference picture’s address is at index 0 and the address of the + forward reference picture – which was decoded earlier than the backward reference – is at index 1. + */ + + switch (ctx->pic_params->picture_coding_type) { + case PICTURE_CODING_I: + psb__information_message(" I-Frame\n"); + /* No reference pictures */ + psb_cmdbuf_rendec_write(cmdbuf, 0); + psb_cmdbuf_rendec_write(cmdbuf, 0); + psb_cmdbuf_rendec_write(cmdbuf, 0); + psb_cmdbuf_rendec_write(cmdbuf, 0); + break; + + case PICTURE_CODING_P: + psb__information_message(" P-Frame\n"); + if (ctx->pic_params->picture_coding_extension.bits.is_first_field) { + /* forward reference picture */ + /* LUMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES */ + psb_cmdbuf_rendec_write_address(cmdbuf, &ctx->forward_ref_surface->psb_surface->buf, ctx->forward_ref_surface->psb_surface->buf.buffer_ofs); + + /* CHROMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES */ + 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); + + /* No backward reference picture */ + psb_cmdbuf_rendec_write(cmdbuf, 0); + psb_cmdbuf_rendec_write(cmdbuf, 0); + } else { + /* backward reference picture */ + /* LUMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES */ + psb_cmdbuf_rendec_write_address(cmdbuf, &target_surface->buf, target_surface->buf.buffer_ofs); + + /* CHROMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES */ + psb_cmdbuf_rendec_write_address(cmdbuf, &target_surface->buf, target_surface->buf.buffer_ofs + target_surface->chroma_offset); + + /* forward reference picture */ + /* LUMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES */ + psb_cmdbuf_rendec_write_address(cmdbuf, &ctx->forward_ref_surface->psb_surface->buf, ctx->forward_ref_surface->psb_surface->buf.buffer_ofs); + + /* CHROMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES */ + 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); + } + break; + + case PICTURE_CODING_B: + psb__information_message(" B-Frame\n"); + /* backward reference picture */ + /* LUMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES */ + psb_cmdbuf_rendec_write_address(cmdbuf, &ctx->backward_ref_surface->psb_surface->buf, ctx->backward_ref_surface->psb_surface->buf.buffer_ofs); + + /* CHROMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES */ + 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); + + /* forward reference picture */ + /* LUMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES */ + psb_cmdbuf_rendec_write_address(cmdbuf, &ctx->forward_ref_surface->psb_surface->buf, ctx->forward_ref_surface->psb_surface->buf.buffer_ofs); + + /* CHROMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES */ + 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); + break; + } + + psb_cmdbuf_rendec_end(cmdbuf); +} + +static void psb__MPEG2_set_picture_header(context_MPEG2_p ctx, VASliceParameterBufferMPEG2 *slice_param) +{ + psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf; + psb_surface_p target_surface = ctx->obj_context->current_render_target->psb_surface; + uint32_t FE_slice; + uint32_t BE_slice; + + psb_cmdbuf_reg_start_block(cmdbuf); + + /* VEC Control register: Front-End MPEG2 PPS0 */ + psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_VEC_MPEG2, CR_VEC_MPEG2_FE_PPS0) , ctx->FE_PPS0); + + /* VEC Control register: Front-End MPEG2 PPS1 */ + psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_VEC_MPEG2, CR_VEC_MPEG2_FE_PPS1) , ctx->FE_PPS1); + + /* Slice level */ + FE_slice = 0; + REGIO_WRITE_FIELD(FE_slice, + MSVDX_VEC_MPEG2, + CR_VEC_MPEG2_FE_SLICE, + FE_FIRST_IN_ROW, + (ctx->previous_slice_vertical_position != slice_param->slice_vertical_position)); + + REGIO_WRITE_FIELD(FE_slice, + MSVDX_VEC_MPEG2, + CR_VEC_MPEG2_FE_SLICE, + FE_SLICE_VERTICAL_POSITION_MINUS1, + slice_param->slice_vertical_position); + + REGIO_WRITE_FIELD(FE_slice, + MSVDX_VEC_MPEG2, + CR_VEC_MPEG2_FE_SLICE, + FE_QUANTISER_SCALE_CODE, + slice_param->quantiser_scale_code); + + psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_VEC_MPEG2, CR_VEC_MPEG2_FE_SLICE) , FE_slice); + + psb_cmdbuf_reg_end_block(cmdbuf); + + + /* BE Section */ + psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_VEC, MPEG2_CR_VEC_MPEG2_BE_SPS0)); + + psb_cmdbuf_rendec_write(cmdbuf, ctx->BE_SPS0); + psb_cmdbuf_rendec_write(cmdbuf, ctx->BE_SPS1); + psb_cmdbuf_rendec_write(cmdbuf, ctx->BE_PPS0); /* VEC Control register: Back-End MPEG2 PPS0 */ + psb_cmdbuf_rendec_write(cmdbuf, ctx->BE_PPS1); /* VEC Control register: Back-End MPEG2 PPS1 */ + psb_cmdbuf_rendec_write(cmdbuf, ctx->BE_PPS2); /* VEC Control register: Back-End MPEG2 PPS2 */ + + BE_slice = 0; + if (!ctx->pic_params->picture_coding_extension.bits.is_first_field) { + /* + BE_IP_PAIR_FLAG is 1 if the current picture_data is a P-coded field which is the 2nd field of a frame, + and which uses the first field of the frame (which was I-coded) as a reference. 0 otherwise. + BE_IP_PAIR_FLAG will only be 1 if BE_SECOND_FIELD_FLAG is 1, and the condition + of "this is a P-field which uses the accompanying I-field as a reference" is met. + */ + if (ctx->pic_params->picture_coding_type == PICTURE_CODING_P) { + if (GET_SURFACE_INFO_picture_coding_type(target_surface) == PICTURE_CODING_I) { + REGIO_WRITE_FIELD_LITE(BE_slice, + MSVDX_VEC_MPEG2, + CR_VEC_MPEG2_BE_SLICE, + BE_IP_PAIR_FLAG, 1); + } + } + + REGIO_WRITE_FIELD_LITE(BE_slice, + MSVDX_VEC_MPEG2, + CR_VEC_MPEG2_BE_SLICE, + BE_SECOND_FIELD_FLAG, 1); + + } else { + // BE_IP_PAIR_FLAG = 0; + // BE_SECOND_FIELD_FLAG = 0; + + /* Update with current settings first field */ + SET_SURFACE_INFO_is_defined(target_surface, TRUE); + SET_SURFACE_INFO_picture_structure(target_surface, ctx->pic_params->picture_coding_extension.bits.picture_structure); + SET_SURFACE_INFO_picture_coding_type(target_surface, ctx->pic_params->picture_coding_type); + } + + REGIO_WRITE_FIELD_LITE(BE_slice, + MSVDX_VEC_MPEG2, + CR_VEC_MPEG2_BE_SLICE, + BE_FIRST_IN_ROW, + (ctx->previous_slice_vertical_position != slice_param->slice_vertical_position)); + + REGIO_WRITE_FIELD_LITE(BE_slice, + MSVDX_VEC_MPEG2, + CR_VEC_MPEG2_BE_SLICE, + BE_SLICE_VERTICAL_POSITION_MINUS1, + slice_param->slice_vertical_position); + + REGIO_WRITE_FIELD_LITE(BE_slice, + MSVDX_VEC_MPEG2, + CR_VEC_MPEG2_BE_SLICE, + BE_QUANTISER_SCALE_CODE, + slice_param->quantiser_scale_code); + + psb__information_message("BE_slice = %08x first_field = %d\n", BE_slice, ctx->pic_params->picture_coding_extension.bits.is_first_field); + + psb_cmdbuf_rendec_write(cmdbuf, BE_slice); + + psb_cmdbuf_rendec_end(cmdbuf); + + ctx->previous_slice_vertical_position = slice_param->slice_vertical_position; +} + +static void psb__MPEG2_set_slice_params(context_MPEG2_p ctx) +{ + psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf; + + uint32_t cmd_data; + + psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, SLICE_PARAMS)); + + cmd_data = 0; /* Build slice parameters */ + REGIO_WRITE_FIELD(cmd_data, + MSVDX_CMDS, + SLICE_PARAMS, + SLICE_FIELD_TYPE, + ctx->pic_params->picture_coding_extension.bits.picture_structure - 1); + + REGIO_WRITE_FIELD(cmd_data, + MSVDX_CMDS, + SLICE_PARAMS, + SLICE_CODE_TYPE, + PICTURE_CODING_D == ctx->pic_params->picture_coding_type ? 0 : ctx->pic_params->picture_coding_type - 1); + + psb_cmdbuf_rendec_write(cmdbuf, cmd_data); + + *ctx->p_slice_params = cmd_data; + + psb_cmdbuf_rendec_end(cmdbuf); +} + +static void psb__MPEG2_write_qmatrices(context_MPEG2_p ctx) +{ + psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf; + int i; + + /* Since we only decode 4:2:0 We only need to the Intra tables. + Chroma quant tables are only used in Mpeg 4:2:2 and 4:4:4. + The hardware wants non-intra followed by intra */ + psb_cmdbuf_rendec_start(cmdbuf, REG_MSVDX_VEC_IQRAM_OFFSET); + + /* todo : optimisation here is to only load the need table */ + + /* NONINTRA_LUMA_Q --> REG_MSVDX_VEC_IQRAM_OFFSET + 0 */ + for (i = 0; i < 16; i++) { + psb_cmdbuf_rendec_write(cmdbuf, ctx->qmatrix_data[NONINTRA_LUMA_Q][i]); +// psb__information_message("NONINTRA_LUMA_Q[i] = %08x\n", ctx->qmatrix_data[NONINTRA_LUMA_Q][i]); + } + /* INTRA_LUMA_Q --> REG_MSVDX_VEC_IQRAM_OFFSET + (16*4) */ + for (i = 0; i < 16; i++) { + psb_cmdbuf_rendec_write(cmdbuf, ctx->qmatrix_data[INTRA_LUMA_Q][i]); +// psb__information_message("INTRA_LUMA_Q[i] = %08x\n", ctx->qmatrix_data[INTRA_LUMA_Q][i]); + } + + psb_cmdbuf_rendec_end(cmdbuf); +} + +static void psb__MPEG2_set_ent_dec(context_MPEG2_p ctx) +{ + psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf; + + uint32_t cmd_data; + + psb_cmdbuf_reg_start_block(cmdbuf); + + cmd_data = 0; /* Entdec Front-End controls */ + REGIO_WRITE_FIELD_LITE(cmd_data, MSVDX_VEC, CR_VEC_ENTDEC_FE_CONTROL, ENTDEC_FE_PROFILE, 1); /* MPEG2 Main Profile */ + REGIO_WRITE_FIELD_LITE(cmd_data, MSVDX_VEC, CR_VEC_ENTDEC_FE_CONTROL, ENTDEC_FE_MODE, 3); /* Set MPEG2 mode */ + + psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_VEC, CR_VEC_ENTDEC_FE_CONTROL), cmd_data); + + psb_cmdbuf_reg_end_block(cmdbuf); + + psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_VEC, CR_VEC_ENTDEC_BE_CONTROL)); + + cmd_data = 0; /* Entdec Back-End controls */ + REGIO_WRITE_FIELD(cmd_data, + MSVDX_VEC, + CR_VEC_ENTDEC_BE_CONTROL, + ENTDEC_BE_PROFILE, + 1); /* MPEG2 Main Profile */ + + REGIO_WRITE_FIELD(cmd_data, + MSVDX_VEC, + CR_VEC_ENTDEC_BE_CONTROL, + ENTDEC_BE_MODE, + 3); /* Set MPEG2 mode */ + + psb_cmdbuf_rendec_write(cmdbuf, cmd_data); + + psb_cmdbuf_rendec_end(cmdbuf); +} + +static void psb__MPEG2_write_kick(context_MPEG2_p ctx, VASliceParameterBufferMPEG2 *slice_param) +{ + psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf; + + (void) slice_param; /* Unused for now */ + + *cmdbuf->cmd_idx++ = CMD_COMPLETION; +} + +static void psb__MPEG2_FE_state(context_MPEG2_p ctx) +{ + psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf; + + /* See RENDER_BUFFER_HEADER */ + *cmdbuf->cmd_idx++ = CMD_HEADER_VC1; + + ctx->p_range_mapping_base0 = cmdbuf->cmd_idx++; + ctx->p_range_mapping_base1 = cmdbuf->cmd_idx++; + + *ctx->p_range_mapping_base0 = 0; + *ctx->p_range_mapping_base1 = 0; + + ctx->p_slice_params = cmdbuf->cmd_idx; + *cmdbuf->cmd_idx++ = 0; /* ui32SliceParams */ + + *cmdbuf->cmd_idx++ = 0; /* skip two lldma addr field */ + + *cmdbuf->cmd_idx++ = 0; + ctx->slice_first_pic_last = cmdbuf->cmd_idx++; +} + +static VAStatus psb__MPEG2_process_slice(context_MPEG2_p ctx, + VASliceParameterBufferMPEG2 *slice_param, + object_buffer_p obj_buffer) +{ + VAStatus vaStatus = VA_STATUS_SUCCESS; + + ASSERT((obj_buffer->type == VASliceDataBufferType) || (obj_buffer->type == VAProtectedSliceDataBufferType)); + + psb__information_message("MPEG2 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\n", slice_param->slice_vertical_position); + psb__information_message(" slice_data_flag = %d\n", slice_param->slice_data_flag); + psb__information_message(" coded size = %dx%d\n", ctx->picture_width_mb, ctx->picture_height_mb); + + 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 */ + psb_context_get_next_cmdbuf(ctx->obj_context); + + psb__MPEG2_FE_state(ctx); + psb__MPEG2_write_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, + 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__MPEG2_set_operating_mode(ctx); + + psb__MPEG2_set_reference_pictures(ctx); + + psb__MPEG2_set_picture_header(ctx, slice_param); + + psb__MPEG2_set_slice_params(ctx); + + psb__MPEG2_write_qmatrices(ctx); + + psb__MPEG2_set_ent_dec(ctx); + + psb__MPEG2_write_kick(ctx, slice_param); + + ctx->split_buffer_pending = FALSE; + ctx->obj_context->video_op = psb_video_vld; + ctx->obj_context->flags = FW_VA_RENDER_IS_VLD_NOT_MC; + ctx->obj_context->first_mb = 0; + + if (ctx->pic_params->picture_coding_extension.bits.progressive_frame) + ctx->obj_context->last_mb = ((ctx->picture_height_mb - 1) << 8) | (ctx->picture_width_mb - 1); + else + ctx->obj_context->last_mb = ((ctx->picture_height_mb / 2 - 1) << 8) | (ctx->picture_width_mb - 1); + + *ctx->slice_first_pic_last = (ctx->obj_context->first_mb << 16) | (ctx->obj_context->last_mb); + + if (psb_context_submit_cmdbuf(ctx->obj_context)) { + vaStatus = VA_STATUS_ERROR_UNKNOWN; + } + } + return vaStatus; +} + +static VAStatus psb__MPEG2_process_slice_data(context_MPEG2_p ctx, object_buffer_p obj_buffer) +{ + VAStatus vaStatus = VA_STATUS_SUCCESS; + VASliceParameterBufferMPEG2 *slice_param; + int buffer_idx = 0; + int element_idx = 0; + + ASSERT((obj_buffer->type == VASliceDataBufferType) || (obj_buffer->type == VAProtectedSliceDataBufferType)); + + ASSERT(ctx->got_iq_matrix); + ASSERT(ctx->pic_params); + ASSERT(ctx->slice_param_list_idx); + + if (!ctx->got_iq_matrix || !ctx->pic_params) { + /* IQ matrix or Picture params missing */ + return VA_STATUS_ERROR_UNKNOWN; + } + if ((NULL == obj_buffer->psb_buffer) || + (0 == obj_buffer->size)) { + /* We need to have data in the bitstream buffer */ + return VA_STATUS_ERROR_UNKNOWN; + } + + 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 = (VASliceParameterBufferMPEG2 *) slice_buf->buffer_data; + slice_param += element_idx; + element_idx++; + vaStatus = psb__MPEG2_process_slice(ctx, slice_param, obj_buffer); + if (vaStatus != VA_STATUS_SUCCESS) { + DEBUG_FAILURE; + break; + } + } + ctx->slice_param_list_idx = 0; + + return vaStatus; +} + +static void psb__MEPG2_send_highlevel_cmd(context_MPEG2_p ctx) +{ + uint32_t cmd; + 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; + + psb_cmdbuf_reg_start_block(cmdbuf); + psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_CMDS, DISPLAY_PICTURE_SIZE), ctx->display_picture_size); + psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_CMDS, CODED_PICTURE_SIZE), ctx->coded_picture_size); + + cmd = 0; + REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, OPERATING_MODE, CHROMA_FORMAT, 1); + REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, OPERATING_MODE, ASYNC_MODE, 1); // 0 = VDMC and VDEB active. 1 = VDEB pass-thru. + REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, OPERATING_MODE, CODEC_MODE, 3); // MPEG2 + REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, OPERATING_MODE, CODEC_PROFILE, 1); // MAIN + REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, OPERATING_MODE, ROW_STRIDE, target_surface->stride_mode); + psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_CMDS, OPERATING_MODE), cmd); + + psb_cmdbuf_reg_set_RELOC(cmdbuf, REGISTER_OFFSET(MSVDX_CMDS, LUMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES), + &target_surface->buf, target_surface->buf.buffer_ofs); + + psb_cmdbuf_reg_set_RELOC(cmdbuf, REGISTER_OFFSET(MSVDX_CMDS, CHROMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES), + &target_surface->buf, target_surface->buf.buffer_ofs + target_surface->chroma_offset); + + psb_cmdbuf_reg_set_RELOC(cmdbuf, REGISTER_OFFSET(MSVDX_CMDS, REFERENCE_PICTURE_BASE_ADDRESSES) + (0 * 8), + &target_surface->buf, target_surface->buf.buffer_ofs); + + psb_cmdbuf_reg_set_RELOC(cmdbuf, REGISTER_OFFSET(MSVDX_CMDS, REFERENCE_PICTURE_BASE_ADDRESSES) + 4 + (0 * 8), + &target_surface->buf, target_surface->buf.buffer_ofs + target_surface->chroma_offset); + + psb_cmdbuf_reg_set_RELOC(cmdbuf, REGISTER_OFFSET(MSVDX_CMDS, REFERENCE_PICTURE_BASE_ADDRESSES) + (1 * 8), + &target_surface->buf, target_surface->buf.buffer_ofs); + + psb_cmdbuf_reg_set_RELOC(cmdbuf, REGISTER_OFFSET(MSVDX_CMDS, REFERENCE_PICTURE_BASE_ADDRESSES) + 4 + (1 * 8), + &target_surface->buf, target_surface->buf.buffer_ofs + target_surface->chroma_offset); + + cmd = 0; + REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, SLICE_PARAMS, SLICE_FIELD_TYPE, 2); /* FRAME PICTURE -- ui8SliceFldType */ + REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, SLICE_PARAMS, SLICE_CODE_TYPE, 1); /* P PICTURE -- (ui8PicType == WMF_PTYPE_BI) ? WMF_PTYPE_I : (ui8PicType & 0x3) */ + psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_CMDS, SLICE_PARAMS), cmd); + *ctx->p_slice_params = cmd; + psb_cmdbuf_reg_end_block(cmdbuf); + + + psb_cmdbuf_reg_start_block(cmdbuf); + psb_cmdbuf_reg_set_RELOC(cmdbuf, REGISTER_OFFSET(MSVDX_CMDS, VC1_LUMA_RANGE_MAPPING_BASE_ADDRESS), + &rotate_surface->buf, rotate_surface->buf.buffer_ofs); + + psb_cmdbuf_reg_set_RELOC(cmdbuf, REGISTER_OFFSET(MSVDX_CMDS, VC1_CHROMA_RANGE_MAPPING_BASE_ADDRESS), + &rotate_surface->buf, rotate_surface->buf.buffer_ofs + rotate_surface->chroma_offset); + psb_cmdbuf_reg_end_block(cmdbuf); + + RELOC(*ctx->p_range_mapping_base0, rotate_surface->buf.buffer_ofs, &rotate_surface->buf); + RELOC(*ctx->p_range_mapping_base1, rotate_surface->buf.buffer_ofs + rotate_surface->chroma_offset, &rotate_surface->buf); +} + +static void psb__MEPG2_send_blit_cmd(context_MPEG2_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; + + psb_cmdbuf_reg_start_block(cmdbuf); + 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); + REGIO_WRITE_FIELD_LITE(cmd, MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION , ROTATION_MODE, rotate_surface->extra_info[5]); + psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION), cmd); + psb_cmdbuf_reg_end_block(cmdbuf); + + *cmdbuf->cmd_idx++ = 0x40000000; /* CMD_BLIT_CMD */ + *cmdbuf->cmd_idx++ = ctx->picture_width_mb; + *cmdbuf->cmd_idx++ = ctx->picture_height_mb; /* FIXME */ + *cmdbuf->cmd_idx++ = CMD_COMPLETION; +} + +static void psb__MPEG2_insert_blit_cmd_to_rotate(context_MPEG2_p ctx) +{ + psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf; + + /* See RENDER_BUFFER_HEADER */ + *cmdbuf->cmd_idx++ = CMD_HEADER_VC1; + + ctx->p_range_mapping_base0 = cmdbuf->cmd_idx++; + ctx->p_range_mapping_base1 = cmdbuf->cmd_idx++; + + *ctx->p_range_mapping_base0 = 0; + *ctx->p_range_mapping_base1 = 0; + + ctx->p_slice_params = cmdbuf->cmd_idx; + *cmdbuf->cmd_idx++ = 0; /* ui32SliceParams */ + + *cmdbuf->cmd_idx++ = 0; /* skip two lldma addr field */ + *cmdbuf->cmd_idx++ = 0; + + ctx->slice_first_pic_last = cmdbuf->cmd_idx++; + *ctx->slice_first_pic_last = 0; + + psb__MEPG2_send_highlevel_cmd(ctx); + psb__MEPG2_send_blit_cmd(ctx); + + ctx->obj_context->video_op = psb_video_mc; + ctx->obj_context->flags = FW_VA_RENDER_IS_LAST_SLICE; + + if (psb_context_submit_cmdbuf(ctx->obj_context)) { + ASSERT(0); + } +} + +static VAStatus pnw_MPEG2_BeginPicture( + object_context_p obj_context) +{ + INIT_CONTEXT_MPEG2 + + psb__information_message("pnw_MPEG2_BeginPicture\n"); + if (ctx->pic_params) { + free(ctx->pic_params); + ctx->pic_params = NULL; + } + ctx->previous_slice_vertical_position = ~1; + + return VA_STATUS_SUCCESS; +} + +static VAStatus pnw_MPEG2_RenderPicture( + object_context_p obj_context, + object_buffer_p *buffers, + int num_buffers) +{ + int i; + INIT_CONTEXT_MPEG2 + 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_MPEG2_RenderPicture got VAPictureParameterBuffer\n"); + vaStatus = psb__MPEG2_process_picture_param(ctx, obj_buffer); + DEBUG_FAILURE; + break; + + case VAIQMatrixBufferType: + psb__information_message("pnw_MPEG2_RenderPicture got VAIQMatrixBufferType\n"); + vaStatus = psb__MPEG2_process_iq_matrix(ctx, obj_buffer); + DEBUG_FAILURE; + break; + + case VASliceParameterBufferType: + psb__information_message("pnw_MPEG2_RenderPicture got VASliceParameterBufferType\n"); + vaStatus = psb__MPEG2_add_slice_param(ctx, obj_buffer); + DEBUG_FAILURE; + break; + + case VASliceDataBufferType: + case VAProtectedSliceDataBufferType: + + psb__information_message("pnw_MPEG2_RenderPicture got %s\n", SLICEDATA_BUFFER_TYPE(obj_buffer->type)); + vaStatus = psb__MPEG2_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_MPEG2_EndPicture( + object_context_p obj_context) +{ + VAStatus vaStatus = VA_STATUS_SUCCESS; + INIT_CONTEXT_MPEG2 + + psb__information_message("pnw_MPEG2_EndPicture\n"); + + if (ctx->obj_context->rotate != VA_ROTATION_NONE) { + if (!(ctx->pic_params->picture_coding_extension.bits.progressive_frame) && + !(ctx->pic_params->picture_coding_extension.bits.is_first_field)) + psb__MPEG2_insert_blit_cmd_to_rotate(ctx); + } + + if (psb_context_flush_cmdbuf(ctx->obj_context)) { + vaStatus = VA_STATUS_ERROR_UNKNOWN; + } + + if (ctx->pic_params) { + free(ctx->pic_params); + ctx->pic_params = NULL; + } + + return vaStatus; +} + +struct format_vtable_s pnw_MPEG2_vtable = { +queryConfigAttributes: + pnw_MPEG2_QueryConfigAttributes, +validateConfig: + pnw_MPEG2_ValidateConfig, +createContext: + pnw_MPEG2_CreateContext, +destroyContext: + pnw_MPEG2_DestroyContext, +beginPicture: + pnw_MPEG2_BeginPicture, +renderPicture: + pnw_MPEG2_RenderPicture, +endPicture: + pnw_MPEG2_EndPicture +}; |