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