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
viddec_h264_init(void * ctxt,uint32_t * persist_mem,uint32_t preserve)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
viddec_h264_parse(void * parent,void * ctxt)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
viddec_h264_is_frame_start(void * ctxt)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
viddec_h264_wkld_done(void * parent,void * ctxt,unsigned int next_sc,uint32_t * codec_specific_errors)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
viddec_h264_get_context_size(viddec_parser_memory_sizes_t * size)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
viddec_h264_get_ops(viddec_parser_ops_t * ops)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