Coverage Report

Created: 2025-11-11 07:01

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_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
2.03k
{
77
2.03k
    UWORD32 i;
78
2.03k
    dpb_info_t *ps_dpb_info = ps_dpb_mgr->as_dpb_info;
79
132k
    for(i = 0; i < MAX_DPB_BUFS; i++)
80
130k
    {
81
130k
        ps_dpb_info[i].ps_prev_dpb = NULL;
82
130k
        ps_dpb_info[i].ps_pic_buf = NULL;
83
84
130k
    }
85
86
2.03k
    ps_dpb_mgr->u1_num_ref_bufs = 0;
87
2.03k
    ps_dpb_mgr->ps_dpb_head = NULL;
88
89
2.03k
}
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
16.1k
{
123
16.1k
    int i;
124
16.1k
    dpb_info_t *ps_dpb_info;
125
126
16.1k
    ps_dpb_info = ps_dpb_mgr->as_dpb_info;
127
128
    /* Return error if buffer is already present in the DPB */
129
1.05M
    for(i = 0; i < MAX_DPB_BUFS; i++)
130
1.03M
    {
131
1.03M
        if((ps_dpb_info[i].ps_pic_buf == ps_pic_buf)
132
0
                        && (ps_dpb_info[i].ps_pic_buf->u1_used_as_ref))
133
0
        {
134
0
            return (-1);
135
0
        }
136
137
138
1.03M
    }
139
140
    /* Find an unused DPB location */
141
23.9k
    for(i = 0; i < MAX_DPB_BUFS; i++)
142
23.9k
    {
143
23.9k
        if(NULL == ps_dpb_info[i].ps_pic_buf)
144
16.1k
        {
145
16.1k
            break;
146
16.1k
        }
147
23.9k
    }
148
16.1k
    if(i == MAX_DPB_BUFS)
149
0
    {
150
0
        return (-1);
151
0
    }
152
153
    /* Create DPB info */
154
16.1k
    ps_dpb_info[i].ps_pic_buf = ps_pic_buf;
155
16.1k
    ps_dpb_info[i].ps_prev_dpb = ps_dpb_mgr->ps_dpb_head;
156
16.1k
    ps_dpb_info[i].ps_pic_buf->u1_buf_id = buf_id;
157
16.1k
    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
16.1k
    ps_dpb_mgr->ps_dpb_head = ps_dpb_info + i;
161
162
    /* Increment Short term buffer count */
163
16.1k
    ps_dpb_mgr->u1_num_ref_bufs++;
164
165
16.1k
    return 0;
166
16.1k
}
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
14.3k
{
200
14.3k
    int i;
201
14.3k
    dpb_info_t *ps_next_dpb;
202
203
14.3k
    dpb_info_t *ps_unmark_node;
204
14.3k
    UWORD8 u1_del_node;
205
14.3k
    UNUSED(u1_del_node);
206
14.3k
    u1_del_node = 0;
207
208
    /* Find the node with matching absolute POC */
209
14.3k
    ps_next_dpb = ps_dpb_mgr->ps_dpb_head;
210
14.3k
    if(ps_next_dpb->ps_pic_buf->i4_abs_poc == i4_abs_poc)
211
12.3k
    {
212
12.3k
        ps_unmark_node = ps_next_dpb;
213
12.3k
    }
214
2.05k
    else
215
2.05k
    {
216
2.79k
        for(i = 1; i < ps_dpb_mgr->u1_num_ref_bufs; i++)
217
2.79k
        {
218
2.79k
            if(ps_next_dpb->ps_prev_dpb->ps_pic_buf->i4_abs_poc == i4_abs_poc)
219
2.05k
                break;
220
732
            ps_next_dpb = ps_next_dpb->ps_prev_dpb;
221
732
        }
222
223
2.05k
        if(i == ps_dpb_mgr->u1_num_ref_bufs)
224
0
        {
225
0
            return;
226
0
        }
227
2.05k
        else
228
2.05k
            ps_unmark_node = ps_next_dpb->ps_prev_dpb;
229
2.05k
    }
230
231
14.3k
    if(ps_unmark_node == ps_dpb_mgr->ps_dpb_head)
232
12.3k
    {
233
12.3k
        ps_dpb_mgr->ps_dpb_head = ps_unmark_node->ps_prev_dpb;
234
12.3k
    }
235
2.05k
    else
236
2.05k
    {
237
2.05k
        ps_next_dpb->ps_prev_dpb = ps_unmark_node->ps_prev_dpb; //update link
238
2.05k
        ps_unmark_node->ps_prev_dpb = NULL;
239
2.05k
    }
240
14.3k
    ps_dpb_mgr->u1_num_ref_bufs--; //decrement buffer count
241
242
    /* Release the physical buffer */
243
14.3k
    ihevc_buf_mgr_release((buf_mgr_t *)ps_buf_mgr, ps_unmark_node->ps_pic_buf->u1_buf_id,
244
14.3k
                          BUF_MGR_REF);
245
14.3k
    ps_unmark_node->ps_prev_dpb = NULL;
246
14.3k
    ps_unmark_node->ps_pic_buf = NULL;
247
14.3k
}
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
41.3k
{
277
41.3k
    WORD32 i;
278
41.3k
    WORD32 min_diff = 0x7FFFFFFF;
279
41.3k
    pic_buf_t *ps_pic_buf = NULL;
280
281
2.69M
    for(i = 0; i < MAX_DPB_BUFS; i++)
282
2.64M
    {
283
2.64M
        if((ps_dpb_mgr->as_dpb_info[i].ps_pic_buf) &&
284
62.3k
                        (ps_dpb_mgr->as_dpb_info[i].ps_pic_buf->u1_used_as_ref != UNUSED_FOR_REF))
285
50.5k
        {
286
50.5k
            WORD32 poc_diff = cur_abs_poc - ps_dpb_mgr->as_dpb_info[i].ps_pic_buf->i4_abs_poc;
287
50.5k
            if((poc_diff > 0) && (poc_diff < min_diff))
288
21.7k
            {
289
21.7k
                min_diff = poc_diff;
290
21.7k
                ps_pic_buf = ps_dpb_mgr->as_dpb_info[i].ps_pic_buf;
291
21.7k
            }
292
50.5k
        }
293
2.64M
    }
294
295
41.3k
    if(NULL == ps_pic_buf)
296
24.6k
    {
297
24.6k
        min_diff = 0x7FFFFFFF;
298
1.60M
        for(i = 0; i < MAX_DPB_BUFS; i++)
299
1.57M
        {
300
1.57M
            if((ps_dpb_mgr->as_dpb_info[i].ps_pic_buf) &&
301
19.9k
                            (ps_dpb_mgr->as_dpb_info[i].ps_pic_buf->u1_used_as_ref != UNUSED_FOR_REF))
302
11.3k
            {
303
11.3k
                WORD32 poc_diff = cur_abs_poc - ps_dpb_mgr->as_dpb_info[i].ps_pic_buf->i4_abs_poc;
304
11.3k
                if(ABS(poc_diff) < min_diff)
305
10.3k
                {
306
10.3k
                    min_diff = ABS(poc_diff);
307
10.3k
                    ps_pic_buf = ps_dpb_mgr->as_dpb_info[i].ps_pic_buf;
308
10.3k
                }
309
11.3k
            }
310
1.57M
        }
311
24.6k
    }
312
313
41.3k
    return ps_pic_buf;
314
41.3k
}
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
47.2k
{
344
47.2k
    UWORD32 i;
345
47.2k
    dpb_info_t *ps_next_ref;
346
47.2k
    pic_buf_t *ps_pic_buf = NULL;
347
348
349
47.2k
    ps_next_ref = ps_dpb_mgr->ps_dpb_head;
350
117k
    for(i = 0; i < ps_dpb_mgr->u1_num_ref_bufs; i++)
351
100k
    {
352
100k
        if(ps_next_ref->ps_pic_buf->i4_abs_poc == abs_poc)
353
30.7k
        {
354
30.7k
            ps_pic_buf = ps_next_ref->ps_pic_buf;
355
30.7k
            break;
356
30.7k
        }
357
358
69.9k
        ps_next_ref = ps_next_ref->ps_prev_dpb;
359
69.9k
    }
360
361
47.2k
    if(i == ps_dpb_mgr->u1_num_ref_bufs)
362
16.5k
    {
363
16.5k
        ps_pic_buf = NULL;
364
16.5k
    }
365
366
47.2k
    return ps_pic_buf;
367
47.2k
}
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
2.40k
{
397
2.40k
    pic_buf_t *ps_pic_buf = NULL;
398
2.40k
    UWORD32 i;
399
2.40k
    dpb_info_t *ps_next_ref;
400
401
2.40k
    ps_next_ref = ps_dpb_mgr->ps_dpb_head;
402
4.49k
    for(i = 0; i < ps_dpb_mgr->u1_num_ref_bufs; i++)
403
3.13k
    {
404
3.13k
        if(ps_next_ref->ps_pic_buf->i4_poc_lsb == poc_lsb)
405
1.04k
        {
406
1.04k
            ps_pic_buf = ps_next_ref->ps_pic_buf;
407
1.04k
            break;
408
1.04k
        }
409
410
2.08k
        ps_next_ref = ps_next_ref->ps_prev_dpb;
411
2.08k
    }
412
413
2.40k
    if(i == ps_dpb_mgr->u1_num_ref_bufs)
414
1.36k
    {
415
1.36k
        ps_pic_buf = NULL;
416
1.36k
    }
417
418
2.40k
    return ps_pic_buf;
419
2.40k
}
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
}