Coverage Report

Created: 2026-07-16 07:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libhevc/decoder/ihevcd_utils.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
*  ihevcd_utils.c
22
*
23
* @brief
24
*  Contains miscellaneous utility functions such as init() etc
25
*
26
* @author
27
*  Harish
28
*
29
* @par List of Functions:
30
*
31
* @remarks
32
*  None
33
*
34
*******************************************************************************
35
*/
36
/*****************************************************************************/
37
/* File Includes                                                             */
38
/*****************************************************************************/
39
#include <stdio.h>
40
#include <stddef.h>
41
#include <stdlib.h>
42
#include <string.h>
43
#include <assert.h>
44
45
#include "ihevc_typedefs.h"
46
#include "iv.h"
47
#include "ivd.h"
48
#include "ihevcd_cxa.h"
49
#include "ithread.h"
50
51
#include "ihevc_defs.h"
52
#include "ihevc_debug.h"
53
#include "ihevc_defs.h"
54
#include "ihevc_error.h"
55
#include "ihevc_structs.h"
56
#include "ihevc_buf_mgr.h"
57
#include "ihevc_dpb_mgr.h"
58
#include "ihevc_macros.h"
59
#include "ihevc_platform_macros.h"
60
61
#include "ihevc_common_tables.h"
62
#include "ihevc_buf_mgr.h"
63
#include "ihevc_disp_mgr.h"
64
#include "ihevc_cabac_tables.h"
65
66
#include "ihevcd_defs.h"
67
68
#include "ihevcd_function_selector.h"
69
#include "ihevcd_structs.h"
70
#include "ihevcd_error.h"
71
#include "ihevcd_nal.h"
72
#include "ihevcd_bitstream.h"
73
#include "ihevcd_utils.h"
74
#include "ihevcd_trace.h"
75
#include "ihevcd_process_slice.h"
76
#include "ihevcd_job_queue.h"
77
#define MAX_DPB_PIC_BUF 6
78
79
/* Function declarations */
80
mv_buf_t* ihevcd_mv_mgr_get_poc(buf_mgr_t *ps_mv_buf_mgr, UWORD32 abs_poc);
81
82
/**
83
*******************************************************************************
84
*
85
* @brief
86
*  Used to get level index for a given level
87
*
88
* @par Description:
89
*  Converts from level_idc (which is multiplied by 30) to an index that can be
90
*  used as a lookup. Also used to ignore invalid levels like 2.2 , 3.2 etc
91
*
92
* @param[in] level
93
*  Level of the stream
94
*
95
* @returns  Level index for a given level
96
*
97
* @remarks
98
*
99
*
100
*******************************************************************************
101
*/
102
WORD32 ihevcd_get_lvl_idx(WORD32 level)
103
0
{
104
0
    WORD32 lvl_idx = 0;
105
106
0
    if(level < IHEVC_LEVEL_20)
107
0
    {
108
0
        lvl_idx = 0;
109
0
    }
110
0
    else if(level >= IHEVC_LEVEL_20 && level < IHEVC_LEVEL_21)
111
0
    {
112
0
        lvl_idx = 1;
113
0
    }
114
0
    else if(level >= IHEVC_LEVEL_21 && level < IHEVC_LEVEL_30)
115
0
    {
116
0
        lvl_idx = 2;
117
0
    }
118
0
    else if(level >= IHEVC_LEVEL_30 && level < IHEVC_LEVEL_31)
119
0
    {
120
0
        lvl_idx = 3;
121
0
    }
122
0
    else if(level >= IHEVC_LEVEL_31 && level < IHEVC_LEVEL_40)
123
0
    {
124
0
        lvl_idx = 4;
125
0
    }
126
0
    else if(level >= IHEVC_LEVEL_40 && level < IHEVC_LEVEL_41)
127
0
    {
128
0
        lvl_idx = 5;
129
0
    }
130
0
    else if(level >= IHEVC_LEVEL_41 && level < IHEVC_LEVEL_50)
131
0
    {
132
0
        lvl_idx = 6;
133
0
    }
134
0
    else if(level >= IHEVC_LEVEL_50 && level < IHEVC_LEVEL_51)
135
0
    {
136
0
        lvl_idx = 7;
137
0
    }
138
0
    else if(level >= IHEVC_LEVEL_51 && level < IHEVC_LEVEL_52)
139
0
    {
140
0
        lvl_idx = 8;
141
0
    }
142
0
    else if(level >= IHEVC_LEVEL_52 && level < IHEVC_LEVEL_60)
143
0
    {
144
0
        lvl_idx = 9;
145
0
    }
146
0
    else if(level >= IHEVC_LEVEL_60 && level < IHEVC_LEVEL_61)
147
0
    {
148
0
        lvl_idx = 10;
149
0
    }
150
0
    else if(level >= IHEVC_LEVEL_61 && level < IHEVC_LEVEL_62)
151
0
    {
152
0
        lvl_idx = 11;
153
0
    }
154
0
    else if(level >= IHEVC_LEVEL_62)
155
0
    {
156
0
        lvl_idx = 12;
157
0
    }
158
159
0
    return (lvl_idx);
160
0
}
161
162
/**
163
*******************************************************************************
164
*
165
* @brief
166
*  Used to get reference picture buffer size for a given level and
167
*  and padding used
168
*
169
* @par Description:
170
*  Used to get reference picture buffer size for a given level and padding used
171
*  Each picture is padded on all four sides
172
*
173
* @param[in] pic_size
174
*  Mumber of luma samples (Width * Height)
175
*
176
* @param[in] level
177
*  Level
178
*
179
* @param[in] horz_pad
180
*  Total padding used in horizontal direction
181
*
182
* @param[in] vert_pad
183
*  Total padding used in vertical direction
184
*
185
* @returns  Total picture buffer size
186
*
187
* @remarks
188
*
189
*
190
*******************************************************************************
191
*/
192
WORD32 ihevcd_get_total_pic_buf_size(codec_t *ps_codec,
193
                                     WORD32 wd,
194
                                     WORD32 ht)
