1 /* Any workload management goes in this file */ 2 3 #include "viddec_fw_debug.h" 4 #include "vc1.h" 5 #include "vc1parse.h" 6 #include "viddec_fw_workload.h" 7 #include <auto_eas/gen4_mfd.h> 8 #include "viddec_pm_utils_bstream.h" 9 10 /* this function returns workload frame types corresponding to VC1 PTYPES (frame types) 11 * VC1 frame types: can be found in vc1parse_common_defs.h 12 * workload frame types are in viddec_workload.h 13 */ 14 static inline uint32_t vc1_populate_frame_type(uint32_t vc1_frame_type) 15 { 16 uint32_t viddec_frame_type; 17 18 switch(vc1_frame_type) 19 { 20 case VC1_I_FRAME: 21 viddec_frame_type = VIDDEC_FRAME_TYPE_I; 22 break; 23 case VC1_P_FRAME: 24 viddec_frame_type = VIDDEC_FRAME_TYPE_P; 25 break; 26 case VC1_B_FRAME: 27 viddec_frame_type = VIDDEC_FRAME_TYPE_B; 28 break; 29 case VC1_BI_FRAME: 30 viddec_frame_type = VIDDEC_FRAME_TYPE_BI; 31 break; 32 case VC1_SKIPPED_FRAME : 33 viddec_frame_type = VIDDEC_FRAME_TYPE_SKIP; 34 break; 35 default: 36 viddec_frame_type = VIDDEC_FRAME_TYPE_INVALID; 37 break; 38 } // switch on vc1 frame type 39 40 return(viddec_frame_type); 41 } // vc1_populate_frame_type 42 43 static void translate_parser_info_to_frame_attributes(void *parent, vc1_viddec_parser_t *parser) 44 { 45 viddec_workload_t *wl = viddec_pm_get_header( parent ); 46 viddec_frame_attributes_t *attrs = &wl->attrs; 47 vc1_Info *info = &parser->info; 48 unsigned i; 49 50 /* typical sequence layer and entry_point data */ 51 attrs->cont_size.height = info->metadata.height * 2 + 2; 52 attrs->cont_size.width = info->metadata.width * 2 + 2; 53 54 /* frame type */ 55 /* we can have two fileds with different types for field interlace coding mode */ 56 if (info->picLayerHeader.FCM == VC1_FCM_FIELD_INTERLACE) { 57 attrs->frame_type = vc1_populate_frame_type(info->picLayerHeader.PTypeField1); 58 attrs->bottom_field_type = vc1_populate_frame_type(info->picLayerHeader.PTypeField2); 59 } else { 60 attrs->frame_type = vc1_populate_frame_type(info->picLayerHeader.PTYPE); 61 attrs->bottom_field_type = VIDDEC_FRAME_TYPE_INVALID; //unknown 62 } 63 64 /* frame counter */ 65 attrs->vc1.tfcntr = info->picLayerHeader.TFCNTR; 66 67 /* TFF, repeat frame, field */ 68 attrs->vc1.tff = info->picLayerHeader.TFF; 69 attrs->vc1.rptfrm = info->picLayerHeader.RPTFRM; 70 attrs->vc1.rff = info->picLayerHeader.RFF; 71 72 /* PAN Scan */ 73 attrs->vc1.ps_present = info->picLayerHeader.PS_PRESENT; 74 attrs->vc1.num_of_pan_scan_windows = info->picLayerHeader.number_of_pan_scan_window; 75 for (i=0;i<attrs->vc1.num_of_pan_scan_windows;i++) { 76 attrs->vc1.pan_scan_window[i].hoffset = info->picLayerHeader.PAN_SCAN_WINDOW[i].hoffset; 77 attrs->vc1.pan_scan_window[i].voffset = info->picLayerHeader.PAN_SCAN_WINDOW[i].voffset; 78 attrs->vc1.pan_scan_window[i].width = info->picLayerHeader.PAN_SCAN_WINDOW[i].width; 79 attrs->vc1.pan_scan_window[i].height = info->picLayerHeader.PAN_SCAN_WINDOW[i].height; 80 } //end for i 81 82 return; 83 } // translate_parser_info_to_frame_attributes 84 85 void vc1_intcomp(vc1_viddec_parser_t *parser, vc1_Info *pInfo, VC1D_SPR_REGS *spr) 86 { 87 vc1_metadata_t *md = &pInfo->metadata; 88 vc1_PictureLayerHeader *pic = &pInfo->picLayerHeader; 89 uint32_t intcomp1 = 1; 90 uint32_t intcomp2 = 0; 91 92 // Get the intensity compensation from the bitstream 93 BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, LUMA_SCALE_1, intcomp1, pic->LUMSCALE); 94 BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, LUMA_SHIFT_1, intcomp1, pic->LUMSHIFT); 95 96 if(md->INTCOMPFIELD == VC1_INTCOMP_BOTH_FIELD) 97 { 98 intcomp2 = 1; 99 BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, LUMA_SCALE_1, intcomp2, md->LUMSCALE2); 100 BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, LUMA_SHIFT_1, intcomp2, md->LUMSHIFT2); 101 } 102 103 switch(md->INTCOMPFIELD) 104 { 105 case VC1_INTCOMP_TOP_FIELD: 106 if(pic->CurrField == 0) // First field decoded 107 { 108 if(pic->TFF) 109 { 110 //parser->intcomp_bot[0] = intcomp1 << 13; 111 BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_2, spr->intcomp_fwd_top, intcomp1); 112 } 113 else 114 { 115 parser->intcomp_top[0] = intcomp1; 116 parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].intcomp_top = intcomp1; 117 BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_1, spr->intcomp_fwd_top, intcomp1); 118 } 119 } 120 else // Second field 121 { 122 if(pic->TFF) 123 { 124 parser->intcomp_top[0] = intcomp1; 125 parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].intcomp_top = intcomp1; 126 BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_1, spr->intcomp_bwd_top, intcomp1); 127 } 128 else 129 { 130 BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_2, spr->intcomp_fwd_top, intcomp1); 131 } 132 } 133 break; 134 case VC1_INTCOMP_BOTTOM_FIELD: 135 if(pic->CurrField == 0) // First field decoded 136 { 137 if(pic->TFF) 138 { 139 parser->intcomp_bot[0] = intcomp1; 140 parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].intcomp_bot = intcomp1; 141 BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_1, spr->intcomp_fwd_bot, intcomp1); 142 } 143 else 144 { 145 parser->intcomp_bot[0] = intcomp1 << 13; 146 BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_2, spr->intcomp_fwd_bot, intcomp1); 147 } 148 } 149 else // Second field 150 { 151 if(pic->TFF) 152 { 153 BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_2, spr->intcomp_fwd_bot, intcomp1); 154 } 155 else 156 { 157 parser->intcomp_bot[0] = intcomp1; 158 parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].intcomp_bot = intcomp1; 159 BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_1, spr->intcomp_bwd_bot, intcomp1); 160 } 161 } 162 break; 163 case VC1_INTCOMP_BOTH_FIELD: 164 if(pic->CurrField == 0) // First field decoded 165 { 166 if(pic->TFF) 167 { 168 parser->intcomp_bot[0] = intcomp2; 169 parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].intcomp_bot = intcomp2; 170 BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_2, spr->intcomp_fwd_top, intcomp1); 171 BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_1, spr->intcomp_fwd_bot, intcomp2); 172 } 173 else 174 { 175 parser->intcomp_top[0] = intcomp2; 176 parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].intcomp_top = intcomp2; 177 BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_2, spr->intcomp_fwd_bot, intcomp1); 178 BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_1, spr->intcomp_fwd_top, intcomp2); 179 } 180 } 181 else // Second field 182 { 183 if(pic->TFF) 184 { 185 parser->intcomp_top[0] = intcomp1; 186 parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].intcomp_top = intcomp1; 187 BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_1, spr->intcomp_bwd_top, intcomp1); 188 BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_2, spr->intcomp_fwd_bot, intcomp2); 189 } 190 else 191 { 192 parser->intcomp_bot[0] = intcomp1; 193 parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].intcomp_bot = intcomp1; 194 BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_1, spr->intcomp_bwd_bot, intcomp1); 195 BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_2, spr->intcomp_fwd_top, intcomp2); 196 } 197 } 198 break; 199 default: 200 break; 201 } // switch on INTCOMPFIELD 202 203 return; 204 } // vc1_intcomp 205 206 static void handle_intensity_compensation(vc1_viddec_parser_t *parser, vc1_Info *pInfo, VC1D_SPR_REGS *spr) 207 { 208 vc1_PictureLayerHeader *pic = &pInfo->picLayerHeader; 209 uint8_t intcomp_present = false; 210 211 if((pic->MVMODE == VC1_MVMODE_INTENSCOMP) || (pic->INTCOMP)) 212 { 213 intcomp_present = true; 214 if(pic->FCM == VC1_FCM_FIELD_INTERLACE) 215 { 216 vc1_intcomp(parser, pInfo, spr); 217 } 218 else 219 { 220 BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_1, spr->intcomp_fwd_top, 1); 221 BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, LUMA_SCALE_1, spr->intcomp_fwd_top, pic->LUMSCALE); 222 BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, LUMA_SHIFT_1, spr->intcomp_fwd_top, pic->LUMSHIFT); 223 224 if(parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].fcm == VC1_FCM_FIELD_INTERLACE) 225 { 226 BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, INT_COMP_2, spr->intcomp_fwd_bot, 1); 227 BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, LUMA_SCALE_2, spr->intcomp_fwd_bot, pic->LUMSCALE); 228 BF_WRITE(VC1_0_SEQPIC_INTENSITY_COMPENSATION, LUMA_SHIFT_2, spr->intcomp_fwd_bot, pic->LUMSHIFT); 229 } 230 231 parser->intcomp_top[0] = spr->intcomp_fwd_top; 232 parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].intcomp_top = spr->intcomp_fwd_top; 233 parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].intcomp_bot = spr->intcomp_fwd_top; 234 } 235 } 236 237 // Propagate the previous picture's intensity compensation 238 if(pic->FCM == VC1_FCM_FIELD_INTERLACE) 239 { 240 if( (pic->CurrField) || 241 ((pic->CurrField == 0) && (parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].fcm == VC1_FCM_FIELD_INTERLACE))) 242 { 243 spr->intcomp_fwd_top |= parser->intcomp_top[1]; 244 spr->intcomp_fwd_bot |= parser->intcomp_bot[1]; 245 } 246 } 247 if(pic->FCM == VC1_FCM_FRAME_INTERLACE) 248 { 249 if( (pic->CurrField) || 250 ((pic->CurrField == 0) && (parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].fcm == VC1_FCM_FIELD_INTERLACE))) 251 { 252 spr->intcomp_fwd_bot |= parser->intcomp_bot[1]; 253 } 254 } 255 256 switch(pic->PTYPE) 257 { 258 case VC1_B_FRAME: 259 spr->intcomp_fwd_top = parser->intcomp_last[0]; 260 spr->intcomp_fwd_bot = parser->intcomp_last[1]; 261 spr->intcomp_bwd_top = parser->intcomp_last[2]; 262 spr->intcomp_bwd_bot = parser->intcomp_last[3]; 263 break; 264 case VC1_P_FRAME: 265 // If first field, store the intcomp values to propagate. 266 // If second field has valid intcomp values, store them 267 // to propagate. 268 if(pic->CurrField == 0) // first field 269 { 270 parser->intcomp_last[0] = spr->intcomp_fwd_top; 271 parser->intcomp_last[1] = spr->intcomp_fwd_bot; 272 parser->intcomp_last[2] = spr->intcomp_bwd_top; 273 parser->intcomp_last[3] = spr->intcomp_bwd_bot; 274 } 275 else // Second field 276 { 277 parser->intcomp_last[0] |= spr->intcomp_fwd_top; 278 parser->intcomp_last[1] |= spr->intcomp_fwd_bot; 279 parser->intcomp_last[2] |= spr->intcomp_bwd_top; 280 parser->intcomp_last[3] |= spr->intcomp_bwd_bot; 281 } 282 break; 283 case VC1_I_FRAME: 284 case VC1_BI_FRAME: 285 break; 286 default: 287 break; 288 } 289 290 return; 291 } // handle_intensity_compensation 292 293 /** 294 * This function populates the registers for range reduction (main profile) 295 * This function assumes pInfo->metadata.RANGERED is ON at the sequence layer (J.1.17) 296 * A frame is marked as range reduced by the RANGEREDFRM flag at the picture layer, 297 * and the output of the decoded range reduced frame needs to be scaled up (8.1.1.4). 298 * Previous reference frame needs be upscaled or downscaled based on the RR status of 299 * current and previous frame (8.3.4.11) 300 */ 301 static inline void vc1_fill_RR_hw_struct(vc1_viddec_parser_t *parser, vc1_Info *pInfo, VC1D_SPR_REGS *spr) 302 { 303 vc1_PictureLayerHeader *pic = &pInfo->picLayerHeader; 304 int is_previous_ref_rr=0; 305 306 /* range reduction applies to luma and chroma component 307 which are the same register bit as RANGE_MAPY_FLAG, RANGE_MAPUV_FLAG */ 308 BF_WRITE(VC1_0_SEQPIC_RANGE_MAP, RANGE_MAP_Y_FLAG, spr->range_map, pic->RANGEREDFRM); 309 BF_WRITE(VC1_0_SEQPIC_RANGE_MAP, RANGE_MAP_UV_FLAG, spr->range_map, pic->RANGEREDFRM); 310 311 /* Get the range reduced status of the previous frame */ 312 switch (pic->PTYPE) 313 { 314 case VC1_P_FRAME: 315 { 316 is_previous_ref_rr = parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].rr_frm; 317 break; 318 } 319 case VC1_B_FRAME: 320 { 321 is_previous_ref_rr = parser->ref_frame[VC1_REF_FRAME_T_MINUS_2].rr_frm; 322 break; 323 } 324 default: 325 { 326 break; 327 } 328 } 329 330 /* if current frame is RR and previous frame is not 331 donwscale the reference pixel ( RANGE_REF_RED_TYPE =1 in register) */ 332 if(pic->RANGEREDFRM) 333 { 334 if(!is_previous_ref_rr) 335 { 336 BF_WRITE(VC1_0_SEQPIC_RECON_CONTROL, RANGE_REF_RED_EN, spr->recon_control, 1); 337 BF_WRITE(VC1_0_SEQPIC_RECON_CONTROL, RANGE_REF_RED_TYPE, spr->recon_control, 1); 338 } 339 } 340 else 341 { 342 /* if current frame is not RR but previous was RR, scale up the reference frame ( RANGE_REF_RED_TYPE = 0) */ 343 if(is_previous_ref_rr) 344 { 345 BF_WRITE(VC1_0_SEQPIC_RECON_CONTROL, RANGE_REF_RED_EN, spr->recon_control, 1); 346 BF_WRITE(VC1_0_SEQPIC_RECON_CONTROL, RANGE_REF_RED_TYPE, spr->recon_control, 0); 347 } 348 } // end for RR upscale 349 350 } // vc1_fill_RR_hw_struct 351 352 /** 353 * fill workload items that will load registers for HW decoder 354 */ 355 static void vc1_fill_hw_struct(vc1_viddec_parser_t *parser, vc1_Info* pInfo, VC1D_SPR_REGS *spr) 356 { 357 vc1_metadata_t *md = &pInfo->metadata; 358 vc1_PictureLayerHeader *pic = &pInfo->picLayerHeader; 359 int field = pic->CurrField; 360 int ptype; 361 362 ptype = pic->PTYPE; 363 364 LOG_CRIT("ptype = %d, field = %d, topfield = %d, slice = %d", ptype, pic->CurrField, pic->BottomField, pic->SLICE_ADDR); 365 366 /* Common to both fields */ 367 BF_WRITE(VC1_0_SEQPIC_STREAM_FORMAT_1, PROFILE, spr->stream_format1, md->PROFILE); 368 369 BF_WRITE(VC1_0_SEQPIC_CODED_SIZE, WIDTH, spr->coded_size, md->width); 370 BF_WRITE(VC1_0_SEQPIC_CODED_SIZE, HEIGHT, spr->coded_size, md->height); 371 372 BF_WRITE(VC1_0_SEQPIC_STREAM_FORMAT_2, INTERLACE, spr->stream_format2, md->INTERLACE); 373 374 BF_WRITE(VC1_0_SEQPIC_ENTRY_POINT_1, LOOPFILTER, spr->entrypoint1, md->LOOPFILTER); 375 BF_WRITE(VC1_0_SEQPIC_ENTRY_POINT_1, FASTUVMC, spr->entrypoint1, md->FASTUVMC); 376 BF_WRITE(VC1_0_SEQPIC_ENTRY_POINT_1, EXTENDED_MV, spr->entrypoint1, md->EXTENDED_MV); 377 BF_WRITE(VC1_0_SEQPIC_ENTRY_POINT_1, DQUANT, spr->entrypoint1, md->DQUANT); 378 BF_WRITE(VC1_0_SEQPIC_ENTRY_POINT_1, VS_TRANSFORM, spr->entrypoint1, md->VSTRANSFORM); 379 BF_WRITE(VC1_0_SEQPIC_ENTRY_POINT_1, OVERLAP, spr->entrypoint1, md->OVERLAP); 380 BF_WRITE(VC1_0_SEQPIC_ENTRY_POINT_1, QUANTIZER, spr->entrypoint1, md->QUANTIZER); 381 BF_WRITE(VC1_0_SEQPIC_ENTRY_POINT_1, EXTENDED_DMV, spr->entrypoint1, md->EXTENDED_DMV); 382 383 /* if range reduction is indicated at seq. layer, populate range reduction registers for the frame*/ 384 if(md->RANGERED) 385 { 386 vc1_fill_RR_hw_struct(parser, pInfo, spr ); 387 } 388 else 389 { //range mapping 390 BF_WRITE( VC1_0_SEQPIC_RANGE_MAP, RANGE_MAP_Y_FLAG, spr->range_map, md->RANGE_MAPY_FLAG); 391 BF_WRITE( VC1_0_SEQPIC_RANGE_MAP, RANGE_MAP_Y, spr->range_map, md->RANGE_MAPY); 392 BF_WRITE( VC1_0_SEQPIC_RANGE_MAP, RANGE_MAP_UV_FLAG, spr->range_map, md->RANGE_MAPUV_FLAG); 393 BF_WRITE( VC1_0_SEQPIC_RANGE_MAP, RANGE_MAP_UV, spr->range_map, md->RANGE_MAPUV); 394 } 395 396 BF_WRITE(VC1_0_SEQPIC_FRAME_TYPE, FCM, spr->frame_type, pic->FCM); 397 BF_WRITE(VC1_0_SEQPIC_FRAME_TYPE, PTYPE, spr->frame_type, pic->PTYPE); 398 399 BF_WRITE( VC1_0_SEQPIC_RECON_CONTROL, RNDCTRL, spr->recon_control, md->RNDCTRL); 400 BF_WRITE( VC1_0_SEQPIC_RECON_CONTROL, UVSAMP, spr->recon_control, pic->UVSAMP); 401 BF_WRITE( VC1_0_SEQPIC_RECON_CONTROL, PQUANT, spr->recon_control, pic->PQUANT); 402 BF_WRITE( VC1_0_SEQPIC_RECON_CONTROL, HALFQP, spr->recon_control, pic->HALFQP); 403 BF_WRITE( VC1_0_SEQPIC_RECON_CONTROL, UNIFORM_QNT, spr->recon_control, pic->UniformQuant); 404 BF_WRITE( VC1_0_SEQPIC_RECON_CONTROL, POSTPROC, spr->recon_control, pic->POSTPROC); 405 BF_WRITE( VC1_0_SEQPIC_RECON_CONTROL, CONDOVER, spr->recon_control, pic->CONDOVER); 406 BF_WRITE( VC1_0_SEQPIC_RECON_CONTROL, PQINDEX_LE8, spr->recon_control, (pic->PQINDEX <= 8)); 407 408 BF_WRITE( VC1_0_SEQPIC_MOTION_VECTOR_CONTROL, MVRANGE, spr->mv_control, pic->MVRANGE); 409 if ( pic->MVMODE == VC1_MVMODE_INTENSCOMP) 410 BF_WRITE( VC1_0_SEQPIC_MOTION_VECTOR_CONTROL, MVMODE, spr->mv_control, pic->MVMODE2); 411 else 412 BF_WRITE( VC1_0_SEQPIC_MOTION_VECTOR_CONTROL, MVMODE, spr->mv_control, pic->MVMODE); 413 BF_WRITE( VC1_0_SEQPIC_MOTION_VECTOR_CONTROL, MVTAB, spr->mv_control, pic->MVTAB); 414 BF_WRITE( VC1_0_SEQPIC_MOTION_VECTOR_CONTROL, DMVRANGE, spr->mv_control, pic->DMVRANGE); 415 BF_WRITE( VC1_0_SEQPIC_MOTION_VECTOR_CONTROL, MV4SWITCH, spr->mv_control, pic->MV4SWITCH); 416 BF_WRITE( VC1_0_SEQPIC_MOTION_VECTOR_CONTROL, MBMODETAB, spr->mv_control, pic->MBMODETAB); 417 BF_WRITE( VC1_0_SEQPIC_MOTION_VECTOR_CONTROL, NUMREF, spr->mv_control, 418 pic->NUMREF || ((pic->PTYPE == VC1_B_FRAME) && ( pic->FCM == VC1_FCM_FIELD_INTERLACE ) )); 419 BF_WRITE( VC1_0_SEQPIC_MOTION_VECTOR_CONTROL, REFFIELD, spr->mv_control, pic->REFFIELD); 420 421 handle_intensity_compensation(parser, pInfo, spr); 422 423 BF_WRITE(VC1_0_SEQPIC_REFERENCE_B_FRACTION, BFRACTION_DEN, spr->ref_bfraction, pic->BFRACTION_DEN); 424 BF_WRITE(VC1_0_SEQPIC_REFERENCE_B_FRACTION, BFRACTION_NUM, spr->ref_bfraction, pic->BFRACTION_NUM); 425 BF_WRITE(VC1_0_SEQPIC_REFERENCE_B_FRACTION, REFDIST, spr->ref_bfraction, md->REFDIST); 426 427 // BLOCK CONTROL REGISTER Offset 0x2C 428 BF_WRITE( VC1_0_SEQPIC_BLOCK_CONTROL, CBPTAB, spr->blk_control, pic->CBPTAB); 429 BF_WRITE(VC1_0_SEQPIC_BLOCK_CONTROL, TTMFB, spr->blk_control, pic->TTMBF); 430 BF_WRITE(VC1_0_SEQPIC_BLOCK_CONTROL, TTFRM, spr->blk_control, pic->TTFRM); 431 BF_WRITE(VC1_0_SEQPIC_BLOCK_CONTROL, MV2BPTAB, spr->blk_control, pic->MV2BPTAB); 432 BF_WRITE(VC1_0_SEQPIC_BLOCK_CONTROL, MV4BPTAB, spr->blk_control, pic->MV4BPTAB); 433 if((field == 1) && (pic->SLICE_ADDR)) 434 { 435 int mby = md->height * 2 + 2; 436 mby = (mby + 15 ) / 16; 437 pic->SLICE_ADDR -= (mby/2); 438 } 439 BF_WRITE(VC1_0_SEQPIC_BLOCK_CONTROL, INITIAL_MV_Y, spr->blk_control, pic->SLICE_ADDR); 440 BF_WRITE(VC1_0_SEQPIC_BLOCK_CONTROL, BP_RAW_ID2, spr->blk_control, md->bp_raw[0]); 441 BF_WRITE(VC1_0_SEQPIC_BLOCK_CONTROL, BP_RAW_ID1, spr->blk_control, md->bp_raw[1]); 442 BF_WRITE(VC1_0_SEQPIC_BLOCK_CONTROL, BP_RAW_ID0, spr->blk_control, md->bp_raw[2]); 443 444 BF_WRITE( VC1_0_SEQPIC_TRANSFORM_DATA, TRANSACFRM, spr->trans_data, pic->TRANSACFRM); 445 BF_WRITE( VC1_0_SEQPIC_TRANSFORM_DATA, TRANSACFRM2, spr->trans_data, pic->TRANSACFRM2); 446 BF_WRITE( VC1_0_SEQPIC_TRANSFORM_DATA, TRANSDCTAB, spr->trans_data, pic->TRANSDCTAB); 447 448 // When DQUANT is 1 or 2, we have the VOPDQUANT structure in the bitstream that 449 // controls the value calculated for ALTPQUANT 450 // ALTPQUANT must be in the range of 1 and 31 for it to be valid 451 // DQUANTFRM is present only when DQUANT is 1 and ALTPQUANT setting should be dependent on DQUANT instead 452 if(md->DQUANT) 453 { 454 if(pic->PQDIFF == 7) 455 BF_WRITE( VC1_0_SEQPIC_VOP_DEQUANT, PQUANT_ALT, spr->vop_dquant, pic->ABSPQ); 456 else if (pic->DQUANTFRM == 1) 457 BF_WRITE( VC1_0_SEQPIC_VOP_DEQUANT, PQUANT_ALT, spr->vop_dquant, pic->PQUANT + pic->PQDIFF + 1); 458 } 459 BF_WRITE( VC1_0_SEQPIC_VOP_DEQUANT, DQUANTFRM, spr->vop_dquant, pic->DQUANTFRM); 460 BF_WRITE( VC1_0_SEQPIC_VOP_DEQUANT, DQPROFILE, spr->vop_dquant, pic->DQPROFILE); 461 BF_WRITE( VC1_0_SEQPIC_VOP_DEQUANT, DQES, spr->vop_dquant, pic->DQSBEDGE); 462 BF_WRITE( VC1_0_SEQPIC_VOP_DEQUANT, DQBILEVEL, spr->vop_dquant, pic->DQBILEVEL); 463 464 BF_WRITE(VC1_0_SEQPIC_CURR_FRAME_ID,FCM, spr->ref_frm_id[VC1_FRAME_CURRENT_REF], pic->FCM ); 465 466 if ( ptype == VC1_B_FRAME) { 467 // Forward reference is past reference and is the second temporally closest reference - hence minus_2 468 BF_WRITE(VC1_0_SEQPIC_FWD_REF_FRAME_ID, FCM, parser->spr.ref_frm_id[VC1_FRAME_PAST], parser->ref_frame[VC1_REF_FRAME_T_MINUS_2].fcm ); 469 // Backward reference is future reference frame and is temporally the closest - hence minus_1 470 BF_WRITE(VC1_0_SEQPIC_BWD_REF_FRAME_ID, FCM, parser->spr.ref_frm_id[VC1_FRAME_FUTURE], parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].fcm ); 471 } else { 472 // Only Forward reference is valid and is the temporally closest reference - hence minus_1, backward is set same as forward 473 BF_WRITE(VC1_0_SEQPIC_FWD_REF_FRAME_ID, FCM, parser->spr.ref_frm_id[VC1_FRAME_PAST], parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].fcm ); 474 BF_WRITE(VC1_0_SEQPIC_BWD_REF_FRAME_ID, FCM, parser->spr.ref_frm_id[VC1_FRAME_FUTURE], parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].fcm ); 475 } 476 477 BF_WRITE( VC1_0_SEQPIC_FIELD_REF_FRAME_ID, TOP_FIELD, spr->fieldref_ctrl_id, pic->BottomField); 478 BF_WRITE( VC1_0_SEQPIC_FIELD_REF_FRAME_ID, SECOND_FIELD, spr->fieldref_ctrl_id, pic->CurrField); 479 if(parser->info.picLayerHeader.PTYPE == VC1_I_FRAME) 480 { 481 BF_WRITE(VC1_0_SEQPIC_FIELD_REF_FRAME_ID, ANCHOR, spr->fieldref_ctrl_id, 1); 482 } 483 else 484 { 485 BF_WRITE(VC1_0_SEQPIC_FIELD_REF_FRAME_ID, ANCHOR, spr->fieldref_ctrl_id, parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].anchor[pic->CurrField]); 486 } 487 488 if( pic->FCM == VC1_FCM_FIELD_INTERLACE ) { 489 BF_WRITE(VC1_0_SEQPIC_IMAGE_STRUCTURE, IMG_STRUC, spr->imgstruct, (pic->BottomField) ? 2 : 1); 490 } 491 492 return; 493 } // vc1_fill_hw_struct 494 495 int32_t vc1_parse_emit_current_frame(void *parent, vc1_viddec_parser_t *parser) 496 { 497 viddec_workload_item_t wi; 498 const uint32_t *pl; 499 int i; 500 int nitems; 501 502 if( parser->info.picLayerHeader.PTYPE == VC1_SKIPPED_FRAME ) { 503 translate_parser_info_to_frame_attributes( parent, parser ); 504 return 0; 505 } 506 507 translate_parser_info_to_frame_attributes( parent, parser ); 508 memset(&parser->spr, 0, sizeof(VC1D_SPR_REGS)); 509 vc1_fill_hw_struct( parser, &parser->info, &parser->spr ); 510 511 /* STUFF BSP Data Memory it into a variety of workload items */ 512 513 pl = (const uint32_t *) &parser->spr; 514 515 // How many payloads must be generated 516 nitems = (sizeof(parser->spr) + 7) / 8; /* In QWORDs rounded up */ 517 518 519 // Dump DMEM to an array of workitems 520 for( i = 0; (i < nitems) && ( (parser->info.picLayerHeader.SLICE_ADDR == 0) || parser->info.picture_info_has_changed ); i++ ) 521 { 522 wi.vwi_type = VIDDEC_WORKLOAD_DECODER_SPECIFIC; 523 wi.data.data_offset = (unsigned int)pl - (unsigned int)&parser->spr; // offset within struct 524 wi.data.data_payload[0] = pl[0]; 525 wi.data.data_payload[1] = pl[1]; 526 pl += 2; 527 528 viddec_pm_append_workitem( parent, &wi ); 529 } 530 531 { 532 uint32_t bit, byte; 533 uint8_t is_emul; 534 viddec_pm_get_au_pos(parent, &bit, &byte, &is_emul); 535 // Send current bit offset and current slice 536 wi.vwi_type = VIDDEC_WORKLOAD_VC1_BITOFFSET; 537 // If slice data starts in the middle of the emulation prevention sequence - 538 // Eg: 00 00 03 01 - slice data starts at the second byte of 0s, we still feed the data 539 // to the decoder starting at the first byte of 0s so that the decoder can detect the 540 // emulation prevention. But the actual data starts are offset 8 in this bit sequence. 541 wi.vwi_payload[0] = bit + (is_emul*8); 542 wi.vwi_payload[1] = parser->info.picLayerHeader.SLICE_ADDR; 543 wi.vwi_payload[2] = 0xdeaddead; 544 viddec_pm_append_workitem( parent, &wi ); 545 } 546 547 viddec_pm_append_pixeldata( parent ); 548 549 return(0); 550 } 551 552 /* sends VIDDEC_WORKLOAD_VC1_PAST_FRAME item */ 553 static inline void vc1_send_past_ref_items(void *parent) 554 { 555 viddec_workload_item_t wi; 556 wi.vwi_type = VIDDEC_WORKLOAD_VC1_PAST_FRAME; 557 wi.ref_frame.reference_id = 0; 558 wi.ref_frame.luma_phys_addr = 0; 559 wi.ref_frame.chroma_phys_addr = 0; 560 viddec_pm_append_workitem( parent, &wi ); 561 return; 562 } 563 564 /* send future frame item */ 565 static inline void vc1_send_future_ref_items(void *parent) 566 { 567 viddec_workload_item_t wi; 568 wi.vwi_type = VIDDEC_WORKLOAD_VC1_FUTURE_FRAME; 569 wi.ref_frame.reference_id = 0; 570 wi.ref_frame.luma_phys_addr = 0; 571 wi.ref_frame.chroma_phys_addr = 0; 572 viddec_pm_append_workitem( parent, &wi ); 573 return; 574 } 575 576 /* send reorder frame item to host 577 * future frame gets push to past */ 578 static inline void send_reorder_ref_items(void *parent) 579 { 580 viddec_workload_item_t wi; 581 wi.vwi_type = VIDDEC_WORKLOAD_REFERENCE_FRAME_REORDER; 582 wi.ref_reorder.ref_table_offset = 0; 583 wi.ref_reorder.ref_reorder_00010203 = 0x01010203; //put reference frame index 1 as reference index 0 584 wi.ref_reorder.ref_reorder_04050607 = 0x04050607; // index 4,5,6,7 stay the same 585 viddec_pm_append_workitem( parent, &wi ); 586 return; 587 } // send_reorder_ref_items 588 589 /** update workload with more workload items for ref and update values to store... 590 */ 591 void vc1_start_new_frame(void *parent, vc1_viddec_parser_t *parser) 592 { 593 vc1_metadata_t *md = &(parser->info.metadata); 594 viddec_workload_t *wl = viddec_pm_get_header(parent); 595 int frame_type = parser->info.picLayerHeader.PTYPE; 596 int frame_id = 1; // new reference frame is assigned index 1 597 598 /* init */ 599 memset(&parser->spr, 0, sizeof(parser->spr)); 600 wl->is_reference_frame = 0; 601 602 /* set flag - extra ouput frame needed for range adjustment (range mapping or range reduction */ 603 if (parser->info.metadata.RANGE_MAPY_FLAG || 604 parser->info.metadata.RANGE_MAPUV_FLAG || 605 parser->info.picLayerHeader.RANGEREDFRM) 606 { 607 wl->is_reference_frame |= WORKLOAD_FLAGS_RA_FRAME; 608 } 609 610 LOG_CRIT("vc1_start_new_frame: frame_type=%d \n",frame_type); 611 612 parser->is_reference_picture = ((VC1_B_FRAME != frame_type) && (VC1_BI_FRAME != frame_type)); 613 614 /* reference / anchor frames processing 615 * we need to send reorder before reference frames */ 616 if (parser->is_reference_picture) 617 { 618 /* one frame has been sent */ 619 if (parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].id != -1) 620 { 621 /* there is a frame in the reference buffer, move it to the past */ 622 send_reorder_ref_items(parent); 623 } 624 } 625 626 /* send workitems for reference frames */ 627 switch( frame_type ) 628 { 629 case VC1_B_FRAME: 630 { 631 vc1_send_past_ref_items(parent); 632 vc1_send_future_ref_items(parent); 633 break; 634 } 635 case VC1_SKIPPED_FRAME: 636 { 637 wl->is_reference_frame |= WORKLOAD_SKIPPED_FRAME; 638 vc1_send_past_ref_items(parent); 639 break; 640 } 641 case VC1_P_FRAME: 642 { 643 vc1_send_past_ref_items( parent); 644 break; 645 } 646 default: 647 break; 648 } 649 650 /* reference / anchor frames from previous code 651 * we may need it for frame reduction */ 652 if (parser->is_reference_picture) 653 { 654 wl->is_reference_frame |= WORKLOAD_REFERENCE_FRAME | (frame_id & WORKLOAD_REFERENCE_FRAME_BMASK); 655 656 parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].id = frame_id; 657 parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].fcm = parser->info.picLayerHeader.FCM; 658 parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].anchor[0] = (parser->info.picLayerHeader.PTYPE == VC1_I_FRAME); 659 if(parser->info.picLayerHeader.FCM == VC1_FCM_FIELD_INTERLACE) 660 { 661 parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].anchor[1] = (parser->info.picLayerHeader.PTypeField2 == VC1_I_FRAME); 662 } 663 else 664 { 665 parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].anchor[1] = parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].anchor[0]; 666 } 667 668 parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].type = parser->info.picLayerHeader.PTYPE; 669 parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].rr_en = md->RANGERED; 670 parser->ref_frame[VC1_REF_FRAME_T_MINUS_0].rr_frm = parser->info.picLayerHeader.RANGEREDFRM; 671 672 LOG_CRIT("anchor[0] = %d, anchor[1] = %d", 673 parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].anchor[0], 674 parser->ref_frame[VC1_REF_FRAME_T_MINUS_1].anchor[1] ); 675 } 676 677 return; 678 } // vc1_start_new_frame 679 680 void vc1_end_frame(vc1_viddec_parser_t *parser) 681 { 682 /* update status of reference frames */ 683 if(parser->is_reference_picture) 684 { 685 parser->ref_frame[VC1_REF_FRAME_T_MINUS_2] = parser->ref_frame[VC1_REF_FRAME_T_MINUS_1]; 686 parser->ref_frame[VC1_REF_FRAME_T_MINUS_1] = parser->ref_frame[VC1_REF_FRAME_T_MINUS_0]; 687 } 688 689 return; 690 } // vc1_end_frame 691 692