1#include "viddec_fw_debug.h"
2#include "viddec_parser_ops.h"
3#include "h264.h"
4#include "h264parse.h"
5#include "viddec_fw_item_types.h"
6#include "h264parse_dpb.h"
7#include <glib.h>
8
9extern void* h264_memcpy( void* dest, void* src, uint32_t num );
10
11uint32_t cp_using_dma(uint32_t ddr_addr, uint32_t local_addr, uint32_t size, char to_ddr, char swap)
12{
13	if (swap != 0)
14	{
15		g_warning("swap copying is not implemented.");
16	}
17
18	if (to_ddr)
19	{
20		memcpy((void*)ddr_addr, (void*)local_addr, size);
21	}
22	else
23	{
24		memcpy((void*)local_addr, (void*)ddr_addr, size);
25	}
26
27    return (0);
28}
29
30#if 0
31void h264_parse_emit_start_new_frame( void *parent, h264_Info *pInfo )
32{
33
34   if(pInfo->Is_first_frame_in_stream) //new stream, fill new frame in cur
35   {
36
37      pInfo->img.g_new_frame = 0;
38      pInfo->Is_first_frame_in_stream =0;
39      pInfo->push_to_cur = 1;
40
41   }
42   else  // move to next for new frame
43   {
44      pInfo->push_to_cur = 0;
45   }
46
47
48
49   //fill dpb managemnt info
50
51
52
53
54      pInfo->dpb.frame_numbers_need_to_be_displayed =0;
55      pInfo->dpb.frame_numbers_need_to_be_removed =0;
56      pInfo->dpb.frame_numbers_need_to_be_allocated =0;
57
58
59}
60
61void h264_parse_emit_eos( void *parent, h264_Info *pInfo )
62{
63  	////
64	//// Now we can flush out all frames in DPB fro display
65	if(pInfo->dpb.fs[pInfo->dpb.fs_dec_idc].is_used != 3)
66	{
67		h264_dpb_mark_dangling_field(&pInfo->dpb, pInfo->dpb.fs_dec_idc);  //, DANGLING_TYPE_GAP_IN_FRAME
68	}
69
70   h264_dpb_store_previous_picture_in_dpb(pInfo, 0,0);
71   h264_dpb_flush_dpb(pInfo, 1, 0, pInfo->active_SPS.num_ref_frames);
72
73
74	pInfo->dpb.frame_numbers_need_to_be_displayed =0;
75   	pInfo->dpb.frame_numbers_need_to_be_removed =0;
76
77}
78
79void h264_parse_emit_current_pic( void *parent, h264_Info *pInfo )
80{
81   pInfo->qm_present_list=0;
82}
83
84void h264_parse_emit_current_slice( void *parent, h264_Info *pInfo )
85{
86#if 1
87   uint32_t  i, nitems=0;
88
89
90   if( (h264_PtypeB==pInfo->SliceHeader.slice_type)||(h264_PtypeP==pInfo->SliceHeader.slice_type) )
91   {
92      if(pInfo->SliceHeader.sh_refpic_l0.ref_pic_list_reordering_flag)
93      {
94         nitems = pInfo->SliceHeader.num_ref_idx_l0_active;
95
96         for(i=0; i<nitems;i++)
97         {
98            if(viddec_h264_get_is_non_existent(&(pInfo->dpb.fs[pInfo->slice_ref_list0[i]&0x1f]))==0)
99            {
100              pInfo->h264_list_replacement = (pInfo->slice_ref_list0[i]&0xFF)|0x80;
101              break;
102            }
103         }
104      }
105      else
106      {
107         nitems = pInfo->dpb.listXsize[0];
108
109         for(i=0; i<nitems;i++)
110         {
111            if(viddec_h264_get_is_non_existent(&(pInfo->dpb.fs[pInfo->dpb.listX_0[i]&0x1f]))==0)
112            {
113              pInfo->h264_list_replacement = (pInfo->dpb.listX_0[i]&0xFF)|0x80;
114              break;
115            }
116         }
117      }
118
119   }
120   else
121   {
122      nitems =0;
123   }
124#endif
125}
126#else
127
128
129void h264_parse_emit_current_slice( void *parent, h264_Info *pInfo )
130{
131
132   viddec_workload_item_t     wi;
133   h264_slice_data 				slice_data;
134
135   uint32_t		i=0, nitems=0, data=0;
136   uint32_t 	bits_offset =0, byte_offset =0;
137   uint8_t    	is_emul =0;
138
139
140	////////////////////// Update Reference list //////////////////
141   if( (h264_PtypeB==pInfo->SliceHeader.slice_type)||(h264_PtypeP==pInfo->SliceHeader.slice_type) )
142   {
143      if(pInfo->SliceHeader.sh_refpic_l0.ref_pic_list_reordering_flag)
144      {
145         nitems = pInfo->SliceHeader.num_ref_idx_l0_active;
146
147         for(i=0; i<nitems;i++)
148         {
149            if(viddec_h264_get_is_non_existent(&(pInfo->dpb.fs[pInfo->slice_ref_list0[i]&0x1f]))==0)
150            {
151              pInfo->h264_list_replacement = (pInfo->slice_ref_list0[i]&0xFF)|0x80;
152              break;
153            }
154         }
155      }
156      else
157      {
158         nitems = pInfo->dpb.listXsize[0];
159
160         for(i=0; i<nitems;i++)
161         {
162            if(viddec_h264_get_is_non_existent(&(pInfo->dpb.fs[pInfo->dpb.listX_0[i]&0x1f]))==0)
163            {
164              pInfo->h264_list_replacement = (pInfo->dpb.listX_0[i]&0xFF)|0x80;
165              break;
166            }
167         }
168      }
169
170   }
171   else
172   {
173      nitems =0;
174   }
175	/////file ref list 0
176  // h264_parse_emit_ref_list(parent, pInfo, 0);
177
178   /////file ref list 1
179   //h264_parse_emit_ref_list(parent, pInfo, 1);
180
181	///////////////////////////////////// Slice Data ////////////////////////////////
182  // h264_fill_slice_data(pInfo, &slice_data);
183
184   wi.vwi_type = VIDDEC_WORKLOAD_H264_SLICE_REG;
185
186   wi.data.data_offset = slice_data.h264_bsd_slice_start;
187   wi.data.data_payload[0] = slice_data.h264_bsd_slice_p1;
188   wi.data.data_payload[1] = slice_data.h264_bsd_slice_p2;
189
190   if(pInfo->push_to_cur) //cur is empty, fill new frame in cur
191   {
192     // viddec_pm_append_workitem( parent , &wi);
193   }
194   else
195   {
196     // viddec_pm_append_workitem_next( parent , &wi);
197   }
198
199
200   ///////////////////////////predict weight table item and data if have///////////////////////////
201   if(pInfo->h264_pwt_enabled)
202   {
203      wi.vwi_type = VIDDEC_WORKLOAD_H264_PWT_BITS_OFFSET;
204      wi.data.data_offset = pInfo->h264_pwt_end_byte_offset- pInfo->h264_pwt_start_byte_offset+1;
205      wi.data.data_payload[0] = pInfo->h264_pwt_start_bit_offset;
206      wi.data.data_payload[1] = pInfo->h264_pwt_end_bit_offset;
207
208      if(pInfo->push_to_cur) //cur is empty, fill new frame in cur
209      {
210        // viddec_pm_append_workitem( parent , &wi);
211
212         wi.vwi_type = VIDDEC_WORKLOAD_H264_PWT_ES_BYTES;
213         wi.es.es_flags = 0;
214        // viddec_pm_append_misc_tags(parent, pInfo->h264_pwt_start_byte_offset, pInfo->h264_pwt_end_byte_offset,&wi,1);
215      }
216      else
217      {
218       //  viddec_pm_append_workitem_next( parent , &wi);
219
220         wi.vwi_type = VIDDEC_WORKLOAD_H264_PWT_ES_BYTES;
221         wi.es.es_flags = 0;
222       //  viddec_pm_append_misc_tags(parent, pInfo->h264_pwt_start_byte_offset, pInfo->h264_pwt_end_byte_offset,&wi,0);
223      }
224   }
225
226
227 	////////////////////////////////// Update ES Buffer for Slice ///////////////////////
228   viddec_pm_get_au_pos(parent, &bits_offset, &byte_offset, &is_emul);
229
230	//OS_INFO("DEBUG---entropy_coding_mode_flag:%d, bits_offset: %d\n", pInfo->active_PPS.entropy_coding_mode_flag, bits_offset);
231
232   if(pInfo->active_PPS.entropy_coding_mode_flag)
233   {
234   	if(0!=bits_offset)  {
235   		 data = data; // fix compilation warning
236   		 // don't skip byte-aligned bits as those bits are actually
237   		 // part of slice_data
238         //viddec_pm_get_bits(parent, &data, 8-bits_offset);
239      }
240   }
241	else
242   {
243      if(0!=bits_offset)  {
244         wi.vwi_type = VIDDEC_WORKLOAD_H264_SH_BITS_OFFSET;
245         wi.data.data_offset = bits_offset;
246         wi.data.data_payload[0]=0;
247         wi.data.data_payload[1]=0;
248
249         if(pInfo->push_to_cur) {			//cur is empty, fill new frame in cur
250           // viddec_pm_append_workitem( parent , &wi);
251         }
252         else {
253            //viddec_pm_append_workitem_next( parent , &wi);
254         }
255      }
256   }
257
258   if(pInfo->push_to_cur) //cur is empty, fill new frame in cur
259   {
260      //viddec_pm_append_pixeldata( parent );
261   }
262   else
263   {
264      //viddec_pm_append_pixeldata_next( parent);
265   }
266
267	return;
268}
269
270
271void h264_parse_emit_current_pic( void *parent, h264_Info *pInfo )
272{
273
274   viddec_workload_item_t     wi;
275
276   const uint32_t             *pl;
277   uint32_t                   i=0,nitems=0;
278
279   h264_pic_data pic_data;
280
281   pInfo->qm_present_list=0;
282
283   //h264_parse_emit_4X4_scaling_matrix(parent, pInfo);
284  // h264_parse_emit_8X8_scaling_matrix(parent, pInfo);
285
286  // h264_fill_pic_data(pInfo, &pic_data);
287
288   // How many payloads must be generated
289   nitems = (sizeof(h264_pic_data) + 7) / 8; // In QWORDs rounded up
290
291   pl = (const uint32_t *) &pic_data;
292
293   // Dump slice data to an array of workitems,  to do pl access non valid mem
294   for( i = 0; i < nitems; i++ )
295   {
296      wi.vwi_type           = VIDDEC_WORKLOAD_H264_PIC_REG;
297      wi.data.data_offset   = (unsigned int)pl - (unsigned int)&pic_data; // offset within struct
298      wi.data.data_payload[0] = pl[0];
299      wi.data.data_payload[1] = pl[1];
300      pl += 2;
301
302      if(pInfo->push_to_cur) //cur is empty, fill new frame in cur
303      {
304
305       //  viddec_pm_append_workitem( parent, &wi );
306      }
307      else
308      {
309         //viddec_pm_append_workitem_next( parent, &wi );
310      }
311   }
312
313	return;
314}
315
316void h264_parse_emit_start_new_frame( void *parent, h264_Info *pInfo )
317{
318
319   viddec_workload_item_t     wi;
320   uint32_t                   i=0,nitems=0;
321
322	///////////////////////// Frame attributes//////////////////////////
323
324   //Push data into current workload if first frame or frame_boundary already detected by non slice nal
325   if( (pInfo->Is_first_frame_in_stream)||(pInfo->is_frame_boundary_detected_by_non_slice_nal))
326   {
327		//viddec_workload_t			*wl_cur = viddec_pm_get_header( parent );
328		//pInfo->img.g_new_frame = 0;
329		pInfo->Is_first_frame_in_stream =0;
330		pInfo->is_frame_boundary_detected_by_non_slice_nal=0;
331		pInfo->push_to_cur = 1;
332		//h264_translate_parser_info_to_frame_attributes(wl_cur, pInfo);
333   }
334   else  // move to cur if frame boundary detected by previous non slice nal, or move to next if not
335   {
336		//viddec_workload_t        *wl_next = viddec_pm_get_next_header (parent);
337
338		pInfo->push_to_cur = 0;
339		//h264_translate_parser_info_to_frame_attributes(wl_next, pInfo);
340
341		pInfo->is_current_workload_done=1;
342   }
343
344	///////////////////// SPS/////////////////////
345  // h264_parse_emit_sps(parent, pInfo);
346
347	/////////////////////display frames/////////////////////
348	nitems = pInfo->dpb.frame_numbers_need_to_be_displayed;
349
350	for(i=0; i<nitems; i++)
351	{
352		wi.vwi_type = VIDDEC_WORKLOAD_REF_FRAME_DISPLAY_0 + pInfo->dpb.frame_id_need_to_be_displayed[i];
353		wi.ref_frame.reference_id = pInfo->dpb.frame_id_need_to_be_displayed[i];
354		wi.ref_frame.luma_phys_addr = 0;
355		wi.ref_frame.chroma_phys_addr = 0;
356
357		if(pInfo->push_to_cur) //cur is empty, fill new frame in cur
358		{
359		  // viddec_pm_append_workitem( parent, &wi );
360		}
361		else
362		{
363		  // viddec_pm_append_workitem_next( parent, &wi );
364		}
365	}
366	pInfo->dpb.frame_numbers_need_to_be_displayed =0;
367
368
369	/////////////////////release frames/////////////////////
370	nitems = pInfo->dpb.frame_numbers_need_to_be_removed;
371
372	for(i=0; i<nitems; i++)
373	{
374	   wi.vwi_type = VIDDEC_WORKLOAD_REF_FRAME_RELEASE_0 + pInfo->dpb.frame_id_need_to_be_removed[i];
375	   wi.ref_frame.reference_id = pInfo->dpb.frame_id_need_to_be_removed[i];
376	   wi.ref_frame.luma_phys_addr = 0;
377	   wi.ref_frame.chroma_phys_addr = 0;
378
379	   if(pInfo->push_to_cur) //cur is empty, fill new frame in cur
380	   {
381	      //viddec_pm_append_workitem( parent, &wi );
382	   }
383	   else
384	   {
385	     // viddec_pm_append_workitem_next( parent, &wi );
386	   }
387
388	}
389	pInfo->dpb.frame_numbers_need_to_be_removed =0;
390
391	/////////////////////flust frames (do not display)/////////////////////
392	nitems = pInfo->dpb.frame_numbers_need_to_be_dropped;
393
394	for(i=0; i<nitems; i++)
395	{
396	   wi.vwi_type = VIDDEC_WORKLOAD_REF_FRAME_DROPOUT_0 + pInfo->dpb.frame_id_need_to_be_dropped[i];
397	   wi.ref_frame.reference_id = pInfo->dpb.frame_id_need_to_be_dropped[i];
398	   wi.ref_frame.luma_phys_addr = 0;
399	   wi.ref_frame.chroma_phys_addr = 0;
400
401	   if(pInfo->push_to_cur) //cur is empty, fill new frame in cur
402	   {
403	      //viddec_pm_append_workitem( parent, &wi );
404	   }
405	   else
406	   {
407	     // viddec_pm_append_workitem_next( parent, &wi );
408	   }
409
410	}
411	pInfo->dpb.frame_numbers_need_to_be_dropped =0;
412
413	/////////////////////updata DPB frames/////////////////////
414	nitems = pInfo->dpb.used_size;
415	for(i=0; i<nitems; i++)
416	{
417	   uint8_t fs_id = pInfo->dpb.fs_dpb_idc[i];
418
419	   if(viddec_h264_get_is_non_existent(&(pInfo->dpb.fs[fs_id])) == 0)
420	   {
421	      wi.vwi_type = VIDDEC_WORKLOAD_DPB_ACTIVE_FRAME_0+fs_id;
422	      wi.ref_frame.reference_id = fs_id;
423	      wi.ref_frame.luma_phys_addr = 0;
424	      wi.ref_frame.chroma_phys_addr = 0;
425
426	      if(pInfo->push_to_cur) //cur is empty, fill new frame in cur
427	      {
428	        // viddec_pm_append_workitem( parent, &wi );
429	      }
430	      else
431	      {
432	         //viddec_pm_append_workitem_next( parent, &wi );
433	      }
434	   }
435	}
436
437
438	/////////////////////updata dpb frames info (poc)/////////////////////
439	nitems = pInfo->dpb.used_size;
440	for(i=0; i<nitems; i++)
441	{
442	   uint8_t fs_id = pInfo->dpb.fs_dpb_idc[i];
443
444	   if(viddec_h264_get_is_non_existent(&(pInfo->dpb.fs[fs_id])) == 0)
445	   {
446	      wi.vwi_type = VIDDEC_WORKLOAD_H264_DPB_FRAME_POC;
447	      wi.data.data_offset = fs_id;
448	      //printf("is_used = %d, tpoc = %d, bpoc = %d\n", pInfo->dpb.fs[fs_id].is_used, pInfo->dpb.fs[fs_id].top_field.poc, pInfo->dpb.fs[fs_id].bottom_field.poc);
449
450	      switch(viddec_h264_get_is_used(&(pInfo->dpb.fs[fs_id])))
451	      {
452	         case (FRAME):{
453	            wi.data.data_payload[0] = pInfo->dpb.fs[fs_id].top_field.poc;
454	            wi.data.data_payload[1] = pInfo->dpb.fs[fs_id].bottom_field.poc;
455	            break;
456	         };
457
458	         case (TOP_FIELD):{
459	            wi.data.data_payload[0] = pInfo->dpb.fs[fs_id].top_field.poc;
460	            wi.data.data_payload[1] = 0;
461	            break;
462	         };
463
464	         case (BOTTOM_FIELD):{
465	            wi.data.data_payload[0] = 0;
466	            wi.data.data_payload[1] = pInfo->dpb.fs[fs_id].bottom_field.poc;
467	            break;
468	         };
469
470	         default : {
471	            wi.data.data_payload[0] = 0;
472	            wi.data.data_payload[1] = 0;
473	            break;
474	         };
475	      }
476
477
478	      if(pInfo->push_to_cur) //cur is empty, fill new frame in cur
479	      {
480	       //  viddec_pm_append_workitem( parent, &wi );
481	      }
482	      else
483	      {
484	         //viddec_pm_append_workitem_next( parent, &wi );
485	      }
486
487	   }
488	}
489
490	/////////////////////Alloc buffer for current Existing frame/////////////////////
491	if(0!=pInfo->dpb.frame_numbers_need_to_be_allocated)
492	{
493	   if(pInfo->push_to_cur)
494	   {
495	     // viddec_workload_t        *wl_cur = viddec_pm_get_header (parent);
496	    //  wl_cur->is_reference_frame |= WORKLOAD_REFERENCE_FRAME | (pInfo->dpb.frame_id_need_to_be_allocated & 0x1f);
497	   }
498	   else
499	   {
500	     // viddec_workload_t        *wl_next = viddec_pm_get_next_header (parent);
501	      //wl_next->is_reference_frame |= WORKLOAD_REFERENCE_FRAME | (pInfo->dpb.frame_id_need_to_be_allocated & 0x1f);
502	   }
503	}
504	pInfo->dpb.frame_numbers_need_to_be_allocated =0;
505
506	return;
507}
508
509
510
511void h264_parse_emit_eos( void *parent, h264_Info *pInfo )
512{
513
514   uint32_t nitems=0, i=0;
515   viddec_workload_item_t	wi;
516
517  	////
518	//// Now we can flush out all frames in DPB fro display
519   	if(viddec_h264_get_is_used(&(pInfo->dpb.fs[pInfo->dpb.fs_dec_idc])) != 3)
520	{
521		h264_dpb_mark_dangling_field(&pInfo->dpb, pInfo->dpb.fs_dec_idc);  //, DANGLING_TYPE_GAP_IN_FRAME
522	}
523
524   h264_dpb_store_previous_picture_in_dpb(pInfo, 0,0);
525   h264_dpb_flush_dpb(pInfo, 1, 0, pInfo->active_SPS.num_ref_frames);
526
527
528	/////////////////////display frames/////////////////////
529	nitems = pInfo->dpb.frame_numbers_need_to_be_displayed;
530
531	for(i=0; i<nitems; i++)
532	{
533		wi.vwi_type = VIDDEC_WORKLOAD_EOS_DISPLAY_FRAME_0 + pInfo->dpb.frame_id_need_to_be_displayed[i];
534		wi.ref_frame.reference_id = pInfo->dpb.frame_id_need_to_be_displayed[i];
535		wi.ref_frame.luma_phys_addr = 0;
536		wi.ref_frame.chroma_phys_addr = 0;
537
538		if(pInfo->push_to_cur) //cur is empty, fill new frame in cur
539		{
540		   //viddec_pm_append_workitem( parent, &wi );
541		}
542		else
543		{
544		   //viddec_pm_append_workitem_next( parent, &wi );
545		}
546	}
547	pInfo->dpb.frame_numbers_need_to_be_displayed =0;
548
549
550	/////////////////////release frames/////////////////////
551	nitems = pInfo->dpb.frame_numbers_need_to_be_removed;
552
553	for(i=0; i<nitems; i++)
554	{
555	   wi.vwi_type = VIDDEC_WORKLOAD_EOS_RELEASE_FRAME_0 + pInfo->dpb.frame_id_need_to_be_removed[i];
556	   wi.ref_frame.reference_id = pInfo->dpb.frame_id_need_to_be_removed[i];
557	   wi.ref_frame.luma_phys_addr = 0;
558	   wi.ref_frame.chroma_phys_addr = 0;
559
560	   if(pInfo->push_to_cur) //cur is empty, fill new frame in cur
561	   {
562	    //  viddec_pm_append_workitem( parent, &wi );
563			viddec_pm_set_next_frame_error_on_eos(parent, VIDDEC_FW_WORKLOAD_ERR_NOTDECODABLE);
564	   }
565	   else
566	   {
567	     // viddec_pm_append_workitem_next( parent, &wi );
568       viddec_pm_set_next_frame_error_on_eos(parent, pInfo->wl_err_next);
569	   }
570	}
571	pInfo->dpb.frame_numbers_need_to_be_removed =0;
572
573	return;
574}
575#endif
576