| /****************************************************************************** |
| * |
| * Copyright (C) 2015 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at: |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| ***************************************************************************** |
| * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore |
| */ |
| /** |
| ******************************************************************************* |
| * @file |
| * ih264_inter_pred_filters.c |
| * |
| * @brief |
| * Contains function definitions for inter prediction interpolation filters |
| * |
| * @author |
| * Ittiam |
| * |
| * @par List of Functions: |
| * - ih264_inter_pred_luma_copy |
| * - ih264_interleave_copy |
| * - ih264_inter_pred_luma_horz |
| * - ih264_inter_pred_luma_vert |
| * - ih264_inter_pred_luma_horz_hpel_vert_hpel |
| * - ih264_inter_pred_luma_horz_qpel |
| * - ih264_inter_pred_luma_vert_qpel |
| * - ih264_inter_pred_luma_horz_qpel_vert_qpel |
| * - ih264_inter_pred_luma_horz_hpel_vert_qpel |
| * - ih264_inter_pred_luma_horz_qpel_vert_hpel |
| * - ih264_inter_pred_luma_bilinear |
| * - ih264_inter_pred_chroma |
| * |
| * @remarks |
| * None |
| * |
| ******************************************************************************* |
| */ |
| |
| /*****************************************************************************/ |
| /* File Includes */ |
| /*****************************************************************************/ |
| |
| /* User include files */ |
| #include "ih264_typedefs.h" |
| #include "ih264_macros.h" |
| #include "ih264_platform_macros.h" |
| #include "ih264_inter_pred_filters.h" |
| |
| |
| /*****************************************************************************/ |
| /* Constant Data variables */ |
| /*****************************************************************************/ |
| |
| /* coefficients for 6 tap filtering*/ |
| const WORD32 ih264_g_six_tap[3] ={1,-5,20}; |
| |
| |
| /*****************************************************************************/ |
| /* Function definitions . */ |
| /*****************************************************************************/ |
| /** |
| ******************************************************************************* |
| * |
| * @brief |
| * Interprediction luma function for copy |
| * |
| * @par Description: |
| * Copies the array of width 'wd' and height 'ht' from the location pointed |
| * by 'src' to the location pointed by 'dst' |
| * |
| * @param[in] pu1_src |
| * UWORD8 pointer to the source |
| * |
| * @param[out] pu1_dst |
| * UWORD8 pointer to the destination |
| * |
| * @param[in] src_strd |
| * integer source stride |
| * |
| * @param[in] dst_strd |
| * integer destination stride |
| * |
| * |
| * @param[in] ht |
| * integer height of the array |
| * |
| * @param[in] wd |
| * integer width of the array |
| * |
| * @returns |
| * |
| * @remarks |
| * None |
| * |
| ******************************************************************************* |
| */ |
| |
| void ih264_inter_pred_luma_copy(UWORD8 *pu1_src, |
| UWORD8 *pu1_dst, |
| WORD32 src_strd, |
| WORD32 dst_strd, |
| WORD32 ht, |
| WORD32 wd, |
| UWORD8* pu1_tmp, |
| WORD32 dydx) |
| { |
| WORD32 row, col; |
| UNUSED(pu1_tmp); |
| UNUSED(dydx); |
| for(row = 0; row < ht; row++) |
| { |
| for(col = 0; col < wd; col++) |
| { |
| pu1_dst[col] = pu1_src[col]; |
| } |
| |
| pu1_src += src_strd; |
| pu1_dst += dst_strd; |
| } |
| } |
| |
| /** |
| ******************************************************************************* |
| * |
| * @brief |
| * Fucntion for copying to an interleaved destination |
| * |
| * @par Description: |
| * Copies the array of width 'wd' and height 'ht' from the location pointed |
| * by 'src' to the location pointed by 'dst' |
| * |
| * @param[in] pu1_src |
| * UWORD8 pointer to the source |
| * |
| * @param[out] pu1_dst |
| * UWORD8 pointer to the destination |
| * |
| * @param[in] src_strd |
| * integer source stride |
| * |
| * @param[in] dst_strd |
| * integer destination stride |
| * |
| * @param[in] ht |
| * integer height of the array |
| * |
| * @param[in] wd |
| * integer width of the array |
| * |
| * @returns |
| * |
| * @remarks |
| * The alternate elements of src will be copied to alternate locations in dsr |
| * Other locations are not touched |
| * |
| ******************************************************************************* |
| */ |
| void ih264_interleave_copy(UWORD8 *pu1_src, |
| UWORD8 *pu1_dst, |
| WORD32 src_strd, |
| WORD32 dst_strd, |
| WORD32 ht, |
| WORD32 wd) |
| { |
| WORD32 row, col; |
| wd *= 2; |
| |
| for(row = 0; row < ht; row++) |
| { |
| for(col = 0; col < wd; col+=2) |
| { |
| pu1_dst[col] = pu1_src[col]; |
| } |
| |
| pu1_src += src_strd; |
| pu1_dst += dst_strd; |
| } |
| } |
| |
| /** |
| ******************************************************************************* |
| * |
| * @brief |
| * Interprediction luma filter for horizontal input |
| * |
| * @par Description: |
| * Applies a 6 tap horizontal filter .The output is clipped to 8 bits |
| * sec 8.4.2.2.1 titled "Luma sample interpolation process" |
| * |
| * @param[in] pu1_src |
| * UWORD8 pointer to the source |
| * |
| * @param[out] pu1_dst |
| * UWORD8 pointer to the destination |
| * |
| * @param[in] src_strd |
| * integer source stride |
| * |
| * @param[in] dst_strd |
| * integer destination stride |
| * |
| * @param[in] ht |
| * integer height of the array |
| * |
| * @param[in] wd |
| * integer width of the array |
| * |
| * @returns |
| * |
| * @remarks |
| * None |
| * |
| ******************************************************************************* |
| */ |
| void ih264_inter_pred_luma_horz(UWORD8 *pu1_src, |
| UWORD8 *pu1_dst, |
| WORD32 src_strd, |
| WORD32 dst_strd, |
| WORD32 ht, |
| WORD32 wd, |
| UWORD8* pu1_tmp, |
| WORD32 dydx) |
| { |
| WORD32 row, col; |
| WORD16 i2_tmp; |
| UNUSED(pu1_tmp); |
| UNUSED(dydx); |
| |
| for(row = 0; row < ht; row++) |
| { |
| for(col = 0; col < wd; col++) |
| { |
| i2_tmp = 0;/*ih264_g_six_tap[] is the array containing the filter coeffs*/ |
| i2_tmp = ih264_g_six_tap[0] * |
| (pu1_src[col - 2] + pu1_src[col + 3]) |
| + ih264_g_six_tap[1] * |
| (pu1_src[col - 1] + pu1_src[col + 2]) |
| + ih264_g_six_tap[2] * |
| (pu1_src[col] + pu1_src[col + 1]); |
| i2_tmp = (i2_tmp + 16) >> 5; |
| pu1_dst[col] = CLIP_U8(i2_tmp); |
| } |
| |
| pu1_src += src_strd; |
| pu1_dst += dst_strd; |
| } |
| |
| } |
| |
| /** |
| ******************************************************************************* |
| * |
| * @brief |
| * Interprediction luma filter for vertical input |
| * |
| * @par Description: |
| * Applies a 6 tap vertical filter.The output is clipped to 8 bits |
| * sec 8.4.2.2.1 titled "Luma sample interpolation process" |
| * |
| * @param[in] pu1_src |
| * UWORD8 pointer to the source |
| * |
| * @param[out] pu1_dst |
| * UWORD8 pointer to the destination |
| * |
| * @param[in] src_strd |
| * integer source stride |
| * |
| * @param[in] dst_strd |
| * integer destination stride |
| * |
| * @param[in] ht |
| * integer height of the array |
| * |
| * @param[in] wd |
| * integer width of the array |
| * |
| * @returns |
| * |
| * @remarks |
| * None |
| * |
| ******************************************************************************* |
| */ |
| void ih264_inter_pred_luma_vert(UWORD8 *pu1_src, |
| UWORD8 *pu1_dst, |
| WORD32 src_strd, |
| WORD32 dst_strd, |
| WORD32 ht, |
| WORD32 wd, |
| UWORD8* pu1_tmp, |
| WORD32 dydx) |
| { |
| WORD32 row, col; |
| WORD16 i2_tmp; |
| UNUSED(pu1_tmp); |
| UNUSED(dydx); |
| |
| for(row = 0; row < ht; row++) |
| { |
| for(col = 0; col < wd; col++) |
| { |
| i2_tmp = 0; /*ih264_g_six_tap[] is the array containing the filter coeffs*/ |
| i2_tmp = ih264_g_six_tap[0] * |
| (pu1_src[col - 2 * src_strd] + pu1_src[col + 3 * src_strd]) |
| + ih264_g_six_tap[1] * |
| (pu1_src[col - 1 * src_strd] + pu1_src[col + 2 * src_strd]) |
| + ih264_g_six_tap[2] * |
| (pu1_src[col] + pu1_src[col + 1 * src_strd]); |
| i2_tmp = (i2_tmp + 16) >> 5; |
| pu1_dst[col] = CLIP_U8(i2_tmp); |
| } |
| pu1_src += src_strd; |
| pu1_dst += dst_strd; |
| } |
| } |
| |
| /*! |
| ************************************************************************** |
| * \if Function name : ih264_inter_pred_luma_horz_hpel_vert_hpel \endif |
| * |
| * \brief |
| * This function implements a two stage cascaded six tap filter. It |
| * applies the six tap filter in the horizontal direction on the |
| * predictor values, followed by applying the same filter in the |
| * vertical direction on the output of the first stage. The six tap |
| * filtering operation is described in sec 8.4.2.2.1 titled "Luma sample |
| * interpolation process" |
| * |
| * \param pu1_src: Pointer to the buffer containing the predictor values. |
| * pu1_src could point to the frame buffer or the predictor buffer. |
| * \param pu1_dst: Pointer to the destination buffer where the output of |
| * the six tap filter is stored. |
| * \param ht: Height of the rectangular pixel grid to be interpolated |
| * \param wd: Width of the rectangular pixel grid to be interpolated |
| * \param src_strd: Width of the buffer pointed to by pu1_src. |
| * \param dst_strd: Width of the destination buffer |
| * \param pu1_tmp: temporary buffer. |
| * \param dydx: x and y reference offset for qpel calculations: UNUSED in this function. |
| * |
| * \return |
| * None. |
| * |
| * \note |
| * This function takes the 8 bit predictor values, applies the six tap |
| * filter in the horizontal direction and outputs the result clipped to |
| * 8 bit precision. The input is stored in the buffer pointed to by |
| * pu1_src while the output is stored in the buffer pointed by pu1_dst. |
| * Both pu1_src and pu1_dst could point to the same buffer i.e. the |
| * six tap filter could be done in place. |
| * |
| ************************************************************************** |
| */ |
| void ih264_inter_pred_luma_horz_hpel_vert_hpel(UWORD8 *pu1_src, |
| UWORD8 *pu1_dst, |
| WORD32 src_strd, |
| WORD32 dst_strd, |
| WORD32 ht, |
| WORD32 wd, |
| UWORD8* pu1_tmp, |
| WORD32 dydx) |
| { |
| WORD32 row, col; |
| WORD32 tmp; |
| WORD16* pi2_pred1_temp; |
| WORD16* pi2_pred1; |
| UNUSED(dydx); |
| pi2_pred1_temp = (WORD16*)pu1_tmp; |
| pi2_pred1_temp += 2; |
| pi2_pred1 = pi2_pred1_temp; |
| for(row = 0; row < ht; row++) |
| { |
| for(col = -2; col < wd + 3; col++) |
| { |
| tmp = 0;/*ih264_g_six_tap[] is the array containing the filter coeffs*/ |
| tmp = ih264_g_six_tap[0] * |
| (pu1_src[col - 2 * src_strd] + pu1_src[col + 3 * src_strd]) |
| + ih264_g_six_tap[1] * |
| (pu1_src[col - 1 * src_strd] + pu1_src[col + 2 * src_strd]) |
| + ih264_g_six_tap[2] * |
| (pu1_src[col] + pu1_src[col + 1 * src_strd]); |
| pi2_pred1_temp[col] = tmp; |
| } |
| pu1_src += src_strd; |
| pi2_pred1_temp = pi2_pred1_temp + wd + 5; |
| } |
| |
| for(row = 0; row < ht; row++) |
| { |
| for(col = 0; col < wd; col++) |
| { |
| tmp = 0;/*ih264_g_six_tap[] is the array containing the filter coeffs*/ |
| tmp = ih264_g_six_tap[0] * |
| (pi2_pred1[col - 2] + pi2_pred1[col + 3]) |
| + ih264_g_six_tap[1] * |
| (pi2_pred1[col - 1] + pi2_pred1[col + 2]) |
| + ih264_g_six_tap[2] * (pi2_pred1[col] + pi2_pred1[col + 1]); |
| tmp = (tmp + 512) >> 10; |
| pu1_dst[col] = CLIP_U8(tmp); |
| } |
| pi2_pred1 += (wd + 5); |
| pu1_dst += dst_strd; |
| } |
| } |
| |
| /*! |
| ************************************************************************** |
| * \if Function name : ih264_inter_pred_luma_horz_qpel \endif |
| * |
| * \brief |
| * This routine applies the six tap filter to the predictors in the |
| * horizontal direction. The six tap filtering operation is described in |
| * sec 8.4.2.2.1 titled "Luma sample interpolation process" |
| * |
| * \param pu1_src: Pointer to the buffer containing the predictor values. |
| * pu1_src could point to the frame buffer or the predictor buffer. |
| * \param pu1_dst: Pointer to the destination buffer where the output of |
| * the six tap filter is stored. |
| * \param ht: Height of the rectangular pixel grid to be interpolated |
| * \param wd: Width of the rectangular pixel grid to be interpolated |
| * \param src_strd: Width of the buffer pointed to by pu1_src. |
| * \param dst_strd: Width of the destination buffer |
| * \param pu1_tmp: temporary buffer: UNUSED in this function |
| * \param dydx: x and y reference offset for qpel calculations. |
| * |
| * \return |
| * None. |
| * |
| * \note |
| * This function takes the 8 bit predictor values, applies the six tap |
| * filter in the horizontal direction and outputs the result clipped to |
| * 8 bit precision. The input is stored in the buffer pointed to by |
| * pu1_src while the output is stored in the buffer pointed by pu1_dst. |
| * Both pu1_src and pu1_dst could point to the same buffer i.e. the |
| * six tap filter could be done in place. |
| * |
| ************************************************************************** |
| */ |
| void ih264_inter_pred_luma_horz_qpel(UWORD8 *pu1_src, |
| UWORD8 *pu1_dst, |
| WORD32 src_strd, |
| WORD32 dst_strd, |
| WORD32 ht, |
| WORD32 wd, |
| UWORD8* pu1_tmp, |
| WORD32 dydx) |
| { |
| WORD32 row, col; |
| UWORD8 *pu1_pred1; |
| WORD32 x_offset = dydx & 0x3; |
| UNUSED(pu1_tmp); |
| pu1_pred1 = pu1_src + (x_offset >> 1); |
| |
| for(row = 0; row < ht; row++) |
| { |
| for(col = 0; col < wd; col++, pu1_src++, pu1_dst++) |
| { |
| WORD16 i2_temp; |
| /* The logic below implements the following equation |
| i2_temp = puc_pred[-2] - 5 * (puc_pred[-1] + puc_pred[2]) + |
| 20 * (puc_pred[0] + puc_pred[1]) + puc_pred[3]; */ |
| i2_temp = pu1_src[-2] + pu1_src[3] |
| - (pu1_src[-1] + pu1_src[2]) |
| + ((pu1_src[0] + pu1_src[1] - pu1_src[-1] - pu1_src[2]) << 2) |
| + ((pu1_src[0] + pu1_src[1]) << 4); |
| i2_temp = (i2_temp + 16) >> 5; |
| i2_temp = CLIP_U8(i2_temp); |
| *pu1_dst = (i2_temp + *pu1_pred1 + 1) >> 1; |
| |
| pu1_pred1++; |
| } |
| pu1_dst += dst_strd - wd; |
| pu1_src += src_strd - wd; |
| pu1_pred1 += src_strd - wd; |
| } |
| } |
| |
| /*! |
| ************************************************************************** |
| * \if Function name : ih264_inter_pred_luma_vert_qpel \endif |
| * |
| * \brief |
| * This routine applies the six tap filter to the predictors in the |
| * vertical direction and interpolates them to obtain pixels at quarter vertical |
| * positions (0, 1/4) and (0, 3/4). The six tap filtering operation is |
| * described in sec 8.4.2.2.1 titled "Luma sample interpolation process" |
| * |
| * \param pu1_src: Pointer to the buffer containing the predictor values. |
| * pu1_src could point to the frame buffer or the predictor buffer. |
| * \param pu1_dst: Pointer to the destination buffer where the output of |
| * the six tap filter is stored. |
| * \param ht: Height of the rectangular pixel grid to be interpolated |
| * \param wd: Width of the rectangular pixel grid to be interpolated |
| * \param src_strd: Width of the buffer pointed to by puc_pred. |
| * \param dst_strd: Width of the destination buffer |
| * \param pu1_tmp: temporary buffer: UNUSED in this function |
| * \param dydx: x and y reference offset for qpel calculations. |
| * |
| * \return |
| * void |
| * |
| * \note |
| * This function takes the 8 bit predictor values, applies the six tap |
| * filter in the vertical direction and outputs the result clipped to |
| * 8 bit precision. The input is stored in the buffer pointed to by |
| * puc_pred while the output is stored in the buffer pointed by puc_dest. |
| * Both puc_pred and puc_dest could point to the same buffer i.e. the |
| * six tap filter could be done in place. |
| * |
| * \para <title> |
| * <paragraph> |
| * ... |
| ************************************************************************** |
| */ |
| void ih264_inter_pred_luma_vert_qpel(UWORD8 *pu1_src, |
| UWORD8 *pu1_dst, |
| WORD32 src_strd, |
| WORD32 dst_strd, |
| WORD32 ht, |
| WORD32 wd, |
| UWORD8* pu1_tmp, |
| WORD32 dydx) |
| { |
| WORD32 row, col; |
| WORD32 y_offset = dydx >> 2; |
| WORD32 off1, off2, off3; |
| UWORD8 *pu1_pred1; |
| UNUSED(pu1_tmp); |
| y_offset = y_offset & 0x3; |
| |
| off1 = src_strd; |
| off2 = src_strd << 1; |
| off3 = off1 + off2; |
| |
| pu1_pred1 = pu1_src + (y_offset >> 1) * src_strd; |
| |
| for(row = 0; row < ht; row++) |
| { |
| for(col = 0; col < wd; col++, pu1_dst++, pu1_src++, pu1_pred1++) |
| { |
| WORD16 i2_temp; |
| /* The logic below implements the following equation |
| i16_temp = puc_pred[-2*src_strd] + puc_pred[3*src_strd] - |
| 5 * (puc_pred[-1*src_strd] + puc_pred[2*src_strd]) + |
| 20 * (puc_pred[0] + puc_pred[src_strd]); */ |
| i2_temp = pu1_src[-off2] + pu1_src[off3] |
| - (pu1_src[-off1] + pu1_src[off2]) |
| + ((pu1_src[0] + pu1_src[off1] - pu1_src[-off1] - pu1_src[off2]) << 2) |
| + ((pu1_src[0] + pu1_src[off1]) << 4); |
| i2_temp = (i2_temp + 16) >> 5; |
| i2_temp = CLIP_U8(i2_temp); |
| |
| *pu1_dst = (i2_temp + *pu1_pred1 + 1) >> 1; |
| } |
| pu1_src += src_strd - wd; |
| pu1_pred1 += src_strd - wd; |
| pu1_dst += dst_strd - wd; |
| } |
| } |
| |
| /*! |
| ************************************************************************** |
| * \if Function name : ih264_inter_pred_luma_horz_qpel_vert_qpel \endif |
| * |
| * \brief |
| * This routine applies the six tap filter to the predictors in the |
| * vertical and horizontal direction and averages them to get pixels at locations |
| * (1/4,1/4), (1/4, 3/4), (3/4, 1/4) & (3/4, 3/4). The six tap filtering operation |
| * is described in sec 8.4.2.2.1 titled "Luma sample interpolation process" |
| * |
| * \param pu1_src: Pointer to the buffer containing the predictor values. |
| * pu1_src could point to the frame buffer or the predictor buffer. |
| * \param pu1_dst: Pointer to the destination buffer where the output of |
| * the six tap filter is stored. |
| * \param wd: Width of the rectangular pixel grid to be interpolated |
| * \param ht: Height of the rectangular pixel grid to be interpolated |
| * \param src_strd: Width of the buffer pointed to by puc_pred. |
| * \param dst_strd: Width of the destination buffer |
| * \param pu1_tmp: temporary buffer, UNUSED in this function |
| * \param dydx: x and y reference offset for qpel calculations. |
| * |
| * \return |
| * void |
| * |
| * \note |
| * This function takes the 8 bit predictor values, applies the six tap |
| * filter in the vertical direction and outputs the result clipped to |
| * 8 bit precision. The input is stored in the buffer pointed to by |
| * puc_pred while the output is stored in the buffer pointed by puc_dest. |
| * Both puc_pred and puc_dest could point to the same buffer i.e. the |
| * six tap filter could be done in place. |
| * |
| * \para <title> |
| * <paragraph> |
| * ... |
| ************************************************************************** |
| */ |
| void ih264_inter_pred_luma_horz_qpel_vert_qpel(UWORD8 *pu1_src, |
| UWORD8 *pu1_dst, |
| WORD32 src_strd, |
| WORD32 dst_strd, |
| WORD32 ht, |
| WORD32 wd, |
| UWORD8* pu1_tmp, |
| WORD32 dydx) |
| { |
| WORD32 row, col; |
| WORD32 x_offset = dydx & 0x3; |
| WORD32 y_offset = dydx >> 2; |
| |
| WORD32 off1, off2, off3; |
| UWORD8* pu1_pred_vert, *pu1_pred_horz; |
| UNUSED(pu1_tmp); |
| y_offset = y_offset & 0x3; |
| |
| off1 = src_strd; |
| off2 = src_strd << 1; |
| off3 = off1 + off2; |
| |
| pu1_pred_horz = pu1_src + (y_offset >> 1) * src_strd; |
| pu1_pred_vert = pu1_src + (x_offset >> 1); |
| |
| for(row = 0; row < ht; row++) |
| { |
| for(col = 0; col < wd; |
| col++, pu1_dst++, pu1_pred_vert++, pu1_pred_horz++) |
| { |
| WORD16 i2_temp_vert, i2_temp_horz; |
| /* The logic below implements the following equation |
| i2_temp = puc_pred[-2*src_strd] + puc_pred[3*src_strd] - |
| 5 * (puc_pred[-1*src_strd] + puc_pred[2*src_strd]) + |
| 20 * (puc_pred[0] + puc_pred[src_strd]); */ |
| i2_temp_vert = pu1_pred_vert[-off2] + pu1_pred_vert[off3] |
| - (pu1_pred_vert[-off1] + pu1_pred_vert[off2]) |
| + ((pu1_pred_vert[0] + pu1_pred_vert[off1] |
| - pu1_pred_vert[-off1] |
| - pu1_pred_vert[off2]) << 2) |
| + ((pu1_pred_vert[0] + pu1_pred_vert[off1]) << 4); |
| i2_temp_vert = (i2_temp_vert + 16) >> 5; |
| i2_temp_vert = CLIP_U8(i2_temp_vert); |
| |
| /* The logic below implements the following equation |
| i16_temp = puc_pred[-2] - 5 * (puc_pred[-1] + puc_pred[2]) + |
| 20 * (puc_pred[0] + puc_pred[1]) + puc_pred[3]; */ |
| i2_temp_horz = pu1_pred_horz[-2] + pu1_pred_horz[3] |
| - (pu1_pred_horz[-1] + pu1_pred_horz[2]) |
| + ((pu1_pred_horz[0] + pu1_pred_horz[1] |
| - pu1_pred_horz[-1] |
| - pu1_pred_horz[2]) << 2) |
| + ((pu1_pred_horz[0] + pu1_pred_horz[1]) << 4); |
| i2_temp_horz = (i2_temp_horz + 16) >> 5; |
| i2_temp_horz = CLIP_U8(i2_temp_horz); |
| *pu1_dst = (i2_temp_vert + i2_temp_horz + 1) >> 1; |
| } |
| pu1_pred_vert += (src_strd - wd); |
| pu1_pred_horz += (src_strd - wd); |
| pu1_dst += (dst_strd - wd); |
| } |
| } |
| |
| /*! |
| ************************************************************************** |
| * \if Function name : ih264_inter_pred_luma_horz_qpel_vert_hpel \endif |
| * |
| * \brief |
| * This routine applies the six tap filter to the predictors in the vertical |
| * and horizontal direction to obtain the pixel at (1/2,1/2). It then interpolates |
| * pixel at (0,1/2) and (1/2,1/2) to obtain pixel at (1/4,1/2). Similarly for (3/4,1/2). |
| * The six tap filtering operation is described in sec 8.4.2.2.1 titled |
| * "Luma sample interpolation process" |
| * |
| * \param pu1_src: Pointer to the buffer containing the predictor values. |
| * pu1_src could point to the frame buffer or the predictor buffer. |
| * \param pu1_dst: Pointer to the destination buffer where the output of |
| * the six tap filter followed by interpolation is stored. |
| * \param wd: Width of the rectangular pixel grid to be interpolated |
| * \param ht: Height of the rectangular pixel grid to be interpolated |
| * \param src_strd: Width of the buffer pointed to by puc_pred. |
| * \param dst_strd: Width of the destination buffer |
| * \param pu1_tmp: buffer to store temporary output after 1st 6-tap filter. |
| * \param dydx: x and y reference offset for qpel calculations. |
| * |
| * \return |
| * void |
| * |
| * \note |
| * This function takes the 8 bit predictor values, applies the six tap |
| * filter in the vertical direction and outputs the result clipped to |
| * 8 bit precision. The input is stored in the buffer pointed to by |
| * puc_pred while the output is stored in the buffer pointed by puc_dest. |
| * Both puc_pred and puc_dest could point to the same buffer i.e. the |
| * six tap filter could be done in place. |
| * |
| * \para <title> |
| * <paragraph> |
| * ... |
| ************************************************************************** |
| */ |
| void ih264_inter_pred_luma_horz_qpel_vert_hpel(UWORD8 *pu1_src, |
| UWORD8 *pu1_dst, |
| WORD32 src_strd, |
| WORD32 dst_strd, |
| WORD32 ht, |
| WORD32 wd, |
| UWORD8* pu1_tmp, |
| WORD32 dydx) |
| { |
| WORD32 row, col; |
| WORD32 tmp; |
| WORD16* pi2_pred1_temp, *pi2_pred1; |
| UWORD8* pu1_dst_tmp; |
| WORD32 x_offset = dydx & 0x3; |
| WORD16 i2_macro; |
| |
| pi2_pred1_temp = (WORD16*)pu1_tmp; |
| pi2_pred1_temp += 2; |
| pi2_pred1 = pi2_pred1_temp; |
| pu1_dst_tmp = pu1_dst; |
| |
| for(row = 0; row < ht; row++) |
| { |
| for(col = -2; col < wd + 3; col++) |
| { |
| tmp = 0;/*ih264_g_six_tap[] is the array containing the filter coeffs*/ |
| tmp = ih264_g_six_tap[0] * |
| (pu1_src[col - 2 * src_strd] + pu1_src[col + 3 * src_strd]) |
| + ih264_g_six_tap[1] * |
| (pu1_src[col - 1 * src_strd] + pu1_src[col + 2 * src_strd]) |
| + ih264_g_six_tap[2] * |
| (pu1_src[col] + pu1_src[col + 1 * src_strd]); |
| pi2_pred1_temp[col] = tmp; |
| } |
| |
| pu1_src += src_strd; |
| pi2_pred1_temp = pi2_pred1_temp + wd + 5; |
| } |
| |
| pi2_pred1_temp = pi2_pred1; |
| for(row = 0; row < ht; row++) |
| { |
| for(col = 0; col < wd; col++) |
| { |
| tmp = 0;/*ih264_g_six_tap[] is the array containing the filter coeffs*/ |
| tmp = ih264_g_six_tap[0] * |
| (pi2_pred1[col - 2] + pi2_pred1[col + 3]) |
| + ih264_g_six_tap[1] * |
| (pi2_pred1[col - 1] + pi2_pred1[col + 2]) |
| + ih264_g_six_tap[2] * |
| (pi2_pred1[col] + pi2_pred1[col + 1]); |
| tmp = (tmp + 512) >> 10; |
| pu1_dst[col] = CLIP_U8(tmp); |
| } |
| pi2_pred1 += (wd + 5); |
| pu1_dst += dst_strd; |
| } |
| |
| pu1_dst = pu1_dst_tmp; |
| pi2_pred1_temp += (x_offset >> 1); |
| for(row = ht; row != 0; row--) |
| { |
| for(col = wd; col != 0; col--, pu1_dst++, pi2_pred1_temp++) |
| { |
| UWORD8 uc_temp; |
| /* Clipping the output of the six tap filter obtained from the |
| first stage of the 2d filter stage */ |
| *pi2_pred1_temp = (*pi2_pred1_temp + 16) >> 5; |
| i2_macro = (*pi2_pred1_temp); |
| uc_temp = CLIP_U8(i2_macro); |
| *pu1_dst = (*pu1_dst + uc_temp + 1) >> 1; |
| } |
| pi2_pred1_temp += 5; |
| pu1_dst += dst_strd - wd; |
| } |
| } |
| |
| /*! |
| ************************************************************************** |
| * \if Function name : ih264_inter_pred_luma_horz_hpel_vert_qpel \endif |
| * |
| * \brief |
| * This routine applies the six tap filter to the predictors in the horizontal |
| * and vertical direction to obtain the pixel at (1/2,1/2). It then interpolates |
| * pixel at (1/2,0) and (1/2,1/2) to obtain pixel at (1/2,1/4). Similarly for (1/2,3/4). |
| * The six tap filtering operation is described in sec 8.4.2.2.1 titled |
| * "Luma sample interpolation process" |
| * |
| * \param pu1_src: Pointer to the buffer containing the predictor values. |
| * pu1_src could point to the frame buffer or the predictor buffer. |
| * \param pu1_dst: Pointer to the destination buffer where the output of |
| * the six tap filter followed by interpolation is stored. |
| * \param wd: Width of the rectangular pixel grid to be interpolated |
| * \param ht: Height of the rectangular pixel grid to be interpolated |
| * \param src_strd: Width of the buffer pointed to by puc_pred. |
| * \param dst_strd: Width of the destination buffer |
| * \param pu1_tmp: buffer to store temporary output after 1st 6-tap filter. |
| * \param dydx: x and y reference offset for qpel calculations. |
| * |
| * \return |
| * void |
| * |
| * \note |
| * This function takes the 8 bit predictor values, applies the six tap |
| * filter in the vertical direction and outputs the result clipped to |
| * 8 bit precision. The input is stored in the buffer pointed to by |
| * puc_pred while the output is stored in the buffer pointed by puc_dest. |
| * Both puc_pred and puc_dest could point to the same buffer i.e. the |
| * six tap filter could be done in place. |
| * |
| * \para <title> |
| * <paragraph> |
| * ... |
| ************************************************************************** |
| */ |
| void ih264_inter_pred_luma_horz_hpel_vert_qpel(UWORD8 *pu1_src, |
| UWORD8 *pu1_dst, |
| WORD32 src_strd, |
| WORD32 dst_strd, |
| WORD32 ht, |
| WORD32 wd, |
| UWORD8* pu1_tmp, |
| WORD32 dydx) |
| { |
| |
| WORD32 row, col; |
| WORD32 tmp; |
| WORD32 y_offset = dydx >> 2; |
| WORD16* pi2_pred1_temp, *pi2_pred1; |
| UWORD8* pu1_dst_tmp; |
| //WORD32 x_offset = dydx & 0x3; |
| WORD16 i2_macro; |
| |
| y_offset = y_offset & 0x3; |
| |
| pi2_pred1_temp = (WORD16*)pu1_tmp; |
| pi2_pred1_temp += 2 * wd; |
| pi2_pred1 = pi2_pred1_temp; |
| pu1_dst_tmp = pu1_dst; |
| pu1_src -= 2 * src_strd; |
| for(row = -2; row < ht + 3; row++) |
| { |
| for(col = 0; col < wd; col++) |
| { |
| tmp = 0;/*ih264_g_six_tap[] is the array containing the filter coeffs*/ |
| tmp = ih264_g_six_tap[0] * (pu1_src[col - 2] + pu1_src[col + 3]) |
| + ih264_g_six_tap[1] * (pu1_src[col - 1] + pu1_src[col + 2]) |
| + ih264_g_six_tap[2] * (pu1_src[col] + pu1_src[col + 1]); |
| pi2_pred1_temp[col - 2 * wd] = tmp; |
| } |
| |
| pu1_src += src_strd; |
| pi2_pred1_temp += wd; |
| } |
| pi2_pred1_temp = pi2_pred1; |
| for(row = 0; row < ht; row++) |
| { |
| for(col = 0; col < wd; col++) |
| { |
| tmp = 0;/*ih264_g_six_tap[] is the array containing the filter coeffs*/ |
| tmp = ih264_g_six_tap[0] * (pi2_pred1[col - 2 * wd] + pi2_pred1[col + 3 * wd]) |
| + ih264_g_six_tap[1] * (pi2_pred1[col - 1 * wd] + pi2_pred1[col + 2 * wd]) |
| + ih264_g_six_tap[2] * (pi2_pred1[col] + pi2_pred1[col + 1 * wd]); |
| tmp = (tmp + 512) >> 10; |
| pu1_dst[col] = CLIP_U8(tmp); |
| } |
| pi2_pred1 += wd; |
| pu1_dst += dst_strd; |
| } |
| pu1_dst = pu1_dst_tmp; |
| pi2_pred1_temp += (y_offset >> 1) * wd; |
| for(row = ht; row != 0; row--) |
| |
| { |
| for(col = wd; col != 0; col--, pu1_dst++, pi2_pred1_temp++) |
| { |
| UWORD8 u1_temp; |
| /* Clipping the output of the six tap filter obtained from the |
| first stage of the 2d filter stage */ |
| *pi2_pred1_temp = (*pi2_pred1_temp + 16) >> 5; |
| i2_macro = (*pi2_pred1_temp); |
| u1_temp = CLIP_U8(i2_macro); |
| *pu1_dst = (*pu1_dst + u1_temp + 1) >> 1; |
| } |
| //pi16_pred1_temp += wd; |
| pu1_dst += dst_strd - wd; |
| } |
| } |
| |
| /** |
| ******************************************************************************* |
| * function:ih264_inter_pred_luma_bilinear |
| * |
| * @brief |
| * This routine applies the bilinear filter to the predictors . |
| * The filtering operation is described in |
| * sec 8.4.2.2.1 titled "Luma sample interpolation process" |
| * |
| * @par Description: |
| \note |
| * This function is called to obtain pixels lying at the following |
| * locations (1/4,1), (3/4,1),(1,1/4), (1,3/4) ,(1/4,1/2), (3/4,1/2),(1/2,1/4), (1/2,3/4),(3/4,1/4),(1/4,3/4),(3/4,3/4)&& (1/4,1/4) . |
| * The function averages the two adjacent values from the two input arrays in horizontal direction. |
| * |
| * |
| * @param[in] pu1_src1: |
| * UWORD8 Pointer to the buffer containing the first input array. |
| * |
| * @param[in] pu1_src2: |
| * UWORD8 Pointer to the buffer containing the second input array. |
| * |
| * @param[out] pu1_dst |
| * UWORD8 pointer to the destination where the output of bilinear filter is stored. |
| * |
| * @param[in] src_strd1 |
| * Stride of the first input buffer |
| * |
| * @param[in] src_strd2 |
| * Stride of the second input buffer |
| * |
| * @param[in] dst_strd |
| * integer destination stride of pu1_dst |
| * |
| * @param[in] ht |
| * integer height of the array |
| * |
| * @param[in] wd |
| * integer width of the array |
| * |
| * @returns |
| * |
| * @remarks |
| * None |
| * |
| ******************************************************************************* |
| */ |
| void ih264_inter_pred_luma_bilinear(UWORD8 *pu1_src1, |
| UWORD8 *pu1_src2, |
| UWORD8 *pu1_dst, |
| WORD32 src_strd1, |
| WORD32 src_strd2, |
| WORD32 dst_strd, |
| WORD32 ht, |
| WORD32 wd) |
| { |
| WORD32 row, col; |
| WORD16 i2_tmp; |
| |
| for(row = 0; row < ht; row++) |
| { |
| for(col = 0; col < wd; col++) |
| { |
| i2_tmp = pu1_src1[col] + pu1_src2[col]; |
| i2_tmp = (i2_tmp + 1) >> 1; |
| pu1_dst[col] = CLIP_U8(i2_tmp); |
| } |
| pu1_src1 += src_strd1; |
| pu1_src2 += src_strd2; |
| pu1_dst += dst_strd; |
| } |
| |
| } |
| |
| /** |
| ******************************************************************************* |
| * |
| * @brief |
| * Interprediction chroma filter |
| * |
| * @par Description: |
| * Applies filtering to chroma samples as mentioned in |
| * sec 8.4.2.2.2 titled "chroma sample interpolation process" |
| * |
| * @param[in] pu1_src |
| * UWORD8 pointer to the source containing alternate U and V samples |
| * |
| * @param[out] pu1_dst |
| * UWORD8 pointer to the destination |
| * |
| * @param[in] src_strd |
| * integer source stride |
| * |
| * @param[in] dst_strd |
| * integer destination stride |
| * |
| * @param[in] u1_dx |
| * dx value where the sample is to be produced(refer sec 8.4.2.2.2 ) |
| * |
| * @param[in] u1_dy |
| * dy value where the sample is to be produced(refer sec 8.4.2.2.2 ) |
| * |
| * @param[in] ht |
| * integer height of the array |
| * |
| * @param[in] wd |
| * integer width of the array |
| * |
| * @returns |
| * |
| * @remarks |
| * None |
| * |
| ******************************************************************************* |
| */ |
| void ih264_inter_pred_chroma(UWORD8 *pu1_src, |
| UWORD8 *pu1_dst, |
| WORD32 src_strd, |
| WORD32 dst_strd, |
| WORD32 dx, |
| WORD32 dy, |
| WORD32 ht, |
| WORD32 wd) |
| { |
| WORD32 row, col; |
| WORD16 i2_tmp; |
| |
| for(row = 0; row < ht; row++) |
| { |
| for(col = 0; col < 2 * wd; col++) |
| { |
| i2_tmp = 0; /* applies equation (8-266) in section 8.4.2.2.2 */ |
| i2_tmp = (8 - dx) * (8 - dy) * pu1_src[col] |
| + (dx) * (8 - dy) * pu1_src[col + 2] |
| + (8 - dx) * (dy) * (pu1_src + src_strd)[col] |
| + (dx) * (dy) * (pu1_src + src_strd)[col + 2]; |
| i2_tmp = (i2_tmp + 32) >> 6; |
| pu1_dst[col] = CLIP_U8(i2_tmp); |
| } |
| pu1_src += src_strd; |
| pu1_dst += dst_strd; |
| } |
| } |