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_decode.c
22  *
23  * @brief
24  *  Contains codecs main decode function
25  *
26  * @author
27  *  Harish
28  *
29  * @par List of Functions:
30  * - fill_outargs()
31  * - ihevcd_decode
32  * @remarks
33  *  None
34  *
35  *******************************************************************************
36  */
37 /*****************************************************************************/
38 /* File Includes                                                             */
39 /*****************************************************************************/
40 #include <stdio.h>
41 #include <stddef.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <assert.h>
45 
46 #include "ihevc_typedefs.h"
47 #include "iv.h"
48 #include "ivd.h"
49 #include "ihevcd_cxa.h"
50 #include "ithread.h"
51 
52 #include "ihevc_defs.h"
53 #include "ihevc_debug.h"
54 #include "ihevc_structs.h"
55 #include "ihevc_macros.h"
56 #include "ihevc_platform_macros.h"
57 #include "ihevc_cabac_tables.h"
58 #include "ihevc_disp_mgr.h"
59 #include "ihevc_buf_mgr.h"
60 #include "ihevc_dpb_mgr.h"
61 #include "ihevc_error.h"
62 
63 #include "ihevcd_defs.h"
64 #include "ihevcd_function_selector.h"
65 #include "ihevcd_structs.h"
66 #include "ihevcd_error.h"
67 #include "ihevcd_nal.h"
68 #include "ihevcd_bitstream.h"
69 #include "ihevcd_fmt_conv.h"
70 #include "ihevcd_job_queue.h"
71 #include "ihevcd_debug.h"
72 #include "ihevcd_process_slice.h"
73 #include "ihevcd_ittiam_logo.h"
74 #include "ihevcd_profile.h"
75 
76 #define NUM_FRAMES_LIMIT_ENABLED 0
77 
78 #if NUM_FRAMES_LIMIT_ENABLED
79 #define NUM_FRAMES_LIMIT 10000
80 #else
81 #define NUM_FRAMES_LIMIT 0x7FFFFFFF
82 #endif
83 
84 IHEVCD_ERROR_T ihevcd_fmt_conv(codec_t *ps_codec,
85                                process_ctxt_t *ps_proc,
86                                UWORD8 *pu1_y_dst,
87                                UWORD8 *pu1_u_dst,
88                                UWORD8 *pu1_v_dst,
89                                WORD32 cur_row,
90                                WORD32 num_rows);
91 WORD32 ihevcd_init(codec_t *ps_codec);
92 /*****************************************************************************/
93 /* Function Prototypes                                                       */
94 /*****************************************************************************/
95 
96 
97 /**
98  *******************************************************************************
99  *
100  * @brief Fills output arguments for decode process
101  *
102  * @par   Description
103  * Fills elements in the output structure based on the current state
104  *
105  * @param[in] ps_codec
106  * Codec context
107  *
108  * @param[in] ps_dec_ip
109  * Pointer to input structure
110  *
111  * @param[in] ps_dec_op
112  * Pointer to output structure
113  *
114  * @returns none
115  *
116  * @remarks
117  *
118  *******************************************************************************
119  */
ihevcd_map_error(IHEVCD_ERROR_T e_error)120 static UWORD32 ihevcd_map_error(IHEVCD_ERROR_T e_error)
121 {
122     UWORD32 error_code = 0;
123     error_code = e_error;
124     switch(error_code)
125     {
126         case IHEVCD_SUCCESS :
127             break;
128         case IHEVCD_INIT_NOT_DONE:
129         case IHEVCD_LEVEL_UNSUPPORTED:
130         case IHEVCD_NUM_REF_UNSUPPORTED:
131         case IHEVCD_NUM_REORDER_UNSUPPORTED:
132         case IHEVCD_NUM_EXTRA_DISP_UNSUPPORTED:
133         case IHEVCD_INSUFFICIENT_MEM_MVBANK:
134         case IHEVCD_INSUFFICIENT_MEM_PICBUF:
135             error_code |= 1 << IVD_FATALERROR;
136             break;
137         case IHEVCD_INVALID_DISP_STRD:
138         case IHEVCD_CXA_VERS_BUF_INSUFFICIENT:
139         case IHEVCD_UNSUPPORTED_VPS_ID:
140         case IHEVCD_UNSUPPORTED_SPS_ID:
141         case IHEVCD_UNSUPPORTED_PPS_ID:
142         case IHEVCD_UNSUPPORTED_CHROMA_FMT_IDC:
143         case IHEVCD_UNSUPPORTED_BIT_DEPTH:
144         case IHEVCD_BUF_MGR_ERROR:
145         case IHEVCD_NO_FREE_MVBANK:
146         case IHEVCD_NO_FREE_PICBUF:
147         case IHEVCD_SLICE_IN_HEADER_MODE:
148         case IHEVCD_END_OF_SEQUENCE:
149             break;
150         default:
151             break;
152     }
153     return error_code;
154 }
155 /**
156  *******************************************************************************
157  *
158  * @brief Fills output arguments for decode process
159  *
160  * @par   Description
161  * Fills elements in the output structure based on the current state
162  *
163  * @param[in] ps_codec
164  * Codec context
165  *
166  * @param[in] ps_dec_ip
167  * Pointer to input structure
168  *
169  * @param[in] ps_dec_op
170  * Pointer to output structure
171  *
172  * @returns none
173  *
174  * @remarks
175  *
176  *******************************************************************************
177  */
ihevcd_fill_outargs(codec_t * ps_codec,ivd_video_decode_ip_t * ps_dec_ip,ivd_video_decode_op_t * ps_dec_op)178 static void ihevcd_fill_outargs(codec_t *ps_codec,
179                                 ivd_video_decode_ip_t *ps_dec_ip,
180                                 ivd_video_decode_op_t *ps_dec_op)
181 {
182 
183     ps_dec_op->u4_error_code = ihevcd_map_error((IHEVCD_ERROR_T)ps_codec->i4_error_code);
184     ps_dec_op->u4_num_bytes_consumed = ps_dec_ip->u4_num_Bytes
185                     - ps_codec->i4_bytes_remaining;
186     if(ps_codec->i4_error_code == IHEVCD_UNSUPPORTED_DIMENSIONS)
187     {
188         ps_dec_op->u4_pic_wd = ps_codec->i4_new_max_wd;
189         ps_dec_op->u4_pic_ht = ps_codec->i4_new_max_ht;
190     }
191     else if(ps_codec->i4_sps_done)
192     {
193         ps_dec_op->u4_pic_wd = ps_codec->i4_disp_wd;
194         ps_dec_op->u4_pic_ht = ps_codec->i4_disp_ht;
195     }
196     else
197     {
198         ps_dec_op->u4_pic_wd = 0;
199         ps_dec_op->u4_pic_ht = 0;
200     }
201 
202     ps_dec_op->e_pic_type = ps_codec->e_dec_pic_type;
203     ps_dec_op->u4_frame_decoded_flag = ps_codec->i4_pic_present;
204     ps_dec_op->u4_new_seq = 0;
205 
206     ps_dec_op->u4_output_present = 0;
207     ps_dec_op->u4_progressive_frame_flag = 1;
208     ps_dec_op->u4_is_ref_flag = 1;
209     ps_dec_op->e_output_format = ps_codec->e_chroma_fmt;
210     ps_dec_op->u4_is_ref_flag = 1;
211 
212     ps_dec_op->e4_fld_type = IV_FLD_TYPE_DEFAULT;
213 
214     ps_dec_op->u4_ts = (UWORD32)(-1);
215     ps_dec_op->u4_disp_buf_id = ps_codec->i4_disp_buf_id;
216     if(ps_codec->i4_flush_mode)
217     {
218         ps_dec_op->u4_num_bytes_consumed = 0;
219         /*In the case of flush ,since no frame is decoded set pic type as invalid*/
220         ps_dec_op->u4_is_ref_flag = 0;
221         ps_dec_op->e_pic_type = IV_NA_FRAME;
222         ps_dec_op->u4_frame_decoded_flag = 0;
223 
224     }
225     /* If there is a display buffer */
226     if(ps_codec->ps_disp_buf)
227     {
228         pic_buf_t *ps_disp_buf = ps_codec->ps_disp_buf;
229 
230         ps_dec_op->u4_output_present = 1;
231         ps_dec_op->u4_ts = ps_disp_buf->u4_ts;
232         if((ps_codec->i4_flush_mode == 0) && (ps_codec->s_parse.i4_end_of_frame == 0))
233             ps_dec_op->u4_output_present = 0;
234         ps_dec_op->s_disp_frm_buf.u4_y_wd = ps_codec->i4_disp_wd;
235         ps_dec_op->s_disp_frm_buf.u4_y_ht = ps_codec->i4_disp_ht;
236 
237         if(ps_codec->i4_share_disp_buf)
238         {
239             ps_dec_op->s_disp_frm_buf.pv_y_buf = ps_disp_buf->pu1_luma;
240             if(ps_codec->e_chroma_fmt != IV_YUV_420P)
241             {
242                 ps_dec_op->s_disp_frm_buf.pv_u_buf = ps_disp_buf->pu1_chroma;
243                 ps_dec_op->s_disp_frm_buf.pv_v_buf = NULL;
244             }
245             else
246             {
247                 ps_dec_op->s_disp_frm_buf.pv_u_buf =
248                                 ps_dec_ip->s_out_buffer.pu1_bufs[1];
249                 ps_dec_op->s_disp_frm_buf.pv_v_buf =
250                                 ps_dec_ip->s_out_buffer.pu1_bufs[2];
251 
252             }
253             ps_dec_op->s_disp_frm_buf.u4_y_strd = ps_codec->i4_strd;
254 
255         }
256         else
257         {
258             ps_dec_op->s_disp_frm_buf.pv_y_buf =
259                             ps_dec_ip->s_out_buffer.pu1_bufs[0];
260             ps_dec_op->s_disp_frm_buf.pv_u_buf =
261                             ps_dec_ip->s_out_buffer.pu1_bufs[1];
262             ps_dec_op->s_disp_frm_buf.pv_v_buf =
263                             ps_dec_ip->s_out_buffer.pu1_bufs[2];
264             ps_dec_op->s_disp_frm_buf.u4_y_strd = ps_codec->i4_disp_strd;
265         }
266 
267         if((IV_YUV_420SP_VU == ps_codec->e_chroma_fmt)
268                         || (IV_YUV_420SP_UV == ps_codec->e_chroma_fmt))
269         {
270             ps_dec_op->s_disp_frm_buf.u4_u_strd =
271                             ps_dec_op->s_disp_frm_buf.u4_y_strd;
272             ps_dec_op->s_disp_frm_buf.u4_v_strd = 0;
273             ps_dec_op->s_disp_frm_buf.u4_u_wd =
274                             ps_dec_op->s_disp_frm_buf.u4_y_wd;
275             ps_dec_op->s_disp_frm_buf.u4_v_wd = 0;
276             ps_dec_op->s_disp_frm_buf.u4_u_ht =
277                             ps_dec_op->s_disp_frm_buf.u4_y_ht / 2;
278             ps_dec_op->s_disp_frm_buf.u4_v_ht = 0;
279         }
280         else if(IV_YUV_420P == ps_codec->e_chroma_fmt)
281         {
282             ps_dec_op->s_disp_frm_buf.u4_u_strd =
283                             ps_dec_op->s_disp_frm_buf.u4_y_strd / 2;
284             ps_dec_op->s_disp_frm_buf.u4_v_strd =
285                             ps_dec_op->s_disp_frm_buf.u4_y_strd / 2;
286             ps_dec_op->s_disp_frm_buf.u4_u_wd =
287                             ps_dec_op->s_disp_frm_buf.u4_y_wd / 2;
288             ps_dec_op->s_disp_frm_buf.u4_v_wd =
289                             ps_dec_op->s_disp_frm_buf.u4_y_wd / 2;
290             ps_dec_op->s_disp_frm_buf.u4_u_ht =
291                             ps_dec_op->s_disp_frm_buf.u4_y_ht / 2;
292             ps_dec_op->s_disp_frm_buf.u4_v_ht =
293                             ps_dec_op->s_disp_frm_buf.u4_y_ht / 2;
294         }
295 
296     }
297     else if(ps_codec->i4_flush_mode)
298     {
299         ps_dec_op->u4_error_code = IHEVCD_END_OF_SEQUENCE;
300         /* Come out of flush mode */
301         ps_codec->i4_flush_mode = 0;
302     }
303 
304 }
305 
306 /**
307  *******************************************************************************
308  *
309  * @brief
310  *  Codec process call
311  *
312  * @par Description:
313  *  Codec process call  Tests for few error checks  Handle flush and decode
314  * header related code  Parse bitstream for start codes  For each NAL unit
315  * call decode NAL function  Once a complete frame is decoded (in frame
316  * decode mode)  Fill output arguments and return
317  *
318  * @param[in] ps_codec_obj
319  *  Pointer to codec object at API level
320  *
321  * @param[in] pv_api_ip
322  *  Pointer to input argument structure
323  *
324  * @param[in] pv_api_op
325  *  Pointer to output argument structure
326  *
327  * @returns  Status
328  *
329  * @remarks
330  *
331  *
332  *******************************************************************************
333  */
ihevcd_decode(iv_obj_t * ps_codec_obj,void * pv_api_ip,void * pv_api_op)334 WORD32 ihevcd_decode(iv_obj_t *ps_codec_obj, void *pv_api_ip, void *pv_api_op)
335 {
336     WORD32 ret = IV_SUCCESS;
337     codec_t *ps_codec = (codec_t *)(ps_codec_obj->pv_codec_handle);
338     ivd_video_decode_ip_t *ps_dec_ip;
339     ivd_video_decode_op_t *ps_dec_op;
340 
341     WORD32 proc_idx = 0;
342     WORD32 prev_proc_idx = 0;
343 
344     /* Initialize error code */
345     ps_codec->i4_error_code = 0;
346 
347     ps_dec_ip = (ivd_video_decode_ip_t *)pv_api_ip;
348     ps_dec_op = (ivd_video_decode_op_t *)pv_api_op;
349 
350     {
351         UWORD32 u4_size = ps_dec_op->u4_size;
352         memset(ps_dec_op, 0, sizeof(ivd_video_decode_op_t));
353         ps_dec_op->u4_size = u4_size; //Restore size field
354     }
355     if(ps_codec->i4_init_done != 1)
356     {
357         ps_dec_op->u4_error_code |= 1 << IVD_FATALERROR;
358         ps_dec_op->u4_error_code |= IHEVCD_INIT_NOT_DONE;
359         return IV_FAIL;
360     }
361 
362     if(ps_codec->u4_pic_cnt >= NUM_FRAMES_LIMIT)
363     {
364         ps_dec_op->u4_error_code |= 1 << IVD_FATALERROR;
365         ps_dec_op->u4_error_code |= IHEVCD_NUM_FRAMES_LIMIT_REACHED;
366         return IV_FAIL;
367     }
368 
369     /* If reset flag is set, flush the existing buffers */
370     if(ps_codec->i4_reset_flag)
371     {
372         ps_codec->i4_flush_mode = 1;
373     }
374 
375     /*Data memory barries instruction,so that bitstream write by the application is complete*/
376     //arm_dsb();
377     /* In case the decoder is not in flush mode check for input buffer validity */
378     if(0 == ps_codec->i4_flush_mode)
379     {
380         if(ps_dec_ip->pv_stream_buffer == NULL)
381         {
382             ps_dec_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
383             ps_dec_op->u4_error_code |= IVD_DEC_FRM_BS_BUF_NULL;
384             return IV_FAIL;
385         }
386         if(ps_dec_ip->u4_num_Bytes <= MIN_START_CODE_LEN)
387         {
388             if((WORD32)ps_dec_ip->u4_num_Bytes > 0)
389                 ps_dec_op->u4_num_bytes_consumed = ps_dec_ip->u4_num_Bytes;
390             else
391                 ps_dec_op->u4_num_bytes_consumed = 0;
392 
393             ps_dec_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
394             ps_dec_op->u4_error_code |= IVD_DEC_NUMBYTES_INV;
395             return IV_FAIL;
396 
397         }
398     }
399 
400 #ifdef APPLY_CONCEALMENT
401     {
402         WORD32 num_mbs;
403 
404         num_mbs = (ps_codec->i4_wd * ps_codec->i4_ht + 255) >> 8;
405         /* Reset MB Count at the beginning of every process call */
406         ps_codec->mb_count = 0;
407         memset(ps_codec->mb_map, 0, ((num_mbs + 7) >> 3));
408     }
409 #endif
410 
411     if(0 == ps_codec->i4_share_disp_buf && ps_codec->i4_header_mode == 0)
412     {
413         UWORD32 i;
414         if(ps_dec_ip->s_out_buffer.u4_num_bufs == 0)
415         {
416             ps_dec_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
417             ps_dec_op->u4_error_code |= IVD_DISP_FRM_ZERO_OP_BUFS;
418             return IV_FAIL;
419         }
420 
421         for(i = 0; i < ps_dec_ip->s_out_buffer.u4_num_bufs; i++)
422         {
423             if(ps_dec_ip->s_out_buffer.pu1_bufs[i] == NULL)
424             {
425                 ps_dec_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
426                 ps_dec_op->u4_error_code |= IVD_DISP_FRM_OP_BUF_NULL;
427                 return IV_FAIL;
428             }
429 
430             if(ps_dec_ip->s_out_buffer.u4_min_out_buf_size[i] == 0)
431             {
432                 ps_dec_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
433                 ps_dec_op->u4_error_code |= IVD_DISP_FRM_ZERO_OP_BUF_SIZE;
434                 return IV_FAIL;
435             }
436         }
437     }
438 
439     ps_codec->ps_out_buffer = &ps_dec_ip->s_out_buffer;
440     ps_codec->u4_ts = ps_dec_ip->u4_ts;
441     if(ps_codec->i4_flush_mode)
442     {
443 
444         ps_dec_op->u4_pic_wd = ps_codec->i4_disp_wd;
445         ps_dec_op->u4_pic_ht = ps_codec->i4_disp_ht;
446 
447         ps_dec_op->u4_new_seq = 0;
448 
449         ps_codec->ps_disp_buf = (pic_buf_t *)ihevc_disp_mgr_get(
450                         (disp_mgr_t *)ps_codec->pv_disp_buf_mgr, &ps_codec->i4_disp_buf_id);
451         /* In case of non-shared mode, then convert/copy the frame to output buffer */
452         /* Only if the codec is in non-shared mode or in shared mode but needs 420P output */
453         if((ps_codec->ps_disp_buf)
454                         && ((0 == ps_codec->i4_share_disp_buf)
455                                         || (IV_YUV_420P
456                                                         == ps_codec->e_chroma_fmt)))
457         {
458 
459             process_ctxt_t *ps_proc = &ps_codec->as_process[prev_proc_idx];
460             if(0 == ps_proc->i4_init_done)
461             {
462                 ihevcd_init_proc_ctxt(ps_proc, 0);
463             }
464 
465             /* Set remaining number of rows to be processed */
466             ret = ihevcd_fmt_conv(ps_codec, &ps_codec->as_process[prev_proc_idx],
467                                   ps_dec_ip->s_out_buffer.pu1_bufs[0],
468                                   ps_dec_ip->s_out_buffer.pu1_bufs[1],
469                                   ps_dec_ip->s_out_buffer.pu1_bufs[2], 0,
470                                   ps_codec->i4_disp_ht);
471 
472             ihevc_buf_mgr_release((buf_mgr_t *)ps_codec->pv_pic_buf_mgr,
473                                   ps_codec->i4_disp_buf_id, BUF_MGR_DISP);
474         }
475 
476         ihevcd_fill_outargs(ps_codec, ps_dec_ip, ps_dec_op);
477 
478         if(1 == ps_dec_op->u4_output_present)
479         {
480             WORD32 xpos = ps_codec->i4_disp_wd - 32 - LOGO_WD;
481             WORD32 ypos = ps_codec->i4_disp_ht - 32 - LOGO_HT;
482 
483             if(ypos < 0)
484                 ypos = 0;
485 
486             if(xpos < 0)
487                 xpos = 0;
488 
489             INSERT_LOGO(ps_dec_ip->s_out_buffer.pu1_bufs[0],
490                         ps_dec_ip->s_out_buffer.pu1_bufs[1],
491                         ps_dec_ip->s_out_buffer.pu1_bufs[2], ps_codec->i4_disp_strd,
492                         xpos,
493                         ypos,
494                         ps_codec->e_chroma_fmt,
495                         ps_codec->i4_disp_wd,
496                         ps_codec->i4_disp_ht);
497         }
498 
499 
500         if(NULL == ps_codec->ps_disp_buf)
501         {
502             /* If in flush mode and there are no more buffers to flush,
503              * check for the reset flag and reset the decoder */
504             if(ps_codec->i4_reset_flag)
505             {
506                 ihevcd_init(ps_codec);
507             }
508             return (IV_FAIL);
509         }
510 
511         return (IV_SUCCESS);
512 
513     }
514     /* In case of shared mode, check if there is a free buffer for reconstruction */
515     if((0 == ps_codec->i4_header_mode) && (1 == ps_codec->i4_share_disp_buf))
516     {
517         WORD32 buf_status;
518         buf_status = 1;
519         if(ps_codec->pv_pic_buf_mgr)
520             buf_status = ihevc_buf_mgr_check_free((buf_mgr_t *)ps_codec->pv_pic_buf_mgr);
521 
522         /* If there is no free buffer, then return with an error code */
523         if(0 == buf_status)
524         {
525             ps_dec_op->u4_error_code = IVD_DEC_REF_BUF_NULL;
526             ps_dec_op->u4_error_code |= (1 << IVD_UNSUPPORTEDPARAM);
527             return IV_FAIL;
528         }
529     }
530     ps_codec->i4_bytes_remaining = ps_dec_ip->u4_num_Bytes;
531     ps_codec->pu1_inp_bitsbuf = (UWORD8 *)ps_dec_ip->pv_stream_buffer;
532     ps_codec->s_parse.i4_end_of_frame = 0;
533 
534     ps_codec->i4_pic_present = 0;
535     ps_codec->i4_slice_error = 0;
536     ps_codec->ps_disp_buf = NULL;
537 
538     if(ps_codec->i4_num_cores > 1)
539     {
540         ithread_set_affinity(0);
541     }
542     while(MIN_START_CODE_LEN < ps_codec->i4_bytes_remaining)
543     {
544         WORD32 nal_len;
545         WORD32 nal_ofst;
546         WORD32 bits_len;
547 
548         if(ps_codec->i4_slice_error)
549         {
550             slice_header_t *ps_slice_hdr_next = ps_codec->s_parse.ps_slice_hdr_base + (ps_codec->s_parse.i4_cur_slice_idx & (MAX_SLICE_HDR_CNT - 1));
551             WORD32 next_slice_addr = ps_slice_hdr_next->i2_ctb_x +
552                             ps_slice_hdr_next->i2_ctb_y * ps_codec->s_parse.ps_sps->i2_pic_wd_in_ctb;
553             if(ps_codec->s_parse.i4_next_ctb_indx == next_slice_addr)
554                 ps_codec->i4_slice_error = 0;
555         }
556 
557         nal_ofst = ihevcd_nal_search_start_code(ps_codec->pu1_inp_bitsbuf,
558                                                 ps_codec->i4_bytes_remaining);
559 
560         ps_codec->i4_nal_ofst = nal_ofst;
561         {
562             WORD32 bytes_remaining = ps_codec->i4_bytes_remaining - nal_ofst;
563 
564             bytes_remaining = MIN((UWORD32)bytes_remaining, ps_codec->u4_bitsbuf_size);
565             ihevcd_nal_remv_emuln_bytes(ps_codec->pu1_inp_bitsbuf + nal_ofst,
566                                         ps_codec->pu1_bitsbuf,
567                                         bytes_remaining,
568                                         &nal_len, &bits_len);
569         }
570         /* This may be used to update the offsets for tiles and entropy sync row offsets */
571         ps_codec->i4_num_emln_bytes = nal_len - bits_len;
572         ps_codec->i4_nal_len = nal_len;
573 
574         ihevcd_bits_init(&ps_codec->s_parse.s_bitstrm, ps_codec->pu1_bitsbuf,
575                          bits_len);
576 
577         ret = ihevcd_nal_unit(ps_codec);
578 
579         /* If the frame is incomplete and
580          * the bytes remaining is zero or a header is received,
581          * complete the frame treating it to be in error */
582         if(ps_codec->i4_pic_present &&
583                         (ps_codec->s_parse.i4_next_ctb_indx != ps_codec->s_parse.ps_sps->i4_pic_size_in_ctb))
584         {
585             if((ps_codec->i4_bytes_remaining - (nal_len + nal_ofst) <= MIN_START_CODE_LEN) ||
586                             (ps_codec->i4_header_in_slice_mode))
587             {
588                 slice_header_t *ps_slice_hdr_next;
589 
590                 ps_codec->s_parse.i4_cur_slice_idx--;
591                 if(ps_codec->s_parse.i4_cur_slice_idx < 0)
592                     ps_codec->s_parse.i4_cur_slice_idx = 0;
593 
594                 ps_slice_hdr_next = ps_codec->s_parse.ps_slice_hdr_base + ((ps_codec->s_parse.i4_cur_slice_idx + 1) & (MAX_SLICE_HDR_CNT - 1));
595                 ps_slice_hdr_next->i2_ctb_x = 0;
596                 ps_slice_hdr_next->i2_ctb_y = ps_codec->s_parse.ps_sps->i2_pic_ht_in_ctb;
597                 ps_codec->i4_slice_error = 1;
598                 continue;
599             }
600         }
601 
602         if(IHEVCD_IGNORE_SLICE == ret)
603         {
604             ps_codec->pu1_inp_bitsbuf += (nal_ofst + nal_len);
605             ps_codec->i4_bytes_remaining -= (nal_ofst + nal_len);
606 
607             continue;
608         }
609 
610         if((IVD_RES_CHANGED == ret) ||
611            (IHEVCD_UNSUPPORTED_DIMENSIONS == ret))
612         {
613             break;
614         }
615 
616         /* Update bytes remaining and bytes consumed and input bitstream pointer */
617         /* Do not consume the NAL in the following cases */
618         /* Slice header reached during header decode mode */
619         /* TODO: Next picture's slice reached */
620         if(ret != IHEVCD_SLICE_IN_HEADER_MODE)
621         {
622             if((0 == ps_codec->i4_slice_error) ||
623                             (ps_codec->i4_bytes_remaining - (nal_len + nal_ofst) <= MIN_START_CODE_LEN))
624             {
625                 ps_codec->pu1_inp_bitsbuf += (nal_ofst + nal_len);
626                 ps_codec->i4_bytes_remaining -= (nal_ofst + nal_len);
627             }
628             if(ret != IHEVCD_SUCCESS)
629                 break;
630 
631             if(ps_codec->s_parse.i4_end_of_frame)
632                 break;
633         }
634         else
635         {
636             ret = IHEVCD_SUCCESS;
637             break;
638         }
639 
640         BREAK_AFTER_SLICE_NAL();
641     }
642 
643     if((ps_codec->u4_pic_cnt == 0) && (ret != IHEVCD_SUCCESS))
644     {
645         ps_codec->i4_error_code = ret;
646 
647         ihevcd_fill_outargs(ps_codec, ps_dec_ip, ps_dec_op);
648         return IV_FAIL;
649     }
650 
651     if(1 == ps_codec->i4_pic_present)
652     {
653         WORD32 i;
654         sps_t *ps_sps = ps_codec->s_parse.ps_sps;
655         ps_codec->i4_first_pic_done = 1;
656 
657         /*TODO temporary fix: end_of_frame is checked before adding format conversion to job queue         */
658         if(ps_codec->i4_num_cores > 1 && ps_codec->s_parse.i4_end_of_frame)
659         {
660 
661             /* Add job queue for format conversion / frame copy for each ctb row */
662             /* Only if the codec is in non-shared mode or in shared mode but needs 420P output */
663             process_ctxt_t *ps_proc;
664 
665             /* i4_num_cores - 1 contexts are currently being used by other threads */
666             ps_proc = &ps_codec->as_process[ps_codec->i4_num_cores - 1];
667 
668             if((ps_codec->ps_disp_buf) &&
669                ((0 == ps_codec->i4_share_disp_buf) || (IV_YUV_420P == ps_codec->e_chroma_fmt)))
670             {
671                 /* If format conversion jobs were not issued in pic_init() add them here */
672                 if((0 == ps_codec->u4_enable_fmt_conv_ahead) ||
673                                 (ps_codec->i4_disp_buf_id == ps_proc->i4_cur_pic_buf_id))
674                     for(i = 0; i < ps_sps->i2_pic_ht_in_ctb; i++)
675                     {
676                         proc_job_t s_job;
677                         IHEVCD_ERROR_T ret;
678                         s_job.i4_cmd = CMD_FMTCONV;
679                         s_job.i2_ctb_cnt = 0;
680                         s_job.i2_ctb_x = 0;
681                         s_job.i2_ctb_y = i;
682                         s_job.i2_slice_idx = 0;
683                         s_job.i4_tu_coeff_data_ofst = 0;
684                         ret = ihevcd_jobq_queue((jobq_t *)ps_codec->s_parse.pv_proc_jobq,
685                                                 &s_job, sizeof(proc_job_t), 1);
686                         if(ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS)
687                             return (WORD32)ret;
688                     }
689             }
690             /* Reached end of frame : Signal terminate */
691             /* The terminate flag is checked only after all the jobs are dequeued */
692             ret = ihevcd_jobq_terminate((jobq_t *)ps_codec->s_parse.pv_proc_jobq);
693 
694             while(1)
695             {
696                 IHEVCD_ERROR_T ret;
697                 proc_job_t s_job;
698                 process_ctxt_t *ps_proc;
699 
700                 /* i4_num_cores - 1 contexts are currently being used by other threads */
701                 ps_proc = &ps_codec->as_process[ps_codec->i4_num_cores - 1];
702 
703                 ret = ihevcd_jobq_dequeue((jobq_t *)ps_proc->pv_proc_jobq, &s_job,
704                                           sizeof(proc_job_t), 1);
705                 if((IHEVCD_ERROR_T)IHEVCD_SUCCESS != ret)
706                     break;
707 
708                 ps_proc->i4_ctb_cnt = s_job.i2_ctb_cnt;
709                 ps_proc->i4_ctb_x = s_job.i2_ctb_x;
710                 ps_proc->i4_ctb_y = s_job.i2_ctb_y;
711                 ps_proc->i4_cur_slice_idx = s_job.i2_slice_idx;
712 
713                 if(CMD_PROCESS == s_job.i4_cmd)
714                 {
715                     ihevcd_init_proc_ctxt(ps_proc, s_job.i4_tu_coeff_data_ofst);
716 
717                     ihevcd_process(ps_proc);
718                 }
719                 else if(CMD_FMTCONV == s_job.i4_cmd)
720                 {
721                     sps_t *ps_sps = ps_codec->s_parse.ps_sps;
722                     WORD32 num_rows = 1 << ps_sps->i1_log2_ctb_size;
723                     if(0 == ps_proc->i4_init_done)
724                     {
725                         ihevcd_init_proc_ctxt(ps_proc, 0);
726                     }
727 
728                     num_rows = MIN(num_rows, (ps_codec->i4_disp_ht - (s_job.i2_ctb_y << ps_sps->i1_log2_ctb_size)));
729                     if(num_rows < 0)
730                         num_rows = 0;
731 
732                     ihevcd_fmt_conv(ps_codec, ps_proc,
733                                     ps_dec_ip->s_out_buffer.pu1_bufs[0],
734                                     ps_dec_ip->s_out_buffer.pu1_bufs[1],
735                                     ps_dec_ip->s_out_buffer.pu1_bufs[2],
736                                     s_job.i2_ctb_y << ps_sps->i1_log2_ctb_size,
737                                     num_rows);
738                 }
739             }
740         }
741         /* In case of non-shared mode and while running in single core mode, then convert/copy the frame to output buffer */
742         /* Only if the codec is in non-shared mode or in shared mode but needs 420P output */
743         else if((ps_codec->ps_disp_buf) && ((0 == ps_codec->i4_share_disp_buf) ||
744                                             (IV_YUV_420P == ps_codec->e_chroma_fmt)) &&
745                         (ps_codec->s_parse.i4_end_of_frame))
746         {
747             process_ctxt_t *ps_proc = &ps_codec->as_process[proc_idx];
748             /* Set remaining number of rows to be processed */
749             ps_codec->s_fmt_conv.i4_num_rows = ps_codec->i4_disp_ht
750                             - ps_codec->s_fmt_conv.i4_cur_row;
751             if(0 == ps_proc->i4_init_done)
752             {
753                 ihevcd_init_proc_ctxt(ps_proc, 0);
754             }
755 
756             if(ps_codec->s_fmt_conv.i4_num_rows < 0)
757                 ps_codec->s_fmt_conv.i4_num_rows = 0;
758 
759             ret = ihevcd_fmt_conv(ps_codec, ps_proc,
760                                   ps_dec_ip->s_out_buffer.pu1_bufs[0],
761                                   ps_dec_ip->s_out_buffer.pu1_bufs[1],
762                                   ps_dec_ip->s_out_buffer.pu1_bufs[2],
763                                   ps_codec->s_fmt_conv.i4_cur_row,
764                                   ps_codec->s_fmt_conv.i4_num_rows);
765             ps_codec->s_fmt_conv.i4_cur_row += ps_codec->s_fmt_conv.i4_num_rows;
766 
767         }
768 
769 
770         DEBUG_DUMP_MV_MAP(ps_codec);
771 
772         /* Mark MV Buf as needed for reference */
773         ihevc_buf_mgr_set_status((buf_mgr_t *)ps_codec->pv_mv_buf_mgr,
774                                  ps_codec->as_process[proc_idx].i4_cur_mv_bank_buf_id,
775                                  BUF_MGR_REF);
776 
777         /* Mark pic buf as needed for reference */
778         ihevc_buf_mgr_set_status((buf_mgr_t *)ps_codec->pv_pic_buf_mgr,
779                                  ps_codec->as_process[proc_idx].i4_cur_pic_buf_id,
780                                  BUF_MGR_REF);
781 
782         /* Mark pic buf as needed for display */
783         ihevc_buf_mgr_set_status((buf_mgr_t *)ps_codec->pv_pic_buf_mgr,
784                                  ps_codec->as_process[proc_idx].i4_cur_pic_buf_id,
785                                  BUF_MGR_DISP);
786 
787         /* Insert the current picture as short term reference */
788         ihevc_dpb_mgr_insert_ref((dpb_mgr_t *)ps_codec->pv_dpb_mgr,
789                                  ps_codec->as_process[proc_idx].ps_cur_pic,
790                                  ps_codec->as_process[proc_idx].i4_cur_pic_buf_id);
791 
792         /* If a frame was displayed (in non-shared mode), then release it from display manager */
793         if((0 == ps_codec->i4_share_disp_buf) && (ps_codec->ps_disp_buf))
794             ihevc_buf_mgr_release((buf_mgr_t *)ps_codec->pv_pic_buf_mgr,
795                                   ps_codec->i4_disp_buf_id, BUF_MGR_DISP);
796 
797         /* Wait for threads */
798         for(i = 0; i < (ps_codec->i4_num_cores - 1); i++)
799         {
800             if(ps_codec->ai4_process_thread_created[i])
801             {
802                 ithread_join(ps_codec->apv_process_thread_handle[i], NULL);
803                 ps_codec->ai4_process_thread_created[i] = 0;
804             }
805         }
806 
807         DEBUG_VALIDATE_PADDED_REGION(&ps_codec->as_process[proc_idx]);
808         if(ps_codec->u4_pic_cnt > 0)
809         {
810             DEBUG_DUMP_PIC_PU(ps_codec);
811         }
812         DEBUG_DUMP_PIC_BUFFERS(ps_codec);
813 
814         /* Increment the number of pictures decoded */
815         ps_codec->u4_pic_cnt++;
816     }
817     ihevcd_fill_outargs(ps_codec, ps_dec_ip, ps_dec_op);
818 
819     if(1 == ps_dec_op->u4_output_present)
820     {
821         WORD32 xpos = ps_codec->i4_disp_wd - 32 - LOGO_WD;
822         WORD32 ypos = ps_codec->i4_disp_ht - 32 - LOGO_HT;
823 
824         if(ypos < 0)
825             ypos = 0;
826 
827         if(xpos < 0)
828             xpos = 0;
829 
830         INSERT_LOGO(ps_dec_ip->s_out_buffer.pu1_bufs[0],
831                     ps_dec_ip->s_out_buffer.pu1_bufs[1],
832                     ps_dec_ip->s_out_buffer.pu1_bufs[2], ps_codec->i4_disp_strd,
833                     xpos,
834                     ypos,
835                     ps_codec->e_chroma_fmt,
836                     ps_codec->i4_disp_wd,
837                     ps_codec->i4_disp_ht);
838     }
839 
840 
841     return ret;
842 }
843 
844