1/******************************************************************************
2 *
3 * Copyright (C) 2015 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 ih264d_thread_parse_decode.c
23 *
24 * \brief
25 *    Contains routines that for multi-thread decoder
26 *
27 * Detailed_description
28 *
29 * \date
30 *    20/02/2012
31 *
32 * \author  ZR
33 **************************************************************************
34 */
35
36#include "ih264d_error_handler.h"
37#include "ih264d_debug.h"
38#include "ithread.h"
39#include <string.h>
40#include "ih264d_defs.h"
41#include "ih264d_debug.h"
42#include "ih264d_tables.h"
43#include "ih264d_structs.h"
44#include "ih264d_defs.h"
45#include "ih264d_mb_utils.h"
46#include "ih264d_thread_parse_decode.h"
47#include "ih264d_inter_pred.h"
48
49#include "ih264d_process_pslice.h"
50#include "ih264d_process_intra_mb.h"
51#include "ih264d_deblocking.h"
52#include "ih264d_format_conv.h"
53
54void ih264d_deblock_mb_level(dec_struct_t *ps_dec,
55                             dec_mb_info_t *ps_cur_mb_info,
56                             UWORD32 nmb_index);
57
58void ih264d_copy_intra_pred_line(dec_struct_t *ps_dec,
59                                 dec_mb_info_t *ps_cur_mb_info,
60                                 UWORD32 nmb_index);
61
62void ih264d_parse_tfr_nmb(dec_struct_t * ps_dec,
63                          UWORD8 u1_mb_idx,
64                          UWORD8 u1_num_mbs,
65                          UWORD8 u1_num_mbs_next,
66                          UWORD8 u1_tfr_n_mb,
67                          UWORD8 u1_end_of_row)
68{
69    WORD32 i, u4_mb_num;
70
71    const UWORD32 u1_mbaff = ps_dec->ps_cur_slice->u1_mbaff_frame_flag;
72    UWORD32 u4_n_mb_start;
73
74    UNUSED(u1_mb_idx);
75    UNUSED(u1_num_mbs_next);
76    if(u1_tfr_n_mb)
77    {
78
79
80        u4_n_mb_start = (ps_dec->u2_cur_mb_addr + 1) - u1_num_mbs;
81
82        // copy into s_frmMbInfo
83
84        u4_mb_num = u4_n_mb_start;
85        u4_mb_num = (ps_dec->u2_cur_mb_addr + 1) - u1_num_mbs;
86
87        for(i = 0; i < u1_num_mbs; i++)
88        {
89            UPDATE_SLICE_NUM_MAP(ps_dec->pu2_slice_num_map, u4_mb_num,
90                                 ps_dec->u2_cur_slice_num);
91            DATA_SYNC();
92            UPDATE_MB_MAP_MBNUM_BYTE(ps_dec->pu1_dec_mb_map, u4_mb_num);
93
94            u4_mb_num++;
95        }
96
97        /****************************************************************/
98        /* Check for End Of Row in Next iteration                       */
99        /****************************************************************/
100
101        /****************************************************************/
102        /* Transfer the Following things                                */
103        /* N-Mb DeblkParams Data    ( To Ext DeblkParams Buffer )       */
104        /* N-Mb Recon Data          ( To Ext Frame Buffer )             */
105        /* N-Mb Intrapredline Data  ( Updated Internally)               */
106        /* N-Mb MV Data             ( To Ext MV Buffer )                */
107        /* N-Mb MVTop/TopRight Data ( To Int MV Top Scratch Buffers)    */
108        /****************************************************************/
109
110        /* Swap top and current pointers */
111
112        ps_dec->s_tran_addrecon_parse.pu1_dest_y +=
113                        ps_dec->s_tran_addrecon_parse.u4_inc_y[u1_end_of_row];
114        ps_dec->s_tran_addrecon_parse.pu1_dest_u +=
115                        ps_dec->s_tran_addrecon_parse.u4_inc_uv[u1_end_of_row];
116        ps_dec->s_tran_addrecon_parse.pu1_dest_v +=
117                        ps_dec->s_tran_addrecon_parse.u4_inc_uv[u1_end_of_row];
118
119        if(u1_end_of_row)
120        {
121            UWORD16 u2_mb_y;
122            UWORD32 u4_frame_stride, y_offset;
123
124            ps_dec->ps_top_mb_row = ps_dec->ps_cur_mb_row;
125            ps_dec->ps_cur_mb_row += ((ps_dec->u2_frm_wd_in_mbs) << u1_mbaff);
126
127            u2_mb_y = ps_dec->u2_mby + (1 + u1_mbaff);
128            u4_frame_stride = ps_dec->u2_frm_wd_y
129                            << ps_dec->ps_cur_slice->u1_field_pic_flag;
130            y_offset = (u2_mb_y * u4_frame_stride) << 4;
131            ps_dec->s_tran_addrecon_parse.pu1_dest_y =
132                            ps_dec->s_cur_pic.pu1_buf1 + y_offset;
133
134            u4_frame_stride = ps_dec->u2_frm_wd_uv
135                            << ps_dec->ps_cur_slice->u1_field_pic_flag;
136            y_offset = (u2_mb_y * u4_frame_stride) << 3;
137            ps_dec->s_tran_addrecon_parse.pu1_dest_u =
138                            ps_dec->s_cur_pic.pu1_buf2 + y_offset;
139            ps_dec->s_tran_addrecon_parse.pu1_dest_v =
140                            ps_dec->s_cur_pic.pu1_buf3 + y_offset;
141
142        }
143
144        ps_dec->ps_deblk_mbn += u1_num_mbs;
145
146        /*
147         * The Slice boundary is also a valid condition to transfer. So recalculate
148         * the Left increment, in case the number of MBs is lesser than the
149         * N MB value. c_numMbs will be equal to N of N MB if the entire N Mb is
150         * decoded.
151         */
152        ps_dec->s_tran_addrecon.u2_mv_left_inc = ((u1_num_mbs >> u1_mbaff) - 1)
153                        << (4 + u1_mbaff);
154        ps_dec->s_tran_addrecon.u2_mv_top_left_inc = (u1_num_mbs << 2) - 1
155                        - (u1_mbaff << 2);
156
157        /* reassign left MV and cur MV pointers */
158        ps_dec->ps_mv_left = ps_dec->ps_mv_cur
159                        + ps_dec->s_tran_addrecon.u2_mv_left_inc;
160
161        ps_dec->ps_mv_cur += (u1_num_mbs << 4);
162        ps_dec->u4_num_mbs_prev_nmb = u1_num_mbs;
163
164    }
165}
166
167void ih264d_decode_tfr_nmb(dec_struct_t * ps_dec,
168                           UWORD8 u1_num_mbs,
169                           UWORD8 u1_num_mbs_next,
170                           UWORD8 u1_end_of_row)
171{
172
173    UWORD32 u1_end_of_row_next;
174
175    const UWORD32 u1_mbaff = ps_dec->ps_cur_slice->u1_mbaff_frame_flag;
176
177    /****************************************************************/
178    /* Check for End Of Row in Next iteration                       */
179    /****************************************************************/
180    u1_end_of_row_next = u1_num_mbs_next &&
181                        ((u1_num_mbs_next) <= (ps_dec->u1_recon_mb_grp >> u1_mbaff));
182
183    /****************************************************************/
184    /* Transfer the Following things                                */
185    /* N-Mb DeblkParams Data    ( To Ext DeblkParams Buffer )       */
186    /* N-Mb Recon Data          ( To Ext Frame Buffer )             */
187    /* N-Mb Intrapredline Data  ( Updated Internally)               */
188    /* N-Mb MV Data             ( To Ext MV Buffer )                */
189    /* N-Mb MVTop/TopRight Data ( To Int MV Top Scratch Buffers)    */
190    /****************************************************************/
191    if(u1_end_of_row)
192    {
193        ps_dec->i2_dec_thread_mb_y += (1 << u1_mbaff);
194    }
195    ih264d_transfer_mb_group_data(ps_dec, u1_num_mbs, u1_end_of_row,
196                                  u1_end_of_row_next);
197
198}
199
200WORD32 ih264d_decode_recon_tfr_nmb_thread(dec_struct_t * ps_dec,
201                                          UWORD8 u1_num_mbs,
202                                          UWORD8 u1_num_mbs_next,
203                                          UWORD8 u1_end_of_row)
204{
205    WORD32 i,j;
206    dec_mb_info_t * ps_cur_mb_info;
207    UWORD32 u4_update_mbaff = 0;
208    const UWORD32 u1_mbaff = ps_dec->ps_cur_slice->u1_mbaff_frame_flag;
209    UWORD32 u1_slice_type, u1_B;
210    WORD32 u1_skip_th;
211    UWORD32 u1_ipcm_th;
212    UWORD32 u4_cond;
213    UWORD16 u2_slice_num,u2_cur_dec_mb_num;
214    WORD32 ret;
215    UWORD32 u4_mb_num;
216    WORD32 nop_cnt = 8*128;
217    u1_slice_type = ps_dec->ps_decode_cur_slice->slice_type;
218
219    u1_B = (u1_slice_type == B_SLICE);
220
221    u1_skip_th = ((u1_slice_type != I_SLICE) ?
222                                    (u1_B ? B_8x8 : PRED_8x8R0) : -1);
223
224    u1_ipcm_th = ((u1_slice_type != I_SLICE) ? (u1_B ? 23 : 5) : 0);
225
226    u2_cur_dec_mb_num = ps_dec->cur_dec_mb_num;
227
228    while(1)
229    {
230
231        UWORD32 u4_max_mb = (UWORD32)(ps_dec->i2_dec_thread_mb_y + (1 << u1_mbaff)) * ps_dec->u2_frm_wd_in_mbs - 1;
232        u4_mb_num = u2_cur_dec_mb_num;
233        /*introducing 1 MB delay*/
234        u4_mb_num = MIN(u4_mb_num + u1_num_mbs + 1, u4_max_mb);
235
236        CHECK_MB_MAP_BYTE(u4_mb_num, ps_dec->pu1_dec_mb_map, u4_cond);
237        if(u4_cond)
238        {
239            break;
240        }
241        else
242        {
243            if(nop_cnt > 0)
244            {
245                nop_cnt -= 128;
246                NOP(128);
247            }
248            else
249            {
250                if(ps_dec->u4_output_present && (2 == ps_dec->u4_num_cores) &&
251                   (ps_dec->u4_fmt_conv_cur_row < ps_dec->s_disp_frame_info.u4_y_ht))
252                {
253                    ps_dec->u4_fmt_conv_num_rows =
254                                MIN(FMT_CONV_NUM_ROWS,
255                                    (ps_dec->s_disp_frame_info.u4_y_ht
256                                                    - ps_dec->u4_fmt_conv_cur_row));
257                    ih264d_format_convert(ps_dec, &(ps_dec->s_disp_op),
258                                          ps_dec->u4_fmt_conv_cur_row,
259                                          ps_dec->u4_fmt_conv_num_rows);
260                    ps_dec->u4_fmt_conv_cur_row += ps_dec->u4_fmt_conv_num_rows;
261                }
262                else
263                {
264                    nop_cnt = 8*128;
265                    ithread_yield();
266                }
267            }
268        }
269    }
270    /* N Mb MC Loop */
271    for(i = 0; i < u1_num_mbs; i++)
272    {
273        u4_mb_num = u2_cur_dec_mb_num;
274
275        GET_SLICE_NUM_MAP(ps_dec->pu2_slice_num_map, u2_cur_dec_mb_num,
276                          u2_slice_num);
277
278        if(u2_slice_num != ps_dec->u2_cur_slice_num_dec_thread)
279        {
280            ps_dec->u4_cur_slice_decode_done = 1;
281            break;
282        }
283
284        ps_cur_mb_info = &ps_dec->ps_frm_mb_info[u2_cur_dec_mb_num];
285
286        ps_dec->u4_dma_buf_idx = 0;
287        ps_dec->u4_pred_info_idx = 0;
288
289        if(ps_cur_mb_info->u1_mb_type <= u1_skip_th)
290        {
291            WORD32 pred_cnt = 0;
292            pred_info_pkd_t *ps_pred_pkd;
293            UWORD32 u4_pred_info_pkd_idx;
294            WORD8 i1_pred;
295
296            u4_pred_info_pkd_idx = ps_cur_mb_info->u4_pred_info_pkd_idx;
297
298            while(pred_cnt < ps_cur_mb_info->u1_num_pred_parts)
299            {
300                ps_pred_pkd = ps_dec->ps_pred_pkd + u4_pred_info_pkd_idx;
301
302                ps_dec->p_form_mb_part_info_thread(ps_pred_pkd,ps_dec,
303                                                   ps_cur_mb_info->u2_mbx,
304                                                   ps_cur_mb_info->u2_mby,
305                                                   (i >> u1_mbaff),
306                                                   ps_cur_mb_info);
307
308                u4_pred_info_pkd_idx++;
309                pred_cnt++;
310            }
311            ps_dec->p_mc_dec_thread(ps_dec, ps_cur_mb_info);
312        }
313        else if(ps_cur_mb_info->u1_mb_type == MB_SKIP)
314        {
315            WORD32 pred_cnt = 0;
316            pred_info_pkd_t *ps_pred_pkd;
317            UWORD32 u4_pred_info_pkd_idx;
318            WORD8 i1_pred;
319
320            u4_pred_info_pkd_idx = ps_cur_mb_info->u4_pred_info_pkd_idx;
321
322            while(pred_cnt < ps_cur_mb_info->u1_num_pred_parts)
323            {
324                ps_pred_pkd = ps_dec->ps_pred_pkd + u4_pred_info_pkd_idx;
325
326                ps_dec->p_form_mb_part_info_thread(ps_pred_pkd,ps_dec,
327                                                   ps_cur_mb_info->u2_mbx,
328                                                   ps_cur_mb_info->u2_mby,
329                                                   (i >> u1_mbaff),
330                                                   ps_cur_mb_info);
331
332                u4_pred_info_pkd_idx++;
333                pred_cnt++;
334            }
335            /* Decode MB skip */
336            ps_dec->p_mc_dec_thread(ps_dec, ps_cur_mb_info);
337        }
338
339        u2_cur_dec_mb_num++;
340    }
341
342    /* N Mb IQ IT RECON  Loop */
343    for(j = 0; j < i; j++)
344    {
345        ps_cur_mb_info = &ps_dec->ps_frm_mb_info[ps_dec->cur_dec_mb_num];
346
347        if((ps_dec->u4_num_cores == 2) || !ps_dec->i1_recon_in_thread3_flag)
348        {
349            if(ps_cur_mb_info->u1_mb_type <= u1_skip_th)
350            {
351                ih264d_process_inter_mb(ps_dec, ps_cur_mb_info, j);
352            }
353            else if(ps_cur_mb_info->u1_mb_type != MB_SKIP)
354            {
355                if((u1_ipcm_th + 25) != ps_cur_mb_info->u1_mb_type)
356                {
357                    ps_cur_mb_info->u1_mb_type -= (u1_skip_th + 1);
358                    ih264d_process_intra_mb(ps_dec, ps_cur_mb_info, j);
359                }
360            }
361
362
363         if(ps_dec->u4_use_intrapred_line_copy == 1)
364                ih264d_copy_intra_pred_line(ps_dec, ps_cur_mb_info, j);
365        }
366
367        DATA_SYNC();
368
369        if(u1_mbaff)
370        {
371            if(u4_update_mbaff)
372            {
373                UWORD32 u4_mb_num = ps_cur_mb_info->u2_mbx
374                                + ps_dec->u2_frm_wd_in_mbs
375                                                * (ps_cur_mb_info->u2_mby >> 1);
376                UPDATE_MB_MAP_MBNUM_BYTE(ps_dec->pu1_recon_mb_map, u4_mb_num);
377                u4_update_mbaff = 0;
378            }
379            else
380            {
381                u4_update_mbaff = 1;
382            }
383        }
384        else
385        {
386            UWORD32 u4_mb_num = ps_cur_mb_info->u2_mbx
387                            + ps_dec->u2_frm_wd_in_mbs * ps_cur_mb_info->u2_mby;
388            UPDATE_MB_MAP_MBNUM_BYTE(ps_dec->pu1_recon_mb_map, u4_mb_num);
389        }
390        ps_dec->cur_dec_mb_num++;
391     }
392
393    /*N MB deblocking*/
394    if(ps_dec->u4_nmb_deblk == 1)
395    {
396        UWORD32 u4_wd_y, u4_wd_uv;
397        tfr_ctxt_t *ps_tfr_cxt = &(ps_dec->s_tran_addrecon);
398        UWORD8 u1_field_pic_flag = ps_dec->ps_cur_slice->u1_field_pic_flag;
399        const WORD32 i4_cb_qp_idx_ofst =
400                       ps_dec->ps_cur_pps->i1_chroma_qp_index_offset;
401        const WORD32 i4_cr_qp_idx_ofst =
402                       ps_dec->ps_cur_pps->i1_second_chroma_qp_index_offset;
403
404        u4_wd_y = ps_dec->u2_frm_wd_y << u1_field_pic_flag;
405        u4_wd_uv = ps_dec->u2_frm_wd_uv << u1_field_pic_flag;
406
407        ps_cur_mb_info = &ps_dec->ps_frm_mb_info[ps_dec->u4_cur_deblk_mb_num];
408
409        ps_dec->u4_deblk_mb_x = ps_cur_mb_info->u2_mbx;
410        ps_dec->u4_deblk_mb_y = ps_cur_mb_info->u2_mby;
411
412
413        for(j = 0; j < i; j++)
414        {
415            ih264d_deblock_mb_nonmbaff(ps_dec, ps_tfr_cxt,
416                                       i4_cb_qp_idx_ofst, i4_cr_qp_idx_ofst,
417                                        u4_wd_y, u4_wd_uv);
418
419        }
420    }
421
422    /*handle the last mb in picture case*/
423    if(ps_dec->cur_dec_mb_num > ps_dec->ps_cur_sps->u2_max_mb_addr)
424        ps_dec->u4_cur_slice_decode_done = 1;
425
426    if(i != u1_num_mbs)
427    {
428        u1_end_of_row = 0;
429        /*Number of MB's left in row*/
430        u1_num_mbs_next = u1_num_mbs_next + ((u1_num_mbs - i) >> u1_mbaff);
431    }
432
433    ih264d_decode_tfr_nmb(ps_dec, (i), u1_num_mbs_next, u1_end_of_row);
434
435    return OK;
436}
437
438WORD32 ih264d_decode_slice_thread(dec_struct_t *ps_dec)
439{
440    UWORD8 u1_num_mbs_next, u1_num_mbsleft, u1_end_of_row = 0;
441    const UWORD32 i2_pic_wdin_mbs = ps_dec->u2_frm_wd_in_mbs;
442    UWORD8 u1_mbaff, u1_num_mbs;
443
444    UWORD16 u2_first_mb_in_slice;
445    UWORD16 i16_mb_x, i16_mb_y;
446    UWORD8 u1_field_pic;
447    UWORD32 u4_frame_stride, x_offset, y_offset;
448    WORD32 ret;
449
450    tfr_ctxt_t *ps_trns_addr;
451
452    /*check for mb map of first mb in slice to ensure slice header is parsed*/
453    while(1)
454    {
455        UWORD32 u4_mb_num = ps_dec->cur_dec_mb_num;
456        UWORD32 u4_cond = 0;
457        WORD32 nop_cnt = 8 * 128;
458        CHECK_MB_MAP_BYTE(u4_mb_num, ps_dec->pu1_dec_mb_map, u4_cond);
459        if(u4_cond)
460        {
461            break;
462        }
463        else
464        {
465            if(nop_cnt > 0)
466            {
467                nop_cnt -= 128;
468                NOP(128);
469            }
470            else if(ps_dec->u4_output_present && (2 == ps_dec->u4_num_cores) &&
471               (ps_dec->u4_fmt_conv_cur_row < ps_dec->s_disp_frame_info.u4_y_ht))
472            {
473                ps_dec->u4_fmt_conv_num_rows =
474                                MIN(FMT_CONV_NUM_ROWS,
475                                    (ps_dec->s_disp_frame_info.u4_y_ht
476                                                    - ps_dec->u4_fmt_conv_cur_row));
477                ih264d_format_convert(ps_dec, &(ps_dec->s_disp_op),
478                                      ps_dec->u4_fmt_conv_cur_row,
479                                      ps_dec->u4_fmt_conv_num_rows);
480                ps_dec->u4_fmt_conv_cur_row += ps_dec->u4_fmt_conv_num_rows;
481            }
482            else
483            {
484                nop_cnt = 8*128;
485                ithread_yield();
486            }
487            DEBUG_THREADS_PRINTF("waiting for mb mapcur_dec_mb_num = %d,ps_dec->u2_cur_mb_addr  = %d\n",u2_cur_dec_mb_num,
488                            ps_dec->u2_cur_mb_addr);
489
490        }
491    }
492
493
494
495    u1_mbaff = ps_dec->ps_cur_slice->u1_mbaff_frame_flag;
496
497    u2_first_mb_in_slice = ps_dec->ps_decode_cur_slice->u4_first_mb_in_slice;
498
499    i16_mb_x = MOD(u2_first_mb_in_slice, i2_pic_wdin_mbs);
500    i16_mb_y = DIV(u2_first_mb_in_slice, i2_pic_wdin_mbs);
501    i16_mb_y <<= u1_mbaff;
502    ps_dec->i2_dec_thread_mb_y = i16_mb_y;
503
504
505    ps_dec->cur_dec_mb_num = u2_first_mb_in_slice << u1_mbaff;
506
507    if((ps_dec->u4_num_cores == 2) || !ps_dec->i1_recon_in_thread3_flag)
508    {
509        ps_dec->pv_proc_tu_coeff_data =
510                (void *) ps_dec->ps_decode_cur_slice->pv_tu_coeff_data_start;
511    }
512
513    // recalculate recon pointers
514    u1_field_pic = ps_dec->ps_cur_slice->u1_field_pic_flag;
515    u4_frame_stride = ps_dec->u2_frm_wd_y << u1_field_pic;
516    x_offset = i16_mb_x << 4;
517    y_offset = (i16_mb_y * u4_frame_stride) << 4;
518
519    ps_trns_addr = &(ps_dec->s_tran_addrecon);
520
521    ps_trns_addr->pu1_dest_y = ps_dec->s_cur_pic.pu1_buf1 + x_offset + y_offset;
522
523    u4_frame_stride = ps_dec->u2_frm_wd_uv << u1_field_pic;
524    x_offset >>= 1;
525    y_offset = (i16_mb_y * u4_frame_stride) << 3;
526
527    x_offset *= YUV420SP_FACTOR;
528
529    ps_trns_addr->pu1_dest_u = ps_dec->s_cur_pic.pu1_buf2 + x_offset + y_offset;
530    ps_trns_addr->pu1_dest_v = ps_dec->s_cur_pic.pu1_buf3 + x_offset + y_offset;
531
532    ps_trns_addr->pu1_mb_y = ps_trns_addr->pu1_dest_y;
533    ps_trns_addr->pu1_mb_u = ps_trns_addr->pu1_dest_u;
534    ps_trns_addr->pu1_mb_v = ps_trns_addr->pu1_dest_v;
535
536
537    /* Initialise MC and formMbPartInfo fn ptrs one time based on profile_idc */
538    {
539        ps_dec->p_mc_dec_thread = ih264d_motion_compensate_bp;
540        ps_dec->p_form_mb_part_info_thread = ih264d_form_mb_part_info_bp;
541    }
542    {
543        UWORD8 uc_nofield_nombaff;
544        uc_nofield_nombaff = ((ps_dec->ps_cur_slice->u1_field_pic_flag == 0)
545                        && (ps_dec->ps_cur_slice->u1_mbaff_frame_flag == 0)
546                        && (ps_dec->ps_decode_cur_slice->slice_type != B_SLICE)
547                        && (ps_dec->ps_cur_pps->u1_wted_pred_flag == 0));
548
549        if(uc_nofield_nombaff == 0)
550        {
551            ps_dec->p_mc_dec_thread = ih264d_motion_compensate_mp;
552            ps_dec->p_form_mb_part_info_thread = ih264d_form_mb_part_info_mp;
553        }
554
555    }
556
557    ps_dec->u4_cur_slice_decode_done = 0;
558
559
560    while(ps_dec->u4_cur_slice_decode_done != 1)
561    {
562
563        u1_num_mbsleft = ((i2_pic_wdin_mbs - i16_mb_x) << u1_mbaff);
564
565        if(u1_num_mbsleft <= ps_dec->u1_recon_mb_grp)
566        {
567            u1_num_mbs = u1_num_mbsleft;
568
569            /*Indicate number of mb's left in a row*/
570            u1_num_mbs_next = 0;
571            u1_end_of_row = 1;
572            i16_mb_x = 0;
573        }
574        else
575        {
576            u1_num_mbs = ps_dec->u1_recon_mb_grp;
577
578            /*Indicate number of mb's left in a row*/
579            u1_num_mbs_next = i2_pic_wdin_mbs - i16_mb_x
580                            - (ps_dec->u1_recon_mb_grp >> u1_mbaff);
581            i16_mb_x += (u1_num_mbs >> u1_mbaff);
582            u1_end_of_row = 0;
583
584        }
585        ret = ih264d_decode_recon_tfr_nmb_thread(ps_dec, u1_num_mbs, u1_num_mbs_next,
586                                           u1_end_of_row);
587        if(ret != OK)
588            return ret;
589    }
590    return OK;
591}
592
593void ih264d_decode_picture_thread(dec_struct_t *ps_dec )
594{
595    ithread_set_name("ih264d_decode_picture_thread");
596    while(1)
597    {
598        /*Complete all writes before processing next slice*/
599
600        DEBUG_THREADS_PRINTF(" Entering decode slice\n");
601
602        ih264d_decode_slice_thread(ps_dec);
603        DEBUG_THREADS_PRINTF(" Exit  ih264d_decode_slice_thread \n");
604
605
606        if(ps_dec->cur_dec_mb_num
607                        > ps_dec->ps_cur_sps->u2_max_mb_addr)
608        {
609            /*Last slice in frame*/
610            break;
611        }
612        else
613        {
614            ps_dec->ps_decode_cur_slice++;
615            ps_dec->u2_cur_slice_num_dec_thread++;
616        }
617
618    }
619    if(ps_dec->u4_output_present && (2 == ps_dec->u4_num_cores) &&
620       (ps_dec->u4_fmt_conv_cur_row < ps_dec->s_disp_frame_info.u4_y_ht))
621    {
622        ps_dec->u4_fmt_conv_num_rows =
623                        (ps_dec->s_disp_frame_info.u4_y_ht
624                                        - ps_dec->u4_fmt_conv_cur_row);
625        ih264d_format_convert(ps_dec, &(ps_dec->s_disp_op),
626                              ps_dec->u4_fmt_conv_cur_row,
627                              ps_dec->u4_fmt_conv_num_rows);
628        ps_dec->u4_fmt_conv_cur_row += ps_dec->u4_fmt_conv_num_rows;
629    }
630}
631
632void ih264d_signal_decode_thread(dec_struct_t *ps_dec)
633{
634    if(ps_dec->u4_dec_thread_created == 1)
635    {
636        ithread_join(ps_dec->pv_dec_thread_handle, NULL);
637        ps_dec->u4_dec_thread_created = 0;
638    }
639}
640void ih264d_signal_bs_deblk_thread(dec_struct_t *ps_dec)
641{
642    if(ps_dec->u4_bs_deblk_thread_created)
643    {
644        ithread_join(ps_dec->pv_bs_deblk_thread_handle, NULL);
645        ps_dec->u4_bs_deblk_thread_created = 0;
646    }
647
648}
649