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