Coverage Report

Created: 2026-09-04 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libhevc/common/ihevc_dpb_mgr.c
Line
Count
Source
1
/******************************************************************************
2
*
3
* Copyright (C) 2012 Ittiam Systems Pvt Ltd, Bangalore
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
/**
19
 *******************************************************************************
20
 * @file
21
 *  ihevc_dpb_mgr.c
22
 *
23
 * @brief
24
 *  Function definitions used for decoded picture buffer management
25
 *
26
 * @author
27
 *  Srinivas T
28
 *
29
 * @par List of Functions:
30
 *   - ihevc_dpb_mgr_init()
31
 *   - ihevc_dpb_mgr_del_lt()
32
 *   - ihevc_dpb_mgr_insert_lt()
33
 *   - ihevc_dpb_mgr_del_st_or_make_lt()
34
 *   - ihevc_dpb_mgr_insert_st()
35
 *   - ihevc_dpb_mgr_reset()
36
 *   - ihevc_dpb_mgr_release_pics()
37
 *
38
 * @remarks
39
 *  None
40
 *
41
 *******************************************************************************
42
 */
43
44
#include <stdio.h>
45
#include <stdlib.h>
46
47
#include "ihevc_typedefs.h"
48
#include "ihevc_defs.h"
49
#include "ihevc_macros.h"
50
#include "ihevc_structs.h"
51
#include "ihevc_buf_mgr.h"
52
#include "ihevc_dpb_mgr.h"
53
54
/**
55
 *******************************************************************************
56
 *
57
 * @brief
58
 *  DPB manager initializer
59
 *
60
 * @par Description:
61
 *  Initialises the DPB manager structure
62
 *
63
 * @param[in] ps_dpb_mgr
64
 *  Pointer to the DPB manager structure
65
 *
66
 * @returns
67
 *
68
 * @remarks
69
 *
70
 *
71
 *******************************************************************************
72
 */
73
74
void ihevc_dpb_mgr_init(dpb_mgr_t *ps_dpb_mgr)
75
0
{
76
0
    UWORD32 i;
77
0
    dpb_info_t *ps_dpb_info = ps_dpb_mgr->as_dpb_info;
78
0
    for(i = 0; i < MAX_DPB_BUFS; i++)
79
0
    {
80
0
        ps_dpb_info[i].ps_prev_dpb = NULL;
81
0
        ps_dpb_info[i].ps_pic_buf = NULL;
82
83
0
    }
84
85
0
    ps_dpb_mgr->u1_num_ref_bufs = 0;
86
0
    ps_dpb_mgr->ps_dpb_head = NULL;
87
88
0
}
89
90
91
/**
92
 *******************************************************************************
93
 *
94
 * @brief
95
 *  Adds a reference picture into the linked  list
96
 *
97
 * @par Description:
98
 *  Adds the reference buffer with the given buffer id into the DPB manager
99
 *
100
 *
101
 * @param[in] ps_dpb_mgr
102
 *  Pointer to the DPB manager structure
103
 *
104
 * @param[in] ps_picBuf
105
 *  Pointer to the picture buffer
106
 *
107
 * @param[in] buf_id
108
 *  buffer id of the picture buffer
109
 *
110
 * @returns  0 if successful, -1 otherwise
111
 *
112
 * @remarks
113
 *
114
 *
115
 *******************************************************************************
116
 */
117
118
WORD32 ihevc_dpb_mgr_insert_ref(dpb_mgr_t *ps_dpb_mgr,
119
                                pic_buf_t *ps_pic_buf,
120
                                WORD32 buf_id)
