ihevcd_utils.c revision 063ce60457496a8ccac95f723ac71e364f3405bb
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 */
80mv_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*/
102WORD32 ihevcd_get_lvl_idx(WORD32 level)
103{
104    WORD32 lvl_idx = 0;
105
106    if(level < IHEVC_LEVEL_20)
107    {
108        lvl_idx = 0;
109    }
110    else if(level >= IHEVC_LEVEL_20 && level < IHEVC_LEVEL_21)
111    {
112        lvl_idx = 1;
113    }
114    else if(level >= IHEVC_LEVEL_21 && level < IHEVC_LEVEL_30)
115    {
116        lvl_idx = 2;
117    }
118    else if(level >= IHEVC_LEVEL_30 && level < IHEVC_LEVEL_31)
119    {
120        lvl_idx = 3;
121    }
122    else if(level >= IHEVC_LEVEL_31 && level < IHEVC_LEVEL_40)
123    {
124        lvl_idx = 4;
125    }
126    else if(level >= IHEVC_LEVEL_40 && level < IHEVC_LEVEL_41)
127    {
128        lvl_idx = 5;
129    }
130    else if(level >= IHEVC_LEVEL_41 && level < IHEVC_LEVEL_50)
131    {
132        lvl_idx = 6;
133    }
134    else if(level >= IHEVC_LEVEL_50 && level < IHEVC_LEVEL_51)
135    {
136        lvl_idx = 7;
137    }
138    else if(level >= IHEVC_LEVEL_51 && level < IHEVC_LEVEL_52)
139    {
140        lvl_idx = 8;
141    }
142    else if(level >= IHEVC_LEVEL_52 && level < IHEVC_LEVEL_60)
143    {
144        lvl_idx = 9;
145    }
146    else if(level >= IHEVC_LEVEL_60 && level < IHEVC_LEVEL_61)
147    {
148        lvl_idx = 10;
149    }
150    else if(level >= IHEVC_LEVEL_61 && level < IHEVC_LEVEL_62)
151    {
152        lvl_idx = 11;
153    }
154    else if(level >= IHEVC_LEVEL_62)
155    {
156        lvl_idx = 12;
157    }
158
159    return (lvl_idx);
160}
161
162/**
163*******************************************************************************
164*
165* @brief
166*  Used to get DPB size for a given level, and number of luma samples
167*
168* @par Description:
169*  For given width, height and level number of max_dpb_size is computed as per
170*  Annex A.4.1
171*
172* @param[in] level
173*  Level of the stream
174*
175* @param[in] pic_size
176*  Width * Height
177*
178* @returns  Number of buffers in DPB
179*
180* @remarks
181*
182*
183*******************************************************************************
184*/
185WORD32 ihevcd_get_dpb_size(WORD32 level, WORD32 pic_size)
186{
187
188    WORD32 max_luma_samples;
189
190    WORD32 max_dpb_size;
191    WORD32 lvl_idx = ihevcd_get_lvl_idx(level);
192    max_luma_samples = gai4_ihevc_max_luma_pic_size[lvl_idx];
193
194
195
196    if(pic_size <= (max_luma_samples >> 2))
197    {
198        max_dpb_size = MIN(4 * MAX_DPB_PIC_BUF, 16);
199    }
200    else if(pic_size <= (max_luma_samples >> 1))
201    {
202        max_dpb_size = MIN(2 * MAX_DPB_PIC_BUF, 16);
203    }
204    else if(pic_size <= ((3 * max_luma_samples) >> 2))
205    {
206        max_dpb_size = MIN((4 * MAX_DPB_PIC_BUF) / 3, 16);
207    }
208    else
209    {
210        max_dpb_size = MAX_DPB_PIC_BUF;
211    }
212
213    return max_dpb_size;
214}
215/**
216*******************************************************************************
217*
218* @brief
219*  Used to get reference picture buffer size for a given level and
220*  and padding used
221*
222* @par Description:
223*  Used to get reference picture buffer size for a given level and padding used
224*  Each picture is padded on all four sides
225*
226* @param[in] pic_size
227*  Mumber of luma samples (Width * Height)
228*
229* @param[in] level
230*  Level
231*
232* @param[in] horz_pad
233*  Total padding used in horizontal direction
234*
235* @param[in] vert_pad
236*  Total padding used in vertical direction
237*
238* @returns  Total picture buffer size
239*
240* @remarks
241*
242*
243*******************************************************************************
244*/
245WORD32 ihevcd_get_total_pic_buf_size(WORD32 pic_size,
246                                     WORD32 level,
247                                     WORD32 horz_pad,
248                                     WORD32 vert_pad,
249                                     WORD32 init_num_bufs,
250                                     WORD32 init_extra_bufs,
251                                     WORD32 chroma_only)
252{
253    WORD32 size;
254    WORD32 num_luma_samples;
255    WORD32 lvl_idx;
256    WORD32 max_wd, min_ht;
257    WORD32 max_dpb_size;
258    WORD32 num_samples;
259    WORD32 max_num_bufs;
260    WORD32 pad = MAX(horz_pad, vert_pad);
261
262
263    /* Get maximum number of buffers for the current picture size */
264    max_dpb_size = ihevcd_get_dpb_size(level, pic_size);
265
266
267    max_num_bufs = (2 * max_dpb_size + 1);
268    /* If num_ref_frames and num_reorder_frmaes is specified
269     * Use minimum value
270     */
271    max_num_bufs = MIN(max_num_bufs, init_num_bufs);
272
273    /*
274     * Add extra buffers if required
275     */
276    max_num_bufs += init_extra_bufs;
277    max_num_bufs = MIN(max_num_bufs, BUF_MGR_MAX_CNT);
278
279    /* Get level index */
280    lvl_idx = ihevcd_get_lvl_idx(level);
281
282
283    /* Maximum width of luma samples in a picture at given level */
284    max_wd = ALIGN64(gai4_ihevc_max_wd_ht[lvl_idx]);
285
286    /* Minimum height of luma samples in a picture at given level */
287    min_ht = ALIGN64(gai4_ihevc_min_wd_ht[lvl_idx]);
288
289    /* Use max_wd and min_ht to get maximum number of luma samples for given level */
290    /* Because max_wd and min_ht are aligned to 64, product will be higher than the
291     * value given by the spec for a given level
292     */
293    num_luma_samples = max_wd * min_ht;
294
295    /* Allocation is required for
296     * (Wd + horz_pad) * (Ht + vert_pad) * (2 * max_dpb_size + 1)
297     *
298     * Above expanded as
299     * ((Wd * Ht) + (horz_pad * vert_pad) + Wd * vert_pad + Ht * horz_pad) * (2 * max_dpb_size + 1)
300     * (Wd * Ht) * (2 * max_dpb_size + 1) + ((horz_pad * vert_pad) + Wd * vert_pad + Ht * horz_pad) * (2 * max_dpb_size + 1)
301     * Now  max_dpb_size increases with smaller Wd and Ht, but Wd * ht * max_dpb_size will still be lesser or equal to max_wd * max_ht * dpb_size
302     *
303     * In the above equation (Wd * Ht) * (2 * max_dpb_size + 1) is accounted by using num_samples * (2 * max_dpb_size + 1) below
304     *
305     * For the padded area use MAX(horz_pad, vert_pad) as pad
306     * ((pad * pad) + pad * (Wd + Ht)) * (2 * max_dpb_size + 1) has to accounted from the above for padding
307     *
308     * Since Width and Height can change worst Wd + Ht is when One of the dimensions is max and other is min
309     * So use max_wd and min_ht
310     */
311
312    /* Account for padding area */
313
314    num_luma_samples += (pad * pad) + pad * (max_wd + min_ht);
315
316    /* Account for chroma */
317    if(0 == chroma_only)
318        num_samples = num_luma_samples * 3 / 2;
319    else
320        num_samples = num_luma_samples / 2;
321
322    /* Number of bytes in reference pictures */
323    size = num_samples * max_num_bufs;
324
325
326    return size;
327}
328/**
329*******************************************************************************
330*
331* @brief
332*  Used to get MV bank size for a given number of luma samples
333*
334* @par Description:
335*  For given number of luma samples  one MV bank size is computed
336*  Each MV bank includes pu_map and pu_t for all the min PUs(4x4) in a picture
337*
338* @param[in] num_luma_samples
339*  Max number of luma pixels in the frame
340*
341* @returns  Total MV Bank size
342*
343* @remarks
344*
345*
346*******************************************************************************
347*/
348WORD32 ihevcd_get_pic_mv_bank_size(WORD32 num_luma_samples)
349{
350    WORD32 size;
351
352    WORD32 pic_size;
353
354    WORD32 mv_bank_size;
355    WORD32 num_pu;
356    WORD32 num_ctb;
357    pic_size = num_luma_samples;
358
359
360    num_pu = pic_size / (MIN_PU_SIZE * MIN_PU_SIZE);
361    num_ctb = pic_size / (MIN_CTB_SIZE * MIN_CTB_SIZE);
362
363    mv_bank_size = 0;
364
365    /* Size for storing pu_t start index each CTB */
366    /* One extra entry is needed to compute number of PUs in the last CTB */
367    mv_bank_size += (num_ctb + 1) * sizeof(WORD32);
368
369    /* Size for pu_map */
370    mv_bank_size += num_pu;
371
372    /* Size for storing pu_t for each PU */
373    mv_bank_size += num_pu * sizeof(pu_t);
374
375    /* Size for storing slice_idx for each CTB */
376    mv_bank_size += ALIGN4(num_ctb * sizeof(UWORD16));
377
378    size =  mv_bank_size;
379    return size;
380}
381/**
382*******************************************************************************
383*
384* @brief
385*  Used to get TU data size for a given number luma samples
386*
387* @par Description:
388*  For a given number of luma samples TU data size is computed
389*  Each TU data includes tu_map and tu_t and coeff data for all
390*  the min TUs(4x4) in given CTB
391*
392* @param[in] num_luma_samples
393*  Number of 64 x 64 CTBs for which TU data has to be allocated.
394*
395* @returns  Total TU data size
396*
397* @remarks Assumption is num_luma_samples will be at least
398* 64 x 64 to handle CTB of size 64 x 64. Can be frame size as well
399*
400*******************************************************************************
401*/
402WORD32 ihevcd_get_tu_data_size(WORD32 num_luma_samples)
403{
404
405
406    WORD32 tu_data_size;
407    WORD32 num_ctb;
408    WORD32 num_luma_tu, num_chroma_tu, num_tu;
409    num_ctb = num_luma_samples / (MIN_CTB_SIZE * MIN_CTB_SIZE);
410
411    num_luma_tu = num_luma_samples / (MIN_TU_SIZE * MIN_TU_SIZE);
412    num_chroma_tu = num_luma_tu >> 1;
413
414    num_tu = num_luma_tu + num_chroma_tu;
415    tu_data_size = 0;
416
417    /* Size for storing tu_t start index each CTB */
418    /* One extra entry is needed to compute number of TUs in the last CTB */
419    tu_data_size += (num_ctb + 1) * sizeof(WORD32);
420
421    /* Size for storing tu map */
422    tu_data_size += num_luma_tu * sizeof(UWORD8);
423
424    /* Size for storing tu_t for each TU */
425    tu_data_size += num_tu * sizeof(tu_t);
426
427    /* Size for storing number of coded subblocks and scan_idx for each TU */
428    tu_data_size += num_tu * (sizeof(WORD8) + sizeof(WORD8));
429
430    /* Size for storing coeff data for each TU */
431    tu_data_size += num_tu * sizeof(tu_sblk_coeff_data_t);
432
433
434    return tu_data_size;
435}
436
437
438WORD32 ihevcd_nctb_cnt(codec_t *ps_codec, sps_t *ps_sps)
439{
440    WORD32 nctb = 1;
441    UNUSED(ps_codec);
442    //TODO: Currently set to 1
443    /* If CTB size is less than 32 x 32 then set nCTB as 4 */
444    if(ps_sps->i1_log2_ctb_size < 5)
445        nctb = 1;
446
447    return nctb;
448}
449
450IHEVCD_ERROR_T ihevcd_get_tile_pos(pps_t *ps_pps,
451                                   sps_t *ps_sps,
452                                   WORD32 ctb_x,
453                                   WORD32 ctb_y,
454                                   WORD32 *pi4_ctb_tile_x,
455                                   WORD32 *pi4_ctb_tile_y,
456                                   WORD32 *pi4_tile_idx)
457{
458
459    tile_t *ps_tile_tmp;
460    WORD32 i;
461    WORD32 tile_row, tile_col;
462
463    if(ctb_x < 0 || ctb_y < 0)
464    {
465        *pi4_ctb_tile_x = 0;
466        *pi4_ctb_tile_y = 0;
467        *pi4_tile_idx = 0;
468
469        return (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
470    }
471
472    tile_row = 0;
473    tile_col = 0;
474    ps_tile_tmp = ps_pps->ps_tile;
475    if(0 == ps_pps->i1_tiles_enabled_flag)
476    {
477        *pi4_ctb_tile_x = ctb_x;
478        *pi4_ctb_tile_y = ctb_y;
479        *pi4_tile_idx = 0;
480    }
481    else
482    {
483        for(i = 0; i < ps_pps->i1_num_tile_columns; i++)
484        {
485            WORD16 next_tile_ctb_x;
486            ps_tile_tmp = ps_pps->ps_tile + i; //* ps_pps->i1_num_tile_rows;
487            if((ps_pps->i1_num_tile_columns - 1) == i)
488            {
489                next_tile_ctb_x = ps_sps->i2_pic_wd_in_ctb;
490            }
491            else
492            {
493                tile_t *ps_tile_next_tmp;
494                ps_tile_next_tmp = ps_pps->ps_tile + i + 1;
495                next_tile_ctb_x = ps_tile_next_tmp->u1_pos_x;
496            }
497            if((ctb_x >= ps_tile_tmp->u1_pos_x) && (ctb_x < next_tile_ctb_x))
498            {
499                tile_col = i;
500                break;
501            }
502        }
503        *pi4_ctb_tile_x = ctb_x - ps_tile_tmp->u1_pos_x;
504
505        for(i = 0; i < ps_pps->i1_num_tile_rows; i++)
506        {
507            WORD16 next_tile_ctb_y;
508            ps_tile_tmp = ps_pps->ps_tile + i * ps_pps->i1_num_tile_columns;
509            if((ps_pps->i1_num_tile_rows - 1) == i)
510            {
511                next_tile_ctb_y = ps_sps->i2_pic_ht_in_ctb;
512            }
513            else
514            {
515                tile_t *ps_tile_next_tmp;
516                ps_tile_next_tmp = ps_pps->ps_tile + ((i + 1) * ps_pps->i1_num_tile_columns);
517                next_tile_ctb_y = ps_tile_next_tmp->u1_pos_y;
518            }
519            if((ctb_y >= ps_tile_tmp->u1_pos_y) && (ctb_y < next_tile_ctb_y))
520            {
521                tile_row = i;
522                break;
523            }
524
525        }
526        *pi4_ctb_tile_y = ctb_y - ps_tile_tmp->u1_pos_y;
527        *pi4_tile_idx = tile_row * ps_pps->i1_num_tile_columns
528                        + tile_col;
529    }
530    return (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
531}
532/**
533*******************************************************************************
534*
535* @brief
536*  Function to initialize ps_pic_buf structs add pic buffers to
537*  buffer manager in case of non-shared mode
538*
539* @par Description:
540*  Function to initialize ps_pic_buf structs add pic buffers to
541*  buffer manager in case of non-shared mode
542*  To be called once per stream or for every reset
543*
544* @param[in] ps_codec
545*  Pointer to codec context
546*
547* @returns  Error from IHEVCD_ERROR_T
548*
549* @remarks
550*
551*
552*******************************************************************************
553*/
554IHEVCD_ERROR_T ihevcd_pic_buf_mgr_add_bufs(codec_t *ps_codec)
555{
556    IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
557    WORD32 i;
558    WORD32 max_dpb_size;
559    sps_t *ps_sps;
560    UWORD8 *pu1_buf;
561    pic_buf_t *ps_pic_buf;
562    WORD32 pic_buf_size_allocated;
563
564    WORD32 max_num_bufs;
565    WORD32 pic_size;
566    WORD32 level;
567
568
569    /* Initialize MV Bank buffer manager */
570    ps_sps = ps_codec->s_parse.ps_sps;
571
572    pic_size = ALIGN64(ps_sps->i2_pic_width_in_luma_samples) *
573                    ALIGN64(ps_sps->i2_pic_height_in_luma_samples);
574
575
576    /* Compute the number of MB Bank buffers needed */
577    level = ps_codec->i4_init_level;
578    max_dpb_size = ihevcd_get_dpb_size(level, pic_size);
579    /* Allocate twice dpb size to handle worst case reorder without returning more
580     * than one output per call
581     */
582    max_dpb_size *= 2;
583    /* Allocate one extra picture to handle current frame
584     * In case of asynchronous parsing and processing, number of buffers should increase here
585     * based on when parsing and processing threads are synchronized
586     */
587    max_dpb_size++;
588
589    /* If num_ref_frames and num_reorder_frmaes is specified
590     * Use minimum value
591     */
592    max_num_bufs = MIN(max_dpb_size, (ps_codec->i4_init_num_ref + ps_codec->i4_init_num_reorder + 1));
593
594
595    pu1_buf = (UWORD8 *)ps_codec->ps_pic_buf;
596
597    ps_pic_buf = (pic_buf_t *)ps_codec->ps_pic_buf;
598
599    pu1_buf += BUF_MGR_MAX_CNT  * sizeof(pic_buf_t);
600
601    /* In case of non-shared mode, add picture buffers to buffer manager
602     * In case of shared mode buffers are added in the run-time
603     */
604    if(0 == ps_codec->i4_share_disp_buf)
605    {
606        WORD32 buf_ret;
607        WORD32 luma_samples;
608        WORD32 chroma_samples;
609        pic_buf_size_allocated = ps_codec->i4_total_pic_buf_size -
610                        BUF_MGR_MAX_CNT * sizeof(pic_buf_t);
611
612        luma_samples = (ps_codec->i4_strd) *
613                        (ps_sps->i2_pic_height_in_luma_samples + PAD_HT);
614
615        chroma_samples = luma_samples / 2;
616
617        /* Try to add as many buffers as possible since memory is already allocated */
618        /* If the number of buffers that can be added is less than max_num_bufs
619         * return with an error.
620         */
621        for(i = 0; i < (2 * MAX_DPB_SIZE) + 1; i++)
622        {
623            pic_buf_size_allocated -= (luma_samples + chroma_samples);
624
625            if(pic_buf_size_allocated < 0)
626            {
627                if(i < max_num_bufs)
628                {
629                    ps_codec->s_parse.i4_error_code = IHEVCD_INSUFFICIENT_MEM_PICBUF;
630                    return IHEVCD_INSUFFICIENT_MEM_PICBUF;
631                }
632                break;
633            }
634
635            ps_pic_buf->pu1_luma = pu1_buf + ps_codec->i4_strd * PAD_TOP + PAD_LEFT;
636            pu1_buf += luma_samples;
637
638            ps_pic_buf->pu1_chroma = pu1_buf + ps_codec->i4_strd * (PAD_TOP / 2) + PAD_LEFT;
639            pu1_buf += chroma_samples;
640
641            buf_ret = ihevc_buf_mgr_add((buf_mgr_t *)ps_codec->pv_pic_buf_mgr, ps_pic_buf, i);
642
643            if(0 != buf_ret)
644            {
645                ps_codec->s_parse.i4_error_code = IHEVCD_BUF_MGR_ERROR;
646                return IHEVCD_BUF_MGR_ERROR;
647            }
648            ps_pic_buf++;
649        }
650    }
651
652    return ret;
653}
654/**
655*******************************************************************************
656*
657* @brief
658*  Function to add buffers to MV Bank buffer manager
659*
660* @par Description:
661*  Function to add buffers to MV Bank buffer manager
662*  To be called once per stream or for every reset
663*
664* @param[in] ps_codec
665*  Pointer to codec context
666*
667* @returns  Error from IHEVCD_ERROR_T
668*
669* @remarks
670*
671*
672*******************************************************************************
673*/
674IHEVCD_ERROR_T ihevcd_mv_buf_mgr_add_bufs(codec_t *ps_codec)
675{
676    IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
677    WORD32 i;
678    WORD32 max_dpb_size;
679    WORD32 mv_bank_size_allocated;
680    WORD32 pic_mv_bank_size;
681    WORD32 level;
682    sps_t *ps_sps;
683    UWORD8 *pu1_buf;
684    mv_buf_t *ps_mv_buf;
685
686
687    /* Initialize MV Bank buffer manager */
688    ps_sps = ps_codec->s_parse.ps_sps;
689
690
691    /* Compute the number of MB Bank buffers needed */
692    level = ps_codec->i4_init_level;
693    max_dpb_size = ihevcd_get_dpb_size(level,
694                                       ALIGN64(ps_sps->i2_pic_width_in_luma_samples) *
695                                       ALIGN64(ps_sps->i2_pic_height_in_luma_samples));
696
697    /* Allocate one extra MV Bank to handle current frame
698     * In case of asynchronous parsing and processing, number of buffers should increase here
699     * based on when parsing and processing threads are synchronized
700     */
701    max_dpb_size++;
702
703    pu1_buf = (UWORD8 *)ps_codec->pv_mv_bank_buf_base;
704
705    ps_mv_buf = (mv_buf_t *)pu1_buf;
706    pu1_buf += (MAX_DPB_SIZE + 1) * sizeof(mv_buf_t);
707    ps_codec->ps_mv_buf = ps_mv_buf;
708    mv_bank_size_allocated = ps_codec->i4_total_mv_bank_size - (MAX_DPB_SIZE + 1) * sizeof(mv_buf_t);
709
710    /* Compute MV bank size per picture */
711    pic_mv_bank_size = ihevcd_get_pic_mv_bank_size(ALIGN64(ps_sps->i2_pic_width_in_luma_samples) *
712                                                   ALIGN64(ps_sps->i2_pic_height_in_luma_samples));
713
714    for(i = 0; i < max_dpb_size; i++)
715    {
716        WORD32 buf_ret;
717        WORD32 num_pu;
718        WORD32 num_ctb;
719        WORD32 pic_size;
720        pic_size = ALIGN64(ps_sps->i2_pic_width_in_luma_samples) *
721                        ALIGN64(ps_sps->i2_pic_height_in_luma_samples);
722
723
724        num_pu = pic_size / (MIN_PU_SIZE * MIN_PU_SIZE);
725        num_ctb = pic_size / (MIN_CTB_SIZE * MIN_CTB_SIZE);
726
727
728        mv_bank_size_allocated -= pic_mv_bank_size;
729
730        if(mv_bank_size_allocated < 0)
731        {
732            ps_codec->s_parse.i4_error_code = IHEVCD_INSUFFICIENT_MEM_MVBANK;
733            return IHEVCD_INSUFFICIENT_MEM_MVBANK;
734        }
735
736        ps_mv_buf->pu4_pic_pu_idx = (UWORD32 *)pu1_buf;
737        pu1_buf += (num_ctb + 1) * sizeof(WORD32);
738
739        ps_mv_buf->pu1_pic_pu_map = pu1_buf;
740        pu1_buf += num_pu;
741
742        ps_mv_buf->pu1_pic_slice_map = (UWORD16 *)pu1_buf;
743        pu1_buf += ALIGN4(num_ctb * sizeof(UWORD16));
744
745        ps_mv_buf->ps_pic_pu = (pu_t *)pu1_buf;
746        pu1_buf += num_pu * sizeof(pu_t);
747
748        buf_ret = ihevc_buf_mgr_add((buf_mgr_t *)ps_codec->pv_mv_buf_mgr, ps_mv_buf, i);
749
750        if(0 != buf_ret)
751        {
752            ps_codec->s_parse.i4_error_code = IHEVCD_BUF_MGR_ERROR;
753            return IHEVCD_BUF_MGR_ERROR;
754        }
755
756        ps_mv_buf++;
757
758    }
759    return ret;
760}
761/**
762*******************************************************************************
763*
764* @brief
765*  Picture level initializations required during parsing
766*
767* @par Description:
768*  Initialize picture level context variables during parsing Initialize mv
769* bank buffer manager in the first init call
770*
771* @param[in] ps_codec
772*  Pointer to codec context
773*
774* @returns  Error from IHEVCD_ERROR_T
775*
776* @remarks
777*
778*
779*******************************************************************************
780*/
781IHEVCD_ERROR_T ihevcd_parse_pic_init(codec_t *ps_codec)
782{
783    IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
784    mv_buf_t *ps_mv_buf;
785    sps_t *ps_sps;
786    WORD32 num_min_cu;
787    WORD32 cur_pic_buf_id;
788    WORD32 cur_mv_bank_buf_id;
789    pic_buf_t *ps_cur_pic;
790    slice_header_t *ps_slice_hdr;
791    UWORD8 *pu1_cur_pic_luma, *pu1_cur_pic_chroma;
792    WORD32 i;
793
794    ps_codec->s_parse.i4_error_code = IHEVCD_SUCCESS;
795    ps_sps = ps_codec->s_parse.ps_sps;
796    ps_slice_hdr = ps_codec->s_parse.ps_slice_hdr;
797    /* If parse_pic_init is called, then slice data is present in the input bitstrea stream */
798    ps_codec->i4_pic_present = 1;
799
800    /* Memset picture level intra map and transquant bypass map to zero */
801    num_min_cu = ((ps_sps->i2_pic_height_in_luma_samples + 7) / 8) * ((ps_sps->i2_pic_width_in_luma_samples + 63) / 64);
802    memset(ps_codec->s_parse.pu1_pic_intra_flag, 0, num_min_cu);
803    memset(ps_codec->s_parse.pu1_pic_no_loop_filter_flag, 0, num_min_cu);
804
805
806
807    if(0 == ps_codec->s_parse.i4_first_pic_init)
808    {
809        ret = ihevcd_mv_buf_mgr_add_bufs(ps_codec);
810        RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
811
812        ret = ihevcd_pic_buf_mgr_add_bufs(ps_codec);
813        RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
814
815        ps_codec->s_parse.i4_first_pic_init = 1;
816    }
817
818    /* Initialize all the slice headers' slice addresses to zero */
819    {
820        WORD32 slice_idx;
821        WORD32 slice_start_idx;
822
823        slice_start_idx = ps_codec->i4_slice_error ? 2 : 1;
824
825        for(slice_idx = slice_start_idx; slice_idx < MAX_SLICE_HDR_CNT; slice_idx++)
826        {
827            slice_header_t *ps_slice_hdr_tmp = ps_codec->ps_slice_hdr_base + slice_idx;
828            ps_slice_hdr_tmp->i2_ctb_x = -1;
829            ps_slice_hdr_tmp->i2_ctb_y = -1;
830
831        }
832    }
833
834    /* Get free MV Bank to hold current picture's motion vector data */
835    {
836        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);
837
838        /* If there are no free buffers then return with an error code.
839         * If the buffer is to be freed by another thread , change the
840         * following to call thread yield and wait for buffer to be freed
841         */
842        if(NULL == ps_mv_buf)
843        {
844            ps_codec->s_parse.i4_error_code = IHEVCD_NO_FREE_MVBANK;
845            ps_codec->i4_error_code = IHEVCD_NO_FREE_MVBANK;
846            return IHEVCD_NO_FREE_MVBANK;
847        }
848
849        ps_codec->s_parse.ps_cur_mv_buf = ps_mv_buf;
850        /* Set current ABS poc to ps_mv_buf, so that while freeing a reference buffer
851         * corresponding mv buffer can be found by looping through ps_codec->ps_mv_buf array
852         * and getting a buffer id to free
853         */
854        ps_mv_buf->i4_abs_poc = ps_slice_hdr->i4_abs_pic_order_cnt;
855    }
856
857    /* Get free picture buffer to hold current picture recon data */
858    /* TODO: For asynchronous api the following initializations related to picture
859     * buffer should be moved to processing side
860     */
861    {
862
863        UWORD8 *pu1_buf;
864        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);
865
866        /* If there are no free buffers then return with an error code.
867         * TODO: If the buffer is to be freed by another thread , change the
868         * following to call thread yield and wait for buffer to be freed
869         */
870        if(NULL == ps_cur_pic)
871        {
872            ps_codec->s_parse.i4_error_code = IHEVCD_NO_FREE_PICBUF;
873            ps_codec->i4_error_code = IHEVCD_NO_FREE_PICBUF;
874            return IHEVCD_NO_FREE_PICBUF;
875        }
876
877        /* Store input timestamp sent with input buffer */
878        ps_cur_pic->u4_ts = ps_codec->u4_ts;
879        ps_cur_pic->i4_abs_poc = ps_slice_hdr->i4_abs_pic_order_cnt;
880        ps_cur_pic->i4_poc_lsb = ps_slice_hdr->i4_pic_order_cnt_lsb;
881        pu1_buf = ps_cur_pic->pu1_luma;
882        pu1_cur_pic_luma = pu1_buf;
883
884        pu1_buf = ps_cur_pic->pu1_chroma;
885
886        pu1_cur_pic_chroma = pu1_buf;
887    }
888
889    if(0 == ps_codec->u4_pic_cnt)
890    {
891        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);
892        memset(ps_cur_pic->pu1_chroma, 128, (ps_sps->i2_pic_width_in_luma_samples + PAD_WD) * ps_sps->i2_pic_height_in_luma_samples / 2);
893    }
894
895    /* Fill the remaining entries of the reference lists with the nearest POC
896     * This is done to handle cases where there is a corruption in the reference index */
897    {
898        pic_buf_t *ps_pic_buf_ref;
899        mv_buf_t *ps_mv_buf_ref;
900        WORD32 r_idx;
901        dpb_mgr_t *ps_dpb_mgr = (dpb_mgr_t *)ps_codec->pv_dpb_mgr;
902        buf_mgr_t *ps_mv_buf_mgr = (buf_mgr_t *)ps_codec->pv_mv_buf_mgr;
903
904        ps_pic_buf_ref = ihevc_dpb_mgr_get_ref_by_nearest_poc(ps_dpb_mgr, ps_slice_hdr->i4_abs_pic_order_cnt);
905        if(NULL == ps_pic_buf_ref)
906        {
907            WORD32 size;
908
909            WORD32 num_pu;
910            WORD32 num_ctb;
911            WORD32 pic_size;
912            /* In case current mv buffer itself is being used as reference mv buffer for colocated
913             * calculations, then memset all the buffers to zero.
914             */
915            pic_size = ALIGN64(ps_sps->i2_pic_width_in_luma_samples) *
916                            ALIGN64(ps_sps->i2_pic_height_in_luma_samples);
917
918            num_pu = pic_size / (MIN_PU_SIZE * MIN_PU_SIZE);
919            num_ctb = pic_size / (MIN_CTB_SIZE * MIN_CTB_SIZE);
920
921            memset(ps_mv_buf->ai4_l0_collocated_poc, 0, sizeof(ps_mv_buf->ai4_l0_collocated_poc));
922            memset(ps_mv_buf->ai1_l0_collocated_poc_lt, 0, sizeof(ps_mv_buf->ai1_l0_collocated_poc_lt));
923            memset(ps_mv_buf->ai4_l1_collocated_poc, 0, sizeof(ps_mv_buf->ai4_l1_collocated_poc));
924            memset(ps_mv_buf->ai1_l1_collocated_poc_lt, 0, sizeof(ps_mv_buf->ai1_l1_collocated_poc_lt));
925
926            size = (num_ctb + 1) * sizeof(WORD32);
927            memset(ps_mv_buf->pu4_pic_pu_idx, 0, size);
928
929            size = num_pu;
930            memset(ps_mv_buf->pu1_pic_pu_map, 0, size);
931            size = ALIGN4(num_ctb * sizeof(UWORD16));
932            memset(ps_mv_buf->pu1_pic_slice_map, 0, size);
933            size = num_pu * sizeof(pu_t);
934            memset(ps_mv_buf->ps_pic_pu, 0, size);
935
936            ps_pic_buf_ref = ps_cur_pic;
937            ps_mv_buf_ref = ps_mv_buf;
938        }
939        else
940        {
941            ps_mv_buf_ref = ihevcd_mv_mgr_get_poc(ps_mv_buf_mgr, ps_pic_buf_ref->i4_abs_poc);
942        }
943
944        for(r_idx = 0; r_idx < ps_slice_hdr->i1_num_ref_idx_l0_active; r_idx++)
945        {
946            if(NULL == ps_slice_hdr->as_ref_pic_list0[r_idx].pv_pic_buf)
947            {
948                ps_slice_hdr->as_ref_pic_list0[r_idx].pv_pic_buf = (void *)ps_pic_buf_ref;
949                ps_slice_hdr->as_ref_pic_list0[r_idx].pv_mv_buf = (void *)ps_mv_buf_ref;
950            }
951        }
952
953        for(r_idx = ps_slice_hdr->i1_num_ref_idx_l0_active; r_idx < MAX_DPB_SIZE; r_idx++)
954        {
955            ps_slice_hdr->as_ref_pic_list0[r_idx].pv_pic_buf = (void *)ps_pic_buf_ref;
956            ps_slice_hdr->as_ref_pic_list0[r_idx].pv_mv_buf = (void *)ps_mv_buf_ref;
957        }
958
959        for(r_idx = 0; r_idx < ps_slice_hdr->i1_num_ref_idx_l1_active; r_idx++)
960        {
961            if(NULL == ps_slice_hdr->as_ref_pic_list1[r_idx].pv_pic_buf)
962            {
963                ps_slice_hdr->as_ref_pic_list1[r_idx].pv_pic_buf = (void *)ps_pic_buf_ref;
964                ps_slice_hdr->as_ref_pic_list1[r_idx].pv_mv_buf = (void *)ps_mv_buf_ref;
965            }
966        }
967
968        for(r_idx = ps_slice_hdr->i1_num_ref_idx_l1_active; r_idx < MAX_DPB_SIZE; r_idx++)
969        {
970            ps_slice_hdr->as_ref_pic_list1[r_idx].pv_pic_buf = (void *)ps_pic_buf_ref;
971            ps_slice_hdr->as_ref_pic_list1[r_idx].pv_mv_buf = (void *)ps_mv_buf_ref;
972        }
973    }
974
975
976    /* Reset the jobq to start of the jobq buffer */
977    ihevcd_jobq_reset((jobq_t *)ps_codec->pv_proc_jobq);
978
979    ps_codec->s_parse.i4_pic_pu_idx = 0;
980    ps_codec->s_parse.i4_pic_tu_idx = 0;
981
982    ps_codec->s_parse.pu1_pic_pu_map = ps_mv_buf->pu1_pic_pu_map;
983    ps_codec->s_parse.ps_pic_pu      = ps_mv_buf->ps_pic_pu;
984    ps_codec->s_parse.pu4_pic_pu_idx = ps_mv_buf->pu4_pic_pu_idx;
985    ps_codec->s_parse.pu1_slice_idx = (UWORD16 *)ps_mv_buf->pu1_pic_slice_map;
986    for(i = 0; i < MAX_PROCESS_THREADS; i++)
987    {
988        ps_codec->as_process[i].pu1_slice_idx = (UWORD16 *)ps_mv_buf->pu1_pic_slice_map;
989    }
990    ps_codec->s_parse.pu1_pu_map = ps_codec->s_parse.pu1_pic_pu_map;
991    ps_codec->s_parse.ps_pu = ps_codec->s_parse.ps_pic_pu;
992
993    {
994        UWORD8 *pu1_buf;
995        WORD32 ctb_luma_min_tu_cnt, ctb_chroma_min_tu_cnt, ctb_min_tu_cnt;
996        WORD32 pic_size;
997        WORD32 num_ctb;
998
999        pic_size = ALIGN64(ps_sps->i2_pic_width_in_luma_samples) *
1000                        ALIGN64(ps_sps->i2_pic_height_in_luma_samples);
1001
1002        ctb_luma_min_tu_cnt = pic_size / (MIN_TU_SIZE * MIN_TU_SIZE);
1003
1004        ctb_chroma_min_tu_cnt = ctb_luma_min_tu_cnt >> 1;
1005
1006        ctb_min_tu_cnt = ctb_luma_min_tu_cnt + ctb_chroma_min_tu_cnt;
1007
1008        num_ctb = pic_size / (MIN_CTB_SIZE * MIN_CTB_SIZE);
1009        pu1_buf  = (UWORD8 *)ps_codec->pv_tu_data;
1010        ps_codec->s_parse.pu4_pic_tu_idx = (UWORD32 *)pu1_buf;
1011        pu1_buf += (num_ctb + 1) * sizeof(WORD32);
1012
1013        ps_codec->s_parse.pu1_pic_tu_map = pu1_buf;
1014        pu1_buf += ctb_min_tu_cnt;
1015
1016        ps_codec->s_parse.ps_pic_tu = (tu_t *)pu1_buf;
1017        pu1_buf += ctb_min_tu_cnt * sizeof(tu_t);
1018
1019        ps_codec->s_parse.pv_pic_tu_coeff_data = pu1_buf;
1020
1021        ps_codec->s_parse.pu1_tu_map = ps_codec->s_parse.pu1_pic_tu_map;
1022        ps_codec->s_parse.ps_tu = ps_codec->s_parse.ps_pic_tu;
1023        ps_codec->s_parse.pv_tu_coeff_data = ps_codec->s_parse.pv_pic_tu_coeff_data;
1024    }
1025
1026    ps_codec->s_parse.s_bs_ctxt.ps_pic_pu = ps_codec->s_parse.ps_pic_pu;
1027    ps_codec->s_parse.s_bs_ctxt.pu4_pic_pu_idx = ps_codec->s_parse.pu4_pic_pu_idx;
1028    ps_codec->s_parse.s_bs_ctxt.pu4_pic_tu_idx = ps_codec->s_parse.pu4_pic_tu_idx;
1029
1030
1031    /* Set number of CTBs to be processed simultaneously */
1032    ps_codec->i4_proc_nctb = ihevcd_nctb_cnt(ps_codec, ps_sps);
1033
1034    /* Memset Parse Map and process map at the start of frame */
1035    //TODO: In case of asynchronous API proc_map can not be set to zero here
1036    {
1037        WORD32 num_ctb;
1038
1039        num_ctb = ps_sps->i4_pic_size_in_ctb;
1040
1041        memset(ps_codec->pu1_parse_map, 0, num_ctb);
1042
1043        memset(ps_codec->pu1_proc_map, 0, num_ctb);
1044    }
1045
1046
1047
1048    /* Initialize disp buf id to -1, this will be updated at the end of frame if there is
1049     * buffer to be displayed
1050     */
1051    ps_codec->i4_disp_buf_id = -1;
1052    ps_codec->ps_disp_buf = NULL;
1053
1054    ps_codec->i4_disable_deblk_pic  = 0;
1055    ps_codec->i4_disable_sao_pic    = 0;
1056    ps_codec->i4_fullpel_inter_pred = 0;
1057    ps_codec->i4_mv_frac_mask       = 0x7FFFFFFF;
1058
1059    /* If degrade is enabled, set the degrade flags appropriately */
1060    if(ps_codec->i4_degrade_type && ps_codec->i4_degrade_pics)
1061    {
1062        WORD32 degrade_pic;
1063        ps_codec->i4_degrade_pic_cnt++;
1064        degrade_pic = 0;
1065
1066        /* If degrade is to be done in all frames, then do not check further */
1067        switch(ps_codec->i4_degrade_pics)
1068        {
1069            case 4:
1070            {
1071                degrade_pic = 1;
1072                break;
1073            }
1074            case 3:
1075            {
1076                if(ps_slice_hdr->i1_slice_type != ISLICE)
1077                    degrade_pic = 1;
1078
1079                break;
1080            }
1081            case 2:
1082            {
1083
1084                /* If pic count hits non-degrade interval or it is an islice, then do not degrade */
1085                if((ps_slice_hdr->i1_slice_type != ISLICE) &&
1086                   (ps_codec->i4_degrade_pic_cnt != ps_codec->i4_nondegrade_interval))
1087                    degrade_pic = 1;
1088
1089                break;
1090            }
1091            case 1:
1092            {
1093                /* Check if the current picture is non-ref */
1094                if((ps_slice_hdr->i1_nal_unit_type < NAL_BLA_W_LP) &&
1095                   (ps_slice_hdr->i1_nal_unit_type % 2 == 0))
1096                {
1097                    degrade_pic = 1;
1098                }
1099                break;
1100            }
1101
1102
1103        }
1104        if(degrade_pic)
1105        {
1106            if(ps_codec->i4_degrade_type & 0x1)
1107                ps_codec->i4_disable_sao_pic = 1;
1108
1109            if(ps_codec->i4_degrade_type & 0x2)
1110                ps_codec->i4_disable_deblk_pic = 1;
1111
1112            /* MC degrading is done only for non-ref pictures */
1113            if((ps_slice_hdr->i1_nal_unit_type < NAL_BLA_W_LP) &&
1114               (ps_slice_hdr->i1_nal_unit_type % 2 == 0))
1115            {
1116                if(ps_codec->i4_degrade_type & 0x4)
1117                    ps_codec->i4_mv_frac_mask = 0;
1118
1119                if(ps_codec->i4_degrade_type & 0x8)
1120                    ps_codec->i4_mv_frac_mask = 0;
1121            }
1122        }
1123        else
1124            ps_codec->i4_degrade_pic_cnt = 0;
1125    }
1126
1127
1128    {
1129        WORD32 i;
1130        for(i = 0; i < MAX_PROCESS_THREADS; i++)
1131        {
1132            ps_codec->as_process[i].pu4_pic_pu_idx = ps_codec->s_parse.pu4_pic_pu_idx;
1133            ps_codec->as_process[i].ps_pic_pu = ps_codec->s_parse.ps_pic_pu;
1134            ps_codec->as_process[i].pu1_pic_pu_map = ps_codec->s_parse.pu1_pic_pu_map;
1135            ps_codec->as_process[i].pu4_pic_tu_idx = ps_codec->s_parse.pu4_pic_tu_idx;
1136            ps_codec->as_process[i].ps_pic_tu = ps_codec->s_parse.ps_pic_tu;
1137            ps_codec->as_process[i].pu1_pic_tu_map = ps_codec->s_parse.pu1_pic_tu_map;
1138            ps_codec->as_process[i].pv_pic_tu_coeff_data = ps_codec->s_parse.pv_pic_tu_coeff_data;
1139            ps_codec->as_process[i].i4_cur_mv_bank_buf_id = cur_mv_bank_buf_id;
1140            ps_codec->as_process[i].s_sao_ctxt.pu1_slice_idx = ps_codec->as_process[i].pu1_slice_idx;
1141            ps_codec->as_process[i].s_sao_ctxt.pu1_tile_idx = ps_codec->as_process[i].pu1_tile_idx;
1142
1143            /* TODO: For asynchronous api the following initializations related to picture
1144             * buffer should be moved to processing side
1145             */
1146            ps_codec->as_process[i].pu1_cur_pic_luma = pu1_cur_pic_luma;
1147            ps_codec->as_process[i].pu1_cur_pic_chroma = pu1_cur_pic_chroma;
1148            ps_codec->as_process[i].ps_cur_pic = ps_cur_pic;
1149            ps_codec->as_process[i].i4_cur_pic_buf_id = cur_pic_buf_id;
1150
1151            ps_codec->as_process[i].ps_out_buffer = ps_codec->ps_out_buffer;
1152            if(1 < ps_codec->i4_num_cores)
1153            {
1154                ps_codec->as_process[i].i4_check_parse_status = 1;
1155                ps_codec->as_process[i].i4_check_proc_status = 1;
1156            }
1157            else
1158            {
1159                ps_codec->as_process[i].i4_check_parse_status = 0;
1160                ps_codec->as_process[i].i4_check_proc_status = 0;
1161            }
1162            ps_codec->as_process[i].pu1_pic_intra_flag = ps_codec->s_parse.pu1_pic_intra_flag;
1163            ps_codec->as_process[i].pu1_pic_no_loop_filter_flag = ps_codec->s_parse.pu1_pic_no_loop_filter_flag;
1164            ps_codec->as_process[i].i4_init_done = 0;
1165
1166            ps_codec->as_process[i].s_bs_ctxt.pu4_pic_tu_idx = ps_codec->as_process[i].pu4_pic_tu_idx;
1167            ps_codec->as_process[i].s_bs_ctxt.pu4_pic_pu_idx = ps_codec->as_process[i].pu4_pic_pu_idx;
1168            ps_codec->as_process[i].s_bs_ctxt.ps_pic_pu = ps_codec->as_process[i].ps_pic_pu;
1169            ps_codec->as_process[i].s_deblk_ctxt.pu1_pic_no_loop_filter_flag = ps_codec->s_parse.pu1_pic_no_loop_filter_flag;
1170            ps_codec->as_process[i].s_deblk_ctxt.pu1_cur_pic_luma = pu1_cur_pic_luma;
1171            ps_codec->as_process[i].s_deblk_ctxt.pu1_cur_pic_chroma = pu1_cur_pic_chroma;
1172            ps_codec->as_process[i].s_sao_ctxt.pu1_pic_no_loop_filter_flag = ps_codec->s_parse.pu1_pic_no_loop_filter_flag;
1173            ps_codec->as_process[i].s_sao_ctxt.pu1_cur_pic_luma = pu1_cur_pic_luma;
1174            ps_codec->as_process[i].s_sao_ctxt.pu1_cur_pic_chroma = pu1_cur_pic_chroma;
1175            if(i < (ps_codec->i4_num_cores - 1))
1176            {
1177                ithread_create(ps_codec->apv_process_thread_handle[i], NULL,
1178                               (void *)ihevcd_process_thread,
1179                               (void *)&ps_codec->as_process[i]);
1180                ps_codec->ai4_process_thread_created[i] = 1;
1181            }
1182            else
1183            {
1184                ps_codec->ai4_process_thread_created[i] = 0;
1185            }
1186
1187        }
1188        ps_codec->s_parse.s_deblk_ctxt.pu1_cur_pic_luma = pu1_cur_pic_luma;
1189        ps_codec->s_parse.s_deblk_ctxt.pu1_cur_pic_chroma = pu1_cur_pic_chroma;
1190
1191        ps_codec->s_parse.s_sao_ctxt.pu1_cur_pic_luma = pu1_cur_pic_luma;
1192        ps_codec->s_parse.s_sao_ctxt.pu1_cur_pic_chroma = pu1_cur_pic_chroma;
1193    }
1194    /* Since any input bitstream buffer that contains slice data will be sent to output(even in
1195     * case of error, this buffer is added to display queue and next buffer in the display queue
1196     * will be returned as the display buffer.
1197     * Note: If format conversion (or frame copy) is used and is scheduled
1198     * in a different thread then it has to check if the processing for the current row is complete before
1199     * it copies/converts a given row. In case of low delay or in case of B pictures, current frame being decoded has to be
1200     * returned, which requires a status check to ensure that the current row is reconstructed before copying.
1201     */
1202    /* Add current picture to display manager */
1203    {
1204        WORD32 abs_poc;
1205        slice_header_t *ps_slice_hdr;
1206        ps_slice_hdr = ps_codec->s_parse.ps_slice_hdr;
1207        abs_poc = ps_slice_hdr->i4_abs_pic_order_cnt;
1208        ihevc_disp_mgr_add((disp_mgr_t *)ps_codec->pv_disp_buf_mgr,
1209                           ps_codec->as_process[0].i4_cur_pic_buf_id,
1210                           abs_poc,
1211                           ps_codec->as_process[0].ps_cur_pic);
1212    }
1213    ps_codec->ps_disp_buf = NULL;
1214    /* Get picture to be displayed if number of pictures decoded is more than max allowed reorder */
1215    /* Since the current will be decoded, check is fore >= instead of > */
1216    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]) ||
1217       ((WORD32)(ps_codec->u4_pic_cnt - ps_codec->u4_disp_cnt) >= ps_codec->i4_init_num_reorder))
1218
1219    {
1220        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);
1221        ps_codec->u4_disp_cnt++;
1222    }
1223
1224    ps_codec->s_fmt_conv.i4_cur_row = 0;
1225    /* Set number of rows to be processed at a time */
1226    ps_codec->s_fmt_conv.i4_num_rows = 4;
1227
1228    if(ps_codec->u4_enable_fmt_conv_ahead && (ps_codec->i4_num_cores > 1))
1229    {
1230        process_ctxt_t *ps_proc;
1231
1232        /* i4_num_cores - 1 contexts are currently being used by other threads */
1233        ps_proc = &ps_codec->as_process[ps_codec->i4_num_cores - 1];
1234
1235        /* If the frame being decoded and displayed are different, schedule format conversion jobs
1236         * this will keep the proc threads busy and lets parse thread decode few CTBs ahead
1237         * If the frame being decoded and displayed are same, then format conversion is scheduled later.
1238         */
1239        if((ps_codec->ps_disp_buf) && (ps_codec->i4_disp_buf_id != ps_proc->i4_cur_pic_buf_id) &&
1240           ((0 == ps_codec->i4_share_disp_buf) || (IV_YUV_420P == ps_codec->e_chroma_fmt)))
1241        {
1242
1243            for(i = 0; i < ps_sps->i2_pic_ht_in_ctb; i++)
1244            {
1245                proc_job_t s_job;
1246                IHEVCD_ERROR_T ret;
1247                s_job.i4_cmd = CMD_FMTCONV;
1248                s_job.i2_ctb_cnt = 0;
1249                s_job.i2_ctb_x = 0;
1250                s_job.i2_ctb_y = i;
1251                s_job.i2_slice_idx = 0;
1252                s_job.i4_tu_coeff_data_ofst = 0;
1253                ret = ihevcd_jobq_queue((jobq_t *)ps_codec->s_parse.pv_proc_jobq,
1254                                        &s_job, sizeof(proc_job_t), 1);
1255                if(ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS)
1256                    return ret;
1257            }
1258        }
1259    }
1260
1261
1262    return ret;
1263}
1264
1265
1266