Home | History | Annotate | Download | only in decoder
      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 
     54 void ih264d_deblock_mb_level(dec_struct_t *ps_dec,
     55                              dec_mb_info_t *ps_cur_mb_info,
     56                              UWORD32 nmb_index);
     57 
     58 void ih264d_copy_intra_pred_line(dec_struct_t *ps_dec,
     59                                  dec_mb_info_t *ps_cur_mb_info,
     60                                  UWORD32 nmb_index);
     61 
     62 void 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 
    167 void 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 
    200 WORD32 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 
    438 WORD32 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 
    593 void 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 
    632 void 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 }
    640 void 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