xref: /aosp_15_r20/external/libavc/common/ih264_dpb_mgr.c (revision 495ae853bb871d1e5a258cb02c2cc13cde8ddb9a)
1 /******************************************************************************
2  *
3  * Copyright (C) 2015 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *****************************************************************************
18  * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19 */
20 
21 /**
22 *******************************************************************************
23 * @file
24 *  ih264_dpb_mgr.c
25 *
26 * @brief
27 *  Function definitions used for decoded picture buffer management
28 *
29 * @author
30 *  ittiam
31 *
32 * @par List of Functions:
33 *  - ih264_dpb_mgr_init
34 *  - ih264_dpb_mgr_sort_short_term_fields_by_frame_num
35 *  - ih264_dpb_mgr_sort_short_term_fields_by_poc_l0
36 *  - ih264_dpb_mgr_sort_short_term_fields_by_poc_l1
37 *  - ih264_dpb_mgr_sort_long_term_fields_by_frame_idx
38 *  - ih264_dpb_mgr_alternate_ref_fields
39 *  - ih264_dpb_mgr_insert_ref_field
40 *  - ih264_dpb_mgr_insert_ref_frame
41 *  - ih264_dpb_mgr_count_ref_frames
42 *  - ih264_dpb_mgr_delete_ref_frame
43 *  - ih264_dpb_mgr_delete_long_ref_fields_max_frame_idx
44 *  - ih264_dpb_mgr_delete_short_ref_frame
45 *  - ih264_dpb_mgr_delete_all_ref_frames
46 *  - ih264_dpb_mgr_reset
47 *  - ih264_dpb_mgr_release_pics
48 *
49 * @remarks
50 *  none
51 *
52 *******************************************************************************
53 */
54 
55 /*****************************************************************************/
56 /* File Includes                                                             */
57 /*****************************************************************************/
58 
59 /* System Include Files */
60 #include <stdio.h>
61 #include <stdlib.h>
62 #include <assert.h>
63 
64 /* User Include Files */
65 #include "ih264_typedefs.h"
66 #include "ih264_debug.h"
67 #include "ih264_macros.h"
68 #include "ih264_error.h"
69 #include "ih264_defs.h"
70 #include "ih264_structs.h"
71 #include "ih264_buf_mgr.h"
72 #include "ih264_dpb_mgr.h"
73 
74 
75 /*****************************************************************************/
76 /* Function Definitions                                                      */
77 /*****************************************************************************/
78 
79 /**
80 *******************************************************************************
81 *
82 * @brief DPB manager initializer
83 *
84 * @par Description Initialises the DPB manager structure
85 *
86 * @param[in] ps_dpb_mgr
87 *  Pointer to the DPB manager structure
88 *
89 * @returns
90 *
91 * @remarks
92 *
93 *******************************************************************************
94 */
ih264_dpb_mgr_init(dpb_mgr_t * ps_dpb_mgr)95 void ih264_dpb_mgr_init(dpb_mgr_t *ps_dpb_mgr)
96 {
97     UWORD32 i;
98     dpb_info_t *ps_dpb_info = ps_dpb_mgr->as_dpb_info;
99 
100     for(i = 0; i < MAX_DPB_BUFS; i++)
101     {
102         ps_dpb_info[i].ps_prev_dpb = NULL;
103         ps_dpb_info[i].ps_pic_buf = NULL;
104         ps_dpb_mgr->as_top_field_pics[i].i4_used_as_ref = INVALID;
105         ps_dpb_mgr->as_bottom_field_pics[i].i4_used_as_ref = INVALID;
106         ps_dpb_mgr->as_top_field_pics[i].i1_field_type = INVALID;
107         ps_dpb_mgr->as_bottom_field_pics[i].i1_field_type = INVALID;
108         ps_dpb_mgr->as_top_field_pics[i].i4_long_term_frame_idx = -1;
109         ps_dpb_mgr->as_bottom_field_pics[i].i4_long_term_frame_idx = -1;
110     }
111     ps_dpb_mgr->u1_num_short_term_ref_bufs = 0;
112     ps_dpb_mgr->u1_num_long_term_ref_bufs = 0;
113     ps_dpb_mgr->ps_dpb_short_term_head = NULL;
114     ps_dpb_mgr->ps_dpb_long_term_head = NULL;
115 }
116 
117 /**
118 *******************************************************************************
119 *
120 * @brief
121 *  Function to sort short term pics by frame_num.
122 *
123 * @par Description:
124 *  Sorts short term fields by frame_num. For 2 fields having same frame_num,
125 *  orders them based on requested first field type.
126 *
127 * @param[in] ps_dpb_mgr
128 *  Pointer to the DPB manager structure
129 *
130 * @param[in] curr_frame_num
131 *  frame_num of the current pic
132 *
133 * @param[in] first_field_type
134 *  For complementary fields, required first field
135 *
136 * @param[in] max_frame_num
137 *  Maximum frame_num allowed
138 *
139 * @returns
140 *
141 * @remarks
142 *
143 *
144 *******************************************************************************
145 */
ih264_dpb_mgr_sort_short_term_fields_by_frame_num(dpb_mgr_t * ps_dpb_mgr,WORD32 curr_frame_num,WORD32 first_field_type,WORD32 max_frame_num)146 WORD32 ih264_dpb_mgr_sort_short_term_fields_by_frame_num(dpb_mgr_t *ps_dpb_mgr,
147                                                          WORD32 curr_frame_num,
148                                                          WORD32 first_field_type,
149                                                          WORD32 max_frame_num)
150 {
151     dpb_info_t *ps_dpb_node1 = ps_dpb_mgr->ps_dpb_short_term_head;
152     dpb_info_t *ps_dpb_node2;
153     WORD32 frame_num_node1;
154     WORD32 frame_num_node2;
155     pic_buf_t *ps_pic_buf;
156 
157     if(ps_dpb_node1 == NULL)
158         return -1;
159 
160     for (; ps_dpb_node1 != NULL; ps_dpb_node1 = ps_dpb_node1->ps_prev_dpb)
161     {
162         for (ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb; ps_dpb_node2 != NULL; ps_dpb_node2 = ps_dpb_node2->ps_prev_dpb)
163         {
164             frame_num_node1 = ps_dpb_node1->ps_pic_buf->i4_frame_num;
165             frame_num_node2 = ps_dpb_node2->ps_pic_buf->i4_frame_num;
166 
167             if(frame_num_node1 > curr_frame_num)
168                 frame_num_node1 = frame_num_node1 - max_frame_num;
169             if(frame_num_node2 > curr_frame_num)
170                 frame_num_node2 = frame_num_node2 - max_frame_num;
171 
172             if(frame_num_node1 < frame_num_node2)
173             {
174                 ps_pic_buf = ps_dpb_node1->ps_pic_buf;
175                 ps_dpb_node1->ps_pic_buf = ps_dpb_node2->ps_pic_buf;
176                 ps_dpb_node2->ps_pic_buf = ps_pic_buf;
177             }
178         }
179     }
180 
181     /**
182      * For frames and complementary field pairs,
183      * ensure first_field_type appears first in the list
184      */
185     ps_dpb_node1 = ps_dpb_mgr->ps_dpb_short_term_head;
186     ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb;
187     while(ps_dpb_node2 != NULL)
188     {
189         pic_buf_t *ps_pic_node1 = ps_dpb_node1->ps_pic_buf;
190         pic_buf_t *ps_pic_node2 = ps_dpb_node2->ps_pic_buf;
191         frame_num_node1 = ps_pic_node1->i4_frame_num;
192         frame_num_node2 = ps_pic_node2->i4_frame_num;
193         if(frame_num_node1 == frame_num_node2)
194         {
195             ASSERT(ps_pic_node1->i1_field_type != ps_pic_node2->i1_field_type);
196             if(ps_pic_node1->i1_field_type != first_field_type)
197             {
198                 ps_dpb_node1->ps_pic_buf = ps_pic_node2;
199                 ps_dpb_node2->ps_pic_buf = ps_pic_node1;
200             }
201         }
202         ps_dpb_node1 = ps_dpb_node2;
203         ps_dpb_node2 = ps_dpb_node2->ps_prev_dpb;
204     }
205     return 0;
206 }
207 
208 /**
209 *******************************************************************************
210 *
211 * @brief
212 *  Function to sort sort term pics by poc for list 0.
213 *
214 * @par Description:
215 *  Orders all the pocs less than current poc in the descending order.
216 *  Then orders all the pocs greater than current poc in the ascending order.
217 *
218 * @param[in] ps_dpb_mgr
219 *  Pointer to the DPB manager structure
220 *
221 * @param[in] curr_poc
222 *  Poc of the current pic
223 *
224 * @param[in] first_field_type
225 *  For complementary fields, required first field
226 *
227 * @returns
228 *
229 * @remarks
230 *
231 *******************************************************************************
232 */
ih264_dpb_mgr_sort_short_term_fields_by_poc_l0(dpb_mgr_t * ps_dpb_mgr,WORD32 curr_poc,WORD32 first_field_type)233 WORD32 ih264_dpb_mgr_sort_short_term_fields_by_poc_l0(dpb_mgr_t *ps_dpb_mgr,
234                                                       WORD32 curr_poc,
235                                                       WORD32 first_field_type)
236 {
237     dpb_info_t *ps_dpb_node1 = ps_dpb_mgr->ps_dpb_short_term_head;
238     dpb_info_t *ps_dpb_node2;
239     WORD32 poc_node1;
240     WORD32 poc_node2;
241     WORD32 frame_num_node1;
242     WORD32 frame_num_node2;
243     pic_buf_t *ps_pic_buf;
244 
245     if(ps_dpb_node1 == NULL)
246         return -1;
247 
248     /**
249      * Sort the fields by poc.
250      * All POCs less than current poc are first placed in the descending order.
251      * Then all POCs greater than current poc are placed in the ascending order.
252      */
253     for (; ps_dpb_node1 != NULL; ps_dpb_node1 = ps_dpb_node1->ps_prev_dpb)
254     {
255         for (ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb; ps_dpb_node2 != NULL; ps_dpb_node2 = ps_dpb_node2->ps_prev_dpb)
256         {
257             poc_node1 = ps_dpb_node1->ps_pic_buf->i4_abs_poc;
258             poc_node2 = ps_dpb_node2->ps_pic_buf->i4_abs_poc;
259             ASSERT(poc_node1 != curr_poc);
260             ASSERT(poc_node2 != curr_poc);
261             if(((poc_node1 < curr_poc) && (poc_node2 > curr_poc)) ||
262                     ((poc_node1 < curr_poc) && (poc_node2 < curr_poc) && (poc_node1 > poc_node2)) ||
263                     ((poc_node1 > curr_poc) && (poc_node2 > curr_poc) && (poc_node1 < poc_node2)))
264                     continue;
265 
266             ps_pic_buf = ps_dpb_node1->ps_pic_buf;
267             ps_dpb_node1->ps_pic_buf = ps_dpb_node2->ps_pic_buf;
268             ps_dpb_node2->ps_pic_buf = ps_pic_buf;
269         }
270     }
271 
272     ps_dpb_node1 = ps_dpb_mgr->ps_dpb_short_term_head;
273     ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb;
274     while(ps_dpb_node2 != NULL)
275     {
276         pic_buf_t *ps_pic_node1 = ps_dpb_node1->ps_pic_buf;
277         pic_buf_t *ps_pic_node2 = ps_dpb_node2->ps_pic_buf;
278         frame_num_node1 = ps_pic_node1->i4_frame_num;
279         frame_num_node2 = ps_pic_node2->i4_frame_num;
280         if(frame_num_node1 == frame_num_node2)
281         {
282             ASSERT(ps_pic_node1->i1_field_type != ps_pic_node2->i1_field_type);
283             if(ps_pic_node1->i1_field_type != first_field_type)
284             {
285                 ps_dpb_node1->ps_pic_buf = ps_pic_node2;
286                 ps_dpb_node2->ps_pic_buf = ps_pic_node1;
287             }
288         }
289         ps_dpb_node1 = ps_dpb_node2;
290         ps_dpb_node2 = ps_dpb_node2->ps_prev_dpb;
291     }
292     return 0;
293 }
294 
295 /**
296 *******************************************************************************
297 *
298 * @brief
299 *  Function to sort sort term pics by poc for list 1.
300 *
301 * @par Description:
302 *  Orders all the pocs greater than current poc in the ascending order.
303 *  Then rrders all the pocs less than current poc in the descending order.
304 *
305 * @param[in] ps_dpb_mgr
306 *  Pointer to the DPB manager structure
307 *
308 * @param[in] curr_poc
309 *  Poc of the current pic
310 *
311 * @param[in] first_field_type
312 *  For complementary fields, required first field
313 *
314 * @returns
315 *
316 * @remarks
317 *
318 *
319 *******************************************************************************
320 */
ih264_dpb_mgr_sort_short_term_fields_by_poc_l1(dpb_mgr_t * ps_dpb_mgr,WORD32 curr_poc,WORD32 first_field_type)321 WORD32 ih264_dpb_mgr_sort_short_term_fields_by_poc_l1(dpb_mgr_t *ps_dpb_mgr,
322                                                       WORD32 curr_poc,
323                                                       WORD32 first_field_type)
324 {
325     dpb_info_t *ps_dpb_node1 = ps_dpb_mgr->ps_dpb_short_term_head;
326     dpb_info_t *ps_dpb_node2;
327     WORD32 poc_node1;
328     WORD32 poc_node2;
329     WORD32 frame_num_node1;
330     WORD32 frame_num_node2;
331     pic_buf_t *ps_pic_buf;
332 
333     if(ps_dpb_node1 == NULL)
334         return -1;
335 
336     /**
337      * Sort the fields by poc.
338      * All POCs greater than current poc are first placed in the ascending order.
339      * Then all POCs less than current poc are placed in the decending order.
340      */
341     for (; ps_dpb_node1 != NULL; ps_dpb_node1 = ps_dpb_node1->ps_prev_dpb)
342     {
343         for (ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb; ps_dpb_node2 != NULL; ps_dpb_node2 = ps_dpb_node2->ps_prev_dpb)
344         {
345             poc_node1 = ps_dpb_node1->ps_pic_buf->i4_abs_poc;
346             poc_node2 = ps_dpb_node2->ps_pic_buf->i4_abs_poc;
347             ASSERT(poc_node1 != curr_poc);
348             ASSERT(poc_node2 != curr_poc);
349             if(((poc_node1 > curr_poc) && (poc_node2 < curr_poc)) ||
350                     ((poc_node1 < curr_poc) && (poc_node2 < curr_poc) && (poc_node1 > poc_node2)) ||
351                     ((poc_node1 > curr_poc) && (poc_node2 > curr_poc) && (poc_node1 < poc_node2)))
352                     continue;
353 
354             ps_pic_buf = ps_dpb_node1->ps_pic_buf;
355             ps_dpb_node1->ps_pic_buf = ps_dpb_node2->ps_pic_buf;
356             ps_dpb_node2->ps_pic_buf = ps_pic_buf;
357         }
358     }
359 
360     ps_dpb_node1 = ps_dpb_mgr->ps_dpb_short_term_head;
361     ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb;
362     while(ps_dpb_node2 != NULL)
363     {
364         pic_buf_t *ps_pic_node1 = ps_dpb_node1->ps_pic_buf;
365         pic_buf_t *ps_pic_node2 = ps_dpb_node2->ps_pic_buf;
366         frame_num_node1 = ps_pic_node1->i4_frame_num;
367         frame_num_node2 = ps_pic_node2->i4_frame_num;
368         if(frame_num_node1 == frame_num_node2)
369         {
370             ASSERT(ps_pic_node1->i1_field_type != ps_pic_node2->i1_field_type);
371             if(ps_pic_node1->i1_field_type != first_field_type)
372             {
373                 ps_dpb_node1->ps_pic_buf = ps_pic_node2;
374                 ps_dpb_node2->ps_pic_buf = ps_pic_node1;
375             }
376         }
377         ps_dpb_node1 = ps_dpb_node2;
378         ps_dpb_node2 = ps_dpb_node2->ps_prev_dpb;
379     }
380     return 0;
381 }
382 
383 /**
384 *******************************************************************************
385 *
386 * @brief
387 *  Function to sort long term pics by long term frame idx.
388 *
389 * @par Description:
390 *  Sorts long term fields by long term frame idx. For 2 fields
391 *  having same frame_num, orders them based on requested first field type.
392 *
393 * @param[in] ps_dpb_mgr
394 *  Pointer to the DPB manager structure
395 *
396 * @param[in] first_field_type
397 *  For complementary fields, required first field
398 *
399 * @returns
400 *
401 * @remarks
402 *
403 *******************************************************************************
404 */
ih264_dpb_mgr_sort_long_term_fields_by_frame_idx(dpb_mgr_t * ps_dpb_mgr,WORD32 first_field_type)405 WORD32 ih264_dpb_mgr_sort_long_term_fields_by_frame_idx(dpb_mgr_t *ps_dpb_mgr,
406                                                         WORD32 first_field_type)
407 {
408     dpb_info_t *ps_dpb_node1 = ps_dpb_mgr->ps_dpb_long_term_head;
409     dpb_info_t *ps_dpb_node2;
410     WORD32 frame_idx_node1;
411     WORD32 frame_idx_node2;
412     pic_buf_t *ps_pic_buf;
413 
414     if(ps_dpb_node1 == NULL)
415         return -1;
416 
417     /* Sort the fields by frame idx */
418     for (; ps_dpb_node1 != NULL; ps_dpb_node1 = ps_dpb_node1->ps_prev_dpb)
419     {
420         for (ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb; ps_dpb_node2 != NULL; ps_dpb_node2 = ps_dpb_node2->ps_prev_dpb)
421         {
422             frame_idx_node1 = ps_dpb_node1->ps_pic_buf->i4_long_term_frame_idx;
423             frame_idx_node2 = ps_dpb_node2->ps_pic_buf->i4_long_term_frame_idx;
424 
425             if(frame_idx_node1 > frame_idx_node2)
426             {
427                 ps_pic_buf = ps_dpb_node1->ps_pic_buf;
428                 ps_dpb_node1->ps_pic_buf = ps_dpb_node2->ps_pic_buf;
429                 ps_dpb_node2->ps_pic_buf = ps_pic_buf;
430             }
431         }
432     }
433 
434     /**
435      * For frames and complementary field pairs,
436      * ensure first_field_type appears first in the list
437      */
438     ps_dpb_node1 = ps_dpb_mgr->ps_dpb_long_term_head;
439     ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb;
440     while(ps_dpb_node2 != NULL)
441     {
442         pic_buf_t *ps_pic_node1 = ps_dpb_node1->ps_pic_buf;
443         pic_buf_t *ps_pic_node2 = ps_dpb_node2->ps_pic_buf;
444         frame_idx_node1 = ps_pic_node1->i4_long_term_frame_idx;
445         frame_idx_node2 = ps_pic_node2->i4_long_term_frame_idx;
446         if(frame_idx_node1 == frame_idx_node2)
447         {
448             ASSERT(ps_pic_node1->i1_field_type != ps_pic_node2->i1_field_type);
449             if(ps_pic_node1->i1_field_type != first_field_type)
450             {
451                 ps_dpb_node1->ps_pic_buf = ps_pic_node2;
452                 ps_dpb_node2->ps_pic_buf = ps_pic_node1;
453             }
454         }
455         ps_dpb_node1 = ps_dpb_node2;
456         ps_dpb_node2 = ps_dpb_node2->ps_prev_dpb;
457     }
458     return 0;
459 }
460 
461 /**
462 *******************************************************************************
463 *
464 * @brief
465 *  Function to alternate fields.
466 *
467 * @par Description:
468 *  In the ordered list of fields, alternate fields starting with
469 *  first_field_type
470 *
471 * @param[in] ps_dpb_mgr
472 *  Pointer to the DPB manager structure
473 *
474 * @param[in] reference_type
475 *  This is used to select between short-term and long-term linked list.
476 *
477 * @param[in] first_field_type
478 *  For complementary fields, required first field
479 *
480 * @returns
481 *
482 * @remarks
483 *
484 *******************************************************************************
485 */
ih264_dpb_mgr_alternate_ref_fields(dpb_mgr_t * ps_dpb_mgr,WORD32 reference_type,WORD32 first_field_type)486 WORD32 ih264_dpb_mgr_alternate_ref_fields(dpb_mgr_t *ps_dpb_mgr,
487                                           WORD32 reference_type,
488                                           WORD32 first_field_type)
489 {
490     dpb_info_t s_dpb_head;
491     dpb_info_t *ps_dpb_head;
492     dpb_info_t *ps_dpb_node1;
493     dpb_info_t *ps_dpb_node2;
494     dpb_info_t *ps_dpb_node3;
495     dpb_info_t *ps_dpb_node4;
496     WORD32 expected_field;
497 
498     expected_field = first_field_type;
499 
500     ps_dpb_head = &s_dpb_head;
501 
502     ps_dpb_head->ps_prev_dpb = (reference_type == SHORT_TERM_REF) ?
503             ps_dpb_mgr->ps_dpb_short_term_head:
504             ps_dpb_mgr->ps_dpb_long_term_head;
505 
506     ps_dpb_node1 = ps_dpb_head;
507     ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb;
508     while(ps_dpb_node2 != NULL)
509     {
510         pic_buf_t *ps_pic_node2 = ps_dpb_node2->ps_pic_buf;
511         if(ps_pic_node2->i1_field_type != expected_field)
512         {
513             /*
514              * If it is not expected field, loop over the node till
515              * the expected field.
516              */
517             ps_dpb_node3 = ps_dpb_node2;
518             ps_dpb_node4 = ps_dpb_node2->ps_prev_dpb;
519             while((ps_dpb_node4 != NULL) &&
520                     (ps_dpb_node4->ps_pic_buf->i1_field_type != expected_field))
521             {
522                 ps_dpb_node3 = ps_dpb_node4;
523                 ps_dpb_node4 = ps_dpb_node4->ps_prev_dpb;
524             }
525             if(ps_dpb_node4 != NULL)
526             {
527                 ps_dpb_node1->ps_prev_dpb = ps_dpb_node4;
528                 ps_dpb_node3->ps_prev_dpb = ps_dpb_node4->ps_prev_dpb;
529                 ps_dpb_node4->ps_prev_dpb = ps_dpb_node2;
530             }
531             else
532             {
533                 /* node4 null means we have reached the end */
534                 break;
535             }
536         }
537         ps_dpb_node1 = ps_dpb_node1->ps_prev_dpb;
538         ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb;
539         expected_field = (ps_dpb_node1->ps_pic_buf->i1_field_type == TOP_FIELD)?
540                             BOTTOM_FIELD:TOP_FIELD;
541     }
542 
543     if(reference_type == SHORT_TERM_REF)
544     {
545         ps_dpb_mgr->ps_dpb_short_term_head = ps_dpb_head->ps_prev_dpb;
546     }
547     else
548     {
549         ps_dpb_mgr->ps_dpb_long_term_head = ps_dpb_head->ps_prev_dpb;
550     }
551 
552     return 0;
553 }
554 
555 /**
556 *******************************************************************************
557 *
558 * @brief
559 *  Add a ref field to short-term or long-term linked list.
560 *
561 * @par Description:
562 *  This function adds a ref field to either short-term or long-term linked
563 *  list. It picks up memory for the link from the array of dpb_info in
564 *  dpb_mgr. The field is added to the beginning of the linked list and the
565 *  head is set the the field.
566 *
567 * @param[in] ps_dpb_mgr
568 *  Pointer to the DPB manager structure
569 *
570 * @param[in] ps_pic_buf
571 *  Pic buf structure for the field being added.
572 *
573 * @param[in] reference_type
574 *  This is used to select between short-term and long-term linked list.
575 *
576 * @param[in] frame_num
577 *  frame_num for the field.
578 *
579 * @param[in] long_term_frame_idx
580 *  If the ref being added is long-term, long_term_frame_idx of the field.
581 *  Otherwise invalid.
582 *
583 * @returns
584 *
585 * @remarks
586 *
587 *******************************************************************************
588 */
ih264_dpb_mgr_insert_ref_field(dpb_mgr_t * ps_dpb_mgr,pic_buf_t * ps_pic_buf,WORD32 reference_type,UWORD32 frame_num,WORD32 long_term_frame_idx)589 WORD32 ih264_dpb_mgr_insert_ref_field(dpb_mgr_t *ps_dpb_mgr,
590                                     pic_buf_t *ps_pic_buf,
591                                     WORD32 reference_type,
592                                     UWORD32 frame_num,
593                                     WORD32 long_term_frame_idx)
594 {
595     WORD32 i;
596     dpb_info_t *ps_dpb_info;
597     dpb_info_t *ps_dpb_head;
598 
599     ps_dpb_info = ps_dpb_mgr->as_dpb_info;
600 
601     /* Return error if buffer is already present in the DPB */
602     for(i = 0; i < MAX_DPB_BUFS; i++)
603     {
604         if( (ps_dpb_info[i].ps_pic_buf == ps_pic_buf)
605                         && (ps_dpb_info[i].ps_pic_buf->i4_used_as_ref == reference_type) )
606         {
607             return (-1);
608         }
609     }
610 
611     /* Find an unused DPB location */
612     for(i = 0; i < MAX_DPB_BUFS; i++)
613     {
614         if(NULL == ps_dpb_info[i].ps_pic_buf)
615         {
616             break;
617         }
618     }
619     if(i == MAX_DPB_BUFS)
620     {
621         return (-1);
622     }
623 
624     ps_dpb_head = (reference_type == SHORT_TERM_REF)
625                     ?ps_dpb_mgr->ps_dpb_short_term_head
626                     :ps_dpb_mgr->ps_dpb_long_term_head;
627 
628     if(reference_type == SHORT_TERM_REF)
629         long_term_frame_idx = -1;
630 
631     /* Create DPB info */
632     ps_dpb_info[i].ps_pic_buf = ps_pic_buf;
633     ps_dpb_info[i].ps_prev_dpb = ps_dpb_head;
634     ps_dpb_info[i].ps_pic_buf->i4_used_as_ref = reference_type;
635     ps_dpb_info[i].ps_pic_buf->i4_frame_num = frame_num;
636     ps_dpb_info[i].ps_pic_buf->i4_long_term_frame_idx = long_term_frame_idx;
637 
638     /* update the head node of linked list to point to the current picture */
639     if(reference_type == SHORT_TERM_REF)
640     {
641         ps_dpb_mgr->ps_dpb_short_term_head = ps_dpb_info + i;
642 
643         /* Increment Short term buffer count */
644         ps_dpb_mgr->u1_num_short_term_ref_bufs++;
645 
646     }
647     else
648     {
649         ps_dpb_mgr->ps_dpb_long_term_head = ps_dpb_info + i;
650 
651         /* Increment Long term buffer count */
652         ps_dpb_mgr->u1_num_long_term_ref_bufs++;
653     }
654 
655     return 0;
656 }
657 
658 /**
659 *******************************************************************************
660 *
661 * @brief
662 *  Add a ref frame to short-term or long-term linked list.
663 *
664 * @par Description:
665 *  This function adds a ref frame to either short-term or long-term linked
666 *  list. Internally it calls add ref field twice to add top and bottom field.
667 *
668 * @param[in] ps_dpb_mgr
669 *  Pointer to the DPB manager structure
670 *
671 * @param[in] ps_pic_buf
672 *  Pic buf structure for the field being added.
673 *
674 * @param[in] reference_type
675 *  This is used to select between short-term and long-term linked list.
676 *
677 * @param[in] frame_num
678 *  frame_num for the field.
679 *
680 * @param[in] long_term_frame_idx
681 *  If the ref being added is long-term, long_term_frame_idx of the field.
682 *  Otherwise invalid.
683 *
684 * @returns
685 *
686 * @remarks
687 *
688 *******************************************************************************
689 */
ih264_dpb_mgr_insert_ref_frame(dpb_mgr_t * ps_dpb_mgr,pic_buf_t * ps_pic_buf,WORD32 reference_type,UWORD32 frame_num,WORD32 long_term_frame_idx)690 WORD32 ih264_dpb_mgr_insert_ref_frame(dpb_mgr_t *ps_dpb_mgr,
691                                       pic_buf_t *ps_pic_buf,
692                                       WORD32 reference_type,
693                                       UWORD32 frame_num,
694                                       WORD32 long_term_frame_idx)
695 {
696     WORD32 buf_id;
697     pic_buf_t *ps_pic_top;
698     pic_buf_t *ps_pic_bottom;
699     WORD32 ret;
700 
701     /*
702      * For a frame, since the ps_pic_buf passed to this function is that of top field
703      * obtain bottom field using buf_id.
704      */
705     ps_pic_top = ps_pic_buf;
706     buf_id = ps_pic_top->i4_buf_id;
707     ps_pic_bottom = &ps_dpb_mgr->as_bottom_field_pics[buf_id];
708 
709     /* Insert top field */
710     ret = ih264_dpb_mgr_insert_ref_field(ps_dpb_mgr,
711                                        ps_pic_top,
712                                        reference_type,
713                                        frame_num,
714                                        long_term_frame_idx);
715 
716     if(ret != 0)
717         return ret;
718 
719     /* Insert bottom field */
720     ret = ih264_dpb_mgr_insert_ref_field(ps_dpb_mgr,
721                                        ps_pic_bottom,
722                                        reference_type,
723                                        frame_num,
724                                        long_term_frame_idx);
725 
726     if(ret != 0)
727         return ret;
728 
729     return ret;
730 }
731 
732 /**
733 *******************************************************************************
734 *
735 * @brief
736 *  Returns the number of ref frames in both the linked list.
737 *
738 * @par Description:
739 *  Returns the count of number of frames, number of complementary field pairs
740 *  and number of unpaired fields.
741 *
742 * @param[in] ps_dpb_mgr
743 *  Pointer to the DPB manager structure
744 *
745 * @param[in] curr_frame_num
746 *  frame_num for the field.
747 *
748 * @param[in] max_frame_num
749 *  Maximum frame_num allowed
750 *
751 * @returns
752 *
753 * @remarks
754 *
755 *******************************************************************************
756 */
ih264_dpb_mgr_count_ref_frames(dpb_mgr_t * ps_dpb_mgr,WORD32 curr_frame_num,WORD32 max_frame_num)757 WORD32 ih264_dpb_mgr_count_ref_frames(dpb_mgr_t *ps_dpb_mgr,
758                                       WORD32 curr_frame_num,
759                                       WORD32 max_frame_num)
760 {
761     WORD32 numShortTerm = 0;
762     WORD32 numLongTerm = 0;
763     dpb_info_t *ps_dpb_node;
764     WORD32 frame_num;
765     WORD32 prev_frame_num;
766 
767     /*
768      * Compute the number of short-term frames/complementary field pairs/
769      * unpaired fields
770      */
771     if(ps_dpb_mgr->ps_dpb_short_term_head != NULL)
772     {
773         /* Sort the short-term list by frame_num */
774         ih264_dpb_mgr_sort_short_term_fields_by_frame_num(ps_dpb_mgr,
775                                                         curr_frame_num,
776                                                         TOP_FIELD,
777                                                         max_frame_num);
778 
779         ps_dpb_node = ps_dpb_mgr->ps_dpb_short_term_head;
780         if(ps_dpb_node != NULL)
781         {
782             numShortTerm++;
783             prev_frame_num = ps_dpb_node->ps_pic_buf->i4_frame_num;
784             ps_dpb_node = ps_dpb_node->ps_prev_dpb;
785         }
786 
787         while(ps_dpb_node != NULL)
788         {
789             frame_num = ps_dpb_node->ps_pic_buf->i4_frame_num;
790             if(frame_num != prev_frame_num)
791                 numShortTerm++;
792             prev_frame_num = ps_dpb_node->ps_pic_buf->i4_frame_num;
793             ps_dpb_node = ps_dpb_node->ps_prev_dpb;
794         }
795     }
796 
797     /*
798      * Compute the number of long-term frames/complementary field pairs/
799      * unpaired fields
800      */
801     if(ps_dpb_mgr->ps_dpb_long_term_head != NULL)
802     {
803         ih264_dpb_mgr_sort_long_term_fields_by_frame_idx(ps_dpb_mgr,
804                                                         TOP_FIELD);
805 
806         ps_dpb_node = ps_dpb_mgr->ps_dpb_long_term_head;
807         if(ps_dpb_node != NULL)
808         {
809             numLongTerm++;
810             prev_frame_num = ps_dpb_node->ps_pic_buf->i4_frame_num;
811             ps_dpb_node = ps_dpb_node->ps_prev_dpb;
812         }
813 
814         while(ps_dpb_node != NULL)
815         {
816             frame_num = ps_dpb_node->ps_pic_buf->i4_frame_num;
817             if(frame_num != prev_frame_num)
818                 numLongTerm++;
819             prev_frame_num = ps_dpb_node->ps_pic_buf->i4_frame_num;
820             ps_dpb_node = ps_dpb_node->ps_prev_dpb;
821         }
822     }
823     return (numShortTerm + numLongTerm);
824 }
825 
826 /**
827 *******************************************************************************
828 *
829 * @brief
830 *  Deletes the ref frame at the end of the linked list.
831 *
832 * @par Description:
833 *  Deletes the ref frame at the end of the linked list. For unpaired fields,
834 *  it deletes just the last node. For frame or complementary field pair, it
835 *  deletes the last two nodes.
836 *
837 * @param[in] ps_dpb_mgr
838 *  Pointer to the DPB manager structure
839 *
840 * @param[in] reference_type
841 *  This is used to select between short-term and long-term linked list.
842 *
843 * @returns
844 *
845 * @remarks
846 *
847 *******************************************************************************
848 */
ih264_dpb_mgr_delete_ref_frame(dpb_mgr_t * ps_dpb_mgr,WORD32 reference_type)849 WORD32 ih264_dpb_mgr_delete_ref_frame(dpb_mgr_t *ps_dpb_mgr,
850                                       WORD32 reference_type)
851 {
852     dpb_info_t *ps_dpb_node1;
853     dpb_info_t *ps_dpb_node2;
854     dpb_info_t *ps_dpb_node3;
855 
856     /*
857      * Assumption: The nodes sorted for frame num.
858      */
859     /* Select bw short-term and long-term list. */
860     ps_dpb_node1 = (reference_type == SHORT_TERM_REF)
861                     ?ps_dpb_mgr->ps_dpb_short_term_head
862                     :ps_dpb_mgr->ps_dpb_long_term_head;
863     /* If null, no entries in the list. Hence return. */
864     if(ps_dpb_node1 == NULL)
865         return 0;
866 
867     /* If only one node in the list, set as unsed for refer and return. */
868     if(ps_dpb_node1->ps_prev_dpb == NULL)
869     {
870         /* Set the picture as unused for reference */
871         ps_dpb_node1->ps_pic_buf->i4_used_as_ref = UNUSED_FOR_REF;
872         ps_dpb_node1->ps_pic_buf = NULL;
873 
874         if(reference_type == SHORT_TERM_REF)
875         {
876             ps_dpb_mgr->ps_dpb_short_term_head = NULL;
877 
878             /* Increment Short term buffer count */
879             ps_dpb_mgr->u1_num_short_term_ref_bufs = 0;
880 
881         }
882         else
883         {
884             ps_dpb_mgr->ps_dpb_long_term_head = NULL;
885 
886             /* Increment Long term buffer count */
887             ps_dpb_mgr->u1_num_long_term_ref_bufs = 0;
888 
889         }
890         return 0;
891     }
892 
893     /**
894      * If there are only 2 nodes in the list, set second node as unused for reference.
895      * If the frame_num of second node and first node is same, set first node also as
896      * unused for reference and set the corresponding head to NULL.
897      */
898     ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb;
899     if(ps_dpb_node2->ps_prev_dpb == NULL)
900     {
901         /* Set the picture as unused for reference */
902         if(ps_dpb_node2->ps_pic_buf->i4_frame_num == ps_dpb_node1->ps_pic_buf->i4_frame_num)
903         {
904             /* Set the picture as unused for reference */
905             ps_dpb_node1->ps_pic_buf->i4_used_as_ref = UNUSED_FOR_REF;
906             ps_dpb_node1->ps_pic_buf = NULL;
907             if(reference_type == SHORT_TERM_REF)
908             {
909                 ps_dpb_mgr->ps_dpb_short_term_head = NULL;
910 
911                 /* Increment Short term buffer count */
912                 ps_dpb_mgr->u1_num_short_term_ref_bufs = 0;
913 
914             }
915             else
916             {
917                 ps_dpb_mgr->ps_dpb_long_term_head = NULL;
918 
919                 /* Increment Long term buffer count */
920                 ps_dpb_mgr->u1_num_long_term_ref_bufs = 0;
921 
922             }
923 
924         }
925         ps_dpb_node2->ps_pic_buf->i4_used_as_ref = UNUSED_FOR_REF;
926         ps_dpb_node2->ps_pic_buf = NULL;
927         ps_dpb_node1->ps_prev_dpb = NULL;
928         return 0;
929     }
930     /*
931      * If there are more than 2 nodes, run a loop to get the last 3 nodes.
932      */
933     ps_dpb_node3 = ps_dpb_node2->ps_prev_dpb;
934     while(ps_dpb_node3->ps_prev_dpb != NULL)
935     {
936         ps_dpb_node1 = ps_dpb_node2;
937         ps_dpb_node2 = ps_dpb_node3;
938         ps_dpb_node3 = ps_dpb_node3->ps_prev_dpb;
939     }
940     /*
941      * If node 2 and node 3 frame_nums are same, set node 2 also as unsed for
942      * reference and del reference from node1.
943      */
944     if(ps_dpb_node2->ps_pic_buf->i4_frame_num == ps_dpb_node3->ps_pic_buf->i4_frame_num)
945     {
946         ps_dpb_node2->ps_pic_buf->i4_used_as_ref = UNUSED_FOR_REF;
947         ps_dpb_node2->ps_pic_buf = NULL;
948         ps_dpb_node1->ps_prev_dpb = NULL;
949 
950     }
951     /* Set the third node as unused for reference */
952     ps_dpb_node3->ps_pic_buf->i4_used_as_ref = UNUSED_FOR_REF;
953     ps_dpb_node3->ps_pic_buf = NULL;
954     ps_dpb_node2->ps_prev_dpb = NULL;
955 
956     return 0;
957 }
958 
959 /**
960 *******************************************************************************
961 *
962 * @brief
963 *  Delete long-term ref fields above max frame idx.
964 *
965 * @par Description:
966 *  Deletes all the long-term ref fields having idx greater than max_frame_idx
967 *
968 * @param[in] ps_dpb_mgr
969 *  Pointer to the DPB manager structure
970 *
971 * @param[in] max_frame_idx
972 *  Max long-term frame idx allowed.
973 *
974 * @returns
975 *
976 * @remarks
977 *
978 *******************************************************************************
979 */
ih264_dpb_mgr_delete_long_ref_fields_max_frame_idx(dpb_mgr_t * ps_dpb_mgr,WORD32 max_frame_idx)980 WORD32 ih264_dpb_mgr_delete_long_ref_fields_max_frame_idx(dpb_mgr_t *ps_dpb_mgr,
981                                                           WORD32 max_frame_idx)
982 {
983     dpb_info_t *ps_dpb_node1;
984     dpb_info_t *ps_dpb_node2;
985 
986     /*
987      * Loop until there is node which isn't to be deleted is encountered.
988      */
989     while(ps_dpb_mgr->ps_dpb_long_term_head != NULL)
990     {
991         if(ps_dpb_mgr->ps_dpb_long_term_head->ps_pic_buf->i4_long_term_frame_idx
992                         <= max_frame_idx)
993         {
994             break;
995         }
996         ps_dpb_mgr->ps_dpb_long_term_head->ps_pic_buf->i4_used_as_ref = UNUSED_FOR_REF;
997         ps_dpb_mgr->ps_dpb_long_term_head->ps_pic_buf = NULL;
998         ps_dpb_mgr->ps_dpb_long_term_head = ps_dpb_mgr->ps_dpb_long_term_head->ps_prev_dpb;
999     }
1000 
1001     ps_dpb_node1 = ps_dpb_mgr->ps_dpb_long_term_head;
1002     if(ps_dpb_node1 == NULL)
1003         return 0;
1004     /*
1005      * With the node that isn't to be deleted as head, loop until the end.
1006      */
1007     ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb;
1008     while(ps_dpb_node2 != NULL)
1009     {
1010         if(ps_dpb_node2->ps_pic_buf->i4_long_term_frame_idx > max_frame_idx)
1011         {
1012             ps_dpb_node2->ps_pic_buf->i4_used_as_ref = UNUSED_FOR_REF;
1013             ps_dpb_node2->ps_pic_buf = NULL;
1014             ps_dpb_node1->ps_prev_dpb = ps_dpb_node2->ps_prev_dpb;
1015         }
1016         ps_dpb_node1 = ps_dpb_node1->ps_prev_dpb;
1017         if(ps_dpb_node1 == NULL)
1018             break;
1019         ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb;
1020     }
1021     return 0;
1022 }
1023 
1024 /**
1025 *******************************************************************************
1026 *
1027 * @brief
1028 *  Deletes the short-term with least frame_num
1029 *
1030 * @par Description:
1031 *  Deletes the short-term with least frame_num. It sorts the function the
1032 *  short-term linked list by frame-num and the function that deletes the last
1033 *  frame in the linked list.
1034 *
1035 * @param[in] ps_dpb_mgr
1036 *  Pointer to the DPB manager structure
1037 *
1038 * @param[in] curr_frame_num
1039 *  frame_num of the current pic
1040 *
1041 * @param[in] max_frame_num
1042 *  Maximum frame_num allowed
1043 *
1044 * @returns
1045 *
1046 * @remarks
1047 *
1048 *******************************************************************************
1049 */
ih264_dpb_mgr_delete_short_ref_frame(dpb_mgr_t * ps_dpb_mgr,WORD32 curr_frame_num,WORD32 max_frame_num)1050 WORD32 ih264_dpb_mgr_delete_short_ref_frame(dpb_mgr_t *ps_dpb_mgr,
1051                                             WORD32 curr_frame_num,
1052                                             WORD32 max_frame_num)
1053 {
1054     WORD32 ret;
1055 
1056     /* Sort the short-term list by frame_num */
1057     ret = ih264_dpb_mgr_sort_short_term_fields_by_frame_num(ps_dpb_mgr,
1058                                                           curr_frame_num,
1059                                                           TOP_FIELD,
1060                                                           max_frame_num);
1061 
1062     /* Delete the last reference frame or field */
1063     ret = ih264_dpb_mgr_delete_ref_frame(ps_dpb_mgr,SHORT_TERM_REF);
1064 
1065     if(ret != 0)
1066     {
1067         ASSERT(0);
1068     }
1069 
1070     return ret;
1071 }
1072 
1073 /**
1074 *******************************************************************************
1075 *
1076 * @brief
1077 *  Deletes all the ref frames.
1078 *
1079 * @par Description:
1080 *  Deletes all of the ref frames/fields in the short-term and long-term linked
1081 *  list.
1082 *
1083 * @param[in] ps_dpb_mgr
1084 *  Pointer to the DPB manager structure
1085 *
1086 * @returns
1087 *
1088 * @remarks
1089 *
1090 *******************************************************************************
1091 */
ih264_dpb_mgr_delete_all_ref_frames(dpb_mgr_t * ps_dpb_mgr)1092 WORD32 ih264_dpb_mgr_delete_all_ref_frames(dpb_mgr_t *ps_dpb_mgr)
1093 {
1094     /* Loop over short-term linked list. */
1095     while(ps_dpb_mgr->ps_dpb_short_term_head != NULL)
1096     {
1097         ih264_dpb_mgr_delete_ref_frame(ps_dpb_mgr,SHORT_TERM_REF);
1098     }
1099 
1100     /* Loop over long-term linked list. */
1101     while(ps_dpb_mgr->ps_dpb_long_term_head != NULL)
1102     {
1103         ih264_dpb_mgr_delete_ref_frame(ps_dpb_mgr,LONG_TERM_REF);
1104     }
1105     return 0;
1106 }
1107 
1108 /**
1109 *******************************************************************************
1110 *
1111 * @brief
1112 *  deletes all pictures from DPB and reset dpb
1113 *
1114 * @par Description:
1115 *  deletes all pictures from DPB and reset dpb
1116 *
1117 * @param[in] ps_dpb_mgr
1118 *  Pointer to the DPB manager structure
1119 *
1120 * @param[in] ps_buf_mgr
1121 *  Pointer to buffer manager structure
1122 *
1123 * @returns
1124 *
1125 * @remarks
1126 *
1127 *******************************************************************************
1128 */
ih264_dpb_mgr_reset(dpb_mgr_t * ps_dpb_mgr,buf_mgr_t * ps_buf_mgr)1129 void ih264_dpb_mgr_reset(dpb_mgr_t *ps_dpb_mgr, buf_mgr_t *ps_buf_mgr)
1130 {
1131     WORD32 i;
1132     dpb_info_t *ps_dpb_info;
1133 
1134     ASSERT(0);
1135     ps_dpb_info = ps_dpb_mgr->as_dpb_info;
1136     for(i = 0; i < MAX_DPB_BUFS; i++)
1137     {
1138         if(ps_dpb_info[i].ps_pic_buf->i4_used_as_ref)
1139         {
1140             ps_dpb_info[i].ps_pic_buf->i4_used_as_ref = UNUSED_FOR_REF;
1141             ps_dpb_info[i].ps_prev_dpb = NULL;
1142             // Release physical buffer
1143             ih264_buf_mgr_release(ps_buf_mgr, ps_dpb_info[i].ps_pic_buf->i4_buf_id,
1144                                   BUF_MGR_REF);
1145 
1146             ps_dpb_info[i].ps_pic_buf = NULL;
1147         }
1148     }
1149     ps_dpb_mgr->u1_num_short_term_ref_bufs = 0;
1150     ps_dpb_mgr->u1_num_long_term_ref_bufs  = 0;
1151     ps_dpb_mgr->ps_dpb_short_term_head = NULL;
1152     ps_dpb_mgr->ps_dpb_long_term_head  = NULL;
1153 }
1154 
1155 /**
1156 *******************************************************************************
1157 *
1158 * @brief
1159 *  deletes all pictures from DPB
1160 *
1161 * @par Description:
1162 *  Deletes all pictures present in the DPB manager
1163 *
1164 * @param[in] ps_buf_mgr
1165 *  Pointer to buffer manager structure
1166 *
1167 * @param[in] u1_disp_bufs
1168 *  Number of buffers to be deleted
1169 *
1170 * @returns
1171 *
1172 * @remarks
1173 *
1174 *******************************************************************************
1175 */
ih264_dpb_mgr_release_pics(buf_mgr_t * ps_buf_mgr,UWORD8 u1_disp_bufs)1176 void ih264_dpb_mgr_release_pics(buf_mgr_t *ps_buf_mgr, UWORD8 u1_disp_bufs)
1177 {
1178     WORD8 i;
1179     UWORD32 buf_status;
1180 
1181     ASSERT(0);
1182     for(i = 0; i < u1_disp_bufs; i++)
1183     {
1184         buf_status = ih264_buf_mgr_get_status(ps_buf_mgr, i);
1185         if(0 != buf_status)
1186         {
1187             ih264_buf_mgr_release((buf_mgr_t *)ps_buf_mgr, i, BUF_MGR_REF);
1188         }
1189     }
1190 }
1191