1 #include "viddec_fw_workload.h" 2 #include "viddec_parser_ops.h" 3 #include "viddec_fw_mp4.h" 4 #include "viddec_mp4_parse.h" 5 6 uint32_t viddec_fw_mp4_populate_attr(viddec_workload_t *wl, viddec_mp4_parser_t *parser) 7 { 8 uint32_t result = MP4_STATUS_OK; 9 viddec_frame_attributes_t *attr = &(wl->attrs); 10 mp4_VideoObjectLayer_t *vol = &(parser->info.VisualObject.VideoObject); 11 12 memset(attr, 0, sizeof(viddec_frame_attributes_t)); 13 14 attr->cont_size.width = vol->video_object_layer_width; 15 attr->cont_size.height = vol->video_object_layer_height; 16 17 // Translate vop_coding_type 18 switch(vol->VideoObjectPlane.vop_coding_type) 19 { 20 case MP4_VOP_TYPE_B: 21 attr->frame_type = VIDDEC_FRAME_TYPE_B; 22 break; 23 case MP4_VOP_TYPE_P: 24 attr->frame_type = VIDDEC_FRAME_TYPE_P; 25 break; 26 case MP4_VOP_TYPE_S: 27 attr->frame_type = VIDDEC_FRAME_TYPE_S; 28 break; 29 case MP4_VOP_TYPE_I: 30 attr->frame_type = VIDDEC_FRAME_TYPE_I; 31 break; 32 default: 33 break; 34 } // switch on vop_coding_type 35 36 attr->mpeg4.top_field_first = vol->VideoObjectPlane.top_field_first; 37 38 return result; 39 } // viddec_fw_mp4_populate_attr 40 41 uint32_t viddec_fw_mp4_insert_vol_workitem(void *parent, viddec_mp4_parser_t *parser) 42 { 43 uint32_t result = MP4_STATUS_OK; 44 viddec_workload_item_t wi; 45 viddec_fw_mp4_vol_info_t vol_info; 46 mp4_VideoObjectLayer_t *vol = &(parser->info.VisualObject.VideoObject); 47 48 memset(&vol_info, 0, sizeof(viddec_fw_mp4_vol_info_t)); 49 50 // Get vol_flags 51 viddec_fw_mp4_set_reversible_vlc(&vol_info, vol->reversible_vlc); 52 viddec_fw_mp4_set_data_partitioned(&vol_info, vol->data_partitioned); 53 viddec_fw_mp4_set_resync_marker_disable(&vol_info, vol->resync_marker_disable); 54 viddec_fw_mp4_set_quarter_sample(&vol_info, vol->quarter_sample); 55 viddec_fw_mp4_set_obmc_disable(&vol_info, vol->obmc_disable); 56 viddec_fw_mp4_set_interlaced(&vol_info, vol->interlaced); 57 viddec_fw_mp4_set_vol_shape(&vol_info, vol->video_object_layer_shape); 58 viddec_fw_mp4_set_short_video_header_flag(&vol_info, vol->short_video_header); 59 60 // Get vol_size 61 viddec_fw_mp4_set_vol_width(&vol_info, vol->video_object_layer_width); 62 viddec_fw_mp4_set_vol_height(&vol_info, vol->video_object_layer_height); 63 64 // Get vol_item 65 viddec_fw_mp4_set_quant_type(&vol_info, vol->quant_type); 66 viddec_fw_mp4_set_quant_precision(&vol_info, vol->quant_precision); 67 viddec_fw_mp4_set_sprite_warping_accuracy(&vol_info, vol->sprite_info.sprite_warping_accuracy); 68 viddec_fw_mp4_set_sprite_warping_points(&vol_info, vol->sprite_info.no_of_sprite_warping_points); 69 viddec_fw_mp4_set_sprite_enable(&vol_info, vol->sprite_enable); 70 viddec_fw_mp4_set_vop_time_increment_resolution(&vol_info, vol->vop_time_increment_resolution); 71 72 73 wi.vwi_type = VIDDEC_WORKLOAD_MP4_VOL_INFO; 74 wi.vwi_payload[0] = vol_info.vol_flags; 75 wi.vwi_payload[1] = vol_info.vol_size; 76 wi.vwi_payload[2] = vol_info.vol_item; 77 78 result = viddec_pm_append_workitem(parent, &wi); 79 80 return result; 81 } // viddec_fw_mp4_insert_vol_workitem 82 83 uint32_t viddec_fw_mp4_insert_vop_workitem(void *parent, viddec_mp4_parser_t *parser) 84 { 85 uint32_t result = MP4_STATUS_OK; 86 viddec_workload_item_t wi; 87 viddec_fw_mp4_vop_info_t vop_info; 88 mp4_VideoObjectPlane_t *vop = &(parser->info.VisualObject.VideoObject.VideoObjectPlane); 89 uint32_t byte = 0; 90 unsigned char is_emul; 91 92 memset(&vop_info, 0, sizeof(viddec_fw_mp4_vop_info_t)); 93 94 // Get frame_info 95 viddec_fw_mp4_set_past_field_frame(&vop_info, parser->ref_frame[VIDDEC_MP4_INDX_2].is_field); 96 viddec_fw_mp4_set_past_frame_id(&vop_info, VIDDEC_MP4_FRAME_PAST); 97 viddec_fw_mp4_set_future_field_frame(&vop_info, parser->ref_frame[VIDDEC_MP4_INDX_1].is_field); 98 viddec_fw_mp4_set_future_frame_id(&vop_info, VIDDEC_MP4_FRAME_FUTURE); 99 viddec_fw_mp4_set_current_field_frame(&vop_info, parser->ref_frame[VIDDEC_MP4_INDX_0].is_field); 100 viddec_fw_mp4_set_current_frame_id(&vop_info, VIDDEC_MP4_FRAME_CURRENT); 101 102 // HW has a limitation that the enums for PAST(1), FUTURE(2) and CURRENT(0) cannot be changed and 103 // the spec does not support field pictures. Hence the field_frame bits are always zero. 104 // This gives us the constant 0x10200. 105 vop_info.frame_info = 0x10200; 106 107 // Get vop_data 108 // Quant scale is in the video_packet_header or the gob_layer - both of which are parsed by the BSP 109 viddec_fw_mp4_set_vop_quant_scale(&vop_info, 0); 110 viddec_fw_mp4_set_vop_fcode_backward(&vop_info, vop->vop_fcode_backward); 111 viddec_fw_mp4_set_vop_fcode_forward(&vop_info, vop->vop_fcode_forward); 112 viddec_fw_mp4_set_vop_quant(&vop_info, vop->vop_quant); 113 viddec_fw_mp4_set_alternate_vertical_scan_flag(&vop_info, vop->alternate_vertical_scan_flag); 114 viddec_fw_mp4_set_top_field_first(&vop_info, vop->top_field_first); 115 viddec_fw_mp4_set_intra_dc_vlc_thr(&vop_info, vop->intra_dc_vlc_thr); 116 viddec_fw_mp4_set_vop_rounding_type(&vop_info, vop->vop_rounding_type); 117 viddec_fw_mp4_set_vop_coding_type(&vop_info, vop->vop_coding_type); 118 119 // Get vol_item 120 result = viddec_pm_get_au_pos(parent, &vop_info.bit_offset, &byte, &is_emul); 121 122 wi.vwi_type = VIDDEC_WORKLOAD_MP4_VOP_INFO; 123 wi.vwi_payload[0] = vop_info.frame_info; 124 wi.vwi_payload[1] = vop_info.vop_data; 125 wi.vwi_payload[2] = vop_info.bit_offset; 126 127 result = viddec_pm_append_workitem(parent, &wi); 128 129 return result; 130 } // viddec_fw_mp4_insert_vop_workitem 131 132 uint32_t viddec_fw_mp4_insert_vpsh_workitem(void *parent, viddec_mp4_parser_t *parser) 133 { 134 uint32_t result = MP4_STATUS_OK; 135 viddec_workload_item_t wi; 136 viddec_fw_mp4_svh_t svh_info; 137 mp4_VideoObjectPlaneH263 *svh = &(parser->info.VisualObject.VideoObject.VideoObjectPlaneH263); 138 139 memset(&svh_info, 0, sizeof(viddec_fw_mp4_svh_t)); 140 141 // Get svh_data 142 viddec_fw_mp4_set_temporal_reference(&svh_info, svh->temporal_reference); 143 viddec_fw_mp4_set_num_macroblocks_in_gob(&svh_info, svh->num_macroblocks_in_gob); 144 viddec_fw_mp4_set_num_gobs_in_vop(&svh_info, svh->num_gobs_in_vop); 145 viddec_fw_mp4_set_num_rows_in_gob(&svh_info, svh->num_rows_in_gob); 146 147 wi.vwi_type = VIDDEC_WORKLOAD_MP4_SVH; 148 wi.vwi_payload[0] = svh_info.svh_data; 149 wi.vwi_payload[1] = svh_info.pad1; 150 wi.vwi_payload[2] = svh_info.pad2; 151 152 result = viddec_pm_append_workitem(parent, &wi); 153 154 return result; 155 } // viddec_fw_mp4_insert_vpsh_workitem 156 157 uint32_t viddec_fw_mp4_insert_sprite_workitem(void *parent, viddec_mp4_parser_t *parser) 158 { 159 uint32_t result = MP4_STATUS_OK; 160 viddec_workload_item_t wi; 161 viddec_fw_mp4_sprite_trajectory_t sprite_info; 162 mp4_VideoObjectLayer_t *vol = &(parser->info.VisualObject.VideoObject); 163 mp4_VideoObjectPlane_t *vop = &(parser->info.VisualObject.VideoObject.VideoObjectPlane); 164 uint8_t no_of_entries_per_item = 3; 165 uint8_t no_of_sprite_workitems = 0; 166 uint8_t warp_index = 0; 167 int i, j; 168 169 if(!vol->sprite_info.no_of_sprite_warping_points) 170 return result; 171 172 no_of_sprite_workitems = (vol->sprite_info.no_of_sprite_warping_points > 3) ? 2 : 1; 173 174 for(i=0; i<no_of_sprite_workitems; i++) 175 { 176 memset(&sprite_info, 0, sizeof(viddec_fw_mp4_sprite_trajectory_t)); 177 178 for(j=0; j<no_of_entries_per_item; j++) 179 { 180 if(warp_index < vol->sprite_info.no_of_sprite_warping_points) 181 { 182 viddec_fw_mp4_set_warping_point_index(sprite_info.warping_mv_code[j], warp_index); 183 viddec_fw_mp4_set_warping_mv_code_du(sprite_info.warping_mv_code[j], vop->warping_mv_code_du[warp_index]); 184 viddec_fw_mp4_set_warping_mv_code_dv(sprite_info.warping_mv_code[j], vop->warping_mv_code_dv[warp_index]); 185 } 186 else 187 { 188 sprite_info.warping_mv_code[j] = 0xF << 28; 189 } 190 warp_index++; 191 } 192 193 wi.vwi_type = VIDDEC_WORKLOAD_MP4_SPRT_TRAJ; 194 wi.vwi_payload[0] = sprite_info.warping_mv_code[0]; 195 wi.vwi_payload[1] = sprite_info.warping_mv_code[1]; 196 wi.vwi_payload[2] = sprite_info.warping_mv_code[2]; 197 198 result = viddec_pm_append_workitem(parent, &wi); 199 } 200 201 return result; 202 } // viddec_fw_mp4_insert_sprite_workitem 203 204 uint32_t viddec_fw_mp4_insert_bvop_workitem(void *parent, viddec_mp4_parser_t *parser) 205 { 206 uint32_t result = MP4_STATUS_OK; 207 viddec_workload_item_t wi; 208 mp4_VideoObjectLayer_t *vol = &(parser->info.VisualObject.VideoObject); 209 210 wi.vwi_type = VIDDEC_WORKLOAD_MP4_BVOP_INFO; 211 wi.vwi_payload[0] = vol->Tframe; 212 wi.vwi_payload[1] = vol->TRD; 213 wi.vwi_payload[2] = vol->TRB; 214 215 result = viddec_pm_append_workitem(parent, &wi); 216 217 return result; 218 } // viddec_fw_mp4_insert_bvop_workitem 219 220 uint32_t viddec_fw_mp4_insert_qmat(void *parent, uint8_t intra_quant_flag, uint32_t *qmat) 221 { 222 uint32_t result = MP4_STATUS_OK; 223 viddec_workload_item_t wi; 224 uint8_t i; 225 226 // No of items = (64/4 Dwords / 3 entries per workload item) 227 // 64 8b entries => 64 * 8 / 32 DWORDS => 64/4 DWORDS => 16 DWORDS 228 // Each item can store 3 DWORDS, 16 DWORDS => 16/3 items => 6 items 229 for(i=0; i<6; i++) 230 { 231 memset(&wi, 0, sizeof(viddec_workload_item_t)); 232 233 if(intra_quant_flag) 234 wi.vwi_type = VIDDEC_WORKLOAD_MP4_IQUANT; 235 else 236 wi.vwi_type = VIDDEC_WORKLOAD_MP4_NIQUANT; 237 238 if(i == 6) 239 { 240 wi.vwi_payload[0] = qmat[0]; 241 wi.vwi_payload[1] = 0; 242 wi.vwi_payload[2] = 0; 243 } 244 else 245 { 246 wi.vwi_payload[0] = qmat[0]; 247 wi.vwi_payload[1] = qmat[1]; 248 wi.vwi_payload[2] = qmat[2]; 249 } 250 251 qmat += 3; 252 253 result = viddec_pm_append_workitem(parent, &wi); 254 } 255 256 return result; 257 } // viddec_fw_mp4_insert_qmat 258 259 uint32_t viddec_fw_mp4_insert_inversequant_workitem(void *parent, mp4_VOLQuant_mat_t *qmat) 260 { 261 uint32_t result = MP4_STATUS_OK; 262 263 if(qmat->load_intra_quant_mat) 264 { 265 result = viddec_fw_mp4_insert_qmat(parent, true, (uint32_t *) &(qmat->intra_quant_mat)); 266 } 267 268 if(qmat->load_nonintra_quant_mat) 269 { 270 result = viddec_fw_mp4_insert_qmat(parent, false, (uint32_t *) &(qmat->nonintra_quant_mat)); 271 } 272 273 return result; 274 } // viddec_fw_mp4_insert_inversequant_workitem 275 276 uint32_t viddec_fw_mp4_insert_past_frame_workitem(void *parent) 277 { 278 uint32_t result = MP4_STATUS_OK; 279 viddec_workload_item_t wi; 280 281 wi.vwi_type = VIDDEC_WORKLOAD_MP4_PAST_FRAME; 282 wi.ref_frame.reference_id = 0; 283 wi.ref_frame.luma_phys_addr = 0; 284 wi.ref_frame.chroma_phys_addr = 0; 285 result = viddec_pm_append_workitem(parent, &wi); 286 287 return result; 288 } // viddec_fw_mp4_insert_past_frame_workitem 289 290 uint32_t viddec_fw_mp4_insert_future_frame_workitem(void *parent) 291 { 292 uint32_t result = MP4_STATUS_OK; 293 viddec_workload_item_t wi; 294 295 wi.vwi_type = VIDDEC_WORKLOAD_MP4_FUTURE_FRAME; 296 wi.ref_frame.reference_id = 0; 297 wi.ref_frame.luma_phys_addr = 0; 298 wi.ref_frame.chroma_phys_addr = 0; 299 result = viddec_pm_append_workitem(parent, &wi); 300 301 return result; 302 } // viddec_fw_mp4_insert_future_frame_workitem 303 304 uint32_t viddec_fw_mp4_insert_reorder_workitem(void *parent) 305 { 306 uint32_t result = MP4_STATUS_OK; 307 viddec_workload_item_t wi; 308 309 // Move frame at location 1 of the reference table to location 0 310 wi.vwi_type = VIDDEC_WORKLOAD_REFERENCE_FRAME_REORDER; 311 wi.ref_reorder.ref_table_offset = 0; 312 wi.ref_reorder.ref_reorder_00010203 = 0x01010203; 313 wi.ref_reorder.ref_reorder_04050607 = 0x04050607; 314 315 result = viddec_pm_append_workitem(parent, &wi); 316 317 return result; 318 } // viddec_fw_mp4_insert_reorder_workitem 319 320 uint32_t viddec_fw_mp4_emit_workload(void *parent, void *ctxt) 321 { 322 uint32_t result = 0; 323 viddec_mp4_parser_t *parser = (viddec_mp4_parser_t *) ctxt; 324 viddec_workload_t *wl = viddec_pm_get_header(parent); 325 326 result = viddec_fw_mp4_populate_attr(wl, parser); 327 result = viddec_fw_mp4_insert_vol_workitem(parent, parser); 328 result = viddec_fw_mp4_insert_vop_workitem(parent, parser); 329 result = viddec_fw_mp4_insert_sprite_workitem(parent, parser); 330 result = viddec_fw_mp4_insert_inversequant_workitem(parent, &(parser->info.VisualObject.VideoObject.quant_mat_info)); 331 332 if(parser->info.VisualObject.VideoObject.short_video_header) 333 result = viddec_fw_mp4_insert_vpsh_workitem(parent, parser); 334 335 if(!parser->info.VisualObject.VideoObject.VideoObjectPlane.vop_coded) 336 wl->is_reference_frame |= WORKLOAD_SKIPPED_FRAME; 337 338 // Send reference re-order tag for all reference frame types 339 if (parser->info.VisualObject.VideoObject.VideoObjectPlane.vop_coding_type != MP4_VOP_TYPE_B) 340 { 341 result = viddec_fw_mp4_insert_reorder_workitem(parent); 342 } 343 344 // Handle vop_coding_type based information 345 switch(parser->info.VisualObject.VideoObject.VideoObjectPlane.vop_coding_type) 346 { 347 case MP4_VOP_TYPE_B: 348 result = viddec_fw_mp4_insert_bvop_workitem(parent, parser); 349 result = viddec_fw_mp4_insert_past_frame_workitem(parent); 350 result = viddec_fw_mp4_insert_future_frame_workitem(parent); 351 break; 352 case MP4_VOP_TYPE_P: 353 case MP4_VOP_TYPE_S: 354 result = viddec_fw_mp4_insert_past_frame_workitem(parent); 355 // Deliberate fall-thru to type I 356 case MP4_VOP_TYPE_I: 357 wl->is_reference_frame |= WORKLOAD_REFERENCE_FRAME | (1 & WORKLOAD_REFERENCE_FRAME_BMASK); 358 // Swap reference information 359 parser->ref_frame[VIDDEC_MP4_INDX_2] = parser->ref_frame[VIDDEC_MP4_INDX_1]; 360 parser->ref_frame[VIDDEC_MP4_INDX_1] = parser->ref_frame[VIDDEC_MP4_INDX_0]; 361 break; 362 break; 363 default: 364 break; 365 } // switch on vop_coding_type 366 367 result = viddec_pm_append_pixeldata(parent); 368 369 return result; 370 } // viddec_fw_mp4_emit_workload 371 372