195
0
{
196
0
    WORD32 size;
197
0
    WORD32 num_luma_samples;
198
0
    WORD32 max_dpb_size;
199
0
    WORD32 num_samples;
200
201
202
0
    sps_t *ps_sps = (ps_codec->s_parse.ps_sps_base + ps_codec->i4_sps_id);
203
204
    /* Get maximum number of buffers for the current picture size */
205
0
    max_dpb_size = ps_sps->ai1_sps_max_dec_pic_buffering[ps_sps->i1_sps_max_sub_layers - 1];
206
207
0
    if(ps_codec->e_frm_out_mode != IVD_DECODE_FRAME_OUT)
208
0
        max_dpb_size += ps_sps->ai1_sps_max_num_reorder_pics[ps_sps->i1_sps_max_sub_layers - 1];
209
210
0
    max_dpb_size++;
211
    /* Allocation is required for
212
     * (Wd + horz_pad) * (Ht + vert_pad) * (2 * max_dpb_size + 1)
213
     */
214
215
    /* Account for padding area */
216
0
    num_luma_samples = (wd + PAD_WD) * (ht + PAD_HT);
217
218
    /* Account for chroma */
219
0
    if(ps_sps->i1_chroma_format_idc == CHROMA_FMT_IDC_YUV444)
220
0
    {
221
0
        num_samples = num_luma_samples * 3;
222
0
    }
223
0
    else if(ps_sps->i1_chroma_format_idc == CHROMA_FMT_IDC_YUV422)
224
0
    {
225
0
        num_samples = num_luma_samples * 2;
226
0
    }
227
0
    else if(ps_sps->i1_chroma_format_idc == CHROMA_FMT_IDC_YUV420)
228
0
    {
229
0
        num_samples = num_luma_samples * 3 / 2;
230
0
    }
231
0
    else
232
0
    {
233
0
        num_samples = num_luma_samples;
234
0
    }
235
236
    /* Number of bytes in reference pictures */
237
0
    size = num_samples * max_dpb_size;
238
239
240
0
    return size;
241
0
}
242
/**
243
*******************************************************************************
244
*
245
* @brief
246
*  Used to get MV bank size for a given number of luma samples
247
*
248
* @par Description:
249
*  For given number of luma samples  one MV bank size is computed
250
*  Each MV bank includes pu_map and pu_t for all the min PUs(4x4) in a picture
251
*
252
* @param[in] num_luma_samples
253
*  Max number of luma pixels in the frame
254
*
255
* @returns  Total MV Bank size
256
*
257
* @remarks
258
*
259
*
260
*******************************************************************************
261
*/
262
WORD32 ihevcd_get_pic_mv_bank_size(WORD32 num_luma_samples)
263
0
{
264
0
    WORD32 size;
265
266
0
    WORD32 pic_size;
267
268
0
    WORD32 mv_bank_size;
269
0
    WORD32 num_pu;
270
0
    WORD32 num_ctb;
271
0
    pic_size = num_luma_samples;
272
273
274
0
    num_pu = pic_size / (MIN_PU_SIZE * MIN_PU_SIZE);
275
0
    num_ctb = pic_size / (MIN_CTB_SIZE * MIN_CTB_SIZE);
276
277
0
    mv_bank_size = 0;
278
279
    /* Size for storing pu_t start index each CTB */
280
    /* One extra entry is needed to compute number of PUs in the last CTB */
281
0
    mv_bank_size += (num_ctb + 1) * sizeof(WORD32);
282
283
    /* Size for pu_map */
284
0
    mv_bank_size += num_pu;
285
286
    /* Size for storing pu_t for each PU */
287
0
    mv_bank_size += num_pu * sizeof(pu_t);
288
289
    /* Size for storing slice_idx for each CTB */
290
0
    mv_bank_size += ALIGN4(num_ctb * sizeof(UWORD16));
291
292
0
    size =  mv_bank_size;
293
0
    return size;
294
0
}
295
/**
296
*******************************************************************************
297
*
298
* @brief
299
*  Used to get TU data size for a given number luma samples
300
*
301
* @par Description:
302
*  For a given number of luma samples TU data size is computed
303
*  Each TU data includes tu_map and tu_t and coeff data for all
304
*  the min TUs(4x4) in given CTB
305
*
306
* @param[in] num_luma_samples
307
*  Number of 64 x 64 CTBs for which TU data has to be allocated.
308
*
309
* @returns  Total TU data size
310
*
311
* @remarks Assumption is num_luma_samples will be at least
312
* 64 x 64 to handle CTB of size 64 x 64. Can be frame size as well
313
*
314
*******************************************************************************
315
*/
316
WORD32 ihevcd_get_tu_data_size(codec_t *ps_codec, WORD32 num_luma_samples)
317
0
{
318
319
0
    sps_t *ps_sps = (ps_codec->s_parse.ps_sps_base + ps_codec->i4_sps_id);
320
0
    WORD32 tu_data_size;
321
0
    WORD32 num_ctb;
322
0
    WORD32 num_luma_tu, num_chroma_tu, num_tu;
323
0
    WORD32 num_chroma_sub_tu = 0;
324
0
    num_ctb = num_luma_samples / (MIN_CTB_SIZE * MIN_CTB_SIZE);
325
326
0
    num_luma_tu = num_luma_samples / (MIN_TU_SIZE * MIN_TU_SIZE);
327
328
0
    if(ps_sps->i1_chroma_format_idc == CHROMA_FMT_IDC_YUV444)
329
0
    {
330
0
        num_chroma_tu = num_luma_tu << 1;
331
0
    }
332
0
    else if(ps_sps->i1_chroma_format_idc == CHROMA_FMT_IDC_YUV422)
333
0
    {
334
0
        num_chroma_tu = num_luma_tu >> 1;
335
0
        num_chroma_sub_tu = num_luma_tu >> 1;
336
0
    }
337
0
    else if(ps_sps->i1_chroma_format_idc == CHROMA_FMT_IDC_YUV420)
338
0
    {
339
0
        num_chroma_tu = num_luma_tu >> 1;
340
0
    }
341
0
    else
342
0
    {
343
0
        num_chroma_tu = 0;
344
0
    }
345
346
0
    num_tu = num_luma_tu + num_chroma_tu;
347
0
    tu_data_size = 0;
348
349
    /* Size for storing tu_t start index each CTB */
350
    /* One extra entry is needed to compute number of TUs in the last CTB */
351
0
    tu_data_size += (num_ctb + 1) * sizeof(WORD32);
352
353
    /* Size for storing tu map */
354
0
    tu_data_size += num_tu * sizeof(UWORD8);
355
356
    /* Size for storing tu_t for each TU */
357
0
    tu_data_size += num_tu * sizeof(tu_t);
358
359
    /* Size for storing number of coded subblocks and scan_idx for each TU */
360
0
    tu_data_size += (num_tu + num_chroma_sub_tu) * (sizeof(WORD8) + sizeof(WORD8));
361
362
    /* Size for storing coeff data for each TU */
363
0
    tu_data_size += (num_tu + num_chroma_sub_tu) * sizeof(tu_sblk_coeff_data_t);
364
365
366
0
    return tu_data_size;
367
0
}
368
369
370
WORD32 ihevcd_nctb_cnt(codec_t *ps_codec, sps_t *ps_sps)
371
0
{
372
0
    WORD32 nctb = 1;
373
0
    UNUSED(ps_codec);
374
    //TODO: Currently set to 1
375
    /* If CTB size is less than 32 x 32 then set nCTB as 4 */
376
0
    if(ps_sps->i1_log2_ctb_size < 5)
377
0
        nctb = 1;
378
379
0
    return nctb;
380
0
}
381
382
IHEVCD_ERROR_T ihevcd_get_tile_pos(pps_t *ps_pps,
383
                                   sps_t *ps_sps,
384
                                   WORD32 ctb_x,
385
                                   WORD32 ctb_y,
386
                                   WORD32 *pi4_ctb_tile_x,
387
                                   WORD32 *pi4_ctb_tile_y,
388
                                   WORD32 *pi4_tile_idx)
