Coverage Report

Created: 2025-07-09 06:20

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