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 #include <stdio.h>
     21 #include "iv_datatypedef.h"
     22 #include "iv.h"
     23 
     24 #include "icv.h"
     25 #include "ideint.h"
     26 
     27 #include "impeg2_buf_mgr.h"
     28 #include "impeg2_disp_mgr.h"
     29 #include "impeg2_defs.h"
     30 #include "impeg2_platform_macros.h"
     31 #include "impeg2_inter_pred.h"
     32 #include "impeg2_idct.h"
     33 #include "impeg2_globals.h"
     34 #include "impeg2_mem_func.h"
     35 #include "impeg2_format_conv.h"
     36 #include "impeg2_macros.h"
     37 
     38 #include "impeg2d.h"
     39 #include "impeg2d_bitstream.h"
     40 #include "impeg2d_structs.h"
     41 #include "impeg2d_globals.h"
     42 #include "impeg2d_mc.h"
     43 #include "impeg2d_pic_proc.h"
     44 #include "impeg2d_deinterlace.h"
     45 
     46 typedef struct
     47 {
     48     IVD_ARCH_T ivd_arch;
     49     ICV_ARCH_T icv_arch;
     50 }arch_map_t;
     51 
     52 static const arch_map_t gas_impeg2d_arch_mapping[] =
     53 {
     54     {ARCH_ARM_NONEON,       ICV_ARM_NONEON},
     55     {ARCH_ARM_A9Q,          ICV_ARM_A9Q},
     56     {ARCH_ARM_A9A,          ICV_ARM_A9A},
     57     {ARCH_ARM_A9,           ICV_ARM_A9},
     58     {ARCH_ARM_A7,           ICV_ARM_A7},
     59     {ARCH_ARM_A5,           ICV_ARM_A5},
     60     {ARCH_ARM_A15,          ICV_ARM_A15},
     61     {ARCH_ARM_NEONINTR,     ICV_ARM_NEONINTR},
     62     {ARCH_ARMV8_GENERIC,    ICV_ARMV8_GENERIC},
     63     {ARCH_X86_GENERIC,      ICV_X86_GENERIC},
     64     {ARCH_X86_SSSE3,        ICV_X86_SSSE3},
     65     {ARCH_X86_SSE42,        ICV_X86_SSE42},
     66     {ARCH_X86_AVX2,         ICV_X86_AVX2},
     67     {ARCH_MIPS_GENERIC,     ICV_MIPS_GENERIC},
     68     {ARCH_MIPS_32,          ICV_MIPS_32}
     69 };
     70 
     71 
     72 static void impeg2d_get_pic(icv_pic_t *ps_dst,
     73                             UWORD8 *pu1_buf_y,
     74                             UWORD8 *pu1_buf_u,
     75                             UWORD8 *pu1_buf_v,
     76                             WORD32 wd,
     77                             WORD32 ht,
     78                             WORD32 strd)
     79 {
     80     ps_dst->ai4_wd[0] = wd;
     81     ps_dst->ai4_wd[1] = wd / 2;
     82     ps_dst->ai4_wd[2] = wd / 2;
     83 
     84     ps_dst->ai4_ht[0] = ht;
     85     ps_dst->ai4_ht[1] = ht / 2;
     86     ps_dst->ai4_ht[2] = ht / 2;
     87 
     88     ps_dst->ai4_strd[0] = strd;
     89     ps_dst->ai4_strd[1] = strd / 2;
     90     ps_dst->ai4_strd[2] = strd / 2;
     91 
     92     ps_dst->apu1_buf[0] = pu1_buf_y;
     93     ps_dst->apu1_buf[1] = pu1_buf_u;
     94     ps_dst->apu1_buf[2] = pu1_buf_v;
     95 
     96     ps_dst->e_color_fmt = ICV_YUV420P;
     97 }
     98 static void impeg2d_get_flds(icv_pic_t *ps_frm,
     99                              icv_pic_t *ps_top_fld,
    100                              icv_pic_t *ps_bot_fld)
    101 {
    102     ps_top_fld->ai4_wd[0] = ps_frm->ai4_wd[0];
    103     ps_top_fld->ai4_wd[1] = ps_frm->ai4_wd[1];
    104     ps_top_fld->ai4_wd[2] = ps_frm->ai4_wd[2];
    105 
    106     ps_top_fld->ai4_ht[0] = ps_frm->ai4_ht[0] / 2;
    107     ps_top_fld->ai4_ht[1] = ps_frm->ai4_ht[1] / 2;
    108     ps_top_fld->ai4_ht[2] = ps_frm->ai4_ht[2] / 2;
    109 
    110     ps_top_fld->ai4_strd[0] = ps_frm->ai4_strd[0] * 2;
    111     ps_top_fld->ai4_strd[1] = ps_frm->ai4_strd[1] * 2;
    112     ps_top_fld->ai4_strd[2] = ps_frm->ai4_strd[2] * 2;
    113 
    114     ps_top_fld->e_color_fmt = ps_frm->e_color_fmt;
    115 
    116     /* Copy top field structure to bottom field, since properties of both fields are same */
    117     *ps_bot_fld = *ps_top_fld;
    118 
    119     /* Initialize the addresses for top field */
    120     ps_top_fld->apu1_buf[0] = ps_frm->apu1_buf[0];
    121     ps_top_fld->apu1_buf[1] = ps_frm->apu1_buf[1];
    122     ps_top_fld->apu1_buf[2] = ps_frm->apu1_buf[2];
    123 
    124     /* Initialize the addresses for bottom field */
    125     ps_bot_fld->apu1_buf[0] = ps_frm->apu1_buf[0] + ps_frm->ai4_strd[0];
    126     ps_bot_fld->apu1_buf[1] = ps_frm->apu1_buf[1] + ps_frm->ai4_strd[1];
    127     ps_bot_fld->apu1_buf[2] = ps_frm->apu1_buf[2] + ps_frm->ai4_strd[2];
    128 
    129     return;
    130 }
    131 
    132 
    133 static ICV_ARCH_T impeg2d_get_arch(IVD_ARCH_T e_arch)
    134 {
    135     ICV_ARCH_T ret_arch;
    136     WORD32 num_entries, i;
    137 
    138     ret_arch = ICV_ARM_A9;
    139     num_entries = sizeof(gas_impeg2d_arch_mapping) / sizeof(gas_impeg2d_arch_mapping[0]);
    140     for(i = 0; i < num_entries; i++)
    141     {
    142         if(e_arch == gas_impeg2d_arch_mapping[i].ivd_arch)
    143         {
    144             ret_arch = gas_impeg2d_arch_mapping[i].icv_arch;
    145             break;
    146         }
    147     }
    148     return ret_arch;
    149 }
    150 
    151 /******************************************************************************
    152 *  Function Name   : impeg2d_deinterlace
    153 *
    154 *  Description     : Deinterlace current picture
    155 *
    156 *  Arguments       :
    157 *  dec             : Decoder Context
    158 *
    159 *  Values Returned : 0 on success, -1 on error
    160 ******************************************************************************/
    161 WORD32 impeg2d_deint_ctxt_size(void)
    162 {
    163     return ideint_ctxt_size();
    164 }
    165 
    166 /******************************************************************************
    167 *  Function Name   : impeg2d_deinterlace
    168 *
    169 *  Description     : Deinterlace current picture
    170 *
    171 *  Arguments       :
    172 *  dec             : Decoder Context
    173 *
    174 *  Values Returned : 0 on success, -1 on error
    175 ******************************************************************************/
    176 WORD32 impeg2d_deinterlace(dec_state_t *ps_dec,
    177                            pic_buf_t *ps_src_pic,
    178                            iv_yuv_buf_t *ps_disp_frm_buf,
    179                            WORD32 start_row,
    180                            WORD32 num_rows)
    181 {
    182     icv_pic_t as_inp_flds[3];
    183     IDEINT_ERROR_T ret;
    184     icv_pic_t s_src_frm;
    185     icv_pic_t s_dst_frm;
    186     UWORD8 *pu1_dst_y, *pu1_dst_u, *pu1_dst_v;
    187     ideint_params_t s_params;
    188 
    189     if((NULL == ps_src_pic) || (NULL == ps_src_pic->pu1_y) || (0 == num_rows))
    190         return -1;
    191 
    192     s_params.e_arch = impeg2d_get_arch(ps_dec->e_processor_arch);
    193     s_params.e_soc = ICV_SOC_GENERIC;
    194     s_params.e_mode = IDEINT_MODE_SPATIAL;
    195     s_params.i4_cur_fld_top = ps_dec->u2_top_field_first;
    196     s_params.i4_disable_weave = 0;
    197     s_params.pf_aligned_alloc = NULL;
    198     s_params.pf_aligned_free = NULL;
    199 
    200     impeg2d_get_pic(&s_src_frm, ps_src_pic->pu1_y, ps_src_pic->pu1_u,
    201                     ps_src_pic->pu1_v, ps_dec->u2_horizontal_size,
    202                     ps_dec->u2_vertical_size, ps_dec->u2_frame_width);
    203     impeg2d_get_flds(&s_src_frm, &as_inp_flds[1], &as_inp_flds[2]);
    204 
    205     if(ps_dec->ps_deint_pic)
    206     {
    207         icv_pic_t s_prv_frm;
    208         icv_pic_t s_fld;
    209         impeg2d_get_pic(&s_prv_frm, ps_dec->ps_deint_pic->pu1_y,
    210                         ps_dec->ps_deint_pic->pu1_u,
    211                         ps_dec->ps_deint_pic->pu1_v, ps_dec->u2_horizontal_size,
    212                         ps_dec->u2_vertical_size, ps_dec->u2_frame_width);
    213         impeg2d_get_flds(&s_prv_frm, &s_fld, &as_inp_flds[0]);
    214     }
    215     else
    216     {
    217         as_inp_flds[0].apu1_buf[0] = NULL;
    218         as_inp_flds[0].apu1_buf[1] = NULL;
    219         as_inp_flds[0].apu1_buf[2] = NULL;
    220     }
    221 
    222     pu1_dst_y = ps_disp_frm_buf->pv_y_buf;
    223     pu1_dst_u = ps_disp_frm_buf->pv_u_buf;
    224     pu1_dst_v = ps_disp_frm_buf->pv_v_buf;
    225 
    226     /* Use intermediate buffer as output to deinterlacer,
    227      * if color format is not 420P
    228      */
    229     if(IV_YUV_420P != ps_dec->i4_chromaFormat)
    230     {
    231         UWORD8 *pu1_buf_y;
    232         UWORD8 *pu1_buf_u;
    233         UWORD8 *pu1_buf_v;
    234         WORD32 wd = ALIGN16(ps_dec->u2_horizontal_size);
    235         WORD32 ht = ALIGN16(ps_dec->u2_vertical_size);
    236 
    237         pu1_buf_y = ps_dec->pu1_deint_fmt_buf;
    238         pu1_buf_u = pu1_buf_y + wd * ht;
    239         pu1_buf_v = pu1_buf_u + wd * ht / 4;
    240 
    241         pu1_dst_u = pu1_buf_u;
    242         pu1_dst_v = pu1_buf_v;
    243 
    244         if((ps_dec->i4_chromaFormat != IV_YUV_420SP_UV) &&
    245            (ps_dec->i4_chromaFormat != IV_YUV_420SP_VU))
    246         {
    247             pu1_dst_y = pu1_buf_y;
    248         }
    249 
    250     }
    251     impeg2d_get_pic(&s_dst_frm, pu1_dst_y, pu1_dst_u, pu1_dst_v,
    252                     ps_dec->u2_horizontal_size, ps_dec->u2_vertical_size,
    253                     ps_dec->u4_frm_buf_stride);
    254 
    255 
    256     ret = ideint_process(ps_dec->pv_deinterlacer_ctxt, &as_inp_flds[0],
    257                          &as_inp_flds[1], &as_inp_flds[2], &s_dst_frm,
    258                          &s_params, start_row, num_rows);
    259 
    260     if(IDEINT_ERROR_NONE != ret)
    261     {
    262         return -1;
    263     }
    264 
    265     /* Format convert deinterlacer output if required*/
    266     if(IV_YUV_420P != ps_dec->i4_chromaFormat)
    267     {
    268         pic_buf_t s_src_pic;
    269 
    270         s_src_pic = *ps_src_pic;
    271         s_src_pic.pu1_y = pu1_dst_y;
    272         s_src_pic.pu1_u = pu1_dst_u;
    273         s_src_pic.pu1_v = pu1_dst_v;
    274 
    275         impeg2d_format_convert(ps_dec,
    276                                &s_src_pic,
    277                                ps_disp_frm_buf,
    278                                start_row,
    279                                num_rows);
    280 
    281     }
    282     return 0;
    283 
    284 }
    285