Home | History | Annotate | Download | only in common
      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
     23 *  ideint_utils.c
     24 *
     25 * @brief
     26 *  This file contains the definitions of the core  processing of the de
     27 * interlacer.
     28 *
     29 * @author
     30 *  Ittiam
     31 *
     32 * @par List of Functions:
     33 *  ideint_weave_pic()
     34 *  init_bob_indices()
     35 *  ideint_weave_blk()
     36 *  ideint_spatial_filter()
     37 *
     38 * @remarks
     39 *  None
     40 *
     41 *******************************************************************************
     42 */
     43 /*****************************************************************************/
     44 /* File Includes                                                             */
     45 /*****************************************************************************/
     46 /* System include files */
     47 #include <stdio.h>
     48 #include <stdint.h>
     49 #include <string.h>
     50 #include <stdlib.h>
     51 #include <assert.h>
     52 
     53 
     54 /* User include files */
     55 #include "icv_datatypes.h"
     56 #include "icv_macros.h"
     57 #include "icv_platform_macros.h"
     58 #include "icv.h"
     59 #include "icv_variance.h"
     60 #include "icv_sad.h"
     61 #include "ideint.h"
     62 #include "ideint_defs.h"
     63 #include "ideint_structs.h"
     64 #include "ideint_utils.h"
     65 #include "ideint_cac.h"
     66 
     67 /**
     68 *******************************************************************************
     69 *
     70 * @brief
     71 *  Weaves two fields to produce a frame
     72 *
     73 * @par   Description
     74 *  Weaves two fields to produce a frame
     75 *
     76 * @param[in] ps_src_top
     77 *  Top field source
     78 *
     79 * @param[in] ps_src_bot
     80 *  Bottom field source
     81 *
     82 * @param[in] ps_dst_frm
     83 *  Destination frame
     84 *
     85 * @returns
     86 *   0 on Success
     87 *
     88 * @remarks
     89 *
     90 *******************************************************************************
     91 */
     92 WORD32 ideint_weave_pic(icv_pic_t *ps_src_top,
     93                         icv_pic_t *ps_src_bot,
     94                         icv_pic_t *ps_dst_frm,
     95                         WORD32 start_row,
     96                         WORD32 num_rows)
     97 {
     98     UWORD8 *pu1_src, *pu1_dst;
     99     WORD32 i, j, num_comp;
    100     icv_pic_t *ps_src_fld;
    101     WORD32 fld;
    102     icv_pic_t *ps_src_flds[2];
    103 
    104     num_comp = 3;
    105     ps_src_flds[0] = ps_src_top;
    106     ps_src_flds[1] = ps_src_bot;
    107 
    108     for(fld = 0; fld < 2; fld++)
    109     {
    110         ps_src_fld = ps_src_flds[fld];
    111         for(i = 0; i < num_comp; i++)
    112         {
    113             WORD32 src_strd;
    114             WORD32 dst_strd;
    115             WORD32 comp_row_start, comp_row_end;
    116             comp_row_start = start_row;
    117             comp_row_end = comp_row_start + num_rows;
    118             if(i)
    119             {
    120                 comp_row_start >>= 1;
    121                 comp_row_end >>= 1;
    122             }
    123 
    124             comp_row_end = MIN(comp_row_end, ps_dst_frm->ai4_ht[i]);
    125 
    126             pu1_src = ps_src_fld->apu1_buf[i];
    127             pu1_dst = ps_dst_frm->apu1_buf[i];
    128 
    129             src_strd = ps_src_fld->ai4_strd[i];
    130             dst_strd = ps_dst_frm->ai4_strd[i];
    131 
    132             /* If source field is bottom, increment destination */
    133             pu1_dst += fld * dst_strd;
    134 
    135             /* In case input and output are pointing to same buffer, then no need to copy */
    136             if((pu1_src != pu1_dst) || ((2 * dst_strd) != src_strd))
    137             {
    138                 pu1_dst += ps_dst_frm->ai4_strd[i] * comp_row_start;
    139                 pu1_src += ps_src_fld->ai4_strd[i] * comp_row_start / 2;
    140 
    141                 for(j = comp_row_start; j < comp_row_end; j += 2)
    142                 {
    143                     memcpy(pu1_dst, pu1_src, ps_dst_frm->ai4_wd[i]);
    144                     pu1_dst += ps_dst_frm->ai4_strd[i] * 2;
    145                     pu1_src += ps_src_fld->ai4_strd[i];
    146                 }
    147             }
    148         }
    149     }
    150     return 0;
    151 }
    152 
    153 
    154 /**
    155 *******************************************************************************
    156 *
    157 * @brief
    158 *  Weaves a 8x8 block
    159 *
    160 * @par   Description
    161 *  Weaves a 8x8 block from two fields
    162 *
    163 * @param[in] pu1_top
    164 *  Top field source
    165 *
    166 * @param[in] pu1_bot
    167 *  Bottom field source
    168 *
    169 * @param[in] pu1_dst
    170 *  Destination
    171 *
    172 * @param[in] dst_strd
    173 *  Destination stride
    174 *
    175 * @param[in] src_strd
    176 *  Source stride
    177 *
    178 * @returns
    179 *  0 on success
    180 *
    181 * @remarks
    182 *
    183 *******************************************************************************
    184 */
    185 WORD32 ideint_weave_blk(UWORD8 *pu1_top,
    186                         UWORD8 *pu1_bot,
    187                         UWORD8 *pu1_dst,
    188                         WORD32 dst_strd,
    189                         WORD32 src_strd,
    190                         WORD32 wd,
    191                         WORD32 ht)
    192 {
    193     WORD32 j;
    194 
    195     for(j = 0; j < ht; j += 2)
    196     {
    197         memcpy(pu1_dst, pu1_top, wd);
    198         pu1_dst += dst_strd;
    199         pu1_top += src_strd;
    200 
    201         memcpy(pu1_dst, pu1_bot, wd);
    202         pu1_dst += dst_strd;
    203         pu1_bot += src_strd;
    204     }
    205     return 0;
    206 }
    207 
    208 /**
    209 *******************************************************************************
    210 *
    211 * @brief
    212 *  Copy a boundary block and pad
    213 *
    214 * @par   Description
    215 *  Copies a block on one of the boundaries and pads
    216 *
    217 * @param[in] pu1_top
    218 *  Top field source
    219 *
    220 * @param[in] pu1_bot
    221 *  Bottom field source
    222 *
    223 * @param[in] pu1_pad
    224 *  Padded destination
    225 *
    226 * @param[in] cur_strd
    227 *  Stride for pu1_top and pu1_bot
    228 *
    229 * @param[in] row
    230 *  Current block's row
    231 *
    232 * @param[in] col
    233 *  Current block's column
    234 *
    235 * @param[in] num_blks_y
    236 *  Number of blocks in Y direction
    237 *
    238 * @param[in] num_blks_x
    239 *  Number of blocks in X direction
    240 
    241 * @returns
    242 *  None
    243 *
    244 * @remarks
    245 *
    246 *******************************************************************************
    247 */
    248 void ideint_pad_blk(UWORD8 *pu1_top,
    249                     UWORD8 *pu1_bot,
    250                     UWORD8 *pu1_pad,
    251                     WORD32 cur_strd,
    252                     WORD32 row,
    253                     WORD32 col,
    254                     WORD32 num_blks_y,
    255                     WORD32 num_blks_x,
    256                     WORD32 blk_wd,
    257                     WORD32 blk_ht)
    258 {
    259     WORD32 i;
    260     WORD32 num_cols, num_rows;
    261     UWORD8 *pu1_dst;
    262     UWORD8 *pu1_src_top;
    263     UWORD8 *pu1_src_bot;
    264 
    265     num_rows = blk_ht + 4;
    266     num_cols = blk_wd + 4;
    267 
    268     pu1_src_top = pu1_top - cur_strd - 2;
    269     pu1_src_bot = pu1_bot - cur_strd - 2;
    270     pu1_dst = pu1_pad;
    271 
    272     if(0 == col)
    273     {
    274         num_cols -= 2;
    275         pu1_dst += 2;
    276         pu1_src_top += 2;
    277         pu1_src_bot += 2;
    278     }
    279 
    280     if(0 == row)
    281     {
    282         num_rows -= 2;
    283         pu1_dst += 2 * (BLK_WD + 4);
    284         pu1_src_top += cur_strd;
    285         pu1_src_bot += cur_strd;
    286     }
    287 
    288     if((num_blks_x - 1) == col)
    289         num_cols -= 2;
    290 
    291     if((num_blks_y - 1) == row)
    292         num_rows -= 2;
    293 
    294     for(i = 0; i < num_rows; i += 2)
    295     {
    296         memcpy(pu1_dst, pu1_src_top, num_cols);
    297         pu1_dst += (BLK_WD + 4);
    298 
    299         memcpy(pu1_dst, pu1_src_bot, num_cols);
    300         pu1_dst += (BLK_WD + 4);
    301 
    302         pu1_src_top += cur_strd;
    303         pu1_src_bot += cur_strd;
    304     }
    305 
    306 
    307     /* Pad Left */
    308     if(0 == col)
    309     {
    310        for(i = 0; i < (BLK_HT + 4); i++)
    311        {
    312            WORD32 ofst = i * (BLK_WD + 4) + 2;
    313            pu1_pad[ofst - 1] = pu1_pad[ofst];
    314            pu1_pad[ofst - 2] = pu1_pad[ofst];
    315        }
    316     }
    317 
    318     /* Pad right */
    319     if((num_blks_x - 1) == col)
    320     {
    321        for(i = 0; i < (BLK_HT + 4); i++)
    322        {
    323            WORD32 ofst =  i * (BLK_WD + 4) + 2 + blk_wd - 1;
    324            WORD32 size = (BLK_WD - blk_wd) + 2;
    325            /* Padding on right should include padding for boundary
    326             * blocks when width is non-multiple of 8
    327             */
    328            memset(&pu1_pad[ofst + 1], pu1_pad[ofst], size);
    329        }
    330     }
    331 
    332     /* Pad Top */
    333     if(0 == row)
    334     {
    335         WORD32 src_ofst = 2 * (BLK_WD + 4);
    336         WORD32 dst_ofst = 0;
    337         memcpy(pu1_pad + dst_ofst, pu1_pad + src_ofst, (BLK_WD + 4));
    338         src_ofst += (BLK_WD + 4);
    339         dst_ofst += (BLK_WD + 4);
    340         memcpy(pu1_pad + dst_ofst, pu1_pad + src_ofst, (BLK_WD + 4));
    341     }
    342 
    343     /* Pad Bottom */
    344     if((num_blks_y - 1) == row)
    345     {
    346         WORD32 src_ofst = (0 + blk_ht) * (BLK_WD + 4);
    347         WORD32 dst_ofst = (1 + blk_ht) * (BLK_WD + 4);
    348         WORD32 size = (BLK_HT - blk_ht) + 2;
    349 
    350         /* Padding on bottom should include padding for boundary
    351          * blocks when height is non-multiple of 8
    352          */
    353         for(i = 0; i < size; i++)
    354         {
    355             memcpy(pu1_pad + dst_ofst, pu1_pad + src_ofst, (BLK_WD + 4));
    356             dst_ofst += (BLK_WD + 4);
    357         }
    358     }
    359 }
    360 
    361 /**
    362 *******************************************************************************
    363 *
    364 * @brief
    365 *  Performs spatial edge adaptive filtering
    366 *
    367 * @par   Description
    368 *  Performs spatial edge adaptive filtering by detecting edge direction
    369 *
    370 * @param[in] pu1_src
    371 *  Source buffer
    372 *
    373 * @param[in] pu1_out
    374 *  Destination buffer
    375 *
    376 * @param[in] src_strd
    377 *  Source stride
    378 *
    379 * @param[in] out_strd
    380 *  Destination stride
    381 
    382 * @returns
    383 * None
    384 *
    385 * @remarks
    386 *
    387 *******************************************************************************
    388 */
    389 void ideint_spatial_filter(UWORD8 *pu1_src,
    390                            UWORD8 *pu1_out,
    391                            WORD32 src_strd,
    392                            WORD32 out_strd)
    393 {
    394     WORD32 i;
    395     WORD32 j;
    396     WORD32 k;
    397 
    398     /*********************************************************************/
    399     /* This loop is for the two halves inside the 8x4 block.             */
    400     /*********************************************************************/
    401     for(k = 0; k < 2; k++)
    402     {
    403         WORD32 adiff[3] = {0, 0, 0};
    404         WORD32 shift;
    405         WORD32 dir_45_le_90, dir_45_le_135, dir_135_le_90;
    406         UWORD8 *pu1_row_1, *pu1_row_2, *pu1_dst;
    407 
    408         /*****************************************************************/
    409         /* Direction detection                                           */
    410         /*****************************************************************/
    411         pu1_row_1 = pu1_src;
    412         pu1_row_2 = pu1_src + src_strd;
    413 
    414         /*****************************************************************/
    415         /* Calculating the difference along each of the 3 directions.    */
    416         /*****************************************************************/
    417         for(j = 0; j < SUB_BLK_HT; j ++)
    418         {
    419             for(i = 0; i < SUB_BLK_WD; i++)
    420             {
    421                 adiff[0] += ABS_DIF(pu1_row_1[i], pu1_row_2[i]); /*  90 */
    422 
    423                 adiff[1] += ABS_DIF(pu1_row_1[i - 1], pu1_row_2[i + 1]); /* 135 */
    424 
    425                 adiff[2] += ABS_DIF(pu1_row_1[i + 1], pu1_row_2[i - 1]); /*  45 */
    426             }
    427             pu1_row_1 += src_strd;
    428             pu1_row_2 += src_strd;
    429         }
    430 
    431         /*****************************************************************/
    432         /* Applying bias, to make the diff comparision more robust.      */
    433         /*****************************************************************/
    434         adiff[0] *= EDGE_BIAS_0;
    435         adiff[1] *= EDGE_BIAS_1;
    436         adiff[2] *= EDGE_BIAS_1;
    437 
    438         /*****************************************************************/
    439         /* comapring the diffs */
    440         /*****************************************************************/
    441         dir_45_le_90  = (adiff[2] <= adiff[0]);
    442         dir_45_le_135 = (adiff[2] <= adiff[1]);
    443         dir_135_le_90 = (adiff[1] <= adiff[0]);
    444 
    445         /*****************************************************************/
    446         /* Direction selection. */
    447         /*****************************************************************/
    448         shift = 0;
    449         if(1 == dir_45_le_135)
    450         {
    451             if(1 == dir_45_le_90)
    452                 shift = 1;
    453         }
    454         else
    455         {
    456             if(1 == dir_135_le_90)
    457                 shift = -1;
    458         }
    459 
    460         /*****************************************************************/
    461         /* Directional interpolation */
    462         /*****************************************************************/
    463         pu1_row_1 = pu1_src + shift;
    464         pu1_row_2 = pu1_src + src_strd - shift;
    465         pu1_dst   = pu1_out;
    466 
    467         for(j = 0; j < SUB_BLK_HT; j++)
    468         {
    469             for(i = 0; i < SUB_BLK_WD; i++)
    470             {
    471                 pu1_dst[i] = (UWORD8)AVG(pu1_row_1[i], pu1_row_2[i]);
    472             }
    473             pu1_row_1 += src_strd;
    474             pu1_row_2 += src_strd;
    475             pu1_dst   += out_strd;
    476         }
    477 
    478         pu1_out += SUB_BLK_WD;
    479         pu1_src += SUB_BLK_WD;
    480     }
    481 }
    482 
    483