121
0
{
122
0
    int i;
123
0
    dpb_info_t *ps_dpb_info;
124
125
0
    ps_dpb_info = ps_dpb_mgr->as_dpb_info;
126
127
    /* Return error if buffer is already present in the DPB */
128
0
    for(i = 0; i < MAX_DPB_BUFS; i++)
129
0
    {
130
0
        if((ps_dpb_info[i].ps_pic_buf == ps_pic_buf)
131
0
                        && (ps_dpb_info[i].ps_pic_buf->u1_used_as_ref))
132
0
        {
133
0
            return (-1);
134
0
        }
135
136
137
0
    }
138
139
    /* Find an unused DPB location */
140
0
    for(i = 0; i < MAX_DPB_BUFS; i++)
141
0
    {
142
0
        if(NULL == ps_dpb_info[i].ps_pic_buf)
143
0
        {
144
0
            break;
145
0
        }
146
0
    }
147
0
    if(i == MAX_DPB_BUFS)
148
0
    {
149
0
        return (-1);
150
0
    }
151
152
    /* Create DPB info */
153
0
    ps_dpb_info[i].ps_pic_buf = ps_pic_buf;
154
0
    ps_dpb_info[i].ps_prev_dpb = ps_dpb_mgr->ps_dpb_head;
155
0
    ps_dpb_info[i].ps_pic_buf->u1_buf_id = buf_id;
156
0
    ps_dpb_info[i].ps_pic_buf->u1_used_as_ref = SHORT_TERM_REF;
157
158
    /* update the head node of linked list to point to the current picture */
159
0
    ps_dpb_mgr->ps_dpb_head = ps_dpb_info + i;
160
161
    /* Increment Short term buffer count */
162
0
    ps_dpb_mgr->u1_num_ref_bufs++;
163
164
0
    return 0;
165
0
}
166
167
/**
168
 *******************************************************************************
169
 *
170
 * @brief
171
 *  Deletes a reference buffer from the dpb manager
172
 *
173
 * @par Description:
174
 *  Delete short term reference with a given POC from the linked
175
 *  list
176
 *
177
 * @param[in] ps_dpb_mgr
178
 *  Pointer to DPB Manager structure
179
 *
180
 * @param[in] ps_buf_mgr
181
 *  Pointer to buffer manager structure
182
 *
183
 * @param[in] u4_abs_poc
184
 *  Node's absolute poc
185
 *
186
 *
187
 * @returns  0 if successful, -1 otherwise
188
 *
189
 * @remarks
190
 *
191
 *
192
 *******************************************************************************
193
 */
194
195
void ihevc_dpb_mgr_del_ref(dpb_mgr_t *ps_dpb_mgr,
196
                           buf_mgr_t *ps_buf_mgr,
197
                           WORD32 i4_abs_poc)
198
0
{
199
0
    int i;
200
0
    dpb_info_t *ps_next_dpb;
201
202
0
    dpb_info_t *ps_unmark_node;
203
0
    UWORD8 u1_del_node;
204
0
    UNUSED(u1_del_node);
205
0
    u1_del_node = 0;
206
207
    /* Find the node with matching absolute POC */
208
0
    ps_next_dpb = ps_dpb_mgr->ps_dpb_head;
209
0
    if(ps_next_dpb->ps_pic_buf->i4_abs_poc == i4_abs_poc)
210
0
    {
211
0
        ps_unmark_node = ps_next_dpb;
212
0
    }
213
0
    else
214
0
    {
215
0
        for(i = 1; i < ps_dpb_mgr->u1_num_ref_bufs; i++)
216
0
        {
217
0
            if(ps_next_dpb->ps_prev_dpb->ps_pic_buf->i4_abs_poc == i4_abs_poc)
218
0
                break;
219
0
            ps_next_dpb = ps_next_dpb->ps_prev_dpb;
220
0
        }
221
222
0
        if(i == ps_dpb_mgr->u1_num_ref_bufs)
223
0
        {
224
0
            return;
225
0
        }
226
0
        else
227
0
            ps_unmark_node = ps_next_dpb->ps_prev_dpb;
228
0
    }
229
230
0
    if(ps_unmark_node == ps_dpb_mgr->ps_dpb_head)
231
0
    {
232
0
        ps_dpb_mgr->ps_dpb_head = ps_unmark_node->ps_prev_dpb;
233
0
    }
234
0
    else
235
0
    {
236
0
        ps_next_dpb->ps_prev_dpb = ps_unmark_node->ps_prev_dpb; //update link
237
0
        ps_unmark_node->ps_prev_dpb = NULL;
238
0
    }
239
0
    ps_dpb_mgr->u1_num_ref_bufs--; //decrement buffer count
240
241
    /* Release the physical buffer */
242
0
    ihevc_buf_mgr_release((buf_mgr_t *)ps_buf_mgr, ps_unmark_node->ps_pic_buf->u1_buf_id,
243
0
                          BUF_MGR_REF);
244
0
    ps_unmark_node->ps_prev_dpb = NULL;
245
0
    ps_unmark_node->ps_pic_buf = NULL;
246
0
}
247
248
249
/**
250
 *******************************************************************************
251
 *
252
 * @brief
253
 *  Gets a buffer with abs_poc closest to the current poc
254
 *
255
 * @par Description:
256
 *  Returns the pointer to the picture buffer whose poc is equal to abs_poc
257
 *
258
 * @param[in] ps_dpb_mgr
259
 *  Pointer to DPB Manager structure
260
 *
261
 * @param[out] ps_pic_buf
262
 *  Pointer to picture buffer
263
264
 * @param[in] abs_poc
265
 *  poc of the buffer to be returned
266
 *
267
 * @returns
268
 *  0 if successful, pic_buf otherwise
269
 * @remarks
270
 *
271
 *
272
 *******************************************************************************
273
 */
