1 #include "viddec_fw_debug.h" 2 #include "viddec_parser_ops.h" 3 4 #include "viddec_fw_workload.h" 5 #include "viddec_pm.h" 6 7 #include "h264.h" 8 #include "h264parse.h" 9 10 #include "viddec_h264_parse.h" 11 #include "h264parse_dpb.h" 12 13 /* Init function which can be called to intialized local context on open and flush and preserve*/ 14 #ifdef VBP 15 void viddec_h264_init(void *ctxt, uint32_t *persist_mem, uint32_t preserve) 16 #else 17 static void viddec_h264_init(void *ctxt, uint32_t *persist_mem, uint32_t preserve) 18 #endif 19 { 20 struct h264_viddec_parser* parser = ctxt; 21 h264_Info * pInfo = &(parser->info); 22 23 if(!preserve) 24 { 25 /* we don't initialize this data if we want to preserve 26 sequence and gop information */ 27 h264_init_sps_pps(parser,persist_mem); 28 } 29 /* picture level info which will always be initialized */ 30 h264_init_Info_under_sps_pps_level(pInfo); 31 return; 32 } 33 34 35 /* ------------------------------------------------------------------------------------------ */ 36 /* ------------------------------------------------------------------------------------------ */ 37 /* ------------------------------------------------------------------------------------------ */ 38 #ifdef VBP 39 uint32_t viddec_h264_parse(void *parent, void *ctxt) 40 #else 41 static uint32_t viddec_h264_parse(void *parent, void *ctxt) 42 #endif 43 { 44 struct h264_viddec_parser* parser = ctxt; 45 46 h264_Info * pInfo = &(parser->info); 47 48 h264_Status status = H264_STATUS_ERROR; 49 50 51 uint8_t nal_ref_idc = 0; 52 53 ///// Parse NAL Unit header 54 pInfo->img.g_new_frame = 0; 55 pInfo->push_to_cur = 1; 56 pInfo->is_current_workload_done =0; 57 pInfo->nal_unit_type = 0; 58 59 h264_Parse_NAL_Unit(parent, pInfo, &nal_ref_idc); 60 61 ///// Check frame bounday for non-vcl elimitter 62 h264_check_previous_frame_end(pInfo); 63 64 //OS_INFO("========================nal_type: %d=================\n", pInfo->nal_unit_type); 65 //DEBUG_WRITE(pInfo->nal_unit_type, pInfo->got_start, pInfo->wl_err_flag, pInfo->is_current_workload_done, 0, 0); 66 #if 0 67 devh_SVEN_WriteModuleEvent( NULL, 68 SVEN_MODULE_EVENT_GV_FW_PARSER_DEBUG_P0, 69 pInfo->got_start,pInfo->nal_unit_type, pInfo->wl_err_curr, pInfo->is_current_workload_done, 0, pInfo->img.frame_num); 70 #endif 71 72 //////// Parse valid NAL unit 73 switch ( pInfo->nal_unit_type ) 74 { 75 case h264_NAL_UNIT_TYPE_IDR: 76 if(pInfo->got_start) { 77 pInfo->img.recovery_point_found |= 1; 78 } 79 80 pInfo->sei_rp_received = 0; 81 82 case h264_NAL_UNIT_TYPE_SLICE: 83 //////////////////////////////////////////////////////////////////////////// 84 // Step 1: Check start point 85 //////////////////////////////////////////////////////////////////////////// 86 // 87 /// Slice parsing must start from the valid start point( SPS, PPS, IDR or recovery point or primary_I) 88 /// 1) No start point reached, append current ES buffer to workload and release it 89 /// 2) else, start parsing 90 // 91 //if(pInfo->got_start && ((pInfo->sei_information.recovery_point) || (pInfo->nal_unit_type == h264_NAL_UNIT_TYPE_IDR))) 92 //{ 93 //pInfo->img.recovery_point_found = 1; 94 //} 95 { 96 97 h264_Slice_Header_t next_SliceHeader; 98 99 /// Reset next slice header 100 h264_memset(&next_SliceHeader, 0x0, sizeof(h264_Slice_Header_t)); 101 next_SliceHeader.nal_ref_idc = nal_ref_idc; 102 103 if( (1==pInfo->primary_pic_type_plus_one)&&(pInfo->got_start)) 104 { 105 pInfo->img.recovery_point_found |=4; 106 } 107 pInfo->primary_pic_type_plus_one = 0; 108 109 110 111 if(pInfo->img.recovery_point_found == 0) { 112 pInfo->img.structure = FRAME; 113 pInfo->wl_err_curr |= VIDDEC_FW_WORKLOAD_ERR_NOTDECODABLE; 114 pInfo->wl_err_curr |= (FRAME << FIELD_ERR_OFFSET); 115 break; 116 } 117 118 //////////////////////////////////////////////////////////////////////////// 119 // Step 2: Parsing slice header 120 //////////////////////////////////////////////////////////////////////////// 121 /// PWT 122 pInfo->h264_pwt_start_byte_offset=0; 123 pInfo->h264_pwt_start_bit_offset=0; 124 pInfo->h264_pwt_end_byte_offset=0; 125 pInfo->h264_pwt_end_bit_offset=0; 126 pInfo->h264_pwt_enabled =0; 127 /// IDR flag 128 next_SliceHeader.idr_flag = (pInfo->nal_unit_type == h264_NAL_UNIT_TYPE_IDR); 129 130 131 /// Pass slice header 132 status = h264_Parse_Slice_Layer_Without_Partitioning_RBSP(parent, pInfo, &next_SliceHeader); 133 134 pInfo->sei_information.recovery_point = 0; 135 136 if(next_SliceHeader.sh_error & 3) { 137 pInfo->wl_err_curr |= VIDDEC_FW_WORKLOAD_ERR_NOTDECODABLE; 138 139 // Error type definition, refer to viddec_fw_common_defs.h 140 // if error in top field, VIDDEC_FW_WORKLOAD_ERR_TOPFIELD = (1 << 17) 141 // if error in bottom field, VIDDEC_FW_WORKLOAD_ERR_BOTTOMFIELD = (1 << 18) 142 // if this is frame based, both 2 bits should be set 143 pInfo->wl_err_curr |= (FRAME << FIELD_ERR_OFFSET); 144 145 break; 146 } 147 pInfo->img.current_slice_num++; 148 149 150 #ifdef DUMP_HEADER_INFO 151 dump_slice_header(pInfo, &next_SliceHeader); 152 ////h264_print_decoder_values(pInfo); 153 #endif 154 155 156 //////////////////////////////////////////////////////////////////////////// 157 // Step 3: Processing if new picture coming 158 // 1) if it's the second field 159 // 2) if it's a new frame 160 //////////////////////////////////////////////////////////////////////////// 161 //AssignQuantParam(pInfo); 162 if(h264_is_new_picture_start(pInfo, next_SliceHeader, pInfo->SliceHeader)) 163 { 164 // 165 ///----------------- New Picture.boundary detected-------------------- 166 // 167 pInfo->img.g_new_pic++; 168 169 // 170 // Complete previous picture 171 h264_dpb_store_previous_picture_in_dpb(pInfo, 0, 0); //curr old 172 //h264_hdr_post_poc(0, 0, use_old); 173 174 // 175 // Update slice structures: 176 h264_update_old_slice(pInfo, next_SliceHeader); //cur->old; next->cur; 177 178 // 179 // 1) if resolution change: reset dpb 180 // 2) else: init frame store 181 h264_update_img_info(pInfo); //img, dpb 182 183 // 184 ///----------------- New frame.boundary detected-------------------- 185 // 186 pInfo->img.second_field = h264_is_second_field(pInfo); 187 if(pInfo->img.second_field == 0) 188 { 189 pInfo->img.g_new_frame = 1; 190 h264_dpb_update_queue_dangling_field(pInfo); 191 192 // 193 /// DPB management 194 /// 1) check the gaps 195 /// 2) assign fs for non-exist frames 196 /// 3) fill the gaps 197 /// 4) store frame into DPB if ... 198 // 199 //if(pInfo->SliceHeader.redundant_pic_cnt) 200 { 201 h264_dpb_gaps_in_frame_num_mem_management(pInfo); 202 } 203 204 #ifdef DUMP_HEADER_INFO 205 dump_new_picture_attr(pInfo, pInfo->SliceHeader.frame_num); 206 #endif 207 } 208 // 209 /// Decoding POC 210 h264_hdr_decoding_poc (pInfo, 0, 0); 211 212 // 213 /// Init Frame Store for next frame 214 h264_dpb_init_frame_store (pInfo); 215 pInfo->img.current_slice_num = 1; 216 217 if(pInfo->SliceHeader.first_mb_in_slice != 0) 218 { 219 ////Come here means we have slice lost at the beginning, since no FMO support 220 pInfo->SliceHeader.sh_error |= (pInfo->SliceHeader.structure << 17); 221 } 222 223 // 224 /// Emit out the New Frame 225 if(pInfo->img.g_new_frame) 226 { 227 h264_parse_emit_start_new_frame(parent, pInfo); 228 } 229 230 h264_parse_emit_current_pic(parent, pInfo); 231 } 232 else ///////////////////////////////////////////////////// If Not a picture start 233 { 234 // 235 /// Update slice structures: cur->old; next->cur; 236 h264_update_old_slice(pInfo, next_SliceHeader); 237 238 // 239 /// 1) if resolution change: reset dpb 240 /// 2) else: update img info 241 h264_update_img_info(pInfo); 242 } 243 244 245 ////////////////////////////////////////////////////////////// 246 // Step 4: DPB reference list init and reordering 247 ////////////////////////////////////////////////////////////// 248 249 //////////////////////////////////////////////// Update frame Type--- IDR/I/P/B for frame or field 250 h264_update_frame_type(pInfo); 251 252 253 h264_dpb_update_ref_lists( pInfo); 254 255 #ifdef DUMP_HEADER_INFO 256 dump_ref_list(pInfo); 257 #endif 258 /// Emit out the current "good" slice 259 h264_parse_emit_current_slice(parent, pInfo); 260 261 } 262 break; 263 264 ///// * Main profile doesn't support Data Partition, skipped.... *//// 265 case h264_NAL_UNIT_TYPE_DPA: 266 case h264_NAL_UNIT_TYPE_DPB: 267 case h264_NAL_UNIT_TYPE_DPC: 268 //OS_INFO("***********************DP feature, not supported currently*******************\n"); 269 pInfo->wl_err_curr |= VIDDEC_FW_WORKLOAD_ERR_NOTDECODABLE; 270 status = H264_STATUS_NOTSUPPORT; 271 break; 272 273 //// * Parsing SEI info *//// 274 case h264_NAL_UNIT_TYPE_SEI: 275 status = H264_STATUS_OK; 276 277 //OS_INFO("*****************************SEI**************************************\n"); 278 if(pInfo->sps_valid){ 279 //h264_user_data_t user_data; /// Replace with tmp buffer while porting to FW 280 pInfo->number_of_first_au_info_nal_before_first_slice++; 281 /// parsing the SEI info 282 status = h264_Parse_Supplemental_Enhancement_Information_Message(parent, pInfo); 283 } 284 285 //h264_rbsp_trailing_bits(pInfo); 286 break; 287 case h264_NAL_UNIT_TYPE_SPS: 288 { 289 //OS_INFO("*****************************SPS**************************************\n"); 290 /// 291 /// Can not define local SPS since the Current local stack size limitation! 292 /// Could be changed after the limitation gone 293 /// 294 uint8_t old_sps_id=0; 295 vui_seq_parameters_t_not_used vui_seq_not_used; 296 297 old_sps_id = pInfo->active_SPS.seq_parameter_set_id; 298 h264_memset(&(pInfo->active_SPS), 0x0, sizeof(seq_param_set_used)); 299 300 301 status = h264_Parse_SeqParameterSet(parent, pInfo, &(pInfo->active_SPS), &vui_seq_not_used, (int32_t *)pInfo->TMP_OFFSET_REFFRM_PADDR_GL); 302 if(status == H264_STATUS_OK) { 303 h264_Parse_Copy_Sps_To_DDR(pInfo, &(pInfo->active_SPS), pInfo->active_SPS.seq_parameter_set_id); 304 pInfo->sps_valid = 1; 305 306 if(1==pInfo->active_SPS.pic_order_cnt_type) { 307 h264_Parse_Copy_Offset_Ref_Frames_To_DDR(pInfo,(int32_t *)pInfo->TMP_OFFSET_REFFRM_PADDR_GL,pInfo->active_SPS.seq_parameter_set_id); 308 } 309 310 #ifdef DUMP_HEADER_INFO 311 dump_sps(&(pInfo->active_SPS)); 312 #endif 313 314 } 315 ///// Restore the active SPS if new arrival's id changed 316 if(old_sps_id>=MAX_NUM_SPS) { 317 h264_memset(&(pInfo->active_SPS), 0x0, sizeof(seq_param_set_used)); 318 pInfo->active_SPS.seq_parameter_set_id = 0xff; 319 } 320 else { 321 if(old_sps_id!=pInfo->active_SPS.seq_parameter_set_id) { 322 h264_Parse_Copy_Sps_From_DDR(pInfo, &(pInfo->active_SPS), old_sps_id); 323 } 324 else { 325 //h264_memset(&(pInfo->active_SPS), 0x0, sizeof(seq_param_set)); 326 pInfo->active_SPS.seq_parameter_set_id = 0xff; 327 } 328 } 329 330 pInfo->number_of_first_au_info_nal_before_first_slice++; 331 } 332 break; 333 case h264_NAL_UNIT_TYPE_PPS: 334 { 335 //OS_INFO("*****************************PPS**************************************\n"); 336 337 uint32_t old_sps_id = pInfo->active_SPS.seq_parameter_set_id; 338 uint32_t old_pps_id = pInfo->active_PPS.pic_parameter_set_id; 339 340 h264_memset(&pInfo->active_PPS, 0x0, sizeof(pic_param_set)); 341 pInfo->number_of_first_au_info_nal_before_first_slice++; 342 343 if (h264_Parse_PicParameterSet(parent, pInfo, &pInfo->active_PPS)== H264_STATUS_OK) 344 { 345 h264_Parse_Copy_Sps_From_DDR(pInfo, &(pInfo->active_SPS), pInfo->active_PPS.seq_parameter_set_id); 346 if(old_sps_id != pInfo->active_SPS.seq_parameter_set_id) 347 { 348 pInfo->Is_SPS_updated = 1; 349 } 350 if(pInfo->active_SPS.seq_parameter_set_id != 0xff) { 351 h264_Parse_Copy_Pps_To_DDR(pInfo, &pInfo->active_PPS, pInfo->active_PPS.pic_parameter_set_id); 352 pInfo->got_start = 1; 353 if(pInfo->sei_information.recovery_point) 354 { 355 pInfo->img.recovery_point_found |= 2; 356 357 //// Enable the RP recovery if no IDR ---Cisco 358 if((pInfo->img.recovery_point_found & 1)==0) 359 pInfo->sei_rp_received = 1; 360 } 361 } 362 else 363 { 364 h264_Parse_Copy_Sps_From_DDR(pInfo, &(pInfo->active_SPS), old_sps_id); 365 } 366 #ifdef DUMP_HEADER_INFO 367 dump_pps(&(pInfo->active_PPS)); 368 #endif 369 } else { 370 if(old_sps_id<MAX_NUM_SPS) 371 h264_Parse_Copy_Sps_From_DDR(pInfo, &(pInfo->active_SPS), old_sps_id); 372 if(old_pps_id<MAX_NUM_PPS) 373 h264_Parse_Copy_Pps_From_DDR(pInfo, &(pInfo->active_PPS), old_pps_id); 374 } 375 376 } //// End of PPS parsing 377 break; 378 379 380 case h264_NAL_UNIT_TYPE_EOSeq: 381 case h264_NAL_UNIT_TYPE_EOstream: 382 383 h264_parse_emit_eos(parent, pInfo); 384 h264_init_dpb(&(pInfo->dpb)); 385 386 /* picture level info which will always be initialized */ 387 //h264_init_Info_under_sps_pps_level(pInfo); 388 389 ////reset the pInfo here 390 //viddec_h264_init(ctxt, (uint32_t *)parser->sps_pps_ddr_paddr, false); 391 392 393 status = H264_STATUS_OK; 394 pInfo->number_of_first_au_info_nal_before_first_slice++; 395 break; 396 397 case h264_NAL_UNIT_TYPE_Acc_unit_delimiter: 398 #if 1 399 ///// primary_pic_type 400 { 401 uint32_t code = 0xff; 402 int32_t ret = 0; 403 ret = viddec_pm_get_bits(parent, (uint32_t *)&(code), 3); 404 405 if(ret != -1) { 406 //if(pInfo->got_start && (code == 0)) 407 //{ 408 //pInfo->img.recovery_point_found |= 4; 409 //} 410 pInfo->primary_pic_type_plus_one = (uint8_t)(code)+1; 411 status = H264_STATUS_OK; 412 } 413 pInfo->number_of_first_au_info_nal_before_first_slice++; 414 break; 415 } 416 #endif 417 418 case h264_NAL_UNIT_TYPE_Reserved1: 419 case h264_NAL_UNIT_TYPE_Reserved2: 420 case h264_NAL_UNIT_TYPE_Reserved3: 421 case h264_NAL_UNIT_TYPE_Reserved4: 422 case h264_NAL_UNIT_TYPE_Reserved5: 423 status = H264_STATUS_OK; 424 pInfo->number_of_first_au_info_nal_before_first_slice++; 425 break; 426 427 case h264_NAL_UNIT_TYPE_filler_data: 428 status = H264_STATUS_OK; 429 break; 430 case h264_NAL_UNIT_TYPE_ACP: 431 break; 432 case h264_NAL_UNIT_TYPE_SPS_extension: 433 case h264_NAL_UNIT_TYPE_unspecified: 434 case h264_NAL_UNIT_TYPE_unspecified2: 435 status = H264_STATUS_OK; 436 //nothing 437 break; 438 default: 439 status = H264_STATUS_OK; 440 break; 441 } 442 443 //pInfo->old_nal_unit_type = pInfo->nal_unit_type; 444 switch ( pInfo->nal_unit_type ) 445 { 446 case h264_NAL_UNIT_TYPE_IDR: 447 case h264_NAL_UNIT_TYPE_SLICE: 448 case h264_NAL_UNIT_TYPE_Acc_unit_delimiter: 449 case h264_NAL_UNIT_TYPE_SPS: 450 case h264_NAL_UNIT_TYPE_PPS: 451 case h264_NAL_UNIT_TYPE_SEI: 452 case h264_NAL_UNIT_TYPE_EOSeq: 453 case h264_NAL_UNIT_TYPE_EOstream: 454 case h264_NAL_UNIT_TYPE_Reserved1: 455 case h264_NAL_UNIT_TYPE_Reserved2: 456 case h264_NAL_UNIT_TYPE_Reserved3: 457 case h264_NAL_UNIT_TYPE_Reserved4: 458 case h264_NAL_UNIT_TYPE_Reserved5: 459 { 460 pInfo->old_nal_unit_type = pInfo->nal_unit_type; 461 break; 462 } 463 default: 464 break; 465 } 466 467 return status; 468 } 469 470 471 472 473 /* ------------------------------------------------------------------------------------------ */ 474 /* ------------------------------------------------------------------------------------------ */ 475 /* ------------------------------------------------------------------------------------------ */ 476 477 static uint32_t viddec_h264_is_frame_start(void *ctxt) 478 { 479 struct h264_viddec_parser* parser = ctxt; 480 uint32_t ret = 0; 481 482 h264_Info * pInfo = &(parser->info); 483 484 if(pInfo->img.g_new_frame) { 485 ret = 1; 486 } 487 488 return ret; 489 } 490 491 #ifdef VBP 492 uint32_t viddec_h264_wkld_done(void *parent, void *ctxt, unsigned int next_sc, 493 uint32_t *codec_specific_errors) 494 #else 495 static uint32_t viddec_h264_wkld_done(void *parent, void *ctxt, unsigned int next_sc, uint32_t *codec_specific_errors) 496 #endif 497 { 498 struct h264_viddec_parser* parser = ctxt; 499 uint32_t ret = VIDDEC_PARSE_SUCESS; 500 h264_Info * pInfo = &(parser->info); 501 uint8_t is_stream_forced_to_complete=false; 502 503 is_stream_forced_to_complete = (VIDDEC_PARSE_EOS == next_sc) || (VIDDEC_PARSE_DISCONTINUITY == next_sc); 504 505 if(is_stream_forced_to_complete || (pInfo->is_current_workload_done)) 506 { 507 viddec_workload_t *wl; 508 viddec_frame_attributes_t *attrs; 509 510 wl = viddec_pm_get_header( parent ); 511 attrs = &wl->attrs; 512 513 if((attrs->cont_size.width < 32) || (attrs->cont_size.width > 2048) || (attrs->cont_size.height < 32) || (attrs->cont_size.height>2048)) 514 { 515 attrs->cont_size.width = 32; 516 attrs->cont_size.height = 32; 517 pInfo->wl_err_curr |= VIDDEC_FW_WORKLOAD_ERR_NOTDECODABLE; 518 pInfo->wl_err_curr |= (FRAME << FIELD_ERR_OFFSET); 519 } 520 521 *codec_specific_errors = pInfo->wl_err_curr; 522 pInfo->wl_err_curr = pInfo->wl_err_next; 523 pInfo->wl_err_next = 0; 524 525 if(is_stream_forced_to_complete) 526 { 527 h264_parse_emit_eos(parent, pInfo); 528 } 529 ret = VIDDEC_PARSE_FRMDONE; 530 } 531 532 return ret; 533 } 534 535 #ifdef VBP 536 void viddec_h264_get_context_size(viddec_parser_memory_sizes_t *size) 537 #else 538 static void viddec_h264_get_context_size(viddec_parser_memory_sizes_t *size) 539 #endif 540 { 541 /* Should return size of my structure */ 542 size->context_size = sizeof(struct h264_viddec_parser); 543 size->persist_size = MAX_NUM_SPS * sizeof(seq_param_set_all) 544 + MAX_NUM_PPS * sizeof(pic_param_set) 545 + MAX_NUM_SPS * sizeof(int32_t) * MAX_NUM_REF_FRAMES_IN_PIC_ORDER_CNT_CYCLE 546 + sizeof(int32_t) * MAX_NUM_REF_FRAMES_IN_PIC_ORDER_CNT_CYCLE; 547 } 548 549 void viddec_h264_get_ops(viddec_parser_ops_t *ops) 550 { 551 ops->init = viddec_h264_init; 552 553 ops->parse_syntax = viddec_h264_parse; 554 ops->get_cxt_size = viddec_h264_get_context_size; 555 ops->is_wkld_done = viddec_h264_wkld_done; 556 ops->is_frame_start = viddec_h264_is_frame_start; 557 return; 558 } 559 560