Coverage Report

Created: 2026-06-13 06:22

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