274
pic_buf_t* ihevc_dpb_mgr_get_ref_by_nearest_poc(dpb_mgr_t *ps_dpb_mgr, WORD32 cur_abs_poc)
275
0
{
276
0
    WORD32 i;
277
0
    WORD32 min_diff = 0x7FFFFFFF;
278
0
    pic_buf_t *ps_pic_buf = NULL;
279
280
0
    for(i = 0; i < MAX_DPB_BUFS; i++)
281
0
    {
282
0
        if((ps_dpb_mgr->as_dpb_info[i].ps_pic_buf) &&
283
0
                        (ps_dpb_mgr->as_dpb_info[i].ps_pic_buf->u1_used_as_ref != UNUSED_FOR_REF))
284
0
        {
285
0
            WORD32 poc_diff = cur_abs_poc - ps_dpb_mgr->as_dpb_info[i].ps_pic_buf->i4_abs_poc;
286
0
            if((poc_diff > 0) && (poc_diff < min_diff))
287
0
            {
288
0
                min_diff = poc_diff;
289
0
                ps_pic_buf = ps_dpb_mgr->as_dpb_info[i].ps_pic_buf;
290
0
            }
291
0
        }
292
0
    }
293
294
0
    if(NULL == ps_pic_buf)
295
0
    {
296
0
        min_diff = 0x7FFFFFFF;
297
0
        for(i = 0; i < MAX_DPB_BUFS; i++)
298
0
        {
299
0
            if((ps_dpb_mgr->as_dpb_info[i].ps_pic_buf) &&
300
0
                            (ps_dpb_mgr->as_dpb_info[i].ps_pic_buf->u1_used_as_ref != UNUSED_FOR_REF))
301
0
            {
302
0
                WORD32 poc_diff = cur_abs_poc - ps_dpb_mgr->as_dpb_info[i].ps_pic_buf->i4_abs_poc;
303
0
                if(ABS(poc_diff) < min_diff)
304
0
                {
305
0
                    min_diff = ABS(poc_diff);
306
0
                    ps_pic_buf = ps_dpb_mgr->as_dpb_info[i].ps_pic_buf;
307
0
                }
308
0
            }
309
0
        }
310
0
    }
311
312
0
    return ps_pic_buf;
313
0
}
314
315
316
/**
317
 *******************************************************************************
318
 *
319
 * @brief
320
 *  Gets a buffer with abs_poc
321
 *
322
 * @par Description:
323
 *  Returns the pointer to the picture buffer whose poc is equal to abs_poc
324
 *
325
 * @param[in] ps_dpb_mgr
326
 *  Pointer to DPB Manager structure
327
 *
328
 * @param[out] ps_pic_buf
329
 *  Pointer to picture buffer
330
331
 * @param[in] abs_poc
332
 *  poc of the buffer to be returned
333
 *
334
 * @returns
335
 *  0 if successful, pic_buf otherwise
336
 * @remarks
337
 *
338
 *
339
 *******************************************************************************
340
 */
341
pic_buf_t* ihevc_dpb_mgr_get_ref_by_poc(dpb_mgr_t *ps_dpb_mgr, WORD32 abs_poc)
342
0
{
343
0
    UWORD32 i;
344
0
    dpb_info_t *ps_next_ref;
345
0
    pic_buf_t *ps_pic_buf = NULL;
346
347
348
0
    ps_next_ref = ps_dpb_mgr->ps_dpb_head;
349
0
    for(i = 0; i < ps_dpb_mgr->u1_num_ref_bufs; i++)
350
0
    {
351
0
        if(ps_next_ref->ps_pic_buf->i4_abs_poc == abs_poc)
352
0
        {
353
0
            ps_pic_buf = ps_next_ref->ps_pic_buf;
354
0
            break;
355
0
        }
356
357
0
        ps_next_ref = ps_next_ref->ps_prev_dpb;
358
0
    }
359
360
0
    if(i == ps_dpb_mgr->u1_num_ref_bufs)
361
0
    {
362
0
        ps_pic_buf = NULL;
363
0
    }
364
365
0
    return ps_pic_buf;
366
0
}
367
368
/**
369
 *******************************************************************************
370
 *
371
 * @brief
372
 *  Gets a buffer with poc_lsb
373
 *
374
 * @par Description:
375
 *  Returns the pointer to the picture buffer whose poc is equal to poc_lsb
376
 *
377
 * @param[in] ps_dpb_mgr
378
 *  Pointer to DPB Manager structure
379
 *
380
 * @param[out] ps_pic_buf
381
 *  Pointer to picture buffer
382
383
 * @param[in] poc_lsb
384
 *  poc_lsb of the buffer to be returned
385
 *
386
 * @returns
387
 *  0 if successful, pic_buf otherwise
388
 * @remarks
389
 *
390
 *
391
 *******************************************************************************
392
 */
