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