xref: /aosp_15_r20/external/libavc/decoder/svc/isvcd_thread_parse_decode.c (revision 495ae853bb871d1e5a258cb02c2cc13cde8ddb9a)
1 /******************************************************************************
2  *
3  * Copyright (C) 2022 The Android Open Source Project
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  * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19  */
20 /**
21  *******************************************************************************
22  * @file
23  *  isvcd_thread_parse_decode.c
24  *
25  * @brief
26  *  Contains routines that for multi-thread decoder
27  *
28  * @author
29  *  Kishore
30  *
31  * @remarks
32  *  None
33  *
34  *******************************************************************************
35  */
36 
37 #include <string.h>
38 #include "ih264d_error_handler.h"
39 #include "ih264d_debug.h"
40 #include "ithread.h"
41 #include "ih264d_defs.h"
42 #include "ih264d_debug.h"
43 #include "ih264d_tables.h"
44 #include "isvcd_structs.h"
45 #include "ih264d_defs.h"
46 #include "ih264d_mb_utils.h"
47 #include "ih264d_thread_parse_decode.h"
48 #include "ih264d_inter_pred.h"
49 #include "ih264d_process_pslice.h"
50 #include "isvcd_process_epslice.h"
51 #include "ih264d_process_intra_mb.h"
52 #include "ih264d_deblocking.h"
53 #include "ih264d_format_conv.h"
54 #include "isvcd_thread_parse_decode.h"
55 
56 /*****************************************************************************/
57 /*                                                                           */
58 /*  Function Name : isvcd_decode_recon_tfr_nmb_thread                        */
59 /*                                                                           */
60 /*  Description   :                                                          */
61 /*                :                                                          */
62 /*                :                                                          */
63 /*  Inputs        :                                                          */
64 /*  Processing    :Only for Target Layer processing                          */
65 /*                                                                           */
66 /*  Outputs       :                                                          */
67 /*  Returns       : None                                                     */
68 /*                                                                           */
69 /*  Revision History:                                                        */
70 /*                                                                           */
71 /*         DD MM YYYY   Author(s)       Changes (Describe the changes made)  */
72 /*                      ITTIAM                                               */
73 /*****************************************************************************/
isvcd_decode_recon_tfr_nmb_thread(svc_dec_lyr_struct_t * ps_svc_lyr_dec,UWORD8 u1_num_mbs,UWORD8 u1_num_mbs_next,UWORD8 u1_end_of_row)74 WORD32 isvcd_decode_recon_tfr_nmb_thread(svc_dec_lyr_struct_t *ps_svc_lyr_dec, UWORD8 u1_num_mbs,
75                                          UWORD8 u1_num_mbs_next, UWORD8 u1_end_of_row)
76 {
77     WORD32 i, j;
78     dec_mb_info_t *ps_cur_mb_info;
79     dec_svc_mb_info_t *ps_svc_cur_mb_info;
80     dec_struct_t *ps_dec = &ps_svc_lyr_dec->s_dec;
81     const UWORD32 u1_mbaff = ps_dec->ps_cur_slice->u1_mbaff_frame_flag;
82     UWORD32 u1_slice_type, u1_B;
83     WORD32 u1_skip_th;
84     UWORD32 u1_ipcm_th;
85     UWORD32 u4_cond;
86     UWORD16 u2_slice_num, u2_cur_dec_mb_num;
87     UWORD32 u4_mb_num;
88     WORD32 nop_cnt = 8 * 128;
89     UWORD16 *pu2_res_luma_csbp;
90     WORD32 ret;
91     u1_slice_type = ps_dec->ps_decode_cur_slice->slice_type;
92 
93     u1_B = (u1_slice_type == B_SLICE);
94     u1_skip_th = ((u1_slice_type != I_SLICE) ? (u1_B ? B_8x8 : PRED_8x8R0) : -1);
95     u1_ipcm_th = ((u1_slice_type != I_SLICE) ? (u1_B ? 23 : 5) : 0);
96     u2_cur_dec_mb_num = ps_dec->cur_dec_mb_num;
97 
98     while(1)
99     {
100         UWORD32 u4_max_mb =
101             (UWORD32) (ps_dec->i2_dec_thread_mb_y + (1 << u1_mbaff)) * ps_dec->u2_frm_wd_in_mbs - 1;
102         u4_mb_num = u2_cur_dec_mb_num;
103         /*introducing 1 MB delay*/
104         u4_mb_num = MIN(u4_mb_num + u1_num_mbs + 1, u4_max_mb);
105 
106         CHECK_MB_MAP_BYTE(u4_mb_num, ps_dec->pu1_dec_mb_map, u4_cond);
107         if(u4_cond)
108         {
109             break;
110         }
111         else
112         {
113             if(nop_cnt > 0)
114             {
115                 nop_cnt -= 128;
116                 NOP(128);
117             }
118             else
119             {
120                 if(ps_dec->u4_output_present && (2 == ps_dec->u4_num_cores) &&
121                    (ps_dec->u4_fmt_conv_cur_row < ps_dec->s_disp_frame_info.u4_y_ht))
122                 {
123                     ps_dec->u4_fmt_conv_num_rows =
124                         MIN(FMT_CONV_NUM_ROWS,
125                             (ps_dec->s_disp_frame_info.u4_y_ht - ps_dec->u4_fmt_conv_cur_row));
126                     ih264d_format_convert(ps_dec, &(ps_dec->s_disp_op), ps_dec->u4_fmt_conv_cur_row,
127                                           ps_dec->u4_fmt_conv_num_rows);
128                     ps_dec->u4_fmt_conv_cur_row += ps_dec->u4_fmt_conv_num_rows;
129                 }
130                 else
131                 {
132                     nop_cnt = 8 * 128;
133                     ithread_yield();
134                 }
135                 if(1 == ps_svc_lyr_dec->u1_error_in_cur_frame)
136                 {
137                     return NOT_OK;
138                 }
139             }
140         }
141     }
142 
143     /* N Mb MC Loop */
144     for(i = 0; i < u1_num_mbs; i++)
145     {
146         u4_mb_num = u2_cur_dec_mb_num;
147         GET_SLICE_NUM_MAP(ps_dec->pu2_slice_num_map, u2_cur_dec_mb_num, u2_slice_num);
148 
149         if(u2_slice_num != ps_dec->u2_cur_slice_num_dec_thread)
150         {
151             ps_dec->u4_cur_slice_decode_done = 1;
152             break;
153         }
154 
155         ps_cur_mb_info = &ps_dec->ps_frm_mb_info[u2_cur_dec_mb_num];
156 
157         ps_dec->u4_dma_buf_idx = 0;
158         ps_dec->u4_pred_info_idx = 0;
159 
160         /*Pointer assignment for Residual NNZ */
161         pu2_res_luma_csbp = ps_svc_lyr_dec->pu2_frm_res_luma_csbp + ps_cur_mb_info->u2_mbx;
162         pu2_res_luma_csbp += ps_cur_mb_info->u2_mby * ps_svc_lyr_dec->i4_frm_res_luma_csbp_stride;
163 
164         if(ps_cur_mb_info->u1_mb_type <= u1_skip_th)
165         {
166             WORD32 pred_cnt = 0;
167             pred_info_pkd_t *ps_pred_pkd;
168             UWORD32 u4_pred_info_pkd_idx;
169 
170             u4_pred_info_pkd_idx = ps_cur_mb_info->u4_pred_info_pkd_idx;
171 
172             while(pred_cnt < ps_cur_mb_info->u1_num_pred_parts)
173             {
174                 ps_pred_pkd = ps_dec->ps_pred_pkd + u4_pred_info_pkd_idx;
175 
176                 ps_dec->p_form_mb_part_info_thread(ps_pred_pkd, ps_dec, ps_cur_mb_info->u2_mbx,
177                                                    ps_cur_mb_info->u2_mby, (i >> u1_mbaff),
178                                                    ps_cur_mb_info);
179 
180                 u4_pred_info_pkd_idx++;
181                 pred_cnt++;
182             }
183             ps_dec->p_mc_dec_thread(ps_dec, ps_cur_mb_info);
184         }
185         else if(ps_cur_mb_info->u1_mb_type == MB_SKIP)
186         {
187             WORD32 pred_cnt = 0;
188             pred_info_pkd_t *ps_pred_pkd;
189             UWORD32 u4_pred_info_pkd_idx;
190 
191             u4_pred_info_pkd_idx = ps_cur_mb_info->u4_pred_info_pkd_idx;
192 
193             while(pred_cnt < ps_cur_mb_info->u1_num_pred_parts)
194             {
195                 ps_pred_pkd = ps_dec->ps_pred_pkd + u4_pred_info_pkd_idx;
196 
197                 ps_dec->p_form_mb_part_info_thread(ps_pred_pkd, ps_dec, ps_cur_mb_info->u2_mbx,
198                                                    ps_cur_mb_info->u2_mby, (i >> u1_mbaff),
199                                                    ps_cur_mb_info);
200 
201                 u4_pred_info_pkd_idx++;
202                 pred_cnt++;
203             }
204             /* Decode MB skip */
205             ps_dec->p_mc_dec_thread(ps_dec, ps_cur_mb_info);
206 
207             *pu2_res_luma_csbp = 0;
208             ps_svc_lyr_dec->ps_inter_lyr_mb_prms_cur_mb =
209                 ps_svc_lyr_dec->ps_inter_lyr_mb_prms_frm_start + ps_cur_mb_info->u2_mbx +
210                 (ps_svc_lyr_dec->u2_inter_lyr_mb_prms_stride * (ps_cur_mb_info->u2_mby));
211             ps_svc_lyr_dec->ps_inter_lyr_mb_prms_cur_mb->i1_mb_mode = SVC_INTER_MB;
212             ps_svc_lyr_dec->ps_inter_lyr_mb_prms_cur_mb->i1_tx_size =
213                 ps_cur_mb_info->u1_tran_form8x8;
214             ps_svc_lyr_dec->ps_inter_lyr_mb_prms_cur_mb->u2_luma_nnz = 0;
215             ps_svc_lyr_dec->ps_inter_lyr_mb_prms_cur_mb->u1_chroma_nnz = 0;
216         }
217 
218         u2_cur_dec_mb_num++;
219     }
220 
221     /* N Mb IQ IT RECON  Loop */
222     for(j = 0; j < i; j++)
223     {
224         ps_cur_mb_info = &ps_dec->ps_frm_mb_info[ps_dec->cur_dec_mb_num];
225         ps_svc_cur_mb_info = &ps_svc_lyr_dec->ps_svc_frm_mb_info[ps_dec->cur_dec_mb_num];
226 
227         if(NULL == ps_cur_mb_info->ps_curmb)
228         {
229             return NOT_OK;
230         }
231 
232         /*Pointer assignment for Residual NNZ */
233         pu2_res_luma_csbp = ps_svc_lyr_dec->pu2_frm_res_luma_csbp + ps_cur_mb_info->u2_mbx;
234         pu2_res_luma_csbp += ps_cur_mb_info->u2_mby * ps_svc_lyr_dec->i4_frm_res_luma_csbp_stride;
235 
236         ps_svc_lyr_dec->ps_inter_lyr_mb_prms_cur_mb =
237             ps_svc_lyr_dec->ps_inter_lyr_mb_prms_frm_start + ps_cur_mb_info->u2_mbx +
238             (ps_svc_lyr_dec->u2_inter_lyr_mb_prms_stride * (ps_cur_mb_info->u2_mby));
239 
240         ps_svc_lyr_dec->ps_inter_lyr_mb_prms_cur_mb->i1_slice_id = (WORD8) ps_dec->u2_cur_slice_num;
241 
242         if((ps_dec->u4_num_cores == 2) || !ps_dec->i1_recon_in_thread3_flag)
243         {
244             if(ps_cur_mb_info->u1_mb_type <= u1_skip_th)
245             {
246                 {
247                     /* inter intra pred generation */
248                     if(SVCD_FALSE == ps_svc_lyr_dec->u1_dyadic_flag)
249                     {
250                         ret = isvcd_process_ii_mb(ps_svc_lyr_dec, ps_cur_mb_info,
251                                                   ps_svc_cur_mb_info, j);
252                         if(ret != OK) return ret;
253                     }
254                     if(0 == ps_svc_cur_mb_info->u1_residual_prediction_flag)
255                     {
256                         /* IT + Recon */
257                         ih264d_process_inter_mb(ps_dec, ps_cur_mb_info, j);
258                         isvcd_update_inter_mb_inter_layer_info(ps_svc_lyr_dec, ps_cur_mb_info, 0);
259                         *pu2_res_luma_csbp = ps_cur_mb_info->u2_luma_csbp;
260                     }
261                     else
262                     {
263                         /* IT + Residual + Recon */
264                         ret = isvcd_process_inter_mb_rsd_pred_target_lyr(
265                             ps_svc_lyr_dec, ps_cur_mb_info, j, 0, pu2_res_luma_csbp);
266                         if(ret != OK) return ret;
267                     }
268                 }
269             }
270 
271             else if((ps_cur_mb_info->u1_mb_type != MB_SKIP) &&
272                     (ps_cur_mb_info->u1_mb_type != MB_INFER))
273             {
274                 if((u1_ipcm_th + 25) != ps_cur_mb_info->u1_mb_type)
275                 {
276                     ps_cur_mb_info->u1_mb_type -= (u1_skip_th + 1);
277                     ih264d_process_intra_mb(ps_dec, ps_cur_mb_info, j);
278                     isvcd_update_intra_mb_inter_layer_info(ps_svc_lyr_dec, ps_cur_mb_info);
279                 }
280                 else
281                 {
282                     isvcd_update_ipcm_mb_inter_layer_info(ps_svc_lyr_dec, ps_cur_mb_info);
283                 }
284                 *pu2_res_luma_csbp = 0;
285             }
286             else if(ps_cur_mb_info->u1_mb_type == MB_INFER)
287             {
288                 /* inter layer intra prediction : intra upsample, IQ, IT ,deblock */
289                 {
290                     /* Intra resample for IBL mode */
291                     ret = isvcd_process_ibl_mb(ps_svc_lyr_dec, ps_cur_mb_info, j, 0);
292                     if(ret != OK) return ret;
293                     /* Pass intra resample as pred to Recon generation */
294                     ih264d_process_inter_mb(ps_dec, ps_cur_mb_info, j);
295                     isvcd_update_inter_mb_inter_layer_info(ps_svc_lyr_dec, ps_cur_mb_info, 1);
296                     *pu2_res_luma_csbp = ps_cur_mb_info->u2_luma_csbp;
297                 }
298                 ps_dec->pi1_left_pred_mode[0] = DC;
299                 ps_dec->pi1_left_pred_mode[1] = DC;
300                 ps_dec->pi1_left_pred_mode[2] = DC;
301                 ps_dec->pi1_left_pred_mode[3] = DC;
302 
303                 ps_cur_mb_info->ps_curmb->pi1_intrapredmodes[0] = DC;
304                 ps_cur_mb_info->ps_curmb->pi1_intrapredmodes[1] = DC;
305                 ps_cur_mb_info->ps_curmb->pi1_intrapredmodes[2] = DC;
306                 ps_cur_mb_info->ps_curmb->pi1_intrapredmodes[3] = DC;
307 
308                 isvcd_update_ibl_mb_inter_layer_info(ps_svc_lyr_dec, ps_cur_mb_info);
309             }
310 
311             if(ps_dec->u4_use_intrapred_line_copy == 1)
312                 ih264d_copy_intra_pred_line(ps_dec, ps_cur_mb_info, j);
313         }
314 
315         DATA_SYNC();
316 
317         u4_mb_num = ps_cur_mb_info->u2_mbx + ps_dec->u2_frm_wd_in_mbs * ps_cur_mb_info->u2_mby;
318         UPDATE_MB_MAP_MBNUM_BYTE(ps_dec->pu1_recon_mb_map, u4_mb_num);
319         ps_dec->cur_dec_mb_num++;
320     }
321 
322     /*N MB deblocking*/
323     if(ps_dec->u4_nmb_deblk == 1)
324     {
325         UWORD32 u4_wd_y, u4_wd_uv;
326         tfr_ctxt_t *ps_tfr_cxt = &(ps_dec->s_tran_addrecon);
327         UWORD8 u1_field_pic_flag = ps_dec->ps_cur_slice->u1_field_pic_flag;
328         const WORD32 i4_cb_qp_idx_ofst = ps_dec->ps_cur_pps->i1_chroma_qp_index_offset;
329         const WORD32 i4_cr_qp_idx_ofst = ps_dec->ps_cur_pps->i1_second_chroma_qp_index_offset;
330 
331         u4_wd_y = ps_dec->u2_frm_wd_y << u1_field_pic_flag;
332         u4_wd_uv = ps_dec->u2_frm_wd_uv << u1_field_pic_flag;
333 
334         ps_cur_mb_info = &ps_dec->ps_frm_mb_info[ps_dec->u4_cur_deblk_mb_num];
335 
336         ps_dec->u4_deblk_mb_x = ps_cur_mb_info->u2_mbx;
337         ps_dec->u4_deblk_mb_y = ps_cur_mb_info->u2_mby;
338 
339         for(j = 0; j < i; j++)
340         {
341             ih264d_deblock_mb_nonmbaff(ps_dec, ps_tfr_cxt, i4_cb_qp_idx_ofst, i4_cr_qp_idx_ofst,
342                                        u4_wd_y, u4_wd_uv);
343         }
344     }
345 
346     /*handle the last mb in picture case*/
347     if(ps_dec->cur_dec_mb_num > ps_dec->ps_cur_sps->u2_max_mb_addr)
348         ps_dec->u4_cur_slice_decode_done = 1;
349 
350     if(i != u1_num_mbs)
351     {
352         u1_end_of_row = 0;
353         /*Number of MB's left in row*/
354         u1_num_mbs_next = u1_num_mbs_next + ((u1_num_mbs - i) >> u1_mbaff);
355     }
356 
357     ih264d_decode_tfr_nmb(ps_dec, (i), u1_num_mbs_next, u1_end_of_row);
358 
359     return OK;
360 }
361 
362 /*****************************************************************************/
363 /*                                                                           */
364 /*  Function Name : isvcd_decode_slice_thread                                */
365 /*                                                                           */
366 /*  Description   :                                                          */
367 /*                :                                                          */
368 /*                :                                                          */
369 /*  Inputs        :                                                          */
370 /*  Processing    :                                                          */
371 /*                                                                           */
372 /*  Outputs       :                                                          */
373 /*  Returns       : 0 on success                                             */
374 /*                                                                           */
375 /*  Revision History:                                                        */
376 /*                                                                           */
377 /*         DD MM YYYY   Author(s)       Changes (Describe the changes made)  */
378 /*                      ITTIAM                                               */
379 /*****************************************************************************/
isvcd_decode_slice_thread(svc_dec_lyr_struct_t * ps_svc_lyr_dec)380 WORD32 isvcd_decode_slice_thread(svc_dec_lyr_struct_t *ps_svc_lyr_dec)
381 {
382     UWORD8 u1_num_mbs_next, u1_num_mbsleft, u1_end_of_row = 0;
383     dec_struct_t *ps_dec = &ps_svc_lyr_dec->s_dec;
384     const UWORD32 i2_pic_wdin_mbs = ps_dec->u2_frm_wd_in_mbs;
385     UWORD8 u1_mbaff, u1_num_mbs;
386 
387     UWORD16 u2_first_mb_in_slice;
388     UWORD16 i16_mb_x, i16_mb_y;
389     UWORD8 u1_field_pic;
390     UWORD32 u4_frame_stride, x_offset, y_offset;
391     WORD32 ret;
392     tfr_ctxt_t *ps_trns_addr;
393 
394     /*check for mb map of first mb in slice to ensure slice header is parsed*/
395     while(1)
396     {
397         UWORD32 u4_mb_num = ps_dec->cur_dec_mb_num;
398         UWORD32 u4_cond = 0;
399         WORD32 nop_cnt = 8 * 128;
400         CHECK_MB_MAP_BYTE(u4_mb_num, ps_dec->pu1_dec_mb_map, u4_cond);
401         if(u4_cond)
402         {
403             break;
404         }
405         else
406         {
407             if(nop_cnt > 0)
408             {
409                 nop_cnt -= 128;
410                 NOP(128);
411             }
412             else if(ps_dec->u4_output_present && (2 == ps_dec->u4_num_cores) &&
413                     (ps_dec->u4_fmt_conv_cur_row < ps_dec->s_disp_frame_info.u4_y_ht))
414             {
415                 ps_dec->u4_fmt_conv_num_rows =
416                     MIN(FMT_CONV_NUM_ROWS,
417                         (ps_dec->s_disp_frame_info.u4_y_ht - ps_dec->u4_fmt_conv_cur_row));
418                 ih264d_format_convert(ps_dec, &(ps_dec->s_disp_op), ps_dec->u4_fmt_conv_cur_row,
419                                       ps_dec->u4_fmt_conv_num_rows);
420                 ps_dec->u4_fmt_conv_cur_row += ps_dec->u4_fmt_conv_num_rows;
421             }
422             else
423             {
424                 nop_cnt = 8 * 128;
425                 ithread_yield();
426             }
427             if(1 == ps_svc_lyr_dec->u1_error_in_cur_frame)
428             {
429                 return NOT_OK;
430             }
431             DEBUG_THREADS_PRINTF(
432                 "waiting for mb mapcur_dec_mb_num = %d,ps_dec->u2_cur_mb_addr  = "
433                 "%d\n",
434                 u2_cur_dec_mb_num, ps_dec->u2_cur_mb_addr);
435         }
436     }
437 
438     u1_mbaff = ps_dec->ps_cur_slice->u1_mbaff_frame_flag;
439     u2_first_mb_in_slice = ps_dec->ps_decode_cur_slice->u4_first_mb_in_slice;
440     i16_mb_x = MOD(u2_first_mb_in_slice, i2_pic_wdin_mbs);
441     i16_mb_y = DIV(u2_first_mb_in_slice, i2_pic_wdin_mbs);
442     i16_mb_y <<= u1_mbaff;
443     ps_dec->i2_dec_thread_mb_y = i16_mb_y;
444     ps_dec->cur_dec_mb_num = u2_first_mb_in_slice << u1_mbaff;
445 
446     if((ps_dec->u4_num_cores == 2) || !ps_dec->i1_recon_in_thread3_flag)
447     {
448         ps_dec->pv_proc_tu_coeff_data =
449             (void *) ps_dec->ps_decode_cur_slice->pv_tu_coeff_data_start;
450     }
451 
452     // recalculate recon pointers
453     u1_field_pic = ps_dec->ps_cur_slice->u1_field_pic_flag;
454     u4_frame_stride = ps_dec->u2_frm_wd_y << u1_field_pic;
455     x_offset = i16_mb_x << 4;
456     y_offset = (i16_mb_y * u4_frame_stride) << 4;
457 
458     ps_trns_addr = &(ps_dec->s_tran_addrecon);
459 
460     ps_trns_addr->pu1_dest_y = ps_dec->s_cur_pic.pu1_buf1 + x_offset + y_offset;
461 
462     u4_frame_stride = ps_dec->u2_frm_wd_uv << u1_field_pic;
463     x_offset >>= 1;
464     y_offset = (i16_mb_y * u4_frame_stride) << 3;
465     x_offset *= YUV420SP_FACTOR;
466 
467     ps_trns_addr->pu1_dest_u = ps_dec->s_cur_pic.pu1_buf2 + x_offset + y_offset;
468     ps_trns_addr->pu1_dest_v = ps_dec->s_cur_pic.pu1_buf3 + x_offset + y_offset;
469 
470     ps_trns_addr->pu1_mb_y = ps_trns_addr->pu1_dest_y;
471     ps_trns_addr->pu1_mb_u = ps_trns_addr->pu1_dest_u;
472     ps_trns_addr->pu1_mb_v = ps_trns_addr->pu1_dest_v;
473 
474     /* Initialise MC and formMbPartInfo fn ptrs one time based on profile_idc */
475     {
476         ps_dec->p_mc_dec_thread = ih264d_motion_compensate_bp;
477         ps_dec->p_form_mb_part_info_thread = ih264d_form_mb_part_info_bp;
478     }
479     {
480         UWORD8 uc_nofield_nombaff;
481         uc_nofield_nombaff = ((ps_dec->ps_cur_slice->u1_field_pic_flag == 0) &&
482                               (ps_dec->ps_cur_slice->u1_mbaff_frame_flag == 0) &&
483                               (ps_dec->ps_decode_cur_slice->slice_type != B_SLICE) &&
484                               (ps_dec->ps_cur_pps->u1_wted_pred_flag == 0));
485 
486         if(uc_nofield_nombaff == 0)
487         {
488             ps_dec->p_mc_dec_thread = ih264d_motion_compensate_mp;
489             ps_dec->p_form_mb_part_info_thread = ih264d_form_mb_part_info_mp;
490         }
491     }
492 
493     ps_dec->u4_cur_slice_decode_done = 0;
494 
495     while(ps_dec->u4_cur_slice_decode_done != 1)
496     {
497         u1_num_mbsleft = ((i2_pic_wdin_mbs - i16_mb_x) << u1_mbaff);
498 
499         if(u1_num_mbsleft <= ps_dec->u1_recon_mb_grp)
500         {
501             u1_num_mbs = u1_num_mbsleft;
502 
503             /*Indicate number of mb's left in a row*/
504             u1_num_mbs_next = 0;
505             u1_end_of_row = 1;
506             i16_mb_x = 0;
507         }
508         else
509         {
510             u1_num_mbs = ps_dec->u1_recon_mb_grp;
511 
512             /*Indicate number of mb's left in a row*/
513             u1_num_mbs_next = i2_pic_wdin_mbs - i16_mb_x - (ps_dec->u1_recon_mb_grp >> u1_mbaff);
514             i16_mb_x += (u1_num_mbs >> u1_mbaff);
515             u1_end_of_row = 0;
516         }
517         if(ps_svc_lyr_dec->u1_layer_identifier == TARGET_LAYER)
518         {
519             ret = isvcd_decode_recon_tfr_nmb_thread(ps_svc_lyr_dec, u1_num_mbs, u1_num_mbs_next,
520                                                     u1_end_of_row);
521         }
522         if(ret != OK) return ret;
523     }
524     return OK;
525 }
526 
527 /*****************************************************************************/
528 /*                                                                           */
529 /*  Function Name : isvcd_decode_picture_thread                              */
530 /*                                                                           */
531 /*  Description   :                                                          */
532 /*                :                                                          */
533 /*                :                                                          */
534 /*  Inputs        :                                                          */
535 /*  Processing    :                                                          */
536 /*                                                                           */
537 /*  Outputs       :                                                          */
538 /*  Returns       : None                                                     */
539 /*                                                                           */
540 /*  Revision History:                                                        */
541 /*                                                                           */
542 /*         DD MM YYYY   Author(s)       Changes (Describe the changes made)  */
543 /*                      ITTIAM                                               */
544 /*****************************************************************************/
isvcd_decode_picture_thread(svc_dec_lyr_struct_t * ps_svc_lyr_dec)545 void isvcd_decode_picture_thread(svc_dec_lyr_struct_t *ps_svc_lyr_dec)
546 {
547     dec_struct_t *ps_dec = &ps_svc_lyr_dec->s_dec;
548     WORD32 ret;
549     ithread_set_name("isvcd_decode_picture_thread");
550     while(1)
551     {
552 #ifdef KEEP_THREADS_ACTIVE
553         ret = ithread_mutex_lock(ps_dec->apv_proc_start_mutex[0]);
554         if(OK != ret) break;
555 
556         while(ps_dec->ai4_process_start[0] != PROC_START)
557         {
558             ithread_cond_wait(ps_dec->apv_proc_start_condition[0], ps_dec->apv_proc_start_mutex[0]);
559         }
560         ps_dec->ai4_process_start[0] = PROC_IN_PROGRESS;
561 
562         ret = ithread_mutex_unlock(ps_dec->apv_proc_start_mutex[0]);
563         if(OK != ret || ps_dec->i4_break_threads == 1) break;
564 #endif
565         while(1)
566         {
567             /*Complete all writes before processing next slice*/
568 
569             DEBUG_THREADS_PRINTF(" Entering decode slice svc ext\n");
570 
571             ret = isvcd_decode_slice_thread(ps_svc_lyr_dec);
572             if(OK != ret) break;
573             DEBUG_THREADS_PRINTF(" Exit  isvcd_decode_slice_thread\n");
574 
575             if(ps_dec->cur_dec_mb_num > ps_dec->ps_cur_sps->u2_max_mb_addr)
576             {
577                 /*Last slice in frame*/
578                 break;
579             }
580             else
581             {
582                 ps_dec->ps_decode_cur_slice++;
583                 ps_dec->u2_cur_slice_num_dec_thread++;
584             }
585         }
586         if(ps_dec->u4_output_present && (2 == ps_dec->u4_num_cores) &&
587            (ps_dec->u4_fmt_conv_cur_row < ps_dec->s_disp_frame_info.u4_y_ht))
588         {
589             ps_dec->u4_fmt_conv_num_rows =
590                 (ps_dec->s_disp_frame_info.u4_y_ht - ps_dec->u4_fmt_conv_cur_row);
591             ih264d_format_convert(ps_dec, &(ps_dec->s_disp_op), ps_dec->u4_fmt_conv_cur_row,
592                                   ps_dec->u4_fmt_conv_num_rows);
593             ps_dec->u4_fmt_conv_cur_row += ps_dec->u4_fmt_conv_num_rows;
594         }
595 #ifdef KEEP_THREADS_ACTIVE
596         ret = ithread_mutex_lock(ps_dec->apv_proc_done_mutex[0]);
597         if(OK != ret) break;
598 
599         ps_dec->ai4_process_done[0] = PROC_DONE;
600         ithread_cond_signal(ps_dec->apv_proc_done_condition[0]);
601 
602         ret = ithread_mutex_unlock(ps_dec->apv_proc_done_mutex[0]);
603         if(OK != ret) break;
604 #else
605         break;
606 #endif
607     }
608 }
609