blob: 2b82b3edca1de3cfcfc3236d2259d8858edacd21 [file] [log] [blame]
/*
* 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>
* Li Zeng <li.zeng@intel.com>
*
*/
#include "pnw_MPEG2.h"
#include "tng_vld_dec.h"
#include "psb_def.h"
#include "psb_drv_debug.h"
#include "pnw_rotate.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
#define HW_SUPPORTED_MAX_PICTURE_WIDTH_MPEG2_MP 1920
#define HW_SUPPORTED_MAX_PICTURE_HEIGHT_MPEG2_MP 1088
#define HW_SUPPORTED_MAX_PICTURE_WIDTH_MPEG2_SP 352
#define HW_SUPPORTED_MAX_PICTURE_HEIGHT_MPEG2_SP 288
#define CACHE_REF_OFFSET 72
#define CACHE_ROW_OFFSET 4
/************************************************************************************/
/* 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) )
static const 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 {
struct context_DEC_s dec_ctx;
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;
uint32_t slice_count;
/* IQ Matrix */
uint32_t qmatrix_data[MAX_QUANT_TABLES][16];
int got_iq_matrix;
/* VLC packed data */
struct psb_buffer_s vlc_packed_table;
/* Misc */
unsigned int previous_slice_vertical_position;
};
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 __maybe_unused profile,
VAEntrypoint __maybe_unused entrypoint,
VAConfigAttrib __maybe_unused * attrib_list,
int __maybe_unused num_attribs)
{
int i;
drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_MPEG2_QueryConfigAttributes\n");
for (i = 0; i < num_attribs; i++) {
switch (attrib_list[i].type) {
case VAConfigAttribMaxPictureWidth:
if (entrypoint == VAEntrypointVLD) {
if (profile == VAProfileMPEG2Simple)
attrib_list[i].value = HW_SUPPORTED_MAX_PICTURE_WIDTH_MPEG2_SP;
else if(profile == VAProfileMPEG2Main)
attrib_list[i].value = HW_SUPPORTED_MAX_PICTURE_WIDTH_MPEG2_MP;
else
attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
}
else
attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
break;
case VAConfigAttribMaxPictureHeight:
if (entrypoint == VAEntrypointVLD) {
if (profile == VAProfileMPEG2Simple)
attrib_list[i].value = HW_SUPPORTED_MAX_PICTURE_HEIGHT_MPEG2_SP;
else if(profile == VAProfileMPEG2Main)
attrib_list[i].value = HW_SUPPORTED_MAX_PICTURE_HEIGHT_MPEG2_MP;
}
else
attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
break;
default:
break;
}
}
}
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;
CHECK_CONTEXT(obj_context);
CHECK_CONFIG(obj_config);
/* 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 void psb__MPEG2_process_slice_data(context_DEC_p dec_ctx, VASliceParameterBufferBase *vld_slice_param);
static void psb__MPEG2_end_slice(context_DEC_p dec_ctx);
static void psb__MPEG2_begin_slice(context_DEC_p dec_ctx, VASliceParameterBufferBase *vld_slice_param);
static VAStatus pnw_MPEG2_process_buffer(context_DEC_p dec_ctx, object_buffer_p buffer);
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);
CHECK_VASTATUS();
CHECK_INVALID_PARAM(obj_context->num_render_targets < 1);
ctx = (context_MPEG2_p) calloc(1, sizeof(struct context_MPEG2_s));
CHECK_ALLOCATION(ctx);
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->dec_ctx.begin_slice = psb__MPEG2_begin_slice;
ctx->dec_ctx.process_slice = psb__MPEG2_process_slice_data;
ctx->dec_ctx.end_slice = psb__MPEG2_end_slice;
ctx->dec_ctx.process_buffer = pnw_MPEG2_process_buffer;
ctx->dec_ctx.preload_buffer = NULL;
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) {
unsigned char *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) {
vaStatus = vld_dec_CreateContext(&ctx->dec_ctx, obj_context);
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
vld_dec_DestroyContext(&ctx->dec_ctx);
psb_buffer_destroy(&ctx->vlc_packed_table);
if (ctx->pic_params) {
free(ctx->pic_params);
ctx->pic_params = NULL;
}
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)
{
object_surface_p obj_surface = ctx->obj_context->current_render_target;
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;
if (obj_surface->share_info) {
obj_surface->share_info->coded_width = ctx->coded_picture_width;
obj_surface->share_info->coded_height = ctx->coded_picture_height;
}
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);
psb_CheckInterlaceRotate(ctx->obj_context, (unsigned char*)ctx->pic_params);
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;
}
/* 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_dma_write_cmdbuf(cmdbuf, &ctx->vlc_packed_table, 0,
sizeof(gaui16mpeg2VlcTableDataPacked), 0,
DMA_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, 0);
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);
}
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;
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);
vld_dec_setup_alternative_frame(ctx->obj_context);
}
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;
if (ctx->slice_count != 0) {
psb_cmdbuf_skip_start_block(cmdbuf, SKIP_ON_CONTEXT_SWITCH);
}
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:
drv_debug_msg(VIDEO_DEBUG_GENERAL, " 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:
drv_debug_msg(VIDEO_DEBUG_GENERAL, " 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:
drv_debug_msg(VIDEO_DEBUG_GENERAL, " 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);
if (ctx->slice_count != 0) {
psb_cmdbuf_skip_end_block(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, 0);
/* 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);
FE_slice = 0;
REGIO_WRITE_FIELD_LITE(FE_slice,
MSVDX_VEC_MPEG2,
CR_VEC_MPEG2_FE_SPS0,
FE_HORIZONTAL_SIZE_MINUS1,
ctx->picture_width_mb - 1);
psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_VEC_MPEG2, CR_VEC_MPEG2_FE_SPS0) , 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);
drv_debug_msg(VIDEO_DEBUG_GENERAL, "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->dec_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]);
// drv_debug_msg(VIDEO_DEBUG_GENERAL, "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]);
// drv_debug_msg(VIDEO_DEBUG_GENERAL, "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, 0);
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);
psb_cmdbuf_rendec_start(cmdbuf, RENDEC_REGISTER_OFFSET(MSVDX_CMDS, MC_CACHE_CONFIGURATION));
cmd_data = 0;
REGIO_WRITE_FIELD_LITE(cmd_data, MSVDX_CMDS, MC_CACHE_CONFIGURATION, CONFIG_REF_OFFSET, CACHE_REF_OFFSET);
REGIO_WRITE_FIELD_LITE(cmd_data, MSVDX_CMDS, MC_CACHE_CONFIGURATION, CONFIG_ROW_OFFSET, CACHE_ROW_OFFSET);
psb_cmdbuf_rendec_write(cmdbuf, cmd_data);
psb_cmdbuf_rendec_end(cmdbuf);
}
static void psb__MPEG2_begin_slice(context_DEC_p dec_ctx, VASliceParameterBufferBase *vld_slice_param)
{
VASliceParameterBufferMPEG2 *slice_param = (VASliceParameterBufferMPEG2 *) vld_slice_param;
context_MPEG2_p ctx = (context_MPEG2_p)dec_ctx;
psb__MPEG2_write_VLC_tables(ctx);
dec_ctx->bits_offset = slice_param->macroblock_offset;
dec_ctx->SR_flags = CMD_SR_VERIFY_STARTCODE;
}
static void psb__MPEG2_process_slice_data(context_DEC_p dec_ctx, VASliceParameterBufferBase *vld_slice_param)
{
VASliceParameterBufferMPEG2 *slice_param = (VASliceParameterBufferMPEG2 *) vld_slice_param;
context_MPEG2_p ctx = (context_MPEG2_p)dec_ctx;
ctx->obj_context->first_mb = 0;
ctx->obj_context->first_mb = slice_param->slice_vertical_position << 8;
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);
}
static void psb__MPEG2_end_slice(context_DEC_p dec_ctx)
{
context_MPEG2_p ctx = (context_MPEG2_p)dec_ctx;
ctx->obj_context->flags = FW_VA_RENDER_IS_VLD_NOT_MC;
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->dec_ctx.slice_first_pic_last) = (ctx->obj_context->first_mb << 16) | (ctx->obj_context->last_mb);
ctx->slice_count++;
}
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->out_loop_surface;
psb_cmdbuf_reg_start_block(cmdbuf, 0);
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->dec_ctx.p_slice_params = cmd;
psb_cmdbuf_reg_end_block(cmdbuf);
psb_cmdbuf_reg_start_block(cmdbuf, 0);
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->dec_ctx.p_range_mapping_base0, rotate_surface->buf.buffer_ofs, &rotate_surface->buf);
RELOC(*ctx->dec_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->out_loop_surface;
psb_cmdbuf_reg_start_block(cmdbuf, 0);
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, GET_SURFACE_INFO_rotate(rotate_surface));
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->dec_ctx.p_range_mapping_base0 = cmdbuf->cmd_idx++;
ctx->dec_ctx.p_range_mapping_base1 = cmdbuf->cmd_idx++;
*ctx->dec_ctx.p_range_mapping_base0 = 0;
*ctx->dec_ctx.p_range_mapping_base1 = 0;
ctx->dec_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->dec_ctx.slice_first_pic_last = cmdbuf->cmd_idx++;
*ctx->dec_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
drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_MPEG2_BeginPicture\n");
if (ctx->pic_params) {
free(ctx->pic_params);
ctx->pic_params = NULL;
}
ctx->previous_slice_vertical_position = ~1;
ctx->slice_count = 0;
return VA_STATUS_SUCCESS;
}
static VAStatus pnw_MPEG2_process_buffer(
context_DEC_p dec_ctx,
object_buffer_p buffer)
{
context_MPEG2_p ctx = (context_MPEG2_p)dec_ctx;
VAStatus vaStatus = VA_STATUS_SUCCESS;
object_buffer_p obj_buffer = buffer;
switch (obj_buffer->type) {
case VAPictureParameterBufferType:
drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_MPEG2_RenderPicture got VAPictureParameterBuffer\n");
vaStatus = psb__MPEG2_process_picture_param(ctx, obj_buffer);
DEBUG_FAILURE;
break;
case VAIQMatrixBufferType:
drv_debug_msg(VIDEO_DEBUG_GENERAL,"pnw_MPEG2_RenderPicture got VAIQMatrixBufferType\n");
vaStatus = psb__MPEG2_process_iq_matrix(ctx, obj_buffer);
DEBUG_FAILURE;
break;
default:
vaStatus = VA_STATUS_ERROR_UNKNOWN;
DEBUG_FAILURE;
}
return vaStatus;
}
static VAStatus pnw_MPEG2_EndPicture(
object_context_p obj_context)
{
VAStatus vaStatus = VA_STATUS_SUCCESS;
INIT_CONTEXT_MPEG2
drv_debug_msg(VIDEO_DEBUG_GENERAL, "pnw_MPEG2_EndPicture\n");
if (CONTEXT_ROTATE(ctx->obj_context)) {
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;
}
ctx->slice_count = 0;
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:
vld_dec_RenderPicture,
endPicture:
pnw_MPEG2_EndPicture
};