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