Home | History | Annotate | Download | only in decoder
      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_intra_pred_mode_prediction.c.c
     22  *
     23  * @brief
     24  *  Contains functions for intra pred mode prediction
     25  *
     26  * @author
     27  *  Ittiam
     28  *
     29  * @par List of Functions:
     30  * - ihevcd_intra_pred_mode_prediction()
     31  *
     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 
     45 #include "ihevc_typedefs.h"
     46 #include "iv.h"
     47 #include "ivd.h"
     48 #include "ihevcd_cxa.h"
     49 
     50 #include "ihevc_defs.h"
     51 #include "ihevc_debug.h"
     52 #include "ihevc_structs.h"
     53 #include "ihevc_macros.h"
     54 #include "ihevc_mem_fns.h"
     55 #include "ihevc_platform_macros.h"
     56 
     57 #include "ihevcd_defs.h"
     58 #include "ihevc_cabac_tables.h"
     59 #include "ihevcd_function_selector.h"
     60 #include "ihevcd_structs.h"
     61 #include "ihevcd_error.h"
     62 
     63 #include "ihevcd_bitstream.h"
     64 
     65 
     66 /*****************************************************************************/
     67 /* Function Prototypes                                                       */
     68 /*****************************************************************************/
     69 
     70 /*****************************************************************************/
     71 /* Availability check is not done inside the function                        */
     72 /* Whenever the top and left are not available, it is assumed that Intra DC  */
     73 /*                  mode will initialized in place of non available          */
     74 /*                  neighbors                                                */
     75 /*****************************************************************************/
     76 
     77 /**
     78 *******************************************************************************
     79 *
     80 * @brief Computes intra prediction mode for a CU
     81 *
     82 * @par   Description
     83 * Computes intra prediction mode for a CU
     84 *
     85 * @param[in,out] ps_cu
     86 * Codic unit context
     87 *
     88 * @param[in] ps_parse
     89 * parse context
     90 *
     91 * @param[in] ps_codec
     92 * codec context
     93 *
     94 * @param[in] log2_cb_size
     95 * log of cb size base 2
     96 *
     97 * @returns none
     98 *
     99 * @remarks
    100 * Availability check is moved to CTB level. If the neighbors are
    101 *  not available or if the pred mode of neighbor is not MODE_INTRA,
    102 *  INTRA_DC mode will be updated in top and left buffers.
    103 *******************************************************************************
    104 */
    105 void ihevcd_intra_pred_mode_prediction(codec_t *ps_codec,
    106                                        WORD32 log2_cb_size,
    107                                        WORD32 x0,
    108                                        WORD32 y0)
    109 {
    110     WORD32 i, j, num_pred_blocks;
    111     WORD32 available_l, available_t;
    112     WORD32 cand_intra_pred_mode_l, cand_intra_pred_mode_t;
    113     WORD32 cand_mode_list[3];
    114     WORD32 cb_size, block_offset_in_min_pu;
    115     UWORD8 *pu1_luma_intra_pred_mode_top;
    116     UWORD8 *pu1_luma_intra_pred_mode_left;
    117 
    118     parse_ctxt_t *ps_parse = &ps_codec->s_parse;
    119     parse_cu_t *ps_cu = &ps_codec->s_parse.s_cu;
    120     sps_t *ps_sps = ps_parse->ps_sps;
    121 
    122 
    123     available_t = 1;
    124     available_l = 1;
    125     /* i4_pos_x and i4_pos_y are in minCu units (8x8), convert them to 4x4 units by multiplying by 2 */
    126     pu1_luma_intra_pred_mode_top = ps_parse->pu1_luma_intra_pred_mode_top
    127                     + (ps_cu->i4_pos_x * 2);
    128 
    129     pu1_luma_intra_pred_mode_left = ps_parse->pu1_luma_intra_pred_mode_left
    130                     + (ps_cu->i4_pos_y * 2);
    131 
    132 /*
    133     if(0 == ps_cu->i4_pos_y)
    134     {
    135         memset(pu1_luma_intra_pred_mode_top, INTRA_DC, 16);
    136     }
    137 
    138     if(0 == ps_cu->i4_pos_x)
    139     {
    140         memset(pu1_luma_intra_pred_mode_left, INTRA_DC, 16);
    141     }
    142 */
    143     if(ps_cu->i4_pos_y)
    144     {
    145         UWORD8 *pu1_pic_intra_flag = ps_codec->s_parse.pu1_pic_intra_flag;
    146         WORD32 top_intra_flag;
    147 
    148         WORD32 numbytes_row =  (ps_sps->i2_pic_width_in_luma_samples + 63) / 64;
    149         pu1_pic_intra_flag += ((y0 - 8) / 8) * numbytes_row;
    150         pu1_pic_intra_flag += (x0 / 64);
    151         top_intra_flag = *pu1_pic_intra_flag;
    152         top_intra_flag &= (1 << ((x0 / 8) % 8));
    153 
    154         if(0 == top_intra_flag)
    155         {
    156             available_t = 0;
    157         }
    158     }
    159     else
    160         available_t = 0;
    161 
    162 
    163     if((0 == ps_cu->i4_pos_x) && (((0 == ps_codec->s_parse.i4_ctb_slice_x) && (0 == ps_codec->s_parse.i4_ctb_slice_y)) ||
    164                                   (0 == ps_codec->s_parse.i4_ctb_tile_x)))
    165     {
    166         available_l = 0;
    167     }
    168 
    169     if(available_l)
    170     {
    171         UWORD8 *pu1_pic_intra_flag = ps_codec->s_parse.pu1_pic_intra_flag;
    172         WORD32 left_intra_flag;
    173         WORD32 numbytes_row =  (ps_sps->i2_pic_width_in_luma_samples + 63) / 64;
    174         pu1_pic_intra_flag += (y0 / 8) * numbytes_row;
    175         pu1_pic_intra_flag += ((x0 - 8) / 64);
    176         left_intra_flag = *pu1_pic_intra_flag;
    177         left_intra_flag &= (1 << (((x0 - 8) / 8) % 8));
    178 
    179         if(0 == left_intra_flag)
    180         {
    181             available_l = 0;
    182         }
    183     }
    184 
    185     cb_size = (1 << log2_cb_size);
    186 
    187     block_offset_in_min_pu = (cb_size / 2) / MIN_PU_SIZE;
    188 
    189     num_pred_blocks = (ps_cu->i4_part_mode == PART_NxN) ? 2 : 1;
    190 
    191     for(i = 0; i < num_pred_blocks; i++)
    192     {
    193         WORD32 available_l_tmp;
    194         available_l_tmp = available_l;
    195         for(j = 0; j < num_pred_blocks; j++)
    196         {
    197             /* Computing Candidate intra pred mode left */
    198             {
    199                 WORD32 block_offset;
    200 
    201                 block_offset = i * block_offset_in_min_pu;
    202                 cand_intra_pred_mode_l = INTRA_DC;
    203                 if(available_l_tmp)
    204                 {
    205                     cand_intra_pred_mode_l =
    206                                     pu1_luma_intra_pred_mode_left[block_offset];
    207                 }
    208 
    209             }
    210 
    211             {
    212                 WORD32 block_offset;
    213                 block_offset = j * block_offset_in_min_pu;
    214                 cand_intra_pred_mode_t = INTRA_DC;
    215                 if(available_t)
    216                 {
    217                     cand_intra_pred_mode_t =
    218                                     pu1_luma_intra_pred_mode_top[block_offset];
    219                 }
    220             }
    221 
    222             /* Computing Candidate mode list */
    223             if(cand_intra_pred_mode_l == cand_intra_pred_mode_t)
    224             {
    225                 if(cand_intra_pred_mode_l < 2)
    226                 {
    227                     cand_mode_list[0] = INTRA_PLANAR;
    228                     cand_mode_list[1] = INTRA_DC;
    229                     cand_mode_list[2] = INTRA_ANGULAR(26); /* angular 26 = Vertical */
    230                 }
    231                 else
    232                 {
    233                     cand_mode_list[0] = cand_intra_pred_mode_l;
    234                     cand_mode_list[1] = 2
    235                                     + ((cand_intra_pred_mode_l + 29) % 32);
    236                     cand_mode_list[2] = 2
    237                                     + ((cand_intra_pred_mode_l - 2 + 1) % 32);
    238                 }
    239             }
    240             else
    241             {
    242                 cand_mode_list[0] = cand_intra_pred_mode_l;
    243                 cand_mode_list[1] = cand_intra_pred_mode_t;
    244 
    245                 if((cand_intra_pred_mode_l != INTRA_PLANAR)
    246                                 && (cand_intra_pred_mode_t != INTRA_PLANAR))
    247                 {
    248                     cand_mode_list[2] = INTRA_PLANAR;
    249                 }
    250                 else if((cand_intra_pred_mode_l != INTRA_DC)
    251                                 && (cand_intra_pred_mode_t != INTRA_DC))
    252                 {
    253                     cand_mode_list[2] = INTRA_DC;
    254                 }
    255                 else
    256                 {
    257                     cand_mode_list[2] = INTRA_ANGULAR(26);
    258                 }
    259             }
    260 
    261             /* Computing Intra pred mode */
    262             if(ps_cu->ai4_prev_intra_luma_pred_flag[2 * i + j] == 1)
    263             {
    264                 ps_cu->ai4_intra_luma_pred_mode[2 * i + j] =
    265                                 cand_mode_list[ps_cu->ai4_mpm_idx[2 * i + j]];
    266             }
    267             else
    268             {
    269                 WORD32 intra_pred_mode;
    270                 /* Arranging cand_mode_list in increasing order */
    271                 if(cand_mode_list[0] > cand_mode_list[1])
    272                 {
    273                     SWAP(cand_mode_list[0], cand_mode_list[1]);
    274                 }
    275                 if(cand_mode_list[0] > cand_mode_list[2])
    276                 {
    277                     SWAP(cand_mode_list[0], cand_mode_list[2]);
    278                 }
    279                 if(cand_mode_list[1] > cand_mode_list[2])
    280                 {
    281                     SWAP(cand_mode_list[1], cand_mode_list[2]);
    282                 }
    283 
    284                 intra_pred_mode = ps_cu->ai4_rem_intra_luma_pred_mode[2 * i + j];
    285 
    286                 if(intra_pred_mode >= cand_mode_list[0])
    287                     intra_pred_mode++;
    288 
    289                 if(intra_pred_mode >= cand_mode_list[1])
    290                     intra_pred_mode++;
    291 
    292                 if(intra_pred_mode >= cand_mode_list[2])
    293                     intra_pred_mode++;
    294 
    295                 ps_cu->ai4_intra_luma_pred_mode[2 * i + j] = intra_pred_mode;
    296             }
    297             /* Update Top and Left intra pred mode */
    298             {
    299                 WORD32 intra_pred_mode;
    300 
    301                 intra_pred_mode = ps_cu->ai4_intra_luma_pred_mode[2 * i + j];
    302 
    303                 ps_codec->s_func_selector.ihevc_memset_fptr(pu1_luma_intra_pred_mode_left + i * block_offset_in_min_pu, intra_pred_mode, (cb_size / num_pred_blocks) / MIN_PU_SIZE);
    304                 ps_codec->s_func_selector.ihevc_memset_fptr(pu1_luma_intra_pred_mode_top + j * block_offset_in_min_pu, intra_pred_mode, (cb_size / num_pred_blocks) / MIN_PU_SIZE);
    305 
    306             }
    307             /* If partition is PART_NxN, then left is available for second column always */
    308             available_l_tmp = 1;
    309 
    310         }
    311         /* If partition is PART_NxN, then top is available for bottom row always */
    312         available_t = 1;
    313     }
    314 
    315     /* In case it is PART_2Nx2N partition, replicate intra pred mode in other three entries */
    316     if(ps_cu->i4_part_mode == PART_2Nx2N)
    317     {
    318         ps_cu->ai4_intra_luma_pred_mode[1] = ps_cu->ai4_intra_luma_pred_mode[0];
    319         ps_cu->ai4_intra_luma_pred_mode[2] = ps_cu->ai4_intra_luma_pred_mode[0];
    320         ps_cu->ai4_intra_luma_pred_mode[3] = ps_cu->ai4_intra_luma_pred_mode[0];
    321     }
    322 }
    323 
    324