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
15void viddec_h264_init(void *ctxt, uint32_t *persist_mem, uint32_t preserve)
16#else
17static 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
39uint32_t viddec_h264_parse(void *parent, void *ctxt)
40#else
41static 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
151dump_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
477static 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
492uint32_t viddec_h264_wkld_done(void *parent, void *ctxt, unsigned int next_sc,
493                                uint32_t *codec_specific_errors)
494#else
495static 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
536void viddec_h264_get_context_size(viddec_parser_memory_sizes_t *size)
537#else
538static 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
549void 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