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
87void 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 */
138WORD32 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 */
227WORD32 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 */
316WORD32 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 */
400WORD32 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 */
482WORD32 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 */
586WORD32 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 */
688WORD32 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 */
756WORD32 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 */
849WORD32 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 */
982WORD32 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 */
1052WORD32 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 */
1093WORD32 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
1110void 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
1162void 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