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