This patch adds MSA (MIPS-SIMD-Arch) optimizations for mpegvideo functions in new file mpegvideo_msa.c Signed-off-by: Shivraj Patil <shivraj.patil@imgtec.com> Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
		
			
				
	
	
		
			251 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			251 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * Copyright (c) 2015 Manojkumar Bhosale (Manojkumar.Bhosale@imgtec.com)
 | 
						|
 *
 | 
						|
 * This file is part of FFmpeg.
 | 
						|
 *
 | 
						|
 * FFmpeg is free software; you can redistribute it and/or
 | 
						|
 * modify it under the terms of the GNU Lesser General Public
 | 
						|
 * License as published by the Free Software Foundation; either
 | 
						|
 * version 2.1 of the License, or (at your option) any later version.
 | 
						|
 *
 | 
						|
 * FFmpeg is distributed in the hope that it will be useful,
 | 
						|
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
						|
 * Lesser General Public License for more details.
 | 
						|
 *
 | 
						|
 * You should have received a copy of the GNU Lesser General Public
 | 
						|
 * License along with FFmpeg; if not, write to the Free Software
 | 
						|
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 | 
						|
 */
 | 
						|
 | 
						|
#include "libavutil/mips/generic_macros_msa.h"
 | 
						|
#include "h263dsp_mips.h"
 | 
						|
 | 
						|
