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