/* * Copyright (c) 2012 * MIPS Technologies, Inc., California. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * Author: Stanislav Ocovaj (socovaj@mips.com) * Szabolcs Pal (sabolc@mips.com) * * AAC coefficients encoder optimized for MIPS floating-point architecture * * 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 */ /** * @file * Reference: libavcodec/aaccoder.c */ #include "libavutil/libm.h" #include <float.h>#include "libavutil/mathematics.h"#include "libavcodec/avcodec.h"#include "libavcodec/put_bits.h"#include "libavcodec/aac.h"#include "libavcodec/aacenc.h"#include "libavcodec/aactab.h"#include "libavcodec/aacenctab.h"#include "libavcodec/aacenc_utils.h" #if HAVE_INLINE_ASM#if !HAVE_MIPS32R6 && !HAVE_MIPS64R6typedef struct BandCodingPath { int prev_idx; float cost; int run;} BandCodingPath; static const uint8_t uquad_sign_bits[81] = { 0, 1, 1, 1, 2, 2, 1, 2, 2, 1, 2, 2, 2, 3, 3, 2, 3, 3, 1, 2, 2, 2, 3, 3, 2, 3, 3, 1, 2, 2, 2, 3, 3, 2, 3, 3, 2, 3, 3, 3, 4, 4, 3, 4, 4, 2, 3, 3, 3, 4, 4, 3, 4, 4, 1, 2, 2, 2, 3, 3, 2, 3, 3, 2, 3, 3, 3, 4, 4, 3, 4, 4, 2, 3, 3, 3, 4, 4, 3, 4, 4}; static const uint8_t upair7_sign_bits[64] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2,}; static const uint8_t upair12_sign_bits[169] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; static const uint8_t esc_sign_bits[289] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; /** * Functions developed from template function and optimized for quantizing and encoding band */static void quantize_and_encode_band_cost_SQUAD_mips(struct AACEncContext *s, PutBitContext *pb, const float *in, float *out, const float *scaled, int size, int scale_idx, int cb, const float lambda, const float uplim, int *bits, float *energy, const float ROUNDING){ const float Q34 = ff_aac_pow34sf_tab[POW_SF2_ZERO - scale_idx + SCALE_ONE_POS - SCALE_DIV_512]; const float IQ = ff_aac_pow2sf_tab [POW_SF2_ZERO + scale_idx - SCALE_ONE_POS + SCALE_DIV_512]; int i; int qc1, qc2, qc3, qc4; float qenergy = 0.0f; uint8_t *p_bits = (uint8_t *)ff_aac_spectral_bits[cb-1]; uint16_t *p_codes = (uint16_t *)ff_aac_spectral_codes[cb-1]; float *p_vec = (float *)ff_aac_codebook_vectors[cb-1]; abs_pow34_v(s->scoefs, in, size); scaled = s->scoefs; for (i = 0; i < size; i += 4) { int curidx; int *in_int = (int *)&in[i]; int t0, t1, t2, t3, t4, t5, t6, t7; const float *vec; qc1 = scaled[i ] * Q34 + ROUND_STANDARD; qc2 = scaled[i+1] * Q34 + ROUND_STANDARD; qc3 = scaled[i+2] * Q34 + ROUND_STANDARD; qc4 = scaled[i+3] * Q34 + ROUND_STANDARD; __asm__ volatile ( ".set push \n\t" ".set noreorder \n\t" "slt %[qc1], $zero, %[qc1] \n\t" "slt %[qc2], $zero, %[qc2] \n\t" "slt %[qc3], $zero, %[qc3] \n\t" "slt %[qc4], $zero, %[qc4] \n\t" "lw %[t0], 0(%[in_int]) \n\t" "lw %[t1], 4(%[in_int]) \n\t" "lw %[t2], 8(%[in_int]) \n\t" "lw %[t3], 12(%[in_int]) \n\t" "srl %[t0], %[t0], 31 \n\t" "srl %[t1], %[t1], 31 \n\t" "srl %[t2], %[t2], 31 \n\t" "srl %[t3], %[t3], 31 \n\t" "subu %[t4], $zero, %[qc1] \n\t" "subu %[t5], $zero, %[qc2] \n\t" "subu %[t6], $zero, %[qc3] \n\t" "subu %[t7], $zero, %[qc4] \n\t" "movn %[qc1], %[t4], %[t0] \n\t" "movn %[qc2], %[t5], %[t1] \n\t" "movn %[qc3], %[t6], %[t2] \n\t" "movn %[qc4], %[t7], %[t3] \n\t" ".set pop \n\t" : [qc1]"+r"(qc1), [qc2]"+r"(qc2), [qc3]"+r"(qc3), [qc4]"+r"(qc4), [t0]"=&r"(t0), [t1]"=&r"(t1), [t2]"=&r"(t2), [t3]"=&r"(t3), [t4]"=&r"(t4), [t5]"=&r"(t5), [t6]"=&r"(t6), [t7]"=&r"(t7) : [in_int]"r"(in_int) : "memory" ); curidx = qc1; curidx *= 3; curidx += qc2; curidx *= 3; curidx += qc3; curidx *= 3; curidx += qc4; curidx += 40; put_bits(pb, p_bits[curidx], p_codes[curidx]); if (out || energy) { float e1,e2,e3,e4; vec = &p_vec[curidx*4]; e1 = vec[0] * IQ; e2 = vec[1] * IQ; e3 = vec[2] * IQ; e4 = vec[3] * IQ; if (out) { out[i+0] = e1; out[i+1] = e2; out[i+2] = e3; out[i+3] = e4; } if (energy) qenergy += (e1*e1 + e2*e2) + (e3*e3 + e4*e4); } } if (energy) *energy = qenergy;} static void quantize_and_encode_band_cost_UQUAD_mips(struct AACEncContext *s, PutBitContext *pb, const float *in, float *out, const float *scaled, int size, int scale_idx, int cb, const float lambda, const float uplim, int *bits, float *energy, const float ROUNDING){ const float Q34 = ff_aac_pow34sf_tab[POW_SF2_ZERO - scale_idx + SCALE_ONE_POS - SCALE_DIV_512]; const float IQ = ff_aac_pow2sf_tab [POW_SF2_ZERO + scale_idx - SCALE_ONE_POS + SCALE_DIV_512]; int i; int qc1, qc2, qc3, qc4; float qenergy = 0.0f; uint8_t *p_bits = (uint8_t *)ff_aac_spectral_bits[cb-1]; uint16_t *p_codes = (uint16_t *)ff_aac_spectral_codes[cb-1]; float *p_vec = (float *)ff_aac_codebook_vectors[cb-1]; abs_pow34_v(s->scoefs, in, size); scaled = s->scoefs; for (i = 0; i < size; i += 4) { int curidx, sign, count; int *in_int = (int *)&in[i]; uint8_t v_bits; unsigned int v_codes; int t0, t1, t2, t3, t4; const float *vec; qc1 = scaled[i ] * Q34 + ROUND_STANDARD; qc2 = scaled[i+1] * Q34 + ROUND_STANDARD; qc3 = scaled[i+2] * Q34 + ROUND_STANDARD; qc4 = scaled[i+3] * Q34 + ROUND_STANDARD; __asm__ volatile ( ".set push \n\t" ".set noreorder \n\t" "ori %[t4], $zero, 2 \n\t" "ori %[sign], $zero, 0 \n\t" "slt %[t0], %[t4], %[qc1] \n\t" "slt %[t1], %[t4], %[qc2] \n\t" "slt %[t2], %[t4], %[qc3] \n\t" "slt %[t3], %[t4], %[qc4] \n\t" "movn %[qc1], %[t4], %[t0] \n\t" "movn %[qc2], %[t4], %[t1] \n\t" "movn %[qc3], %[t4], %[t2] \n\t" "movn %[qc4], %[t4], %[t3] \n\t" "lw %[t0], 0(%[in_int]) \n\t" "lw %[t1], 4(%[in_int]) \n\t" "lw %[t2], 8(%[in_int]) \n\t" "lw %[t3], 12(%[in_int]) \n\t" "slt %[t0], %[t0], $zero \n\t" "movn %[sign], %[t0], %[qc1] \n\t" "slt %[t1], %[t1], $zero \n\t" "slt %[t2], %[t2], $zero \n\t" "slt %[t3], %[t3], $zero \n\t" "sll %[t0], %[sign], 1 \n\t" "or %[t0], %[t0], %[t1] \n\t" "movn %[sign], %[t0], %[qc2] \n\t" "slt %[t4], $zero, %[qc1] \n\t" "slt %[t1], $zero, %[qc2] \n\t" "slt %[count], $zero, %[qc3] \n\t" "sll %[t0], %[sign], 1 \n\t" "or %[t0], %[t0], %[t2] \n\t" "movn %[sign], %[t0], %[qc3] \n\t" "slt %[t2], $zero, %[qc4] \n\t" "addu %[count], %[count], %[t4] \n\t" "addu %[count], %[count], %[t1] \n\t" "sll %[t0], %[sign], 1 \n\t" "or %[t0], %[t0], %[t3] \n\t" "movn %[sign], %[t0], %[qc4] \n\t" "addu %[count], %[count], %[t2] \n\t" ".set pop \n\t" : [qc1]"+r"(qc1), [qc2]"+r"(qc2), [qc3]"+r"(qc3), [qc4]"+r"(qc4), [sign]"=&r"(sign), [count]"=&r"(count), [t0]"=&r"(t0), [t1]"=&r"(t1), [t2]"=&r"(t2), [t3]"=&r"(t3), [t4]"=&r"(t4) : [in_int]"r"(in_int) : "memory" ); curidx = qc1; curidx *= 3; curidx += qc2; curidx *= 3; curidx += qc3; curidx *= 3; curidx += qc4; v_codes = (p_codes[curidx] << count) | (sign & ((1 << count) - 1)); v_bits = p_bits[curidx] + count; put_bits(pb, v_bits, v_codes); if (out || energy) { float e1,e2,e3,e4; vec = &p_vec[curidx*4]; e1 = copysignf(vec[0] * IQ, in[i+0]); e2 = copysignf(vec[1] * IQ, in[i+1]); e3 = copysignf(vec[2] * IQ, in[i+2]); e4 = copysignf(vec[3] * IQ, in[i+3]); if (out) { out[i+0] = e1; out[i+1] = e2; out[i+2] = e3; out[i+3] = e4; } if (energy) qenergy += (e1*e1 + e2*e2) + (e3*e3 + e4*e4); } } if (energy) *energy = qenergy;} static void quantize_and_encode_band_cost_SPAIR_mips(struct AACEncContext *s, PutBitContext *pb, const float *in, float *out, const float *scaled, int size, int scale_idx, int cb, const float lambda, const float uplim, int *bits, float *energy, const float ROUNDING){ const float Q34 = ff_aac_pow34sf_tab[POW_SF2_ZERO - scale_idx + SCALE_ONE_POS - SCALE_DIV_512]; const float IQ = ff_aac_pow2sf_tab [POW_SF2_ZERO + scale_idx - SCALE_ONE_POS + SCALE_DIV_512]; int i; int qc1, qc2, qc3, qc4; float qenergy = 0.0f; uint8_t *p_bits = (uint8_t *)ff_aac_spectral_bits[cb-1]; uint16_t *p_codes = (uint16_t *)ff_aac_spectral_codes[cb-1]; float *p_vec = (float *)ff_aac_codebook_vectors[cb-1]; abs_pow34_v(s->scoefs, in, size); scaled = s->scoefs; for (i = 0; i < size; i += 4) { int curidx, curidx2; int *in_int = (int *)&in[i]; uint8_t v_bits; unsigned int v_codes; int t0, t1, t2, t3, t4, t5, t6, t7; const float *vec1, *vec2; qc1 = scaled[i ] * Q34 + ROUND_STANDARD; qc2 = scaled[i+1] * Q34 + ROUND_STANDARD; qc3 = scaled[i+2] * Q34 + ROUND_STANDARD; qc4 = scaled[i+3] * Q34 + ROUND_STANDARD; __asm__ volatile ( ".set push \n\t" ".set noreorder \n\t" "ori %[t4], $zero, 4 \n\t" "slt %[t0], %[t4], %[qc1] \n\t" "slt %[t1], %[t4], %[qc2] \n\t" "slt %[t2], %[t4], %[qc3] \n\t" "slt %[t3], %[t4], %[qc4] \n\t" "movn %[qc1], %[t4], %[t0] \n\t" "movn %[qc2], %[t4], %[t1] \n\t" "movn %[qc3], %[t4], %[t2] \n\t" "movn %[qc4], %[t4], %[t3] \n\t" "lw %[t0], 0(%[in_int]) \n\t" "lw %[t1], 4(%[in_int]) \n\t" "lw %[t2], 8(%[in_int]) \n\t" "lw %[t3], 12(%[in_int]) \n\t" "srl %[t0], %[t0], 31 \n\t" "srl %[t1], %[t1], 31 \n\t" "srl %[t2], %[t2], 31 \n\t" "srl %[t3], %[t3], 31 \n\t" "subu %[t4], $zero, %[qc1] \n\t" "subu %[t5], $zero, %[qc2] \n\t" "subu %[t6], $zero, %[qc3] \n\t" "subu %[t7], $zero, %[qc4] \n\t" "movn %[qc1], %[t4], %[t0] \n\t" "movn %[qc2], %[t5], %[t1] \n\t" "movn %[qc3], %[t6], %[t2] \n\t" "movn %[qc4], %[t7], %[t3] \n\t" ".set pop \n\t" : [qc1]"+r"(qc1), [qc2]"+r"(qc2), [qc3]"+r"(qc3), [qc4]"+r"(qc4), [t0]"=&r"(t0), [t1]"=&r"(t1), [t2]"=&r"(t2), [t3]"=&r"(t3), [t4]"=&r"(t4), [t5]"=&r"(t5), [t6]"=&r"(t6), [t7]"=&r"(t7) : [in_int]"r"(in_int) : "memory" ); curidx = 9 * qc1; curidx += qc2 + 40; curidx2 = 9 * qc3; curidx2 += qc4 + 40; v_codes = (p_codes[curidx] << p_bits[curidx2]) | (p_codes[curidx2]); v_bits = p_bits[curidx] + p_bits[curidx2]; put_bits(pb, v_bits, v_codes); if (out || energy) { float e1,e2,e3,e4; vec1 = &p_vec[curidx*2 ]; vec2 = &p_vec[curidx2*2]; e1 = vec1[0] * IQ; e2 = vec1[1] * IQ; e3 = vec2[0] * IQ; e4 = vec2[1] * IQ; if (out) { out[i+0] = e1; out[i+1] = e2; out[i+2] = e3; out[i+3] = e4; } if (energy) qenergy += (e1*e1 + e2*e2) + (e3*e3 + e4*e4); } } if (energy) *energy = qenergy;} static void quantize_and_encode_band_cost_UPAIR7_mips(struct AACEncContext *s, PutBitContext *pb, const float *in, float *out, const float *scaled, int size, int scale_idx, int cb, const float lambda, const float uplim, int *bits, float *energy, const float ROUNDING){ const float Q34 = ff_aac_pow34sf_tab[POW_SF2_ZERO - scale_idx + SCALE_ONE_POS - SCALE_DIV_512]; const float IQ = ff_aac_pow2sf_tab [POW_SF2_ZERO + scale_idx - SCALE_ONE_POS + SCALE_DIV_512]; int i; int qc1, qc2, qc3, qc4; float qenergy = 0.0f; uint8_t *p_bits = (uint8_t*) ff_aac_spectral_bits[cb-1]; uint16_t *p_codes = (uint16_t*)ff_aac_spectral_codes[cb-1]; float *p_vec = (float *)ff_aac_codebook_vectors[cb-1]; abs_pow34_v(s->scoefs, in, size); scaled = s->scoefs; for (i = 0; i < size; i += 4) { int curidx1, curidx2, sign1, count1, sign2, count2; int *in_int = (int *)&in[i]; uint8_t v_bits; unsigned int v_codes; int t0, t1, t2, t3, t4; const float *vec1, *vec2; qc1 = scaled[i ] * Q34 + ROUND_STANDARD; qc2 = scaled[i+1] * Q34 + ROUND_STANDARD; qc3 = scaled[i+2] * Q34 + ROUND_STANDARD; qc4 = scaled[i+3] * Q34 + ROUND_STANDARD; __asm__ volatile ( ".set push \n\t" ".set noreorder \n\t" "ori %[t4], $zero, 7 \n\t" "ori %[sign1], $zero, 0 \n\t" "ori %[sign2], $zero, 0 \n\t" "slt %[t0], %[t4], %[qc1] \n\t" "slt %[t1], %[t4], %[qc2] \n\t" "slt %[t2], %[t4], %[qc3] \n\t" "slt %[t3], %[t4], %[qc4] \n\t" "movn %[qc1], %[t4], %[t0] \n\t" "movn %[qc2], %[t4], %[t1] \n\t" "movn %[qc3], %[t4], %[t2] \n\t" "movn %[qc4], %[t4], %[t3] \n\t" "lw %[t0], 0(%[in_int]) \n\t" "lw %[t1], 4(%[in_int]) \n\t" "lw %[t2], 8(%[in_int]) \n\t"Lines 1–500 of 2502. Load more
/* * Copyright (c) 2012 * MIPS Technologies, Inc., California. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * Author: Stanislav Ocovaj (socovaj@mips.com) * Szabolcs Pal (sabolc@mips.com) * * AAC coefficients encoder optimized for MIPS floating-point architecture * * 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 */ /** * @file * Reference: libavcodec/aaccoder.c */ #include "libavutil/libm.h" #include <float.h> #include "libavutil/mathematics.h" #include "libavcodec/avcodec.h" #include "libavcodec/put_bits.h" #include "libavcodec/aac.h" #include "libavcodec/aacenc.h" #include "libavcodec/aactab.h" #include "libavcodec/aacenctab.h" #include "libavcodec/aacenc_utils.h" #if HAVE_INLINE_ASM #if !HAVE_MIPS32R6 && !HAVE_MIPS64R6 typedef struct BandCodingPath { int prev_idx; float cost; int run; } BandCodingPath; static const uint8_t uquad_sign_bits[81] = { 0, 1, 1, 1, 2, 2, 1, 2, 2, 1, 2, 2, 2, 3, 3, 2, 3, 3, 1, 2, 2, 2, 3, 3, 2, 3, 3, 1, 2, 2, 2, 3, 3, 2, 3, 3, 2, 3, 3, 3, 4, 4, 3, 4, 4, 2, 3, 3, 3, 4, 4, 3, 4, 4, 1, 2, 2, 2, 3, 3, 2, 3, 3, 2, 3, 3, 3, 4, 4, 3, 4, 4, 2, 3, 3, 3, 4, 4, 3, 4, 4 }; static const uint8_t upair7_sign_bits[64] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, }; static const uint8_t upair12_sign_bits[169] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }; static const uint8_t esc_sign_bits[289] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }; /** * Functions developed from template function and optimized for quantizing and encoding band */ static void quantize_and_encode_band_cost_SQUAD_mips(struct AACEncContext *s, PutBitContext *pb, const float *in, float *out, const float *scaled, int size, int scale_idx, int cb, const float lambda, const float uplim, int *bits, float *energy, const float ROUNDING) { const float Q34 = ff_aac_pow34sf_tab[POW_SF2_ZERO - scale_idx + SCALE_ONE_POS - SCALE_DIV_512]; const float IQ = ff_aac_pow2sf_tab [POW_SF2_ZERO + scale_idx - SCALE_ONE_POS + SCALE_DIV_512]; int i; int qc1, qc2, qc3, qc4; float qenergy = 0.0f; uint8_t *p_bits = (uint8_t *)ff_aac_spectral_bits[cb-1]; uint16_t *p_codes = (uint16_t *)ff_aac_spectral_codes[cb-1]; float *p_vec = (float *)ff_aac_codebook_vectors[cb-1]; abs_pow34_v(s->scoefs, in, size); scaled = s->scoefs; for (i = 0; i < size; i += 4) { int curidx; int *in_int = (int *)&in[i]; int t0, t1, t2, t3, t4, t5, t6, t7; const float *vec; qc1 = scaled[i ] * Q34 + ROUND_STANDARD; qc2 = scaled[i+1] * Q34 + ROUND_STANDARD; qc3 = scaled[i+2] * Q34 + ROUND_STANDARD; qc4 = scaled[i+3] * Q34 + ROUND_STANDARD; __asm__ volatile ( ".set push \n\t" ".set noreorder \n\t" "slt %[qc1], $zero, %[qc1] \n\t" "slt %[qc2], $zero, %[qc2] \n\t" "slt %[qc3], $zero, %[qc3] \n\t" "slt %[qc4], $zero, %[qc4] \n\t" "lw %[t0], 0(%[in_int]) \n\t" "lw %[t1], 4(%[in_int]) \n\t" "lw %[t2], 8(%[in_int]) \n\t" "lw %[t3], 12(%[in_int]) \n\t" "srl %[t0], %[t0], 31 \n\t" "srl %[t1], %[t1], 31 \n\t" "srl %[t2], %[t2], 31 \n\t" "srl %[t3], %[t3], 31 \n\t" "subu %[t4], $zero, %[qc1] \n\t" "subu %[t5], $zero, %[qc2] \n\t" "subu %[t6], $zero, %[qc3] \n\t" "subu %[t7], $zero, %[qc4] \n\t" "movn %[qc1], %[t4], %[t0] \n\t" "movn %[qc2], %[t5], %[t1] \n\t" "movn %[qc3], %[t6], %[t2] \n\t" "movn %[qc4], %[t7], %[t3] \n\t" ".set pop \n\t" : [qc1]"+r"(qc1), [qc2]"+r"(qc2), [qc3]"+r"(qc3), [qc4]"+r"(qc4), [t0]"=&r"(t0), [t1]"=&r"(t1), [t2]"=&r"(t2), [t3]"=&r"(t3), [t4]"=&r"(t4), [t5]"=&r"(t5), [t6]"=&r"(t6), [t7]"=&r"(t7) : [in_int]"r"(in_int) : "memory" ); curidx = qc1; curidx *= 3; curidx += qc2; curidx *= 3; curidx += qc3; curidx *= 3; curidx += qc4; curidx += 40; put_bits(pb, p_bits[curidx], p_codes[curidx]); if (out || energy) { float e1,e2,e3,e4; vec = &p_vec[curidx*4]; e1 = vec[0] * IQ; e2 = vec[1] * IQ; e3 = vec[2] * IQ; e4 = vec[3] * IQ; if (out) { out[i+0] = e1; out[i+1] = e2; out[i+2] = e3; out[i+3] = e4; } if (energy) qenergy += (e1*e1 + e2*e2) + (e3*e3 + e4*e4); } } if (energy) *energy = qenergy; } static void quantize_and_encode_band_cost_UQUAD_mips(struct AACEncContext *s, PutBitContext *pb, const float *in, float *out, const float *scaled, int size, int scale_idx, int cb, const float lambda, const float uplim, int *bits, float *energy, const float ROUNDING) { const float Q34 = ff_aac_pow34sf_tab[POW_SF2_ZERO - scale_idx + SCALE_ONE_POS - SCALE_DIV_512]; const float IQ = ff_aac_pow2sf_tab [POW_SF2_ZERO + scale_idx - SCALE_ONE_POS + SCALE_DIV_512]; int i; int qc1, qc2, qc3, qc4; float qenergy = 0.0f; uint8_t *p_bits = (uint8_t *)ff_aac_spectral_bits[cb-1]; uint16_t *p_codes = (uint16_t *)ff_aac_spectral_codes[cb-1]; float *p_vec = (float *)ff_aac_codebook_vectors[cb-1]; abs_pow34_v(s->scoefs, in, size); scaled = s->scoefs; for (i = 0; i < size; i += 4) { int curidx, sign, count; int *in_int = (int *)&in[i]; uint8_t v_bits; unsigned int v_codes; int t0, t1, t2, t3, t4; const float *vec; qc1 = scaled[i ] * Q34 + ROUND_STANDARD; qc2 = scaled[i+1] * Q34 + ROUND_STANDARD; qc3 = scaled[i+2] * Q34 + ROUND_STANDARD; qc4 = scaled[i+3] * Q34 + ROUND_STANDARD; __asm__ volatile ( ".set push \n\t" ".set noreorder \n\t" "ori %[t4], $zero, 2 \n\t" "ori %[sign], $zero, 0 \n\t" "slt %[t0], %[t4], %[qc1] \n\t" "slt %[t1], %[t4], %[qc2] \n\t" "slt %[t2], %[t4], %[qc3] \n\t" "slt %[t3], %[t4], %[qc4] \n\t" "movn %[qc1], %[t4], %[t0] \n\t" "movn %[qc2], %[t4], %[t1] \n\t" "movn %[qc3], %[t4], %[t2] \n\t" "movn %[qc4], %[t4], %[t3] \n\t" "lw %[t0], 0(%[in_int]) \n\t" "lw %[t1], 4(%[in_int]) \n\t" "lw %[t2], 8(%[in_int]) \n\t" "lw %[t3], 12(%[in_int]) \n\t" "slt %[t0], %[t0], $zero \n\t" "movn %[sign], %[t0], %[qc1] \n\t" "slt %[t1], %[t1], $zero \n\t" "slt %[t2], %[t2], $zero \n\t" "slt %[t3], %[t3], $zero \n\t" "sll %[t0], %[sign], 1 \n\t" "or %[t0], %[t0], %[t1] \n\t" "movn %[sign], %[t0], %[qc2] \n\t" "slt %[t4], $zero, %[qc1] \n\t" "slt %[t1], $zero, %[qc2] \n\t" "slt %[count], $zero, %[qc3] \n\t" "sll %[t0], %[sign], 1 \n\t" "or %[t0], %[t0], %[t2] \n\t" "movn %[sign], %[t0], %[qc3] \n\t" "slt %[t2], $zero, %[qc4] \n\t" "addu %[count], %[count], %[t4] \n\t" "addu %[count], %[count], %[t1] \n\t" "sll %[t0], %[sign], 1 \n\t" "or %[t0], %[t0], %[t3] \n\t" "movn %[sign], %[t0], %[qc4] \n\t" "addu %[count], %[count], %[t2] \n\t" ".set pop \n\t" : [qc1]"+r"(qc1), [qc2]"+r"(qc2), [qc3]"+r"(qc3), [qc4]"+r"(qc4), [sign]"=&r"(sign), [count]"=&r"(count), [t0]"=&r"(t0), [t1]"=&r"(t1), [t2]"=&r"(t2), [t3]"=&r"(t3), [t4]"=&r"(t4) : [in_int]"r"(in_int) : "memory" ); curidx = qc1; curidx *= 3; curidx += qc2; curidx *= 3; curidx += qc3; curidx *= 3; curidx += qc4; v_codes = (p_codes[curidx] << count) | (sign & ((1 << count) - 1)); v_bits = p_bits[curidx] + count; put_bits(pb, v_bits, v_codes); if (out || energy) { float e1,e2,e3,e4; vec = &p_vec[curidx*4]; e1 = copysignf(vec[0] * IQ, in[i+0]); e2 = copysignf(vec[1] * IQ, in[i+1]); e3 = copysignf(vec[2] * IQ, in[i+2]); e4 = copysignf(vec[3] * IQ, in[i+3]); if (out) { out[i+0] = e1; out[i+1] = e2; out[i+2] = e3; out[i+3] = e4; } if (energy) qenergy += (e1*e1 + e2*e2) + (e3*e3 + e4*e4); } } if (energy) *energy = qenergy; } static void quantize_and_encode_band_cost_SPAIR_mips(struct AACEncContext *s, PutBitContext *pb, const float *in, float *out, const float *scaled, int size, int scale_idx, int cb, const float lambda, const float uplim, int *bits, float *energy, const float ROUNDING) { const float Q34 = ff_aac_pow34sf_tab[POW_SF2_ZERO - scale_idx + SCALE_ONE_POS - SCALE_DIV_512]; const float IQ = ff_aac_pow2sf_tab [POW_SF2_ZERO + scale_idx - SCALE_ONE_POS + SCALE_DIV_512]; int i; int qc1, qc2, qc3, qc4; float qenergy = 0.0f; uint8_t *p_bits = (uint8_t *)ff_aac_spectral_bits[cb-1]; uint16_t *p_codes = (uint16_t *)ff_aac_spectral_codes[cb-1]; float *p_vec = (float *)ff_aac_codebook_vectors[cb-1]; abs_pow34_v(s->scoefs, in, size); scaled = s->scoefs; for (i = 0; i < size; i += 4) { int curidx, curidx2; int *in_int = (int *)&in[i]; uint8_t v_bits; unsigned int v_codes; int t0, t1, t2, t3, t4, t5, t6, t7; const float *vec1, *vec2; qc1 = scaled[i ] * Q34 + ROUND_STANDARD; qc2 = scaled[i+1] * Q34 + ROUND_STANDARD; qc3 = scaled[i+2] * Q34 + ROUND_STANDARD; qc4 = scaled[i+3] * Q34 + ROUND_STANDARD; __asm__ volatile ( ".set push \n\t" ".set noreorder \n\t" "ori %[t4], $zero, 4 \n\t" "slt %[t0], %[t4], %[qc1] \n\t" "slt %[t1], %[t4], %[qc2] \n\t" "slt %[t2], %[t4], %[qc3] \n\t" "slt %[t3], %[t4], %[qc4] \n\t" "movn %[qc1], %[t4], %[t0] \n\t" "movn %[qc2], %[t4], %[t1] \n\t" "movn %[qc3], %[t4], %[t2] \n\t" "movn %[qc4], %[t4], %[t3] \n\t" "lw %[t0], 0(%[in_int]) \n\t" "lw %[t1], 4(%[in_int]) \n\t" "lw %[t2], 8(%[in_int]) \n\t" "lw %[t3], 12(%[in_int]) \n\t" "srl %[t0], %[t0], 31 \n\t" "srl %[t1], %[t1], 31 \n\t" "srl %[t2], %[t2], 31 \n\t" "srl %[t3], %[t3], 31 \n\t" "subu %[t4], $zero, %[qc1] \n\t" "subu %[t5], $zero, %[qc2] \n\t" "subu %[t6], $zero, %[qc3] \n\t" "subu %[t7], $zero, %[qc4] \n\t" "movn %[qc1], %[t4], %[t0] \n\t" "movn %[qc2], %[t5], %[t1] \n\t" "movn %[qc3], %[t6], %[t2] \n\t" "movn %[qc4], %[t7], %[t3] \n\t" ".set pop \n\t" : [qc1]"+r"(qc1), [qc2]"+r"(qc2), [qc3]"+r"(qc3), [qc4]"+r"(qc4), [t0]"=&r"(t0), [t1]"=&r"(t1), [t2]"=&r"(t2), [t3]"=&r"(t3), [t4]"=&r"(t4), [t5]"=&r"(t5), [t6]"=&r"(t6), [t7]"=&r"(t7) : [in_int]"r"(in_int) : "memory" ); curidx = 9 * qc1; curidx += qc2 + 40; curidx2 = 9 * qc3; curidx2 += qc4 + 40; v_codes = (p_codes[curidx] << p_bits[curidx2]) | (p_codes[curidx2]); v_bits = p_bits[curidx] + p_bits[curidx2]; put_bits(pb, v_bits, v_codes); if (out || energy) { float e1,e2,e3,e4; vec1 = &p_vec[curidx*2 ]; vec2 = &p_vec[curidx2*2]; e1 = vec1[0] * IQ; e2 = vec1[1] * IQ; e3 = vec2[0] * IQ; e4 = vec2[1] * IQ; if (out) { out[i+0] = e1; out[i+1] = e2; out[i+2] = e3; out[i+3] = e4; } if (energy) qenergy += (e1*e1 + e2*e2) + (e3*e3 + e4*e4); } } if (energy) *energy = qenergy; } static void quantize_and_encode_band_cost_UPAIR7_mips(struct AACEncContext *s, PutBitContext *pb, const float *in, float *out, const float *scaled, int size, int scale_idx, int cb, const float lambda, const float uplim, int *bits, float *energy, const float ROUNDING) { const float Q34 = ff_aac_pow34sf_tab[POW_SF2_ZERO - scale_idx + SCALE_ONE_POS - SCALE_DIV_512]; const float IQ = ff_aac_pow2sf_tab [POW_SF2_ZERO + scale_idx - SCALE_ONE_POS + SCALE_DIV_512]; int i; int qc1, qc2, qc3, qc4; float qenergy = 0.0f; uint8_t *p_bits = (uint8_t*) ff_aac_spectral_bits[cb-1]; uint16_t *p_codes = (uint16_t*)ff_aac_spectral_codes[cb-1]; float *p_vec = (float *)ff_aac_codebook_vectors[cb-1]; abs_pow34_v(s->scoefs, in, size); scaled = s->scoefs; for (i = 0; i < size; i += 4) { int curidx1, curidx2, sign1, count1, sign2, count2; int *in_int = (int *)&in[i]; uint8_t v_bits; unsigned int v_codes; int t0, t1, t2, t3, t4; const float *vec1, *vec2; qc1 = scaled[i ] * Q34 + ROUND_STANDARD; qc2 = scaled[i+1] * Q34 + ROUND_STANDARD; qc3 = scaled[i+2] * Q34 + ROUND_STANDARD; qc4 = scaled[i+3] * Q34 + ROUND_STANDARD; __asm__ volatile ( ".set push \n\t" ".set noreorder \n\t" "ori %[t4], $zero, 7 \n\t" "ori %[sign1], $zero, 0 \n\t" "ori %[sign2], $zero, 0 \n\t" "slt %[t0], %[t4], %[qc1] \n\t" "slt %[t1], %[t4], %[qc2] \n\t" "slt %[t2], %[t4], %[qc3] \n\t" "slt %[t3], %[t4], %[qc4] \n\t" "movn %[qc1], %[t4], %[t0] \n\t" "movn %[qc2], %[t4], %[t1] \n\t" "movn %[qc3], %[t4], %[t2] \n\t" "movn %[qc4], %[t4], %[t3] \n\t" "lw %[t0], 0(%[in_int]) \n\t" "lw %[t1], 4(%[in_int]) \n\t" "lw %[t2], 8(%[in_int]) \n\t"