393
394
pic_buf_t* ihevc_dpb_mgr_get_ref_by_poc_lsb(dpb_mgr_t *ps_dpb_mgr, WORD32 poc_lsb)
395
0
{
396
0
    pic_buf_t *ps_pic_buf = NULL;
397
0
    UWORD32 i;
398
0
    dpb_info_t *ps_next_ref;
399
400
0
    ps_next_ref = ps_dpb_mgr->ps_dpb_head;
401
0
    for(i = 0; i < ps_dpb_mgr->u1_num_ref_bufs; i++)
402
0
    {
403
0
        if(ps_next_ref->ps_pic_buf->i4_poc_lsb == poc_lsb)
404
0
        {
405
0
            ps_pic_buf = ps_next_ref->ps_pic_buf;
406
0
            break;
407
0
        }
408
409
0
        ps_next_ref = ps_next_ref->ps_prev_dpb;
410
0
    }
411
412
0
    if(i == ps_dpb_mgr->u1_num_ref_bufs)
413
0
    {
414
0
        ps_pic_buf = NULL;
415
0
    }
416
417
0
    return ps_pic_buf;
418
0
}
419
420
421
/**
422
 *******************************************************************************
423
 *
424
 * @brief
425
 *  Resets the DPB manager
426
 *
427
 * @par Description:
428
 *  Re-initialises the DPB manager structure
429
 *
430
 * @param[in] ps_dpb_mgr
431
 *  Pointer to DPB Manager structure
432
 *
433
 * @param[in] ps_buf_mgr
434
 *  Pointer to buffer manager structure
435
 *
436
 * @returns
437
 *
438
 * @remarks
439
 *
440
 *
441
 *******************************************************************************
442
 */
443
444
void ihevc_dpb_mgr_reset(dpb_mgr_t *ps_dpb_mgr, buf_mgr_t *ps_buf_mgr)
445
0
{
446
0
    int i;
447
0
    dpb_info_t *ps_dpb_info;
448
449
0
    ps_dpb_info = ps_dpb_mgr->as_dpb_info;
450
451
0
    for(i = 0; i < MAX_DPB_BUFS; i++)
452
0
    {
453
0
        if(ps_dpb_info[i].ps_pic_buf->u1_used_as_ref)
454
0
        {
455
0
            ps_dpb_info[i].ps_pic_buf->u1_used_as_ref = UNUSED_FOR_REF;
456
0
            ps_dpb_info[i].ps_prev_dpb = NULL;
457
            //Release physical buffer
458
0
            ihevc_buf_mgr_release(ps_buf_mgr, ps_dpb_info[i].ps_pic_buf->u1_buf_id,
459
0
                                  BUF_MGR_REF);
460
461
0
            ps_dpb_info[i].ps_pic_buf = NULL;
462
0
        }
463
0
    }
464
0
    ps_dpb_mgr->u1_num_ref_bufs = 0;
465
0
    ps_dpb_mgr->ps_dpb_head = NULL;
466
467
0
}
468
469
/**
470
 *******************************************************************************
471
 *
472
 * @brief
473
 *  deletes all pictures from DPB
474
 *
475
 * @par Description:
476
 *  Deletes all pictures present in the DPB manager
477
 *
478
 * @param[in] ps_buf_mgr
479
 *  Pointer to buffer manager structure
480
 *
481
 * @param[in] u1_disp_bufs
482
 *  Number of buffers to be deleted
483
 *
484
 * @returns
485
 *
486
 * @remarks
487
 *
488
 *
489
 *******************************************************************************
490
 */
491
492
void ihevc_dpb_mgr_release_pics(buf_mgr_t *ps_buf_mgr, UWORD8 u1_disp_bufs)
493
0
{
494
0
    WORD8 i;
495
0
    UWORD32 buf_status;
496
497
0
    for(i = 0; i < u1_disp_bufs; i++)
498
0
    {
499
0
        buf_status = ihevc_buf_mgr_get_status(ps_buf_mgr, i);
500
0
        if(0 != buf_status)
501
0
        {
502
0
            ihevc_buf_mgr_release((buf_mgr_t *)ps_buf_mgr, i, BUF_MGR_REF);
503
0
        }
504
0
    }
505
0
}