xref: /aosp_15_r20/external/libhevc/decoder/ihevcd_decode.c (revision c83a76b084498d55f252f48b2e3786804cdf24b7)
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_parse_slice.h"
73 #include "ihevcd_process_slice.h"
74 #include "ihevcd_ittiam_logo.h"
75 #include "ihevcd_profile.h"
76 
77 #define NUM_FRAMES_LIMIT_ENABLED 0
78 
79 #if NUM_FRAMES_LIMIT_ENABLED
80 #define NUM_FRAMES_LIMIT 10000
81 #else
82 #define NUM_FRAMES_LIMIT 0x7FFFFFFF
83 #endif
84 
85 IHEVCD_ERROR_T ihevcd_check_out_buf_size(codec_t *ps_codec);
86 IHEVCD_ERROR_T ihevcd_fmt_conv(codec_t *ps_codec,
87                                process_ctxt_t *ps_proc,
88                                UWORD8 *pu1_y_dst,
89                                UWORD8 *pu1_u_dst,
90                                UWORD8 *pu1_v_dst,
91                                WORD32 cur_row,
92                                WORD32 num_rows);
93 WORD32 ihevcd_init(codec_t *ps_codec);
94 
95 WORD32 ihevcd_allocate_dynamic_bufs(codec_t *ps_codec);
96 WORD32 ihevcd_free_dynamic_bufs(codec_t *ps_codec);
97 /*****************************************************************************/
98 /* Function Prototypes                                                       */
99 /*****************************************************************************/
100 
101 
102 /**
103  *******************************************************************************
104  *
105  * @brief Fills output arguments for decode process
106  *
107  * @par   Description
108  * Fills elements in the output structure based on the current state
109  *
110  * @param[in] ps_codec
111  * Codec context
112  *
113  * @param[in] ps_dec_ip
114  * Pointer to input structure
115  *
116  * @param[in] ps_dec_op
117  * Pointer to output structure
118  *
119  * @returns none
120  *
121  * @remarks
122  *
123  *******************************************************************************
124  */
ihevcd_map_error(IHEVCD_ERROR_T e_error)125 static UWORD32 ihevcd_map_error(IHEVCD_ERROR_T e_error)
126 {
127     UWORD32 error_code = 0;
128     error_code = e_error;
129     switch(error_code)
130     {
131         case IHEVCD_SUCCESS :
132             break;
133         case IHEVCD_INIT_NOT_DONE:
134         case IHEVCD_LEVEL_UNSUPPORTED:
135         case IHEVCD_NUM_REF_UNSUPPORTED:
136         case IHEVCD_NUM_REORDER_UNSUPPORTED:
137         case IHEVCD_NUM_EXTRA_DISP_UNSUPPORTED:
138         case IHEVCD_INSUFFICIENT_MEM_MVBANK:
139         case IHEVCD_INSUFFICIENT_MEM_PICBUF:
140         case IHEVCD_UNSUPPORTED_CHROMA_FMT_IDC:
141         case IHEVCD_UNSUPPORTED_BIT_DEPTH:
142         case IVD_MEM_ALLOC_FAILED:
143         case IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED:
144             error_code |= 1 << IVD_FATALERROR;
145             break;
146         case IHEVCD_INVALID_DISP_STRD:
147         case IHEVCD_CXA_VERS_BUF_INSUFFICIENT:
148         case IHEVCD_UNSUPPORTED_VPS_ID:
149         case IHEVCD_UNSUPPORTED_SPS_ID:
150         case IHEVCD_UNSUPPORTED_PPS_ID:
151         case IHEVCD_BUF_MGR_ERROR:
152         case IHEVCD_NO_FREE_MVBANK:
153         case IHEVCD_NO_FREE_PICBUF:
154         case IHEVCD_SLICE_IN_HEADER_MODE:
155         case IHEVCD_END_OF_SEQUENCE:
156             break;
157         default:
158             break;
159     }
160     return error_code;
161 }
162 /**
163  *******************************************************************************
164  *
165  * @brief Fills output arguments for decode process
166  *
167  * @par   Description
168  * Fills elements in the output structure based on the current state
169  *
170  * @param[in] ps_codec
171  * Codec context
172  *
173  * @param[in] ps_dec_ip
174  * Pointer to input structure
175  *
176  * @param[in] ps_dec_op
177  * Pointer to output structure
178  *
179  * @returns none
180  *
181  * @remarks
182  *
183  *******************************************************************************
184  */
ihevcd_fill_outargs(codec_t * ps_codec,void * pv_api_ip,void * pv_api_op)185 static void ihevcd_fill_outargs(codec_t *ps_codec,
186                                 void *pv_api_ip,
187                                 void *pv_api_op)
188 {
189 
190     ihevcd_cxa_video_decode_ip_t *ps_hevcd_dec_ip;
191     ihevcd_cxa_video_decode_op_t *ps_hevcd_dec_op;
192     ivd_video_decode_ip_t *ps_dec_ip;
193     ivd_video_decode_op_t *ps_dec_op;
194 
195     ps_hevcd_dec_ip = (ihevcd_cxa_video_decode_ip_t *)pv_api_ip;
196     ps_hevcd_dec_op = (ihevcd_cxa_video_decode_op_t *)pv_api_op;
197     ps_dec_ip = &ps_hevcd_dec_ip->s_ivd_video_decode_ip_t;
198     ps_dec_op = &ps_hevcd_dec_op->s_ivd_video_decode_op_t;
199 
200     ps_dec_op->u4_error_code = ihevcd_map_error((IHEVCD_ERROR_T)ps_codec->i4_error_code);
201     ps_dec_op->u4_num_bytes_consumed = ps_dec_ip->u4_num_Bytes
202                     - ps_codec->i4_bytes_remaining;
203     if(ps_codec->i4_sps_done)
204     {
205         ps_dec_op->u4_pic_wd = ps_codec->i4_disp_wd;
206         ps_dec_op->u4_pic_ht = ps_codec->i4_disp_ht;
207     }
208     else
209     {
210         ps_dec_op->u4_pic_wd = 0;
211         ps_dec_op->u4_pic_ht = 0;
212     }
213 
214     ps_dec_op->e_pic_type = ps_codec->e_dec_pic_type;
215     ps_dec_op->u4_frame_decoded_flag = ps_codec->i4_pic_present;
216     ps_dec_op->u4_new_seq = 0;
217 
218     ps_dec_op->u4_output_present = 0;
219     ps_dec_op->u4_progressive_frame_flag = 1;
220     ps_dec_op->i4_display_index = -1;
221     ps_dec_op->i4_reorder_depth = -1;
222     if(ps_codec->i4_sps_done)
223     {
224         sps_t *ps_sps = (ps_codec->s_parse.ps_sps_base + ps_codec->i4_sps_id);
225         profile_tier_lvl_info_t *ps_ptl;
226         ps_ptl = &ps_sps->s_ptl;
227         if((0 == ps_ptl->s_ptl_gen.i1_general_progressive_source_flag) &&
228            (1 == ps_ptl->s_ptl_gen.i1_general_interlaced_source_flag))
229         {
230             ps_dec_op->u4_progressive_frame_flag = 0;
231         }
232         ps_dec_op->i4_reorder_depth =
233                         ps_sps->ai1_sps_max_num_reorder_pics[ps_sps->i1_sps_max_sub_layers - 1];
234     }
235 
236     ps_dec_op->u4_is_ref_flag = 1;
237     ps_dec_op->e_output_format = ps_codec->e_chroma_fmt;
238     ps_dec_op->u4_is_ref_flag = 1;
239 
240     ps_dec_op->e4_fld_type = IV_FLD_TYPE_DEFAULT;
241     ps_dec_op->u4_ts = (UWORD32)(-1);
242     ps_dec_op->u4_disp_buf_id = ps_codec->i4_disp_buf_id;
243     if(ps_codec->i4_flush_mode)
244     {
245         ps_dec_op->u4_num_bytes_consumed = 0;
246         /*In the case of flush ,since no frame is decoded set pic type as invalid*/
247         ps_dec_op->u4_is_ref_flag = 0;
248         ps_dec_op->e_pic_type = IV_NA_FRAME;
249         ps_dec_op->u4_frame_decoded_flag = 0;
250 
251     }
252     /* If there is a display buffer */
253     if(ps_codec->ps_disp_buf)
254     {
255         pic_buf_t *ps_disp_buf = ps_codec->ps_disp_buf;
256 #ifndef DISABLE_SEI
257         sei_params_t *ps_sei = &ps_disp_buf->s_sei_params;
258 
259         if(ps_sei->i1_sei_parameters_present_flag &&
260            ps_sei->i1_pic_timing_params_present_flag)
261         {
262             UWORD32 u4_pic_struct;
263             u4_pic_struct = ps_sei->s_pic_timing_sei_params.u4_pic_struct;
264             switch(u4_pic_struct)
265             {
266                 case 1:
267                     ps_dec_op->e4_fld_type = IV_TOP_FLD;
268                     ps_dec_op->u4_progressive_frame_flag = 0;
269                     break;
270                 case 2:
271                     ps_dec_op->e4_fld_type = IV_BOT_FLD;
272                     ps_dec_op->u4_progressive_frame_flag = 0;
273                     break;
274                 case 0:
275                 default:
276                     ps_dec_op->e4_fld_type = IV_FLD_TYPE_DEFAULT;
277                     ps_dec_op->u4_progressive_frame_flag = 1;
278                     break;
279             }
280         }
281 #endif
282         ps_dec_op->i4_display_index = ps_disp_buf->i4_abs_poc;
283         ps_dec_op->u4_output_present = 1;
284         ps_dec_op->u4_ts = ps_disp_buf->u4_ts;
285         if((ps_codec->i4_flush_mode == 0) && (ps_codec->s_parse.i4_end_of_frame == 0))
286             ps_dec_op->u4_output_present = 0;
287         ps_dec_op->s_disp_frm_buf.u4_y_wd = ps_codec->i4_disp_wd;
288         ps_dec_op->s_disp_frm_buf.u4_y_ht = ps_codec->i4_disp_ht;
289 
290         if(ps_codec->i4_share_disp_buf)
291         {
292             ps_dec_op->s_disp_frm_buf.pv_y_buf = ps_disp_buf->pu1_luma;
293             if(ps_codec->e_chroma_fmt != IV_YUV_420P)
294             {
295                 ps_dec_op->s_disp_frm_buf.pv_u_buf = ps_disp_buf->pu1_chroma;
296                 ps_dec_op->s_disp_frm_buf.pv_v_buf = NULL;
297             }
298             else
299             {
300                 WORD32 i;
301                 UWORD8 *pu1_u_dst = NULL, *pu1_v_dst = NULL;
302                 for(i = 0; i < ps_codec->i4_share_disp_buf_cnt; i++)
303                 {
304                     WORD32 diff = ps_disp_buf->pu1_luma - ps_codec->s_disp_buffer[i].pu1_bufs[0];
305                     if(diff == (ps_codec->i4_strd * PAD_TOP + PAD_LEFT))
306                     {
307                         pu1_u_dst = ps_codec->s_disp_buffer[i].pu1_bufs[1];
308                         pu1_u_dst += (ps_codec->i4_strd * PAD_TOP) / 4 + (PAD_LEFT / 2);
309 
310                         pu1_v_dst = ps_codec->s_disp_buffer[i].pu1_bufs[2];
311                         pu1_v_dst += (ps_codec->i4_strd * PAD_TOP) / 4 + (PAD_LEFT / 2);
312                         break;
313                     }
314                 }
315                 ps_dec_op->s_disp_frm_buf.pv_u_buf = pu1_u_dst;
316                 ps_dec_op->s_disp_frm_buf.pv_v_buf = pu1_v_dst;
317             }
318             ps_dec_op->s_disp_frm_buf.u4_y_strd = ps_codec->i4_strd;
319         }
320         else
321         {
322             ps_dec_op->s_disp_frm_buf.pv_y_buf =
323                             ps_dec_ip->s_out_buffer.pu1_bufs[0];
324             ps_dec_op->s_disp_frm_buf.pv_u_buf =
325                             ps_dec_ip->s_out_buffer.pu1_bufs[1];
326             ps_dec_op->s_disp_frm_buf.pv_v_buf =
327                             ps_dec_ip->s_out_buffer.pu1_bufs[2];
328             ps_dec_op->s_disp_frm_buf.u4_y_strd = ps_codec->i4_disp_strd;
329         }
330 
331         if((IV_YUV_420SP_VU == ps_codec->e_chroma_fmt)
332                         || (IV_YUV_420SP_UV == ps_codec->e_chroma_fmt))
333         {
334             ps_dec_op->s_disp_frm_buf.u4_u_strd =
335                             ps_dec_op->s_disp_frm_buf.u4_y_strd;
336             ps_dec_op->s_disp_frm_buf.u4_v_strd = 0;
337             ps_dec_op->s_disp_frm_buf.u4_u_wd =
338                             ps_dec_op->s_disp_frm_buf.u4_y_wd;
339             ps_dec_op->s_disp_frm_buf.u4_v_wd = 0;
340             ps_dec_op->s_disp_frm_buf.u4_u_ht =
341                             ps_dec_op->s_disp_frm_buf.u4_y_ht / 2;
342             ps_dec_op->s_disp_frm_buf.u4_v_ht = 0;
343         }
344         else if(IV_YUV_420P == ps_codec->e_chroma_fmt)
345         {
346             ps_dec_op->s_disp_frm_buf.u4_u_strd =
347                             ps_dec_op->s_disp_frm_buf.u4_y_strd / 2;
348             ps_dec_op->s_disp_frm_buf.u4_v_strd =
349                             ps_dec_op->s_disp_frm_buf.u4_y_strd / 2;
350             ps_dec_op->s_disp_frm_buf.u4_u_wd =
351                             ps_dec_op->s_disp_frm_buf.u4_y_wd / 2;
352             ps_dec_op->s_disp_frm_buf.u4_v_wd =
353                             ps_dec_op->s_disp_frm_buf.u4_y_wd / 2;
354             ps_dec_op->s_disp_frm_buf.u4_u_ht =
355                             ps_dec_op->s_disp_frm_buf.u4_y_ht / 2;
356             ps_dec_op->s_disp_frm_buf.u4_v_ht =
357                             ps_dec_op->s_disp_frm_buf.u4_y_ht / 2;
358         }
359 
360     }
361     else if(ps_codec->i4_flush_mode)
362     {
363         ps_dec_op->u4_error_code = IHEVCD_END_OF_SEQUENCE;
364         /* Come out of flush mode */
365         ps_codec->i4_flush_mode = 0;
366     }
367 
368     if(ps_codec->u1_enable_cu_info && ps_dec_op->u4_output_present)
369     {
370         WORD32 info_map_dst_strd = ALIGN8(ps_codec->i4_wd) >> 3;
371         WORD32 info_map_src_strd = ALIGN64(ps_codec->i4_wd) >> 3;
372         WORD32 info_map_ht = ALIGN8(ps_codec->i4_ht);
373         UWORD32 info_map_size = (ALIGN8(ps_codec->i4_wd) * info_map_ht) >> 6;
374         WORD32 vert_8x8;
375         UWORD8 *pu1_out_qp_map, *pu1_qp_map;
376         UWORD8 *pu1_out_blk_type_map, *pu1_type_map;
377 
378         if(ps_hevcd_dec_ip->pu1_8x8_blk_qp_map)
379         {
380             ps_hevcd_dec_op->pu1_8x8_blk_qp_map = ps_hevcd_dec_ip->pu1_8x8_blk_qp_map;
381             ps_hevcd_dec_op->u4_8x8_blk_qp_map_size = info_map_size;
382 
383             pu1_out_qp_map = ps_hevcd_dec_op->pu1_8x8_blk_qp_map;
384             pu1_qp_map = ps_codec->as_buf_id_info_map[ps_codec->i4_disp_buf_id].pu1_qp_map;
385             for(vert_8x8 = 0; vert_8x8 < info_map_ht; vert_8x8++)
386             {
387                 memcpy(pu1_out_qp_map, pu1_qp_map, info_map_dst_strd);
388                 pu1_out_qp_map += info_map_dst_strd;
389                 pu1_qp_map += info_map_src_strd;
390             }
391         }
392 
393         if(ps_hevcd_dec_ip->pu1_8x8_blk_type_map)
394         {
395             ps_hevcd_dec_op->pu1_8x8_blk_type_map = ps_hevcd_dec_ip->pu1_8x8_blk_type_map;
396             ps_hevcd_dec_op->u4_8x8_blk_type_map_size = info_map_size;
397 
398             pu1_out_blk_type_map = ps_hevcd_dec_op->pu1_8x8_blk_type_map;
399             pu1_type_map =
400                 ps_codec->as_buf_id_info_map[ps_codec->i4_disp_buf_id].pu1_cu_type_map;
401             for(vert_8x8 = 0; vert_8x8 < info_map_ht; vert_8x8++)
402             {
403                 memcpy(pu1_out_blk_type_map, pu1_type_map, info_map_dst_strd);
404                 pu1_out_blk_type_map += info_map_dst_strd;
405                 pu1_type_map += info_map_src_strd;
406             }
407         }
408     }
409 }
410 
411 /**
412  *******************************************************************************
413  *
414  * @brief
415  *  Codec process call
416  *
417  * @par Description:
418  *  Codec process call  Tests for few error checks  Handle flush and decode
419  * header related code  Parse bitstream for start codes  For each NAL unit
420  * call decode NAL function  Once a complete frame is decoded (in frame
421  * decode mode)  Fill output arguments and return
422  *
423  * @param[in] ps_codec_obj
424  *  Pointer to codec object at API level
425  *
426  * @param[in] pv_api_ip
427  *  Pointer to input argument structure
428  *
429  * @param[in] pv_api_op
430  *  Pointer to output argument structure
431  *
432  * @returns  Status
433  *
434  * @remarks
435  *
436  *
437  *******************************************************************************
438  */
ihevcd_decode(iv_obj_t * ps_codec_obj,void * pv_api_ip,void * pv_api_op)439 WORD32 ihevcd_decode(iv_obj_t *ps_codec_obj, void *pv_api_ip, void *pv_api_op)
440 {
441     WORD32 ret = IV_SUCCESS;
442     codec_t *ps_codec = (codec_t *)(ps_codec_obj->pv_codec_handle);
443     ihevcd_cxa_video_decode_ip_t s_hevcd_dec_ip = {};
444     ihevcd_cxa_video_decode_ip_t *ps_hevcd_dec_ip;
445     ihevcd_cxa_video_decode_op_t *ps_hevcd_dec_op;
446     ivd_video_decode_ip_t *ps_dec_ip;
447     ivd_video_decode_op_t *ps_dec_op;
448 
449     WORD32 proc_idx = 0;
450     WORD32 prev_proc_idx = 0;
451 
452     /* Initialize error code */
453     ps_codec->i4_error_code = 0;
454     /* Initialize bytes remaining */
455     ps_codec->i4_bytes_remaining = 0;
456 
457     ps_dec_ip = (ivd_video_decode_ip_t *)pv_api_ip;
458     memcpy(&s_hevcd_dec_ip, ps_dec_ip, ps_dec_ip->u4_size);
459     s_hevcd_dec_ip.s_ivd_video_decode_ip_t.u4_size = sizeof(ihevcd_cxa_video_decode_ip_t);
460 
461     ps_hevcd_dec_ip = &s_hevcd_dec_ip;
462     ps_dec_ip = &ps_hevcd_dec_ip->s_ivd_video_decode_ip_t;
463 
464     ps_hevcd_dec_op = (ihevcd_cxa_video_decode_op_t *)pv_api_op;
465     ps_dec_op = &ps_hevcd_dec_op->s_ivd_video_decode_op_t;
466 
467     {
468         UWORD32 u4_size = ps_dec_op->u4_size;
469         memset(ps_hevcd_dec_op, 0, u4_size);
470         ps_dec_op->u4_size = u4_size; //Restore size field
471     }
472     if(ps_codec->i4_init_done != 1)
473     {
474         ps_dec_op->u4_error_code |= 1 << IVD_FATALERROR;
475         ps_dec_op->u4_error_code |= IHEVCD_INIT_NOT_DONE;
476         return IV_FAIL;
477     }
478 
479     if(ps_codec->u4_pic_cnt >= NUM_FRAMES_LIMIT)
480     {
481         ps_dec_op->u4_error_code |= 1 << IVD_FATALERROR;
482         ps_dec_op->u4_error_code |= IHEVCD_NUM_FRAMES_LIMIT_REACHED;
483         return IV_FAIL;
484     }
485 
486     if(ps_codec->u1_enable_cu_info && ps_codec->i4_sps_done)
487     {
488         UWORD32 blk_qp_map_size = ps_hevcd_dec_ip->u4_8x8_blk_qp_map_size;
489         UWORD32 blk_type_map_size = ps_hevcd_dec_ip->u4_8x8_blk_type_map_size;
490         UWORD32 blk_8x8_map_size = (ALIGN8(ps_codec->i4_wd) * ALIGN8(ps_codec->i4_ht)) >> 6;
491 
492         if ((ps_hevcd_dec_ip->pu1_8x8_blk_qp_map && blk_qp_map_size < blk_8x8_map_size) ||
493             (ps_hevcd_dec_ip->pu1_8x8_blk_type_map && blk_type_map_size < blk_8x8_map_size))
494         {
495             ps_dec_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
496             ps_dec_op->u4_error_code |= IHEVCD_INSUFFICIENT_METADATA_BUFFER;
497             return IV_FAIL;
498         }
499      }
500 
501     /* If reset flag is set, flush the existing buffers */
502     if(ps_codec->i4_reset_flag)
503     {
504         ps_codec->i4_flush_mode = 1;
505     }
506 
507     /*Data memory barries instruction,so that bitstream write by the application is complete*/
508     //arm_dsb();
509     /* In case the decoder is not in flush mode check for input buffer validity */
510     if(0 == ps_codec->i4_flush_mode)
511     {
512         if(ps_dec_ip->pv_stream_buffer == NULL)
513         {
514             ps_dec_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
515             ps_dec_op->u4_error_code |= IVD_DEC_FRM_BS_BUF_NULL;
516             return IV_FAIL;
517         }
518         if(ps_dec_ip->u4_num_Bytes <= MIN_START_CODE_LEN)
519         {
520             if((WORD32)ps_dec_ip->u4_num_Bytes > 0)
521                 ps_dec_op->u4_num_bytes_consumed = ps_dec_ip->u4_num_Bytes;
522             else
523                 ps_dec_op->u4_num_bytes_consumed = 0;
524 
525             ps_dec_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
526             ps_dec_op->u4_error_code |= IVD_DEC_NUMBYTES_INV;
527             return IV_FAIL;
528 
529         }
530     }
531 
532 #ifdef APPLY_CONCEALMENT
533     {
534         WORD32 num_mbs;
535 
536         num_mbs = (ps_codec->i4_wd * ps_codec->i4_ht + 255) >> 8;
537         /* Reset MB Count at the beginning of every process call */
538         ps_codec->mb_count = 0;
539         memset(ps_codec->mb_map, 0, ((num_mbs + 7) >> 3));
540     }
541 #endif
542 
543     if(0 == ps_codec->i4_share_disp_buf && ps_codec->i4_header_mode == 0)
544     {
545         UWORD32 i;
546         if((ps_dec_ip->s_out_buffer.u4_num_bufs <= 0) ||
547            (ps_dec_ip->s_out_buffer.u4_num_bufs > IVD_VIDDEC_MAX_IO_BUFFERS))
548         {
549             ps_dec_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
550             ps_dec_op->u4_error_code |= IVD_DISP_FRM_ZERO_OP_BUFS;
551             return IV_FAIL;
552         }
553 
554         for(i = 0; i < ps_dec_ip->s_out_buffer.u4_num_bufs; i++)
555         {
556             if(ps_dec_ip->s_out_buffer.pu1_bufs[i] == NULL)
557             {
558                 ps_dec_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
559                 ps_dec_op->u4_error_code |= IVD_DISP_FRM_OP_BUF_NULL;
560                 return IV_FAIL;
561             }
562 
563             if(ps_dec_ip->s_out_buffer.u4_min_out_buf_size[i] == 0)
564             {
565                 ps_dec_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM;
566                 ps_dec_op->u4_error_code |= IVD_DISP_FRM_ZERO_OP_BUF_SIZE;
567                 return IV_FAIL;
568             }
569         }
570     }
571 
572     ps_codec->ps_out_buffer = &ps_dec_ip->s_out_buffer;
573     ps_codec->u4_ts = ps_dec_ip->u4_ts;
574     if(ps_codec->i4_flush_mode)
575     {
576 
577         ps_dec_op->u4_pic_wd = ps_codec->i4_disp_wd;
578         ps_dec_op->u4_pic_ht = ps_codec->i4_disp_ht;
579 
580         ps_dec_op->u4_new_seq = 0;
581 
582         ps_codec->ps_disp_buf = (pic_buf_t *)ihevc_disp_mgr_get(
583                         (disp_mgr_t *)ps_codec->pv_disp_buf_mgr, &ps_codec->i4_disp_buf_id);
584         /* In case of non-shared mode, then convert/copy the frame to output buffer */
585         /* Only if the codec is in non-shared mode or in shared mode but needs 420P output */
586         if((ps_codec->ps_disp_buf)
587                         && ((0 == ps_codec->i4_share_disp_buf)
588                                         || (IV_YUV_420P
589                                                         == ps_codec->e_chroma_fmt)))
590         {
591 
592             process_ctxt_t *ps_proc = &ps_codec->as_process[prev_proc_idx];
593             if(0 == ps_proc->i4_init_done)
594             {
595                 ihevcd_init_proc_ctxt(ps_proc, 0);
596             }
597 
598             /* Output buffer check */
599             ret = ihevcd_check_out_buf_size(ps_codec);
600             RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
601 
602             /* Set remaining number of rows to be processed */
603             ret = ihevcd_fmt_conv(ps_codec, &ps_codec->as_process[prev_proc_idx],
604                                   ps_dec_ip->s_out_buffer.pu1_bufs[0],
605                                   ps_dec_ip->s_out_buffer.pu1_bufs[1],
606                                   ps_dec_ip->s_out_buffer.pu1_bufs[2], 0,
607                                   ps_codec->i4_disp_ht);
608 
609             ihevc_buf_mgr_release((buf_mgr_t *)ps_codec->pv_pic_buf_mgr,
610                                   ps_codec->i4_disp_buf_id, BUF_MGR_DISP);
611         }
612 
613         ihevcd_fill_outargs(ps_codec, ps_hevcd_dec_ip, ps_hevcd_dec_op);
614 
615         if(1 == ps_dec_op->u4_output_present)
616         {
617             WORD32 xpos = ps_codec->i4_disp_wd - 32 - LOGO_WD;
618             WORD32 ypos = ps_codec->i4_disp_ht - 32 - LOGO_HT;
619 
620             if(ypos < 0)
621                 ypos = 0;
622 
623             if(xpos < 0)
624                 xpos = 0;
625 
626             INSERT_LOGO(ps_dec_ip->s_out_buffer.pu1_bufs[0],
627                         ps_dec_ip->s_out_buffer.pu1_bufs[1],
628                         ps_dec_ip->s_out_buffer.pu1_bufs[2], ps_codec->i4_disp_strd,
629                         xpos,
630                         ypos,
631                         ps_codec->e_chroma_fmt,
632                         ps_codec->i4_disp_wd,
633                         ps_codec->i4_disp_ht);
634         }
635 
636 
637         if(NULL == ps_codec->ps_disp_buf)
638         {
639             /* If in flush mode and there are no more buffers to flush,
640              * check for the reset flag and reset the decoder */
641             if(ps_codec->i4_reset_flag)
642             {
643                 ihevcd_init(ps_codec);
644             }
645             return (IV_FAIL);
646         }
647 
648         return (IV_SUCCESS);
649 
650     }
651     /* In case of shared mode, check if there is a free buffer for reconstruction */
652     if((0 == ps_codec->i4_header_mode) && (1 == ps_codec->i4_share_disp_buf))
653     {
654         WORD32 buf_status;
655         buf_status = 1;
656         if(ps_codec->pv_pic_buf_mgr)
657             buf_status = ihevc_buf_mgr_check_free((buf_mgr_t *)ps_codec->pv_pic_buf_mgr);
658 
659         /* If there is no free buffer, then return with an error code */
660         if(0 == buf_status)
661         {
662             ps_dec_op->u4_error_code = IVD_DEC_REF_BUF_NULL;
663             ps_dec_op->u4_error_code |= (1 << IVD_UNSUPPORTEDPARAM);
664             return IV_FAIL;
665         }
666     }
667     ps_codec->i4_bytes_remaining = ps_dec_ip->u4_num_Bytes;
668     ps_codec->pu1_inp_bitsbuf = (UWORD8 *)ps_dec_ip->pv_stream_buffer;
669     ps_codec->s_parse.i4_end_of_frame = 0;
670 
671     ps_codec->i4_pic_present = 0;
672     ps_codec->i4_slice_error = 0;
673     ps_codec->ps_disp_buf = NULL;
674 
675     if(ps_codec->i4_num_cores > 1)
676     {
677         ithread_set_affinity(0);
678     }
679     while(MIN_START_CODE_LEN < ps_codec->i4_bytes_remaining)
680     {
681         WORD32 nal_len;
682         WORD32 nal_ofst;
683         WORD32 bits_len;
684 
685         if(ps_codec->i4_slice_error)
686         {
687             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));
688             WORD32 next_slice_addr = ps_slice_hdr_next->i2_ctb_x +
689                             ps_slice_hdr_next->i2_ctb_y * ps_codec->s_parse.ps_sps->i2_pic_wd_in_ctb;
690             if(ps_codec->s_parse.i4_next_ctb_indx == next_slice_addr)
691                 ps_codec->i4_slice_error = 0;
692         }
693 
694         if(ps_codec->pu1_bitsbuf_dynamic)
695         {
696             ps_codec->pu1_bitsbuf = ps_codec->pu1_bitsbuf_dynamic;
697             ps_codec->u4_bitsbuf_size = ps_codec->u4_bitsbuf_size_dynamic;
698         }
699         else
700         {
701             ps_codec->pu1_bitsbuf = ps_codec->pu1_bitsbuf_static;
702             ps_codec->u4_bitsbuf_size = ps_codec->u4_bitsbuf_size_static;
703         }
704 
705         nal_ofst = ihevcd_nal_search_start_code(ps_codec->pu1_inp_bitsbuf,
706                                                 ps_codec->i4_bytes_remaining);
707         /* If there is no start code found, consume the data and break */
708         if(nal_ofst == ps_codec->i4_bytes_remaining)
709         {
710             ps_codec->pu1_inp_bitsbuf += nal_ofst;
711             ps_codec->i4_bytes_remaining -= nal_ofst;
712             break;
713         }
714 
715         ps_codec->i4_nal_ofst = nal_ofst;
716         {
717             WORD32 bytes_remaining = ps_codec->i4_bytes_remaining - nal_ofst;
718 
719             bytes_remaining = MIN((UWORD32)bytes_remaining, ps_codec->u4_bitsbuf_size);
720             ihevcd_nal_remv_emuln_bytes(ps_codec->pu1_inp_bitsbuf + nal_ofst,
721                                         ps_codec->pu1_bitsbuf,
722                                         bytes_remaining,
723                                         &nal_len, &bits_len);
724 
725             /* Decoder may read upto 8 extra bytes at the end of frame */
726             /* These are not used, but still set them to zero to avoid uninitialized reads */
727             if(bits_len < (WORD32)(ps_codec->u4_bitsbuf_size - 8))
728             {
729                 memset(ps_codec->pu1_bitsbuf + bits_len, 0, 2 * sizeof(UWORD32));
730             }
731         }
732         /* This may be used to update the offsets for tiles and entropy sync row offsets */
733         ps_codec->i4_num_emln_bytes = nal_len - bits_len;
734         ps_codec->i4_nal_len = nal_len;
735 
736         ihevcd_bits_init(&ps_codec->s_parse.s_bitstrm, ps_codec->pu1_bitsbuf,
737                          bits_len);
738 
739         ret = ihevcd_nal_unit(ps_codec);
740 
741         /* If the frame is incomplete and
742          * the bytes remaining is zero or a header is received,
743          * complete the frame treating it to be in error */
744         if(ps_codec->i4_pic_present &&
745                         (ps_codec->s_parse.i4_next_ctb_indx != ps_codec->s_parse.ps_sps->i4_pic_size_in_ctb))
746         {
747             if((ps_codec->i4_bytes_remaining - (nal_len + nal_ofst) <= MIN_START_CODE_LEN) ||
748                             (ps_codec->i4_header_in_slice_mode))
749             {
750                 slice_header_t *ps_slice_hdr_next;
751 
752                 ps_codec->s_parse.i4_cur_slice_idx--;
753                 if(ps_codec->s_parse.i4_cur_slice_idx < 0)
754                     ps_codec->s_parse.i4_cur_slice_idx = 0;
755 
756                 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));
757                 ps_slice_hdr_next->i2_ctb_x = 0;
758                 ps_slice_hdr_next->i2_ctb_y = ps_codec->s_parse.ps_sps->i2_pic_ht_in_ctb;
759                 ps_codec->i4_slice_error = 1;
760                 continue;
761             }
762         }
763 
764         if(IHEVCD_IGNORE_SLICE == ret)
765         {
766             ps_codec->pu1_inp_bitsbuf += (nal_ofst + nal_len);
767             ps_codec->i4_bytes_remaining -= (nal_ofst + nal_len);
768 
769             continue;
770         }
771 
772         if(IVD_RES_CHANGED == ret)
773         {
774             break;
775         }
776 
777         /* Update bytes remaining and bytes consumed and input bitstream pointer */
778         /* Do not consume the NAL in the following cases */
779         /* Slice header reached during header decode mode */
780         /* TODO: Next picture's slice reached */
781         if(ret != IHEVCD_SLICE_IN_HEADER_MODE)
782         {
783             if((0 == ps_codec->i4_slice_error) ||
784                             (ps_codec->i4_bytes_remaining - (nal_len + nal_ofst) <= MIN_START_CODE_LEN))
785             {
786                 ps_codec->pu1_inp_bitsbuf += (nal_ofst + nal_len);
787                 ps_codec->i4_bytes_remaining -= (nal_ofst + nal_len);
788             }
789             if(ret != IHEVCD_SUCCESS)
790                 break;
791 
792             if(ps_codec->s_parse.i4_end_of_frame)
793                 break;
794         }
795         else
796         {
797             ret = IHEVCD_SUCCESS;
798             break;
799         }
800 
801         /* Allocate dynamic bitstream buffer once SPS is decoded */
802         if((ps_codec->u4_allocate_dynamic_done == 0) && ps_codec->i4_sps_done)
803         {
804             WORD32 ret;
805             ret = ihevcd_allocate_dynamic_bufs(ps_codec);
806             if(ret != IV_SUCCESS)
807             {
808                 /* Free any dynamic buffers that are allocated */
809                 ihevcd_free_dynamic_bufs(ps_codec);
810                 ps_codec->i4_error_code = IVD_MEM_ALLOC_FAILED;
811                 ps_dec_op->u4_error_code = 1 << IVD_FATALERROR;
812                 ps_dec_op->u4_error_code |= IVD_MEM_ALLOC_FAILED;
813 
814                 return IV_FAIL;
815             }
816         }
817 
818         BREAK_AFTER_SLICE_NAL();
819     }
820 
821     if(1 == ps_codec->i4_pic_present && 0 == ps_codec->s_parse.i4_end_of_frame)
822     {
823         slice_header_t *ps_slice_hdr_next;
824         ps_codec->i4_slice_error = 1;
825         ps_codec->s_parse.i4_cur_slice_idx--;
826         if(ps_codec->s_parse.i4_cur_slice_idx < 0)
827             ps_codec->s_parse.i4_cur_slice_idx = 0;
828 
829         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));
830         ps_slice_hdr_next->i2_ctb_x = -1;
831         ps_slice_hdr_next->i2_ctb_y = -1;
832 
833         ihevcd_parse_slice_data(ps_codec);
834         ASSERT(ps_codec->s_parse.i4_end_of_frame != 0);
835     }
836 
837     if(1 == ps_codec->i4_pic_present)
838     {
839         WORD32 i;
840         sps_t *ps_sps = ps_codec->s_parse.ps_sps;
841         ps_codec->i4_first_pic_done = 1;
842 
843         /*TODO temporary fix: end_of_frame is checked before adding format conversion to job queue         */
844         if(ps_codec->i4_num_cores > 1 && ps_codec->s_parse.i4_end_of_frame)
845         {
846 
847             /* Add job queue for format conversion / frame copy for each ctb row */
848             /* Only if the codec is in non-shared mode or in shared mode but needs 420P output */
849             process_ctxt_t *ps_proc;
850 
851             /* i4_num_cores - 1 contexts are currently being used by other threads */
852             ps_proc = &ps_codec->as_process[ps_codec->i4_num_cores - 1];
853 
854             if((ps_codec->ps_disp_buf) &&
855                ((0 == ps_codec->i4_share_disp_buf) || (IV_YUV_420P == ps_codec->e_chroma_fmt)))
856             {
857                 /* If format conversion jobs were not issued in pic_init() add them here */
858                 if((0 == ps_codec->u4_enable_fmt_conv_ahead) ||
859                                 (ps_codec->i4_disp_buf_id == ps_proc->i4_cur_pic_buf_id))
860                     for(i = 0; i < ps_sps->i2_pic_ht_in_ctb; i++)
861                     {
862                         proc_job_t s_job;
863                         IHEVCD_ERROR_T ret;
864                         s_job.i4_cmd = CMD_FMTCONV;
865                         s_job.i2_ctb_cnt = 0;
866                         s_job.i2_ctb_x = 0;
867                         s_job.i2_ctb_y = i;
868                         s_job.i2_slice_idx = 0;
869                         s_job.i4_tu_coeff_data_ofst = 0;
870                         ret = ihevcd_jobq_queue((jobq_t *)ps_codec->s_parse.pv_proc_jobq,
871                                                 &s_job, sizeof(proc_job_t), 1);
872                         if(ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS)
873                             return (WORD32)ret;
874                     }
875             }
876             /* Reached end of frame : Signal terminate */
877             /* The terminate flag is checked only after all the jobs are dequeued */
878             ret = ihevcd_jobq_terminate((jobq_t *)ps_codec->s_parse.pv_proc_jobq);
879 
880             while(1)
881             {
882                 IHEVCD_ERROR_T ret;
883                 proc_job_t s_job;
884                 process_ctxt_t *ps_proc;
885 
886                 /* i4_num_cores - 1 contexts are currently being used by other threads */
887                 ps_proc = &ps_codec->as_process[ps_codec->i4_num_cores - 1];
888 
889                 ret = ihevcd_jobq_dequeue((jobq_t *)ps_proc->pv_proc_jobq, &s_job,
890                                           sizeof(proc_job_t), 1);
891                 if((IHEVCD_ERROR_T)IHEVCD_SUCCESS != ret)
892                     break;
893 
894                 ps_proc->i4_ctb_cnt = s_job.i2_ctb_cnt;
895                 ps_proc->i4_ctb_x = s_job.i2_ctb_x;
896                 ps_proc->i4_ctb_y = s_job.i2_ctb_y;
897                 ps_proc->i4_cur_slice_idx = s_job.i2_slice_idx;
898 
899                 if(CMD_PROCESS == s_job.i4_cmd)
900                 {
901                     ihevcd_init_proc_ctxt(ps_proc, s_job.i4_tu_coeff_data_ofst);
902 
903                     ihevcd_process(ps_proc);
904                 }
905                 else if(CMD_FMTCONV == s_job.i4_cmd)
906                 {
907                     sps_t *ps_sps = ps_codec->s_parse.ps_sps;
908                     WORD32 num_rows = 1 << ps_sps->i1_log2_ctb_size;
909                     if(0 == ps_proc->i4_init_done)
910                     {
911                         ihevcd_init_proc_ctxt(ps_proc, 0);
912                     }
913 
914                     num_rows = MIN(num_rows, (ps_codec->i4_disp_ht - (s_job.i2_ctb_y << ps_sps->i1_log2_ctb_size)));
915                     if(num_rows < 0)
916                         num_rows = 0;
917 
918                     ihevcd_fmt_conv(ps_codec, ps_proc,
919                                     ps_dec_ip->s_out_buffer.pu1_bufs[0],
920                                     ps_dec_ip->s_out_buffer.pu1_bufs[1],
921                                     ps_dec_ip->s_out_buffer.pu1_bufs[2],
922                                     s_job.i2_ctb_y << ps_sps->i1_log2_ctb_size,
923                                     num_rows);
924                 }
925             }
926         }
927         /* In case of non-shared mode and while running in single core mode, then convert/copy the frame to output buffer */
928         /* Only if the codec is in non-shared mode or in shared mode but needs 420P output */
929         else if((ps_codec->ps_disp_buf) && ((0 == ps_codec->i4_share_disp_buf) ||
930                                             (IV_YUV_420P == ps_codec->e_chroma_fmt)) &&
931                         (ps_codec->s_parse.i4_end_of_frame))
932         {
933             process_ctxt_t *ps_proc = &ps_codec->as_process[proc_idx];
934             /* Set remaining number of rows to be processed */
935             ps_codec->s_fmt_conv.i4_num_rows = ps_codec->i4_disp_ht
936                             - ps_codec->s_fmt_conv.i4_cur_row;
937             if(0 == ps_proc->i4_init_done)
938             {
939                 ihevcd_init_proc_ctxt(ps_proc, 0);
940             }
941 
942             if(ps_codec->s_fmt_conv.i4_num_rows < 0)
943                 ps_codec->s_fmt_conv.i4_num_rows = 0;
944 
945             ret = ihevcd_fmt_conv(ps_codec, ps_proc,
946                                   ps_dec_ip->s_out_buffer.pu1_bufs[0],
947                                   ps_dec_ip->s_out_buffer.pu1_bufs[1],
948                                   ps_dec_ip->s_out_buffer.pu1_bufs[2],
949                                   ps_codec->s_fmt_conv.i4_cur_row,
950                                   ps_codec->s_fmt_conv.i4_num_rows);
951             ps_codec->s_fmt_conv.i4_cur_row += ps_codec->s_fmt_conv.i4_num_rows;
952 
953         }
954 
955 
956         DEBUG_DUMP_MV_MAP(ps_codec);
957 
958         /* Mark MV Buf as needed for reference */
959         ihevc_buf_mgr_set_status((buf_mgr_t *)ps_codec->pv_mv_buf_mgr,
960                                  ps_codec->as_process[proc_idx].i4_cur_mv_bank_buf_id,
961                                  BUF_MGR_REF);
962 
963         /* Mark pic buf as needed for reference */
964         ihevc_buf_mgr_set_status((buf_mgr_t *)ps_codec->pv_pic_buf_mgr,
965                                  ps_codec->as_process[proc_idx].i4_cur_pic_buf_id,
966                                  BUF_MGR_REF);
967 
968         /* Mark pic buf as needed for display */
969         ihevc_buf_mgr_set_status((buf_mgr_t *)ps_codec->pv_pic_buf_mgr,
970                                  ps_codec->as_process[proc_idx].i4_cur_pic_buf_id,
971                                  BUF_MGR_DISP);
972 
973         /* Insert the current picture as short term reference */
974         ihevc_dpb_mgr_insert_ref((dpb_mgr_t *)ps_codec->pv_dpb_mgr,
975                                  ps_codec->as_process[proc_idx].ps_cur_pic,
976                                  ps_codec->as_process[proc_idx].i4_cur_pic_buf_id);
977 
978         /* If a frame was displayed (in non-shared mode), then release it from display manager */
979         if((0 == ps_codec->i4_share_disp_buf) && (ps_codec->ps_disp_buf))
980             ihevc_buf_mgr_release((buf_mgr_t *)ps_codec->pv_pic_buf_mgr,
981                                   ps_codec->i4_disp_buf_id, BUF_MGR_DISP);
982 
983         /* Wait for threads */
984         for(i = 0; i < (ps_codec->i4_num_cores - 1); i++)
985         {
986             if(ps_codec->ai4_process_thread_created[i])
987             {
988                 if(ps_codec->i4_threads_active)
989                 {
990                     ret = ithread_mutex_lock(ps_codec->apv_proc_done_mutex[i]);
991                     RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
992 
993                     while(!ps_codec->ai4_process_done[i])
994                     {
995                         ithread_cond_wait(ps_codec->apv_proc_done_condition[i],
996                                           ps_codec->apv_proc_done_mutex[i]);
997                     }
998                     ps_codec->ai4_process_done[i] = 0;
999                     ret = ithread_mutex_unlock(ps_codec->apv_proc_done_mutex[i]);
1000                     RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
1001                 }
1002                 else
1003                 {
1004                     ithread_join(ps_codec->apv_process_thread_handle[i], NULL);
1005                     ps_codec->ai4_process_thread_created[i] = 0;
1006                 }
1007             }
1008         }
1009 
1010         DEBUG_VALIDATE_PADDED_REGION(&ps_codec->as_process[proc_idx]);
1011         if(ps_codec->u4_pic_cnt > 0)
1012         {
1013             DEBUG_DUMP_PIC_PU(ps_codec);
1014         }
1015         DEBUG_DUMP_PIC_BUFFERS(ps_codec);
1016 
1017         /* Increment the number of pictures decoded */
1018         ps_codec->u4_pic_cnt++;
1019     }
1020     ihevcd_fill_outargs(ps_codec, ps_hevcd_dec_ip, ps_hevcd_dec_op);
1021 
1022     if(1 == ps_dec_op->u4_output_present)
1023     {
1024         WORD32 xpos = ps_codec->i4_disp_wd - 32 - LOGO_WD;
1025         WORD32 ypos = ps_codec->i4_disp_ht - 32 - LOGO_HT;
1026 
1027         if(ypos < 0)
1028             ypos = 0;
1029 
1030         if(xpos < 0)
1031             xpos = 0;
1032 
1033         INSERT_LOGO(ps_dec_ip->s_out_buffer.pu1_bufs[0],
1034                     ps_dec_ip->s_out_buffer.pu1_bufs[1],
1035                     ps_dec_ip->s_out_buffer.pu1_bufs[2], ps_codec->i4_disp_strd,
1036                     xpos,
1037                     ypos,
1038                     ps_codec->e_chroma_fmt,
1039                     ps_codec->i4_disp_wd,
1040                     ps_codec->i4_disp_ht);
1041     }
1042 
1043 
1044     return ret;
1045 }
1046 
1047