• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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