1 /* 2 * Copyright (c) 2011 Intel Corporation. All Rights Reserved. 3 * Copyright (c) Imagination Technologies Limited, UK 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial portions 15 * of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * 25 * Authors: 26 * Shengquan Yuan <shengquan.yuan (at) intel.com> 27 * 28 */ 29 30 #include "psb_MPEG2.h" 31 #include "psb_def.h" 32 #include "psb_surface.h" 33 #include "psb_cmdbuf.h" 34 #include "psb_drv_debug.h" 35 36 #include "hwdefs/reg_io2.h" 37 #include "hwdefs/msvdx_offsets.h" 38 #include "hwdefs/msvdx_cmds_io2.h" 39 #include "hwdefs/msvdx_vdmc_reg_io2.h" 40 #include "hwdefs/msvdx_vec_reg_io2.h" 41 #include "hwdefs/msvdx_vec_mpeg2_reg_io2.h" 42 #include "hwdefs/dxva_fw_ctrl.h" 43 44 #include <stdlib.h> 45 #include <stdint.h> 46 #include <string.h> 47 48 49 /* TODO: for interlace 50 * bit 0: first vector forward 51 * bit 1: first vector backward 52 * bit 2: second vector forward 53 * bit 3: second vector backward 54 */ 55 #define MBPARAM_MvertFieldSel_3(ptr) (((ptr)->motion_vertical_field_select & 0x8) >> 3) 56 #define MBPARAM_MvertFieldSel_2(ptr) (((ptr)->motion_vertical_field_select & 0x4) >> 2) 57 #define MBPARAM_MvertFieldSel_1(ptr) (((ptr)->motion_vertical_field_select & 0x2) >> 1) 58 #define MBPARAM_MvertFieldSel_0(ptr) (((ptr)->motion_vertical_field_select & 0x1) >> 0) 59 #define MBPARAM_MotionType(ptr) (((ptr)->macroblock_modes.bits.frame_motion_type << 1) | (ptr)->macroblock_modes.bits.field_motion_type) 60 #define MBPARAM_MotionBackward(ptr) (((ptr)->macroblock_type & VA_MB_TYPE_MOTION_BACKWARD)?1:0) 61 #define MBPARAM_MotionForward(ptr) (((ptr)->macroblock_type & VA_MB_TYPE_MOTION_FORWARD)?1:0) 62 #define MBPARAM_IntraMacroblock(ptr) ((ptr)->macroblock_type & VA_MB_TYPE_MOTION_INTRA ) 63 #define MBPARAM_CodedBlockPattern(ptr) ((ptr)->coded_block_pattern << 6) /* align with VA code */ 64 #define MBPARAM_MBskipsFollowing(ptr) ((ptr)->num_skipped_macroblocks) 65 66 typedef enum { MB_CODE_TYPE_I , MB_CODE_TYPE_P , MB_CODE_TYPE_B , MB_CODE_TYPE_GMC } eMB_CODE_TYPE; 67 68 /* Constants */ 69 #define PICTURE_CODING_I 0x01 70 #define PICTURE_CODING_P 0x02 71 #define PICTURE_CODING_B 0x03 72 73 #define CODEC_MODE_MPEG2 3 74 #define CODEC_PROFILE_MPEG2_MAIN 1 75 76 /* picture structure */ 77 #define TOP_FIELD 1 78 #define BOTTOM_FIELD 2 79 #define FRAME_PICTURE 3 80 81 #define INTRA_MB_WORST_CASE 6 82 #define INTER_MB_WORST_CASE 100 83 84 static const uint32_t pict_libva2msvdx[] = {0,/* Invalid picture type */ 85 0,/* I picture */ 86 1,/* P picture */ 87 2,/* B pricture */ 88 3 89 };/* Invalid picture type */ 90 91 92 static const uint32_t ft_libva2msvdx[] = {0,/* Invalid picture type */ 93 0,/* Top field */ 94 1,/* Bottom field */ 95 2 96 };/* Frame picture */ 97 98 99 struct context_MPEG2MC_s { 100 object_context_p obj_context; /* back reference */ 101 102 VAMacroblockParameterBufferMPEG2 *mb_param ; /* Pointer to the mbCtrl structure */ 103 uint32_t mb_in_buffer; /* Number of MBs in current buffer */ 104 uint32_t mb_first_addr; /* MB address of first mb in buffer */ 105 106 uint32_t picture_coding_type; 107 uint32_t picture_structure; 108 109 uint32_t coded_picture_width; 110 uint32_t coded_picture_height; 111 112 uint32_t picture_width_mb; /* in macroblocks */ 113 uint32_t picture_height_mb; /* in macroblocks */ 114 uint32_t size_mb; /* in macroblocks */ 115 116 VAPictureParameterBufferMPEG2 *pic_params; 117 118 object_surface_p forward_ref_surface; 119 object_surface_p backward_ref_surface; 120 121 uint32_t ref_indexA; 122 uint32_t ref_indexB; 123 124 uint32_t coded_picture_size; 125 uint32_t display_picture_size; 126 uint32_t operation_mode; 127 128 uint32_t *lldma_idx; /* Index in command stream for LLDMA pointer */ 129 uint32_t residual_pendingDMA; 130 IMG_INT32 residual_sent; 131 132 psb_buffer_p residual_buf; 133 uint32_t blk_in_buffer;/* buffer elements */ 134 uint32_t blk_size;/* buffer elements size */ 135 136 uint32_t fstmb_slice; 137 }; 138 139 typedef struct context_MPEG2MC_s *context_MPEG2MC_p; 140 141 #define INIT_CONTEXT_MPEG2MC context_MPEG2MC_p ctx = (context_MPEG2MC_p) obj_context->format_data 142 #define SURFACE(id) ((object_surface_p) object_heap_lookup( &ctx->obj_context->driver_data->surface_heap, id )) 143 144 static void psb__MPEG2MC_send_interPB_prediction( 145 context_MPEG2MC_p ctx, 146 psb_cmdbuf_p const cmdbuf, 147 VAMacroblockParameterBufferMPEG2 * const mb_param, 148 int second_pred 149 ) 150 { 151 uint32_t cmd; 152 uint32_t blk_size; 153 uint32_t pred_offset; 154 155 /* Determine residual data's block size (16x8 or 16x16) */ 156 if (FRAME_PICTURE == ctx->picture_structure) { 157 if ((1 == MBPARAM_MotionType(mb_param)) || /* Field MC */ 158 (3 == MBPARAM_MotionType(mb_param))) { /* Dual Prime */ 159 blk_size = 1; /* 16 x 8 */ 160 } else { 161 blk_size = 0; /* 16 x 16 */ 162 } 163 } else { 164 if (2 == MBPARAM_MotionType(mb_param)) { /* Non-Frame MC */ 165 blk_size = 1; /* 16 x 8 */ 166 } else { 167 blk_size = 0; /* 16 x 16 */ 168 } 169 } 170 171 /* Determine whether this is for 1st MV or 2nd MV */ 172 if (TRUE == second_pred) { 173 pred_offset = 8; 174 } else { 175 pred_offset = 0; 176 } 177 178 cmd = 0; 179 180 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, INTER_PRED_BLOCK_SIZE, blk_size); 181 182 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A, ctx->ref_indexA); 183 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_B, ctx->ref_indexB); 184 185 if (3 == MBPARAM_MotionType(mb_param)) { /* Dual Prime */ 186 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A_VALID, 1); 187 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_B_VALID, 1); 188 } else { 189 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A_VALID, 190 MBPARAM_MotionForward(mb_param)); 191 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_B_VALID, 192 MBPARAM_MotionBackward(mb_param)); 193 } 194 195 if (FRAME_PICTURE == ctx->picture_structure) { 196 /* Frame picture processing */ 197 if ((1 == MBPARAM_MotionType(mb_param)) || /* Field MC */ 198 (3 == MBPARAM_MotionType(mb_param))) { /* Dual Prime */ 199 if ((1 == MBPARAM_MotionForward(mb_param)) || 200 (3 == MBPARAM_MotionType(mb_param))) { /* Dual Prime */ 201 if (second_pred) { 202 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, 203 REF_INDEX_FIELD_A, MBPARAM_MvertFieldSel_2(mb_param)); 204 } else { 205 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, 206 REF_INDEX_FIELD_A, MBPARAM_MvertFieldSel_0(mb_param)); 207 } 208 } 209 210 if ((1 == MBPARAM_MotionBackward(mb_param)) || 211 (3 == MBPARAM_MotionType(mb_param))) { /* Dual Prime */ 212 if (second_pred) { 213 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, 214 REF_INDEX_FIELD_B, MBPARAM_MvertFieldSel_3(mb_param)); 215 } else { 216 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, 217 REF_INDEX_FIELD_B, MBPARAM_MvertFieldSel_1(mb_param)); 218 } 219 } 220 } 221 } else { 222 /* Field picture processing */ 223 if ((0 == MBPARAM_MotionForward(mb_param)) && 224 (0 == MBPARAM_MotionBackward(mb_param))) { 225 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A, ctx->ref_indexA); 226 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_B, ctx->ref_indexB); 227 } 228 229 if (1 == MBPARAM_MotionForward(mb_param)) { 230 if (second_pred) { 231 if ((0 == MBPARAM_MvertFieldSel_2(mb_param)) && 232 (PICTURE_CODING_P == ctx->picture_coding_type)) { /* Top field of this frame */ 233 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A, ctx->ref_indexB); 234 } else { /* Bottom field of previous frame*/ 235 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A, ctx->ref_indexA); 236 } 237 238 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_FIELD_A, 239 MBPARAM_MvertFieldSel_2(mb_param)); 240 } else { 241 if (((ctx->picture_structure == BOTTOM_FIELD) != MBPARAM_MvertFieldSel_0(mb_param)) && 242 (PICTURE_CODING_P == ctx->picture_coding_type)) { /* Top field of this frame */ 243 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A, ctx->ref_indexB); 244 } else { /* Bottom field of previous frame*/ 245 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A, ctx->ref_indexA); 246 } 247 248 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_FIELD_A, 249 MBPARAM_MvertFieldSel_0(mb_param)); 250 } 251 } 252 253 254 if (1 == MBPARAM_MotionBackward(mb_param)) { 255 if (second_pred) { 256 if ((1 == MBPARAM_MvertFieldSel_3(mb_param)) && 257 (PICTURE_CODING_P == ctx->picture_coding_type)) { /* Top field of this frame */ 258 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_B, ctx->ref_indexA); 259 } else { /* Bottom field of previous frame*/ 260 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_B, ctx->ref_indexB); 261 } 262 263 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_FIELD_B, 264 MBPARAM_MvertFieldSel_3(mb_param)); 265 } else { 266 if ((1 == MBPARAM_MvertFieldSel_1(mb_param)) && 267 (PICTURE_CODING_P == ctx->picture_coding_type)) { /* Top field of this frame */ 268 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_B, ctx->ref_indexA); 269 } else { /* Bottom field of previous frame*/ 270 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_B, ctx->ref_indexB); 271 } 272 273 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_FIELD_B, 274 MBPARAM_MvertFieldSel_1(mb_param)); 275 } 276 } 277 } 278 279 /* Dual Prime */ 280 if (3 == MBPARAM_MotionType(mb_param) && (ctx->picture_structure != FRAME_PICTURE)) { 281 if (ctx->picture_structure == TOP_FIELD) { 282 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A, 0); 283 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_FIELD_A, 0); 284 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_FIELD_B, 1); 285 } else { 286 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_A, 1); 287 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_FIELD_A, 1); 288 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTER_BLOCK_PREDICTION, REF_INDEX_FIELD_B, 0); 289 } 290 } 291 292 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, INTER_BLOCK_PREDICTION) + pred_offset, cmd); 293 } 294 295 typedef struct _PSB_MVvalue { 296 short horz; 297 short vert; 298 } psb_MVvalue, *psb_MVvalue_p; 299 300 #define MV_LIBVA2PSB(mb_param) \ 301 do { \ 302 MVector[0].horz = mb_param->PMV[0][0][0]; \ 303 MVector[0].vert = mb_param->PMV[0][0][1]; \ 304 \ 305 MVector[1].horz = mb_param->PMV[0][1][0]; \ 306 MVector[1].vert = mb_param->PMV[0][1][1]; \ 307 \ 308 MVector[2].horz = mb_param->PMV[1][0][0]; \ 309 MVector[2].vert = mb_param->PMV[1][0][1]; \ 310 \ 311 MVector[3].horz = mb_param->PMV[1][1][0]; \ 312 MVector[3].vert = mb_param->PMV[1][1][1]; \ 313 } while (0) 314 315 static void psb__MPEG2MC_send_motion_vectores( 316 context_MPEG2MC_p const ctx, 317 psb_cmdbuf_p cmdbuf, 318 VAMacroblockParameterBufferMPEG2 * const mb_param 319 ) 320 { 321 uint32_t cmd = 0; 322 uint32_t MV1Address = 0; 323 uint32_t MV2Address = 0; 324 325 psb_MVvalue MVector[4]; 326 327 MV_LIBVA2PSB(mb_param); 328 329 MV1Address = 0x00; 330 MV2Address = 0x00; 331 332 if (FRAME_PICTURE == ctx->picture_structure) { 333 /* FRAME PICTURE PROCESSING */ 334 if (2 == MBPARAM_MotionType(mb_param)) { /* Frame MC */ 335 if ((0 == MBPARAM_MotionForward(mb_param)) && 336 (0 == MBPARAM_MotionBackward(mb_param))) { 337 cmd = 0; 338 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_X, 0); 339 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, 0); 340 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, MOTION_VECTOR) , cmd); 341 } else { 342 if (1 == MBPARAM_MotionForward(mb_param)) { 343 cmd = 0; 344 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_X, MVector[0].horz << 1); 345 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[0].vert << 1); 346 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, MOTION_VECTOR) , cmd); 347 } 348 349 if (1 == MBPARAM_MotionBackward(mb_param)) { 350 cmd = 0; 351 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_X, MVector[1].horz << 1); 352 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[1].vert << 1); 353 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, MOTION_VECTOR) + 0x10 , cmd); 354 } 355 } 356 } else { 357 if ((1 == MBPARAM_MotionType(mb_param)) || /* Field MC */ 358 (3 == MBPARAM_MotionType(mb_param))) { /* Dual Prime */ 359 /* 360 * Vertical motion vectors for fields located in frame pictures 361 * should be divided by 2 (MPEG-2 7.6.3.1). Thus the original value 362 * contained in the stream is equivalent to 1/4-pel format; the 363 * resolution required by MSVDX. 364 */ 365 if ((1 == MBPARAM_MotionForward(mb_param)) || 366 (3 == MBPARAM_MotionType(mb_param))) { /* Dual Prime */ 367 cmd = 0; 368 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_X, MVector[0].horz << 1); 369 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[0].vert); 370 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, MOTION_VECTOR) , cmd); 371 } 372 373 if ((1 == MBPARAM_MotionBackward(mb_param)) || 374 (3 == MBPARAM_MotionType(mb_param))) { /* Dual Prime */ 375 cmd = 0; 376 377 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_X, MVector[1].horz << 1); 378 379 if (3 == MBPARAM_MotionType(mb_param)) { /* Dual Prime */ 380 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[1].vert << 1); 381 } else { 382 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[1].vert); 383 } 384 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, MOTION_VECTOR) + 0x10 , cmd); 385 } 386 387 /* Fields and Dual Prime are 16x8 and need 2nd inter_block_pred cmd */ 388 psb__MPEG2MC_send_interPB_prediction(ctx, cmdbuf, mb_param, IMG_TRUE); 389 390 if ((1 == MBPARAM_MotionForward(mb_param)) || 391 (3 == MBPARAM_MotionType(mb_param))) { /* Dual Prime */ 392 cmd = 0; 393 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_X, MVector[2].horz << 1); 394 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[2].vert); 395 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, MOTION_VECTOR) + 0x40 , cmd); 396 } 397 398 if ((1 == MBPARAM_MotionBackward(mb_param)) || 399 (3 == MBPARAM_MotionType(mb_param))) { /* Dual Prime */ 400 cmd = 0; 401 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_X, MVector[3].horz << 1); 402 if (3 == MBPARAM_MotionType(mb_param)) { /* Dual Prime */ 403 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[3].vert << 1); 404 } else { 405 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[3].vert); 406 } 407 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, MOTION_VECTOR) + 0x50 , cmd); 408 } 409 } 410 } 411 } else { 412 /* FIELD PICTURE PROCESSING */ 413 int MV0index = 0, MV1index = 1; 414 415 if ((ctx->picture_structure == BOTTOM_FIELD) && (3 == MBPARAM_MotionType(mb_param))) { 416 MV0index = 1; 417 MV1index = 0; 418 } 419 420 if ((1 == MBPARAM_MotionForward(mb_param)) || /* Forward MV */ 421 (3 == MBPARAM_MotionType(mb_param))) { /* Dual Prime */ 422 cmd = 0; 423 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_X, MVector[MV0index].horz << 1); 424 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[MV0index].vert << 1); 425 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, MOTION_VECTOR) , cmd); 426 427 } 428 429 if ((1 == MBPARAM_MotionBackward(mb_param)) || /* Backward MV */ 430 (3 == MBPARAM_MotionType(mb_param))) { /* Dual Prime */ 431 cmd = 0; 432 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_X, MVector[MV1index].horz << 1); 433 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[MV1index].vert << 1); 434 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, MOTION_VECTOR) + 0x10, cmd); 435 } 436 437 if (2 == MBPARAM_MotionType(mb_param)) { /* 16x8 MC */ 438 psb__MPEG2MC_send_interPB_prediction(ctx, cmdbuf, mb_param, IMG_TRUE); 439 440 if ((1 == MBPARAM_MotionForward(mb_param)) || /* Forward MV */ 441 (3 == MBPARAM_MotionType(mb_param))) { /* Dual Prime */ 442 cmd = 0; 443 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_X, MVector[2].horz << 1); 444 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[2].vert << 1); 445 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, MOTION_VECTOR) + 0x40, cmd); 446 } 447 448 if ((1 == MBPARAM_MotionBackward(mb_param)) || /* Backward MV */ 449 (3 == MBPARAM_MotionType(mb_param))) { /* Dual Prime */ 450 cmd = 0; 451 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_X, MVector[3].horz << 1); 452 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MOTION_VECTOR, MV_Y, MVector[3].vert << 1); 453 454 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, MOTION_VECTOR) + 0x50, cmd); 455 } 456 } 457 } 458 } 459 460 461 /* Send macroblock_number command to MSVDX. */ 462 static void psb__MPEG2MC_send_mb_number( 463 context_MPEG2MC_p const ctx, 464 psb_cmdbuf_p cmdbuf, 465 const uint32_t mb_addr, 466 const uint32_t motion_type, 467 const eMB_CODE_TYPE MB_coding_type 468 ) 469 { 470 uint32_t cmd; 471 uint32_t mb_x; 472 473 /* 3.3.21. Macroblock Number */ 474 cmd = 0; 475 476 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_ERROR_FLAG, 0); 477 478 /* 479 MB_FIELD_CODE (MC + VDEB): Indicate if the macroblock is field predicted (when = 1), 480 or frame predicted (when VDEB = 0). 481 MPEG2: For Interlaced frame, derived from frame_motion_type, else same 482 frame/filed type as SLICE_FIELD_TYPE 483 484 */ 485 if (FRAME_PICTURE == ctx->picture_structure) { 486 if ((0 == motion_type) || 487 (2 == motion_type)) { 488 /* MB is frame predicted */ 489 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_FIELD_CODE, 0); 490 } else { /* MB is field predicted */ 491 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_FIELD_CODE, 1); 492 } 493 } else { /* MB is field predicted */ 494 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_FIELD_CODE, 1); 495 } 496 497 ASSERT((0 != ctx->picture_coding_type) && (4 != ctx->picture_coding_type)); 498 499 /* 500 MB_CODE_TYPE (MC + VDEB): Indicate macroblock type is I, P, B or MPEG4 S(GMC). 501 0x0: I or SI macroblock 502 0x1: P or SP macroblock 503 0x2: B macroblock 504 0x3: MPEG4 GMC 505 MPEG2: Derived from macroblock_type 506 */ 507 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_CODE_TYPE, (uint32_t) MB_coding_type); 508 509 510 /* 511 MB_NO_Y (MC + VDEB): Vertical offset of current Macroblock (where 0 = topmost macroblock of picture) 512 Derived from macroblock number divided by picture width in macroblocks. 513 MB_NO_X (MC + VDEB): Horizontal offset of current Macroblock (where 0 = leftmost macroblock of picture) 514 Derived from macroblock number mod picture width in macroblocks. 515 */ 516 if ((FRAME_PICTURE != ctx->picture_structure) && 517 (mb_addr / ctx->picture_width_mb)) { 518 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_NO_Y, (mb_addr / ctx->picture_width_mb) * 2); 519 } else { 520 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_NO_Y, mb_addr / ctx->picture_width_mb); 521 } 522 523 mb_x = mb_addr % ctx->picture_width_mb; 524 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_NUMBER, MB_NO_X, mb_x); 525 /* 526 Only defined for current MB, set to 0 for above1 and above2. 527 Indicate if MB is on Left Hand Side of slice or picture 528 0: MB is not on left hand side of slice or picture 529 1: MB is on left hand side of slice or picture 530 */ 531 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_NUMBER , MB_SLICE_LHS, ctx->fstmb_slice || (mb_x == 0)); 532 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_NUMBER , MB_SLICE_TOP, 1); 533 534 psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_CMDS, MACROBLOCK_NUMBER) , cmd); 535 } 536 537 static void psb__MPEG2MC_finalise_residDMA( 538 context_MPEG2MC_p const ctx 539 ) 540 { 541 uint32_t *save_idx = ctx->obj_context->cmdbuf->cmd_idx; 542 ctx->obj_context->cmdbuf->cmd_idx = ctx->lldma_idx; 543 if (ctx->residual_pendingDMA) { 544 #if 0 545 if (ctx->residual_pendingDMA != (ctx->blk_size * ctx->blk_in_buffer)) { 546 drv_debug_msg(VIDEO_DEBUG_ERROR, "psb__MPEG2MC_finalise_residDMA:residual_pendingDMA=%d(block:%d)," 547 "actual data size=%d (block:%d)\n", 548 ctx->residual_pendingDMA, ctx->residual_pendingDMA / ctx->blk_size, 549 ctx->blk_size * ctx->blk_in_buffer, 550 ctx->blk_in_buffer); 551 } 552 #endif 553 554 psb_cmdbuf_lldma_write_cmdbuf(ctx->obj_context->cmdbuf, 555 ctx->residual_buf, 556 ctx->residual_sent, 557 ctx->residual_pendingDMA, 558 0, 559 LLDMA_TYPE_RESIDUAL); 560 } else { 561 //*ctx->obj_context->cmdbuf->cmd_idx = CMD_NOP; 562 *ctx->obj_context->cmdbuf->cmd_idx = 0xf000000; 563 } 564 ctx->obj_context->cmdbuf->cmd_idx = save_idx; 565 ctx->residual_sent += ctx->residual_pendingDMA; 566 ctx->residual_pendingDMA = 0; 567 } 568 569 static void psb__MPEG2MC_check_segment_residDMA( 570 context_MPEG2MC_p const ctx, 571 uint32_t min_space 572 ) 573 { 574 if (psb_cmdbuf_segment_space(ctx->obj_context->cmdbuf) < min_space) { 575 psb__MPEG2MC_finalise_residDMA(ctx); 576 577 psb_cmdbuf_next_segment(ctx->obj_context->cmdbuf); 578 579 ctx->lldma_idx = ctx->obj_context->cmdbuf->cmd_idx++; /* Insert the LLDMA record here later */ 580 } 581 } 582 583 584 /* Send residual difference data to MSVDX. */ 585 static void psb__MPEG2MC_send_residual( 586 context_MPEG2MC_p ctx, 587 uint32_t pattern_code) 588 { 589 uint8_t pattern_code_byte = (uint8_t)(pattern_code >> 6); 590 uint8_t blocks = 0; 591 592 while (pattern_code_byte) { 593 blocks += (pattern_code_byte & 1); 594 pattern_code_byte >>= 1; 595 } 596 597 if (PICTURE_CODING_I == ctx->picture_coding_type) { 598 ctx->residual_pendingDMA += blocks * (8 * 8); /* 8bit */ 599 } else { 600 /* We do not suport ConfigSpatialResid8==1 */ 601 /* ASSERT(ConfigSpatialResid8 == 0); */ 602 ctx->residual_pendingDMA += blocks * (8 * 8) * 2;/* 16 bit */ 603 } 604 } 605 606 607 static void psb__MPEG2MC_send_slice_parameters( 608 context_MPEG2MC_p const ctx 609 ) 610 { 611 psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf; 612 uint32_t cmd; 613 614 ctx->lldma_idx = ctx->obj_context->cmdbuf->cmd_idx++; /* Insert the LLDMA record here later */ 615 616 psb_cmdbuf_reg_start_block(cmdbuf, 0); 617 618 /* 3.3.19. Slice Params*/ 619 /* 620 3:2 SLICE_FIELD_TYPE (MC+VDEB) Indicate if slice is a frame, top fie 621 0x0: Top field picture 622 0x1: Bottom field picture 623 0x2: Frame picture 624 1:0 SLICE_CODE_TYPE (MC+VDEB) Indicate if it is an I, P, B slice 625 0x0: I slice 626 0x1: P slice 627 0x2: B slice 628 0x3: S(GMC) (MPEG4 only) 629 */ 630 cmd = 0; 631 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, SLICE_PARAMS, SLICE_FIELD_TYPE, 632 ft_libva2msvdx[ctx->picture_structure]); 633 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, SLICE_PARAMS, SLICE_CODE_TYPE, 634 pict_libva2msvdx[ctx->picture_coding_type]); 635 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, SLICE_PARAMS), cmd); 636 637 psb_cmdbuf_reg_end_block(cmdbuf); 638 } 639 640 static void psb__MPEG2MC_send_slice_picture_endcommand( 641 context_MPEG2MC_p const ctx, 642 int end_picture 643 ) 644 { 645 psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf; 646 uint32_t cmd; 647 648 /* 649 3.3.22. End Slice/Picture 650 Offset: 0x0404 651 This command is sent at the end of a slice or picture. The final macroblock of slice/picture will not be 652 processed until this command is sent. The End Slice/Picture commands can be sent more than once 653 at the end of a slice (provided no other commands are interleaved). 654 If the command is sent more than once at the end of a slice, the first command should indicate the 655 end of the slice (no data bits set) with repeat commands used to indicate end of slice, flushing VDEB 656 buffers or picture end. The FLUSH_VDEB_BUFFERS bit should not be set in any repeat commands 657 sent after a command in which the PICTURE_END bit is set. 658 31:2 - Reserved 659 1 FLUSH_VDEB_BUFFERS(VDEB) If set, indicates VDEB should flush its internal buffers to system memory 660 when slice processing is complete 661 0 PICTURE_END(MC + VDEB) If set, indicates both Picture and Slice end, otherwise Slice end 662 */ 663 psb_cmdbuf_reg_start_block(cmdbuf, 0); 664 665 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, END_SLICE_PICTURE), 0); 666 667 if (end_picture) { 668 cmd = 0; 669 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, END_SLICE_PICTURE, PICTURE_END, end_picture); 670 psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_CMDS, END_SLICE_PICTURE), cmd); 671 } 672 673 psb_cmdbuf_reg_end_block(cmdbuf); 674 } 675 676 static void psb__MPEG2MC_send_highlevel_commands( 677 context_MPEG2MC_p const ctx 678 ) 679 { 680 psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf; 681 psb_surface_p target_surface = ctx->obj_context->current_render_target->psb_surface; 682 683 psb_cmdbuf_reg_start_block(cmdbuf, 0); 684 685 /* 3.3.1. Display Picture Size */ 686 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, DISPLAY_PICTURE_SIZE), ctx->display_picture_size); 687 688 /* 3.3.2. Coded Picture Size*/ 689 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, CODED_PICTURE_SIZE), ctx->coded_picture_size); 690 691 /* 3.3.3. Operating Mode */ 692 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, OPERATING_MODE), ctx->obj_context->operating_mode); 693 694 /* 3.3.4. Luma Reconstructed Picture Base Address */ 695 psb_cmdbuf_reg_set_RELOC(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, LUMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES), 696 &target_surface->buf, 0); 697 698 /* 3.3.5. Chroma Reconstructed Picture Base Address */ 699 psb_cmdbuf_reg_set_RELOC(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, CHROMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES), 700 &target_surface->buf, target_surface->chroma_offset); 701 702 /* 3.3.13. Reference Picture Base Addresses */ 703 /* 704 Reference Picture Base Addresses 705 Offset: 0x0100 + N*8 = Luma base addresses 706 Offset: 0x0104 + N*8 = Chroma base addresses 707 This register can store up to 16 luma picture base addresses and 16 chroma picture base addresses. 708 Luma and chroma ref base registers are interleaved. 709 710 Bit Symbol Used Description 711 31:12 LUMA_REF_BASE_ADDR MC Luma picture base byte address [31:12] 712 11:0 - Reserved 713 Bit Symbol Used Description 714 31:12 CHROMA_REF_BASE_ADDR MC Chroma picture base byte address [31:12] 715 11:0 - Reserved 716 - In MPEG2, the registers at N=0 are always used to store the base address of the luma and 717 chroma buffers of the most recently decoded reference picture. The registers at N=1 are used 718 to store the base address of the luma and chroma buffers of the older reference picture, if 719 more than one reference picture is used. This means that when decoding a P picture the 720 forward reference pictures address is at index 0. When decoding a B-picture the backward 721 reference pictures address is at index 0 and the address of the forward reference picture 722 which was decoded earlier than the backward reference is at index 1. 723 */ 724 725 /* WABA: backward / forward refs are always set, even when they aren't strictly needed */ 726 psb_surface_p forward_surface = ctx->forward_ref_surface->psb_surface; 727 psb_surface_p backward_surface = ctx->backward_ref_surface->psb_surface; 728 729 if (backward_surface) { 730 psb_cmdbuf_reg_set_RELOC(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, REFERENCE_PICTURE_BASE_ADDRESSES) + (0 * 8), 731 &backward_surface->buf, 0); 732 733 psb_cmdbuf_reg_set_RELOC(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, REFERENCE_PICTURE_BASE_ADDRESSES) + 4 + (0 * 8), 734 &backward_surface->buf, backward_surface->chroma_offset); 735 } 736 if (forward_surface) { 737 psb_cmdbuf_reg_set_RELOC(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, REFERENCE_PICTURE_BASE_ADDRESSES) + (1 * 8), 738 &forward_surface->buf, 0); 739 740 psb_cmdbuf_reg_set_RELOC(cmdbuf , REGISTER_OFFSET(MSVDX_CMDS, REFERENCE_PICTURE_BASE_ADDRESSES) + 4 + (1 * 8), 741 &forward_surface->buf, forward_surface->chroma_offset); 742 } 743 744 /* 745 * VDMC_RESIDUAL_DIRECT_INSERT_CONTROL, spec p 159 746 * 0 VDMC_RESIDUAL_DIRECT_CONTROL (VDMC) residual direct insert control. 747 * Control insertion of spatial residual data. When set to 1 residual 748 * data taken from writes to VDMC_RESIDUAL_DIRECT_INSERT_DATA 749 * when set to 0, residual data taken from vEC 750 */ 751 psb_cmdbuf_reg_set(cmdbuf , REGISTER_OFFSET(MSVDX_VDMC, CR_VDMC_RESIDUAL_DIRECT_INSERT_CONTROL), 1); 752 753 psb_cmdbuf_reg_end_block(cmdbuf); 754 } 755 756 757 758 /* Control building of the MSVDX command buffer for a B and P pictures.*/ 759 static void psb__MPEG2MC_interPB_mb( 760 context_MPEG2MC_p const ctx, 761 VAMacroblockParameterBufferMPEG2 * const mb_param 762 ) 763 { 764 psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf; 765 uint32_t cmd; 766 767 psb_cmdbuf_reg_start_block(cmdbuf, 0); 768 769 /* 3.3.21. Macroblock Number */ 770 psb__MPEG2MC_send_mb_number(ctx, cmdbuf, mb_param->macroblock_address, MBPARAM_MotionType(mb_param), 771 MBPARAM_IntraMacroblock(mb_param) ? MB_CODE_TYPE_I : pict_libva2msvdx[ctx->picture_coding_type] 772 ); 773 774 cmd = 0; 775 /* Only used for direct insert of residual data;- 776 00 = 8-bit signed data 777 01 = 8-bit unsigned data 778 10 = 16-bit signed 779 11 = Reserved 780 */ 781 /* TODO:: ASSERT(ConfigSpatialResid8==0 ); */ 782 if (MBPARAM_IntraMacroblock(mb_param)) { 783 if (1/* TODO:: ConfigIntraResidUnsigned == 0 */) { 784 /* sent as as 16 bit signed relative to 128*/ 785 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, VA_ADD_128, 1); 786 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, VA_DATA_FORMAT, 2); 787 } else { /* ConfigIntraResidUnsigned == 1 */ 788 /* 16 bit unsigned unsigned relative to 0*/ 789 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, VA_ADD_128, 0); 790 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, VA_DATA_FORMAT, 2); 791 } 792 } else { 793 /* For non-intra in Inter frames : 16 bit signed */ 794 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, VA_ADD_128, 0); 795 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, VA_DATA_FORMAT, 2); 796 } 797 798 799 if (FRAME_PICTURE == ctx->picture_structure) { 800 /* mb_param->macroblock_modes.bits.dct_type =1: field DCT */ 801 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, RESIDUAL_FIELD_CODED, mb_param->macroblock_modes.bits.dct_type ? 1 : 0); 802 } else { 803 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, RESIDUAL_FIELD_CODED, 1); 804 } 805 806 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, CR_FROM_VEC, 807 ((MBPARAM_CodedBlockPattern(mb_param) & 0x40) ? 1 : 0)); 808 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, CB_FROM_VEC, 809 ((MBPARAM_CodedBlockPattern(mb_param) & 0x80) ? 1 : 0)); 810 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, Y3_FROM_VEC, 811 ((MBPARAM_CodedBlockPattern(mb_param) & 0x100) ? 1 : 0)); 812 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, Y2_FROM_VEC, 813 ((MBPARAM_CodedBlockPattern(mb_param) & 0x200) ? 1 : 0)); 814 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, Y1_FROM_VEC, 815 ((MBPARAM_CodedBlockPattern(mb_param) & 0x400) ? 1 : 0)); 816 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, Y0_FROM_VEC, 817 ((MBPARAM_CodedBlockPattern(mb_param) & 0x800) ? 1 : 0)); 818 psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT) , cmd); 819 820 /* Send Residuals */ 821 if (MBPARAM_IntraMacroblock(mb_param)) { 822 cmd = 0; 823 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTRA_BLOCK_PREDICTION, INTRA_PRED_MODE0, 0); 824 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTRA_BLOCK_PREDICTION, INTRA_PRED_MODE1, 0); 825 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTRA_BLOCK_PREDICTION, INTRA_PRED_MODE2, 0); 826 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTRA_BLOCK_PREDICTION, INTRA_PRED_MODE3, 0); 827 psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_CMDS, INTRA_BLOCK_PREDICTION) , cmd); 828 829 psb__MPEG2MC_send_residual(ctx, MBPARAM_CodedBlockPattern(mb_param)); 830 } else { 831 psb__MPEG2MC_send_interPB_prediction(ctx, cmdbuf, mb_param, IMG_FALSE); 832 833 /* Send motion vectors */ 834 psb__MPEG2MC_send_motion_vectores(ctx, cmdbuf, mb_param); 835 836 psb__MPEG2MC_send_residual(ctx, MBPARAM_CodedBlockPattern(mb_param)); 837 } 838 839 psb_cmdbuf_reg_end_block(cmdbuf); 840 } 841 842 843 844 /* Process Macroblocks of a B or P picture.*/ 845 static VAStatus psb__MPEG2MC_process_mbs_interPB( 846 context_MPEG2MC_p const ctx 847 ) 848 { 849 uint32_t skip_count = 0; 850 VAMacroblockParameterBufferMPEG2 *mb_param = NULL; 851 VAMacroblockParameterBufferMPEG2 mbparam_skip; 852 853 uint32_t mb_pending = ctx->mb_in_buffer; 854 uint32_t mb_addr = ctx->mb_first_addr; 855 uint32_t mb_last = mb_addr + mb_pending; 856 mb_param = (VAMacroblockParameterBufferMPEG2 *) ctx->mb_param; 857 858 /* Proccess all VA_MBctrl_P_HostResidDiff_1 structure in the buffer 859 * - this may genererate more macroblocks due to skipped 860 */ 861 while (mb_pending || skip_count) { 862 uint32_t mb_in_buffer = (ctx->picture_width_mb); 863 psb_cmdbuf_p cmdbuf; 864 unsigned char *cmd_start; 865 866 ctx->fstmb_slice = IMG_TRUE; 867 868 psb_context_get_next_cmdbuf(ctx->obj_context); 869 cmdbuf = ctx->obj_context->cmdbuf; 870 cmd_start = (unsigned char *) cmdbuf->cmd_idx; 871 872 /* Build the high-level commands */ 873 psb__MPEG2MC_send_highlevel_commands(ctx); 874 875 psb__MPEG2MC_send_slice_parameters(ctx); 876 877 /* Process all the macroblocks in the slice */ 878 while ((mb_pending || skip_count) && mb_in_buffer--) { 879 /* Check for segment space - do we have space for at least one more 880 * worst case InterMB plus completion 881 */ 882 psb__MPEG2MC_check_segment_residDMA(ctx, INTER_MB_WORST_CASE + 2); 883 884 if (skip_count) { /* Skipped macroblock processing */ 885 mbparam_skip.macroblock_address++; 886 887 ASSERT(mb_param->macroblock_address < ctx->size_mb); 888 ASSERT(mbparam_skip.macroblock_address == mb_addr); 889 890 psb__MPEG2MC_interPB_mb(ctx, &mbparam_skip); 891 892 skip_count--; 893 } else { 894 ASSERT(mb_pending); 895 ASSERT(mb_param->macroblock_address < ctx->size_mb); 896 ASSERT(mb_param->macroblock_address == mb_addr); 897 898 psb__MPEG2MC_interPB_mb(ctx, mb_param); 899 900 skip_count = MBPARAM_MBskipsFollowing(mb_param); 901 if (skip_count) { 902 memcpy(&mbparam_skip, mb_param, sizeof(mbparam_skip)); 903 } 904 905 mb_param++; 906 mb_pending--; 907 } 908 909 ctx->fstmb_slice = IMG_FALSE; 910 911 mb_addr++; 912 } 913 914 /* Tell hardware we're done */ 915 psb__MPEG2MC_send_slice_picture_endcommand(ctx, (mb_pending == 0) && (skip_count == 0) && (ctx->size_mb == mb_last)); 916 psb__MPEG2MC_finalise_residDMA(ctx); 917 918 /* write_kick */ 919 *cmdbuf->cmd_idx++ = CMD_COMPLETION; 920 921 ctx->obj_context->video_op = psb_video_mc; 922 ctx->obj_context->flags = (mb_pending == 0) && (skip_count == 0) && (ctx->size_mb == mb_last) ? FW_VA_RENDER_IS_LAST_SLICE : 0; 923 ctx->obj_context->first_mb = 0; 924 ctx->obj_context->last_mb = 0; 925 psb_context_submit_cmdbuf(ctx->obj_context); 926 927 /* check if the remained cmdbuf size can fill the commands of next slice */ 928 if (1 || (cmdbuf->lldma_base - (unsigned char *) cmdbuf->cmd_idx) < ((unsigned char *) cmdbuf->cmd_idx - cmd_start)) 929 psb_context_flush_cmdbuf(ctx->obj_context); 930 } 931 932 return VA_STATUS_SUCCESS; 933 } 934 935 936 static void psb__MPEG2MC_intra_mb( 937 context_MPEG2MC_p const ctx, 938 const VAMacroblockParameterBufferMPEG2* const mb_param 939 ) 940 { 941 psb_cmdbuf_p cmdbuf = ctx->obj_context->cmdbuf; 942 uint32_t cmd; 943 944 psb_cmdbuf_reg_start_block(cmdbuf, 0); 945 946 /* 3.3.21. Macroblock Number */ 947 psb__MPEG2MC_send_mb_number(ctx, cmdbuf, mb_param->macroblock_address, MBPARAM_MotionType(mb_param), MB_CODE_TYPE_I); 948 949 /*3.3.25. Macroblock Residual Format */ 950 cmd = 0; 951 952 /* In INTRA pictures, spatial-blocks are always 8bit when BBP is 8 */ 953 /* 00 = 8-bit signed data 954 * 01 = 8-bit unsigned data 955 */ 956 if (1/* TODO:: ConfigIntraResidUnsigned==0 */) { 957 /* spec p67: 958 * VA_ADD_128 MC Only used for direct insert of residual data;- 959 * 0: add 0 to residual data input 960 * 1: indicates 128 should be added to residual data input 961 * 962 * VA_DATA_FORMAT:Only used for direct insert of residual data;- 963 * 0x0: 8-bit signed data 964 * 0x1: 8-bit unsigned data 965 * 0x2: 16-bit signed 966 */ 967 /* Sent as 8 bit signed relative to 128 */ 968 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, VA_DATA_FORMAT, 0); /* ok ish */ 969 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, VA_ADD_128, 1); /* ok ish */ 970 } else { 971 /* Sent as 8 bit unsigned relative to 0 */ 972 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, VA_DATA_FORMAT, 1); 973 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, VA_ADD_128, 0); 974 } 975 976 if (FRAME_PICTURE == ctx->picture_structure) { 977 /* 978 * RESIDUAL_FIELD_CODED MC 979 * 0: residual data frame coded 980 * 1: (luma)residual data field coded 981 * N.B. For VC1, MPEG4 and MPEG2, if SLICE_FIELD_TYPE = 982 * frame, chroma residual will be frame coded, even if the luma 983 * residual is field coded. 984 */ 985 /* 986 * (VA:wMBType bit 5: FieldResidual, wMBtype & 0x20)/libVA(dct_type:1 field DCT): 987 * Indicates whether the residual difference blocks use a field IDCT structure as specified in MPEG-2. 988 * 989 * Must be 1 if the bPicStructure member of VA_PictureParameters is 1 or 2. When used for MPEG-2, 990 * FieldResidual must be zero if the frame_pred_frame_DCT variable in the MPEG-2 syntax is 1, and 991 * must be equal to the dct_type variable in the MPEG-2 syntax if dct_type is present for the macroblock. 992 */ 993 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, 994 RESIDUAL_FIELD_CODED, ((mb_param->macroblock_modes.bits.dct_type) ? 1 : 0)); 995 } else { 996 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, RESIDUAL_FIELD_CODED, 1); 997 } 998 999 /* CR_FROM_VEC MC 0: constant zero residual 1000 1: block Cr provided by VEC 1001 (If REVERSE_FLAG_ORDER=1, this bit indicates if Y0 provided) 1002 CB_FROM_VEC MC 0: constant zero residual 1003 1: block Cb provided by VEC 1004 (If REVERSE_FLAG_ORDER=1, this bit indicates if Y1 provided) 1005 Y3_FROM_VEC MC 0: constant zero residual 1006 1: block Y3 provided by VEC 1007 (If REVERSE_FLAG_ORDER=1, this bit indicates if Y2 provided) 1008 Y2_FROM_VEC MC 0: constant zero residual 1009 1: block Y2 provided by VEC 1010 (If REVERSE_FLAG_ORDER=1, this bit indicates if Y3 provided) 1011 Y1_FROM_VEC MC 0: constant zero residual 1012 1: block Y1 provided by VEC 1013 (If REVERSE_FLAG_ORDER=1, this bit indicates if Cb provided) 1014 Y0_FROM_VEC MC 0: constant zero residual 1015 1: block Y0 provided by VEC 1016 (If REVERSE_FLAG_ORDER=1, this bit indicates if Cr provided) 1017 */ 1018 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, CR_FROM_VEC, 1019 ((MBPARAM_CodedBlockPattern(mb_param) & 0x40) ? 1 : 0)); 1020 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, CB_FROM_VEC, 1021 ((MBPARAM_CodedBlockPattern(mb_param) & 0x80) ? 1 : 0)); 1022 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, Y3_FROM_VEC, 1023 ((MBPARAM_CodedBlockPattern(mb_param) & 0x100) ? 1 : 0)); 1024 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, Y2_FROM_VEC, 1025 ((MBPARAM_CodedBlockPattern(mb_param) & 0x200) ? 1 : 0)); 1026 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, Y1_FROM_VEC, 1027 ((MBPARAM_CodedBlockPattern(mb_param) & 0x400) ? 1 : 0)); 1028 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT, Y0_FROM_VEC, 1029 ((MBPARAM_CodedBlockPattern(mb_param) & 0x800) ? 1 : 0)); 1030 psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_CMDS, MACROBLOCK_RESIDUAL_FORMAT) , cmd); 1031 1032 /* Send Residuals, spec p69,h264 only */ 1033 cmd = 0; 1034 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTRA_BLOCK_PREDICTION, INTRA_PRED_MODE0, 0); 1035 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTRA_BLOCK_PREDICTION, INTRA_PRED_MODE1, 0); 1036 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTRA_BLOCK_PREDICTION, INTRA_PRED_MODE2, 0); 1037 REGIO_WRITE_FIELD(cmd, MSVDX_CMDS, INTRA_BLOCK_PREDICTION, INTRA_PRED_MODE3, 0); 1038 psb_cmdbuf_reg_set(cmdbuf, REGISTER_OFFSET(MSVDX_CMDS, INTRA_BLOCK_PREDICTION) , cmd); 1039 1040 psb__MPEG2MC_send_residual(ctx, MBPARAM_CodedBlockPattern(mb_param)); 1041 1042 psb_cmdbuf_reg_end_block(cmdbuf); 1043 } 1044 1045 1046 static VAStatus psb__MPEG2MC_process_mbs_intra( 1047 context_MPEG2MC_p const ctx 1048 ) 1049 { 1050 const VAMacroblockParameterBufferMPEG2* mb_param = NULL; 1051 uint32_t mb_pending = ctx->mb_in_buffer; 1052 uint32_t mb_addr = ctx->mb_first_addr; 1053 uint32_t mb_last = mb_addr + mb_pending; 1054 1055 mb_param = (VAMacroblockParameterBufferMPEG2*) ctx->mb_param; 1056 1057 while (mb_pending) { /* one slice per loop */ 1058 uint32_t mb_in_buffer = min(mb_pending, ctx->picture_width_mb); 1059 psb_cmdbuf_p cmdbuf; 1060 unsigned char *cmd_start; 1061 1062 mb_pending -= mb_in_buffer; 1063 1064 psb_context_get_next_cmdbuf(ctx->obj_context); 1065 cmdbuf = ctx->obj_context->cmdbuf; 1066 cmd_start = (unsigned char *) cmdbuf->cmd_idx; 1067 1068 ctx->fstmb_slice = IMG_TRUE; 1069 1070 /* Build the high-level commands */ 1071 psb__MPEG2MC_send_highlevel_commands(ctx); 1072 1073 psb__MPEG2MC_send_slice_parameters(ctx); 1074 1075 /* Process all the macroblocks in the slice */ 1076 while (mb_in_buffer--) { /* for every MB */ 1077 ASSERT(mb_param->macroblock_address < ctx->size_mb); 1078 ASSERT(mb_param->macroblock_address == mb_addr); 1079 1080 /* Check for segment space - do we have space for at least one more 1081 * worst case IntraMB plus completion 1082 */ 1083 psb__MPEG2MC_check_segment_residDMA(ctx, INTRA_MB_WORST_CASE + 2); 1084 1085 psb__MPEG2MC_intra_mb(ctx, mb_param); 1086 1087 mb_param++; /* next macroblock parameter */ 1088 mb_addr++; 1089 1090 ctx->fstmb_slice = IMG_FALSE; 1091 } 1092 1093 psb__MPEG2MC_send_slice_picture_endcommand(ctx, (mb_pending == 0) && (ctx->size_mb == mb_last)); /* Tell hardware we're done */ 1094 1095 psb__MPEG2MC_finalise_residDMA(ctx); 1096 1097 /* write_kick */ 1098 *cmdbuf->cmd_idx++ = CMD_COMPLETION; 1099 1100 ctx->obj_context->video_op = psb_video_mc; 1101 ctx->obj_context->flags = (mb_pending == 0) && (ctx->size_mb == mb_last) ? FW_VA_RENDER_IS_LAST_SLICE : 0; 1102 ctx->obj_context->first_mb = 0; 1103 ctx->obj_context->last_mb = 0; 1104 psb_context_submit_cmdbuf(ctx->obj_context); 1105 1106 /* check if the remained cmdbuf size can fill the commands of next slice */ 1107 if (1 || (cmdbuf->lldma_base - (unsigned char *) cmdbuf->cmd_idx) < ((unsigned char *) cmdbuf->cmd_idx - cmd_start)) 1108 psb_context_flush_cmdbuf(ctx->obj_context); 1109 } 1110 1111 //ASSERT(ctx->residual_bytes == 0); /* There should be no more data left */ 1112 1113 return VA_STATUS_SUCCESS; 1114 } 1115 1116 1117 static VAStatus psb__MPEG2MC_process_picture_param(context_MPEG2MC_p ctx, object_buffer_p obj_buffer) 1118 { 1119 int coded_pic_height; 1120 1121 /* Take a copy of the picture parameters */ 1122 ctx->pic_params = (VAPictureParameterBufferMPEG2 *) obj_buffer->buffer_data; 1123 obj_buffer->buffer_data = NULL; 1124 obj_buffer->size = 0; 1125 1126 ctx->picture_coding_type = ctx->pic_params->picture_coding_type; 1127 ctx->picture_structure = ctx->pic_params->picture_coding_extension.bits.picture_structure; 1128 1129 ctx->forward_ref_surface = SURFACE(ctx->pic_params->forward_reference_picture); 1130 ctx->backward_ref_surface = SURFACE(ctx->pic_params->backward_reference_picture); 1131 1132 /* Set picture type and reference indices for reference frames */ 1133 if (ctx->picture_coding_type != PICTURE_CODING_I) { 1134 if (ctx->pic_params->picture_coding_extension.bits.is_first_field) { /* first field */ 1135 if (ctx->backward_ref_surface) { 1136 ctx->picture_coding_type = PICTURE_CODING_B; 1137 ctx->ref_indexA = 0x01;/* Forward reference frame*/ 1138 ctx->ref_indexB = 0x00;/* Backward reference frame*/ 1139 } else { 1140 ctx->picture_coding_type = PICTURE_CODING_P; 1141 ctx->ref_indexA = 0x00; /* Always reference frame 0*/ 1142 } 1143 } else { 1144 if ((PICTURE_CODING_B == ctx->picture_coding_type) && (ctx->backward_ref_surface)) { 1145 ctx->picture_coding_type = PICTURE_CODING_B; 1146 ctx->ref_indexA = 0x01; /* Forward reference frame*/ 1147 ctx->ref_indexB = 0x00;/* Backward reference frame */ 1148 } else { 1149 ctx->picture_coding_type = PICTURE_CODING_P; 1150 if (ctx->forward_ref_surface) { 1151 ctx->ref_indexA = 0x00; 1152 } else { 1153 ctx->ref_indexA = 0x01; 1154 ctx->ref_indexB = 0x00; 1155 } 1156 } 1157 } 1158 } 1159 ctx->pic_params->picture_coding_type = ctx->picture_coding_type; 1160 1161 /* residual data size per element */ 1162 if (ctx->picture_coding_type == PICTURE_CODING_I) { 1163 ctx->blk_size = 64; /* unsigned char */ 1164 } else { 1165 ctx->blk_size = 2 * 64; /* unsigned short */ 1166 } 1167 1168 if (ctx->picture_coding_type != PICTURE_CODING_I) { 1169 if (ctx->backward_ref_surface) { 1170 if (ctx->forward_ref_surface == NULL) 1171 ctx->forward_ref_surface = ctx->backward_ref_surface; 1172 } else { 1173 ctx->backward_ref_surface = ctx->forward_ref_surface; 1174 } 1175 } 1176 if (NULL == ctx->backward_ref_surface) { 1177 ctx->backward_ref_surface = ctx->obj_context->current_render_target; 1178 } 1179 if (NULL == ctx->forward_ref_surface) { 1180 ctx->forward_ref_surface = ctx->obj_context->current_render_target; 1181 } 1182 1183 ctx->coded_picture_width = ctx->pic_params->horizontal_size; 1184 ctx->coded_picture_height = ctx->pic_params->vertical_size; 1185 ctx->picture_width_mb = ctx->pic_params->horizontal_size / 16; 1186 if (ctx->pic_params->picture_coding_extension.bits.progressive_frame == 1) /* should be progressive_sequence? */ 1187 ctx->picture_height_mb = (ctx->coded_picture_height + 15) / 16; 1188 else { 1189 if (FRAME_PICTURE != ctx->picture_structure) { /*Interlaced Field Pictures */ 1190 ctx->picture_height_mb = ((ctx->coded_picture_height + 31) / 32); 1191 } else { 1192 ctx->picture_height_mb = 2 * ((ctx->coded_picture_height + 31) / 32); 1193 } 1194 } 1195 coded_pic_height = (ctx->picture_structure != FRAME_PICTURE) ? 1196 ((ctx->picture_height_mb) * 32) : ((ctx->picture_height_mb) * 16); 1197 ctx->size_mb = ctx->picture_width_mb * (coded_pic_height >> 4); 1198 1199 ctx->display_picture_size = 0; 1200 REGIO_WRITE_FIELD_LITE(ctx->display_picture_size, MSVDX_CMDS, 1201 DISPLAY_PICTURE_SIZE, DISPLAY_PICTURE_HEIGHT, ctx->coded_picture_height - 1); 1202 REGIO_WRITE_FIELD_LITE(ctx->display_picture_size, MSVDX_CMDS, 1203 DISPLAY_PICTURE_SIZE, DISPLAY_PICTURE_WIDTH, ctx->coded_picture_width - 1); 1204 1205 ctx->coded_picture_size = 0; 1206 REGIO_WRITE_FIELD_LITE(ctx->coded_picture_size, MSVDX_CMDS, 1207 CODED_PICTURE_SIZE, CODED_PICTURE_HEIGHT, ctx->coded_picture_height - 1); 1208 REGIO_WRITE_FIELD_LITE(ctx->coded_picture_size, MSVDX_CMDS, 1209 CODED_PICTURE_SIZE, CODED_PICTURE_WIDTH, ctx->coded_picture_width - 1); 1210 1211 ctx->obj_context->operating_mode = 0; 1212 REGIO_WRITE_FIELD(ctx->obj_context->operating_mode, MSVDX_CMDS, OPERATING_MODE, CHROMA_FORMAT, 1); 1213 REGIO_WRITE_FIELD(ctx->obj_context->operating_mode, MSVDX_CMDS, OPERATING_MODE, ASYNC_MODE, 1); 1214 /* 0 = VDMC and VDEB active. 1 = VDEB pass-thru. */ 1215 REGIO_WRITE_FIELD(ctx->obj_context->operating_mode, MSVDX_CMDS, OPERATING_MODE, 1216 CODEC_MODE, CODEC_MODE_MPEG2); 1217 REGIO_WRITE_FIELD(ctx->obj_context->operating_mode, MSVDX_CMDS, OPERATING_MODE, 1218 CODEC_PROFILE, CODEC_PROFILE_MPEG2_MAIN); 1219 REGIO_WRITE_FIELD(ctx->obj_context->operating_mode, MSVDX_CMDS, OPERATING_MODE, 1220 ROW_STRIDE, (ctx->obj_context->current_render_target->psb_surface->stride_mode)); 1221 1222 return VA_STATUS_SUCCESS; 1223 } 1224 1225 1226 1227 static void psb_MPEG2MC_QueryConfigAttributes( 1228 VAProfile profile, 1229 VAEntrypoint entrypoint, 1230 VAConfigAttrib *attrib_list, 1231 int num_attribs) 1232 { 1233 /* No MPEG2 specific attributes */ 1234 } 1235 1236 static VAStatus psb_MPEG2MC_ValidateConfig( 1237 object_config_p obj_config) 1238 { 1239 int i; 1240 /* Check all attributes */ 1241 for (i = 0; i < obj_config->attrib_count; i++) { 1242 switch (obj_config->attrib_list[i].type) { 1243 case VAConfigAttribRTFormat: 1244 /* Ignore */ 1245 break; 1246 1247 default: 1248 return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED; 1249 } 1250 } 1251 1252 return VA_STATUS_SUCCESS; 1253 } 1254 1255 static VAStatus psb__MPEG2MC_check_legal_picture(object_context_p obj_context, object_config_p obj_config) 1256 { 1257 VAStatus vaStatus = VA_STATUS_SUCCESS; 1258 1259 if (NULL == obj_context) { 1260 vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT; 1261 DEBUG_FAILURE; 1262 return vaStatus; 1263 } 1264 1265 if (NULL == obj_config) { 1266 vaStatus = VA_STATUS_ERROR_INVALID_CONFIG; 1267 DEBUG_FAILURE; 1268 return vaStatus; 1269 } 1270 1271 /* MSVDX decode capability for MPEG2: 1272 * MP@HL 1273 * 1274 * Refer to Table 8-11 (Upper bounds for luminance sample rate) of ISO/IEC 13818-2: 1995(E), 1275 * and the "MSVDX MPEG2 decode capability" table of "Poulsbo Media Software Overview" 1276 */ 1277 1278 switch (obj_config->profile) { 1279 case VAProfileMPEG2Simple: 1280 if ((obj_context->picture_width <= 0) || (obj_context->picture_width > 352) 1281 || (obj_context->picture_height <= 0) || (obj_context->picture_height > 288)) { 1282 vaStatus = VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED; 1283 } 1284 break; 1285 1286 case VAProfileMPEG2Main: 1287 if ((obj_context->picture_width <= 0) || (obj_context->picture_width > 1920) 1288 || (obj_context->picture_height <= 0) || (obj_context->picture_height > 1088)) { 1289 vaStatus = VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED; 1290 } 1291 break; 1292 1293 default: 1294 vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE; 1295 break; 1296 } 1297 1298 return vaStatus; 1299 } 1300 1301 static VAStatus psb_MPEG2MC_CreateContext( 1302 object_context_p obj_context, 1303 object_config_p obj_config) 1304 { 1305 VAStatus vaStatus = VA_STATUS_SUCCESS; 1306 context_MPEG2MC_p ctx; 1307 1308 /* Validate flag */ 1309 /* Validate picture dimensions */ 1310 vaStatus = psb__MPEG2MC_check_legal_picture(obj_context, obj_config); 1311 if (VA_STATUS_SUCCESS != vaStatus) { 1312 DEBUG_FAILURE; 1313 return vaStatus; 1314 } 1315 1316 if (obj_context->num_render_targets < 1) { 1317 vaStatus = VA_STATUS_ERROR_UNKNOWN; 1318 DEBUG_FAILURE; 1319 return vaStatus; 1320 } 1321 1322 ctx = (context_MPEG2MC_p) calloc(1, sizeof(struct context_MPEG2MC_s)); 1323 if (NULL == ctx) { 1324 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; 1325 DEBUG_FAILURE; 1326 return vaStatus; 1327 } 1328 1329 /* TODO: initialize ctx content */ 1330 obj_context->format_data = (void*) ctx; 1331 ctx->obj_context = obj_context; 1332 ctx->pic_params = NULL; 1333 /* TODO create and map buffer */ 1334 1335 return vaStatus; 1336 } 1337 1338 1339 static void psb_MPEG2MC_DestroyContext( 1340 object_context_p obj_context) 1341 { 1342 INIT_CONTEXT_MPEG2MC; 1343 1344 /* TODO:unmap and destroy buffers */ 1345 if (ctx->pic_params) { 1346 free(ctx->pic_params); 1347 ctx->pic_params = NULL; 1348 } 1349 1350 free(obj_context->format_data); 1351 obj_context->format_data = NULL; 1352 } 1353 1354 static VAStatus psb_MPEG2MC_BeginPicture( 1355 object_context_p obj_context) 1356 { 1357 INIT_CONTEXT_MPEG2MC; 1358 1359 #if 0 /* clear surface for debugging */ 1360 unsigned char *surface_data = NULL; 1361 static psb_surface_p target_surface = NULL; 1362 psb_surface_p tmp = ctx->obj_context->current_render_target->psb_surface; 1363 if (target_surface != tmp) { /* for field picture, only reset one time */ 1364 target_surface = tmp; 1365 1366 int ret = psb_buffer_map(&target_surface->buf, &surface_data); 1367 if (ret) { 1368 goto out; 1369 } 1370 memset(surface_data, 0x33, target_surface->size); 1371 psb_buffer_unmap(&target_surface->buf); 1372 } 1373 out: 1374 #endif 1375 1376 if (ctx->pic_params) { 1377 free(ctx->pic_params); 1378 ctx->pic_params = NULL; 1379 } 1380 1381 /* TODO: others */ 1382 return VA_STATUS_SUCCESS; 1383 } 1384 1385 1386 static VAStatus psb_MPEG2MC_RenderPicture( 1387 object_context_p obj_context, 1388 object_buffer_p *buffers, 1389 int num_buffers) 1390 { 1391 int i; 1392 INIT_CONTEXT_MPEG2MC; 1393 VAStatus vaStatus = VA_STATUS_SUCCESS; 1394 1395 ctx->mb_param = NULL; /* Init. compressed buffer pointers */ 1396 ctx->residual_buf = NULL; 1397 1398 for (i = 0; i < num_buffers; i++) { 1399 object_buffer_p obj_buffer = buffers[i]; 1400 1401 switch (obj_buffer->type) { 1402 /* Picture parameters processing */ 1403 case VAPictureParameterBufferType: { 1404 vaStatus = psb__MPEG2MC_process_picture_param(ctx, obj_buffer); 1405 DEBUG_FAILURE; 1406 break; 1407 } 1408 /* Macroblock Data processing */ 1409 case VAMacroblockParameterBufferType: { 1410 ctx->mb_param = (VAMacroblockParameterBufferMPEG2 *)obj_buffer->buffer_data; 1411 ctx->mb_first_addr = ctx->mb_param->macroblock_address; 1412 ctx->mb_in_buffer = obj_buffer->num_elements; 1413 /* drv_debug_msg(VIDEO_DEBUG_GENERAL, "Macroblock count %d\n",ctx->mb_in_buffer); */ 1414 break; 1415 } 1416 /* Residual Difference Data processing */ 1417 case VAResidualDataBufferType: { 1418 /* store the data after VLD+IDCT */ 1419 ctx->residual_buf = obj_buffer->psb_buffer; 1420 ctx->blk_in_buffer = obj_buffer->num_elements; 1421 break; 1422 } 1423 default: 1424 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Unhandled buffer type 0x%x\n", obj_buffer->type); 1425 break; 1426 } 1427 } 1428 1429 /* Assuming residual and MB control buffers have been located */ 1430 if (ctx->residual_buf && ctx->mb_param) { 1431 ctx->residual_sent = 0; 1432 ctx->residual_pendingDMA = 0; 1433 1434 if (ctx->picture_coding_type == PICTURE_CODING_I) { 1435 psb__MPEG2MC_process_mbs_intra(ctx); 1436 } else { 1437 psb__MPEG2MC_process_mbs_interPB(ctx); 1438 } 1439 ctx->mb_param = NULL; 1440 } 1441 1442 return VA_STATUS_SUCCESS; 1443 } 1444 1445 1446 static VAStatus psb_MPEG2MC_EndPicture( 1447 object_context_p obj_context) 1448 { 1449 VAStatus vaStatus = VA_STATUS_SUCCESS; 1450 INIT_CONTEXT_MPEG2MC; 1451 1452 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psb_MPEG2MC_EndPicture\n"); 1453 1454 if (psb_context_flush_cmdbuf(ctx->obj_context)) { 1455 vaStatus = VA_STATUS_ERROR_UNKNOWN; 1456 } 1457 1458 return vaStatus; 1459 } 1460 1461 /* TODO: integrate with VLD */ 1462 struct format_vtable_s psb_MPEG2MC_vtable = { 1463 queryConfigAttributes: 1464 psb_MPEG2MC_QueryConfigAttributes, 1465 validateConfig: 1466 psb_MPEG2MC_ValidateConfig, 1467 createContext: 1468 psb_MPEG2MC_CreateContext, 1469 destroyContext: 1470 psb_MPEG2MC_DestroyContext, 1471 beginPicture: 1472 psb_MPEG2MC_BeginPicture, 1473 renderPicture: 1474 psb_MPEG2MC_RenderPicture, 1475 endPicture: 1476 psb_MPEG2MC_EndPicture 1477 }; 1478