389
0
{
390
391
0
    tile_t *ps_tile_tmp;
392
0
    WORD32 i;
393
0
    WORD32 tile_row, tile_col;
394
395
0
    if(ctb_x < 0 || ctb_y < 0)
396
0
    {
397
0
        *pi4_ctb_tile_x = 0;
398
0
        *pi4_ctb_tile_y = 0;
399
0
        *pi4_tile_idx = 0;
400
401
0
        return (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
402
0
    }
403
404
0
    tile_row = 0;
405
0
    tile_col = 0;
406
0
    ps_tile_tmp = ps_pps->ps_tile;
407
0
    if(0 == ps_pps->i1_tiles_enabled_flag)
408
0
    {
409
0
        *pi4_ctb_tile_x = ctb_x;
410
0
        *pi4_ctb_tile_y = ctb_y;
411
0
        *pi4_tile_idx = 0;
412
0
    }
413
0
    else
414
0
    {
415
0
        for(i = 0; i < ps_pps->i1_num_tile_columns; i++)
416
0
        {
417
0
            WORD16 next_tile_ctb_x;
418
0
            ps_tile_tmp = ps_pps->ps_tile + i; //* ps_pps->i1_num_tile_rows;
419
0
            if((ps_pps->i1_num_tile_columns - 1) == i)
420
0
            {
421
0
                next_tile_ctb_x = ps_sps->i2_pic_wd_in_ctb;
422
0
            }
423
0
            else
424
0
            {
425
0
                tile_t *ps_tile_next_tmp;
426
0
                ps_tile_next_tmp = ps_pps->ps_tile + i + 1;
427
0
                next_tile_ctb_x = ps_tile_next_tmp->u1_pos_x;
428
0
            }
429
0
            if((ctb_x >= ps_tile_tmp->u1_pos_x) && (ctb_x < next_tile_ctb_x))
430
0
            {
431
0
                tile_col = i;
432
0
                break;
433
0
            }
434
0
        }
435
0
        *pi4_ctb_tile_x = ctb_x - ps_tile_tmp->u1_pos_x;
436
437
0
        for(i = 0; i < ps_pps->i1_num_tile_rows; i++)
438
0
        {
439
0
            WORD16 next_tile_ctb_y;
440
0
            ps_tile_tmp = ps_pps->ps_tile + i * ps_pps->i1_num_tile_columns;
441
0
            if((ps_pps->i1_num_tile_rows - 1) == i)
442
0
            {
443
0
                next_tile_ctb_y = ps_sps->i2_pic_ht_in_ctb;
444
0
            }
445
0
            else
446
0
            {
447
0
                tile_t *ps_tile_next_tmp;
448
0
                ps_tile_next_tmp = ps_pps->ps_tile + ((i + 1) * ps_pps->i1_num_tile_columns);
449
0
                next_tile_ctb_y = ps_tile_next_tmp->u1_pos_y;
450
0
            }
451
0
            if((ctb_y >= ps_tile_tmp->u1_pos_y) && (ctb_y < next_tile_ctb_y))
452
0
            {
453
0
                tile_row = i;
454
0
                break;
455
0
            }
456
457
0
        }
458
0
        *pi4_ctb_tile_y = ctb_y - ps_tile_tmp->u1_pos_y;
459
0
        *pi4_tile_idx = tile_row * ps_pps->i1_num_tile_columns
460
0
                        + tile_col;
461
0
    }
462
0
    return (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
463
0
}
464
/**
465
*******************************************************************************
466
*
467
* @brief
468
*  Function to initialize ps_pic_buf structs add pic buffers to
469
*  buffer manager in case of non-shared mode
470
*
471
* @par Description:
472
*  Function to initialize ps_pic_buf structs add pic buffers to
473
*  buffer manager in case of non-shared mode
474
*  To be called once per stream or for every reset
475
*
476
* @param[in] ps_codec
477
*  Pointer to codec context
478
*
479
* @returns  Error from IHEVCD_ERROR_T
480
*
481
* @remarks
482
*
483
*
484
*******************************************************************************
485
*/
486
IHEVCD_ERROR_T ihevcd_pic_buf_mgr_add_bufs(codec_t *ps_codec)
487
0
{
488
0
    IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
489
0
    WORD32 i;
490
0
    WORD32 max_dpb_size;
491
0
    sps_t *ps_sps;
492
0
    UWORD8 *pu1_buf;
493
0
    pic_buf_t *ps_pic_buf;
494
0
    WORD32 pic_buf_size_allocated;
495
0
    WORD32 h_samp_factor, v_samp_factor;
496
0
    WORD32 chroma_pixel_strd = 2;
497
498
499
    /* Initialize Pic buffer manager */
500
0
    ps_sps = ps_codec->s_parse.ps_sps;
501
502
0
    h_samp_factor = (CHROMA_FMT_IDC_YUV444 == ps_sps->i1_chroma_format_idc) ? 1 : 2;
503
0
    v_samp_factor = (CHROMA_FMT_IDC_YUV420 == ps_sps->i1_chroma_format_idc) ? 2 : 1;
504
505
    /* Compute the number of Pic buffers needed */
506
0
    max_dpb_size = ps_sps->ai1_sps_max_dec_pic_buffering[ps_sps->i1_sps_max_sub_layers - 1];
507
508
0
    if(ps_codec->e_frm_out_mode != IVD_DECODE_FRAME_OUT)
509
0
        max_dpb_size += ps_sps->ai1_sps_max_num_reorder_pics[ps_sps->i1_sps_max_sub_layers - 1];
510
511
    /* Allocate one extra picture to handle current frame
512
     * In case of asynchronous parsing and processing, number of buffers should increase here
513
     * based on when parsing and processing threads are synchronized
514
     */
515
0
    max_dpb_size++;
516
517
518
0
    pu1_buf = (UWORD8 *)ps_codec->pu1_ref_pic_buf_base;
519
520
0
    ps_pic_buf = (pic_buf_t *)ps_codec->ps_pic_buf;
521
522
    /* In case of non-shared mode, add picture buffers to buffer manager
523
     * In case of shared mode buffers are added in the run-time
524
     */
525
0
    if(0 == ps_codec->i4_share_disp_buf)
526
0
    {
527
0
        WORD32 buf_ret;
528
0
        WORD32 luma_samples;
529
0
        WORD32 chroma_samples;
530
0
        pic_buf_size_allocated = ps_codec->i4_total_pic_buf_size;
531
532
0
        luma_samples = (ps_codec->i4_strd) *
533
0
                        (ps_sps->i2_pic_height_in_luma_samples + PAD_HT);
534
535
0
        if(CHROMA_FMT_IDC_MONOCHROME == ps_sps->i1_chroma_format_idc)
536
0
        {
537
0
            chroma_samples = 0;
538
0
        }
539
0
        else
540
0
        {
541
0
            chroma_samples = luma_samples * 2 / (h_samp_factor * v_samp_factor);
542
0
        }
543
544
        /* Try to add as many buffers as possible since memory is already allocated */
545
        /* If the number of buffers that can be added is less than max_num_bufs
546
         * return with an error.
547
         */
548
0
        for(i = 0; i < max_dpb_size; i++)
549
0
        {
550
0
            pic_buf_size_allocated -= (luma_samples + chroma_samples);
551
552
0
            if(pic_buf_size_allocated < 0)
553
0
            {
554
0
                ps_codec->s_parse.i4_error_code = IHEVCD_INSUFFICIENT_MEM_PICBUF;
555
0
                return IHEVCD_INSUFFICIENT_MEM_PICBUF;
556
0
            }
557
558
0
            ps_pic_buf->pu1_luma = pu1_buf + ps_codec->i4_strd * PAD_TOP + PAD_LEFT;
559
0
            pu1_buf += luma_samples;
560
561
0
            if(chroma_samples)
562
0
            {
563
0
                ps_pic_buf->pu1_chroma = pu1_buf
564
0
                                + (ps_codec->i4_strd * chroma_pixel_strd / h_samp_factor) * (PAD_TOP / v_samp_factor)
565
0
                                + (PAD_LEFT * chroma_pixel_strd / h_samp_factor);
566
0
                pu1_buf += chroma_samples;
567
0
            }
568
0
            else
569
0
            {
570
0
                ps_pic_buf->pu1_chroma = NULL;
571
0
            }
572
573
            /* Pad boundary pixels (one pixel on all sides) */
574
            /* This ensures SAO does not read uninitialized pixels */
575
            /* Note these are not used in actual processing */
576
0
            {
577
0
                UWORD8 *pu1_buf;
578
0
                WORD32 strd, wd, ht;
579
0
                WORD32 i;
580
0
                strd = ps_codec->i4_strd;
581
0
                wd = ps_codec->i4_wd;
582
0
                ht = ps_codec->i4_ht;
583
584
0
                pu1_buf = ps_pic_buf->pu1_luma;
585
0
                for(i = 0; i < ht; i++)
586
0
                {
587
0
                    pu1_buf[-1] = 0;
588
0
                    pu1_buf[wd] = 0;
589
0
                    pu1_buf += strd;
590
0
                }
591
0
                pu1_buf = ps_pic_buf->pu1_luma;
592
0
                memset(pu1_buf - strd - 1, 0, wd + 2);
593
594
0
                pu1_buf += strd * ht;
595
0
                memset(pu1_buf - 1, 0, wd + 2);
596
597
0
                if(ps_pic_buf->pu1_chroma)
598
0
                {
599
0
                    pu1_buf = ps_pic_buf->pu1_chroma;
600
0
                    ht /= v_samp_factor;
601
0
                    WORD32 chroma_strd_scale = chroma_pixel_strd / h_samp_factor;
602
0
                    for(i = 0; i < ht; i++)
603
0
                    {
604
0
                        pu1_buf[-1] = 0;
605
0
                        pu1_buf[-2] = 0;
606
0
                        pu1_buf[wd * chroma_strd_scale] = 0;
607
0
                        pu1_buf[wd * chroma_strd_scale + 1] = 0;
608
0
                        pu1_buf += (strd * chroma_strd_scale);
609
0
                    }
610
0
                    pu1_buf = ps_pic_buf->pu1_chroma;
611
0
                    memset(pu1_buf - (strd * chroma_strd_scale) - 2, 0, wd * chroma_strd_scale + 4);
612
613
0
                    pu1_buf += (strd * chroma_strd_scale) * ht;
614
0
                    memset(pu1_buf - 2, 0, wd * chroma_strd_scale + 4);
615
0
                }
616
0
            }
617
618
0
            buf_ret = ihevc_buf_mgr_add((buf_mgr_t *)ps_codec->pv_pic_buf_mgr, ps_pic_buf, i);
619
620
621
0
            if(0 != buf_ret)
622
0
            {
623
0
                ps_codec->s_parse.i4_error_code = IHEVCD_BUF_MGR_ERROR;
624
0
                return IHEVCD_BUF_MGR_ERROR;
625
0
            }
626
0
            ps_pic_buf++;
627
0
        }
628
0
    }
629
0
    else
630
0
    {
631
        /* In case of shared mode, buffers are added without adjusting for padding.
632
           Update luma and chroma pointers here to account for padding as per stride.
633
           In some cases stride might not be available when set_display_frame is called.
634
           Hence updated luma and chroma pointers here */
635
636
0
        for(i = 0; i < BUF_MGR_MAX_CNT; i++)
637
0
        {
638
0
            ps_pic_buf = ihevc_buf_mgr_get_buf((buf_mgr_t *)ps_codec->pv_pic_buf_mgr, i);
639
0
            if((NULL == ps_pic_buf) ||
640
0
               (NULL == ps_pic_buf->pu1_luma) ||
641
0
               (NULL == ps_pic_buf->pu1_chroma))
642
0
            {
643
0
                break;
644
0
            }
645
0
            ps_pic_buf->pu1_luma += ps_codec->i4_strd * PAD_TOP + PAD_LEFT;
646
0
            ps_pic_buf->pu1_chroma += (ps_codec->i4_strd * chroma_pixel_strd / h_samp_factor) * (PAD_TOP / v_samp_factor)
647
0
                            + (PAD_LEFT * chroma_pixel_strd / h_samp_factor);
648
0
        }
649
0
    }
650
651
0
    return ret;
652
0
}
653
/**
654
*******************************************************************************
655
*
656
* @brief
657
*  Function to add buffers to MV Bank buffer manager
658
*
659
* @par Description:
660
*  Function to add buffers to MV Bank buffer manager
661
*  To be called once per stream or for every reset
662
*
663
* @param[in] ps_codec
664
*  Pointer to codec context
665
*
666
* @returns  Error from IHEVCD_ERROR_T
667
*
668
* @remarks
669
*
670
*
671
*******************************************************************************
672
*/
673
IHEVCD_ERROR_T ihevcd_mv_buf_mgr_add_bufs(codec_t *ps_codec)
674
0
{
675
0
    IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
676
0
    WORD32 i;
677
0
    WORD32 max_dpb_size;
678
0
    WORD32 mv_bank_size_allocated;
679
0
    WORD32 pic_mv_bank_size;
680
681
0
    sps_t *ps_sps;
682
0
    UWORD8 *pu1_buf;
683
0
    mv_buf_t *ps_mv_buf;
684
685
686
    /* Initialize MV Bank buffer manager */
687
0
    ps_sps = ps_codec->s_parse.ps_sps;
688
689
690
    /* Compute the number of MV Bank buffers needed */
691
0
    max_dpb_size = ps_sps->ai1_sps_max_dec_pic_buffering[ps_sps->i1_sps_max_sub_layers - 1];
692
693
    /* Allocate one extra MV Bank to handle current frame
694
     * In case of asynchronous parsing and processing, number of buffers should increase here
695
     * based on when parsing and processing threads are synchronized
696
     */
697
0
    max_dpb_size++;
698
699
0
    ps_codec->i4_max_dpb_size = max_dpb_size;
700
701
0
    pu1_buf = (UWORD8 *)ps_codec->pv_mv_bank_buf_base;
702
703
0
    ps_mv_buf = (mv_buf_t *)pu1_buf;
704
0
    pu1_buf += max_dpb_size * sizeof(mv_buf_t);
705
0
    ps_codec->ps_mv_buf = ps_mv_buf;
706
0
    mv_bank_size_allocated = ps_codec->i4_total_mv_bank_size - max_dpb_size  * sizeof(mv_buf_t);
707
708
    /* Compute MV bank size per picture */
709
0
    pic_mv_bank_size = ihevcd_get_pic_mv_bank_size(ALIGN64(ps_sps->i2_pic_width_in_luma_samples) *
710
0
                                                   ALIGN64(ps_sps->i2_pic_height_in_luma_samples));
711
712
0
    for(i = 0; i < max_dpb_size; i++)
713
0
    {
714
0
        WORD32 buf_ret;
715
0
        WORD32 num_pu;
716
0
        WORD32 num_ctb;
717
0
        WORD32 pic_size;
718
0
        pic_size = ALIGN64(ps_sps->i2_pic_width_in_luma_samples) *
719
0
                        ALIGN64(ps_sps->i2_pic_height_in_luma_samples);
720
721
722
0
        num_pu = pic_size / (MIN_PU_SIZE * MIN_PU_SIZE);
723
0
        num_ctb = pic_size / (MIN_CTB_SIZE * MIN_CTB_SIZE);
724
725
726
0
        mv_bank_size_allocated -= pic_mv_bank_size;
727
728
0
        if(mv_bank_size_allocated < 0)
729
0
        {
730
0
            ps_codec->s_parse.i4_error_code = IHEVCD_INSUFFICIENT_MEM_MVBANK;
731
0
            return IHEVCD_INSUFFICIENT_MEM_MVBANK;
732
0
        }
733
734
0
        ps_mv_buf->pu4_pic_pu_idx = (UWORD32 *)pu1_buf;
735
0
        pu1_buf += (num_ctb + 1) * sizeof(WORD32);
736
737
0
        ps_mv_buf->pu1_pic_pu_map = pu1_buf;
738
0
        pu1_buf += num_pu;
739
740
0
        ps_mv_buf->pu1_pic_slice_map = (UWORD16 *)pu1_buf;
741
0
        pu1_buf += ALIGN4(num_ctb * sizeof(UWORD16));
742
743
0
        ps_mv_buf->ps_pic_pu = (pu_t *)pu1_buf;
744
0
        pu1_buf += num_pu * sizeof(pu_t);
745
746
0
        buf_ret = ihevc_buf_mgr_add((buf_mgr_t *)ps_codec->pv_mv_buf_mgr, ps_mv_buf, i);
747
748
0
        if(0 != buf_ret)
749
0
        {
750
0
            ps_codec->s_parse.i4_error_code = IHEVCD_BUF_MGR_ERROR;
751
0
            return IHEVCD_BUF_MGR_ERROR;
752
0
        }
753
754
0
        ps_mv_buf++;
755
756
0
    }
757
0
    return ret;
758
0
}
759
/**
760
*******************************************************************************
761
*
762
* @brief
763
*  Output buffer check
764
*
765
* @par Description:
766
*  Check for the number of buffers and buffer sizes of output buffer
767
*
768
* @param[in] ps_codec
769
*  Pointer to codec context
770
*
771
* @returns  Error from IHEVCD_ERROR_T
772
*
773
* @remarks
774
*
775
*
776
*******************************************************************************
777
*/
778
IHEVCD_ERROR_T ihevcd_check_out_buf_size(codec_t *ps_codec)
779
0
{
780
0
    ivd_out_bufdesc_t *ps_out_buffer = ps_codec->ps_out_buffer;
781
0
    UWORD32 au4_min_out_buf_size[IVD_VIDDEC_MAX_IO_BUFFERS];
782
0
    UWORD32 u4_min_num_out_bufs = 0, i;
783
0
    UWORD32 wd, ht;
784
0
    UWORD32 aligned_wd, aligned_ht;
785
786
0
    if(0 == ps_codec->i4_share_disp_buf)
787
0
    {
788
0
        wd = ps_codec->i4_disp_wd;
789
0
        ht = ps_codec->i4_disp_ht;
790
0
    }
791
0
    else
792
0
    {
793
        /* In case of shared mode, do not check validity of ps_codec->ps_out_buffer */
794
0
        return (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
795
0
    }
796
797
0
    if(ps_codec->i4_disp_strd > (WORD32)wd)
798
0
        wd = ps_codec->i4_disp_strd;
799
800
0
    if(ps_codec->e_chroma_fmt == IV_YUV_420P)
801
0
        u4_min_num_out_bufs = MIN_OUT_BUFS_420;
802
0
    else if(ps_codec->e_chroma_fmt == IV_YUV_444P)
803
0
        u4_min_num_out_bufs = MIN_OUT_BUFS_444;
804
0
    else if(ps_codec->e_chroma_fmt == IV_YUV_422P)
805
0
        u4_min_num_out_bufs = MIN_OUT_BUFS_422;
806
0
    else if((ps_codec->e_chroma_fmt == IV_YUV_420SP_UV)
807
0
                    || (ps_codec->e_chroma_fmt == IV_YUV_420SP_VU))
808
0
        u4_min_num_out_bufs = MIN_OUT_BUFS_420SP;
809
0
    else if(ps_codec->e_chroma_fmt == IV_GRAY)
810
0
        u4_min_num_out_bufs = MIN_OUT_BUFS_GRAY;
811
812
0
    aligned_wd = ALIGN2(wd);
813
0
    aligned_ht = ALIGN2(ht);
814
0
    if(ps_codec->e_chroma_fmt == IV_YUV_420P)
815
0
    {
816
0
        au4_min_out_buf_size[0] = (wd * ht);
817
0
        au4_min_out_buf_size[1] = (aligned_wd * aligned_ht) >> 2;
818
0
        au4_min_out_buf_size[2] = (aligned_wd * aligned_ht) >> 2;
819
0
    }
820
0
    else if(ps_codec->e_chroma_fmt == IV_YUV_444P)
821
0
    {
822
0
        au4_min_out_buf_size[0] = (wd * ht);
823
0
        au4_min_out_buf_size[1] = (wd * ht);
824
0
        au4_min_out_buf_size[2] = (wd * ht);
825
0
    }
826
0
    else if((ps_codec->e_chroma_fmt == IV_YUV_420SP_UV)
827
0
                    || (ps_codec->e_chroma_fmt == IV_YUV_420SP_VU))
828
0
    {
829
0
        au4_min_out_buf_size[0] = (wd * ht);
830
0
        au4_min_out_buf_size[1] = (aligned_wd * aligned_ht) >> 1;
831
0
        au4_min_out_buf_size[2] = 0;
832
0
    }
833
0
    else if(ps_codec->e_chroma_fmt == IV_GRAY)
834
0
    {
835
0
        au4_min_out_buf_size[0] = (wd * ht);
836
0
        au4_min_out_buf_size[1] = 0;
837
0
        au4_min_out_buf_size[2] = 0;
838
0
    }
839
0
    else if(ps_codec->e_chroma_fmt == IV_YUV_422P)
840
0
    {
841
0
        au4_min_out_buf_size[0] = (wd * ht);
842
0
        au4_min_out_buf_size[1] = (aligned_wd * ht) >> 1;
843
0
        au4_min_out_buf_size[2] = (aligned_wd * ht) >> 1;
844
0
    }
845
846
847
0
    if(ps_out_buffer->u4_num_bufs < u4_min_num_out_bufs)
848
0
    {
849
0
        return (IHEVCD_ERROR_T)IV_FAIL;
850
0
    }
851
852
0
    for (i = 0 ; i < u4_min_num_out_bufs; i++)
853
0
    {
854
0
        if(ps_out_buffer->u4_min_out_buf_size[i] < au4_min_out_buf_size[i])
855
0
        {
856
0
            return (IHEVCD_ERROR_T)IV_FAIL;
857
0
        }
858
0
    }
859
860
0
    return (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
861
0
}
862
863
/**
864
*******************************************************************************
865
*
866
* @brief
867
*  Picture level initializations required during parsing
868
*
869
* @par Description:
870
*  Initialize picture level context variables during parsing Initialize mv
871
* bank buffer manager in the first init call
872
*
873
* @param[in] ps_codec
874
*  Pointer to codec context
875
*
876
* @returns  Error from IHEVCD_ERROR_T
877
*
878
* @remarks
879
*
880
*
881
*******************************************************************************
882
*/
883
IHEVCD_ERROR_T ihevcd_parse_pic_init(codec_t *ps_codec)
884
0
{
885
0
    IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
886
0
    mv_buf_t *ps_mv_buf;
887
0
    sps_t *ps_sps;
888
0
    WORD32 num_min_cu;
889
0
    WORD32 cur_pic_buf_id;
890
0
    WORD32 cur_mv_bank_buf_id;
891
0
    pic_buf_t *ps_cur_pic;
892
0
    slice_header_t *ps_slice_hdr;
893
0
    UWORD8 *pu1_cur_pic_luma, *pu1_cur_pic_chroma;
894
0
    WORD32 h_samp_factor, v_samp_factor;
895
0
    WORD32 chroma_pixel_strd = 2;
896
0
    WORD32 i;
897
898
0
    ps_codec->s_parse.i4_error_code = IHEVCD_SUCCESS;
899
0
    ps_sps = ps_codec->s_parse.ps_sps;
900
0
    ps_slice_hdr = ps_codec->s_parse.ps_slice_hdr;
901
902
    /* Memset picture level intra map and transquant bypass map to zero */
903
0
    num_min_cu = ((ps_sps->i2_pic_height_in_luma_samples + 7) / 8) * ((ps_sps->i2_pic_width_in_luma_samples + 63) / 64);
904
0
    memset(ps_codec->s_parse.pu1_pic_intra_flag, 0, num_min_cu);
905
0
    memset(ps_codec->s_parse.pu1_pic_no_loop_filter_flag, 0, num_min_cu);
906
907
0
    h_samp_factor = (CHROMA_FMT_IDC_YUV444 == ps_sps->i1_chroma_format_idc) ? 1 : 2;
908
0
    v_samp_factor = (CHROMA_FMT_IDC_YUV420 == ps_sps->i1_chroma_format_idc) ? 2 : 1;
909
910
0
    if(0 == ps_codec->s_parse.i4_first_pic_init)
911
0
    {
912
0
        ret = ihevcd_mv_buf_mgr_add_bufs(ps_codec);
913
0
        RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
914
915
0
        ret = ihevcd_pic_buf_mgr_add_bufs(ps_codec);
916
0
        RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
917
918
0
        ps_codec->s_parse.i4_first_pic_init = 1;
919
0
    }
920
921
    /* Output buffer check */
922
0
    ret = ihevcd_check_out_buf_size(ps_codec);
923
0
    RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
924
925
    /* Initialize all the slice headers' slice addresses to zero */
926
0
    {
927
0
        WORD32 slice_idx;
928
0
        WORD32 slice_start_idx;
929
930
0
        slice_start_idx = ps_codec->i4_slice_error ? 2 : 1;
931
932
0
        for(slice_idx = slice_start_idx; slice_idx < MAX_SLICE_HDR_CNT; slice_idx++)
933
0
        {
934
0
            slice_header_t *ps_slice_hdr_tmp = ps_codec->ps_slice_hdr_base + slice_idx;
935
0
            ps_slice_hdr_tmp->i2_ctb_x = -1;
936
0
            ps_slice_hdr_tmp->i2_ctb_y = -1;
937
938
0
        }
939
0
    }
940
941
    /* Get free MV Bank to hold current picture's motion vector data */
942
0
    {
943
0
        ps_mv_buf = (mv_buf_t *)ihevc_buf_mgr_get_next_free((buf_mgr_t *)ps_codec->pv_mv_buf_mgr, &cur_mv_bank_buf_id);
944
945
        /* If there are no free buffers then return with an error code.
946
         * If the buffer is to be freed by another thread , change the
947
         * following to call thread yield and wait for buffer to be freed
948
         */
949
0
        if(NULL == ps_mv_buf)
950
0
        {
951
0
            ps_codec->s_parse.i4_error_code = IHEVCD_NO_FREE_MVBANK;
952
0
            ps_codec->i4_error_code = IHEVCD_NO_FREE_MVBANK;
953
0
            return IHEVCD_NO_FREE_MVBANK;
954
0
        }
955
956
0
        ps_codec->s_parse.ps_cur_mv_buf = ps_mv_buf;
957
        /* Set current ABS poc to ps_mv_buf, so that while freeing a reference buffer
958
         * corresponding mv buffer can be found by looping through ps_codec->ps_mv_buf array
959
         * and getting a buffer id to free
960
         */
961
0
        ps_mv_buf->i4_abs_poc = ps_slice_hdr->i4_abs_pic_order_cnt;
962
0
    }
963
964
    /* Get free picture buffer to hold current picture recon data */
965
    /* TODO: For asynchronous api the following initializations related to picture
966
     * buffer should be moved to processing side
967
     */
968
0
    {
969
970
0
        UWORD8 *pu1_buf;
971
0
        ps_cur_pic = (pic_buf_t *)ihevc_buf_mgr_get_next_free((buf_mgr_t *)ps_codec->pv_pic_buf_mgr, &cur_pic_buf_id);
972
973
        /* If there are no free buffers then return with an error code.
974
         * TODO: If the buffer is to be freed by another thread , change the
975
         * following to call thread yield and wait for buffer to be freed
976
         */
977
0
        if(NULL == ps_cur_pic)
978
0
        {
979
0
            ps_codec->s_parse.i4_error_code = IHEVCD_NO_FREE_PICBUF;
980
0
            ps_codec->i4_error_code = IHEVCD_NO_FREE_PICBUF;
981
0
            return IHEVCD_NO_FREE_PICBUF;
982
0
        }
983
984
        /* Store input timestamp sent with input buffer */
985
0
        ps_cur_pic->u4_ts = ps_codec->u4_ts;
986
0
        ps_cur_pic->i4_abs_poc = ps_slice_hdr->i4_abs_pic_order_cnt;
987
0
        ps_cur_pic->i4_poc_lsb = ps_slice_hdr->i4_pic_order_cnt_lsb;
988
0
        pu1_buf = ps_cur_pic->pu1_luma;
989
0
        pu1_cur_pic_luma = pu1_buf;
990
991
0
        pu1_buf = ps_cur_pic->pu1_chroma;
992
0
        pu1_cur_pic_chroma = pu1_buf;
993
994
0
#ifndef DISABLE_SEI
995
0
        ps_cur_pic->s_sei_params.i1_sei_parameters_present_flag = 0;
996
0
        if(ps_codec->s_parse.s_sei_params.i1_sei_parameters_present_flag)
997
0
        {
998
0
            sei_params_t *ps_sei = &ps_codec->s_parse.s_sei_params;
999
0
            ps_cur_pic->s_sei_params = ps_codec->s_parse.s_sei_params;
1000
1001
            /* Once sei_params is copied to pic_buf,
1002
             * mark sei_params in s_parse as not present,
1003
             * this ensures that future frames do not use this data again.
1004
             */
1005
0
            ps_sei->i1_sei_parameters_present_flag = 0;
1006
0
            ps_sei->i1_user_data_registered_present_flag = 0;
1007
0
            ps_sei->i1_aud_present_flag = 0;
1008
0
            ps_sei->i1_time_code_present_flag = 0;
1009
0
            ps_sei->i1_buf_period_params_present_flag = 0;
1010
0
            ps_sei->i1_pic_timing_params_present_flag = 0;
1011
0
            ps_sei->i1_recovery_point_params_present_flag = 0;
1012
0
            ps_sei->i1_active_parameter_set = 0;
1013
0
            ps_sei->i4_sei_mastering_disp_colour_vol_params_present_flags = 0;
1014
0
        }
1015
0
#endif
1016
0
    }
1017
1018
0
    if(0 == ps_codec->u4_pic_cnt)
1019
0
    {
1020
0
        memset(ps_cur_pic->pu1_luma, 128, (ps_sps->i2_pic_width_in_luma_samples + PAD_WD) * ps_sps->i2_pic_height_in_luma_samples);
1021
0
        if(ps_sps->i1_chroma_format_idc != CHROMA_FMT_IDC_MONOCHROME)
1022
0
        {
1023
0
            memset(ps_cur_pic->pu1_chroma,
1024
0
                   128,
1025
0
                   (((ps_sps->i2_pic_width_in_luma_samples + PAD_WD) * (chroma_pixel_strd / h_samp_factor))
1026
0
                                   * ps_sps->i2_pic_height_in_luma_samples / v_samp_factor));
1027
0
        }
1028
0
    }
1029
1030
    /* Fill the remaining entries of the reference lists with the nearest POC
1031
     * This is done to handle cases where there is a corruption in the reference index */
1032
0
    {
1033
0
        pic_buf_t *ps_pic_buf_ref;
1034
0
        mv_buf_t *ps_mv_buf_ref;
1035
0
        WORD32 r_idx;
1036
0
        dpb_mgr_t *ps_dpb_mgr = (dpb_mgr_t *)ps_codec->pv_dpb_mgr;
1037
0
        buf_mgr_t *ps_mv_buf_mgr = (buf_mgr_t *)ps_codec->pv_mv_buf_mgr;
1038
1039
0
        ps_pic_buf_ref = ihevc_dpb_mgr_get_ref_by_nearest_poc(ps_dpb_mgr, ps_slice_hdr->i4_abs_pic_order_cnt);
1040
0
        if(NULL == ps_pic_buf_ref)
1041
0
        {
1042
0
            WORD32 size;
1043
1044
0
            WORD32 num_pu;
1045
0
            WORD32 num_ctb;
1046
0
            WORD32 pic_size;
1047
            /* In case current mv buffer itself is being used as reference mv buffer for colocated
1048
             * calculations, then memset all the buffers to zero.
1049
             */
1050
0
            pic_size = ALIGN64(ps_sps->i2_pic_width_in_luma_samples) *
1051
0
                            ALIGN64(ps_sps->i2_pic_height_in_luma_samples);
1052
1053
0
            num_pu = pic_size / (MIN_PU_SIZE * MIN_PU_SIZE);
1054
0
            num_ctb = pic_size / (MIN_CTB_SIZE * MIN_CTB_SIZE);
1055
1056
0
            memset(ps_mv_buf->ai4_l0_collocated_poc, 0, sizeof(ps_mv_buf->ai4_l0_collocated_poc));
1057
0
            memset(ps_mv_buf->ai1_l0_collocated_poc_lt, 0, sizeof(ps_mv_buf->ai1_l0_collocated_poc_lt));
1058
0
            memset(ps_mv_buf->ai4_l1_collocated_poc, 0, sizeof(ps_mv_buf->ai4_l1_collocated_poc));
1059
0
            memset(ps_mv_buf->ai1_l1_collocated_poc_lt, 0, sizeof(ps_mv_buf->ai1_l1_collocated_poc_lt));
1060
1061
0
            size = (num_ctb + 1) * sizeof(WORD32);
1062
0
            memset(ps_mv_buf->pu4_pic_pu_idx, 0, size);
1063
1064
0
            size = num_pu;
1065
0
            memset(ps_mv_buf->pu1_pic_pu_map, 0, size);
1066
0
            size = ALIGN4(num_ctb * sizeof(UWORD16));
1067
0
            memset(ps_mv_buf->pu1_pic_slice_map, 0, size);
1068
0
            size = num_pu * sizeof(pu_t);
1069
0
            memset(ps_mv_buf->ps_pic_pu, 0, size);
1070
1071
0
            ps_pic_buf_ref = ps_cur_pic;
1072
0
            ps_mv_buf_ref = ps_mv_buf;
1073
0
        }
1074
0
        else
1075
0
        {
1076
0
            ps_mv_buf_ref = ihevcd_mv_mgr_get_poc(ps_mv_buf_mgr, ps_pic_buf_ref->i4_abs_poc);
1077
0
        }
1078
1079
0
        for(r_idx = 0; r_idx < ps_slice_hdr->i1_num_ref_idx_l0_active; r_idx++)
1080
0
        {
1081
0
            if(NULL == ps_slice_hdr->as_ref_pic_list0[r_idx].pv_pic_buf)
1082
0
            {
1083
0
                ps_slice_hdr->as_ref_pic_list0[r_idx].pv_pic_buf = (void *)ps_pic_buf_ref;
1084
0
                ps_slice_hdr->as_ref_pic_list0[r_idx].pv_mv_buf = (void *)ps_mv_buf_ref;
1085
0
            }
1086
0
        }
1087
1088
0
        for(r_idx = ps_slice_hdr->i1_num_ref_idx_l0_active; r_idx < MAX_DPB_SIZE; r_idx++)
1089
0
        {
1090
0
            ps_slice_hdr->as_ref_pic_list0[r_idx].pv_pic_buf = (void *)ps_pic_buf_ref;
1091
0
            ps_slice_hdr->as_ref_pic_list0[r_idx].pv_mv_buf = (void *)ps_mv_buf_ref;
1092
0
        }
1093
1094
0
        for(r_idx = 0; r_idx < ps_slice_hdr->i1_num_ref_idx_l1_active; r_idx++)
1095
0
        {
1096
0
            if(NULL == ps_slice_hdr->as_ref_pic_list1[r_idx].pv_pic_buf)
1097
0
            {
1098
0
                ps_slice_hdr->as_ref_pic_list1[r_idx].pv_pic_buf = (void *)ps_pic_buf_ref;
1099
0
                ps_slice_hdr->as_ref_pic_list1[r_idx].pv_mv_buf = (void *)ps_mv_buf_ref;
1100
0
            }
1101
0
        }
1102
1103
0
        for(r_idx = ps_slice_hdr->i1_num_ref_idx_l1_active; r_idx < MAX_DPB_SIZE; r_idx++)
1104
0
        {
1105
0
            ps_slice_hdr->as_ref_pic_list1[r_idx].pv_pic_buf = (void *)ps_pic_buf_ref;
1106
0
            ps_slice_hdr->as_ref_pic_list1[r_idx].pv_mv_buf = (void *)ps_mv_buf_ref;
1107
0
        }
1108
0
    }
1109
1110
1111
    /* Reset the jobq to start of the jobq buffer */
1112
0
    ihevcd_jobq_reset((jobq_t *)ps_codec->pv_proc_jobq);
1113
1114
0
    if(ps_codec->i4_threads_active)
1115
0
    {
1116
0
        ps_codec->i4_break_threads = 0;
1117
0
    }
1118
0
    ps_codec->s_parse.i4_pic_pu_idx = 0;
1119
0
    ps_codec->s_parse.i4_pic_tu_idx = 0;
1120
1121
0
    ps_codec->s_parse.pu1_pic_pu_map = ps_mv_buf->pu1_pic_pu_map;
1122
0
    ps_codec->s_parse.ps_pic_pu      = ps_mv_buf->ps_pic_pu;
1123
0
    ps_codec->s_parse.pu4_pic_pu_idx = ps_mv_buf->pu4_pic_pu_idx;
1124
0
    ps_codec->s_parse.pu1_slice_idx = (UWORD16 *)ps_mv_buf->pu1_pic_slice_map;
1125
0
    for(i = 0; i < MAX_PROCESS_THREADS; i++)
1126
0
    {
1127
0
        ps_codec->as_process[i].pu1_slice_idx = (UWORD16 *)ps_mv_buf->pu1_pic_slice_map;
1128
0
    }
1129
0
    ps_codec->s_parse.pu1_pu_map = ps_codec->s_parse.pu1_pic_pu_map;
1130
0
    ps_codec->s_parse.ps_pu = ps_codec->s_parse.ps_pic_pu;
1131
1132
0
    {
1133
0
        UWORD8 *pu1_buf;
1134
0
        WORD32 ctb_luma_min_tu_cnt, ctb_chroma_min_tu_cnt, ctb_min_tu_cnt;
1135
0
        WORD32 pic_size;
1136
0
        WORD32 num_ctb;
1137
1138
0
        pic_size = ALIGN64(ps_sps->i2_pic_width_in_luma_samples) *
1139
0
                        ALIGN64(ps_sps->i2_pic_height_in_luma_samples);
1140
1141
0
        ctb_luma_min_tu_cnt = pic_size / (MIN_TU_SIZE * MIN_TU_SIZE);
1142
1143
0
        if(ps_sps->i1_chroma_format_idc == CHROMA_FMT_IDC_YUV444)
1144
0
        {
1145
0
            ctb_chroma_min_tu_cnt = ctb_luma_min_tu_cnt << 1;
1146
0
        }
1147
0
        else if(ps_sps->i1_chroma_format_idc == CHROMA_FMT_IDC_YUV422 ||
1148
0
                ps_sps->i1_chroma_format_idc == CHROMA_FMT_IDC_YUV420)
1149
0
        {
1150
0
            ctb_chroma_min_tu_cnt = ctb_luma_min_tu_cnt >> 1;
1151
0
        }
1152
0
        else
1153
0
        {
1154
0
            ctb_chroma_min_tu_cnt = 0;
1155
0
        }
1156
1157
0
        ctb_min_tu_cnt = ctb_luma_min_tu_cnt + ctb_chroma_min_tu_cnt;
1158
1159
0
        num_ctb = pic_size / (MIN_CTB_SIZE * MIN_CTB_SIZE);
1160
0
        pu1_buf  = (UWORD8 *)ps_codec->pv_tu_data;
1161
0
        ps_codec->s_parse.pu4_pic_tu_idx = (UWORD32 *)pu1_buf;
1162
0
        pu1_buf += (num_ctb + 1) * sizeof(WORD32);
1163
1164
0
        ps_codec->s_parse.pu1_pic_tu_map = pu1_buf;
1165
0
        pu1_buf += ctb_min_tu_cnt;
1166
1167
0
        ps_codec->s_parse.ps_pic_tu = (tu_t *)pu1_buf;
1168
0
        pu1_buf += ctb_min_tu_cnt * sizeof(tu_t);
1169
1170
0
        ps_codec->s_parse.pv_pic_tu_coeff_data = pu1_buf;
1171
1172
0
        ps_codec->s_parse.pu1_tu_map = ps_codec->s_parse.pu1_pic_tu_map;
1173
0
        ps_codec->s_parse.ps_tu = ps_codec->s_parse.ps_pic_tu;
1174
0
        ps_codec->s_parse.pv_tu_coeff_data = ps_codec->s_parse.pv_pic_tu_coeff_data;
1175
0
    }
1176
1177
0
    ps_codec->s_parse.s_bs_ctxt.ps_pic_pu = ps_codec->s_parse.ps_pic_pu;
1178
0
    ps_codec->s_parse.s_bs_ctxt.pu4_pic_pu_idx = ps_codec->s_parse.pu4_pic_pu_idx;
1179
0
    ps_codec->s_parse.s_bs_ctxt.pu4_pic_tu_idx = ps_codec->s_parse.pu4_pic_tu_idx;
1180
1181
1182
    /* Set number of CTBs to be processed simultaneously */
1183
0
    ps_codec->i4_proc_nctb = ihevcd_nctb_cnt(ps_codec, ps_sps);
1184
1185
    /* Memset Parse Map and process map at the start of frame */
1186
    //TODO: In case of asynchronous API proc_map can not be set to zero here
1187
0
    {
1188
0
        WORD32 num_ctb;
1189
1190
0
        num_ctb = ps_sps->i4_pic_size_in_ctb;
1191
1192
0
        memset(ps_codec->pu1_parse_map, 0, num_ctb);
1193
1194
0
        memset(ps_codec->pu1_proc_map, 0, num_ctb);
1195
0
    }
1196
1197
1198
1199
    /* Initialize disp buf id to -1, this will be updated at the end of frame if there is
1200
     * buffer to be displayed
1201
     */
1202
0
    ps_codec->i4_disp_buf_id = -1;
1203
0
    ps_codec->ps_disp_buf = NULL;
1204
1205
0
    ps_codec->i4_disable_deblk_pic  = 0;
1206
0
    ps_codec->i4_disable_sao_pic    = 0;
1207
0
    ps_codec->i4_fullpel_inter_pred = 0;
1208
0
    ps_codec->i4_mv_frac_mask       = 0x7FFFFFFF;
1209
1210
    /* If degrade is enabled, set the degrade flags appropriately */
1211
0
    if(ps_codec->i4_degrade_type && ps_codec->i4_degrade_pics)
1212
0
    {
1213
0
        WORD32 degrade_pic;
1214
0
        ps_codec->i4_degrade_pic_cnt++;
1215
0
        degrade_pic = 0;
1216
1217
        /* If degrade is to be done in all frames, then do not check further */
1218
0
        switch(ps_codec->i4_degrade_pics)
1219
0
        {
1220
0
            case 4:
1221
0
            {
1222
0
                degrade_pic = 1;
1223
0
                break;
1224
0
            }
1225
0
            case 3:
1226
0
            {
1227
0
                if(ps_slice_hdr->i1_slice_type != ISLICE)
1228
0
                    degrade_pic = 1;
1229
1230
0
                break;
1231
0
            }
1232
0
            case 2:
1233
0
            {
1234
1235
                /* If pic count hits non-degrade interval or it is an islice, then do not degrade */
1236
0
                if((ps_slice_hdr->i1_slice_type != ISLICE) &&
1237
0
                   (ps_codec->i4_degrade_pic_cnt != ps_codec->i4_nondegrade_interval))
1238
0
                    degrade_pic = 1;
1239
1240
0
                break;
1241
0
            }
1242
0
            case 1:
1243
0
            {
1244
                /* Check if the current picture is non-ref */
1245
0
                if((ps_slice_hdr->i1_nal_unit_type < NAL_BLA_W_LP) &&
1246
0
                   (ps_slice_hdr->i1_nal_unit_type % 2 == 0))
1247
0
                {
1248
0
                    degrade_pic = 1;
1249
0
                }
1250
0
                break;
1251
0
            }
1252
1253
1254
0
        }
1255
0
        if(degrade_pic)
1256
0
        {
1257
0
            if(ps_codec->i4_degrade_type & 0x1)
1258
0
                ps_codec->i4_disable_sao_pic = 1;
1259
1260
0
            if(ps_codec->i4_degrade_type & 0x2)
1261
0
                ps_codec->i4_disable_deblk_pic = 1;
1262
1263
            /* MC degrading is done only for non-ref pictures */
1264
0
            if((ps_slice_hdr->i1_nal_unit_type < NAL_BLA_W_LP) &&
1265
0
               (ps_slice_hdr->i1_nal_unit_type % 2 == 0))
1266
0
            {
1267
0
                if(ps_codec->i4_degrade_type & 0x4)
1268
0
                    ps_codec->i4_mv_frac_mask = 0;
1269
1270
0
                if(ps_codec->i4_degrade_type & 0x8)
1271
0
                    ps_codec->i4_mv_frac_mask = 0;
1272
0
            }
1273
0
        }
1274
0
        else
1275
0
            ps_codec->i4_degrade_pic_cnt = 0;
1276
0
    }
1277
1278
1279
0
    {
1280
0
        WORD32 i;
1281
0
        for(i = 0; i < MAX_PROCESS_THREADS; i++)
1282
0
        {
1283
0
            ps_codec->as_process[i].pu4_pic_pu_idx = ps_codec->s_parse.pu4_pic_pu_idx;
1284
0
            ps_codec->as_process[i].ps_pic_pu = ps_codec->s_parse.ps_pic_pu;
1285
0
            ps_codec->as_process[i].pu1_pic_pu_map = ps_codec->s_parse.pu1_pic_pu_map;
1286
0
            ps_codec->as_process[i].pu4_pic_tu_idx = ps_codec->s_parse.pu4_pic_tu_idx;
1287
0
            ps_codec->as_process[i].ps_pic_tu = ps_codec->s_parse.ps_pic_tu;
1288
0
            ps_codec->as_process[i].pu1_pic_tu_map = ps_codec->s_parse.pu1_pic_tu_map;
1289
0
            ps_codec->as_process[i].pv_pic_tu_coeff_data = ps_codec->s_parse.pv_pic_tu_coeff_data;
1290
0
            ps_codec->as_process[i].i4_cur_mv_bank_buf_id = cur_mv_bank_buf_id;
1291
0
            ps_codec->as_process[i].s_sao_ctxt.pu1_slice_idx = ps_codec->as_process[i].pu1_slice_idx;
1292
0
            ps_codec->as_process[i].s_sao_ctxt.pu1_tile_idx = ps_codec->as_process[i].pu1_tile_idx;
1293
1294
            /* TODO: For asynchronous api the following initializations related to picture
1295
             * buffer should be moved to processing side
1296
             */
1297
0
            ps_codec->as_process[i].pu1_cur_pic_luma = pu1_cur_pic_luma;
1298
0
            ps_codec->as_process[i].pu1_cur_pic_chroma = pu1_cur_pic_chroma;
1299
0
            ps_codec->as_process[i].ps_cur_pic = ps_cur_pic;
1300
0
            ps_codec->as_process[i].i4_cur_pic_buf_id = cur_pic_buf_id;
1301
1302
0
            ps_codec->as_process[i].ps_out_buffer = ps_codec->ps_out_buffer;
1303
0
            if(1 < ps_codec->i4_num_cores)
1304
0
            {
1305
0
                ps_codec->as_process[i].i4_check_parse_status = 1;
1306
0
                ps_codec->as_process[i].i4_check_proc_status = 1;
1307
0
            }
1308
0
            else
1309
0
            {
1310
0
                ps_codec->as_process[i].i4_check_parse_status = 0;
1311
0
                ps_codec->as_process[i].i4_check_proc_status = 0;
1312
0
            }
1313
0
            ps_codec->as_process[i].pu1_pic_intra_flag = ps_codec->s_parse.pu1_pic_intra_flag;
1314
0
            ps_codec->as_process[i].pu1_pic_no_loop_filter_flag = ps_codec->s_parse.pu1_pic_no_loop_filter_flag;
1315
0
            ps_codec->as_process[i].i4_init_done = 0;
1316
1317
0
            ps_codec->as_process[i].s_bs_ctxt.pu4_pic_tu_idx = ps_codec->as_process[i].pu4_pic_tu_idx;
1318
0
            ps_codec->as_process[i].s_bs_ctxt.pu4_pic_pu_idx = ps_codec->as_process[i].pu4_pic_pu_idx;
1319
0
            ps_codec->as_process[i].s_bs_ctxt.ps_pic_pu = ps_codec->as_process[i].ps_pic_pu;
1320
0
            ps_codec->as_process[i].s_deblk_ctxt.pu1_pic_no_loop_filter_flag = ps_codec->s_parse.pu1_pic_no_loop_filter_flag;
1321
0
            ps_codec->as_process[i].s_deblk_ctxt.pu1_cur_pic_luma = pu1_cur_pic_luma;
1322
0
            ps_codec->as_process[i].s_deblk_ctxt.pu1_cur_pic_chroma = pu1_cur_pic_chroma;
1323
0
            ps_codec->as_process[i].s_sao_ctxt.pu1_pic_no_loop_filter_flag = ps_codec->s_parse.pu1_pic_no_loop_filter_flag;
1324
0
            ps_codec->as_process[i].s_sao_ctxt.pu1_cur_pic_luma = pu1_cur_pic_luma;
1325
0
            ps_codec->as_process[i].s_sao_ctxt.pu1_cur_pic_chroma = pu1_cur_pic_chroma;
1326
0
            if(i < (ps_codec->i4_num_cores - 1))
1327
0
            {
1328
0
                if (!ps_codec->ai4_process_thread_created[i])
1329
0
                {
1330
0
                    ithread_create(ps_codec->apv_process_thread_handle[i], NULL,
1331
0
                                (void *)ihevcd_process_thread,
1332
0
                                (void *)&ps_codec->as_process[i]);
1333
0
                    ps_codec->ai4_process_thread_created[i] = 1;
1334
0
                }
1335
0
                if(ps_codec->i4_threads_active)
1336
0
                {
1337
0
                    ret = ithread_mutex_lock(ps_codec->apv_proc_start_mutex[i]);
1338
0
                    RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
1339
1340
0
                    ps_codec->ai4_process_start[i] = 1;
1341
0
                    ithread_cond_signal(ps_codec->apv_proc_start_condition[i]);
1342
1343
0
                    ret = ithread_mutex_unlock(ps_codec->apv_proc_start_mutex[i]);
1344
0
                    RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
1345
0
                }
1346
0
            }
1347
0
            else
1348
0
            {
1349
0
                ps_codec->ai4_process_thread_created[i] = 0;
1350
0
            }
1351
1352
0
        }
1353
0
        if(ps_codec->u1_enable_cu_info)
1354
0
        {
1355
0
            ps_codec->as_buf_id_info_map[cur_pic_buf_id].pu1_qp_map =
1356
0
                ps_codec->pu1_qp_map_base + (cur_pic_buf_id * ps_codec->u4_num_8x8_blks);
1357
0
            ps_codec->as_buf_id_info_map[cur_pic_buf_id].pu1_cu_type_map =
1358
0
                ps_codec->pu1_cu_type_map_base + (cur_pic_buf_id * ps_codec->u4_num_8x8_blks);
1359
0
            memset(ps_codec->as_buf_id_info_map[cur_pic_buf_id].pu1_qp_map,
1360
0
                0, ps_codec->u4_num_8x8_blks);
1361
0
            memset(ps_codec->as_buf_id_info_map[cur_pic_buf_id].pu1_qp_map,
1362
0
                0, ps_codec->u4_num_8x8_blks);
1363
0
        }
1364
1365
0
        ps_codec->s_parse.s_deblk_ctxt.pu1_cur_pic_luma = pu1_cur_pic_luma;
1366
0
        ps_codec->s_parse.s_deblk_ctxt.pu1_cur_pic_chroma = pu1_cur_pic_chroma;
1367
1368
0
        ps_codec->s_parse.s_sao_ctxt.pu1_cur_pic_luma = pu1_cur_pic_luma;
1369
0
        ps_codec->s_parse.s_sao_ctxt.pu1_cur_pic_chroma = pu1_cur_pic_chroma;
1370
0
    }
1371
    /* Since any input bitstream buffer that contains slice data will be sent to output(even in
1372
     * case of error, this buffer is added to display queue and next buffer in the display queue
1373
     * will be returned as the display buffer.
1374
     * Note: If format conversion (or frame copy) is used and is scheduled
1375
     * in a different thread then it has to check if the processing for the current row is complete before
1376
     * it copies/converts a given row. In case of low delay or in case of B pictures, current frame being decoded has to be
1377
     * returned, which requires a status check to ensure that the current row is reconstructed before copying.
1378
     */
1379
    /* Add current picture to display manager */
1380
0
    {
1381
0
        WORD32 abs_poc;
1382
0
        slice_header_t *ps_slice_hdr;
1383
0
        ps_slice_hdr = ps_codec->s_parse.ps_slice_hdr;
1384
0
        abs_poc = ps_slice_hdr->i4_abs_pic_order_cnt;
1385
0
        ihevc_disp_mgr_add((disp_mgr_t *)ps_codec->pv_disp_buf_mgr,
1386
0
                           ps_codec->as_process[0].i4_cur_pic_buf_id,
1387
0
                           abs_poc,
1388
0
                           ps_codec->as_process[0].ps_cur_pic);
1389
0
    }
1390
0
    ps_codec->ps_disp_buf = NULL;
1391
    /* Get picture to be displayed if number of pictures decoded is more than max allowed reorder */
1392
    /* Since the current will be decoded, check is fore >= instead of > */
1393
0
    if(((WORD32)(ps_codec->u4_pic_cnt - ps_codec->u4_disp_cnt) >= ps_sps->ai1_sps_max_num_reorder_pics[ps_sps->i1_sps_max_sub_layers - 1]) ||
1394
0
       (ps_codec->e_frm_out_mode == IVD_DECODE_FRAME_OUT))
1395
1396
0
    {
1397
0
        ps_codec->ps_disp_buf = (pic_buf_t *)ihevc_disp_mgr_get((disp_mgr_t *)ps_codec->pv_disp_buf_mgr, &ps_codec->i4_disp_buf_id);
1398
0
        ps_codec->u4_disp_cnt++;
1399
0
    }
1400
1401
0
    ps_codec->s_fmt_conv.i4_cur_row = 0;
1402
    /* Set number of rows to be processed at a time */
1403
0
    ps_codec->s_fmt_conv.i4_num_rows = 4;
1404
1405
0
    if(ps_codec->u4_enable_fmt_conv_ahead && (ps_codec->i4_num_cores > 1))
1406
0
    {
1407
0
        process_ctxt_t *ps_proc;
1408
1409
        /* i4_num_cores - 1 contexts are currently being used by other threads */
1410
0
        ps_proc = &ps_codec->as_process[ps_codec->i4_num_cores - 1];
1411
1412
        /* If the frame being decoded and displayed are different, schedule format conversion jobs
1413
         * this will keep the proc threads busy and lets parse thread decode few CTBs ahead
1414
         * If the frame being decoded and displayed are same, then format conversion is scheduled later.
1415
         */
1416
0
        if((ps_codec->ps_disp_buf) && (ps_codec->i4_disp_buf_id != ps_proc->i4_cur_pic_buf_id) &&
1417
0
           ((0 == ps_codec->i4_share_disp_buf) || (IV_YUV_420P == ps_codec->e_chroma_fmt)))
1418
0
        {
1419
1420
0
            for(i = 0; i < ps_sps->i2_pic_ht_in_ctb; i++)
1421
0
            {
1422
0
                proc_job_t s_job;
1423
0
                IHEVCD_ERROR_T ret;
1424
0
                s_job.i4_cmd = CMD_FMTCONV;
1425
0
                s_job.i2_ctb_cnt = 0;
1426
0
                s_job.i2_ctb_x = 0;
1427
0
                s_job.i2_ctb_y = i;
1428
0
                s_job.i2_slice_idx = 0;
1429
0
                s_job.i4_tu_coeff_data_ofst = 0;
1430
0
                ret = ihevcd_jobq_queue((jobq_t *)ps_codec->s_parse.pv_proc_jobq,
1431
0
                                        &s_job, sizeof(proc_job_t), 1);
1432
0
                if(ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS)
1433
0
                    return ret;
1434
0
            }
1435
0
        }
1436
0
    }
1437
1438
    /* If parse_pic_init is called, then slice data is present in the input bitstrea stream */
1439
0
    ps_codec->i4_pic_present = 1;
1440
1441
0
    return ret;
1442
0
}
1443
1444