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             buf_ret = ihevc_buf_mgr_add((buf_mgr_t *)ps_codec->pv_pic_buf_mgr, ps_pic_buf, i);
522 
523 
524             if(0 != buf_ret)
525             {
526                 ps_codec->s_parse.i4_error_code = IHEVCD_BUF_MGR_ERROR;
527                 return IHEVCD_BUF_MGR_ERROR;
528             }
529             ps_pic_buf++;
530         }
531     }
532     else
533     {
534         /* In case of shared mode, buffers are added without adjusting for padding.
535            Update luma and chroma pointers here to account for padding as per stride.
536            In some cases stride might not be available when set_display_frame is called.
537            Hence updated luma and chroma pointers here */
538 
539         for(i = 0; i < BUF_MGR_MAX_CNT; i++)
540         {
541             ps_pic_buf = ihevc_buf_mgr_get_buf((buf_mgr_t *)ps_codec->pv_pic_buf_mgr, i);
542             if((NULL == ps_pic_buf) ||
543                (NULL == ps_pic_buf->pu1_luma) ||
544                (NULL == ps_pic_buf->pu1_chroma))
545             {
546                 break;
547             }
548             ps_pic_buf->pu1_luma += ps_codec->i4_strd * PAD_TOP + PAD_LEFT;
549             ps_pic_buf->pu1_chroma += ps_codec->i4_strd * (PAD_TOP / 2) + PAD_LEFT;
550         }
551     }
552 
553     return ret;
554 }
555 /**
556 *******************************************************************************
557 *
558 * @brief
559 *  Function to add buffers to MV Bank buffer manager
560 *
561 * @par Description:
562 *  Function to add buffers to MV Bank buffer manager
563 *  To be called once per stream or for every reset
564 *
565 * @param[in] ps_codec
566 *  Pointer to codec context
567 *
568 * @returns  Error from IHEVCD_ERROR_T
569 *
570 * @remarks
571 *
572 *
573 *******************************************************************************
574 */
ihevcd_mv_buf_mgr_add_bufs(codec_t * ps_codec)575 IHEVCD_ERROR_T ihevcd_mv_buf_mgr_add_bufs(codec_t *ps_codec)
576 {
577     IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
578     WORD32 i;
579     WORD32 max_dpb_size;
580     WORD32 mv_bank_size_allocated;
581     WORD32 pic_mv_bank_size;
582 
583     sps_t *ps_sps;
584     UWORD8 *pu1_buf;
585     mv_buf_t *ps_mv_buf;
586 
587 
588     /* Initialize MV Bank buffer manager */
589     ps_sps = ps_codec->s_parse.ps_sps;
590 
591 
592     /* Compute the number of MV Bank buffers needed */
593     max_dpb_size = ps_sps->ai1_sps_max_dec_pic_buffering[ps_sps->i1_sps_max_sub_layers - 1];
594 
595     /* Allocate one extra MV Bank to handle current frame
596      * In case of asynchronous parsing and processing, number of buffers should increase here
597      * based on when parsing and processing threads are synchronized
598      */
599     max_dpb_size++;
600 
601     pu1_buf = (UWORD8 *)ps_codec->pv_mv_bank_buf_base;
602 
603     ps_mv_buf = (mv_buf_t *)pu1_buf;
604     pu1_buf += max_dpb_size * sizeof(mv_buf_t);
605     ps_codec->ps_mv_buf = ps_mv_buf;
606     mv_bank_size_allocated = ps_codec->i4_total_mv_bank_size - max_dpb_size  * sizeof(mv_buf_t);
607 
608     /* Compute MV bank size per picture */
609     pic_mv_bank_size = ihevcd_get_pic_mv_bank_size(ALIGN64(ps_sps->i2_pic_width_in_luma_samples) *
610                                                    ALIGN64(ps_sps->i2_pic_height_in_luma_samples));
611 
612     for(i = 0; i < max_dpb_size; i++)
613     {
614         WORD32 buf_ret;
615         WORD32 num_pu;
616         WORD32 num_ctb;
617         WORD32 pic_size;
618         pic_size = ALIGN64(ps_sps->i2_pic_width_in_luma_samples) *
619                         ALIGN64(ps_sps->i2_pic_height_in_luma_samples);
620 
621 
622         num_pu = pic_size / (MIN_PU_SIZE * MIN_PU_SIZE);
623         num_ctb = pic_size / (MIN_CTB_SIZE * MIN_CTB_SIZE);
624 
625 
626         mv_bank_size_allocated -= pic_mv_bank_size;
627 
628         if(mv_bank_size_allocated < 0)
629         {
630             ps_codec->s_parse.i4_error_code = IHEVCD_INSUFFICIENT_MEM_MVBANK;
631             return IHEVCD_INSUFFICIENT_MEM_MVBANK;
632         }
633 
634         ps_mv_buf->pu4_pic_pu_idx = (UWORD32 *)pu1_buf;
635         pu1_buf += (num_ctb + 1) * sizeof(WORD32);
636 
637         ps_mv_buf->pu1_pic_pu_map = pu1_buf;
638         pu1_buf += num_pu;
639 
640         ps_mv_buf->pu1_pic_slice_map = (UWORD16 *)pu1_buf;
641         pu1_buf += ALIGN4(num_ctb * sizeof(UWORD16));
642 
643         ps_mv_buf->ps_pic_pu = (pu_t *)pu1_buf;
644         pu1_buf += num_pu * sizeof(pu_t);
645 
646         buf_ret = ihevc_buf_mgr_add((buf_mgr_t *)ps_codec->pv_mv_buf_mgr, ps_mv_buf, i);
647 
648         if(0 != buf_ret)
649         {
650             ps_codec->s_parse.i4_error_code = IHEVCD_BUF_MGR_ERROR;
651             return IHEVCD_BUF_MGR_ERROR;
652         }
653 
654         ps_mv_buf++;
655 
656     }
657     return ret;
658 }
659 /**
660 *******************************************************************************
661 *
662 * @brief
663 *  Picture level initializations required during parsing
664 *
665 * @par Description:
666 *  Initialize picture level context variables during parsing Initialize mv
667 * bank buffer manager in the first init call
668 *
669 * @param[in] ps_codec
670 *  Pointer to codec context
671 *
672 * @returns  Error from IHEVCD_ERROR_T
673 *
674 * @remarks
675 *
676 *
677 *******************************************************************************
678 */
ihevcd_parse_pic_init(codec_t * ps_codec)679 IHEVCD_ERROR_T ihevcd_parse_pic_init(codec_t *ps_codec)
680 {
681     IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
682     mv_buf_t *ps_mv_buf;
683     sps_t *ps_sps;
684     WORD32 num_min_cu;
685     WORD32 cur_pic_buf_id;
686     WORD32 cur_mv_bank_buf_id;
687     pic_buf_t *ps_cur_pic;
688     slice_header_t *ps_slice_hdr;
689     UWORD8 *pu1_cur_pic_luma, *pu1_cur_pic_chroma;
690     WORD32 i;
691 
692     ps_codec->s_parse.i4_error_code = IHEVCD_SUCCESS;
693     ps_sps = ps_codec->s_parse.ps_sps;
694     ps_slice_hdr = ps_codec->s_parse.ps_slice_hdr;
695     /* If parse_pic_init is called, then slice data is present in the input bitstrea stream */
696     ps_codec->i4_pic_present = 1;
697 
698     /* Memset picture level intra map and transquant bypass map to zero */
699     num_min_cu = ((ps_sps->i2_pic_height_in_luma_samples + 7) / 8) * ((ps_sps->i2_pic_width_in_luma_samples + 63) / 64);
700     memset(ps_codec->s_parse.pu1_pic_intra_flag, 0, num_min_cu);
701     memset(ps_codec->s_parse.pu1_pic_no_loop_filter_flag, 0, num_min_cu);
702 
703 
704 
705     if(0 == ps_codec->s_parse.i4_first_pic_init)
706     {
707         ret = ihevcd_mv_buf_mgr_add_bufs(ps_codec);
708         RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
709 
710         ret = ihevcd_pic_buf_mgr_add_bufs(ps_codec);
711         RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
712 
713         ps_codec->s_parse.i4_first_pic_init = 1;
714     }
715 
716     /* Initialize all the slice headers' slice addresses to zero */
717     {
718         WORD32 slice_idx;
719         WORD32 slice_start_idx;
720 
721         slice_start_idx = ps_codec->i4_slice_error ? 2 : 1;
722 
723         for(slice_idx = slice_start_idx; slice_idx < MAX_SLICE_HDR_CNT; slice_idx++)
724         {
725             slice_header_t *ps_slice_hdr_tmp = ps_codec->ps_slice_hdr_base + slice_idx;
726             ps_slice_hdr_tmp->i2_ctb_x = -1;
727             ps_slice_hdr_tmp->i2_ctb_y = -1;
728 
729         }
730     }
731 
732     /* Get free MV Bank to hold current picture's motion vector data */
733     {
734         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);
735 
736         /* If there are no free buffers then return with an error code.
737          * If the buffer is to be freed by another thread , change the
738          * following to call thread yield and wait for buffer to be freed
739          */
740         if(NULL == ps_mv_buf)
741         {
742             ps_codec->s_parse.i4_error_code = IHEVCD_NO_FREE_MVBANK;
743             ps_codec->i4_error_code = IHEVCD_NO_FREE_MVBANK;
744             return IHEVCD_NO_FREE_MVBANK;
745         }
746 
747         ps_codec->s_parse.ps_cur_mv_buf = ps_mv_buf;
748         /* Set current ABS poc to ps_mv_buf, so that while freeing a reference buffer
749          * corresponding mv buffer can be found by looping through ps_codec->ps_mv_buf array
750          * and getting a buffer id to free
751          */
752         ps_mv_buf->i4_abs_poc = ps_slice_hdr->i4_abs_pic_order_cnt;
753     }
754 
755     /* Get free picture buffer to hold current picture recon data */
756     /* TODO: For asynchronous api the following initializations related to picture
757      * buffer should be moved to processing side
758      */
759     {
760 
761         UWORD8 *pu1_buf;
762         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);
763 
764         /* If there are no free buffers then return with an error code.
765          * TODO: If the buffer is to be freed by another thread , change the
766          * following to call thread yield and wait for buffer to be freed
767          */
768         if(NULL == ps_cur_pic)
769         {
770             ps_codec->s_parse.i4_error_code = IHEVCD_NO_FREE_PICBUF;
771             ps_codec->i4_error_code = IHEVCD_NO_FREE_PICBUF;
772             return IHEVCD_NO_FREE_PICBUF;
773         }
774 
775         /* Store input timestamp sent with input buffer */
776         ps_cur_pic->u4_ts = ps_codec->u4_ts;
777         ps_cur_pic->i4_abs_poc = ps_slice_hdr->i4_abs_pic_order_cnt;
778         ps_cur_pic->i4_poc_lsb = ps_slice_hdr->i4_pic_order_cnt_lsb;
779         pu1_buf = ps_cur_pic->pu1_luma;
780         pu1_cur_pic_luma = pu1_buf;
781 
782         pu1_buf = ps_cur_pic->pu1_chroma;
783 
784         pu1_cur_pic_chroma = pu1_buf;
785     }
786 
787     if(0 == ps_codec->u4_pic_cnt)
788     {
789         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);
790         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);
791     }
792 
793     /* Fill the remaining entries of the reference lists with the nearest POC
794      * This is done to handle cases where there is a corruption in the reference index */
795     {
796         pic_buf_t *ps_pic_buf_ref;
797         mv_buf_t *ps_mv_buf_ref;
798         WORD32 r_idx;
799         dpb_mgr_t *ps_dpb_mgr = (dpb_mgr_t *)ps_codec->pv_dpb_mgr;
800         buf_mgr_t *ps_mv_buf_mgr = (buf_mgr_t *)ps_codec->pv_mv_buf_mgr;
801 
802         ps_pic_buf_ref = ihevc_dpb_mgr_get_ref_by_nearest_poc(ps_dpb_mgr, ps_slice_hdr->i4_abs_pic_order_cnt);
803         if(NULL == ps_pic_buf_ref)
804         {
805             WORD32 size;
806 
807             WORD32 num_pu;
808             WORD32 num_ctb;
809             WORD32 pic_size;
810             /* In case current mv buffer itself is being used as reference mv buffer for colocated
811              * calculations, then memset all the buffers to zero.
812              */
813             pic_size = ALIGN64(ps_sps->i2_pic_width_in_luma_samples) *
814                             ALIGN64(ps_sps->i2_pic_height_in_luma_samples);
815 
816             num_pu = pic_size / (MIN_PU_SIZE * MIN_PU_SIZE);
817             num_ctb = pic_size / (MIN_CTB_SIZE * MIN_CTB_SIZE);
818 
819             memset(ps_mv_buf->ai4_l0_collocated_poc, 0, sizeof(ps_mv_buf->ai4_l0_collocated_poc));
820             memset(ps_mv_buf->ai1_l0_collocated_poc_lt, 0, sizeof(ps_mv_buf->ai1_l0_collocated_poc_lt));
821             memset(ps_mv_buf->ai4_l1_collocated_poc, 0, sizeof(ps_mv_buf->ai4_l1_collocated_poc));
822             memset(ps_mv_buf->ai1_l1_collocated_poc_lt, 0, sizeof(ps_mv_buf->ai1_l1_collocated_poc_lt));
823 
824             size = (num_ctb + 1) * sizeof(WORD32);
825             memset(ps_mv_buf->pu4_pic_pu_idx, 0, size);
826 
827             size = num_pu;
828             memset(ps_mv_buf->pu1_pic_pu_map, 0, size);
829             size = ALIGN4(num_ctb * sizeof(UWORD16));
830             memset(ps_mv_buf->pu1_pic_slice_map, 0, size);
831             size = num_pu * sizeof(pu_t);
832             memset(ps_mv_buf->ps_pic_pu, 0, size);
833 
834             ps_pic_buf_ref = ps_cur_pic;
835             ps_mv_buf_ref = ps_mv_buf;
836         }
837         else
838         {
839             ps_mv_buf_ref = ihevcd_mv_mgr_get_poc(ps_mv_buf_mgr, ps_pic_buf_ref->i4_abs_poc);
840         }
841 
842         for(r_idx = 0; r_idx < ps_slice_hdr->i1_num_ref_idx_l0_active; r_idx++)
843         {
844             if(NULL == ps_slice_hdr->as_ref_pic_list0[r_idx].pv_pic_buf)
845             {
846                 ps_slice_hdr->as_ref_pic_list0[r_idx].pv_pic_buf = (void *)ps_pic_buf_ref;
847                 ps_slice_hdr->as_ref_pic_list0[r_idx].pv_mv_buf = (void *)ps_mv_buf_ref;
848             }
849         }
850 
851         for(r_idx = ps_slice_hdr->i1_num_ref_idx_l0_active; r_idx < MAX_DPB_SIZE; r_idx++)
852         {
853             ps_slice_hdr->as_ref_pic_list0[r_idx].pv_pic_buf = (void *)ps_pic_buf_ref;
854             ps_slice_hdr->as_ref_pic_list0[r_idx].pv_mv_buf = (void *)ps_mv_buf_ref;
855         }
856 
857         for(r_idx = 0; r_idx < ps_slice_hdr->i1_num_ref_idx_l1_active; r_idx++)
858         {
859             if(NULL == ps_slice_hdr->as_ref_pic_list1[r_idx].pv_pic_buf)
860             {
861                 ps_slice_hdr->as_ref_pic_list1[r_idx].pv_pic_buf = (void *)ps_pic_buf_ref;
862                 ps_slice_hdr->as_ref_pic_list1[r_idx].pv_mv_buf = (void *)ps_mv_buf_ref;
863             }
864         }
865 
866         for(r_idx = ps_slice_hdr->i1_num_ref_idx_l1_active; r_idx < MAX_DPB_SIZE; r_idx++)
867         {
868             ps_slice_hdr->as_ref_pic_list1[r_idx].pv_pic_buf = (void *)ps_pic_buf_ref;
869             ps_slice_hdr->as_ref_pic_list1[r_idx].pv_mv_buf = (void *)ps_mv_buf_ref;
870         }
871     }
872 
873 
874     /* Reset the jobq to start of the jobq buffer */
875     ihevcd_jobq_reset((jobq_t *)ps_codec->pv_proc_jobq);
876 
877     ps_codec->s_parse.i4_pic_pu_idx = 0;
878     ps_codec->s_parse.i4_pic_tu_idx = 0;
879 
880     ps_codec->s_parse.pu1_pic_pu_map = ps_mv_buf->pu1_pic_pu_map;
881     ps_codec->s_parse.ps_pic_pu      = ps_mv_buf->ps_pic_pu;
882     ps_codec->s_parse.pu4_pic_pu_idx = ps_mv_buf->pu4_pic_pu_idx;
883     ps_codec->s_parse.pu1_slice_idx = (UWORD16 *)ps_mv_buf->pu1_pic_slice_map;
884     for(i = 0; i < MAX_PROCESS_THREADS; i++)
885     {
886         ps_codec->as_process[i].pu1_slice_idx = (UWORD16 *)ps_mv_buf->pu1_pic_slice_map;
887     }
888     ps_codec->s_parse.pu1_pu_map = ps_codec->s_parse.pu1_pic_pu_map;
889     ps_codec->s_parse.ps_pu = ps_codec->s_parse.ps_pic_pu;
890 
891     {
892         UWORD8 *pu1_buf;
893         WORD32 ctb_luma_min_tu_cnt, ctb_chroma_min_tu_cnt, ctb_min_tu_cnt;
894         WORD32 pic_size;
895         WORD32 num_ctb;
896 
897         pic_size = ALIGN64(ps_sps->i2_pic_width_in_luma_samples) *
898                         ALIGN64(ps_sps->i2_pic_height_in_luma_samples);
899 
900         ctb_luma_min_tu_cnt = pic_size / (MIN_TU_SIZE * MIN_TU_SIZE);
901 
902         ctb_chroma_min_tu_cnt = ctb_luma_min_tu_cnt >> 1;
903 
904         ctb_min_tu_cnt = ctb_luma_min_tu_cnt + ctb_chroma_min_tu_cnt;
905 
906         num_ctb = pic_size / (MIN_CTB_SIZE * MIN_CTB_SIZE);
907         pu1_buf  = (UWORD8 *)ps_codec->pv_tu_data;
908         ps_codec->s_parse.pu4_pic_tu_idx = (UWORD32 *)pu1_buf;
909         pu1_buf += (num_ctb + 1) * sizeof(WORD32);
910 
911         ps_codec->s_parse.pu1_pic_tu_map = pu1_buf;
912         pu1_buf += ctb_min_tu_cnt;
913 
914         ps_codec->s_parse.ps_pic_tu = (tu_t *)pu1_buf;
915         pu1_buf += ctb_min_tu_cnt * sizeof(tu_t);
916 
917         ps_codec->s_parse.pv_pic_tu_coeff_data = pu1_buf;
918 
919         ps_codec->s_parse.pu1_tu_map = ps_codec->s_parse.pu1_pic_tu_map;
920         ps_codec->s_parse.ps_tu = ps_codec->s_parse.ps_pic_tu;
921         ps_codec->s_parse.pv_tu_coeff_data = ps_codec->s_parse.pv_pic_tu_coeff_data;
922     }
923 
924     ps_codec->s_parse.s_bs_ctxt.ps_pic_pu = ps_codec->s_parse.ps_pic_pu;
925     ps_codec->s_parse.s_bs_ctxt.pu4_pic_pu_idx = ps_codec->s_parse.pu4_pic_pu_idx;
926     ps_codec->s_parse.s_bs_ctxt.pu4_pic_tu_idx = ps_codec->s_parse.pu4_pic_tu_idx;
927 
928 
929     /* Set number of CTBs to be processed simultaneously */
930     ps_codec->i4_proc_nctb = ihevcd_nctb_cnt(ps_codec, ps_sps);
931 
932     /* Memset Parse Map and process map at the start of frame */
933     //TODO: In case of asynchronous API proc_map can not be set to zero here
934     {
935         WORD32 num_ctb;
936 
937         num_ctb = ps_sps->i4_pic_size_in_ctb;
938 
939         memset(ps_codec->pu1_parse_map, 0, num_ctb);
940 
941         memset(ps_codec->pu1_proc_map, 0, num_ctb);
942     }
943 
944 
945 
946     /* Initialize disp buf id to -1, this will be updated at the end of frame if there is
947      * buffer to be displayed
948      */
949     ps_codec->i4_disp_buf_id = -1;
950     ps_codec->ps_disp_buf = NULL;
951 
952     ps_codec->i4_disable_deblk_pic  = 0;
953     ps_codec->i4_disable_sao_pic    = 0;
954     ps_codec->i4_fullpel_inter_pred = 0;
955     ps_codec->i4_mv_frac_mask       = 0x7FFFFFFF;
956 
957     /* If degrade is enabled, set the degrade flags appropriately */
958     if(ps_codec->i4_degrade_type && ps_codec->i4_degrade_pics)
959     {
960         WORD32 degrade_pic;
961         ps_codec->i4_degrade_pic_cnt++;
962         degrade_pic = 0;
963 
964         /* If degrade is to be done in all frames, then do not check further */
965         switch(ps_codec->i4_degrade_pics)
966         {
967             case 4:
968             {
969                 degrade_pic = 1;
970                 break;
971             }
972             case 3:
973             {
974                 if(ps_slice_hdr->i1_slice_type != ISLICE)
975                     degrade_pic = 1;
976 
977                 break;
978             }
979             case 2:
980             {
981 
982                 /* If pic count hits non-degrade interval or it is an islice, then do not degrade */
983                 if((ps_slice_hdr->i1_slice_type != ISLICE) &&
984                    (ps_codec->i4_degrade_pic_cnt != ps_codec->i4_nondegrade_interval))
985                     degrade_pic = 1;
986 
987                 break;
988             }
989             case 1:
990             {
991                 /* Check if the current picture is non-ref */
992                 if((ps_slice_hdr->i1_nal_unit_type < NAL_BLA_W_LP) &&
993                    (ps_slice_hdr->i1_nal_unit_type % 2 == 0))
994                 {
995                     degrade_pic = 1;
996                 }
997                 break;
998             }
999 
1000 
1001         }
1002         if(degrade_pic)
1003         {
1004             if(ps_codec->i4_degrade_type & 0x1)
1005                 ps_codec->i4_disable_sao_pic = 1;
1006 
1007             if(ps_codec->i4_degrade_type & 0x2)
1008                 ps_codec->i4_disable_deblk_pic = 1;
1009 
1010             /* MC degrading is done only for non-ref pictures */
1011             if((ps_slice_hdr->i1_nal_unit_type < NAL_BLA_W_LP) &&
1012                (ps_slice_hdr->i1_nal_unit_type % 2 == 0))
1013             {
1014                 if(ps_codec->i4_degrade_type & 0x4)
1015                     ps_codec->i4_mv_frac_mask = 0;
1016 
1017                 if(ps_codec->i4_degrade_type & 0x8)
1018                     ps_codec->i4_mv_frac_mask = 0;
1019             }
1020         }
1021         else
1022             ps_codec->i4_degrade_pic_cnt = 0;
1023     }
1024 
1025 
1026     {
1027         WORD32 i;
1028         for(i = 0; i < MAX_PROCESS_THREADS; i++)
1029         {
1030             ps_codec->as_process[i].pu4_pic_pu_idx = ps_codec->s_parse.pu4_pic_pu_idx;
1031             ps_codec->as_process[i].ps_pic_pu = ps_codec->s_parse.ps_pic_pu;
1032             ps_codec->as_process[i].pu1_pic_pu_map = ps_codec->s_parse.pu1_pic_pu_map;
1033             ps_codec->as_process[i].pu4_pic_tu_idx = ps_codec->s_parse.pu4_pic_tu_idx;
1034             ps_codec->as_process[i].ps_pic_tu = ps_codec->s_parse.ps_pic_tu;
1035             ps_codec->as_process[i].pu1_pic_tu_map = ps_codec->s_parse.pu1_pic_tu_map;
1036             ps_codec->as_process[i].pv_pic_tu_coeff_data = ps_codec->s_parse.pv_pic_tu_coeff_data;
1037             ps_codec->as_process[i].i4_cur_mv_bank_buf_id = cur_mv_bank_buf_id;
1038             ps_codec->as_process[i].s_sao_ctxt.pu1_slice_idx = ps_codec->as_process[i].pu1_slice_idx;
1039             ps_codec->as_process[i].s_sao_ctxt.pu1_tile_idx = ps_codec->as_process[i].pu1_tile_idx;
1040 
1041             /* TODO: For asynchronous api the following initializations related to picture
1042              * buffer should be moved to processing side
1043              */
1044             ps_codec->as_process[i].pu1_cur_pic_luma = pu1_cur_pic_luma;
1045             ps_codec->as_process[i].pu1_cur_pic_chroma = pu1_cur_pic_chroma;
1046             ps_codec->as_process[i].ps_cur_pic = ps_cur_pic;
1047             ps_codec->as_process[i].i4_cur_pic_buf_id = cur_pic_buf_id;
1048 
1049             ps_codec->as_process[i].ps_out_buffer = ps_codec->ps_out_buffer;
1050             if(1 < ps_codec->i4_num_cores)
1051             {
1052                 ps_codec->as_process[i].i4_check_parse_status = 1;
1053                 ps_codec->as_process[i].i4_check_proc_status = 1;
1054             }
1055             else
1056             {
1057                 ps_codec->as_process[i].i4_check_parse_status = 0;
1058                 ps_codec->as_process[i].i4_check_proc_status = 0;
1059             }
1060             ps_codec->as_process[i].pu1_pic_intra_flag = ps_codec->s_parse.pu1_pic_intra_flag;
1061             ps_codec->as_process[i].pu1_pic_no_loop_filter_flag = ps_codec->s_parse.pu1_pic_no_loop_filter_flag;
1062             ps_codec->as_process[i].i4_init_done = 0;
1063 
1064             ps_codec->as_process[i].s_bs_ctxt.pu4_pic_tu_idx = ps_codec->as_process[i].pu4_pic_tu_idx;
1065             ps_codec->as_process[i].s_bs_ctxt.pu4_pic_pu_idx = ps_codec->as_process[i].pu4_pic_pu_idx;
1066             ps_codec->as_process[i].s_bs_ctxt.ps_pic_pu = ps_codec->as_process[i].ps_pic_pu;
1067             ps_codec->as_process[i].s_deblk_ctxt.pu1_pic_no_loop_filter_flag = ps_codec->s_parse.pu1_pic_no_loop_filter_flag;
1068             ps_codec->as_process[i].s_deblk_ctxt.pu1_cur_pic_luma = pu1_cur_pic_luma;
1069             ps_codec->as_process[i].s_deblk_ctxt.pu1_cur_pic_chroma = pu1_cur_pic_chroma;
1070             ps_codec->as_process[i].s_sao_ctxt.pu1_pic_no_loop_filter_flag = ps_codec->s_parse.pu1_pic_no_loop_filter_flag;
1071             ps_codec->as_process[i].s_sao_ctxt.pu1_cur_pic_luma = pu1_cur_pic_luma;
1072             ps_codec->as_process[i].s_sao_ctxt.pu1_cur_pic_chroma = pu1_cur_pic_chroma;
1073             if(i < (ps_codec->i4_num_cores - 1))
1074             {
1075                 ithread_create(ps_codec->apv_process_thread_handle[i], NULL,
1076                                (void *)ihevcd_process_thread,
1077                                (void *)&ps_codec->as_process[i]);
1078                 ps_codec->ai4_process_thread_created[i] = 1;
1079             }
1080             else
1081             {
1082                 ps_codec->ai4_process_thread_created[i] = 0;
1083             }
1084 
1085         }
1086         ps_codec->s_parse.s_deblk_ctxt.pu1_cur_pic_luma = pu1_cur_pic_luma;
1087         ps_codec->s_parse.s_deblk_ctxt.pu1_cur_pic_chroma = pu1_cur_pic_chroma;
1088 
1089         ps_codec->s_parse.s_sao_ctxt.pu1_cur_pic_luma = pu1_cur_pic_luma;
1090         ps_codec->s_parse.s_sao_ctxt.pu1_cur_pic_chroma = pu1_cur_pic_chroma;
1091     }
1092     /* Since any input bitstream buffer that contains slice data will be sent to output(even in
1093      * case of error, this buffer is added to display queue and next buffer in the display queue
1094      * will be returned as the display buffer.
1095      * Note: If format conversion (or frame copy) is used and is scheduled
1096      * in a different thread then it has to check if the processing for the current row is complete before
1097      * it copies/converts a given row. In case of low delay or in case of B pictures, current frame being decoded has to be
1098      * returned, which requires a status check to ensure that the current row is reconstructed before copying.
1099      */
1100     /* Add current picture to display manager */
1101     {
1102         WORD32 abs_poc;
1103         slice_header_t *ps_slice_hdr;
1104         ps_slice_hdr = ps_codec->s_parse.ps_slice_hdr;
1105         abs_poc = ps_slice_hdr->i4_abs_pic_order_cnt;
1106         ihevc_disp_mgr_add((disp_mgr_t *)ps_codec->pv_disp_buf_mgr,
1107                            ps_codec->as_process[0].i4_cur_pic_buf_id,
1108                            abs_poc,
1109                            ps_codec->as_process[0].ps_cur_pic);
1110     }
1111     ps_codec->ps_disp_buf = NULL;
1112     /* Get picture to be displayed if number of pictures decoded is more than max allowed reorder */
1113     /* Since the current will be decoded, check is fore >= instead of > */
1114     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]) ||
1115        (ps_codec->e_frm_out_mode == IVD_DECODE_FRAME_OUT))
1116 
1117     {
1118         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);
1119         ps_codec->u4_disp_cnt++;
1120     }
1121 
1122     ps_codec->s_fmt_conv.i4_cur_row = 0;
1123     /* Set number of rows to be processed at a time */
1124     ps_codec->s_fmt_conv.i4_num_rows = 4;
1125 
1126     if(ps_codec->u4_enable_fmt_conv_ahead && (ps_codec->i4_num_cores > 1))
1127     {
1128         process_ctxt_t *ps_proc;
1129 
1130         /* i4_num_cores - 1 contexts are currently being used by other threads */
1131         ps_proc = &ps_codec->as_process[ps_codec->i4_num_cores - 1];
1132 
1133         /* If the frame being decoded and displayed are different, schedule format conversion jobs
1134          * this will keep the proc threads busy and lets parse thread decode few CTBs ahead
1135          * If the frame being decoded and displayed are same, then format conversion is scheduled later.
1136          */
1137         if((ps_codec->ps_disp_buf) && (ps_codec->i4_disp_buf_id != ps_proc->i4_cur_pic_buf_id) &&
1138            ((0 == ps_codec->i4_share_disp_buf) || (IV_YUV_420P == ps_codec->e_chroma_fmt)))
1139         {
1140 
1141             for(i = 0; i < ps_sps->i2_pic_ht_in_ctb; i++)
1142             {
1143                 proc_job_t s_job;
1144                 IHEVCD_ERROR_T ret;
1145                 s_job.i4_cmd = CMD_FMTCONV;
1146                 s_job.i2_ctb_cnt = 0;
1147                 s_job.i2_ctb_x = 0;
1148                 s_job.i2_ctb_y = i;
1149                 s_job.i2_slice_idx = 0;
1150                 s_job.i4_tu_coeff_data_ofst = 0;
1151                 ret = ihevcd_jobq_queue((jobq_t *)ps_codec->s_parse.pv_proc_jobq,
1152                                         &s_job, sizeof(proc_job_t), 1);
1153                 if(ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS)
1154                     return ret;
1155             }
1156         }
1157     }
1158 
1159 
1160     return ret;
1161 }
1162 
1163 
1164