static void h263_dct_unquantize_msa(int16_t *block, int16_t qmul,
 | 
						|
                                    int16_t qadd, int8_t n_coeffs,
 | 
						|
                                    uint8_t loop_start)
 | 
						|
{
 | 
						|
    int16_t *block_dup = block;
 | 
						|
    int32_t level, cnt;
 | 
						|
    v8i16 block_vec, qmul_vec, qadd_vec, sub;
 | 
						|
    v8i16 add, mask, mul, zero_mask;
 | 
						|
 | 
						|
    qmul_vec = __msa_fill_h(qmul);
 | 
						|
    qadd_vec = __msa_fill_h(qadd);
 | 
						|
    for (cnt = 0; cnt < (n_coeffs >> 3); cnt++) {
 | 
						|
        block_vec = LD_SH(block_dup + loop_start);
 | 
						|
        mask = __msa_clti_s_h(block_vec, 0);
 | 
						|
        zero_mask = __msa_ceqi_h(block_vec, 0);
 | 
						|
        mul = block_vec * qmul_vec;
 | 
						|
        sub = mul - qadd_vec;
 | 
						|
        add = mul + qadd_vec;
 | 
						|
        add = (v8i16) __msa_bmnz_v((v16u8) add, (v16u8) sub, (v16u8) mask);
 | 
						|
        block_vec = (v8i16) __msa_bmnz_v((v16u8) add, (v16u8) block_vec,
 | 
						|
                                         (v16u8) zero_mask);
 | 
						|
        ST_SH(block_vec, block_dup + loop_start);
 | 
						|
        block_dup += 8;
 | 
						|
    }
 | 
						|
 | 
						|
    cnt = ((n_coeffs >> 3) * 8) + loop_start;
 | 
						|
 | 
						|
    for (; cnt <= n_coeffs; cnt++) {
 | 
						|
        level = block[cnt];
 | 
						|
        if (level) {
 | 
						|
            if (level < 0) {
 | 
						|
                level = level * qmul - qadd;
 | 
						|
            } else {
 | 
						|
                level = level * qmul + qadd;
 | 
						|
            }
 | 
						|
            block[cnt] = level;
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static int32_t mpeg2_dct_unquantize_inter_msa(int16_t *block,
 | 
						|
                                              int32_t qscale,
 | 
						|
                                              const int16_t *quant_matrix)
 | 
						|
{
 | 
						|
    int32_t cnt, sum_res = -1;
 | 
						|
    v8i16 block_vec, block_neg, qscale_vec, mask;
 | 
						|
    v8i16 block_org0, block_org1, block_org2, block_org3;
 | 
						|
    v8i16 quant_m0, quant_m1, quant_m2, quant_m3;
 | 
						|
    v8i16 sum, mul, zero_mask;
 | 
						|
    v4i32 mul_vec, qscale_l, qscale_r, quant_m_r, quant_m_l;
 | 
						|
    v4i32 block_l, block_r, sad;
 | 
						|
 | 
						|
    qscale_vec = __msa_fill_h(qscale);
 | 
						|
    for (cnt = 0; cnt < 2; cnt++) {
 | 
						|
        LD_SH4(block, 8, block_org0, block_org1, block_org2, block_org3);
 | 
						|
        LD_SH4(quant_matrix, 8, quant_m0, quant_m1, quant_m2, quant_m3);
 | 
						|
        mask = __msa_clti_s_h(block_org0, 0);
 | 
						|
        zero_mask = __msa_ceqi_h(block_org0, 0);
 | 
						|
        block_neg = -block_org0;
 | 
						|
        block_vec = (v8i16) __msa_bmnz_v((v16u8) block_org0, (v16u8) block_neg,
 | 
						|
                                         (v16u8) mask);
 | 
						|
        block_vec <<= 1;
 | 
						|
        block_vec += 1;
 | 
						|
        UNPCK_SH_SW(block_vec, block_r, block_l);
 | 
						|
        UNPCK_SH_SW(qscale_vec, qscale_r, qscale_l);
 | 
						|
        UNPCK_SH_SW(quant_m0, quant_m_r, quant_m_l);
 | 
						|
        mul_vec = block_l * qscale_l;
 | 
						|
        mul_vec *= quant_m_l;
 | 
						|
        block_l = mul_vec >> 4;
 | 
						|
        mul_vec = block_r * qscale_r;
 | 
						|
        mul_vec *= quant_m_r;
 | 
						|
        block_r = mul_vec >> 4;
 | 
						|
        mul = (v8i16) __msa_pckev_h((v8i16) block_l, (v8i16) block_r);
 | 
						|
        block_neg = - mul;
 | 
						|
        sum = (v8i16) __msa_bmnz_v((v16u8) mul, (v16u8) block_neg,
 | 
						|
                                   (v16u8) mask);
 | 
						|
        sum = (v8i16) __msa_bmnz_v((v16u8) sum, (v16u8) block_org0,
 | 
						|
                                   (v16u8) zero_mask);
 | 
						|
        ST_SH(sum, block);
 | 
						|
        block += 8;
 | 
						|
        quant_matrix += 8;
 | 
						|
        sad = __msa_hadd_s_w(sum, sum);
 | 
						|
        sum_res += HADD_SW_S32(sad);
 | 
						|
        mask = __msa_clti_s_h(block_org1, 0);
 | 
						|
        zero_mask = __msa_ceqi_h(block_org1, 0);
 | 
						|
        block_neg = - block_org1;
 | 
						|
        block_vec = (v8i16) __msa_bmnz_v((v16u8) block_org1, (v16u8) block_neg,
 | 
						|
                                         (v16u8) mask);
 | 
						|
        block_vec <<= 1;
 | 
						|
        block_vec += 1;
 | 
						|
        UNPCK_SH_SW(block_vec, block_r, block_l);
 | 
						|
        UNPCK_SH_SW(qscale_vec, qscale_r, qscale_l);
 | 
						|
        UNPCK_SH_SW(quant_m1, quant_m_r, quant_m_l);
 | 
						|
        mul_vec = block_l * qscale_l;
 | 
						|
        mul_vec *= quant_m_l;
 | 
						|
        block_l = mul_vec >> 4;
 | 
						|
        mul_vec = block_r * qscale_r;
 | 
						|
        mul_vec *= quant_m_r;
 | 
						|
        block_r = mul_vec >> 4;
 | 
						|
        mul = __msa_pckev_h((v8i16) block_l, (v8i16) block_r);
 | 
						|
        block_neg = - mul;
 | 
						|
        sum = (v8i16) __msa_bmnz_v((v16u8) mul, (v16u8) block_neg,
 | 
						|
                                   (v16u8) mask);
 | 
						|
        sum = (v8i16) __msa_bmnz_v((v16u8) sum, (v16u8) block_org1,
 | 
						|
                                   (v16u8) zero_mask);
 | 
						|
        ST_SH(sum, block);
 | 
						|
 | 
						|
        block += 8;
 | 
						|
        quant_matrix += 8;
 | 
						|
        sad = __msa_hadd_s_w(sum, sum);
 | 
						|
        sum_res += HADD_SW_S32(sad);
 | 
						|
        mask = __msa_clti_s_h(block_org2, 0);
 | 
						|
        zero_mask = __msa_ceqi_h(block_org2, 0);
 | 
						|
        block_neg = - block_org2;
 | 
						|
        block_vec = (v8i16) __msa_bmnz_v((v16u8) block_org2, (v16u8) block_neg,
 | 
						|
                                         (v16u8) mask);
 | 
						|
        block_vec <<= 1;
 | 
						|
        block_vec += 1;
 | 
						|
        UNPCK_SH_SW(block_vec, block_r, block_l);
 | 
						|
        UNPCK_SH_SW(qscale_vec, qscale_r, qscale_l);
 | 
						|
        UNPCK_SH_SW(quant_m2, quant_m_r, quant_m_l);
 | 
						|
        mul_vec = block_l * qscale_l;
 | 
						|
        mul_vec *= quant_m_l;
 | 
						|
        block_l = mul_vec >> 4;
 | 
						|
        mul_vec = block_r * qscale_r;
 | 
						|
        mul_vec *= quant_m_r;
 | 
						|
        block_r = mul_vec >> 4;
 | 
						|
        mul = __msa_pckev_h((v8i16) block_l, (v8i16) block_r);
 | 
						|
        block_neg = - mul;
 | 
						|
        sum = (v8i16) __msa_bmnz_v((v16u8) mul, (v16u8) block_neg,
 | 
						|
                                   (v16u8) mask);
 | 
						|
        sum = (v8i16) __msa_bmnz_v((v16u8) sum, (v16u8) block_org2,
 | 
						|
                                   (v16u8) zero_mask);
 | 
						|
        ST_SH(sum, block);
 | 
						|
 | 
						|
        block += 8;
 | 
						|
        quant_matrix += 8;
 | 
						|
        sad = __msa_hadd_s_w(sum, sum);
 | 
						|
        sum_res += HADD_SW_S32(sad);
 | 
						|
        mask = __msa_clti_s_h(block_org3, 0);
 | 
						|
        zero_mask = __msa_ceqi_h(block_org3, 0);
 | 
						|
        block_neg = - block_org3;
 | 
						|
        block_vec = (v8i16) __msa_bmnz_v((v16u8) block_org3, (v16u8) block_neg,
 | 
						|
                                         (v16u8) mask);
 | 
						|
        block_vec <<= 1;
 | 
						|
        block_vec += 1;
 | 
						|
        UNPCK_SH_SW(block_vec, block_r, block_l);
 | 
						|
        UNPCK_SH_SW(qscale_vec, qscale_r, qscale_l);
 | 
						|
        UNPCK_SH_SW(quant_m3, quant_m_r, quant_m_l);
 | 
						|
        mul_vec = block_l * qscale_l;
 | 
						|
        mul_vec *= quant_m_l;
 | 
						|
        block_l = mul_vec >> 4;
 | 
						|
        mul_vec = block_r * qscale_r;
 | 
						|
        mul_vec *= quant_m_r;
 | 
						|
        block_r = mul_vec >> 4;
 | 
						|
        mul = __msa_pckev_h((v8i16) block_l, (v8i16) block_r);
 | 
						|
        block_neg = - mul;
 | 
						|
        sum = (v8i16) __msa_bmnz_v((v16u8) mul, (v16u8) block_neg,
 | 
						|
                                   (v16u8) mask);
 | 
						|
        sum = (v8i16) __msa_bmnz_v((v16u8) sum, (v16u8) block_org3,
 | 
						|
                                   (v16u8) zero_mask);
 | 
						|
        ST_SH(sum, block);
 | 
						|
 | 
						|
        block += 8;
 | 
						|
        quant_matrix += 8;
 | 
						|
        sad = __msa_hadd_s_w(sum, sum);
 | 
						|
        sum_res += HADD_SW_S32(sad);
 | 
						|
    }
 | 
						|
 | 
						|
    return sum_res;
 | 
						|
}
 | 
						|
 | 
						|
void ff_dct_unquantize_h263_intra_msa(MpegEncContext *s,
 | 
						|
                                      int16_t *block, int32_t index,
 | 
						|
                                      int32_t qscale)
 | 
						|
{
 | 
						|
    int32_t qmul, qadd;
 | 
						|
    int32_t nCoeffs;
 | 
						|
 | 
						|
    av_assert2(s->block_last_index[index] >= 0 || s->h263_aic);
 | 
						|
 | 
						|
    qmul = qscale << 1;
 | 
						|
 | 
						|
    if (!s->h263_aic) {
 | 
						|
        block[0] *= index < 4 ? s->y_dc_scale : s->c_dc_scale;
 | 
						|
        qadd = (qscale - 1) | 1;
 | 
						|
    } else {
 | 
						|
        qadd = 0;
 | 
						|
    }
 | 
						|
    if (s->ac_pred)
 | 
						|
        nCoeffs = 63;
 | 
						|
    else
 | 
						|
        nCoeffs = s->inter_scantable.raster_end[s->block_last_index[index]];
 | 
						|
 | 
						|
    h263_dct_unquantize_msa(block, qmul, qadd, nCoeffs, 1);
 | 
						|
}
 | 
						|
 | 
						|
void ff_dct_unquantize_h263_inter_msa(MpegEncContext *s,
 | 
						|
                                      int16_t *block, int32_t index,
 | 
						|
                                      int32_t qscale)
 | 
						|
{
 | 
						|
    int32_t qmul, qadd;
 | 
						|
    int32_t nCoeffs;
 | 
						|
 | 
						|
    av_assert2(s->block_last_index[index] >= 0);
 | 
						|
 | 
						|
    qadd = (qscale - 1) | 1;
 | 
						|
    qmul = qscale << 1;
 | 
						|
 | 
						|
    nCoeffs = s->inter_scantable.raster_end[s->block_last_index[index]];
 | 
						|
 | 
						|
    h263_dct_unquantize_msa(block, qmul, qadd, nCoeffs, 0);
 | 
						|
}
 | 
						|
 | 
						|
void ff_dct_unquantize_mpeg2_inter_msa(MpegEncContext *s,
 | 
						|
                                       int16_t *block, int32_t index,
 | 
						|
                                       int32_t qscale)
 | 
						|
{
 | 
						|
    const uint16_t *quant_matrix;
 | 
						|
    int32_t sum = -1;
 | 
						|
 | 
						|
    quant_matrix = s->inter_matrix;
 | 
						|
 | 
						|
    sum = mpeg2_dct_unquantize_inter_msa(block, qscale, quant_matrix);
 | 
						|
 | 
						|
    block[63] ^= sum & 1;
 | 
						|
}
 |