/******************************************************************************
*
* Copyright (C) 2018 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 ihevce_chroma_had_satd.c
*
* \brief
* This file contains function definitions of chroma HAD SATD functions
*
* \date
* 15/07/2013
*
* \author
* Ittiam
*
* List of Functions
* ihevce_chroma_HAD_4x4_8b()
* ihevce_chroma_compute_AC_HAD_4x4_8bit()
* ihevce_hbd_chroma_HAD_4x4()
* ihevce_hbd_chroma_compute_AC_HAD_4x4()
* ihevce_chroma_HAD_8x8_8bit()
* ihevce_hbd_chroma_HAD_8x8()
* ihevce_chroma_HAD_16x16_8bit()
* ihevce_hbd_chroma_HAD_16x16()
*
******************************************************************************
*/
/*****************************************************************************/
/* File Includes */
/*****************************************************************************/
/* System include files */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <stdarg.h>
#include <math.h>
/* User include files */
#include "ihevc_typedefs.h"
#include "ihevc_debug.h"
#include "itt_video_api.h"
#include "ihevce_api.h"
#include "ihevce_defs.h"
#include "ihevce_had_satd.h"
/*****************************************************************************/
/* Function Definitions */
/*****************************************************************************/
/**
*******************************************************************************
*
* @brief
* Chroma Hadamard Transform of 4x4 block (8-bit input)
*
* @par Description:
*
* @param[in] pu1_origin
* UWORD8 pointer to the source block (u or v, interleaved)
*
* @param[in] src_strd
* WORD32 Source stride
*
* @param[in] pu1_pred_buf
* UWORD8 pointer to the prediction block (u or v, interleaved)
*
* @param[in] pred_strd
* WORD32 Pred stride
*
* @param[in] pi2_dst
* WORD16 pointer to the transform block
*
* @param[in] dst_strd (u or v, interleaved)
* WORD32 Destination stride
*
* @returns
* Hadamard SAD
*
* @remarks
* Not updating the transform destination now. Only returning the SATD
*
*******************************************************************************
*/
UWORD32 ihevce_chroma_HAD_4x4_8bit(
UWORD8 *pu1_origin,
WORD32 src_strd,
UWORD8 *pu1_pred_buf,
WORD32 pred_strd,
WORD16 *pi2_dst,
WORD32 dst_strd)
{
WORD32 k;
WORD16 diff[16], m[16], d[16];
UWORD32 u4_sad = 0;
(void)pi2_dst;
(void)dst_strd;
for(k = 0; k < 16; k += 4)
{
/* u or v, interleaved */
diff[k + 0] = pu1_origin[2 * 0] - pu1_pred_buf[2 * 0];
diff[k + 1] = pu1_origin[2 * 1] - pu1_pred_buf[2 * 1];
diff[k + 2] = pu1_origin[2 * 2] - pu1_pred_buf[2 * 2];
diff[k + 3] = pu1_origin[2 * 3] - pu1_pred_buf[2 * 3];
pu1_pred_buf += pred_strd;
pu1_origin += src_strd;
}
/*===== hadamard transform =====*/
m[0] = diff[0] + diff[12];
m[1] = diff[1] + diff[13];
m[2] = diff[2] + diff[14];
m[3] = diff[3] + diff[15];
m[4] = diff[4] + diff[8];
m[5] = diff[5] + diff[9];
m[6] = diff[6] + diff[10];
m[7] = diff[7] + diff[11];
m[8] = diff[4] - diff[8];
m[9] = diff[5] - diff[9];
m[10] = diff[6] - diff[10];
m[11] = diff[7] - diff[11];
m[12] = diff[0] - diff[12];
m[13] = diff[1] - diff[13];
m[14] = diff[2] - diff[14];
m[15] = diff[3] - diff[15];
d[0] = m[0] + m[4];
d[1] = m[1] + m[5];
d[2] = m[2] + m[6];
d[3] = m[3] + m[7];
d[4] = m[8] + m[12];
d[5] = m[9] + m[13];
d[6] = m[10] + m[14];
d[7] = m[11] + m[15];
d[8] = m[0] - m[4];
d[9] = m[1] - m[5];
d[10] = m[2] - m[6];
d[11] = m[3] - m[7];
d[12] = m[12] - m[8];
d[13] = m[13] - m[9];
d[14] = m[14] - m[10];
d[15] = m[15] - m[11];
m[0] = d[0] + d[3];
m[1] = d[1] + d[2];
m[2] = d[1] - d[2];
m[3] = d[0] - d[3];
m[4] = d[4] + d[7];
m[5] = d[5] + d[6];
m[6] = d[5] - d[6];
m[7] = d[4] - d[7];
m[8] = d[8] + d[11];
m[9] = d[9] + d[10];
m[10] = d[9] - d[10];
m[11] = d[8] - d[11];
m[12] = d[12] + d[15];
m[13] = d[13] + d[14];
m[14] = d[13] - d[14];
m[15] = d[12] - d[15];
d[0] = m[0] + m[1];
d[1] = m[0] - m[1];
d[2] = m[2] + m[3];
d[3] = m[3] - m[2];
d[4] = m[4] + m[5];
d[5] = m[4] - m[5];
d[6] = m[6] + m[7];
d[7] = m[7] - m[6];
d[8] = m[8] + m[9];
d[9] = m[8] - m[9];
d[10] = m[10] + m[11];
d[11] = m[11] - m[10];
d[12] = m[12] + m[13];
d[13] = m[12] - m[13];
d[14] = m[14] + m[15];
d[15] = m[15] - m[14];
/*===== sad =====*/
for(k = 0; k < 16; ++k)
{
u4_sad += (d[k] > 0 ? d[k] : -d[k]);
}
u4_sad = ((u4_sad + 2) >> 2);
return u4_sad;
}
/**
*******************************************************************************
*
* @brief
* Chroma Hadamard Transform of 4x4 block (8-bit input) with DC suppressed
*
* @par Description:
*
* @param[in] pu1_origin
* UWORD8 pointer to the source block (u or v, interleaved)
*
* @param[in] src_strd
* WORD32 Source stride
*
* @param[in] pu1_pred_buf
* UWORD8 pointer to the prediction block (u or v, interleaved)
*
* @param[in] pred_strd
* WORD32 Pred stride
*
* @param[in] pi2_dst
* WORD16 pointer to the transform block
*
* @param[in] dst_strd (u or v, interleaved)
* WORD32 Destination stride
*
* @returns
* Hadamard SAD
*
* @remarks
* Not updating the transform destination now. Only returning the SATD
*
*******************************************************************************
*/
UWORD32 ihevce_chroma_compute_AC_HAD_4x4_8bit(
UWORD8 *pu1_origin,
WORD32 src_strd,
UWORD8 *pu1_pred_buf,
WORD32 pred_strd,
WORD16 *pi2_dst,
WORD32 dst_strd)
{
WORD32 k;
WORD16 diff[16], m[16], d[16];
UWORD32 u4_sad = 0;
(void)pi2_dst;
(void)dst_strd;
for(k = 0; k < 16; k += 4)
{
/* u or v, interleaved */
diff[k + 0] = pu1_origin[2 * 0] - pu1_pred_buf[2 * 0];
diff[k + 1] = pu1_origin[2 * 1] - pu1_pred_buf[2 * 1];
diff[k + 2] = pu1_origin[2 * 2] - pu1_pred_buf[2 * 2];
diff[k + 3] = pu1_origin[2 * 3] - pu1_pred_buf[2 * 3];
pu1_pred_buf += pred_strd;
pu1_origin += src_strd;
}
/*===== hadamard transform =====*/
m[0] = diff[0] + diff[12];
m[1] = diff[1] + diff[13];
m[2] = diff[2] + diff[14];
m[3] = diff[3] + diff[15];
m[4] = diff[4] + diff[8];
m[5] = diff[5] + diff[9];
m[6] = diff[6] + diff[10];
m[7] = diff[7] + diff[11];
m[8] = diff[4] - diff[8];
m[9] = diff[5] - diff[9];
m[10] = diff[6] - diff[10];
m[11] = diff[7] - diff[11];
m[12] = diff[0] - diff[12];
m[13] = diff[1] - diff[13];
m[14] = diff[2] - diff[14];
m[15] = diff[3] - diff[15];
d[0] = m[0] + m[4];
d[1] = m[1] + m[5];
d[2] = m[2] + m[6];
d[3] = m[3] + m[7];
d[4] = m[8] + m[12];
d[5] = m[9] + m[13];
d[6] = m[10] + m[14];
d[7] = m[11] + m[15];
d[8] = m[0] - m[4];
d[9] = m[1] - m[5];
d[10] = m[2] - m[6];
d[11] = m[3] - m[7];
d[12] = m[12] - m[8];
d[13] = m[13] - m[9];
d[14] = m[14] - m[10];
d[15] = m[15] - m[11];
m[0] = d[0] + d[3];
m[1] = d[1] + d[2];
m[2] = d[1] - d[2];
m[3] = d[0] - d[3];
m[4] = d[4] + d[7];
m[5] = d[5] + d[6];
m[6] = d[5] - d[6];
m[7] = d[4] - d[7];
m[8] = d[8] + d[11];
m[9] = d[9] + d[10];
m[10] = d[9] - d[10];
m[11] = d[8] - d[11];
m[12] = d[12] + d[15];
m[13] = d[13] + d[14];
m[14] = d[13] - d[14];
m[15] = d[12] - d[15];
d[0] = m[0] + m[1];
d[1] = m[0] - m[1];
d[2] = m[2] + m[3];
d[3] = m[3] - m[2];
d[4] = m[4] + m[5];
d[5] = m[4] - m[5];
d[6] = m[6] + m[7];
d[7] = m[7] - m[6];
d[8] = m[8] + m[9];
d[9] = m[8] - m[9];
d[10] = m[10] + m[11];
d[11] = m[11] - m[10];
d[12] = m[12] + m[13];
d[13] = m[12] - m[13];
d[14] = m[14] + m[15];
d[15] = m[15] - m[14];
/* DC masking */
d[0] = 0;
/*===== sad =====*/
for(k = 0; k < 16; ++k)
{
u4_sad += (d[k] > 0 ? d[k] : -d[k]);
}
u4_sad = ((u4_sad + 2) >> 2);
return u4_sad;
}
/**
*******************************************************************************
*
* @brief
* Chroma Hadamard Transform of 8x8 block (8-bit input)
*
* @par Description:
*
* @param[in] pu1_origin
* UWORD8 pointer to the source block (u or v, interleaved)
*
* @param[in] src_strd
* WORD32 Source stride
*
* @param[in] pu1_pred_buf
* UWORD8 pointer to the prediction block (u or v, interleaved)
*
* @param[in] pred_strd
* WORD32 Pred stride
*
* @param[in] pi2_dst
* WORD16 pointer to the transform block
*
* @param[in] dst_strd (u or v, interleaved)
* WORD32 Destination stride
*
* @returns
* Hadamard SAD
*
* @remarks
* Not updating the transform destination now. Only returning the SATD
*
*******************************************************************************
*/
UWORD32 ihevce_chroma_HAD_8x8_8bit(
UWORD8 *pu1_origin,
WORD32 src_strd,
UWORD8 *pu1_pred_buf,
WORD32 pred_strd,
WORD16 *pi2_dst,
WORD32 dst_strd)
{
WORD32 k, i, j, jj;
UWORD32 u4_sad = 0;
WORD16 diff[64], m1[8][8], m2[8][8], m3[8][8];
(void)pi2_dst;
(void)dst_strd;
for(k = 0; k < 64; k += 8)
{
/* u or v, interleaved */
diff[k + 0] = pu1_origin[2 * 0] - pu1_pred_buf[2 * 0];
diff[k + 1] = pu1_origin[2 * 1] - pu1_pred_buf[2 * 1];
diff[k + 2] = pu1_origin[2 * 2] - pu1_pred_buf[2 * 2];
diff[k + 3] = pu1_origin[2 * 3] - pu1_pred_buf[2 * 3];
diff[k + 4] = pu1_origin[2 * 4] - pu1_pred_buf[2 * 4];
diff[k + 5] = pu1_origin[2 * 5] - pu1_pred_buf[2 * 5];
diff[k + 6] = pu1_origin[2 * 6] - pu1_pred_buf[2 * 6];
diff[k + 7] = pu1_origin[2 * 7] - pu1_pred_buf[2 * 7];
pu1_pred_buf += pred_strd;
pu1_origin += src_strd;
}
/*===== hadamard transform =====*/
// horizontal
for(j = 0; j < 8; j++)
{
jj = j << 3;
m2[j][0] = diff[jj] + diff[jj + 4];
m2[j][1] = diff[jj + 1] + diff[jj + 5];
m2[j][2] = diff[jj + 2] + diff[jj + 6];
m2[j][3] = diff[jj + 3] + diff[jj + 7];
m2[j][4] = diff[jj] - diff[jj + 4];
m2[j][5] = diff[jj + 1] - diff[jj + 5];
m2[j][6] = diff[jj + 2] - diff[jj + 6];
m2[j][7] = diff[jj + 3] - diff[jj + 7];
m1[j][0] = m2[j][0] + m2[j][2];
m1[j][1] = m2[j][1] + m2[j][3];
m1[j][2] = m2[j][0] - m2[j][2];
m1[j][3] = m2[j][1] - m2[j][3];
m1[j][4] = m2[j][4] + m2[j][6];
m1[j][5] = m2[j][5] + m2[j][7];
m1[j][6] = m2[j][4] - m2[j][6];
m1[j][7] = m2[j][5] - m2[j][7];
m2[j][0] = m1[j][0] + m1[j][1];
m2[j][1] = m1[j][0] - m1[j][1];
m2[j][2] = m1[j][2] + m1[j][3];
m2[j][3] = m1[j][2] - m1[j][3];
m2[j][4] = m1[j][4] + m1[j][5];
m2[j][5] = m1[j][4] - m1[j][5];
m2[j][6] = m1[j][6] + m1[j][7];
m2[j][7] = m1[j][6] - m1[j][7];
}
// vertical
for(i = 0; i < 8; i++)
{
m3[0][i] = m2[0][i] + m2[4][i];
m3[1][i] = m2[1][i] + m2[5][i];
m3[2][i] = m2[2][i] + m2[6][i];
m3[3][i] = m2[3][i] + m2[7][i];
m3[4][i] = m2[0][i] - m2[4][i];
m3[5][i] = m2[1][i] - m2[5][i];
m3[6][i] = m2[2][i] - m2[6][i];
m3[7][i] = m2[3][i] - m2[7][i];
m1[0][i] = m3[0][i] + m3[2][i];
m1[1][i] = m3[1][i] + m3[3][i];
m1[2][i] = m3[0][i] - m3[2][i];
m1[3][i] = m3[1][i] - m3[3][i];
m1[4][i] = m3[4][i] + m3[6][i];
m1[5][i] = m3[5][i] + m3[7][i];
m1[6][i] = m3[4][i] - m3[6][i];
m1[7][i] = m3[5][i] - m3[7][i];
m2[0][i] = m1[0][i] + m1[1][i];
m2[1][i] = m1[0][i] - m1[1][i];
m2[2][i] = m1[2][i] + m1[3][i];
m2[3][i] = m1[2][i] - m1[3][i];
m2[4][i] = m1[4][i] + m1[5][i];
m2[5][i] = m1[4][i] - m1[5][i];
m2[6][i] = m1[6][i] + m1[7][i];
m2[7][i] = m1[6][i] - m1[7][i];
}
/*===== sad =====*/
for(i = 0; i < 8; i++)
{
for(j = 0; j < 8; j++)
{
u4_sad += (m2[i][j] > 0 ? m2[i][j] : -m2[i][j]);
}
}
u4_sad = ((u4_sad + 4) >> 3);
return u4_sad;
}
/**
*******************************************************************************
*
* @brief
* Chroma Hadamard Transform of 16x16 block (8-bit input)
*
* @par Description:
*
* @param[in] pu1_origin
* UWORD8 pointer to the source block (u or v, interleaved)
*
* @param[in] src_strd
* WORD32 Source stride
*
* @param[in] pu1_pred_buf
* UWORD8 pointer to the prediction block (u or v, interleaved)
*
* @param[in] pred_strd
* WORD32 Pred stride
*
* @param[in] pi2_dst
* WORD16 pointer to the transform block
*
* @param[in] dst_strd (u or v, interleaved)
* WORD32 Destination stride
*
* @returns
* Hadamard SAD
*
* @remarks
* Not updating the transform destination now. Only returning the SATD
*
*******************************************************************************
*/
UWORD32 ihevce_chroma_HAD_16x16_8bit(
UWORD8 *pu1_origin,
WORD32 src_strd,
UWORD8 *pu1_pred_buf,
WORD32 pred_strd,
WORD16 *pi2_dst,
WORD32 dst_strd)
{
UWORD32 au4_sad[4], u4_result = 0;
WORD32 i;
for(i = 0; i < 4; i++)
{
au4_sad[i] = ihevce_chroma_HAD_8x8_8bit(
pu1_origin, src_strd, pu1_pred_buf, pred_strd, pi2_dst, dst_strd);
if(i == 0 || i == 2)
{
pu1_origin += 16;
pu1_pred_buf += 16;
}
if(i == 1)
{
pu1_origin += (8 * src_strd) - 16;
pu1_pred_buf += (8 * pred_strd) - 16;
}
u4_result += au4_sad[i];
}
return u4_result;
}