mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-06 07:17:30 +09:00
Import aom library
This is the reference implementation for the Alliance for Open Media's av1 video code. The commit used was 4d668d7feb1f8abd809d1bca0418570a7f142a36.
This commit is contained in:
parent
eb8cd130a8
commit
edc8d83307
989 changed files with 470949 additions and 0 deletions
73
third_party/aom/aom_dsp/add_noise.c
vendored
Normal file
73
third_party/aom/aom_dsp/add_noise.c
vendored
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "./aom_config.h"
|
||||
#include "./aom_dsp_rtcd.h"
|
||||
|
||||
#include "aom/aom_integer.h"
|
||||
#include "aom_ports/mem.h"
|
||||
|
||||
void aom_plane_add_noise_c(uint8_t *start, char *noise, char blackclamp[16],
|
||||
char whiteclamp[16], char bothclamp[16],
|
||||
unsigned int width, unsigned int height, int pitch) {
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0; i < height; ++i) {
|
||||
uint8_t *pos = start + i * pitch;
|
||||
char *ref = (char *)(noise + (rand() & 0xff)); // NOLINT
|
||||
|
||||
for (j = 0; j < width; ++j) {
|
||||
int v = pos[j];
|
||||
|
||||
v = clamp(v - blackclamp[0], 0, 255);
|
||||
v = clamp(v + bothclamp[0], 0, 255);
|
||||
v = clamp(v - whiteclamp[0], 0, 255);
|
||||
|
||||
pos[j] = v + ref[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static double gaussian(double sigma, double mu, double x) {
|
||||
return 1 / (sigma * sqrt(2.0 * 3.14159265)) *
|
||||
(exp(-(x - mu) * (x - mu) / (2 * sigma * sigma)));
|
||||
}
|
||||
|
||||
int aom_setup_noise(double sigma, int size, char *noise) {
|
||||
char char_dist[256];
|
||||
int next = 0, i, j;
|
||||
|
||||
// set up a 256 entry lookup that matches gaussian distribution
|
||||
for (i = -32; i < 32; ++i) {
|
||||
const int a_i = (int)(0.5 + 256 * gaussian(sigma, 0, i));
|
||||
if (a_i) {
|
||||
for (j = 0; j < a_i; ++j) {
|
||||
char_dist[next + j] = (char)i;
|
||||
}
|
||||
next = next + j;
|
||||
}
|
||||
}
|
||||
|
||||
// Rounding error - might mean we have less than 256.
|
||||
for (; next < 256; ++next) {
|
||||
char_dist[next] = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < size; ++i) {
|
||||
noise[i] = char_dist[rand() & 0xff]; // NOLINT
|
||||
}
|
||||
|
||||
// Returns the highest non 0 value used in distribution.
|
||||
return -char_dist[0];
|
||||
}
|
||||
44
third_party/aom/aom_dsp/ans.h
vendored
Normal file
44
third_party/aom/aom_dsp/ans.h
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#ifndef AOM_DSP_ANS_H_
|
||||
#define AOM_DSP_ANS_H_
|
||||
// Constants, types and utilities for Asymmetric Numeral Systems
|
||||
// http://arxiv.org/abs/1311.2540v2
|
||||
|
||||
#include <assert.h>
|
||||
#include "./aom_config.h"
|
||||
#include "aom/aom_integer.h"
|
||||
#include "aom_dsp/prob.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
// Use windowed ANS, size is passed in at initialization
|
||||
#define ANS_MAX_SYMBOLS 1
|
||||
#define ANS_REVERSE 1
|
||||
|
||||
typedef uint8_t AnsP8;
|
||||
#define ANS_P8_PRECISION 256u
|
||||
#define ANS_P8_SHIFT 8
|
||||
#define RANS_PROB_BITS 15
|
||||
#define RANS_PRECISION (1u << RANS_PROB_BITS)
|
||||
|
||||
// L_BASE is the ANS base state. L_BASE % PRECISION must be 0.
|
||||
#define L_BASE (1u << 17)
|
||||
#define IO_BASE 256
|
||||
// Range I = { L_BASE, L_BASE + 1, ..., L_BASE * IO_BASE - 1 }
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
#endif // AOM_DSP_ANS_H_
|
||||
214
third_party/aom/aom_dsp/ansreader.h
vendored
Normal file
214
third_party/aom/aom_dsp/ansreader.h
vendored
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#ifndef AOM_DSP_ANSREADER_H_
|
||||
#define AOM_DSP_ANSREADER_H_
|
||||
// An implementation of Asymmetric Numeral Systems
|
||||
// http://arxiv.org/abs/1311.2540v2
|
||||
// Implements decoding of:
|
||||
// * rABS (range Asymmetric Binary Systems), a boolean coder
|
||||
// * rANS (range Asymmetric Numeral Systems), a multi-symbol coder
|
||||
|
||||
#include <assert.h>
|
||||
#include "./aom_config.h"
|
||||
#include "aom/aom_integer.h"
|
||||
#include "aom_dsp/prob.h"
|
||||
#include "aom_dsp/ans.h"
|
||||
#include "aom_ports/mem_ops.h"
|
||||
#if CONFIG_ACCOUNTING
|
||||
#include "av1/decoder/accounting.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
struct AnsDecoder {
|
||||
const uint8_t *buf;
|
||||
int buf_offset;
|
||||
uint32_t state;
|
||||
#if ANS_MAX_SYMBOLS
|
||||
int symbols_left;
|
||||
int window_size;
|
||||
#endif
|
||||
#if CONFIG_ACCOUNTING
|
||||
Accounting *accounting;
|
||||
#endif
|
||||
};
|
||||
|
||||
static INLINE int ans_read_reinit(struct AnsDecoder *const ans);
|
||||
|
||||
static INLINE unsigned refill_state(struct AnsDecoder *const ans,
|
||||
unsigned state) {
|
||||
#if ANS_REVERSE
|
||||
while (state < L_BASE && ans->buf_offset < 0) {
|
||||
state = state * IO_BASE + ans->buf[ans->buf_offset++];
|
||||
}
|
||||
#else
|
||||
while (state < L_BASE && ans->buf_offset > 0) {
|
||||
state = state * IO_BASE + ans->buf[--ans->buf_offset];
|
||||
}
|
||||
#endif
|
||||
return state;
|
||||
}
|
||||
|
||||
// Decode one rABS encoded boolean where the probability of the value being zero
|
||||
// is p0.
|
||||
static INLINE int rabs_read(struct AnsDecoder *ans, AnsP8 p0) {
|
||||
#if ANS_MAX_SYMBOLS
|
||||
if (ans->symbols_left-- == 0) {
|
||||
ans_read_reinit(ans);
|
||||
ans->symbols_left--;
|
||||
}
|
||||
#endif
|
||||
unsigned state = refill_state(ans, ans->state);
|
||||
const unsigned quotient = state / ANS_P8_PRECISION;
|
||||
const unsigned remainder = state % ANS_P8_PRECISION;
|
||||
const int value = remainder >= p0;
|
||||
const unsigned qp0 = quotient * p0;
|
||||
if (value)
|
||||
state = state - qp0 - p0;
|
||||
else
|
||||
state = qp0 + remainder;
|
||||
ans->state = state;
|
||||
return value;
|
||||
}
|
||||
|
||||
// Decode one rABS encoded boolean where the probability of the value being zero
|
||||
// is one half.
|
||||
static INLINE int rabs_read_bit(struct AnsDecoder *ans) {
|
||||
#if ANS_MAX_SYMBOLS
|
||||
if (ans->symbols_left-- == 0) {
|
||||
ans_read_reinit(ans);
|
||||
ans->symbols_left--;
|
||||
}
|
||||
#endif
|
||||
unsigned state = refill_state(ans, ans->state);
|
||||
const int value = !!(state & 0x80);
|
||||
ans->state = ((state >> 1) & ~0x7F) | (state & 0x7F);
|
||||
return value;
|
||||
}
|
||||
|
||||
struct rans_dec_sym {
|
||||
uint8_t val;
|
||||
aom_cdf_prob prob;
|
||||
aom_cdf_prob cum_prob; // not-inclusive
|
||||
};
|
||||
|
||||
static INLINE void fetch_sym(struct rans_dec_sym *out, const aom_cdf_prob *cdf,
|
||||
aom_cdf_prob rem) {
|
||||
int i;
|
||||
aom_cdf_prob cum_prob = 0, top_prob;
|
||||
// TODO(skal): if critical, could be a binary search.
|
||||
// Or, better, an O(1) alias-table.
|
||||
for (i = 0; rem >= (top_prob = cdf[i]); ++i) {
|
||||
cum_prob = top_prob;
|
||||
}
|
||||
out->val = i;
|
||||
out->prob = top_prob - cum_prob;
|
||||
out->cum_prob = cum_prob;
|
||||
}
|
||||
|
||||
static INLINE int rans_read(struct AnsDecoder *ans, const aom_cdf_prob *tab) {
|
||||
unsigned rem;
|
||||
unsigned quo;
|
||||
struct rans_dec_sym sym;
|
||||
#if ANS_MAX_SYMBOLS
|
||||
if (ans->symbols_left-- == 0) {
|
||||
ans_read_reinit(ans);
|
||||
ans->symbols_left--;
|
||||
}
|
||||
#endif
|
||||
ans->state = refill_state(ans, ans->state);
|
||||
quo = ans->state / RANS_PRECISION;
|
||||
rem = ans->state % RANS_PRECISION;
|
||||
fetch_sym(&sym, tab, rem);
|
||||
ans->state = quo * sym.prob + rem - sym.cum_prob;
|
||||
return sym.val;
|
||||
}
|
||||
|
||||
static INLINE int ans_read_init(struct AnsDecoder *const ans,
|
||||
const uint8_t *const buf, int offset) {
|
||||
unsigned x;
|
||||
if (offset < 1) return 1;
|
||||
#if ANS_REVERSE
|
||||
ans->buf = buf + offset;
|
||||
ans->buf_offset = -offset;
|
||||
x = buf[0];
|
||||
if ((x & 0x80) == 0) { // Marker is 0xxx xxxx
|
||||
if (offset < 2) return 1;
|
||||
ans->buf_offset += 2;
|
||||
ans->state = mem_get_be16(buf) & 0x7FFF;
|
||||
#if L_BASE * IO_BASE > (1 << 23)
|
||||
} else if ((x & 0xC0) == 0x80) { // Marker is 10xx xxxx
|
||||
if (offset < 3) return 1;
|
||||
ans->buf_offset += 3;
|
||||
ans->state = mem_get_be24(buf) & 0x3FFFFF;
|
||||
} else { // Marker is 11xx xxxx
|
||||
if (offset < 4) return 1;
|
||||
ans->buf_offset += 4;
|
||||
ans->state = mem_get_be32(buf) & 0x3FFFFFFF;
|
||||
#else
|
||||
} else { // Marker is 1xxx xxxx
|
||||
if (offset < 3) return 1;
|
||||
ans->buf_offset += 3;
|
||||
ans->state = mem_get_be24(buf) & 0x7FFFFF;
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
ans->buf = buf;
|
||||
x = buf[offset - 1];
|
||||
if ((x & 0x80) == 0) { // Marker is 0xxx xxxx
|
||||
if (offset < 2) return 1;
|
||||
ans->buf_offset = offset - 2;
|
||||
ans->state = mem_get_le16(buf + offset - 2) & 0x7FFF;
|
||||
} else if ((x & 0xC0) == 0x80) { // Marker is 10xx xxxx
|
||||
if (offset < 3) return 1;
|
||||
ans->buf_offset = offset - 3;
|
||||
ans->state = mem_get_le24(buf + offset - 3) & 0x3FFFFF;
|
||||
} else if ((x & 0xE0) == 0xE0) { // Marker is 111x xxxx
|
||||
if (offset < 4) return 1;
|
||||
ans->buf_offset = offset - 4;
|
||||
ans->state = mem_get_le32(buf + offset - 4) & 0x1FFFFFFF;
|
||||
} else {
|
||||
// Marker 110x xxxx implies this byte is a superframe marker
|
||||
return 1;
|
||||
}
|
||||
#endif // ANS_REVERSE
|
||||
#if CONFIG_ACCOUNTING
|
||||
ans->accounting = NULL;
|
||||
#endif
|
||||
ans->state += L_BASE;
|
||||
if (ans->state >= L_BASE * IO_BASE) return 1;
|
||||
#if ANS_MAX_SYMBOLS
|
||||
assert(ans->window_size > 1);
|
||||
ans->symbols_left = ans->window_size;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if ANS_REVERSE
|
||||
static INLINE int ans_read_reinit(struct AnsDecoder *const ans) {
|
||||
return ans_read_init(ans, ans->buf + ans->buf_offset, -ans->buf_offset);
|
||||
}
|
||||
#endif
|
||||
|
||||
static INLINE int ans_read_end(const struct AnsDecoder *const ans) {
|
||||
return ans->buf_offset == 0 && ans->state < L_BASE;
|
||||
}
|
||||
|
||||
static INLINE int ans_reader_has_error(const struct AnsDecoder *const ans) {
|
||||
return ans->state < L_BASE / RANS_PRECISION;
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
#endif // AOM_DSP_ANSREADER_H_
|
||||
148
third_party/aom/aom_dsp/answriter.h
vendored
Normal file
148
third_party/aom/aom_dsp/answriter.h
vendored
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#ifndef AOM_DSP_ANSWRITER_H_
|
||||
#define AOM_DSP_ANSWRITER_H_
|
||||
// An implementation of Asymmetric Numeral Systems
|
||||
// http://arxiv.org/abs/1311.2540v2
|
||||
// Implements encoding of:
|
||||
// * rABS (range Asymmetric Binary Systems), a boolean coder
|
||||
// * rANS (range Asymmetric Numeral Systems), a multi-symbol coder
|
||||
|
||||
#include <assert.h>
|
||||
#include "./aom_config.h"
|
||||
#include "aom/aom_integer.h"
|
||||
#include "aom_dsp/ans.h"
|
||||
#include "aom_dsp/prob.h"
|
||||
#include "aom_ports/mem_ops.h"
|
||||
#include "av1/common/odintrin.h"
|
||||
|
||||
#if RANS_PRECISION <= OD_DIVU_DMAX
|
||||
#define ANS_DIVREM(quotient, remainder, dividend, divisor) \
|
||||
do { \
|
||||
quotient = OD_DIVU_SMALL((dividend), (divisor)); \
|
||||
remainder = (dividend) - (quotient) * (divisor); \
|
||||
} while (0)
|
||||
#else
|
||||
#define ANS_DIVREM(quotient, remainder, dividend, divisor) \
|
||||
do { \
|
||||
quotient = (dividend) / (divisor); \
|
||||
remainder = (dividend) % (divisor); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#define ANS_DIV8(dividend, divisor) OD_DIVU_SMALL((dividend), (divisor))
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
struct AnsCoder {
|
||||
uint8_t *buf;
|
||||
int buf_offset;
|
||||
uint32_t state;
|
||||
};
|
||||
|
||||
static INLINE void ans_write_init(struct AnsCoder *const ans,
|
||||
uint8_t *const buf) {
|
||||
ans->buf = buf;
|
||||
ans->buf_offset = 0;
|
||||
ans->state = L_BASE;
|
||||
}
|
||||
|
||||
static INLINE int ans_write_end(struct AnsCoder *const ans) {
|
||||
uint32_t state;
|
||||
int ans_size;
|
||||
assert(ans->state >= L_BASE);
|
||||
assert(ans->state < L_BASE * IO_BASE);
|
||||
state = ans->state - L_BASE;
|
||||
if (state < (1u << 15)) {
|
||||
mem_put_le16(ans->buf + ans->buf_offset, (0x00u << 15) + state);
|
||||
ans_size = ans->buf_offset + 2;
|
||||
#if ANS_REVERSE
|
||||
#if L_BASE * IO_BASE > (1 << 23)
|
||||
} else if (state < (1u << 22)) {
|
||||
mem_put_le24(ans->buf + ans->buf_offset, (0x02u << 22) + state);
|
||||
ans_size = ans->buf_offset + 3;
|
||||
} else if (state < (1u << 30)) {
|
||||
mem_put_le32(ans->buf + ans->buf_offset, (0x03u << 30) + state);
|
||||
ans_size = ans->buf_offset + 4;
|
||||
#else
|
||||
} else if (state < (1u << 23)) {
|
||||
mem_put_le24(ans->buf + ans->buf_offset, (0x01u << 23) + state);
|
||||
ans_size = ans->buf_offset + 3;
|
||||
#endif
|
||||
#else
|
||||
} else if (state < (1u << 22)) {
|
||||
mem_put_le24(ans->buf + ans->buf_offset, (0x02u << 22) + state);
|
||||
ans_size = ans->buf_offset + 3;
|
||||
} else if (state < (1u << 29)) {
|
||||
mem_put_le32(ans->buf + ans->buf_offset, (0x07u << 29) + state);
|
||||
ans_size = ans->buf_offset + 4;
|
||||
#endif
|
||||
} else {
|
||||
assert(0 && "State is too large to be serialized");
|
||||
return ans->buf_offset;
|
||||
}
|
||||
#if ANS_REVERSE
|
||||
{
|
||||
int i;
|
||||
uint8_t tmp;
|
||||
for (i = 0; i < (ans_size >> 1); i++) {
|
||||
tmp = ans->buf[i];
|
||||
ans->buf[i] = ans->buf[ans_size - 1 - i];
|
||||
ans->buf[ans_size - 1 - i] = tmp;
|
||||
}
|
||||
ans->buf += ans_size;
|
||||
ans->buf_offset = 0;
|
||||
ans->state = L_BASE;
|
||||
}
|
||||
#endif
|
||||
return ans_size;
|
||||
}
|
||||
|
||||
// Write one boolean using rABS where p0 is the probability of the value being
|
||||
// zero.
|
||||
static INLINE void rabs_write(struct AnsCoder *ans, int value, AnsP8 p0) {
|
||||
const AnsP8 p = ANS_P8_PRECISION - p0;
|
||||
const unsigned l_s = value ? p : p0;
|
||||
unsigned state = ans->state;
|
||||
while (state >= L_BASE / ANS_P8_PRECISION * IO_BASE * l_s) {
|
||||
ans->buf[ans->buf_offset++] = state % IO_BASE;
|
||||
state /= IO_BASE;
|
||||
}
|
||||
const unsigned quotient = ANS_DIV8(state, l_s);
|
||||
const unsigned remainder = state - quotient * l_s;
|
||||
ans->state = quotient * ANS_P8_PRECISION + remainder + (value ? p0 : 0);
|
||||
}
|
||||
|
||||
// Encode one symbol using rANS.
|
||||
// cum_prob: The cumulative probability before this symbol (the offset of
|
||||
// the symbol in the symbol cycle)
|
||||
// prob: The probability of this symbol (l_s from the paper)
|
||||
// RANS_PRECISION takes the place of m from the paper.
|
||||
static INLINE void rans_write(struct AnsCoder *ans, aom_cdf_prob cum_prob,
|
||||
aom_cdf_prob prob) {
|
||||
unsigned quotient, remainder;
|
||||
while (ans->state >= L_BASE / RANS_PRECISION * IO_BASE * prob) {
|
||||
ans->buf[ans->buf_offset++] = ans->state % IO_BASE;
|
||||
ans->state /= IO_BASE;
|
||||
}
|
||||
ANS_DIVREM(quotient, remainder, ans->state, prob);
|
||||
ans->state = quotient * RANS_PRECISION + remainder + cum_prob;
|
||||
}
|
||||
|
||||
#undef ANS_DIV8
|
||||
#undef ANS_DIVREM
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
#endif // AOM_DSP_ANSWRITER_H_
|
||||
854
third_party/aom/aom_dsp/aom_convolve.c
vendored
Normal file
854
third_party/aom/aom_dsp/aom_convolve.c
vendored
Normal file
|
|
@ -0,0 +1,854 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "./aom_config.h"
|
||||
#include "./aom_dsp_rtcd.h"
|
||||
#include "aom/aom_integer.h"
|
||||
#include "aom_dsp/aom_convolve.h"
|
||||
#include "aom_dsp/aom_dsp_common.h"
|
||||
#include "aom_dsp/aom_filter.h"
|
||||
#include "aom_ports/mem.h"
|
||||
|
||||
static void convolve_horiz(const uint8_t *src, ptrdiff_t src_stride,
|
||||
uint8_t *dst, ptrdiff_t dst_stride,
|
||||
const InterpKernel *x_filters, int x0_q4,
|
||||
int x_step_q4, int w, int h) {
|
||||
int x, y;
|
||||
src -= SUBPEL_TAPS / 2 - 1;
|
||||
for (y = 0; y < h; ++y) {
|
||||
int x_q4 = x0_q4;
|
||||
for (x = 0; x < w; ++x) {
|
||||
const uint8_t *const src_x = &src[x_q4 >> SUBPEL_BITS];
|
||||
const int16_t *const x_filter = x_filters[x_q4 & SUBPEL_MASK];
|
||||
int k, sum = 0;
|
||||
for (k = 0; k < SUBPEL_TAPS; ++k) sum += src_x[k] * x_filter[k];
|
||||
dst[x] = clip_pixel(ROUND_POWER_OF_TWO(sum, FILTER_BITS));
|
||||
x_q4 += x_step_q4;
|
||||
}
|
||||
src += src_stride;
|
||||
dst += dst_stride;
|
||||
}
|
||||
}
|
||||
|
||||
static void convolve_avg_horiz(const uint8_t *src, ptrdiff_t src_stride,
|
||||
uint8_t *dst, ptrdiff_t dst_stride,
|
||||
const InterpKernel *x_filters, int x0_q4,
|
||||
int x_step_q4, int w, int h) {
|
||||
int x, y;
|
||||
src -= SUBPEL_TAPS / 2 - 1;
|
||||
for (y = 0; y < h; ++y) {
|
||||
int x_q4 = x0_q4;
|
||||
for (x = 0; x < w; ++x) {
|
||||
const uint8_t *const src_x = &src[x_q4 >> SUBPEL_BITS];
|
||||
const int16_t *const x_filter = x_filters[x_q4 & SUBPEL_MASK];
|
||||
int k, sum = 0;
|
||||
for (k = 0; k < SUBPEL_TAPS; ++k) sum += src_x[k] * x_filter[k];
|
||||
dst[x] = ROUND_POWER_OF_TWO(
|
||||
dst[x] + clip_pixel(ROUND_POWER_OF_TWO(sum, FILTER_BITS)), 1);
|
||||
x_q4 += x_step_q4;
|
||||
}
|
||||
src += src_stride;
|
||||
dst += dst_stride;
|
||||
}
|
||||
}
|
||||
|
||||
static void convolve_vert(const uint8_t *src, ptrdiff_t src_stride,
|
||||
uint8_t *dst, ptrdiff_t dst_stride,
|
||||
const InterpKernel *y_filters, int y0_q4,
|
||||
int y_step_q4, int w, int h) {
|
||||
int x, y;
|
||||
src -= src_stride * (SUBPEL_TAPS / 2 - 1);
|
||||
|
||||
for (x = 0; x < w; ++x) {
|
||||
int y_q4 = y0_q4;
|
||||
for (y = 0; y < h; ++y) {
|
||||
const unsigned char *src_y = &src[(y_q4 >> SUBPEL_BITS) * src_stride];
|
||||
const int16_t *const y_filter = y_filters[y_q4 & SUBPEL_MASK];
|
||||
int k, sum = 0;
|
||||
for (k = 0; k < SUBPEL_TAPS; ++k)
|
||||
sum += src_y[k * src_stride] * y_filter[k];
|
||||
dst[y * dst_stride] = clip_pixel(ROUND_POWER_OF_TWO(sum, FILTER_BITS));
|
||||
y_q4 += y_step_q4;
|
||||
}
|
||||
++src;
|
||||
++dst;
|
||||
}
|
||||
}
|
||||
|
||||
static void convolve_avg_vert(const uint8_t *src, ptrdiff_t src_stride,
|
||||
uint8_t *dst, ptrdiff_t dst_stride,
|
||||
const InterpKernel *y_filters, int y0_q4,
|
||||
int y_step_q4, int w, int h) {
|
||||
int x, y;
|
||||
src -= src_stride * (SUBPEL_TAPS / 2 - 1);
|
||||
|
||||
for (x = 0; x < w; ++x) {
|
||||
int y_q4 = y0_q4;
|
||||
for (y = 0; y < h; ++y) {
|
||||
const unsigned char *src_y = &src[(y_q4 >> SUBPEL_BITS) * src_stride];
|
||||
const int16_t *const y_filter = y_filters[y_q4 & SUBPEL_MASK];
|
||||
int k, sum = 0;
|
||||
for (k = 0; k < SUBPEL_TAPS; ++k)
|
||||
sum += src_y[k * src_stride] * y_filter[k];
|
||||
dst[y * dst_stride] = ROUND_POWER_OF_TWO(
|
||||
dst[y * dst_stride] +
|
||||
clip_pixel(ROUND_POWER_OF_TWO(sum, FILTER_BITS)),
|
||||
1);
|
||||
y_q4 += y_step_q4;
|
||||
}
|
||||
++src;
|
||||
++dst;
|
||||
}
|
||||
}
|
||||
|
||||
static void convolve(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst,
|
||||
ptrdiff_t dst_stride, const InterpKernel *const x_filters,
|
||||
int x0_q4, int x_step_q4,
|
||||
const InterpKernel *const y_filters, int y0_q4,
|
||||
int y_step_q4, int w, int h) {
|
||||
// Note: Fixed size intermediate buffer, temp, places limits on parameters.
|
||||
// 2d filtering proceeds in 2 steps:
|
||||
// (1) Interpolate horizontally into an intermediate buffer, temp.
|
||||
// (2) Interpolate temp vertically to derive the sub-pixel result.
|
||||
// Deriving the maximum number of rows in the temp buffer (135):
|
||||
// --Smallest scaling factor is x1/2 ==> y_step_q4 = 32 (Normative).
|
||||
// --Largest block size is 64x64 pixels.
|
||||
// --64 rows in the downscaled frame span a distance of (64 - 1) * 32 in the
|
||||
// original frame (in 1/16th pixel units).
|
||||
// --Must round-up because block may be located at sub-pixel position.
|
||||
// --Require an additional SUBPEL_TAPS rows for the 8-tap filter tails.
|
||||
// --((64 - 1) * 32 + 15) >> 4 + 8 = 135.
|
||||
uint8_t temp[MAX_EXT_SIZE * MAX_SB_SIZE];
|
||||
int intermediate_height =
|
||||
(((h - 1) * y_step_q4 + y0_q4) >> SUBPEL_BITS) + SUBPEL_TAPS;
|
||||
|
||||
assert(w <= MAX_SB_SIZE);
|
||||
assert(h <= MAX_SB_SIZE);
|
||||
|
||||
assert(y_step_q4 <= 32);
|
||||
assert(x_step_q4 <= 32);
|
||||
|
||||
convolve_horiz(src - src_stride * (SUBPEL_TAPS / 2 - 1), src_stride, temp,
|
||||
MAX_SB_SIZE, x_filters, x0_q4, x_step_q4, w,
|
||||
intermediate_height);
|
||||
convolve_vert(temp + MAX_SB_SIZE * (SUBPEL_TAPS / 2 - 1), MAX_SB_SIZE, dst,
|
||||
dst_stride, y_filters, y0_q4, y_step_q4, w, h);
|
||||
}
|
||||
|
||||
static const InterpKernel *get_filter_base(const int16_t *filter) {
|
||||
// NOTE: This assumes that the filter table is 256-byte aligned.
|
||||
// TODO(agrange) Modify to make independent of table alignment.
|
||||
return (const InterpKernel *)(((intptr_t)filter) & ~((intptr_t)0xFF));
|
||||
}
|
||||
|
||||
static int get_filter_offset(const int16_t *f, const InterpKernel *base) {
|
||||
return (int)((const InterpKernel *)(intptr_t)f - base);
|
||||
}
|
||||
|
||||
void aom_convolve8_horiz_c(const uint8_t *src, ptrdiff_t src_stride,
|
||||
uint8_t *dst, ptrdiff_t dst_stride,
|
||||
const int16_t *filter_x, int x_step_q4,
|
||||
const int16_t *filter_y, int y_step_q4, int w,
|
||||
int h) {
|
||||
const InterpKernel *const filters_x = get_filter_base(filter_x);
|
||||
const int x0_q4 = get_filter_offset(filter_x, filters_x);
|
||||
|
||||
(void)filter_y;
|
||||
(void)y_step_q4;
|
||||
|
||||
convolve_horiz(src, src_stride, dst, dst_stride, filters_x, x0_q4, x_step_q4,
|
||||
w, h);
|
||||
}
|
||||
|
||||
void aom_convolve8_avg_horiz_c(const uint8_t *src, ptrdiff_t src_stride,
|
||||
uint8_t *dst, ptrdiff_t dst_stride,
|
||||
const int16_t *filter_x, int x_step_q4,
|
||||
const int16_t *filter_y, int y_step_q4, int w,
|
||||
int h) {
|
||||
const InterpKernel *const filters_x = get_filter_base(filter_x);
|
||||
const int x0_q4 = get_filter_offset(filter_x, filters_x);
|
||||
|
||||
(void)filter_y;
|
||||
(void)y_step_q4;
|
||||
|
||||
convolve_avg_horiz(src, src_stride, dst, dst_stride, filters_x, x0_q4,
|
||||
x_step_q4, w, h);
|
||||
}
|
||||
|
||||
void aom_convolve8_vert_c(const uint8_t *src, ptrdiff_t src_stride,
|
||||
uint8_t *dst, ptrdiff_t dst_stride,
|
||||
const int16_t *filter_x, int x_step_q4,
|
||||
const int16_t *filter_y, int y_step_q4, int w,
|
||||
int h) {
|
||||
const InterpKernel *const filters_y = get_filter_base(filter_y);
|
||||
const int y0_q4 = get_filter_offset(filter_y, filters_y);
|
||||
|
||||
(void)filter_x;
|
||||
(void)x_step_q4;
|
||||
|
||||
convolve_vert(src, src_stride, dst, dst_stride, filters_y, y0_q4, y_step_q4,
|
||||
w, h);
|
||||
}
|
||||
|
||||
void aom_convolve8_avg_vert_c(const uint8_t *src, ptrdiff_t src_stride,
|
||||
uint8_t *dst, ptrdiff_t dst_stride,
|
||||
const int16_t *filter_x, int x_step_q4,
|
||||
const int16_t *filter_y, int y_step_q4, int w,
|
||||
int h) {
|
||||
const InterpKernel *const filters_y = get_filter_base(filter_y);
|
||||
const int y0_q4 = get_filter_offset(filter_y, filters_y);
|
||||
|
||||
(void)filter_x;
|
||||
(void)x_step_q4;
|
||||
|
||||
convolve_avg_vert(src, src_stride, dst, dst_stride, filters_y, y0_q4,
|
||||
y_step_q4, w, h);
|
||||
}
|
||||
|
||||
void aom_convolve8_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst,
|
||||
ptrdiff_t dst_stride, const int16_t *filter_x,
|
||||
int x_step_q4, const int16_t *filter_y, int y_step_q4,
|
||||
int w, int h) {
|
||||
const InterpKernel *const filters_x = get_filter_base(filter_x);
|
||||
const int x0_q4 = get_filter_offset(filter_x, filters_x);
|
||||
|
||||
const InterpKernel *const filters_y = get_filter_base(filter_y);
|
||||
const int y0_q4 = get_filter_offset(filter_y, filters_y);
|
||||
|
||||
convolve(src, src_stride, dst, dst_stride, filters_x, x0_q4, x_step_q4,
|
||||
filters_y, y0_q4, y_step_q4, w, h);
|
||||
}
|
||||
|
||||
void aom_convolve8_avg_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst,
|
||||
ptrdiff_t dst_stride, const int16_t *filter_x,
|
||||
int x_step_q4, const int16_t *filter_y, int y_step_q4,
|
||||
int w, int h) {
|
||||
/* Fixed size intermediate buffer places limits on parameters. */
|
||||
DECLARE_ALIGNED(16, uint8_t, temp[MAX_SB_SIZE * MAX_SB_SIZE]);
|
||||
assert(w <= MAX_SB_SIZE);
|
||||
assert(h <= MAX_SB_SIZE);
|
||||
|
||||
aom_convolve8_c(src, src_stride, temp, MAX_SB_SIZE, filter_x, x_step_q4,
|
||||
filter_y, y_step_q4, w, h);
|
||||
aom_convolve_avg_c(temp, MAX_SB_SIZE, dst, dst_stride, NULL, 0, NULL, 0, w,
|
||||
h);
|
||||
}
|
||||
|
||||
void aom_convolve_copy_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst,
|
||||
ptrdiff_t dst_stride, const int16_t *filter_x,
|
||||
int filter_x_stride, const int16_t *filter_y,
|
||||
int filter_y_stride, int w, int h) {
|
||||
int r;
|
||||
|
||||
(void)filter_x;
|
||||
(void)filter_x_stride;
|
||||
(void)filter_y;
|
||||
(void)filter_y_stride;
|
||||
|
||||
for (r = h; r > 0; --r) {
|
||||
memcpy(dst, src, w);
|
||||
src += src_stride;
|
||||
dst += dst_stride;
|
||||
}
|
||||
}
|
||||
|
||||
void aom_convolve_avg_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst,
|
||||
ptrdiff_t dst_stride, const int16_t *filter_x,
|
||||
int filter_x_stride, const int16_t *filter_y,
|
||||
int filter_y_stride, int w, int h) {
|
||||
int x, y;
|
||||
|
||||
(void)filter_x;
|
||||
(void)filter_x_stride;
|
||||
(void)filter_y;
|
||||
(void)filter_y_stride;
|
||||
|
||||
for (y = 0; y < h; ++y) {
|
||||
for (x = 0; x < w; ++x) dst[x] = ROUND_POWER_OF_TWO(dst[x] + src[x], 1);
|
||||
|
||||
src += src_stride;
|
||||
dst += dst_stride;
|
||||
}
|
||||
}
|
||||
|
||||
void aom_scaled_horiz_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst,
|
||||
ptrdiff_t dst_stride, const int16_t *filter_x,
|
||||
int x_step_q4, const int16_t *filter_y, int y_step_q4,
|
||||
int w, int h) {
|
||||
aom_convolve8_horiz_c(src, src_stride, dst, dst_stride, filter_x, x_step_q4,
|
||||
filter_y, y_step_q4, w, h);
|
||||
}
|
||||
|
||||
void aom_scaled_vert_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst,
|
||||
ptrdiff_t dst_stride, const int16_t *filter_x,
|
||||
int x_step_q4, const int16_t *filter_y, int y_step_q4,
|
||||
int w, int h) {
|
||||
aom_convolve8_vert_c(src, src_stride, dst, dst_stride, filter_x, x_step_q4,
|
||||
filter_y, y_step_q4, w, h);
|
||||
}
|
||||
|
||||
void aom_scaled_2d_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst,
|
||||
ptrdiff_t dst_stride, const int16_t *filter_x,
|
||||
int x_step_q4, const int16_t *filter_y, int y_step_q4,
|
||||
int w, int h) {
|
||||
aom_convolve8_c(src, src_stride, dst, dst_stride, filter_x, x_step_q4,
|
||||
filter_y, y_step_q4, w, h);
|
||||
}
|
||||
|
||||
void aom_scaled_avg_horiz_c(const uint8_t *src, ptrdiff_t src_stride,
|
||||
uint8_t *dst, ptrdiff_t dst_stride,
|
||||
const int16_t *filter_x, int x_step_q4,
|
||||
const int16_t *filter_y, int y_step_q4, int w,
|
||||
int h) {
|
||||
aom_convolve8_avg_horiz_c(src, src_stride, dst, dst_stride, filter_x,
|
||||
x_step_q4, filter_y, y_step_q4, w, h);
|
||||
}
|
||||
|
||||
void aom_scaled_avg_vert_c(const uint8_t *src, ptrdiff_t src_stride,
|
||||
uint8_t *dst, ptrdiff_t dst_stride,
|
||||
const int16_t *filter_x, int x_step_q4,
|
||||
const int16_t *filter_y, int y_step_q4, int w,
|
||||
int h) {
|
||||
aom_convolve8_avg_vert_c(src, src_stride, dst, dst_stride, filter_x,
|
||||
x_step_q4, filter_y, y_step_q4, w, h);
|
||||
}
|
||||
|
||||
void aom_scaled_avg_2d_c(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst,
|
||||
ptrdiff_t dst_stride, const int16_t *filter_x,
|
||||
int x_step_q4, const int16_t *filter_y, int y_step_q4,
|
||||
int w, int h) {
|
||||
aom_convolve8_avg_c(src, src_stride, dst, dst_stride, filter_x, x_step_q4,
|
||||
filter_y, y_step_q4, w, h);
|
||||
}
|
||||
|
||||
#if CONFIG_LOOP_RESTORATION
|
||||
static void convolve_add_src_horiz(const uint8_t *src, ptrdiff_t src_stride,
|
||||
uint8_t *dst, ptrdiff_t dst_stride,
|
||||
const InterpKernel *x_filters, int x0_q4,
|
||||
int x_step_q4, int w, int h) {
|
||||
int x, y;
|
||||
src -= SUBPEL_TAPS / 2 - 1;
|
||||
for (y = 0; y < h; ++y) {
|
||||
int x_q4 = x0_q4;
|
||||
for (x = 0; x < w; ++x) {
|
||||
const uint8_t *const src_x = &src[x_q4 >> SUBPEL_BITS];
|
||||
const int16_t *const x_filter = x_filters[x_q4 & SUBPEL_MASK];
|
||||
int k, sum = 0;
|
||||
for (k = 0; k < SUBPEL_TAPS; ++k) sum += src_x[k] * x_filter[k];
|
||||
dst[x] = clip_pixel(ROUND_POWER_OF_TWO(sum, FILTER_BITS) +
|
||||
src_x[SUBPEL_TAPS / 2 - 1]);
|
||||
x_q4 += x_step_q4;
|
||||
}
|
||||
src += src_stride;
|
||||
dst += dst_stride;
|
||||
}
|
||||
}
|
||||
|
||||
static void convolve_add_src_vert(const uint8_t *src, ptrdiff_t src_stride,
|
||||
uint8_t *dst, ptrdiff_t dst_stride,
|
||||
const InterpKernel *y_filters, int y0_q4,
|
||||
int y_step_q4, int w, int h) {
|
||||
int x, y;
|
||||
src -= src_stride * (SUBPEL_TAPS / 2 - 1);
|
||||
|
||||
for (x = 0; x < w; ++x) {
|
||||
int y_q4 = y0_q4;
|
||||
for (y = 0; y < h; ++y) {
|
||||
const unsigned char *src_y = &src[(y_q4 >> SUBPEL_BITS) * src_stride];
|
||||
const int16_t *const y_filter = y_filters[y_q4 & SUBPEL_MASK];
|
||||
int k, sum = 0;
|
||||
for (k = 0; k < SUBPEL_TAPS; ++k)
|
||||
sum += src_y[k * src_stride] * y_filter[k];
|
||||
dst[y * dst_stride] =
|
||||
clip_pixel(ROUND_POWER_OF_TWO(sum, FILTER_BITS) +
|
||||
src_y[(SUBPEL_TAPS / 2 - 1) * src_stride]);
|
||||
y_q4 += y_step_q4;
|
||||
}
|
||||
++src;
|
||||
++dst;
|
||||
}
|
||||
}
|
||||
|
||||
static void convolve_add_src(const uint8_t *src, ptrdiff_t src_stride,
|
||||
uint8_t *dst, ptrdiff_t dst_stride,
|
||||
const InterpKernel *const x_filters, int x0_q4,
|
||||
int x_step_q4, const InterpKernel *const y_filters,
|
||||
int y0_q4, int y_step_q4, int w, int h) {
|
||||
uint8_t temp[MAX_EXT_SIZE * MAX_SB_SIZE];
|
||||
int intermediate_height =
|
||||
(((h - 1) * y_step_q4 + y0_q4) >> SUBPEL_BITS) + SUBPEL_TAPS;
|
||||
|
||||
assert(w <= MAX_SB_SIZE);
|
||||
assert(h <= MAX_SB_SIZE);
|
||||
|
||||
assert(y_step_q4 <= 32);
|
||||
assert(x_step_q4 <= 32);
|
||||
|
||||
convolve_add_src_horiz(src - src_stride * (SUBPEL_TAPS / 2 - 1), src_stride,
|
||||
temp, MAX_SB_SIZE, x_filters, x0_q4, x_step_q4, w,
|
||||
intermediate_height);
|
||||
convolve_add_src_vert(temp + MAX_SB_SIZE * (SUBPEL_TAPS / 2 - 1), MAX_SB_SIZE,
|
||||
dst, dst_stride, y_filters, y0_q4, y_step_q4, w, h);
|
||||
}
|
||||
|
||||
void aom_convolve8_add_src_horiz_c(const uint8_t *src, ptrdiff_t src_stride,
|
||||
uint8_t *dst, ptrdiff_t dst_stride,
|
||||
const int16_t *filter_x, int x_step_q4,
|
||||
const int16_t *filter_y, int y_step_q4,
|
||||
int w, int h) {
|
||||
const InterpKernel *const filters_x = get_filter_base(filter_x);
|
||||
const int x0_q4 = get_filter_offset(filter_x, filters_x);
|
||||
|
||||
(void)filter_y;
|
||||
(void)y_step_q4;
|
||||
|
||||
convolve_add_src_horiz(src, src_stride, dst, dst_stride, filters_x, x0_q4,
|
||||
x_step_q4, w, h);
|
||||
}
|
||||
|
||||
void aom_convolve8_add_src_vert_c(const uint8_t *src, ptrdiff_t src_stride,
|
||||
uint8_t *dst, ptrdiff_t dst_stride,
|
||||
const int16_t *filter_x, int x_step_q4,
|
||||
const int16_t *filter_y, int y_step_q4, int w,
|
||||
int h) {
|
||||
const InterpKernel *const filters_y = get_filter_base(filter_y);
|
||||
const int y0_q4 = get_filter_offset(filter_y, filters_y);
|
||||
|
||||
(void)filter_x;
|
||||
(void)x_step_q4;
|
||||
|
||||
convolve_add_src_vert(src, src_stride, dst, dst_stride, filters_y, y0_q4,
|
||||
y_step_q4, w, h);
|
||||
}
|
||||
|
||||
void aom_convolve8_add_src_c(const uint8_t *src, ptrdiff_t src_stride,
|
||||
uint8_t *dst, ptrdiff_t dst_stride,
|
||||
const int16_t *filter_x, int x_step_q4,
|
||||
const int16_t *filter_y, int y_step_q4, int w,
|
||||
int h) {
|
||||
const InterpKernel *const filters_x = get_filter_base(filter_x);
|
||||
const int x0_q4 = get_filter_offset(filter_x, filters_x);
|
||||
|
||||
const InterpKernel *const filters_y = get_filter_base(filter_y);
|
||||
const int y0_q4 = get_filter_offset(filter_y, filters_y);
|
||||
|
||||
convolve_add_src(src, src_stride, dst, dst_stride, filters_x, x0_q4,
|
||||
x_step_q4, filters_y, y0_q4, y_step_q4, w, h);
|
||||
}
|
||||
#endif // CONFIG_LOOP_RESTORATION
|
||||
|
||||
#if CONFIG_HIGHBITDEPTH
|
||||
static void highbd_convolve_horiz(const uint8_t *src8, ptrdiff_t src_stride,
|
||||
uint8_t *dst8, ptrdiff_t dst_stride,
|
||||
const InterpKernel *x_filters, int x0_q4,
|
||||
int x_step_q4, int w, int h, int bd) {
|
||||
int x, y;
|
||||
uint16_t *src = CONVERT_TO_SHORTPTR(src8);
|
||||
uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
|
||||
src -= SUBPEL_TAPS / 2 - 1;
|
||||
for (y = 0; y < h; ++y) {
|
||||
int x_q4 = x0_q4;
|
||||
for (x = 0; x < w; ++x) {
|
||||
const uint16_t *const src_x = &src[x_q4 >> SUBPEL_BITS];
|
||||
const int16_t *const x_filter = x_filters[x_q4 & SUBPEL_MASK];
|
||||
int k, sum = 0;
|
||||
for (k = 0; k < SUBPEL_TAPS; ++k) sum += src_x[k] * x_filter[k];
|
||||
dst[x] = clip_pixel_highbd(ROUND_POWER_OF_TWO(sum, FILTER_BITS), bd);
|
||||
x_q4 += x_step_q4;
|
||||
}
|
||||
src += src_stride;
|
||||
dst += dst_stride;
|
||||
}
|
||||
}
|
||||
|
||||
static void highbd_convolve_avg_horiz(const uint8_t *src8, ptrdiff_t src_stride,
|
||||
uint8_t *dst8, ptrdiff_t dst_stride,
|
||||
const InterpKernel *x_filters, int x0_q4,
|
||||
int x_step_q4, int w, int h, int bd) {
|
||||
int x, y;
|
||||
uint16_t *src = CONVERT_TO_SHORTPTR(src8);
|
||||
uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
|
||||
src -= SUBPEL_TAPS / 2 - 1;
|
||||
for (y = 0; y < h; ++y) {
|
||||
int x_q4 = x0_q4;
|
||||
for (x = 0; x < w; ++x) {
|
||||
const uint16_t *const src_x = &src[x_q4 >> SUBPEL_BITS];
|
||||
const int16_t *const x_filter = x_filters[x_q4 & SUBPEL_MASK];
|
||||
int k, sum = 0;
|
||||
for (k = 0; k < SUBPEL_TAPS; ++k) sum += src_x[k] * x_filter[k];
|
||||
dst[x] = ROUND_POWER_OF_TWO(
|
||||
dst[x] + clip_pixel_highbd(ROUND_POWER_OF_TWO(sum, FILTER_BITS), bd),
|
||||
1);
|
||||
x_q4 += x_step_q4;
|
||||
}
|
||||
src += src_stride;
|
||||
dst += dst_stride;
|
||||
}
|
||||
}
|
||||
|
||||
static void highbd_convolve_vert(const uint8_t *src8, ptrdiff_t src_stride,
|
||||
uint8_t *dst8, ptrdiff_t dst_stride,
|
||||
const InterpKernel *y_filters, int y0_q4,
|
||||
int y_step_q4, int w, int h, int bd) {
|
||||
int x, y;
|
||||
uint16_t *src = CONVERT_TO_SHORTPTR(src8);
|
||||
uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
|
||||
src -= src_stride * (SUBPEL_TAPS / 2 - 1);
|
||||
for (x = 0; x < w; ++x) {
|
||||
int y_q4 = y0_q4;
|
||||
for (y = 0; y < h; ++y) {
|
||||
const uint16_t *src_y = &src[(y_q4 >> SUBPEL_BITS) * src_stride];
|
||||
const int16_t *const y_filter = y_filters[y_q4 & SUBPEL_MASK];
|
||||
int k, sum = 0;
|
||||
for (k = 0; k < SUBPEL_TAPS; ++k)
|
||||
sum += src_y[k * src_stride] * y_filter[k];
|
||||
dst[y * dst_stride] =
|
||||
clip_pixel_highbd(ROUND_POWER_OF_TWO(sum, FILTER_BITS), bd);
|
||||
y_q4 += y_step_q4;
|
||||
}
|
||||
++src;
|
||||
++dst;
|
||||
}
|
||||
}
|
||||
|
||||
static void highbd_convolve_avg_vert(const uint8_t *src8, ptrdiff_t src_stride,
|
||||
uint8_t *dst8, ptrdiff_t dst_stride,
|
||||
const InterpKernel *y_filters, int y0_q4,
|
||||
int y_step_q4, int w, int h, int bd) {
|
||||
int x, y;
|
||||
uint16_t *src = CONVERT_TO_SHORTPTR(src8);
|
||||
uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
|
||||
src -= src_stride * (SUBPEL_TAPS / 2 - 1);
|
||||
for (x = 0; x < w; ++x) {
|
||||
int y_q4 = y0_q4;
|
||||
for (y = 0; y < h; ++y) {
|
||||
const uint16_t *src_y = &src[(y_q4 >> SUBPEL_BITS) * src_stride];
|
||||
const int16_t *const y_filter = y_filters[y_q4 & SUBPEL_MASK];
|
||||
int k, sum = 0;
|
||||
for (k = 0; k < SUBPEL_TAPS; ++k)
|
||||
sum += src_y[k * src_stride] * y_filter[k];
|
||||
dst[y * dst_stride] = ROUND_POWER_OF_TWO(
|
||||
dst[y * dst_stride] +
|
||||
clip_pixel_highbd(ROUND_POWER_OF_TWO(sum, FILTER_BITS), bd),
|
||||
1);
|
||||
y_q4 += y_step_q4;
|
||||
}
|
||||
++src;
|
||||
++dst;
|
||||
}
|
||||
}
|
||||
|
||||
static void highbd_convolve(const uint8_t *src, ptrdiff_t src_stride,
|
||||
uint8_t *dst, ptrdiff_t dst_stride,
|
||||
const InterpKernel *const x_filters, int x0_q4,
|
||||
int x_step_q4, const InterpKernel *const y_filters,
|
||||
int y0_q4, int y_step_q4, int w, int h, int bd) {
|
||||
// Note: Fixed size intermediate buffer, temp, places limits on parameters.
|
||||
// 2d filtering proceeds in 2 steps:
|
||||
// (1) Interpolate horizontally into an intermediate buffer, temp.
|
||||
// (2) Interpolate temp vertically to derive the sub-pixel result.
|
||||
// Deriving the maximum number of rows in the temp buffer (135):
|
||||
// --Smallest scaling factor is x1/2 ==> y_step_q4 = 32 (Normative).
|
||||
// --Largest block size is 64x64 pixels.
|
||||
// --64 rows in the downscaled frame span a distance of (64 - 1) * 32 in the
|
||||
// original frame (in 1/16th pixel units).
|
||||
// --Must round-up because block may be located at sub-pixel position.
|
||||
// --Require an additional SUBPEL_TAPS rows for the 8-tap filter tails.
|
||||
// --((64 - 1) * 32 + 15) >> 4 + 8 = 135.
|
||||
uint16_t temp[MAX_EXT_SIZE * MAX_SB_SIZE];
|
||||
int intermediate_height =
|
||||
(((h - 1) * y_step_q4 + y0_q4) >> SUBPEL_BITS) + SUBPEL_TAPS;
|
||||
|
||||
assert(w <= MAX_SB_SIZE);
|
||||
assert(h <= MAX_SB_SIZE);
|
||||
assert(y_step_q4 <= 32);
|
||||
assert(x_step_q4 <= 32);
|
||||
|
||||
highbd_convolve_horiz(src - src_stride * (SUBPEL_TAPS / 2 - 1), src_stride,
|
||||
CONVERT_TO_BYTEPTR(temp), MAX_SB_SIZE, x_filters, x0_q4,
|
||||
x_step_q4, w, intermediate_height, bd);
|
||||
highbd_convolve_vert(
|
||||
CONVERT_TO_BYTEPTR(temp) + MAX_SB_SIZE * (SUBPEL_TAPS / 2 - 1),
|
||||
MAX_SB_SIZE, dst, dst_stride, y_filters, y0_q4, y_step_q4, w, h, bd);
|
||||
}
|
||||
|
||||
void aom_highbd_convolve8_horiz_c(const uint8_t *src, ptrdiff_t src_stride,
|
||||
uint8_t *dst, ptrdiff_t dst_stride,
|
||||
const int16_t *filter_x, int x_step_q4,
|
||||
const int16_t *filter_y, int y_step_q4, int w,
|
||||
int h, int bd) {
|
||||
const InterpKernel *const filters_x = get_filter_base(filter_x);
|
||||
const int x0_q4 = get_filter_offset(filter_x, filters_x);
|
||||
(void)filter_y;
|
||||
(void)y_step_q4;
|
||||
|
||||
highbd_convolve_horiz(src, src_stride, dst, dst_stride, filters_x, x0_q4,
|
||||
x_step_q4, w, h, bd);
|
||||
}
|
||||
|
||||
void aom_highbd_convolve8_avg_horiz_c(const uint8_t *src, ptrdiff_t src_stride,
|
||||
uint8_t *dst, ptrdiff_t dst_stride,
|
||||
const int16_t *filter_x, int x_step_q4,
|
||||
const int16_t *filter_y, int y_step_q4,
|
||||
int w, int h, int bd) {
|
||||
const InterpKernel *const filters_x = get_filter_base(filter_x);
|
||||
const int x0_q4 = get_filter_offset(filter_x, filters_x);
|
||||
(void)filter_y;
|
||||
(void)y_step_q4;
|
||||
|
||||
highbd_convolve_avg_horiz(src, src_stride, dst, dst_stride, filters_x, x0_q4,
|
||||
x_step_q4, w, h, bd);
|
||||
}
|
||||
|
||||
void aom_highbd_convolve8_vert_c(const uint8_t *src, ptrdiff_t src_stride,
|
||||
uint8_t *dst, ptrdiff_t dst_stride,
|
||||
const int16_t *filter_x, int x_step_q4,
|
||||
const int16_t *filter_y, int y_step_q4, int w,
|
||||
int h, int bd) {
|
||||
const InterpKernel *const filters_y = get_filter_base(filter_y);
|
||||
const int y0_q4 = get_filter_offset(filter_y, filters_y);
|
||||
(void)filter_x;
|
||||
(void)x_step_q4;
|
||||
|
||||
highbd_convolve_vert(src, src_stride, dst, dst_stride, filters_y, y0_q4,
|
||||
y_step_q4, w, h, bd);
|
||||
}
|
||||
|
||||
void aom_highbd_convolve8_avg_vert_c(const uint8_t *src, ptrdiff_t src_stride,
|
||||
uint8_t *dst, ptrdiff_t dst_stride,
|
||||
const int16_t *filter_x, int x_step_q4,
|
||||
const int16_t *filter_y, int y_step_q4,
|
||||
int w, int h, int bd) {
|
||||
const InterpKernel *const filters_y = get_filter_base(filter_y);
|
||||
const int y0_q4 = get_filter_offset(filter_y, filters_y);
|
||||
(void)filter_x;
|
||||
(void)x_step_q4;
|
||||
|
||||
highbd_convolve_avg_vert(src, src_stride, dst, dst_stride, filters_y, y0_q4,
|
||||
y_step_q4, w, h, bd);
|
||||
}
|
||||
|
||||
void aom_highbd_convolve8_c(const uint8_t *src, ptrdiff_t src_stride,
|
||||
uint8_t *dst, ptrdiff_t dst_stride,
|
||||
const int16_t *filter_x, int x_step_q4,
|
||||
const int16_t *filter_y, int y_step_q4, int w,
|
||||
int h, int bd) {
|
||||
const InterpKernel *const filters_x = get_filter_base(filter_x);
|
||||
const int x0_q4 = get_filter_offset(filter_x, filters_x);
|
||||
|
||||
const InterpKernel *const filters_y = get_filter_base(filter_y);
|
||||
const int y0_q4 = get_filter_offset(filter_y, filters_y);
|
||||
|
||||
highbd_convolve(src, src_stride, dst, dst_stride, filters_x, x0_q4, x_step_q4,
|
||||
filters_y, y0_q4, y_step_q4, w, h, bd);
|
||||
}
|
||||
|
||||
void aom_highbd_convolve8_avg_c(const uint8_t *src, ptrdiff_t src_stride,
|
||||
uint8_t *dst, ptrdiff_t dst_stride,
|
||||
const int16_t *filter_x, int x_step_q4,
|
||||
const int16_t *filter_y, int y_step_q4, int w,
|
||||
int h, int bd) {
|
||||
// Fixed size intermediate buffer places limits on parameters.
|
||||
DECLARE_ALIGNED(16, uint16_t, temp[MAX_SB_SIZE * MAX_SB_SIZE]);
|
||||
assert(w <= MAX_SB_SIZE);
|
||||
assert(h <= MAX_SB_SIZE);
|
||||
|
||||
aom_highbd_convolve8_c(src, src_stride, CONVERT_TO_BYTEPTR(temp), MAX_SB_SIZE,
|
||||
filter_x, x_step_q4, filter_y, y_step_q4, w, h, bd);
|
||||
aom_highbd_convolve_avg_c(CONVERT_TO_BYTEPTR(temp), MAX_SB_SIZE, dst,
|
||||
dst_stride, NULL, 0, NULL, 0, w, h, bd);
|
||||
}
|
||||
|
||||
void aom_highbd_convolve_copy_c(const uint8_t *src8, ptrdiff_t src_stride,
|
||||
uint8_t *dst8, ptrdiff_t dst_stride,
|
||||
const int16_t *filter_x, int filter_x_stride,
|
||||
const int16_t *filter_y, int filter_y_stride,
|
||||
int w, int h, int bd) {
|
||||
int r;
|
||||
uint16_t *src = CONVERT_TO_SHORTPTR(src8);
|
||||
uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
|
||||
(void)filter_x;
|
||||
(void)filter_y;
|
||||
(void)filter_x_stride;
|
||||
(void)filter_y_stride;
|
||||
(void)bd;
|
||||
|
||||
for (r = h; r > 0; --r) {
|
||||
memcpy(dst, src, w * sizeof(uint16_t));
|
||||
src += src_stride;
|
||||
dst += dst_stride;
|
||||
}
|
||||
}
|
||||
|
||||
void aom_highbd_convolve_avg_c(const uint8_t *src8, ptrdiff_t src_stride,
|
||||
uint8_t *dst8, ptrdiff_t dst_stride,
|
||||
const int16_t *filter_x, int filter_x_stride,
|
||||
const int16_t *filter_y, int filter_y_stride,
|
||||
int w, int h, int bd) {
|
||||
int x, y;
|
||||
uint16_t *src = CONVERT_TO_SHORTPTR(src8);
|
||||
uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
|
||||
(void)filter_x;
|
||||
(void)filter_y;
|
||||
(void)filter_x_stride;
|
||||
(void)filter_y_stride;
|
||||
(void)bd;
|
||||
|
||||
for (y = 0; y < h; ++y) {
|
||||
for (x = 0; x < w; ++x) {
|
||||
dst[x] = ROUND_POWER_OF_TWO(dst[x] + src[x], 1);
|
||||
}
|
||||
src += src_stride;
|
||||
dst += dst_stride;
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_LOOP_RESTORATION
|
||||
static void highbd_convolve_add_src_horiz(const uint8_t *src8,
|
||||
ptrdiff_t src_stride, uint8_t *dst8,
|
||||
ptrdiff_t dst_stride,
|
||||
const InterpKernel *x_filters,
|
||||
int x0_q4, int x_step_q4, int w,
|
||||
int h, int bd) {
|
||||
int x, y;
|
||||
uint16_t *src = CONVERT_TO_SHORTPTR(src8);
|
||||
uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
|
||||
src -= SUBPEL_TAPS / 2 - 1;
|
||||
for (y = 0; y < h; ++y) {
|
||||
int x_q4 = x0_q4;
|
||||
for (x = 0; x < w; ++x) {
|
||||
const uint16_t *const src_x = &src[x_q4 >> SUBPEL_BITS];
|
||||
const int16_t *const x_filter = x_filters[x_q4 & SUBPEL_MASK];
|
||||
int k, sum = 0;
|
||||
for (k = 0; k < SUBPEL_TAPS; ++k) sum += src_x[k] * x_filter[k];
|
||||
dst[x] = clip_pixel_highbd(
|
||||
ROUND_POWER_OF_TWO(sum, FILTER_BITS) + src_x[SUBPEL_TAPS / 2 - 1],
|
||||
bd);
|
||||
x_q4 += x_step_q4;
|
||||
}
|
||||
src += src_stride;
|
||||
dst += dst_stride;
|
||||
}
|
||||
}
|
||||
|
||||
static void highbd_convolve_add_src_vert(const uint8_t *src8,
|
||||
ptrdiff_t src_stride, uint8_t *dst8,
|
||||
ptrdiff_t dst_stride,
|
||||
const InterpKernel *y_filters,
|
||||
int y0_q4, int y_step_q4, int w, int h,
|
||||
int bd) {
|
||||
int x, y;
|
||||
uint16_t *src = CONVERT_TO_SHORTPTR(src8);
|
||||
uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
|
||||
src -= src_stride * (SUBPEL_TAPS / 2 - 1);
|
||||
for (x = 0; x < w; ++x) {
|
||||
int y_q4 = y0_q4;
|
||||
for (y = 0; y < h; ++y) {
|
||||
const uint16_t *src_y = &src[(y_q4 >> SUBPEL_BITS) * src_stride];
|
||||
const int16_t *const y_filter = y_filters[y_q4 & SUBPEL_MASK];
|
||||
int k, sum = 0;
|
||||
for (k = 0; k < SUBPEL_TAPS; ++k)
|
||||
sum += src_y[k * src_stride] * y_filter[k];
|
||||
dst[y * dst_stride] =
|
||||
clip_pixel_highbd(ROUND_POWER_OF_TWO(sum, FILTER_BITS) +
|
||||
src_y[(SUBPEL_TAPS / 2 - 1) * src_stride],
|
||||
bd);
|
||||
y_q4 += y_step_q4;
|
||||
}
|
||||
++src;
|
||||
++dst;
|
||||
}
|
||||
}
|
||||
|
||||
static void highbd_convolve_add_src(const uint8_t *src, ptrdiff_t src_stride,
|
||||
uint8_t *dst, ptrdiff_t dst_stride,
|
||||
const InterpKernel *const x_filters,
|
||||
int x0_q4, int x_step_q4,
|
||||
const InterpKernel *const y_filters,
|
||||
int y0_q4, int y_step_q4, int w, int h,
|
||||
int bd) {
|
||||
// Note: Fixed size intermediate buffer, temp, places limits on parameters.
|
||||
// 2d filtering proceeds in 2 steps:
|
||||
// (1) Interpolate horizontally into an intermediate buffer, temp.
|
||||
// (2) Interpolate temp vertically to derive the sub-pixel result.
|
||||
// Deriving the maximum number of rows in the temp buffer (135):
|
||||
// --Smallest scaling factor is x1/2 ==> y_step_q4 = 32 (Normative).
|
||||
// --Largest block size is 64x64 pixels.
|
||||
// --64 rows in the downscaled frame span a distance of (64 - 1) * 32 in the
|
||||
// original frame (in 1/16th pixel units).
|
||||
// --Must round-up because block may be located at sub-pixel position.
|
||||
// --Require an additional SUBPEL_TAPS rows for the 8-tap filter tails.
|
||||
// --((64 - 1) * 32 + 15) >> 4 + 8 = 135.
|
||||
uint16_t temp[MAX_EXT_SIZE * MAX_SB_SIZE];
|
||||
int intermediate_height =
|
||||
(((h - 1) * y_step_q4 + y0_q4) >> SUBPEL_BITS) + SUBPEL_TAPS;
|
||||
|
||||
assert(w <= MAX_SB_SIZE);
|
||||
assert(h <= MAX_SB_SIZE);
|
||||
assert(y_step_q4 <= 32);
|
||||
assert(x_step_q4 <= 32);
|
||||
|
||||
highbd_convolve_add_src_horiz(src - src_stride * (SUBPEL_TAPS / 2 - 1),
|
||||
src_stride, CONVERT_TO_BYTEPTR(temp),
|
||||
MAX_SB_SIZE, x_filters, x0_q4, x_step_q4, w,
|
||||
intermediate_height, bd);
|
||||
highbd_convolve_add_src_vert(
|
||||
CONVERT_TO_BYTEPTR(temp) + MAX_SB_SIZE * (SUBPEL_TAPS / 2 - 1),
|
||||
MAX_SB_SIZE, dst, dst_stride, y_filters, y0_q4, y_step_q4, w, h, bd);
|
||||
}
|
||||
|
||||
void aom_highbd_convolve8_add_src_horiz_c(
|
||||
const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst,
|
||||
ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4,
|
||||
const int16_t *filter_y, int y_step_q4, int w, int h, int bd) {
|
||||
const InterpKernel *const filters_x = get_filter_base(filter_x);
|
||||
const int x0_q4 = get_filter_offset(filter_x, filters_x);
|
||||
(void)filter_y;
|
||||
(void)y_step_q4;
|
||||
|
||||
highbd_convolve_add_src_horiz(src, src_stride, dst, dst_stride, filters_x,
|
||||
x0_q4, x_step_q4, w, h, bd);
|
||||
}
|
||||
|
||||
void aom_highbd_convolve8_add_src_vert_c(const uint8_t *src,
|
||||
ptrdiff_t src_stride, uint8_t *dst,
|
||||
ptrdiff_t dst_stride,
|
||||
const int16_t *filter_x, int x_step_q4,
|
||||
const int16_t *filter_y, int y_step_q4,
|
||||
int w, int h, int bd) {
|
||||
const InterpKernel *const filters_y = get_filter_base(filter_y);
|
||||
const int y0_q4 = get_filter_offset(filter_y, filters_y);
|
||||
(void)filter_x;
|
||||
(void)x_step_q4;
|
||||
|
||||
highbd_convolve_add_src_vert(src, src_stride, dst, dst_stride, filters_y,
|
||||
y0_q4, y_step_q4, w, h, bd);
|
||||
}
|
||||
|
||||
void aom_highbd_convolve8_add_src_c(const uint8_t *src, ptrdiff_t src_stride,
|
||||
uint8_t *dst, ptrdiff_t dst_stride,
|
||||
const int16_t *filter_x, int x_step_q4,
|
||||
const int16_t *filter_y, int y_step_q4,
|
||||
int w, int h, int bd) {
|
||||
const InterpKernel *const filters_x = get_filter_base(filter_x);
|
||||
const int x0_q4 = get_filter_offset(filter_x, filters_x);
|
||||
|
||||
const InterpKernel *const filters_y = get_filter_base(filter_y);
|
||||
const int y0_q4 = get_filter_offset(filter_y, filters_y);
|
||||
|
||||
highbd_convolve_add_src(src, src_stride, dst, dst_stride, filters_x, x0_q4,
|
||||
x_step_q4, filters_y, y0_q4, y_step_q4, w, h, bd);
|
||||
}
|
||||
#endif // CONFIG_LOOP_RESTORATION
|
||||
#endif // CONFIG_HIGHBITDEPTH
|
||||
57
third_party/aom/aom_dsp/aom_convolve.h
vendored
Normal file
57
third_party/aom/aom_dsp/aom_convolve.h
vendored
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
#ifndef AOM_DSP_AOM_CONVOLVE_H_
|
||||
#define AOM_DSP_AOM_CONVOLVE_H_
|
||||
|
||||
#include "./aom_config.h"
|
||||
#include "aom/aom_integer.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Note: Fixed size intermediate buffers, place limits on parameters
|
||||
// of some functions. 2d filtering proceeds in 2 steps:
|
||||
// (1) Interpolate horizontally into an intermediate buffer, temp.
|
||||
// (2) Interpolate temp vertically to derive the sub-pixel result.
|
||||
// Deriving the maximum number of rows in the temp buffer (135):
|
||||
// --Smallest scaling factor is x1/2 ==> y_step_q4 = 32 (Normative).
|
||||
// --Largest block size is 64x64 pixels.
|
||||
// --64 rows in the downscaled frame span a distance of (64 - 1) * 32 in the
|
||||
// original frame (in 1/16th pixel units).
|
||||
// --Must round-up because block may be located at sub-pixel position.
|
||||
// --Require an additional SUBPEL_TAPS rows for the 8-tap filter tails.
|
||||
// --((64 - 1) * 32 + 15) >> 4 + 8 = 135.
|
||||
#if CONFIG_AV1 && CONFIG_EXT_PARTITION
|
||||
#define MAX_EXT_SIZE 263
|
||||
#else
|
||||
#define MAX_EXT_SIZE 135
|
||||
#endif // CONFIG_AV1 && CONFIG_EXT_PARTITION
|
||||
|
||||
typedef void (*convolve_fn_t)(const uint8_t *src, ptrdiff_t src_stride,
|
||||
uint8_t *dst, ptrdiff_t dst_stride,
|
||||
const int16_t *filter_x, int x_step_q4,
|
||||
const int16_t *filter_y, int y_step_q4, int w,
|
||||
int h);
|
||||
|
||||
#if CONFIG_HIGHBITDEPTH
|
||||
typedef void (*highbd_convolve_fn_t)(const uint8_t *src, ptrdiff_t src_stride,
|
||||
uint8_t *dst, ptrdiff_t dst_stride,
|
||||
const int16_t *filter_x, int x_step_q4,
|
||||
const int16_t *filter_y, int y_step_q4,
|
||||
int w, int h, int bd);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // AOM_DSP_AOM_CONVOLVE_H_
|
||||
509
third_party/aom/aom_dsp/aom_dsp.cmake
vendored
Normal file
509
third_party/aom/aom_dsp/aom_dsp.cmake
vendored
Normal file
|
|
@ -0,0 +1,509 @@
|
|||
##
|
||||
## Copyright (c) 2017, Alliance for Open Media. All rights reserved
|
||||
##
|
||||
## This source code is subject to the terms of the BSD 2 Clause License and
|
||||
## the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
## was not distributed with this source code in the LICENSE file, you can
|
||||
## obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
## Media Patent License 1.0 was not distributed with this source code in the
|
||||
## PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
##
|
||||
set(AOM_DSP_COMMON_SOURCES
|
||||
"${AOM_ROOT}/aom_dsp/aom_convolve.c"
|
||||
"${AOM_ROOT}/aom_dsp/aom_convolve.h"
|
||||
"${AOM_ROOT}/aom_dsp/aom_dsp_common.h"
|
||||
"${AOM_ROOT}/aom_dsp/aom_filter.h"
|
||||
"${AOM_ROOT}/aom_dsp/aom_simd.h"
|
||||
"${AOM_ROOT}/aom_dsp/aom_simd_inline.h"
|
||||
"${AOM_ROOT}/aom_dsp/blend.h"
|
||||
"${AOM_ROOT}/aom_dsp/blend_a64_hmask.c"
|
||||
"${AOM_ROOT}/aom_dsp/blend_a64_mask.c"
|
||||
"${AOM_ROOT}/aom_dsp/blend_a64_vmask.c"
|
||||
"${AOM_ROOT}/aom_dsp/intrapred.c"
|
||||
"${AOM_ROOT}/aom_dsp/loopfilter.c"
|
||||
"${AOM_ROOT}/aom_dsp/prob.c"
|
||||
"${AOM_ROOT}/aom_dsp/prob.h"
|
||||
"${AOM_ROOT}/aom_dsp/sad.c"
|
||||
"${AOM_ROOT}/aom_dsp/simd/v128_intrinsics.h"
|
||||
"${AOM_ROOT}/aom_dsp/simd/v128_intrinsics_c.h"
|
||||
"${AOM_ROOT}/aom_dsp/simd/v256_intrinsics.h"
|
||||
"${AOM_ROOT}/aom_dsp/simd/v256_intrinsics_c.h"
|
||||
"${AOM_ROOT}/aom_dsp/simd/v64_intrinsics.h"
|
||||
"${AOM_ROOT}/aom_dsp/simd/v64_intrinsics_c.h"
|
||||
"${AOM_ROOT}/aom_dsp/subtract.c"
|
||||
"${AOM_ROOT}/aom_dsp/txfm_common.h"
|
||||
"${AOM_ROOT}/aom_dsp/x86/txfm_common_intrin.h")
|
||||
|
||||
set(AOM_DSP_COMMON_ASM_SSE2
|
||||
"${AOM_ROOT}/aom_dsp/x86/aom_convolve_copy_sse2.asm"
|
||||
"${AOM_ROOT}/aom_dsp/x86/aom_subpixel_8t_sse2.asm"
|
||||
"${AOM_ROOT}/aom_dsp/x86/aom_subpixel_bilinear_sse2.asm"
|
||||
"${AOM_ROOT}/aom_dsp/x86/intrapred_sse2.asm")
|
||||
|
||||
set(AOM_DSP_COMMON_INTRIN_SSE2
|
||||
"${AOM_ROOT}/aom_dsp/x86/aom_asm_stubs.c"
|
||||
"${AOM_ROOT}/aom_dsp/x86/convolve.h"
|
||||
"${AOM_ROOT}/aom_dsp/x86/txfm_common_sse2.h"
|
||||
"${AOM_ROOT}/aom_dsp/x86/loopfilter_sse2.c")
|
||||
|
||||
set(AOM_DSP_COMMON_ASM_SSSE3
|
||||
"${AOM_ROOT}/aom_dsp/x86/aom_subpixel_8t_ssse3.asm"
|
||||
"${AOM_ROOT}/aom_dsp/x86/aom_subpixel_bilinear_ssse3.asm"
|
||||
"${AOM_ROOT}/aom_dsp/x86/intrapred_ssse3.asm")
|
||||
|
||||
set(AOM_DSP_COMMON_INTRIN_SSSE3
|
||||
"${AOM_ROOT}/aom_dsp/x86/aom_subpixel_8t_intrin_ssse3.c"
|
||||
"${AOM_ROOT}/aom_dsp/x86/inv_txfm_ssse3.c")
|
||||
|
||||
set(AOM_DSP_COMMON_INTRIN_SSE4_1
|
||||
"${AOM_ROOT}/aom_dsp/x86/blend_a64_hmask_sse4.c"
|
||||
"${AOM_ROOT}/aom_dsp/x86/blend_a64_mask_sse4.c"
|
||||
"${AOM_ROOT}/aom_dsp/x86/blend_a64_vmask_sse4.c")
|
||||
|
||||
set(AOM_DSP_COMMON_INTRIN_AVX2
|
||||
"${AOM_ROOT}/aom_dsp/x86/aom_subpixel_8t_intrin_avx2.c"
|
||||
"${AOM_ROOT}/aom_dsp/x86/fwd_txfm_avx2.c"
|
||||
"${AOM_ROOT}/aom_dsp/x86/loopfilter_avx2.c")
|
||||
|
||||
set(AOM_DSP_COMMON_ASM_NEON
|
||||
"${AOM_ROOT}/aom_dsp/arm/aom_convolve8_avg_neon_asm.asm"
|
||||
"${AOM_ROOT}/aom_dsp/arm/aom_convolve8_neon_asm.asm"
|
||||
"${AOM_ROOT}/aom_dsp/arm/aom_convolve_avg_neon_asm.asm"
|
||||
"${AOM_ROOT}/aom_dsp/arm/aom_convolve_copy_neon_asm.asm"
|
||||
"${AOM_ROOT}/aom_dsp/arm/idct16x16_1_add_neon.asm"
|
||||
"${AOM_ROOT}/aom_dsp/arm/idct16x16_add_neon.asm"
|
||||
"${AOM_ROOT}/aom_dsp/arm/idct32x32_1_add_neon.asm"
|
||||
"${AOM_ROOT}/aom_dsp/arm/idct32x32_add_neon.asm"
|
||||
"${AOM_ROOT}/aom_dsp/arm/idct4x4_1_add_neon.asm"
|
||||
"${AOM_ROOT}/aom_dsp/arm/idct4x4_add_neon.asm"
|
||||
"${AOM_ROOT}/aom_dsp/arm/idct8x8_1_add_neon.asm"
|
||||
"${AOM_ROOT}/aom_dsp/arm/idct8x8_add_neon.asm"
|
||||
"${AOM_ROOT}/aom_dsp/arm/intrapred_neon_asm.asm"
|
||||
"${AOM_ROOT}/aom_dsp/arm/loopfilter_16_neon.asm"
|
||||
"${AOM_ROOT}/aom_dsp/arm/loopfilter_4_neon.asm"
|
||||
"${AOM_ROOT}/aom_dsp/arm/loopfilter_8_neon.asm"
|
||||
"${AOM_ROOT}/aom_dsp/arm/loopfilter_mb_neon.asm"
|
||||
"${AOM_ROOT}/aom_dsp/arm/save_reg_neon.asm")
|
||||
|
||||
set(AOM_DSP_COMMON_INTRIN_NEON
|
||||
"${AOM_ROOT}/aom_dsp/arm/aom_convolve_neon.c"
|
||||
"${AOM_ROOT}/aom_dsp/arm/avg_neon.c"
|
||||
"${AOM_ROOT}/aom_dsp/arm/fwd_txfm_neon.c"
|
||||
"${AOM_ROOT}/aom_dsp/arm/hadamard_neon.c"
|
||||
"${AOM_ROOT}/aom_dsp/arm/idct16x16_neon.c"
|
||||
"${AOM_ROOT}/aom_dsp/arm/intrapred_neon.c"
|
||||
"${AOM_ROOT}/aom_dsp/arm/loopfilter_neon.c"
|
||||
"${AOM_ROOT}/aom_dsp/arm/sad4d_neon.c"
|
||||
"${AOM_ROOT}/aom_dsp/arm/sad_neon.c"
|
||||
"${AOM_ROOT}/aom_dsp/arm/subpel_variance_neon.c"
|
||||
"${AOM_ROOT}/aom_dsp/arm/subtract_neon.c"
|
||||
"${AOM_ROOT}/aom_dsp/arm/variance_neon.c")
|
||||
|
||||
if ("${AOM_TARGET_CPU}" STREQUAL "arm64")
|
||||
set(AOM_DSP_COMMON_INTRIN_NEON
|
||||
${AOM_DSP_COMMON_INTRIN_NEON}
|
||||
"${AOM_ROOT}/aom_dsp/arm/aom_convolve8_avg_neon.c"
|
||||
"${AOM_ROOT}/aom_dsp/arm/aom_convolve8_neon.c"
|
||||
"${AOM_ROOT}/aom_dsp/arm/aom_convolve_avg_neon.c"
|
||||
"${AOM_ROOT}/aom_dsp/arm/aom_convolve_copy_neon.c"
|
||||
"${AOM_ROOT}/aom_dsp/arm/idct16x16_1_add_neon.c"
|
||||
"${AOM_ROOT}/aom_dsp/arm/idct16x16_add_neon.c"
|
||||
"${AOM_ROOT}/aom_dsp/arm/idct32x32_1_add_neon.c"
|
||||
"${AOM_ROOT}/aom_dsp/arm/idct32x32_add_neon.c"
|
||||
"${AOM_ROOT}/aom_dsp/arm/idct4x4_1_add_neon.c"
|
||||
"${AOM_ROOT}/aom_dsp/arm/idct4x4_add_neon.c"
|
||||
"${AOM_ROOT}/aom_dsp/arm/idct8x8_1_add_neon.c"
|
||||
"${AOM_ROOT}/aom_dsp/arm/idct8x8_add_neon.c"
|
||||
"${AOM_ROOT}/aom_dsp/arm/intrapred_neon.c"
|
||||
"${AOM_ROOT}/aom_dsp/arm/loopfilter_16_neon.c"
|
||||
"${AOM_ROOT}/aom_dsp/arm/loopfilter_4_neon.c"
|
||||
"${AOM_ROOT}/aom_dsp/arm/loopfilter_8_neon.c")
|
||||
endif ()
|
||||
|
||||
set(AOM_DSP_COMMON_INTRIN_DSPR2
|
||||
"${AOM_ROOT}/aom_dsp/mips/common_dspr2.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/common_dspr2.h"
|
||||
"${AOM_ROOT}/aom_dsp/mips/convolve2_avg_dspr2.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/convolve2_avg_horiz_dspr2.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/convolve2_dspr2.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/convolve2_horiz_dspr2.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/convolve2_vert_dspr2.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/convolve8_avg_dspr2.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/convolve8_avg_horiz_dspr2.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/convolve8_dspr2.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/convolve8_horiz_dspr2.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/convolve8_vert_dspr2.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/convolve_common_dspr2.h"
|
||||
"${AOM_ROOT}/aom_dsp/mips/intrapred16_dspr2.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/intrapred4_dspr2.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/intrapred8_dspr2.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/inv_txfm_dspr2.h"
|
||||
"${AOM_ROOT}/aom_dsp/mips/loopfilter_filters_dspr2.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/loopfilter_filters_dspr2.h"
|
||||
"${AOM_ROOT}/aom_dsp/mips/loopfilter_macros_dspr2.h"
|
||||
"${AOM_ROOT}/aom_dsp/mips/loopfilter_masks_dspr2.h"
|
||||
"${AOM_ROOT}/aom_dsp/mips/loopfilter_mb_dspr2.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/loopfilter_mb_horiz_dspr2.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/loopfilter_mb_vert_dspr2.c")
|
||||
|
||||
set(AOM_DSP_COMMON_INTRIN_MSA
|
||||
"${AOM_ROOT}/aom_dsp/mips/aom_convolve8_avg_horiz_msa.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/aom_convolve8_avg_msa.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/aom_convolve8_avg_vert_msa.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/aom_convolve8_horiz_msa.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/aom_convolve8_msa.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/aom_convolve8_vert_msa.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/aom_convolve_avg_msa.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/aom_convolve_copy_msa.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/aom_convolve_msa.h"
|
||||
"${AOM_ROOT}/aom_dsp/mips/fwd_dct32x32_msa.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/fwd_txfm_msa.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/fwd_txfm_msa.h"
|
||||
"${AOM_ROOT}/aom_dsp/mips/idct16x16_msa.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/idct32x32_msa.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/idct4x4_msa.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/idct8x8_msa.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/intrapred_msa.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/inv_txfm_msa.h"
|
||||
"${AOM_ROOT}/aom_dsp/mips/loopfilter_16_msa.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/loopfilter_4_msa.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/loopfilter_8_msa.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/loopfilter_msa.h"
|
||||
"${AOM_ROOT}/aom_dsp/mips/macros_msa.h"
|
||||
"${AOM_ROOT}/aom_dsp/mips/txfm_macros_msa.h")
|
||||
|
||||
if (CONFIG_HIGHBITDEPTH)
|
||||
set(AOM_DSP_COMMON_ASM_SSE2
|
||||
${AOM_DSP_COMMON_ASM_SSE2}
|
||||
"${AOM_ROOT}/aom_dsp/x86/highbd_intrapred_sse2.asm")
|
||||
|
||||
set(AOM_DSP_COMMON_INTRIN_SSE2
|
||||
${AOM_DSP_COMMON_INTRIN_SSE2}
|
||||
"${AOM_ROOT}/aom_dsp/x86/highbd_loopfilter_sse2.c")
|
||||
|
||||
set(AOM_DSP_COMMON_INTRIN_AVX2
|
||||
${AOM_DSP_COMMON_INTRIN_AVX2}
|
||||
"${AOM_ROOT}/aom_dsp/x86/highbd_convolve_avx2.c")
|
||||
else ()
|
||||
set(AOM_DSP_COMMON_INTRIN_DSPR2
|
||||
${AOM_DSP_COMMON_INTRIN_DSPR2}
|
||||
"${AOM_ROOT}/aom_dsp/mips/itrans16_dspr2.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/itrans32_cols_dspr2.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/itrans32_dspr2.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/itrans4_dspr2.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/itrans8_dspr2.c")
|
||||
endif ()
|
||||
|
||||
if (CONFIG_ANS)
|
||||
set(AOM_DSP_COMMON_SOURCES
|
||||
${AOM_DSP_COMMON_SOURCES}
|
||||
"${AOM_ROOT}/aom_dsp/ans.h")
|
||||
elseif (CONFIG_DAALA_EC)
|
||||
set(AOM_DSP_COMMON_SOURCES
|
||||
${AOM_DSP_COMMON_SOURCES}
|
||||
"${AOM_ROOT}/aom_dsp/entcode.c"
|
||||
"${AOM_ROOT}/aom_dsp/entcode.h")
|
||||
endif ()
|
||||
|
||||
if (CONFIG_AV1)
|
||||
set(AOM_DSP_COMMON_SOURCES
|
||||
${AOM_DSP_COMMON_SOURCES}
|
||||
"${AOM_ROOT}/aom_dsp/inv_txfm.c"
|
||||
"${AOM_ROOT}/aom_dsp/inv_txfm.h")
|
||||
|
||||
set(AOM_DSP_COMMON_ASM_SSE2
|
||||
${AOM_DSP_COMMON_ASM_SSE2}
|
||||
"${AOM_ROOT}/aom_dsp/x86/inv_wht_sse2.asm")
|
||||
|
||||
set(AOM_DSP_COMMON_INTRIN_SSE2
|
||||
${AOM_DSP_COMMON_INTRIN_SSE2}
|
||||
"${AOM_ROOT}/aom_dsp/x86/inv_txfm_sse2.c"
|
||||
"${AOM_ROOT}/aom_dsp/x86/inv_txfm_sse2.h")
|
||||
endif ()
|
||||
|
||||
if (CONFIG_DECODERS)
|
||||
set(AOM_DSP_DECODER_SOURCES
|
||||
"${AOM_ROOT}/aom_dsp/binary_codes_reader.c"
|
||||
"${AOM_ROOT}/aom_dsp/binary_codes_reader.h"
|
||||
"${AOM_ROOT}/aom_dsp/bitreader.h"
|
||||
"${AOM_ROOT}/aom_dsp/bitreader_buffer.c"
|
||||
"${AOM_ROOT}/aom_dsp/bitreader_buffer.h")
|
||||
|
||||
if (CONFIG_ANS)
|
||||
set(AOM_DSP_DECODER_SOURCES
|
||||
${AOM_DSP_DECODER_SOURCES}
|
||||
"${AOM_ROOT}/aom_dsp/ansreader.h")
|
||||
elseif (CONFIG_DAALA_EC)
|
||||
set(AOM_DSP_DECODER_SOURCES
|
||||
${AOM_DSP_DECODER_SOURCES}
|
||||
"${AOM_ROOT}/aom_dsp/daalaboolreader.c"
|
||||
"${AOM_ROOT}/aom_dsp/daalaboolreader.h"
|
||||
"${AOM_ROOT}/aom_dsp/entdec.c"
|
||||
"${AOM_ROOT}/aom_dsp/entdec.h")
|
||||
else ()
|
||||
set(AOM_DSP_DECODER_SOURCES
|
||||
${AOM_DSP_DECODER_SOURCES}
|
||||
"${AOM_ROOT}/aom_dsp/dkboolreader.c"
|
||||
"${AOM_ROOT}/aom_dsp/dkboolreader.h")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (CONFIG_ENCODERS)
|
||||
set(AOM_DSP_ENCODER_SOURCES
|
||||
"${AOM_ROOT}/aom_dsp/binary_codes_writer.c"
|
||||
"${AOM_ROOT}/aom_dsp/binary_codes_writer.h"
|
||||
"${AOM_ROOT}/aom_dsp/bitwriter.h"
|
||||
"${AOM_ROOT}/aom_dsp/bitwriter_buffer.c"
|
||||
"${AOM_ROOT}/aom_dsp/bitwriter_buffer.h"
|
||||
"${AOM_ROOT}/aom_dsp/psnr.c"
|
||||
"${AOM_ROOT}/aom_dsp/psnr.h"
|
||||
"${AOM_ROOT}/aom_dsp/variance.c"
|
||||
"${AOM_ROOT}/aom_dsp/variance.h")
|
||||
|
||||
set(AOM_DSP_ENCODER_ASM_SSE2
|
||||
${AOM_DSP_ENCODER_ASM_SSE2}
|
||||
"${AOM_ROOT}/aom_dsp/x86/halfpix_variance_impl_sse2.asm"
|
||||
"${AOM_ROOT}/aom_dsp/x86/sad4d_sse2.asm"
|
||||
"${AOM_ROOT}/aom_dsp/x86/sad_sse2.asm"
|
||||
"${AOM_ROOT}/aom_dsp/x86/subtract_sse2.asm"
|
||||
"${AOM_ROOT}/aom_dsp/x86/subpel_variance_sse2.asm")
|
||||
|
||||
set(AOM_DSP_ENCODER_INTRIN_SSE2
|
||||
"${AOM_ROOT}/aom_dsp/x86/quantize_sse2.c")
|
||||
|
||||
set(AOM_DSP_ENCODER_ASM_SSSE3
|
||||
"${AOM_ROOT}/aom_dsp/x86/sad_ssse3.asm")
|
||||
|
||||
set(AOM_DSP_ENCODER_ASM_SSSE3_X86_64
|
||||
"${AOM_ROOT}/aom_dsp/x86/fwd_txfm_ssse3_x86_64.asm"
|
||||
"${AOM_ROOT}/aom_dsp/x86/ssim_opt_x86_64.asm")
|
||||
|
||||
set(AOM_DSP_ENCODER_INTRIN_SSE3 "${AOM_ROOT}/aom_dsp/x86/sad_sse3.asm")
|
||||
set(AOM_DSP_ENCODER_ASM_SSE4_1 "${AOM_ROOT}/aom_dsp/x86/sad_sse4.asm")
|
||||
|
||||
set(AOM_DSP_ENCODER_INTRIN_AVX2
|
||||
"${AOM_ROOT}/aom_dsp/x86/sad4d_avx2.c"
|
||||
"${AOM_ROOT}/aom_dsp/x86/sad_avx2.c"
|
||||
"${AOM_ROOT}/aom_dsp/x86/sad_impl_avx2.c"
|
||||
"${AOM_ROOT}/aom_dsp/x86/variance_avx2.c"
|
||||
"${AOM_ROOT}/aom_dsp/x86/variance_impl_avx2.c")
|
||||
|
||||
if (CONFIG_AV1_ENCODER)
|
||||
set(AOM_DSP_ENCODER_SOURCES
|
||||
${AOM_DSP_ENCODER_SOURCES}
|
||||
"${AOM_ROOT}/aom_dsp/avg.c"
|
||||
"${AOM_ROOT}/aom_dsp/fwd_txfm.c"
|
||||
"${AOM_ROOT}/aom_dsp/fwd_txfm.h"
|
||||
"${AOM_ROOT}/aom_dsp/quantize.c"
|
||||
"${AOM_ROOT}/aom_dsp/quantize.h"
|
||||
"${AOM_ROOT}/aom_dsp/sum_squares.c")
|
||||
|
||||
set(AOM_DSP_ENCODER_INTRIN_SSE2
|
||||
${AOM_DSP_ENCODER_INTRIN_SSE2}
|
||||
"${AOM_ROOT}/aom_dsp/x86/avg_intrin_sse2.c"
|
||||
"${AOM_ROOT}/aom_dsp/x86/fwd_dct32_8cols_sse2.c"
|
||||
"${AOM_ROOT}/aom_dsp/x86/fwd_dct32x32_impl_sse2.h"
|
||||
"${AOM_ROOT}/aom_dsp/x86/fwd_txfm_impl_sse2.h"
|
||||
"${AOM_ROOT}/aom_dsp/x86/fwd_txfm_sse2.c"
|
||||
"${AOM_ROOT}/aom_dsp/x86/fwd_txfm_sse2.h"
|
||||
"${AOM_ROOT}/aom_dsp/x86/halfpix_variance_sse2.c"
|
||||
"${AOM_ROOT}/aom_dsp/x86/variance_sse2.c"
|
||||
"${AOM_ROOT}/aom_dsp/x86/sum_squares_sse2.c")
|
||||
|
||||
set(AOM_DSP_ENCODER_INTRIN_SSSE3
|
||||
${AOM_DSP_ENCODER_INTRIN_SSSE3}
|
||||
"${AOM_ROOT}/aom_dsp/x86/masked_sad_intrin_ssse3.c"
|
||||
"${AOM_ROOT}/aom_dsp/x86/masked_variance_intrin_ssse3.c")
|
||||
|
||||
set(AOM_DSP_ENCODER_ASM_SSSE3_X86_64
|
||||
${AOM_DSP_ENCODER_ASM_SSSE3_X86_64}
|
||||
"${AOM_ROOT}/aom_dsp/x86/avg_ssse3_x86_64.asm"
|
||||
"${AOM_ROOT}/aom_dsp/x86/quantize_ssse3_x86_64.asm")
|
||||
|
||||
set(AOM_DSP_ENCODER_AVX_ASM_X86_64
|
||||
${AOM_DSP_ENCODER_AVX_ASM_X86_64}
|
||||
"${AOM_ROOT}/aom_dsp/x86/quantize_avx_x86_64.asm")
|
||||
|
||||
set(AOM_DSP_ENCODER_INTRIN_MSA
|
||||
"${AOM_ROOT}/aom_dsp/mips/avg_msa.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/sad_msa.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/subtract_msa.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/variance_msa.c"
|
||||
"${AOM_ROOT}/aom_dsp/mips/sub_pixel_variance_msa.c")
|
||||
|
||||
if (CONFIG_HIGHBITDEPTH)
|
||||
set(AOM_DSP_ENCODER_INTRIN_SSE2
|
||||
${AOM_DSP_ENCODER_INTRIN_SSE2}
|
||||
"${AOM_ROOT}/aom_dsp/x86/highbd_quantize_intrin_sse2.c"
|
||||
"${AOM_ROOT}/aom_dsp/x86/highbd_subtract_sse2.c")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (CONFIG_HIGHBITDEPTH)
|
||||
set(AOM_DSP_ENCODER_ASM_SSE2
|
||||
${AOM_DSP_ENCODER_ASM_SSE2}
|
||||
"${AOM_ROOT}/aom_dsp/x86/highbd_sad4d_sse2.asm"
|
||||
"${AOM_ROOT}/aom_dsp/x86/highbd_sad_sse2.asm"
|
||||
"${AOM_ROOT}/aom_dsp/x86/highbd_subpel_variance_impl_sse2.asm"
|
||||
"${AOM_ROOT}/aom_dsp/x86/highbd_variance_impl_sse2.asm"
|
||||
"${AOM_ROOT}/aom_dsp/x86/aom_high_subpixel_8t_sse2.asm"
|
||||
"${AOM_ROOT}/aom_dsp/x86/aom_high_subpixel_bilinear_sse2.asm")
|
||||
|
||||
set(AOM_DSP_ENCODER_INTRIN_SSE2
|
||||
${AOM_DSP_ENCODER_INTRIN_SSE2}
|
||||
"${AOM_ROOT}/aom_dsp/x86/highbd_variance_sse2.c")
|
||||
|
||||
set(AOM_DSP_ENCODER_INTRIN_SSE4_1
|
||||
${AOM_DSP_ENCODER_INTRIN_SSE4_1}
|
||||
"${AOM_ROOT}/aom_dsp/x86/highbd_variance_sse4.c")
|
||||
|
||||
set(AOM_DSP_ENCODER_INTRIN_AVX2
|
||||
${AOM_DSP_ENCODER_INTRIN_AVX2}
|
||||
"${AOM_ROOT}/aom_dsp/x86/sad_highbd_avx2.c")
|
||||
endif ()
|
||||
|
||||
if (CONFIG_ANS)
|
||||
set(AOM_DSP_ENCODER_SOURCES
|
||||
${AOM_DSP_ENCODER_SOURCES}
|
||||
"${AOM_ROOT}/aom_dsp/answriter.h"
|
||||
"${AOM_ROOT}/aom_dsp/buf_ans.c"
|
||||
"${AOM_ROOT}/aom_dsp/buf_ans.h")
|
||||
elseif (CONFIG_DAALA_EC)
|
||||
set(AOM_DSP_ENCODER_SOURCES
|
||||
${AOM_DSP_ENCODER_SOURCES}
|
||||
"${AOM_ROOT}/aom_dsp/daalaboolwriter.c"
|
||||
"${AOM_ROOT}/aom_dsp/daalaboolwriter.h"
|
||||
"${AOM_ROOT}/aom_dsp/entenc.c"
|
||||
"${AOM_ROOT}/aom_dsp/entenc.h")
|
||||
else ()
|
||||
set(AOM_DSP_ENCODER_SOURCES
|
||||
${AOM_DSP_ENCODER_SOURCES}
|
||||
"${AOM_ROOT}/aom_dsp/dkboolwriter.c"
|
||||
"${AOM_ROOT}/aom_dsp/dkboolwriter.h")
|
||||
endif ()
|
||||
|
||||
if (CONFIG_INTERNAL_STATS)
|
||||
set(AOM_DSP_ENCODER_SOURCES
|
||||
${AOM_DSP_ENCODER_SOURCES}
|
||||
"${AOM_ROOT}/aom_dsp/fastssim.c"
|
||||
"${AOM_ROOT}/aom_dsp/psnrhvs.c"
|
||||
"${AOM_ROOT}/aom_dsp/ssim.c"
|
||||
"${AOM_ROOT}/aom_dsp/ssim.h")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (CONFIG_MOTION_VAR)
|
||||
set(AOM_DSP_ENCODER_INTRIN_SSE4_1
|
||||
${AOM_DSP_ENCODER_INTRIN_SSE4_1}
|
||||
"${AOM_ROOT}/aom_dsp/x86/obmc_sad_sse4.c"
|
||||
"${AOM_ROOT}/aom_dsp/x86/obmc_variance_sse4.c")
|
||||
endif ()
|
||||
|
||||
# Creates aom_dsp build targets. Must not be called until after libaom target
|
||||
# has been created.
|
||||
function (setup_aom_dsp_targets)
|
||||
add_library(aom_dsp_common OBJECT ${AOM_DSP_COMMON_SOURCES})
|
||||
set(AOM_LIB_TARGETS ${AOM_LIB_TARGETS} aom_dsp_common)
|
||||
target_sources(aom PUBLIC $<TARGET_OBJECTS:aom_dsp_common>)
|
||||
|
||||
if (CONFIG_DECODERS)
|
||||
add_library(aom_dsp_decoder OBJECT ${AOM_DSP_DECODER_SOURCES})
|
||||
set(AOM_LIB_TARGETS ${AOM_LIB_TARGETS} aom_dsp_decoder)
|
||||
target_sources(aom PUBLIC $<TARGET_OBJECTS:aom_dsp_decoder>)
|
||||
endif ()
|
||||
|
||||
if (CONFIG_ENCODERS)
|
||||
add_library(aom_dsp_encoder OBJECT ${AOM_DSP_ENCODER_SOURCES})
|
||||
set(AOM_LIB_TARGETS ${AOM_LIB_TARGETS} aom_dsp_encoder)
|
||||
target_sources(aom PUBLIC $<TARGET_OBJECTS:aom_dsp_encoder>)
|
||||
endif ()
|
||||
|
||||
if (HAVE_SSE2)
|
||||
add_asm_library("aom_dsp_common_sse2" "AOM_DSP_COMMON_ASM_SSE2" "aom")
|
||||
add_intrinsics_object_library("-msse2" "sse2" "aom_dsp_common"
|
||||
"AOM_DSP_COMMON_INTRIN_SSE2")
|
||||
if (CONFIG_ENCODERS)
|
||||
add_asm_library("aom_dsp_encoder_sse2" "AOM_DSP_ENCODER_ASM_SSE2" "aom")
|
||||
add_intrinsics_object_library("-msse2" "sse2" "aom_dsp_encoder"
|
||||
"AOM_DSP_ENCODER_INTRIN_SSE2")
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
if (HAVE_SSE3 AND CONFIG_ENCODERS)
|
||||
add_asm_library("aom_dsp_encoder_sse3" "AOM_DSP_ENCODER_INTRIN_SSE3" "aom")
|
||||
endif ()
|
||||
|
||||
if (HAVE_SSSE3)
|
||||
add_asm_library("aom_dsp_common_ssse3" "AOM_DSP_COMMON_ASM_SSSE3" "aom")
|
||||
add_intrinsics_object_library("-mssse3" "ssse3" "aom_dsp_common"
|
||||
"AOM_DSP_COMMON_INTRIN_SSSE3")
|
||||
|
||||
if (CONFIG_ENCODERS)
|
||||
if ("${AOM_TARGET_CPU}" STREQUAL "x86_64")
|
||||
list(APPEND AOM_DSP_ENCODER_ASM_SSSE3
|
||||
${AOM_DSP_ENCODER_ASM_SSSE3_X86_64})
|
||||
endif ()
|
||||
add_asm_library("aom_dsp_encoder_ssse3" "AOM_DSP_ENCODER_ASM_SSSE3" "aom")
|
||||
add_intrinsics_object_library("-mssse3" "ssse3" "aom_dsp_encoder"
|
||||
"AOM_DSP_ENCODER_INTRIN_SSSE3")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (HAVE_SSE4_1)
|
||||
add_intrinsics_object_library("-msse4.1" "sse4_1" "aom_dsp_common"
|
||||
"AOM_DSP_COMMON_INTRIN_SSE4_1")
|
||||
if (CONFIG_ENCODERS)
|
||||
if (AOM_DSP_ENCODER_INTRIN_SSE4_1)
|
||||
add_intrinsics_object_library("-msse4.1" "sse4_1" "aom_dsp_encoder"
|
||||
"AOM_DSP_ENCODER_INTRIN_SSE4_1")
|
||||
endif ()
|
||||
add_asm_library("aom_dsp_encoder_sse4_1" "AOM_DSP_ENCODER_ASM_SSE4_1"
|
||||
"aom")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (HAVE_AVX AND "${AOM_TARGET_CPU}" STREQUAL "x86_64")
|
||||
add_asm_library("aom_dsp_encoder_avx" "AOM_DSP_ENCODER_AVX_ASM_X86_64"
|
||||
"aom")
|
||||
endif ()
|
||||
|
||||
if (HAVE_AVX2)
|
||||
add_intrinsics_object_library("-mavx2" "avx2" "aom_dsp_common"
|
||||
"AOM_DSP_COMMON_INTRIN_AVX2")
|
||||
if (CONFIG_ENCODERS)
|
||||
add_intrinsics_object_library("-mavx2" "avx2" "aom_dsp_encoder"
|
||||
"AOM_DSP_ENCODER_INTRIN_AVX2")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (HAVE_NEON_ASM)
|
||||
if (AOM_ADS2GAS_REQUIRED)
|
||||
add_gas_asm_library("aom_dsp_common_neon" "AOM_DSP_COMMON_ASM_NEON" "aom")
|
||||
else ()
|
||||
add_asm_library("aom_dsp_common_neon" "AOM_DSP_COMMON_ASM_NEON" "aom")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (HAVE_NEON)
|
||||
add_intrinsics_object_library("${AOM_NEON_INTRIN_FLAG}" "neon"
|
||||
"aom_dsp_common" "AOM_DSP_COMMON_INTRIN_NEON")
|
||||
endif ()
|
||||
|
||||
if (HAVE_DSPR2)
|
||||
add_intrinsics_object_library("" "dspr2" "aom_dsp_common"
|
||||
"AOM_DSP_COMMON_INTRIN_DSPR2")
|
||||
endif ()
|
||||
|
||||
if (HAVE_MSA)
|
||||
add_intrinsics_object_library("" "msa" "aom_dsp_common"
|
||||
"AOM_DSP_COMMON_INTRIN_MSA")
|
||||
if (CONFIG_ENCODERS)
|
||||
add_intrinsics_object_library("" "msa" "aom_dsp_encoder"
|
||||
"AOM_DSP_ENCODER_INTRIN_MSA")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# Pass the new lib targets up to the parent scope instance of
|
||||
# $AOM_LIB_TARGETS.
|
||||
set(AOM_LIB_TARGETS ${AOM_LIB_TARGETS} PARENT_SCOPE)
|
||||
endfunction ()
|
||||
428
third_party/aom/aom_dsp/aom_dsp.mk
vendored
Normal file
428
third_party/aom/aom_dsp/aom_dsp.mk
vendored
Normal file
|
|
@ -0,0 +1,428 @@
|
|||
##
|
||||
## Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
##
|
||||
## This source code is subject to the terms of the BSD 2 Clause License and
|
||||
## the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
## was not distributed with this source code in the LICENSE file, you can
|
||||
## obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
## Media Patent License 1.0 was not distributed with this source code in the
|
||||
## PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
##
|
||||
|
||||
|
||||
DSP_SRCS-yes += aom_dsp.mk
|
||||
DSP_SRCS-yes += aom_dsp_common.h
|
||||
|
||||
DSP_SRCS-$(HAVE_MSA) += mips/macros_msa.h
|
||||
|
||||
DSP_SRCS-$(ARCH_X86)$(ARCH_X86_64) += x86/synonyms.h
|
||||
|
||||
# bit reader
|
||||
DSP_SRCS-yes += prob.h
|
||||
DSP_SRCS-yes += prob.c
|
||||
DSP_SRCS-$(CONFIG_ANS) += ans.h
|
||||
|
||||
ifeq ($(CONFIG_ENCODERS),yes)
|
||||
ifeq ($(CONFIG_ANS),yes)
|
||||
DSP_SRCS-yes += answriter.h
|
||||
DSP_SRCS-yes += buf_ans.h
|
||||
DSP_SRCS-yes += buf_ans.c
|
||||
else ifeq ($(CONFIG_DAALA_EC),yes)
|
||||
DSP_SRCS-yes += entenc.c
|
||||
DSP_SRCS-yes += entenc.h
|
||||
DSP_SRCS-yes += daalaboolwriter.c
|
||||
DSP_SRCS-yes += daalaboolwriter.h
|
||||
else
|
||||
DSP_SRCS-yes += dkboolwriter.h
|
||||
DSP_SRCS-yes += dkboolwriter.c
|
||||
endif
|
||||
DSP_SRCS-yes += bitwriter.h
|
||||
DSP_SRCS-yes += bitwriter_buffer.c
|
||||
DSP_SRCS-yes += bitwriter_buffer.h
|
||||
DSP_SRCS-yes += binary_codes_writer.c
|
||||
DSP_SRCS-yes += binary_codes_writer.h
|
||||
DSP_SRCS-yes += psnr.c
|
||||
DSP_SRCS-yes += psnr.h
|
||||
DSP_SRCS-$(CONFIG_INTERNAL_STATS) += ssim.c
|
||||
DSP_SRCS-$(CONFIG_INTERNAL_STATS) += ssim.h
|
||||
DSP_SRCS-$(CONFIG_INTERNAL_STATS) += psnrhvs.c
|
||||
DSP_SRCS-$(CONFIG_INTERNAL_STATS) += fastssim.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_DECODERS),yes)
|
||||
ifeq ($(CONFIG_ANS),yes)
|
||||
DSP_SRCS-yes += ansreader.h
|
||||
else ifeq ($(CONFIG_DAALA_EC),yes)
|
||||
DSP_SRCS-yes += entdec.c
|
||||
DSP_SRCS-yes += entdec.h
|
||||
DSP_SRCS-yes += daalaboolreader.c
|
||||
DSP_SRCS-yes += daalaboolreader.h
|
||||
else
|
||||
DSP_SRCS-yes += dkboolreader.h
|
||||
DSP_SRCS-yes += dkboolreader.c
|
||||
endif
|
||||
DSP_SRCS-yes += bitreader.h
|
||||
DSP_SRCS-yes += bitreader_buffer.c
|
||||
DSP_SRCS-yes += bitreader_buffer.h
|
||||
DSP_SRCS-yes += binary_codes_reader.c
|
||||
DSP_SRCS-yes += binary_codes_reader.h
|
||||
endif
|
||||
|
||||
# intra predictions
|
||||
DSP_SRCS-yes += intrapred.c
|
||||
|
||||
ifeq ($(CONFIG_DAALA_EC),yes)
|
||||
DSP_SRCS-yes += entcode.c
|
||||
DSP_SRCS-yes += entcode.h
|
||||
endif
|
||||
|
||||
DSP_SRCS-$(HAVE_SSE) += x86/intrapred_sse2.asm
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/intrapred_sse2.asm
|
||||
DSP_SRCS-$(HAVE_SSSE3) += x86/intrapred_ssse3.asm
|
||||
DSP_SRCS-$(HAVE_SSSE3) += x86/aom_subpixel_8t_ssse3.asm
|
||||
|
||||
ifeq ($(CONFIG_HIGHBITDEPTH),yes)
|
||||
DSP_SRCS-$(HAVE_SSE) += x86/highbd_intrapred_sse2.asm
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/highbd_intrapred_sse2.asm
|
||||
endif # CONFIG_HIGHBITDEPTH
|
||||
|
||||
DSP_SRCS-$(HAVE_NEON_ASM) += arm/intrapred_neon_asm$(ASM)
|
||||
DSP_SRCS-$(HAVE_NEON) += arm/intrapred_neon.c
|
||||
DSP_SRCS-$(HAVE_MSA) += mips/intrapred_msa.c
|
||||
DSP_SRCS-$(HAVE_DSPR2) += mips/intrapred4_dspr2.c
|
||||
DSP_SRCS-$(HAVE_DSPR2) += mips/intrapred8_dspr2.c
|
||||
DSP_SRCS-$(HAVE_DSPR2) += mips/intrapred16_dspr2.c
|
||||
|
||||
DSP_SRCS-$(HAVE_DSPR2) += mips/common_dspr2.h
|
||||
DSP_SRCS-$(HAVE_DSPR2) += mips/common_dspr2.c
|
||||
|
||||
# inter predictions
|
||||
DSP_SRCS-yes += blend.h
|
||||
DSP_SRCS-yes += blend_a64_mask.c
|
||||
DSP_SRCS-yes += blend_a64_hmask.c
|
||||
DSP_SRCS-yes += blend_a64_vmask.c
|
||||
DSP_SRCS-$(HAVE_SSE4_1) += x86/blend_sse4.h
|
||||
DSP_SRCS-$(HAVE_SSE4_1) += x86/blend_a64_mask_sse4.c
|
||||
DSP_SRCS-$(HAVE_SSE4_1) += x86/blend_a64_hmask_sse4.c
|
||||
DSP_SRCS-$(HAVE_SSE4_1) += x86/blend_a64_vmask_sse4.c
|
||||
|
||||
# interpolation filters
|
||||
DSP_SRCS-yes += aom_convolve.c
|
||||
DSP_SRCS-yes += aom_convolve.h
|
||||
DSP_SRCS-yes += aom_filter.h
|
||||
|
||||
DSP_SRCS-$(ARCH_X86)$(ARCH_X86_64) += x86/convolve.h
|
||||
DSP_SRCS-$(ARCH_X86)$(ARCH_X86_64) += x86/aom_asm_stubs.c
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/aom_subpixel_8t_sse2.asm
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/aom_subpixel_bilinear_sse2.asm
|
||||
DSP_SRCS-$(HAVE_SSSE3) += x86/aom_subpixel_8t_ssse3.asm
|
||||
DSP_SRCS-$(HAVE_SSSE3) += x86/aom_subpixel_bilinear_ssse3.asm
|
||||
DSP_SRCS-$(HAVE_AVX2) += x86/aom_subpixel_8t_intrin_avx2.c
|
||||
DSP_SRCS-$(HAVE_SSSE3) += x86/aom_subpixel_8t_intrin_ssse3.c
|
||||
ifeq ($(CONFIG_HIGHBITDEPTH),yes)
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/aom_high_subpixel_8t_sse2.asm
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/aom_high_subpixel_bilinear_sse2.asm
|
||||
DSP_SRCS-$(HAVE_AVX2) += x86/highbd_convolve_avx2.c
|
||||
endif
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/aom_convolve_copy_sse2.asm
|
||||
|
||||
ifeq ($(HAVE_NEON_ASM),yes)
|
||||
DSP_SRCS-yes += arm/aom_convolve_copy_neon_asm$(ASM)
|
||||
DSP_SRCS-yes += arm/aom_convolve8_avg_neon_asm$(ASM)
|
||||
DSP_SRCS-yes += arm/aom_convolve8_neon_asm$(ASM)
|
||||
DSP_SRCS-yes += arm/aom_convolve_avg_neon_asm$(ASM)
|
||||
DSP_SRCS-yes += arm/aom_convolve_neon.c
|
||||
else
|
||||
ifeq ($(HAVE_NEON),yes)
|
||||
DSP_SRCS-yes += arm/aom_convolve_copy_neon.c
|
||||
DSP_SRCS-yes += arm/aom_convolve8_avg_neon.c
|
||||
DSP_SRCS-yes += arm/aom_convolve8_neon.c
|
||||
DSP_SRCS-yes += arm/aom_convolve_avg_neon.c
|
||||
DSP_SRCS-yes += arm/aom_convolve_neon.c
|
||||
endif # HAVE_NEON
|
||||
endif # HAVE_NEON_ASM
|
||||
|
||||
# common (msa)
|
||||
DSP_SRCS-$(HAVE_MSA) += mips/aom_convolve8_avg_horiz_msa.c
|
||||
DSP_SRCS-$(HAVE_MSA) += mips/aom_convolve8_avg_msa.c
|
||||
DSP_SRCS-$(HAVE_MSA) += mips/aom_convolve8_avg_vert_msa.c
|
||||
DSP_SRCS-$(HAVE_MSA) += mips/aom_convolve8_horiz_msa.c
|
||||
DSP_SRCS-$(HAVE_MSA) += mips/aom_convolve8_msa.c
|
||||
DSP_SRCS-$(HAVE_MSA) += mips/aom_convolve8_vert_msa.c
|
||||
DSP_SRCS-$(HAVE_MSA) += mips/aom_convolve_avg_msa.c
|
||||
DSP_SRCS-$(HAVE_MSA) += mips/aom_convolve_copy_msa.c
|
||||
DSP_SRCS-$(HAVE_MSA) += mips/aom_convolve_msa.h
|
||||
|
||||
# common (dspr2)
|
||||
DSP_SRCS-$(HAVE_DSPR2) += mips/convolve_common_dspr2.h
|
||||
DSP_SRCS-$(HAVE_DSPR2) += mips/convolve2_avg_dspr2.c
|
||||
DSP_SRCS-$(HAVE_DSPR2) += mips/convolve2_avg_horiz_dspr2.c
|
||||
DSP_SRCS-$(HAVE_DSPR2) += mips/convolve2_dspr2.c
|
||||
DSP_SRCS-$(HAVE_DSPR2) += mips/convolve2_horiz_dspr2.c
|
||||
DSP_SRCS-$(HAVE_DSPR2) += mips/convolve2_vert_dspr2.c
|
||||
DSP_SRCS-$(HAVE_DSPR2) += mips/convolve8_avg_dspr2.c
|
||||
DSP_SRCS-$(HAVE_DSPR2) += mips/convolve8_avg_horiz_dspr2.c
|
||||
DSP_SRCS-$(HAVE_DSPR2) += mips/convolve8_dspr2.c
|
||||
DSP_SRCS-$(HAVE_DSPR2) += mips/convolve8_horiz_dspr2.c
|
||||
DSP_SRCS-$(HAVE_DSPR2) += mips/convolve8_vert_dspr2.c
|
||||
|
||||
# loop filters
|
||||
DSP_SRCS-yes += loopfilter.c
|
||||
|
||||
DSP_SRCS-$(ARCH_X86)$(ARCH_X86_64) += x86/loopfilter_sse2.c
|
||||
DSP_SRCS-$(HAVE_AVX2) += x86/loopfilter_avx2.c
|
||||
|
||||
DSP_SRCS-$(HAVE_NEON) += arm/loopfilter_neon.c
|
||||
ifeq ($(HAVE_NEON_ASM),yes)
|
||||
DSP_SRCS-yes += arm/loopfilter_mb_neon$(ASM)
|
||||
DSP_SRCS-yes += arm/loopfilter_16_neon$(ASM)
|
||||
DSP_SRCS-yes += arm/loopfilter_8_neon$(ASM)
|
||||
DSP_SRCS-yes += arm/loopfilter_4_neon$(ASM)
|
||||
else
|
||||
ifeq ($(HAVE_NEON),yes)
|
||||
DSP_SRCS-yes += arm/loopfilter_16_neon.c
|
||||
DSP_SRCS-yes += arm/loopfilter_8_neon.c
|
||||
DSP_SRCS-yes += arm/loopfilter_4_neon.c
|
||||
endif # HAVE_NEON
|
||||
endif # HAVE_NEON_ASM
|
||||
|
||||
DSP_SRCS-$(HAVE_MSA) += mips/loopfilter_msa.h
|
||||
DSP_SRCS-$(HAVE_MSA) += mips/loopfilter_16_msa.c
|
||||
DSP_SRCS-$(HAVE_MSA) += mips/loopfilter_8_msa.c
|
||||
DSP_SRCS-$(HAVE_MSA) += mips/loopfilter_4_msa.c
|
||||
DSP_SRCS-$(HAVE_DSPR2) += mips/loopfilter_filters_dspr2.h
|
||||
DSP_SRCS-$(HAVE_DSPR2) += mips/loopfilter_filters_dspr2.c
|
||||
DSP_SRCS-$(HAVE_DSPR2) += mips/loopfilter_macros_dspr2.h
|
||||
DSP_SRCS-$(HAVE_DSPR2) += mips/loopfilter_masks_dspr2.h
|
||||
DSP_SRCS-$(HAVE_DSPR2) += mips/loopfilter_mb_dspr2.c
|
||||
DSP_SRCS-$(HAVE_DSPR2) += mips/loopfilter_mb_horiz_dspr2.c
|
||||
DSP_SRCS-$(HAVE_DSPR2) += mips/loopfilter_mb_vert_dspr2.c
|
||||
|
||||
ifeq ($(CONFIG_HIGHBITDEPTH),yes)
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/highbd_loopfilter_sse2.c
|
||||
endif # CONFIG_HIGHBITDEPTH
|
||||
|
||||
DSP_SRCS-yes += txfm_common.h
|
||||
DSP_SRCS-yes += x86/txfm_common_intrin.h
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/txfm_common_sse2.h
|
||||
DSP_SRCS-$(HAVE_MSA) += mips/txfm_macros_msa.h
|
||||
|
||||
# forward transform
|
||||
ifneq ($(findstring yes,$(CONFIG_AV1)$(CONFIG_PVQ)),)
|
||||
DSP_SRCS-$(HAVE_AVX2) += x86/txfm_common_avx2.h
|
||||
ifeq ($(CONFIG_AV1_ENCODER),yes)
|
||||
DSP_SRCS-yes += fwd_txfm.c
|
||||
DSP_SRCS-yes += fwd_txfm.h
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/fwd_txfm_sse2.h
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/fwd_txfm_sse2.c
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/fwd_dct32_8cols_sse2.c
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/fwd_txfm_impl_sse2.h
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/fwd_dct32x32_impl_sse2.h
|
||||
ifeq ($(ARCH_X86_64),yes)
|
||||
DSP_SRCS-$(HAVE_SSSE3) += x86/fwd_txfm_ssse3_x86_64.asm
|
||||
endif
|
||||
DSP_SRCS-$(HAVE_AVX2) += x86/fwd_txfm_avx2.h
|
||||
DSP_SRCS-$(HAVE_AVX2) += x86/fwd_txfm_avx2.c
|
||||
DSP_SRCS-$(HAVE_AVX2) += x86/fwd_dct32x32_impl_avx2.h
|
||||
DSP_SRCS-$(HAVE_NEON) += arm/fwd_txfm_neon.c
|
||||
DSP_SRCS-$(HAVE_MSA) += mips/fwd_txfm_msa.h
|
||||
DSP_SRCS-$(HAVE_MSA) += mips/fwd_txfm_msa.c
|
||||
DSP_SRCS-$(HAVE_MSA) += mips/fwd_dct32x32_msa.c
|
||||
endif # CONFIG_AV1_ENCODER
|
||||
endif # CONFIG_AV1
|
||||
|
||||
# inverse transform
|
||||
ifeq ($(CONFIG_AV1), yes)
|
||||
DSP_SRCS-yes += inv_txfm.h
|
||||
DSP_SRCS-yes += inv_txfm.c
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/inv_txfm_sse2.h
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/inv_txfm_sse2.c
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/inv_wht_sse2.asm
|
||||
DSP_SRCS-$(HAVE_SSSE3) += x86/inv_txfm_ssse3.c
|
||||
|
||||
ifeq ($(HAVE_NEON_ASM),yes)
|
||||
DSP_SRCS-yes += arm/save_reg_neon$(ASM)
|
||||
DSP_SRCS-yes += arm/idct4x4_1_add_neon$(ASM)
|
||||
DSP_SRCS-yes += arm/idct4x4_add_neon$(ASM)
|
||||
DSP_SRCS-yes += arm/idct8x8_1_add_neon$(ASM)
|
||||
DSP_SRCS-yes += arm/idct8x8_add_neon$(ASM)
|
||||
DSP_SRCS-yes += arm/idct16x16_1_add_neon$(ASM)
|
||||
DSP_SRCS-yes += arm/idct16x16_add_neon$(ASM)
|
||||
DSP_SRCS-yes += arm/idct32x32_1_add_neon$(ASM)
|
||||
DSP_SRCS-yes += arm/idct32x32_add_neon$(ASM)
|
||||
else
|
||||
ifeq ($(HAVE_NEON),yes)
|
||||
DSP_SRCS-yes += arm/idct4x4_1_add_neon.c
|
||||
DSP_SRCS-yes += arm/idct4x4_add_neon.c
|
||||
DSP_SRCS-yes += arm/idct8x8_1_add_neon.c
|
||||
DSP_SRCS-yes += arm/idct8x8_add_neon.c
|
||||
DSP_SRCS-yes += arm/idct16x16_1_add_neon.c
|
||||
DSP_SRCS-yes += arm/idct16x16_add_neon.c
|
||||
DSP_SRCS-yes += arm/idct32x32_1_add_neon.c
|
||||
DSP_SRCS-yes += arm/idct32x32_add_neon.c
|
||||
endif # HAVE_NEON
|
||||
endif # HAVE_NEON_ASM
|
||||
DSP_SRCS-$(HAVE_NEON) += arm/idct16x16_neon.c
|
||||
|
||||
DSP_SRCS-$(HAVE_MSA) += mips/inv_txfm_msa.h
|
||||
DSP_SRCS-$(HAVE_MSA) += mips/idct4x4_msa.c
|
||||
DSP_SRCS-$(HAVE_MSA) += mips/idct8x8_msa.c
|
||||
DSP_SRCS-$(HAVE_MSA) += mips/idct16x16_msa.c
|
||||
DSP_SRCS-$(HAVE_MSA) += mips/idct32x32_msa.c
|
||||
|
||||
ifneq ($(CONFIG_HIGHBITDEPTH),yes)
|
||||
DSP_SRCS-$(HAVE_DSPR2) += mips/inv_txfm_dspr2.h
|
||||
DSP_SRCS-$(HAVE_DSPR2) += mips/itrans4_dspr2.c
|
||||
DSP_SRCS-$(HAVE_DSPR2) += mips/itrans8_dspr2.c
|
||||
DSP_SRCS-$(HAVE_DSPR2) += mips/itrans16_dspr2.c
|
||||
DSP_SRCS-$(HAVE_DSPR2) += mips/itrans32_dspr2.c
|
||||
DSP_SRCS-$(HAVE_DSPR2) += mips/itrans32_cols_dspr2.c
|
||||
endif # CONFIG_HIGHBITDEPTH
|
||||
endif # CONFIG_AV1
|
||||
|
||||
# quantization
|
||||
ifneq ($(filter yes,$(CONFIG_AV1_ENCODER)),)
|
||||
DSP_SRCS-yes += quantize.c
|
||||
DSP_SRCS-yes += quantize.h
|
||||
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/quantize_sse2.c
|
||||
ifeq ($(CONFIG_HIGHBITDEPTH),yes)
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/highbd_quantize_intrin_sse2.c
|
||||
endif
|
||||
ifeq ($(ARCH_X86_64),yes)
|
||||
DSP_SRCS-$(HAVE_SSSE3) += x86/quantize_ssse3_x86_64.asm
|
||||
DSP_SRCS-$(HAVE_AVX) += x86/quantize_avx_x86_64.asm
|
||||
endif
|
||||
|
||||
# avg
|
||||
DSP_SRCS-yes += avg.c
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/avg_intrin_sse2.c
|
||||
DSP_SRCS-$(HAVE_NEON) += arm/avg_neon.c
|
||||
DSP_SRCS-$(HAVE_MSA) += mips/avg_msa.c
|
||||
DSP_SRCS-$(HAVE_NEON) += arm/hadamard_neon.c
|
||||
ifeq ($(ARCH_X86_64),yes)
|
||||
DSP_SRCS-$(HAVE_SSSE3) += x86/avg_ssse3_x86_64.asm
|
||||
endif
|
||||
|
||||
# high bit depth subtract
|
||||
ifeq ($(CONFIG_HIGHBITDEPTH),yes)
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/highbd_subtract_sse2.c
|
||||
endif
|
||||
|
||||
endif # CONFIG_AV1_ENCODER
|
||||
|
||||
ifeq ($(CONFIG_AV1_ENCODER),yes)
|
||||
DSP_SRCS-yes += sum_squares.c
|
||||
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/sum_squares_sse2.c
|
||||
endif # CONFIG_AV1_ENCODER
|
||||
|
||||
ifeq ($(CONFIG_ENCODERS),yes)
|
||||
DSP_SRCS-yes += sad.c
|
||||
DSP_SRCS-yes += subtract.c
|
||||
|
||||
DSP_SRCS-$(HAVE_MEDIA) += arm/sad_media$(ASM)
|
||||
DSP_SRCS-$(HAVE_NEON) += arm/sad4d_neon.c
|
||||
DSP_SRCS-$(HAVE_NEON) += arm/sad_neon.c
|
||||
DSP_SRCS-$(HAVE_NEON) += arm/subtract_neon.c
|
||||
|
||||
DSP_SRCS-$(HAVE_MSA) += mips/sad_msa.c
|
||||
DSP_SRCS-$(HAVE_MSA) += mips/subtract_msa.c
|
||||
|
||||
DSP_SRCS-$(HAVE_SSE3) += x86/sad_sse3.asm
|
||||
DSP_SRCS-$(HAVE_SSSE3) += x86/sad_ssse3.asm
|
||||
DSP_SRCS-$(HAVE_SSE4_1) += x86/sad_sse4.asm
|
||||
DSP_SRCS-$(HAVE_AVX2) += x86/sad4d_avx2.c
|
||||
DSP_SRCS-$(HAVE_AVX2) += x86/sad_avx2.c
|
||||
|
||||
ifeq ($(CONFIG_HIGHBITDEPTH),yes)
|
||||
DSP_SRCS-$(HAVE_AVX2) += x86/sad_highbd_avx2.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_AV1_ENCODER),yes)
|
||||
ifeq ($(CONFIG_EXT_INTER),yes)
|
||||
DSP_SRCS-$(HAVE_SSSE3) += x86/masked_sad_intrin_ssse3.c
|
||||
DSP_SRCS-$(HAVE_SSSE3) += x86/masked_variance_intrin_ssse3.c
|
||||
endif #CONFIG_EXT_INTER
|
||||
ifeq ($(CONFIG_MOTION_VAR),yes)
|
||||
DSP_SRCS-$(HAVE_SSE4_1) += x86/obmc_sad_sse4.c
|
||||
DSP_SRCS-$(HAVE_SSE4_1) += x86/obmc_variance_sse4.c
|
||||
endif #CONFIG_MOTION_VAR
|
||||
ifeq ($(CONFIG_EXT_PARTITION),yes)
|
||||
DSP_SRCS-$(HAVE_AVX2) += x86/sad_impl_avx2.c
|
||||
endif
|
||||
endif #CONFIG_AV1_ENCODER
|
||||
|
||||
DSP_SRCS-$(HAVE_SSE) += x86/sad4d_sse2.asm
|
||||
DSP_SRCS-$(HAVE_SSE) += x86/sad_sse2.asm
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/sad4d_sse2.asm
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/sad_sse2.asm
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/subtract_sse2.asm
|
||||
|
||||
ifeq ($(CONFIG_HIGHBITDEPTH),yes)
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/highbd_sad4d_sse2.asm
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/highbd_sad_sse2.asm
|
||||
endif # CONFIG_HIGHBITDEPTH
|
||||
|
||||
endif # CONFIG_ENCODERS
|
||||
|
||||
ifneq ($(filter yes,$(CONFIG_ENCODERS)),)
|
||||
DSP_SRCS-yes += variance.c
|
||||
DSP_SRCS-yes += variance.h
|
||||
|
||||
DSP_SRCS-$(HAVE_MEDIA) += arm/bilinear_filter_media$(ASM)
|
||||
DSP_SRCS-$(HAVE_MEDIA) += arm/subpel_variance_media.c
|
||||
DSP_SRCS-$(HAVE_MEDIA) += arm/variance_halfpixvar16x16_h_media$(ASM)
|
||||
DSP_SRCS-$(HAVE_MEDIA) += arm/variance_halfpixvar16x16_hv_media$(ASM)
|
||||
DSP_SRCS-$(HAVE_MEDIA) += arm/variance_halfpixvar16x16_v_media$(ASM)
|
||||
DSP_SRCS-$(HAVE_MEDIA) += arm/variance_media$(ASM)
|
||||
DSP_SRCS-$(HAVE_NEON) += arm/subpel_variance_neon.c
|
||||
DSP_SRCS-$(HAVE_NEON) += arm/variance_neon.c
|
||||
|
||||
DSP_SRCS-$(HAVE_MSA) += mips/variance_msa.c
|
||||
DSP_SRCS-$(HAVE_MSA) += mips/sub_pixel_variance_msa.c
|
||||
|
||||
DSP_SRCS-$(HAVE_SSE) += x86/variance_sse2.c
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/variance_sse2.c # Contains SSE2 and SSSE3
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/halfpix_variance_sse2.c
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/halfpix_variance_impl_sse2.asm
|
||||
DSP_SRCS-$(HAVE_AVX2) += x86/variance_avx2.c
|
||||
DSP_SRCS-$(HAVE_AVX2) += x86/variance_impl_avx2.c
|
||||
|
||||
ifeq ($(ARCH_X86_64),yes)
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/ssim_opt_x86_64.asm
|
||||
endif # ARCH_X86_64
|
||||
|
||||
DSP_SRCS-$(HAVE_SSE) += x86/subpel_variance_sse2.asm
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/subpel_variance_sse2.asm # Contains SSE2 and SSSE3
|
||||
|
||||
ifeq ($(CONFIG_HIGHBITDEPTH),yes)
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/highbd_variance_sse2.c
|
||||
DSP_SRCS-$(HAVE_SSE4_1) += x86/highbd_variance_sse4.c
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/highbd_variance_impl_sse2.asm
|
||||
DSP_SRCS-$(HAVE_SSE2) += x86/highbd_subpel_variance_impl_sse2.asm
|
||||
endif # CONFIG_HIGHBITDEPTH
|
||||
endif # CONFIG_ENCODERS
|
||||
|
||||
DSP_SRCS-no += $(DSP_SRCS_REMOVE-yes)
|
||||
|
||||
DSP_SRCS-yes += aom_dsp_rtcd.c
|
||||
DSP_SRCS-yes += aom_dsp_rtcd_defs.pl
|
||||
|
||||
DSP_SRCS-yes += aom_simd.h
|
||||
DSP_SRCS-yes += aom_simd_inline.h
|
||||
DSP_SRCS-yes += simd/v64_intrinsics.h
|
||||
DSP_SRCS-yes += simd/v64_intrinsics_c.h
|
||||
DSP_SRCS-yes += simd/v128_intrinsics.h
|
||||
DSP_SRCS-yes += simd/v128_intrinsics_c.h
|
||||
DSP_SRCS-yes += simd/v256_intrinsics.h
|
||||
DSP_SRCS-yes += simd/v256_intrinsics_c.h
|
||||
DSP_SRCS-yes += simd/v256_intrinsics_v128.h
|
||||
DSP_SRCS-$(HAVE_SSE2) += simd/v64_intrinsics_x86.h
|
||||
DSP_SRCS-$(HAVE_SSE2) += simd/v128_intrinsics_x86.h
|
||||
DSP_SRCS-$(HAVE_SSE2) += simd/v256_intrinsics_x86.h
|
||||
DSP_SRCS-$(HAVE_NEON) += simd/v64_intrinsics_arm.h
|
||||
DSP_SRCS-$(HAVE_NEON) += simd/v128_intrinsics_arm.h
|
||||
DSP_SRCS-$(HAVE_NEON) += simd/v256_intrinsics_arm.h
|
||||
|
||||
$(eval $(call rtcd_h_template,aom_dsp_rtcd,aom_dsp/aom_dsp_rtcd_defs.pl))
|
||||
107
third_party/aom/aom_dsp/aom_dsp_common.h
vendored
Normal file
107
third_party/aom/aom_dsp/aom_dsp_common.h
vendored
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#ifndef AOM_DSP_AOM_DSP_COMMON_H_
|
||||
#define AOM_DSP_AOM_DSP_COMMON_H_
|
||||
|
||||
#include "./aom_config.h"
|
||||
#include "aom/aom_integer.h"
|
||||
#include "aom_ports/mem.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef MAX_SB_SIZE
|
||||
#if CONFIG_AV1 && CONFIG_EXT_PARTITION
|
||||
#define MAX_SB_SIZE 128
|
||||
#else
|
||||
#define MAX_SB_SIZE 64
|
||||
#endif // CONFIG_AV1 && CONFIG_EXT_PARTITION
|
||||
#endif // ndef MAX_SB_SIZE
|
||||
|
||||
#define AOMMIN(x, y) (((x) < (y)) ? (x) : (y))
|
||||
#define AOMMAX(x, y) (((x) > (y)) ? (x) : (y))
|
||||
|
||||
#define IMPLIES(a, b) (!(a) || (b)) // Logical 'a implies b' (or 'a -> b')
|
||||
|
||||
#define IS_POWER_OF_TWO(x) (((x) & ((x)-1)) == 0)
|
||||
|
||||
/* Left shifting a negative value became undefined behavior in C99 (downgraded
|
||||
from merely implementation-defined in C89). This should still compile to the
|
||||
correct thing on any two's-complement machine, but avoid ubsan warnings.*/
|
||||
#define AOM_SIGNED_SHL(x, shift) ((x) * (((x)*0 + 1) << (shift)))
|
||||
|
||||
// These can be used to give a hint about branch outcomes.
|
||||
// This can have an effect, even if your target processor has a
|
||||
// good branch predictor, as these hints can affect basic block
|
||||
// ordering by the compiler.
|
||||
#ifdef __GNUC__
|
||||
#define LIKELY(v) __builtin_expect(v, 1)
|
||||
#define UNLIKELY(v) __builtin_expect(v, 0)
|
||||
#else
|
||||
#define LIKELY(v) (v)
|
||||
#define UNLIKELY(v) (v)
|
||||
#endif
|
||||
|
||||
#define AOM_SWAP(type, a, b) \
|
||||
do { \
|
||||
type c = (b); \
|
||||
b = a; \
|
||||
a = c; \
|
||||
} while (0)
|
||||
|
||||
#if CONFIG_AOM_QM
|
||||
typedef uint16_t qm_val_t;
|
||||
#define AOM_QM_BITS 6
|
||||
#endif
|
||||
#if CONFIG_HIGHBITDEPTH
|
||||
// Note:
|
||||
// tran_low_t is the datatype used for final transform coefficients.
|
||||
// tran_high_t is the datatype used for intermediate transform stages.
|
||||
typedef int64_t tran_high_t;
|
||||
typedef int32_t tran_low_t;
|
||||
#else
|
||||
// Note:
|
||||
// tran_low_t is the datatype used for final transform coefficients.
|
||||
// tran_high_t is the datatype used for intermediate transform stages.
|
||||
typedef int32_t tran_high_t;
|
||||
typedef int16_t tran_low_t;
|
||||
#endif // CONFIG_HIGHBITDEPTH
|
||||
|
||||
static INLINE uint8_t clip_pixel(int val) {
|
||||
return (val > 255) ? 255 : (val < 0) ? 0 : val;
|
||||
}
|
||||
|
||||
static INLINE int clamp(int value, int low, int high) {
|
||||
return value < low ? low : (value > high ? high : value);
|
||||
}
|
||||
|
||||
static INLINE double fclamp(double value, double low, double high) {
|
||||
return value < low ? low : (value > high ? high : value);
|
||||
}
|
||||
|
||||
#if CONFIG_HIGHBITDEPTH
|
||||
static INLINE uint16_t clip_pixel_highbd(int val, int bd) {
|
||||
switch (bd) {
|
||||
case 8:
|
||||
default: return (uint16_t)clamp(val, 0, 255);
|
||||
case 10: return (uint16_t)clamp(val, 0, 1023);
|
||||
case 12: return (uint16_t)clamp(val, 0, 4095);
|
||||
}
|
||||
}
|
||||
#endif // CONFIG_HIGHBITDEPTH
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // AOM_DSP_AOM_DSP_COMMON_H_
|
||||
16
third_party/aom/aom_dsp/aom_dsp_rtcd.c
vendored
Normal file
16
third_party/aom/aom_dsp/aom_dsp_rtcd.c
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
#include "./aom_config.h"
|
||||
#define RTCD_C
|
||||
#include "./aom_dsp_rtcd.h"
|
||||
#include "aom_ports/aom_once.h"
|
||||
|
||||
void aom_dsp_rtcd() { once(setup_rtcd_internal); }
|
||||
1495
third_party/aom/aom_dsp/aom_dsp_rtcd_defs.pl
vendored
Executable file
1495
third_party/aom/aom_dsp/aom_dsp_rtcd_defs.pl
vendored
Executable file
File diff suppressed because it is too large
Load diff
43
third_party/aom/aom_dsp/aom_filter.h
vendored
Normal file
43
third_party/aom/aom_dsp/aom_filter.h
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#ifndef AOM_DSP_AOM_FILTER_H_
|
||||
#define AOM_DSP_AOM_FILTER_H_
|
||||
|
||||
#include "aom/aom_integer.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define FILTER_BITS 7
|
||||
|
||||
#define SUBPEL_BITS 4
|
||||
#define SUBPEL_MASK ((1 << SUBPEL_BITS) - 1)
|
||||
#define SUBPEL_SHIFTS (1 << SUBPEL_BITS)
|
||||
#define SUBPEL_TAPS 8
|
||||
|
||||
typedef int16_t InterpKernel[SUBPEL_TAPS];
|
||||
|
||||
#define BIL_SUBPEL_BITS 3
|
||||
#define BIL_SUBPEL_SHIFTS (1 << BIL_SUBPEL_BITS)
|
||||
|
||||
// 2 tap bilinear filters
|
||||
static const uint8_t bilinear_filters_2t[BIL_SUBPEL_SHIFTS][2] = {
|
||||
{ 128, 0 }, { 112, 16 }, { 96, 32 }, { 80, 48 },
|
||||
{ 64, 64 }, { 48, 80 }, { 32, 96 }, { 16, 112 },
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // AOM_DSP_AOM_FILTER_H_
|
||||
37
third_party/aom/aom_dsp/aom_simd.h
vendored
Normal file
37
third_party/aom/aom_dsp/aom_simd.h
vendored
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#ifndef AOM_DSP_AOM_AOM_SIMD_H_
|
||||
#define AOM_DSP_AOM_AOM_SIMD_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
#include "./aom_config.h"
|
||||
#include "./aom_simd_inline.h"
|
||||
|
||||
#define SIMD_CHECK 1 // Sanity checks in C equivalents
|
||||
|
||||
#if HAVE_NEON
|
||||
#include "simd/v256_intrinsics_arm.h"
|
||||
// VS compiling for 32 bit targets does not support vector types in
|
||||
// structs as arguments, which makes the v256 type of the intrinsics
|
||||
// hard to support, so optimizations for this target are disabled.
|
||||
#elif HAVE_SSE2 && (defined(_WIN64) || !defined(_MSC_VER) || defined(__clang__))
|
||||
#include "simd/v256_intrinsics_x86.h"
|
||||
#else
|
||||
#include "simd/v256_intrinsics.h"
|
||||
#endif
|
||||
|
||||
#endif // AOM_DSP_AOM_AOM_SIMD_H_
|
||||
21
third_party/aom/aom_dsp/aom_simd_inline.h
vendored
Normal file
21
third_party/aom/aom_dsp/aom_simd_inline.h
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#ifndef AOM_DSP_AOM_SIMD_INLINE_H_
|
||||
#define AOM_DSP_AOM_SIMD_INLINE_H_
|
||||
|
||||
#include "aom/aom_integer.h"
|
||||
|
||||
#ifndef SIMD_INLINE
|
||||
#define SIMD_INLINE static AOM_FORCE_INLINE
|
||||
#endif
|
||||
|
||||
#endif // AOM_DSP_AOM_SIMD_INLINE_H_
|
||||
364
third_party/aom/aom_dsp/arm/aom_convolve8_avg_neon.c
vendored
Normal file
364
third_party/aom/aom_dsp/arm/aom_convolve8_avg_neon.c
vendored
Normal file
|
|
@ -0,0 +1,364 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <arm_neon.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "./aom_config.h"
|
||||
#include "./aom_dsp_rtcd.h"
|
||||
#include "aom/aom_integer.h"
|
||||
#include "aom_ports/mem.h"
|
||||
|
||||
static INLINE int32x4_t MULTIPLY_BY_Q0(int16x4_t dsrc0, int16x4_t dsrc1,
|
||||
int16x4_t dsrc2, int16x4_t dsrc3,
|
||||
int16x4_t dsrc4, int16x4_t dsrc5,
|
||||
int16x4_t dsrc6, int16x4_t dsrc7,
|
||||
int16x8_t q0s16) {
|
||||
int32x4_t qdst;
|
||||
int16x4_t d0s16, d1s16;
|
||||
|
||||
d0s16 = vget_low_s16(q0s16);
|
||||
d1s16 = vget_high_s16(q0s16);
|
||||
|
||||
qdst = vmull_lane_s16(dsrc0, d0s16, 0);
|
||||
qdst = vmlal_lane_s16(qdst, dsrc1, d0s16, 1);
|
||||
qdst = vmlal_lane_s16(qdst, dsrc2, d0s16, 2);
|
||||
qdst = vmlal_lane_s16(qdst, dsrc3, d0s16, 3);
|
||||
qdst = vmlal_lane_s16(qdst, dsrc4, d1s16, 0);
|
||||
qdst = vmlal_lane_s16(qdst, dsrc5, d1s16, 1);
|
||||
qdst = vmlal_lane_s16(qdst, dsrc6, d1s16, 2);
|
||||
qdst = vmlal_lane_s16(qdst, dsrc7, d1s16, 3);
|
||||
return qdst;
|
||||
}
|
||||
|
||||
void aom_convolve8_avg_horiz_neon(const uint8_t *src, ptrdiff_t src_stride,
|
||||
uint8_t *dst, ptrdiff_t dst_stride,
|
||||
const int16_t *filter_x, int x_step_q4,
|
||||
const int16_t *filter_y, // unused
|
||||
int y_step_q4, // unused
|
||||
int w, int h) {
|
||||
int width;
|
||||
const uint8_t *s;
|
||||
uint8_t *d;
|
||||
uint8x8_t d2u8, d3u8, d24u8, d25u8, d26u8, d27u8, d28u8, d29u8;
|
||||
uint32x2_t d2u32, d3u32, d6u32, d7u32, d28u32, d29u32, d30u32, d31u32;
|
||||
uint8x16_t q1u8, q3u8, q12u8, q13u8, q14u8, q15u8;
|
||||
int16x4_t d16s16, d17s16, d18s16, d19s16, d20s16, d22s16, d23s16;
|
||||
int16x4_t d24s16, d25s16, d26s16, d27s16;
|
||||
uint16x4_t d2u16, d3u16, d4u16, d5u16, d16u16, d17u16, d18u16, d19u16;
|
||||
int16x8_t q0s16;
|
||||
uint16x8_t q1u16, q2u16, q8u16, q9u16, q10u16, q11u16, q12u16, q13u16;
|
||||
int32x4_t q1s32, q2s32, q14s32, q15s32;
|
||||
uint16x8x2_t q0x2u16;
|
||||
uint8x8x2_t d0x2u8, d1x2u8;
|
||||
uint32x2x2_t d0x2u32;
|
||||
uint16x4x2_t d0x2u16, d1x2u16;
|
||||
uint32x4x2_t q0x2u32;
|
||||
|
||||
assert(x_step_q4 == 16);
|
||||
|
||||
(void)x_step_q4;
|
||||
(void)y_step_q4;
|
||||
(void)filter_y;
|
||||
|
||||
q0s16 = vld1q_s16(filter_x);
|
||||
|
||||
src -= 3; // adjust for taps
|
||||
for (; h > 0; h -= 4) { // loop_horiz_v
|
||||
s = src;
|
||||
d24u8 = vld1_u8(s);
|
||||
s += src_stride;
|
||||
d25u8 = vld1_u8(s);
|
||||
s += src_stride;
|
||||
d26u8 = vld1_u8(s);
|
||||
s += src_stride;
|
||||
d27u8 = vld1_u8(s);
|
||||
|
||||
q12u8 = vcombine_u8(d24u8, d25u8);
|
||||
q13u8 = vcombine_u8(d26u8, d27u8);
|
||||
|
||||
q0x2u16 =
|
||||
vtrnq_u16(vreinterpretq_u16_u8(q12u8), vreinterpretq_u16_u8(q13u8));
|
||||
d24u8 = vreinterpret_u8_u16(vget_low_u16(q0x2u16.val[0]));
|
||||
d25u8 = vreinterpret_u8_u16(vget_high_u16(q0x2u16.val[0]));
|
||||
d26u8 = vreinterpret_u8_u16(vget_low_u16(q0x2u16.val[1]));
|
||||
d27u8 = vreinterpret_u8_u16(vget_high_u16(q0x2u16.val[1]));
|
||||
d0x2u8 = vtrn_u8(d24u8, d25u8);
|
||||
d1x2u8 = vtrn_u8(d26u8, d27u8);
|
||||
|
||||
__builtin_prefetch(src + src_stride * 4);
|
||||
__builtin_prefetch(src + src_stride * 5);
|
||||
|
||||
q8u16 = vmovl_u8(d0x2u8.val[0]);
|
||||
q9u16 = vmovl_u8(d0x2u8.val[1]);
|
||||
q10u16 = vmovl_u8(d1x2u8.val[0]);
|
||||
q11u16 = vmovl_u8(d1x2u8.val[1]);
|
||||
|
||||
src += 7;
|
||||
d16u16 = vget_low_u16(q8u16);
|
||||
d17u16 = vget_high_u16(q8u16);
|
||||
d18u16 = vget_low_u16(q9u16);
|
||||
d19u16 = vget_high_u16(q9u16);
|
||||
q8u16 = vcombine_u16(d16u16, d18u16); // vswp 17 18
|
||||
q9u16 = vcombine_u16(d17u16, d19u16);
|
||||
|
||||
d20s16 = vreinterpret_s16_u16(vget_low_u16(q10u16));
|
||||
d23s16 = vreinterpret_s16_u16(vget_high_u16(q10u16)); // vmov 23 21
|
||||
for (width = w; width > 0; width -= 4, src += 4, dst += 4) { // loop_horiz
|
||||
s = src;
|
||||
d28u32 = vld1_dup_u32((const uint32_t *)s);
|
||||
s += src_stride;
|
||||
d29u32 = vld1_dup_u32((const uint32_t *)s);
|
||||
s += src_stride;
|
||||
d31u32 = vld1_dup_u32((const uint32_t *)s);
|
||||
s += src_stride;
|
||||
d30u32 = vld1_dup_u32((const uint32_t *)s);
|
||||
|
||||
__builtin_prefetch(src + 64);
|
||||
|
||||
d0x2u16 =
|
||||
vtrn_u16(vreinterpret_u16_u32(d28u32), vreinterpret_u16_u32(d31u32));
|
||||
d1x2u16 =
|
||||
vtrn_u16(vreinterpret_u16_u32(d29u32), vreinterpret_u16_u32(d30u32));
|
||||
d0x2u8 = vtrn_u8(vreinterpret_u8_u16(d0x2u16.val[0]), // d28
|
||||
vreinterpret_u8_u16(d1x2u16.val[0])); // d29
|
||||
d1x2u8 = vtrn_u8(vreinterpret_u8_u16(d0x2u16.val[1]), // d31
|
||||
vreinterpret_u8_u16(d1x2u16.val[1])); // d30
|
||||
|
||||
__builtin_prefetch(src + 64 + src_stride);
|
||||
|
||||
q14u8 = vcombine_u8(d0x2u8.val[0], d0x2u8.val[1]);
|
||||
q15u8 = vcombine_u8(d1x2u8.val[1], d1x2u8.val[0]);
|
||||
q0x2u32 =
|
||||
vtrnq_u32(vreinterpretq_u32_u8(q14u8), vreinterpretq_u32_u8(q15u8));
|
||||
|
||||
d28u8 = vreinterpret_u8_u32(vget_low_u32(q0x2u32.val[0]));
|
||||
d29u8 = vreinterpret_u8_u32(vget_high_u32(q0x2u32.val[0]));
|
||||
q12u16 = vmovl_u8(d28u8);
|
||||
q13u16 = vmovl_u8(d29u8);
|
||||
|
||||
__builtin_prefetch(src + 64 + src_stride * 2);
|
||||
|
||||
d = dst;
|
||||
d6u32 = vld1_lane_u32((const uint32_t *)d, d6u32, 0);
|
||||
d += dst_stride;
|
||||
d7u32 = vld1_lane_u32((const uint32_t *)d, d7u32, 0);
|
||||
d += dst_stride;
|
||||
d6u32 = vld1_lane_u32((const uint32_t *)d, d6u32, 1);
|
||||
d += dst_stride;
|
||||
d7u32 = vld1_lane_u32((const uint32_t *)d, d7u32, 1);
|
||||
|
||||
d16s16 = vreinterpret_s16_u16(vget_low_u16(q8u16));
|
||||
d17s16 = vreinterpret_s16_u16(vget_high_u16(q8u16));
|
||||
d18s16 = vreinterpret_s16_u16(vget_low_u16(q9u16));
|
||||
d19s16 = vreinterpret_s16_u16(vget_high_u16(q9u16));
|
||||
d22s16 = vreinterpret_s16_u16(vget_low_u16(q11u16));
|
||||
d24s16 = vreinterpret_s16_u16(vget_low_u16(q12u16));
|
||||
d25s16 = vreinterpret_s16_u16(vget_high_u16(q12u16));
|
||||
d26s16 = vreinterpret_s16_u16(vget_low_u16(q13u16));
|
||||
d27s16 = vreinterpret_s16_u16(vget_high_u16(q13u16));
|
||||
|
||||
q1s32 = MULTIPLY_BY_Q0(d16s16, d17s16, d20s16, d22s16, d18s16, d19s16,
|
||||
d23s16, d24s16, q0s16);
|
||||
q2s32 = MULTIPLY_BY_Q0(d17s16, d20s16, d22s16, d18s16, d19s16, d23s16,
|
||||
d24s16, d26s16, q0s16);
|
||||
q14s32 = MULTIPLY_BY_Q0(d20s16, d22s16, d18s16, d19s16, d23s16, d24s16,
|
||||
d26s16, d27s16, q0s16);
|
||||
q15s32 = MULTIPLY_BY_Q0(d22s16, d18s16, d19s16, d23s16, d24s16, d26s16,
|
||||
d27s16, d25s16, q0s16);
|
||||
|
||||
__builtin_prefetch(src + 64 + src_stride * 3);
|
||||
|
||||
d2u16 = vqrshrun_n_s32(q1s32, 7);
|
||||
d3u16 = vqrshrun_n_s32(q2s32, 7);
|
||||
d4u16 = vqrshrun_n_s32(q14s32, 7);
|
||||
d5u16 = vqrshrun_n_s32(q15s32, 7);
|
||||
|
||||
q1u16 = vcombine_u16(d2u16, d3u16);
|
||||
q2u16 = vcombine_u16(d4u16, d5u16);
|
||||
|
||||
d2u8 = vqmovn_u16(q1u16);
|
||||
d3u8 = vqmovn_u16(q2u16);
|
||||
|
||||
d0x2u16 = vtrn_u16(vreinterpret_u16_u8(d2u8), vreinterpret_u16_u8(d3u8));
|
||||
d0x2u32 = vtrn_u32(vreinterpret_u32_u16(d0x2u16.val[0]),
|
||||
vreinterpret_u32_u16(d0x2u16.val[1]));
|
||||
d0x2u8 = vtrn_u8(vreinterpret_u8_u32(d0x2u32.val[0]),
|
||||
vreinterpret_u8_u32(d0x2u32.val[1]));
|
||||
|
||||
q1u8 = vcombine_u8(d0x2u8.val[0], d0x2u8.val[1]);
|
||||
q3u8 = vreinterpretq_u8_u32(vcombine_u32(d6u32, d7u32));
|
||||
|
||||
q1u8 = vrhaddq_u8(q1u8, q3u8);
|
||||
|
||||
d2u32 = vreinterpret_u32_u8(vget_low_u8(q1u8));
|
||||
d3u32 = vreinterpret_u32_u8(vget_high_u8(q1u8));
|
||||
|
||||
d = dst;
|
||||
vst1_lane_u32((uint32_t *)d, d2u32, 0);
|
||||
d += dst_stride;
|
||||
vst1_lane_u32((uint32_t *)d, d3u32, 0);
|
||||
d += dst_stride;
|
||||
vst1_lane_u32((uint32_t *)d, d2u32, 1);
|
||||
d += dst_stride;
|
||||
vst1_lane_u32((uint32_t *)d, d3u32, 1);
|
||||
|
||||
q8u16 = q9u16;
|
||||
d20s16 = d23s16;
|
||||
q11u16 = q12u16;
|
||||
q9u16 = q13u16;
|
||||
d23s16 = vreinterpret_s16_u16(vget_high_u16(q11u16));
|
||||
}
|
||||
src += src_stride * 4 - w - 7;
|
||||
dst += dst_stride * 4 - w;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void aom_convolve8_avg_vert_neon(const uint8_t *src, ptrdiff_t src_stride,
|
||||
uint8_t *dst, ptrdiff_t dst_stride,
|
||||
const int16_t *filter_x, // unused
|
||||
int x_step_q4, // unused
|
||||
const int16_t *filter_y, int y_step_q4, int w,
|
||||
int h) {
|
||||
int height;
|
||||
const uint8_t *s;
|
||||
uint8_t *d;
|
||||
uint8x8_t d2u8, d3u8;
|
||||
uint32x2_t d2u32, d3u32, d6u32, d7u32;
|
||||
uint32x2_t d16u32, d18u32, d20u32, d22u32, d24u32, d26u32;
|
||||
uint8x16_t q1u8, q3u8;
|
||||
int16x4_t d16s16, d17s16, d18s16, d19s16, d20s16, d21s16, d22s16;
|
||||
int16x4_t d24s16, d25s16, d26s16, d27s16;
|
||||
uint16x4_t d2u16, d3u16, d4u16, d5u16;
|
||||
int16x8_t q0s16;
|
||||
uint16x8_t q1u16, q2u16, q8u16, q9u16, q10u16, q11u16, q12u16, q13u16;
|
||||
int32x4_t q1s32, q2s32, q14s32, q15s32;
|
||||
|
||||
assert(y_step_q4 == 16);
|
||||
|
||||
(void)x_step_q4;
|
||||
(void)y_step_q4;
|
||||
(void)filter_x;
|
||||
|
||||
src -= src_stride * 3;
|
||||
q0s16 = vld1q_s16(filter_y);
|
||||
for (; w > 0; w -= 4, src += 4, dst += 4) { // loop_vert_h
|
||||
s = src;
|
||||
d16u32 = vld1_lane_u32((const uint32_t *)s, d16u32, 0);
|
||||
s += src_stride;
|
||||
d16u32 = vld1_lane_u32((const uint32_t *)s, d16u32, 1);
|
||||
s += src_stride;
|
||||
d18u32 = vld1_lane_u32((const uint32_t *)s, d18u32, 0);
|
||||
s += src_stride;
|
||||
d18u32 = vld1_lane_u32((const uint32_t *)s, d18u32, 1);
|
||||
s += src_stride;
|
||||
d20u32 = vld1_lane_u32((const uint32_t *)s, d20u32, 0);
|
||||
s += src_stride;
|
||||
d20u32 = vld1_lane_u32((const uint32_t *)s, d20u32, 1);
|
||||
s += src_stride;
|
||||
d22u32 = vld1_lane_u32((const uint32_t *)s, d22u32, 0);
|
||||
s += src_stride;
|
||||
|
||||
q8u16 = vmovl_u8(vreinterpret_u8_u32(d16u32));
|
||||
q9u16 = vmovl_u8(vreinterpret_u8_u32(d18u32));
|
||||
q10u16 = vmovl_u8(vreinterpret_u8_u32(d20u32));
|
||||
q11u16 = vmovl_u8(vreinterpret_u8_u32(d22u32));
|
||||
|
||||
d18s16 = vreinterpret_s16_u16(vget_low_u16(q9u16));
|
||||
d19s16 = vreinterpret_s16_u16(vget_high_u16(q9u16));
|
||||
d22s16 = vreinterpret_s16_u16(vget_low_u16(q11u16));
|
||||
d = dst;
|
||||
for (height = h; height > 0; height -= 4) { // loop_vert
|
||||
d24u32 = vld1_lane_u32((const uint32_t *)s, d24u32, 0);
|
||||
s += src_stride;
|
||||
d26u32 = vld1_lane_u32((const uint32_t *)s, d26u32, 0);
|
||||
s += src_stride;
|
||||
d26u32 = vld1_lane_u32((const uint32_t *)s, d26u32, 1);
|
||||
s += src_stride;
|
||||
d24u32 = vld1_lane_u32((const uint32_t *)s, d24u32, 1);
|
||||
s += src_stride;
|
||||
|
||||
q12u16 = vmovl_u8(vreinterpret_u8_u32(d24u32));
|
||||
q13u16 = vmovl_u8(vreinterpret_u8_u32(d26u32));
|
||||
|
||||
d6u32 = vld1_lane_u32((const uint32_t *)d, d6u32, 0);
|
||||
d += dst_stride;
|
||||
d6u32 = vld1_lane_u32((const uint32_t *)d, d6u32, 1);
|
||||
d += dst_stride;
|
||||
d7u32 = vld1_lane_u32((const uint32_t *)d, d7u32, 0);
|
||||
d += dst_stride;
|
||||
d7u32 = vld1_lane_u32((const uint32_t *)d, d7u32, 1);
|
||||
d -= dst_stride * 3;
|
||||
|
||||
d16s16 = vreinterpret_s16_u16(vget_low_u16(q8u16));
|
||||
d17s16 = vreinterpret_s16_u16(vget_high_u16(q8u16));
|
||||
d20s16 = vreinterpret_s16_u16(vget_low_u16(q10u16));
|
||||
d21s16 = vreinterpret_s16_u16(vget_high_u16(q10u16));
|
||||
d24s16 = vreinterpret_s16_u16(vget_low_u16(q12u16));
|
||||
d25s16 = vreinterpret_s16_u16(vget_high_u16(q12u16));
|
||||
d26s16 = vreinterpret_s16_u16(vget_low_u16(q13u16));
|
||||
d27s16 = vreinterpret_s16_u16(vget_high_u16(q13u16));
|
||||
|
||||
__builtin_prefetch(s);
|
||||
__builtin_prefetch(s + src_stride);
|
||||
q1s32 = MULTIPLY_BY_Q0(d16s16, d17s16, d18s16, d19s16, d20s16, d21s16,
|
||||
d22s16, d24s16, q0s16);
|
||||
__builtin_prefetch(s + src_stride * 2);
|
||||
__builtin_prefetch(s + src_stride * 3);
|
||||
q2s32 = MULTIPLY_BY_Q0(d17s16, d18s16, d19s16, d20s16, d21s16, d22s16,
|
||||
d24s16, d26s16, q0s16);
|
||||
__builtin_prefetch(d);
|
||||
__builtin_prefetch(d + dst_stride);
|
||||
q14s32 = MULTIPLY_BY_Q0(d18s16, d19s16, d20s16, d21s16, d22s16, d24s16,
|
||||
d26s16, d27s16, q0s16);
|
||||
__builtin_prefetch(d + dst_stride * 2);
|
||||
__builtin_prefetch(d + dst_stride * 3);
|
||||
q15s32 = MULTIPLY_BY_Q0(d19s16, d20s16, d21s16, d22s16, d24s16, d26s16,
|
||||
d27s16, d25s16, q0s16);
|
||||
|
||||
d2u16 = vqrshrun_n_s32(q1s32, 7);
|
||||
d3u16 = vqrshrun_n_s32(q2s32, 7);
|
||||
d4u16 = vqrshrun_n_s32(q14s32, 7);
|
||||
d5u16 = vqrshrun_n_s32(q15s32, 7);
|
||||
|
||||
q1u16 = vcombine_u16(d2u16, d3u16);
|
||||
q2u16 = vcombine_u16(d4u16, d5u16);
|
||||
|
||||
d2u8 = vqmovn_u16(q1u16);
|
||||
d3u8 = vqmovn_u16(q2u16);
|
||||
|
||||
q1u8 = vcombine_u8(d2u8, d3u8);
|
||||
q3u8 = vreinterpretq_u8_u32(vcombine_u32(d6u32, d7u32));
|
||||
|
||||
q1u8 = vrhaddq_u8(q1u8, q3u8);
|
||||
|
||||
d2u32 = vreinterpret_u32_u8(vget_low_u8(q1u8));
|
||||
d3u32 = vreinterpret_u32_u8(vget_high_u8(q1u8));
|
||||
|
||||
vst1_lane_u32((uint32_t *)d, d2u32, 0);
|
||||
d += dst_stride;
|
||||
vst1_lane_u32((uint32_t *)d, d2u32, 1);
|
||||
d += dst_stride;
|
||||
vst1_lane_u32((uint32_t *)d, d3u32, 0);
|
||||
d += dst_stride;
|
||||
vst1_lane_u32((uint32_t *)d, d3u32, 1);
|
||||
d += dst_stride;
|
||||
|
||||
q8u16 = q10u16;
|
||||
d18s16 = d22s16;
|
||||
d19s16 = d24s16;
|
||||
q10u16 = q13u16;
|
||||
d22s16 = d25s16;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
295
third_party/aom/aom_dsp/arm/aom_convolve8_avg_neon_asm.asm
vendored
Normal file
295
third_party/aom/aom_dsp/arm/aom_convolve8_avg_neon_asm.asm
vendored
Normal file
|
|
@ -0,0 +1,295 @@
|
|||
;
|
||||
; Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
;
|
||||
; This source code is subject to the terms of the BSD 2 Clause License and
|
||||
; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
; was not distributed with this source code in the LICENSE file, you can
|
||||
; obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
; Media Patent License 1.0 was not distributed with this source code in the
|
||||
; PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
;
|
||||
|
||||
;
|
||||
|
||||
|
||||
; These functions are only valid when:
|
||||
; x_step_q4 == 16
|
||||
; w%4 == 0
|
||||
; h%4 == 0
|
||||
; taps == 8
|
||||
; AV1_FILTER_WEIGHT == 128
|
||||
; AV1_FILTER_SHIFT == 7
|
||||
|
||||
EXPORT |aom_convolve8_avg_horiz_neon|
|
||||
EXPORT |aom_convolve8_avg_vert_neon|
|
||||
ARM
|
||||
REQUIRE8
|
||||
PRESERVE8
|
||||
|
||||
AREA ||.text||, CODE, READONLY, ALIGN=2
|
||||
|
||||
; Multiply and accumulate by q0
|
||||
MACRO
|
||||
MULTIPLY_BY_Q0 $dst, $src0, $src1, $src2, $src3, $src4, $src5, $src6, $src7
|
||||
vmull.s16 $dst, $src0, d0[0]
|
||||
vmlal.s16 $dst, $src1, d0[1]
|
||||
vmlal.s16 $dst, $src2, d0[2]
|
||||
vmlal.s16 $dst, $src3, d0[3]
|
||||
vmlal.s16 $dst, $src4, d1[0]
|
||||
vmlal.s16 $dst, $src5, d1[1]
|
||||
vmlal.s16 $dst, $src6, d1[2]
|
||||
vmlal.s16 $dst, $src7, d1[3]
|
||||
MEND
|
||||
|
||||
; r0 const uint8_t *src
|
||||
; r1 int src_stride
|
||||
; r2 uint8_t *dst
|
||||
; r3 int dst_stride
|
||||
; sp[]const int16_t *filter_x
|
||||
; sp[]int x_step_q4
|
||||
; sp[]const int16_t *filter_y ; unused
|
||||
; sp[]int y_step_q4 ; unused
|
||||
; sp[]int w
|
||||
; sp[]int h
|
||||
|
||||
|aom_convolve8_avg_horiz_neon| PROC
|
||||
push {r4-r10, lr}
|
||||
|
||||
sub r0, r0, #3 ; adjust for taps
|
||||
|
||||
ldr r5, [sp, #32] ; filter_x
|
||||
ldr r6, [sp, #48] ; w
|
||||
ldr r7, [sp, #52] ; h
|
||||
|
||||
vld1.s16 {q0}, [r5] ; filter_x
|
||||
|
||||
sub r8, r1, r1, lsl #2 ; -src_stride * 3
|
||||
add r8, r8, #4 ; -src_stride * 3 + 4
|
||||
|
||||
sub r4, r3, r3, lsl #2 ; -dst_stride * 3
|
||||
add r4, r4, #4 ; -dst_stride * 3 + 4
|
||||
|
||||
rsb r9, r6, r1, lsl #2 ; reset src for outer loop
|
||||
sub r9, r9, #7
|
||||
rsb r12, r6, r3, lsl #2 ; reset dst for outer loop
|
||||
|
||||
mov r10, r6 ; w loop counter
|
||||
|
||||
aom_convolve8_avg_loop_horiz_v
|
||||
vld1.8 {d24}, [r0], r1
|
||||
vld1.8 {d25}, [r0], r1
|
||||
vld1.8 {d26}, [r0], r1
|
||||
vld1.8 {d27}, [r0], r8
|
||||
|
||||
vtrn.16 q12, q13
|
||||
vtrn.8 d24, d25
|
||||
vtrn.8 d26, d27
|
||||
|
||||
pld [r0, r1, lsl #2]
|
||||
|
||||
vmovl.u8 q8, d24
|
||||
vmovl.u8 q9, d25
|
||||
vmovl.u8 q10, d26
|
||||
vmovl.u8 q11, d27
|
||||
|
||||
; save a few instructions in the inner loop
|
||||
vswp d17, d18
|
||||
vmov d23, d21
|
||||
|
||||
add r0, r0, #3
|
||||
|
||||
aom_convolve8_avg_loop_horiz
|
||||
add r5, r0, #64
|
||||
|
||||
vld1.32 {d28[]}, [r0], r1
|
||||
vld1.32 {d29[]}, [r0], r1
|
||||
vld1.32 {d31[]}, [r0], r1
|
||||
vld1.32 {d30[]}, [r0], r8
|
||||
|
||||
pld [r5]
|
||||
|
||||
vtrn.16 d28, d31
|
||||
vtrn.16 d29, d30
|
||||
vtrn.8 d28, d29
|
||||
vtrn.8 d31, d30
|
||||
|
||||
pld [r5, r1]
|
||||
|
||||
; extract to s16
|
||||
vtrn.32 q14, q15
|
||||
vmovl.u8 q12, d28
|
||||
vmovl.u8 q13, d29
|
||||
|
||||
pld [r5, r1, lsl #1]
|
||||
|
||||
; slightly out of order load to match the existing data
|
||||
vld1.u32 {d6[0]}, [r2], r3
|
||||
vld1.u32 {d7[0]}, [r2], r3
|
||||
vld1.u32 {d6[1]}, [r2], r3
|
||||
vld1.u32 {d7[1]}, [r2], r3
|
||||
|
||||
sub r2, r2, r3, lsl #2 ; reset for store
|
||||
|
||||
; src[] * filter_x
|
||||
MULTIPLY_BY_Q0 q1, d16, d17, d20, d22, d18, d19, d23, d24
|
||||
MULTIPLY_BY_Q0 q2, d17, d20, d22, d18, d19, d23, d24, d26
|
||||
MULTIPLY_BY_Q0 q14, d20, d22, d18, d19, d23, d24, d26, d27
|
||||
MULTIPLY_BY_Q0 q15, d22, d18, d19, d23, d24, d26, d27, d25
|
||||
|
||||
pld [r5, -r8]
|
||||
|
||||
; += 64 >> 7
|
||||
vqrshrun.s32 d2, q1, #7
|
||||
vqrshrun.s32 d3, q2, #7
|
||||
vqrshrun.s32 d4, q14, #7
|
||||
vqrshrun.s32 d5, q15, #7
|
||||
|
||||
; saturate
|
||||
vqmovn.u16 d2, q1
|
||||
vqmovn.u16 d3, q2
|
||||
|
||||
; transpose
|
||||
vtrn.16 d2, d3
|
||||
vtrn.32 d2, d3
|
||||
vtrn.8 d2, d3
|
||||
|
||||
; average the new value and the dst value
|
||||
vrhadd.u8 q1, q1, q3
|
||||
|
||||
vst1.u32 {d2[0]}, [r2@32], r3
|
||||
vst1.u32 {d3[0]}, [r2@32], r3
|
||||
vst1.u32 {d2[1]}, [r2@32], r3
|
||||
vst1.u32 {d3[1]}, [r2@32], r4
|
||||
|
||||
vmov q8, q9
|
||||
vmov d20, d23
|
||||
vmov q11, q12
|
||||
vmov q9, q13
|
||||
|
||||
subs r6, r6, #4 ; w -= 4
|
||||
bgt aom_convolve8_avg_loop_horiz
|
||||
|
||||
; outer loop
|
||||
mov r6, r10 ; restore w counter
|
||||
add r0, r0, r9 ; src += src_stride * 4 - w
|
||||
add r2, r2, r12 ; dst += dst_stride * 4 - w
|
||||
subs r7, r7, #4 ; h -= 4
|
||||
bgt aom_convolve8_avg_loop_horiz_v
|
||||
|
||||
pop {r4-r10, pc}
|
||||
|
||||
ENDP
|
||||
|
||||
|aom_convolve8_avg_vert_neon| PROC
|
||||
push {r4-r8, lr}
|
||||
|
||||
; adjust for taps
|
||||
sub r0, r0, r1
|
||||
sub r0, r0, r1, lsl #1
|
||||
|
||||
ldr r4, [sp, #32] ; filter_y
|
||||
ldr r6, [sp, #40] ; w
|
||||
ldr lr, [sp, #44] ; h
|
||||
|
||||
vld1.s16 {q0}, [r4] ; filter_y
|
||||
|
||||
lsl r1, r1, #1
|
||||
lsl r3, r3, #1
|
||||
|
||||
aom_convolve8_avg_loop_vert_h
|
||||
mov r4, r0
|
||||
add r7, r0, r1, asr #1
|
||||
mov r5, r2
|
||||
add r8, r2, r3, asr #1
|
||||
mov r12, lr ; h loop counter
|
||||
|
||||
vld1.u32 {d16[0]}, [r4], r1
|
||||
vld1.u32 {d16[1]}, [r7], r1
|
||||
vld1.u32 {d18[0]}, [r4], r1
|
||||
vld1.u32 {d18[1]}, [r7], r1
|
||||
vld1.u32 {d20[0]}, [r4], r1
|
||||
vld1.u32 {d20[1]}, [r7], r1
|
||||
vld1.u32 {d22[0]}, [r4], r1
|
||||
|
||||
vmovl.u8 q8, d16
|
||||
vmovl.u8 q9, d18
|
||||
vmovl.u8 q10, d20
|
||||
vmovl.u8 q11, d22
|
||||
|
||||
aom_convolve8_avg_loop_vert
|
||||
; always process a 4x4 block at a time
|
||||
vld1.u32 {d24[0]}, [r7], r1
|
||||
vld1.u32 {d26[0]}, [r4], r1
|
||||
vld1.u32 {d26[1]}, [r7], r1
|
||||
vld1.u32 {d24[1]}, [r4], r1
|
||||
|
||||
; extract to s16
|
||||
vmovl.u8 q12, d24
|
||||
vmovl.u8 q13, d26
|
||||
|
||||
vld1.u32 {d6[0]}, [r5@32], r3
|
||||
vld1.u32 {d6[1]}, [r8@32], r3
|
||||
vld1.u32 {d7[0]}, [r5@32], r3
|
||||
vld1.u32 {d7[1]}, [r8@32], r3
|
||||
|
||||
pld [r7]
|
||||
pld [r4]
|
||||
|
||||
; src[] * filter_y
|
||||
MULTIPLY_BY_Q0 q1, d16, d17, d18, d19, d20, d21, d22, d24
|
||||
|
||||
pld [r7, r1]
|
||||
pld [r4, r1]
|
||||
|
||||
MULTIPLY_BY_Q0 q2, d17, d18, d19, d20, d21, d22, d24, d26
|
||||
|
||||
pld [r5]
|
||||
pld [r8]
|
||||
|
||||
MULTIPLY_BY_Q0 q14, d18, d19, d20, d21, d22, d24, d26, d27
|
||||
|
||||
pld [r5, r3]
|
||||
pld [r8, r3]
|
||||
|
||||
MULTIPLY_BY_Q0 q15, d19, d20, d21, d22, d24, d26, d27, d25
|
||||
|
||||
; += 64 >> 7
|
||||
vqrshrun.s32 d2, q1, #7
|
||||
vqrshrun.s32 d3, q2, #7
|
||||
vqrshrun.s32 d4, q14, #7
|
||||
vqrshrun.s32 d5, q15, #7
|
||||
|
||||
; saturate
|
||||
vqmovn.u16 d2, q1
|
||||
vqmovn.u16 d3, q2
|
||||
|
||||
; average the new value and the dst value
|
||||
vrhadd.u8 q1, q1, q3
|
||||
|
||||
sub r5, r5, r3, lsl #1 ; reset for store
|
||||
sub r8, r8, r3, lsl #1
|
||||
|
||||
vst1.u32 {d2[0]}, [r5@32], r3
|
||||
vst1.u32 {d2[1]}, [r8@32], r3
|
||||
vst1.u32 {d3[0]}, [r5@32], r3
|
||||
vst1.u32 {d3[1]}, [r8@32], r3
|
||||
|
||||
vmov q8, q10
|
||||
vmov d18, d22
|
||||
vmov d19, d24
|
||||
vmov q10, q13
|
||||
vmov d22, d25
|
||||
|
||||
subs r12, r12, #4 ; h -= 4
|
||||
bgt aom_convolve8_avg_loop_vert
|
||||
|
||||
; outer loop
|
||||
add r0, r0, #4
|
||||
add r2, r2, #4
|
||||
subs r6, r6, #4 ; w -= 4
|
||||
bgt aom_convolve8_avg_loop_vert_h
|
||||
|
||||
pop {r4-r8, pc}
|
||||
|
||||
ENDP
|
||||
END
|
||||
331
third_party/aom/aom_dsp/arm/aom_convolve8_neon.c
vendored
Normal file
331
third_party/aom/aom_dsp/arm/aom_convolve8_neon.c
vendored
Normal file
|
|
@ -0,0 +1,331 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <arm_neon.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "./aom_config.h"
|
||||
#include "./aom_dsp_rtcd.h"
|
||||
#include "aom/aom_integer.h"
|
||||
#include "aom_ports/mem.h"
|
||||
|
||||
static INLINE int32x4_t MULTIPLY_BY_Q0(int16x4_t dsrc0, int16x4_t dsrc1,
|
||||
int16x4_t dsrc2, int16x4_t dsrc3,
|
||||
int16x4_t dsrc4, int16x4_t dsrc5,
|
||||
int16x4_t dsrc6, int16x4_t dsrc7,
|
||||
int16x8_t q0s16) {
|
||||
int32x4_t qdst;
|
||||
int16x4_t d0s16, d1s16;
|
||||
|
||||
d0s16 = vget_low_s16(q0s16);
|
||||
d1s16 = vget_high_s16(q0s16);
|
||||
|
||||
qdst = vmull_lane_s16(dsrc0, d0s16, 0);
|
||||
qdst = vmlal_lane_s16(qdst, dsrc1, d0s16, 1);
|
||||
qdst = vmlal_lane_s16(qdst, dsrc2, d0s16, 2);
|
||||
qdst = vmlal_lane_s16(qdst, dsrc3, d0s16, 3);
|
||||
qdst = vmlal_lane_s16(qdst, dsrc4, d1s16, 0);
|
||||
qdst = vmlal_lane_s16(qdst, dsrc5, d1s16, 1);
|
||||
qdst = vmlal_lane_s16(qdst, dsrc6, d1s16, 2);
|
||||
qdst = vmlal_lane_s16(qdst, dsrc7, d1s16, 3);
|
||||
return qdst;
|
||||
}
|
||||
|
||||
void aom_convolve8_horiz_neon(const uint8_t *src, ptrdiff_t src_stride,
|
||||
uint8_t *dst, ptrdiff_t dst_stride,
|
||||
const int16_t *filter_x, int x_step_q4,
|
||||
const int16_t *filter_y, // unused
|
||||
int y_step_q4, // unused
|
||||
int w, int h) {
|
||||
int width;
|
||||
const uint8_t *s, *psrc;
|
||||
uint8_t *d, *pdst;
|
||||
uint8x8_t d2u8, d3u8, d24u8, d25u8, d26u8, d27u8, d28u8, d29u8;
|
||||
uint32x2_t d2u32, d3u32, d28u32, d29u32, d30u32, d31u32;
|
||||
uint8x16_t q12u8, q13u8, q14u8, q15u8;
|
||||
int16x4_t d16s16, d17s16, d18s16, d19s16, d20s16, d22s16, d23s16;
|
||||
int16x4_t d24s16, d25s16, d26s16, d27s16;
|
||||
uint16x4_t d2u16, d3u16, d4u16, d5u16, d16u16, d17u16, d18u16, d19u16;
|
||||
int16x8_t q0s16;
|
||||
uint16x8_t q1u16, q2u16, q8u16, q9u16, q10u16, q11u16, q12u16, q13u16;
|
||||
int32x4_t q1s32, q2s32, q14s32, q15s32;
|
||||
uint16x8x2_t q0x2u16;
|
||||
uint8x8x2_t d0x2u8, d1x2u8;
|
||||
uint32x2x2_t d0x2u32;
|
||||
uint16x4x2_t d0x2u16, d1x2u16;
|
||||
uint32x4x2_t q0x2u32;
|
||||
|
||||
assert(x_step_q4 == 16);
|
||||
|
||||
(void)x_step_q4;
|
||||
(void)y_step_q4;
|
||||
(void)filter_y;
|
||||
|
||||
q0s16 = vld1q_s16(filter_x);
|
||||
|
||||
src -= 3; // adjust for taps
|
||||
for (; h > 0; h -= 4, src += src_stride * 4,
|
||||
dst += dst_stride * 4) { // loop_horiz_v
|
||||
s = src;
|
||||
d24u8 = vld1_u8(s);
|
||||
s += src_stride;
|
||||
d25u8 = vld1_u8(s);
|
||||
s += src_stride;
|
||||
d26u8 = vld1_u8(s);
|
||||
s += src_stride;
|
||||
d27u8 = vld1_u8(s);
|
||||
|
||||
q12u8 = vcombine_u8(d24u8, d25u8);
|
||||
q13u8 = vcombine_u8(d26u8, d27u8);
|
||||
|
||||
q0x2u16 =
|
||||
vtrnq_u16(vreinterpretq_u16_u8(q12u8), vreinterpretq_u16_u8(q13u8));
|
||||
d24u8 = vreinterpret_u8_u16(vget_low_u16(q0x2u16.val[0]));
|
||||
d25u8 = vreinterpret_u8_u16(vget_high_u16(q0x2u16.val[0]));
|
||||
d26u8 = vreinterpret_u8_u16(vget_low_u16(q0x2u16.val[1]));
|
||||
d27u8 = vreinterpret_u8_u16(vget_high_u16(q0x2u16.val[1]));
|
||||
d0x2u8 = vtrn_u8(d24u8, d25u8);
|
||||
d1x2u8 = vtrn_u8(d26u8, d27u8);
|
||||
|
||||
__builtin_prefetch(src + src_stride * 4);
|
||||
__builtin_prefetch(src + src_stride * 5);
|
||||
__builtin_prefetch(src + src_stride * 6);
|
||||
|
||||
q8u16 = vmovl_u8(d0x2u8.val[0]);
|
||||
q9u16 = vmovl_u8(d0x2u8.val[1]);
|
||||
q10u16 = vmovl_u8(d1x2u8.val[0]);
|
||||
q11u16 = vmovl_u8(d1x2u8.val[1]);
|
||||
|
||||
d16u16 = vget_low_u16(q8u16);
|
||||
d17u16 = vget_high_u16(q8u16);
|
||||
d18u16 = vget_low_u16(q9u16);
|
||||
d19u16 = vget_high_u16(q9u16);
|
||||
q8u16 = vcombine_u16(d16u16, d18u16); // vswp 17 18
|
||||
q9u16 = vcombine_u16(d17u16, d19u16);
|
||||
|
||||
d20s16 = vreinterpret_s16_u16(vget_low_u16(q10u16));
|
||||
d23s16 = vreinterpret_s16_u16(vget_high_u16(q10u16)); // vmov 23 21
|
||||
for (width = w, psrc = src + 7, pdst = dst; width > 0;
|
||||
width -= 4, psrc += 4, pdst += 4) { // loop_horiz
|
||||
s = psrc;
|
||||
d28u32 = vld1_dup_u32((const uint32_t *)s);
|
||||
s += src_stride;
|
||||
d29u32 = vld1_dup_u32((const uint32_t *)s);
|
||||
s += src_stride;
|
||||
d31u32 = vld1_dup_u32((const uint32_t *)s);
|
||||
s += src_stride;
|
||||
d30u32 = vld1_dup_u32((const uint32_t *)s);
|
||||
|
||||
__builtin_prefetch(psrc + 64);
|
||||
|
||||
d0x2u16 =
|
||||
vtrn_u16(vreinterpret_u16_u32(d28u32), vreinterpret_u16_u32(d31u32));
|
||||
d1x2u16 =
|
||||
vtrn_u16(vreinterpret_u16_u32(d29u32), vreinterpret_u16_u32(d30u32));
|
||||
d0x2u8 = vtrn_u8(vreinterpret_u8_u16(d0x2u16.val[0]), // d28
|
||||
vreinterpret_u8_u16(d1x2u16.val[0])); // d29
|
||||
d1x2u8 = vtrn_u8(vreinterpret_u8_u16(d0x2u16.val[1]), // d31
|
||||
vreinterpret_u8_u16(d1x2u16.val[1])); // d30
|
||||
|
||||
__builtin_prefetch(psrc + 64 + src_stride);
|
||||
|
||||
q14u8 = vcombine_u8(d0x2u8.val[0], d0x2u8.val[1]);
|
||||
q15u8 = vcombine_u8(d1x2u8.val[1], d1x2u8.val[0]);
|
||||
q0x2u32 =
|
||||
vtrnq_u32(vreinterpretq_u32_u8(q14u8), vreinterpretq_u32_u8(q15u8));
|
||||
|
||||
d28u8 = vreinterpret_u8_u32(vget_low_u32(q0x2u32.val[0]));
|
||||
d29u8 = vreinterpret_u8_u32(vget_high_u32(q0x2u32.val[0]));
|
||||
q12u16 = vmovl_u8(d28u8);
|
||||
q13u16 = vmovl_u8(d29u8);
|
||||
|
||||
__builtin_prefetch(psrc + 64 + src_stride * 2);
|
||||
|
||||
d16s16 = vreinterpret_s16_u16(vget_low_u16(q8u16));
|
||||
d17s16 = vreinterpret_s16_u16(vget_high_u16(q8u16));
|
||||
d18s16 = vreinterpret_s16_u16(vget_low_u16(q9u16));
|
||||
d19s16 = vreinterpret_s16_u16(vget_high_u16(q9u16));
|
||||
d22s16 = vreinterpret_s16_u16(vget_low_u16(q11u16));
|
||||
d24s16 = vreinterpret_s16_u16(vget_low_u16(q12u16));
|
||||
d25s16 = vreinterpret_s16_u16(vget_high_u16(q12u16));
|
||||
d26s16 = vreinterpret_s16_u16(vget_low_u16(q13u16));
|
||||
d27s16 = vreinterpret_s16_u16(vget_high_u16(q13u16));
|
||||
|
||||
q1s32 = MULTIPLY_BY_Q0(d16s16, d17s16, d20s16, d22s16, d18s16, d19s16,
|
||||
d23s16, d24s16, q0s16);
|
||||
q2s32 = MULTIPLY_BY_Q0(d17s16, d20s16, d22s16, d18s16, d19s16, d23s16,
|
||||
d24s16, d26s16, q0s16);
|
||||
q14s32 = MULTIPLY_BY_Q0(d20s16, d22s16, d18s16, d19s16, d23s16, d24s16,
|
||||
d26s16, d27s16, q0s16);
|
||||
q15s32 = MULTIPLY_BY_Q0(d22s16, d18s16, d19s16, d23s16, d24s16, d26s16,
|
||||
d27s16, d25s16, q0s16);
|
||||
|
||||
__builtin_prefetch(psrc + 60 + src_stride * 3);
|
||||
|
||||
d2u16 = vqrshrun_n_s32(q1s32, 7);
|
||||
d3u16 = vqrshrun_n_s32(q2s32, 7);
|
||||
d4u16 = vqrshrun_n_s32(q14s32, 7);
|
||||
d5u16 = vqrshrun_n_s32(q15s32, 7);
|
||||
|
||||
q1u16 = vcombine_u16(d2u16, d3u16);
|
||||
q2u16 = vcombine_u16(d4u16, d5u16);
|
||||
|
||||
d2u8 = vqmovn_u16(q1u16);
|
||||
d3u8 = vqmovn_u16(q2u16);
|
||||
|
||||
d0x2u16 = vtrn_u16(vreinterpret_u16_u8(d2u8), vreinterpret_u16_u8(d3u8));
|
||||
d0x2u32 = vtrn_u32(vreinterpret_u32_u16(d0x2u16.val[0]),
|
||||
vreinterpret_u32_u16(d0x2u16.val[1]));
|
||||
d0x2u8 = vtrn_u8(vreinterpret_u8_u32(d0x2u32.val[0]),
|
||||
vreinterpret_u8_u32(d0x2u32.val[1]));
|
||||
|
||||
d2u32 = vreinterpret_u32_u8(d0x2u8.val[0]);
|
||||
d3u32 = vreinterpret_u32_u8(d0x2u8.val[1]);
|
||||
|
||||
d = pdst;
|
||||
vst1_lane_u32((uint32_t *)d, d2u32, 0);
|
||||
d += dst_stride;
|
||||
vst1_lane_u32((uint32_t *)d, d3u32, 0);
|
||||
d += dst_stride;
|
||||
vst1_lane_u32((uint32_t *)d, d2u32, 1);
|
||||
d += dst_stride;
|
||||
vst1_lane_u32((uint32_t *)d, d3u32, 1);
|
||||
|
||||
q8u16 = q9u16;
|
||||
d20s16 = d23s16;
|
||||
q11u16 = q12u16;
|
||||
q9u16 = q13u16;
|
||||
d23s16 = vreinterpret_s16_u16(vget_high_u16(q11u16));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void aom_convolve8_vert_neon(const uint8_t *src, ptrdiff_t src_stride,
|
||||
uint8_t *dst, ptrdiff_t dst_stride,
|
||||
const int16_t *filter_x, // unused
|
||||
int x_step_q4, // unused
|
||||
const int16_t *filter_y, int y_step_q4, int w,
|
||||
int h) {
|
||||
int height;
|
||||
const uint8_t *s;
|
||||
uint8_t *d;
|
||||
uint32x2_t d2u32, d3u32;
|
||||
uint32x2_t d16u32, d18u32, d20u32, d22u32, d24u32, d26u32;
|
||||
int16x4_t d16s16, d17s16, d18s16, d19s16, d20s16, d21s16, d22s16;
|
||||
int16x4_t d24s16, d25s16, d26s16, d27s16;
|
||||
uint16x4_t d2u16, d3u16, d4u16, d5u16;
|
||||
int16x8_t q0s16;
|
||||
uint16x8_t q1u16, q2u16, q8u16, q9u16, q10u16, q11u16, q12u16, q13u16;
|
||||
int32x4_t q1s32, q2s32, q14s32, q15s32;
|
||||
|
||||
assert(y_step_q4 == 16);
|
||||
|
||||
(void)x_step_q4;
|
||||
(void)y_step_q4;
|
||||
(void)filter_x;
|
||||
|
||||
src -= src_stride * 3;
|
||||
q0s16 = vld1q_s16(filter_y);
|
||||
for (; w > 0; w -= 4, src += 4, dst += 4) { // loop_vert_h
|
||||
s = src;
|
||||
d16u32 = vld1_lane_u32((const uint32_t *)s, d16u32, 0);
|
||||
s += src_stride;
|
||||
d16u32 = vld1_lane_u32((const uint32_t *)s, d16u32, 1);
|
||||
s += src_stride;
|
||||
d18u32 = vld1_lane_u32((const uint32_t *)s, d18u32, 0);
|
||||
s += src_stride;
|
||||
d18u32 = vld1_lane_u32((const uint32_t *)s, d18u32, 1);
|
||||
s += src_stride;
|
||||
d20u32 = vld1_lane_u32((const uint32_t *)s, d20u32, 0);
|
||||
s += src_stride;
|
||||
d20u32 = vld1_lane_u32((const uint32_t *)s, d20u32, 1);
|
||||
s += src_stride;
|
||||
d22u32 = vld1_lane_u32((const uint32_t *)s, d22u32, 0);
|
||||
s += src_stride;
|
||||
|
||||
q8u16 = vmovl_u8(vreinterpret_u8_u32(d16u32));
|
||||
q9u16 = vmovl_u8(vreinterpret_u8_u32(d18u32));
|
||||
q10u16 = vmovl_u8(vreinterpret_u8_u32(d20u32));
|
||||
q11u16 = vmovl_u8(vreinterpret_u8_u32(d22u32));
|
||||
|
||||
d18s16 = vreinterpret_s16_u16(vget_low_u16(q9u16));
|
||||
d19s16 = vreinterpret_s16_u16(vget_high_u16(q9u16));
|
||||
d22s16 = vreinterpret_s16_u16(vget_low_u16(q11u16));
|
||||
d = dst;
|
||||
for (height = h; height > 0; height -= 4) { // loop_vert
|
||||
d24u32 = vld1_lane_u32((const uint32_t *)s, d24u32, 0);
|
||||
s += src_stride;
|
||||
d26u32 = vld1_lane_u32((const uint32_t *)s, d26u32, 0);
|
||||
s += src_stride;
|
||||
d26u32 = vld1_lane_u32((const uint32_t *)s, d26u32, 1);
|
||||
s += src_stride;
|
||||
d24u32 = vld1_lane_u32((const uint32_t *)s, d24u32, 1);
|
||||
s += src_stride;
|
||||
|
||||
q12u16 = vmovl_u8(vreinterpret_u8_u32(d24u32));
|
||||
q13u16 = vmovl_u8(vreinterpret_u8_u32(d26u32));
|
||||
|
||||
d16s16 = vreinterpret_s16_u16(vget_low_u16(q8u16));
|
||||
d17s16 = vreinterpret_s16_u16(vget_high_u16(q8u16));
|
||||
d20s16 = vreinterpret_s16_u16(vget_low_u16(q10u16));
|
||||
d21s16 = vreinterpret_s16_u16(vget_high_u16(q10u16));
|
||||
d24s16 = vreinterpret_s16_u16(vget_low_u16(q12u16));
|
||||
d25s16 = vreinterpret_s16_u16(vget_high_u16(q12u16));
|
||||
d26s16 = vreinterpret_s16_u16(vget_low_u16(q13u16));
|
||||
d27s16 = vreinterpret_s16_u16(vget_high_u16(q13u16));
|
||||
|
||||
__builtin_prefetch(d);
|
||||
__builtin_prefetch(d + dst_stride);
|
||||
q1s32 = MULTIPLY_BY_Q0(d16s16, d17s16, d18s16, d19s16, d20s16, d21s16,
|
||||
d22s16, d24s16, q0s16);
|
||||
__builtin_prefetch(d + dst_stride * 2);
|
||||
__builtin_prefetch(d + dst_stride * 3);
|
||||
q2s32 = MULTIPLY_BY_Q0(d17s16, d18s16, d19s16, d20s16, d21s16, d22s16,
|
||||
d24s16, d26s16, q0s16);
|
||||
__builtin_prefetch(s);
|
||||
__builtin_prefetch(s + src_stride);
|
||||
q14s32 = MULTIPLY_BY_Q0(d18s16, d19s16, d20s16, d21s16, d22s16, d24s16,
|
||||
d26s16, d27s16, q0s16);
|
||||
__builtin_prefetch(s + src_stride * 2);
|
||||
__builtin_prefetch(s + src_stride * 3);
|
||||
q15s32 = MULTIPLY_BY_Q0(d19s16, d20s16, d21s16, d22s16, d24s16, d26s16,
|
||||
d27s16, d25s16, q0s16);
|
||||
|
||||
d2u16 = vqrshrun_n_s32(q1s32, 7);
|
||||
d3u16 = vqrshrun_n_s32(q2s32, 7);
|
||||
d4u16 = vqrshrun_n_s32(q14s32, 7);
|
||||
d5u16 = vqrshrun_n_s32(q15s32, 7);
|
||||
|
||||
q1u16 = vcombine_u16(d2u16, d3u16);
|
||||
q2u16 = vcombine_u16(d4u16, d5u16);
|
||||
|
||||
d2u32 = vreinterpret_u32_u8(vqmovn_u16(q1u16));
|
||||
d3u32 = vreinterpret_u32_u8(vqmovn_u16(q2u16));
|
||||
|
||||
vst1_lane_u32((uint32_t *)d, d2u32, 0);
|
||||
d += dst_stride;
|
||||
vst1_lane_u32((uint32_t *)d, d2u32, 1);
|
||||
d += dst_stride;
|
||||
vst1_lane_u32((uint32_t *)d, d3u32, 0);
|
||||
d += dst_stride;
|
||||
vst1_lane_u32((uint32_t *)d, d3u32, 1);
|
||||
d += dst_stride;
|
||||
|
||||
q8u16 = q10u16;
|
||||
d18s16 = d22s16;
|
||||
d19s16 = d24s16;
|
||||
q10u16 = q13u16;
|
||||
d22s16 = d25s16;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
273
third_party/aom/aom_dsp/arm/aom_convolve8_neon_asm.asm
vendored
Normal file
273
third_party/aom/aom_dsp/arm/aom_convolve8_neon_asm.asm
vendored
Normal file
|
|
@ -0,0 +1,273 @@
|
|||
;
|
||||
; Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
;
|
||||
; This source code is subject to the terms of the BSD 2 Clause License and
|
||||
; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
; was not distributed with this source code in the LICENSE file, you can
|
||||
; obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
; Media Patent License 1.0 was not distributed with this source code in the
|
||||
; PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
;
|
||||
|
||||
;
|
||||
|
||||
|
||||
; These functions are only valid when:
|
||||
; x_step_q4 == 16
|
||||
; w%4 == 0
|
||||
; h%4 == 0
|
||||
; taps == 8
|
||||
; AV1_FILTER_WEIGHT == 128
|
||||
; AV1_FILTER_SHIFT == 7
|
||||
|
||||
EXPORT |aom_convolve8_horiz_neon|
|
||||
EXPORT |aom_convolve8_vert_neon|
|
||||
ARM
|
||||
REQUIRE8
|
||||
PRESERVE8
|
||||
|
||||
AREA ||.text||, CODE, READONLY, ALIGN=2
|
||||
|
||||
; Multiply and accumulate by q0
|
||||
MACRO
|
||||
MULTIPLY_BY_Q0 $dst, $src0, $src1, $src2, $src3, $src4, $src5, $src6, $src7
|
||||
vmull.s16 $dst, $src0, d0[0]
|
||||
vmlal.s16 $dst, $src1, d0[1]
|
||||
vmlal.s16 $dst, $src2, d0[2]
|
||||
vmlal.s16 $dst, $src3, d0[3]
|
||||
vmlal.s16 $dst, $src4, d1[0]
|
||||
vmlal.s16 $dst, $src5, d1[1]
|
||||
vmlal.s16 $dst, $src6, d1[2]
|
||||
vmlal.s16 $dst, $src7, d1[3]
|
||||
MEND
|
||||
|
||||
; r0 const uint8_t *src
|
||||
; r1 int src_stride
|
||||
; r2 uint8_t *dst
|
||||
; r3 int dst_stride
|
||||
; sp[]const int16_t *filter_x
|
||||
; sp[]int x_step_q4
|
||||
; sp[]const int16_t *filter_y ; unused
|
||||
; sp[]int y_step_q4 ; unused
|
||||
; sp[]int w
|
||||
; sp[]int h
|
||||
|
||||
|aom_convolve8_horiz_neon| PROC
|
||||
push {r4-r10, lr}
|
||||
|
||||
sub r0, r0, #3 ; adjust for taps
|
||||
|
||||
ldr r5, [sp, #32] ; filter_x
|
||||
ldr r6, [sp, #48] ; w
|
||||
ldr r7, [sp, #52] ; h
|
||||
|
||||
vld1.s16 {q0}, [r5] ; filter_x
|
||||
|
||||
sub r8, r1, r1, lsl #2 ; -src_stride * 3
|
||||
add r8, r8, #4 ; -src_stride * 3 + 4
|
||||
|
||||
sub r4, r3, r3, lsl #2 ; -dst_stride * 3
|
||||
add r4, r4, #4 ; -dst_stride * 3 + 4
|
||||
|
||||
rsb r9, r6, r1, lsl #2 ; reset src for outer loop
|
||||
sub r9, r9, #7
|
||||
rsb r12, r6, r3, lsl #2 ; reset dst for outer loop
|
||||
|
||||
mov r10, r6 ; w loop counter
|
||||
|
||||
aom_convolve8_loop_horiz_v
|
||||
vld1.8 {d24}, [r0], r1
|
||||
vld1.8 {d25}, [r0], r1
|
||||
vld1.8 {d26}, [r0], r1
|
||||
vld1.8 {d27}, [r0], r8
|
||||
|
||||
vtrn.16 q12, q13
|
||||
vtrn.8 d24, d25
|
||||
vtrn.8 d26, d27
|
||||
|
||||
pld [r0, r1, lsl #2]
|
||||
|
||||
vmovl.u8 q8, d24
|
||||
vmovl.u8 q9, d25
|
||||
vmovl.u8 q10, d26
|
||||
vmovl.u8 q11, d27
|
||||
|
||||
; save a few instructions in the inner loop
|
||||
vswp d17, d18
|
||||
vmov d23, d21
|
||||
|
||||
add r0, r0, #3
|
||||
|
||||
aom_convolve8_loop_horiz
|
||||
add r5, r0, #64
|
||||
|
||||
vld1.32 {d28[]}, [r0], r1
|
||||
vld1.32 {d29[]}, [r0], r1
|
||||
vld1.32 {d31[]}, [r0], r1
|
||||
vld1.32 {d30[]}, [r0], r8
|
||||
|
||||
pld [r5]
|
||||
|
||||
vtrn.16 d28, d31
|
||||
vtrn.16 d29, d30
|
||||
vtrn.8 d28, d29
|
||||
vtrn.8 d31, d30
|
||||
|
||||
pld [r5, r1]
|
||||
|
||||
; extract to s16
|
||||
vtrn.32 q14, q15
|
||||
vmovl.u8 q12, d28
|
||||
vmovl.u8 q13, d29
|
||||
|
||||
pld [r5, r1, lsl #1]
|
||||
|
||||
; src[] * filter_x
|
||||
MULTIPLY_BY_Q0 q1, d16, d17, d20, d22, d18, d19, d23, d24
|
||||
MULTIPLY_BY_Q0 q2, d17, d20, d22, d18, d19, d23, d24, d26
|
||||
MULTIPLY_BY_Q0 q14, d20, d22, d18, d19, d23, d24, d26, d27
|
||||
MULTIPLY_BY_Q0 q15, d22, d18, d19, d23, d24, d26, d27, d25
|
||||
|
||||
pld [r5, -r8]
|
||||
|
||||
; += 64 >> 7
|
||||
vqrshrun.s32 d2, q1, #7
|
||||
vqrshrun.s32 d3, q2, #7
|
||||
vqrshrun.s32 d4, q14, #7
|
||||
vqrshrun.s32 d5, q15, #7
|
||||
|
||||
; saturate
|
||||
vqmovn.u16 d2, q1
|
||||
vqmovn.u16 d3, q2
|
||||
|
||||
; transpose
|
||||
vtrn.16 d2, d3
|
||||
vtrn.32 d2, d3
|
||||
vtrn.8 d2, d3
|
||||
|
||||
vst1.u32 {d2[0]}, [r2@32], r3
|
||||
vst1.u32 {d3[0]}, [r2@32], r3
|
||||
vst1.u32 {d2[1]}, [r2@32], r3
|
||||
vst1.u32 {d3[1]}, [r2@32], r4
|
||||
|
||||
vmov q8, q9
|
||||
vmov d20, d23
|
||||
vmov q11, q12
|
||||
vmov q9, q13
|
||||
|
||||
subs r6, r6, #4 ; w -= 4
|
||||
bgt aom_convolve8_loop_horiz
|
||||
|
||||
; outer loop
|
||||
mov r6, r10 ; restore w counter
|
||||
add r0, r0, r9 ; src += src_stride * 4 - w
|
||||
add r2, r2, r12 ; dst += dst_stride * 4 - w
|
||||
subs r7, r7, #4 ; h -= 4
|
||||
bgt aom_convolve8_loop_horiz_v
|
||||
|
||||
pop {r4-r10, pc}
|
||||
|
||||
ENDP
|
||||
|
||||
|aom_convolve8_vert_neon| PROC
|
||||
push {r4-r8, lr}
|
||||
|
||||
; adjust for taps
|
||||
sub r0, r0, r1
|
||||
sub r0, r0, r1, lsl #1
|
||||
|
||||
ldr r4, [sp, #32] ; filter_y
|
||||
ldr r6, [sp, #40] ; w
|
||||
ldr lr, [sp, #44] ; h
|
||||
|
||||
vld1.s16 {q0}, [r4] ; filter_y
|
||||
|
||||
lsl r1, r1, #1
|
||||
lsl r3, r3, #1
|
||||
|
||||
aom_convolve8_loop_vert_h
|
||||
mov r4, r0
|
||||
add r7, r0, r1, asr #1
|
||||
mov r5, r2
|
||||
add r8, r2, r3, asr #1
|
||||
mov r12, lr ; h loop counter
|
||||
|
||||
vld1.u32 {d16[0]}, [r4], r1
|
||||
vld1.u32 {d16[1]}, [r7], r1
|
||||
vld1.u32 {d18[0]}, [r4], r1
|
||||
vld1.u32 {d18[1]}, [r7], r1
|
||||
vld1.u32 {d20[0]}, [r4], r1
|
||||
vld1.u32 {d20[1]}, [r7], r1
|
||||
vld1.u32 {d22[0]}, [r4], r1
|
||||
|
||||
vmovl.u8 q8, d16
|
||||
vmovl.u8 q9, d18
|
||||
vmovl.u8 q10, d20
|
||||
vmovl.u8 q11, d22
|
||||
|
||||
aom_convolve8_loop_vert
|
||||
; always process a 4x4 block at a time
|
||||
vld1.u32 {d24[0]}, [r7], r1
|
||||
vld1.u32 {d26[0]}, [r4], r1
|
||||
vld1.u32 {d26[1]}, [r7], r1
|
||||
vld1.u32 {d24[1]}, [r4], r1
|
||||
|
||||
; extract to s16
|
||||
vmovl.u8 q12, d24
|
||||
vmovl.u8 q13, d26
|
||||
|
||||
pld [r5]
|
||||
pld [r8]
|
||||
|
||||
; src[] * filter_y
|
||||
MULTIPLY_BY_Q0 q1, d16, d17, d18, d19, d20, d21, d22, d24
|
||||
|
||||
pld [r5, r3]
|
||||
pld [r8, r3]
|
||||
|
||||
MULTIPLY_BY_Q0 q2, d17, d18, d19, d20, d21, d22, d24, d26
|
||||
|
||||
pld [r7]
|
||||
pld [r4]
|
||||
|
||||
MULTIPLY_BY_Q0 q14, d18, d19, d20, d21, d22, d24, d26, d27
|
||||
|
||||
pld [r7, r1]
|
||||
pld [r4, r1]
|
||||
|
||||
MULTIPLY_BY_Q0 q15, d19, d20, d21, d22, d24, d26, d27, d25
|
||||
|
||||
; += 64 >> 7
|
||||
vqrshrun.s32 d2, q1, #7
|
||||
vqrshrun.s32 d3, q2, #7
|
||||
vqrshrun.s32 d4, q14, #7
|
||||
vqrshrun.s32 d5, q15, #7
|
||||
|
||||
; saturate
|
||||
vqmovn.u16 d2, q1
|
||||
vqmovn.u16 d3, q2
|
||||
|
||||
vst1.u32 {d2[0]}, [r5@32], r3
|
||||
vst1.u32 {d2[1]}, [r8@32], r3
|
||||
vst1.u32 {d3[0]}, [r5@32], r3
|
||||
vst1.u32 {d3[1]}, [r8@32], r3
|
||||
|
||||
vmov q8, q10
|
||||
vmov d18, d22
|
||||
vmov d19, d24
|
||||
vmov q10, q13
|
||||
vmov d22, d25
|
||||
|
||||
subs r12, r12, #4 ; h -= 4
|
||||
bgt aom_convolve8_loop_vert
|
||||
|
||||
; outer loop
|
||||
add r0, r0, #4
|
||||
add r2, r2, #4
|
||||
subs r6, r6, #4 ; w -= 4
|
||||
bgt aom_convolve8_loop_vert_h
|
||||
|
||||
pop {r4-r8, pc}
|
||||
|
||||
ENDP
|
||||
END
|
||||
145
third_party/aom/aom_dsp/arm/aom_convolve_avg_neon.c
vendored
Normal file
145
third_party/aom/aom_dsp/arm/aom_convolve_avg_neon.c
vendored
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <arm_neon.h>
|
||||
|
||||
#include "./aom_dsp_rtcd.h"
|
||||
#include "aom/aom_integer.h"
|
||||
|
||||
void aom_convolve_avg_neon(const uint8_t *src, // r0
|
||||
ptrdiff_t src_stride, // r1
|
||||
uint8_t *dst, // r2
|
||||
ptrdiff_t dst_stride, // r3
|
||||
const int16_t *filter_x, int filter_x_stride,
|
||||
const int16_t *filter_y, int filter_y_stride, int w,
|
||||
int h) {
|
||||
uint8_t *d;
|
||||
uint8x8_t d0u8, d1u8, d2u8, d3u8;
|
||||
uint32x2_t d0u32, d2u32;
|
||||
uint8x16_t q0u8, q1u8, q2u8, q3u8, q8u8, q9u8, q10u8, q11u8;
|
||||
(void)filter_x;
|
||||
(void)filter_x_stride;
|
||||
(void)filter_y;
|
||||
(void)filter_y_stride;
|
||||
|
||||
d = dst;
|
||||
if (w > 32) { // avg64
|
||||
for (; h > 0; h -= 1) {
|
||||
q0u8 = vld1q_u8(src);
|
||||
q1u8 = vld1q_u8(src + 16);
|
||||
q2u8 = vld1q_u8(src + 32);
|
||||
q3u8 = vld1q_u8(src + 48);
|
||||
src += src_stride;
|
||||
q8u8 = vld1q_u8(d);
|
||||
q9u8 = vld1q_u8(d + 16);
|
||||
q10u8 = vld1q_u8(d + 32);
|
||||
q11u8 = vld1q_u8(d + 48);
|
||||
d += dst_stride;
|
||||
|
||||
q0u8 = vrhaddq_u8(q0u8, q8u8);
|
||||
q1u8 = vrhaddq_u8(q1u8, q9u8);
|
||||
q2u8 = vrhaddq_u8(q2u8, q10u8);
|
||||
q3u8 = vrhaddq_u8(q3u8, q11u8);
|
||||
|
||||
vst1q_u8(dst, q0u8);
|
||||
vst1q_u8(dst + 16, q1u8);
|
||||
vst1q_u8(dst + 32, q2u8);
|
||||
vst1q_u8(dst + 48, q3u8);
|
||||
dst += dst_stride;
|
||||
}
|
||||
} else if (w == 32) { // avg32
|
||||
for (; h > 0; h -= 2) {
|
||||
q0u8 = vld1q_u8(src);
|
||||
q1u8 = vld1q_u8(src + 16);
|
||||
src += src_stride;
|
||||
q2u8 = vld1q_u8(src);
|
||||
q3u8 = vld1q_u8(src + 16);
|
||||
src += src_stride;
|
||||
q8u8 = vld1q_u8(d);
|
||||
q9u8 = vld1q_u8(d + 16);
|
||||
d += dst_stride;
|
||||
q10u8 = vld1q_u8(d);
|
||||
q11u8 = vld1q_u8(d + 16);
|
||||
d += dst_stride;
|
||||
|
||||
q0u8 = vrhaddq_u8(q0u8, q8u8);
|
||||
q1u8 = vrhaddq_u8(q1u8, q9u8);
|
||||
q2u8 = vrhaddq_u8(q2u8, q10u8);
|
||||
q3u8 = vrhaddq_u8(q3u8, q11u8);
|
||||
|
||||
vst1q_u8(dst, q0u8);
|
||||
vst1q_u8(dst + 16, q1u8);
|
||||
dst += dst_stride;
|
||||
vst1q_u8(dst, q2u8);
|
||||
vst1q_u8(dst + 16, q3u8);
|
||||
dst += dst_stride;
|
||||
}
|
||||
} else if (w > 8) { // avg16
|
||||
for (; h > 0; h -= 2) {
|
||||
q0u8 = vld1q_u8(src);
|
||||
src += src_stride;
|
||||
q1u8 = vld1q_u8(src);
|
||||
src += src_stride;
|
||||
q2u8 = vld1q_u8(d);
|
||||
d += dst_stride;
|
||||
q3u8 = vld1q_u8(d);
|
||||
d += dst_stride;
|
||||
|
||||
q0u8 = vrhaddq_u8(q0u8, q2u8);
|
||||
q1u8 = vrhaddq_u8(q1u8, q3u8);
|
||||
|
||||
vst1q_u8(dst, q0u8);
|
||||
dst += dst_stride;
|
||||
vst1q_u8(dst, q1u8);
|
||||
dst += dst_stride;
|
||||
}
|
||||
} else if (w == 8) { // avg8
|
||||
for (; h > 0; h -= 2) {
|
||||
d0u8 = vld1_u8(src);
|
||||
src += src_stride;
|
||||
d1u8 = vld1_u8(src);
|
||||
src += src_stride;
|
||||
d2u8 = vld1_u8(d);
|
||||
d += dst_stride;
|
||||
d3u8 = vld1_u8(d);
|
||||
d += dst_stride;
|
||||
|
||||
q0u8 = vcombine_u8(d0u8, d1u8);
|
||||
q1u8 = vcombine_u8(d2u8, d3u8);
|
||||
q0u8 = vrhaddq_u8(q0u8, q1u8);
|
||||
|
||||
vst1_u8(dst, vget_low_u8(q0u8));
|
||||
dst += dst_stride;
|
||||
vst1_u8(dst, vget_high_u8(q0u8));
|
||||
dst += dst_stride;
|
||||
}
|
||||
} else { // avg4
|
||||
for (; h > 0; h -= 2) {
|
||||
d0u32 = vld1_lane_u32((const uint32_t *)src, d0u32, 0);
|
||||
src += src_stride;
|
||||
d0u32 = vld1_lane_u32((const uint32_t *)src, d0u32, 1);
|
||||
src += src_stride;
|
||||
d2u32 = vld1_lane_u32((const uint32_t *)d, d2u32, 0);
|
||||
d += dst_stride;
|
||||
d2u32 = vld1_lane_u32((const uint32_t *)d, d2u32, 1);
|
||||
d += dst_stride;
|
||||
|
||||
d0u8 = vrhadd_u8(vreinterpret_u8_u32(d0u32), vreinterpret_u8_u32(d2u32));
|
||||
|
||||
d0u32 = vreinterpret_u32_u8(d0u8);
|
||||
vst1_lane_u32((uint32_t *)dst, d0u32, 0);
|
||||
dst += dst_stride;
|
||||
vst1_lane_u32((uint32_t *)dst, d0u32, 1);
|
||||
dst += dst_stride;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
119
third_party/aom/aom_dsp/arm/aom_convolve_avg_neon_asm.asm
vendored
Normal file
119
third_party/aom/aom_dsp/arm/aom_convolve_avg_neon_asm.asm
vendored
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
;
|
||||
; Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
;
|
||||
; This source code is subject to the terms of the BSD 2 Clause License and
|
||||
; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
; was not distributed with this source code in the LICENSE file, you can
|
||||
; obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
; Media Patent License 1.0 was not distributed with this source code in the
|
||||
; PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
;
|
||||
|
||||
;
|
||||
|
||||
EXPORT |aom_convolve_avg_neon|
|
||||
ARM
|
||||
REQUIRE8
|
||||
PRESERVE8
|
||||
|
||||
AREA ||.text||, CODE, READONLY, ALIGN=2
|
||||
|
||||
|aom_convolve_avg_neon| PROC
|
||||
push {r4-r6, lr}
|
||||
ldrd r4, r5, [sp, #32]
|
||||
mov r6, r2
|
||||
|
||||
cmp r4, #32
|
||||
bgt avg64
|
||||
beq avg32
|
||||
cmp r4, #8
|
||||
bgt avg16
|
||||
beq avg8
|
||||
b avg4
|
||||
|
||||
avg64
|
||||
sub lr, r1, #32
|
||||
sub r4, r3, #32
|
||||
avg64_h
|
||||
pld [r0, r1, lsl #1]
|
||||
vld1.8 {q0-q1}, [r0]!
|
||||
vld1.8 {q2-q3}, [r0], lr
|
||||
pld [r2, r3]
|
||||
vld1.8 {q8-q9}, [r6@128]!
|
||||
vld1.8 {q10-q11}, [r6@128], r4
|
||||
vrhadd.u8 q0, q0, q8
|
||||
vrhadd.u8 q1, q1, q9
|
||||
vrhadd.u8 q2, q2, q10
|
||||
vrhadd.u8 q3, q3, q11
|
||||
vst1.8 {q0-q1}, [r2@128]!
|
||||
vst1.8 {q2-q3}, [r2@128], r4
|
||||
subs r5, r5, #1
|
||||
bgt avg64_h
|
||||
pop {r4-r6, pc}
|
||||
|
||||
avg32
|
||||
vld1.8 {q0-q1}, [r0], r1
|
||||
vld1.8 {q2-q3}, [r0], r1
|
||||
vld1.8 {q8-q9}, [r6@128], r3
|
||||
vld1.8 {q10-q11}, [r6@128], r3
|
||||
pld [r0]
|
||||
vrhadd.u8 q0, q0, q8
|
||||
pld [r0, r1]
|
||||
vrhadd.u8 q1, q1, q9
|
||||
pld [r6]
|
||||
vrhadd.u8 q2, q2, q10
|
||||
pld [r6, r3]
|
||||
vrhadd.u8 q3, q3, q11
|
||||
vst1.8 {q0-q1}, [r2@128], r3
|
||||
vst1.8 {q2-q3}, [r2@128], r3
|
||||
subs r5, r5, #2
|
||||
bgt avg32
|
||||
pop {r4-r6, pc}
|
||||
|
||||
avg16
|
||||
vld1.8 {q0}, [r0], r1
|
||||
vld1.8 {q1}, [r0], r1
|
||||
vld1.8 {q2}, [r6@128], r3
|
||||
vld1.8 {q3}, [r6@128], r3
|
||||
pld [r0]
|
||||
pld [r0, r1]
|
||||
vrhadd.u8 q0, q0, q2
|
||||
pld [r6]
|
||||
pld [r6, r3]
|
||||
vrhadd.u8 q1, q1, q3
|
||||
vst1.8 {q0}, [r2@128], r3
|
||||
vst1.8 {q1}, [r2@128], r3
|
||||
subs r5, r5, #2
|
||||
bgt avg16
|
||||
pop {r4-r6, pc}
|
||||
|
||||
avg8
|
||||
vld1.8 {d0}, [r0], r1
|
||||
vld1.8 {d1}, [r0], r1
|
||||
vld1.8 {d2}, [r6@64], r3
|
||||
vld1.8 {d3}, [r6@64], r3
|
||||
pld [r0]
|
||||
pld [r0, r1]
|
||||
vrhadd.u8 q0, q0, q1
|
||||
pld [r6]
|
||||
pld [r6, r3]
|
||||
vst1.8 {d0}, [r2@64], r3
|
||||
vst1.8 {d1}, [r2@64], r3
|
||||
subs r5, r5, #2
|
||||
bgt avg8
|
||||
pop {r4-r6, pc}
|
||||
|
||||
avg4
|
||||
vld1.32 {d0[0]}, [r0], r1
|
||||
vld1.32 {d0[1]}, [r0], r1
|
||||
vld1.32 {d2[0]}, [r6@32], r3
|
||||
vld1.32 {d2[1]}, [r6@32], r3
|
||||
vrhadd.u8 d0, d0, d2
|
||||
vst1.32 {d0[0]}, [r2@32], r3
|
||||
vst1.32 {d0[1]}, [r2@32], r3
|
||||
subs r5, r5, #2
|
||||
bgt avg4
|
||||
pop {r4-r6, pc}
|
||||
ENDP
|
||||
|
||||
END
|
||||
93
third_party/aom/aom_dsp/arm/aom_convolve_copy_neon.c
vendored
Normal file
93
third_party/aom/aom_dsp/arm/aom_convolve_copy_neon.c
vendored
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <arm_neon.h>
|
||||
|
||||
#include "./aom_dsp_rtcd.h"
|
||||
#include "aom/aom_integer.h"
|
||||
|
||||
void aom_convolve_copy_neon(const uint8_t *src, // r0
|
||||
ptrdiff_t src_stride, // r1
|
||||
uint8_t *dst, // r2
|
||||
ptrdiff_t dst_stride, // r3
|
||||
const int16_t *filter_x, int filter_x_stride,
|
||||
const int16_t *filter_y, int filter_y_stride, int w,
|
||||
int h) {
|
||||
uint8x8_t d0u8, d2u8;
|
||||
uint8x16_t q0u8, q1u8, q2u8, q3u8;
|
||||
(void)filter_x;
|
||||
(void)filter_x_stride;
|
||||
(void)filter_y;
|
||||
(void)filter_y_stride;
|
||||
|
||||
if (w > 32) { // copy64
|
||||
for (; h > 0; h--) {
|
||||
q0u8 = vld1q_u8(src);
|
||||
q1u8 = vld1q_u8(src + 16);
|
||||
q2u8 = vld1q_u8(src + 32);
|
||||
q3u8 = vld1q_u8(src + 48);
|
||||
src += src_stride;
|
||||
|
||||
vst1q_u8(dst, q0u8);
|
||||
vst1q_u8(dst + 16, q1u8);
|
||||
vst1q_u8(dst + 32, q2u8);
|
||||
vst1q_u8(dst + 48, q3u8);
|
||||
dst += dst_stride;
|
||||
}
|
||||
} else if (w == 32) { // copy32
|
||||
for (; h > 0; h -= 2) {
|
||||
q0u8 = vld1q_u8(src);
|
||||
q1u8 = vld1q_u8(src + 16);
|
||||
src += src_stride;
|
||||
q2u8 = vld1q_u8(src);
|
||||
q3u8 = vld1q_u8(src + 16);
|
||||
src += src_stride;
|
||||
|
||||
vst1q_u8(dst, q0u8);
|
||||
vst1q_u8(dst + 16, q1u8);
|
||||
dst += dst_stride;
|
||||
vst1q_u8(dst, q2u8);
|
||||
vst1q_u8(dst + 16, q3u8);
|
||||
dst += dst_stride;
|
||||
}
|
||||
} else if (w > 8) { // copy16
|
||||
for (; h > 0; h -= 2) {
|
||||
q0u8 = vld1q_u8(src);
|
||||
src += src_stride;
|
||||
q1u8 = vld1q_u8(src);
|
||||
src += src_stride;
|
||||
|
||||
vst1q_u8(dst, q0u8);
|
||||
dst += dst_stride;
|
||||
vst1q_u8(dst, q1u8);
|
||||
dst += dst_stride;
|
||||
}
|
||||
} else if (w == 8) { // copy8
|
||||
for (; h > 0; h -= 2) {
|
||||
d0u8 = vld1_u8(src);
|
||||
src += src_stride;
|
||||
d2u8 = vld1_u8(src);
|
||||
src += src_stride;
|
||||
|
||||
vst1_u8(dst, d0u8);
|
||||
dst += dst_stride;
|
||||
vst1_u8(dst, d2u8);
|
||||
dst += dst_stride;
|
||||
}
|
||||
} else { // copy4
|
||||
for (; h > 0; h--) {
|
||||
*(uint32_t *)dst = *(const uint32_t *)src;
|
||||
src += src_stride;
|
||||
dst += dst_stride;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
87
third_party/aom/aom_dsp/arm/aom_convolve_copy_neon_asm.asm
vendored
Normal file
87
third_party/aom/aom_dsp/arm/aom_convolve_copy_neon_asm.asm
vendored
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
;
|
||||
; Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
;
|
||||
; This source code is subject to the terms of the BSD 2 Clause License and
|
||||
; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
; was not distributed with this source code in the LICENSE file, you can
|
||||
; obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
; Media Patent License 1.0 was not distributed with this source code in the
|
||||
; PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
;
|
||||
|
||||
;
|
||||
|
||||
EXPORT |aom_convolve_copy_neon|
|
||||
ARM
|
||||
REQUIRE8
|
||||
PRESERVE8
|
||||
|
||||
AREA ||.text||, CODE, READONLY, ALIGN=2
|
||||
|
||||
|aom_convolve_copy_neon| PROC
|
||||
push {r4-r5, lr}
|
||||
ldrd r4, r5, [sp, #28]
|
||||
|
||||
cmp r4, #32
|
||||
bgt copy64
|
||||
beq copy32
|
||||
cmp r4, #8
|
||||
bgt copy16
|
||||
beq copy8
|
||||
b copy4
|
||||
|
||||
copy64
|
||||
sub lr, r1, #32
|
||||
sub r3, r3, #32
|
||||
copy64_h
|
||||
pld [r0, r1, lsl #1]
|
||||
vld1.8 {q0-q1}, [r0]!
|
||||
vld1.8 {q2-q3}, [r0], lr
|
||||
vst1.8 {q0-q1}, [r2@128]!
|
||||
vst1.8 {q2-q3}, [r2@128], r3
|
||||
subs r5, r5, #1
|
||||
bgt copy64_h
|
||||
pop {r4-r5, pc}
|
||||
|
||||
copy32
|
||||
pld [r0, r1, lsl #1]
|
||||
vld1.8 {q0-q1}, [r0], r1
|
||||
pld [r0, r1, lsl #1]
|
||||
vld1.8 {q2-q3}, [r0], r1
|
||||
vst1.8 {q0-q1}, [r2@128], r3
|
||||
vst1.8 {q2-q3}, [r2@128], r3
|
||||
subs r5, r5, #2
|
||||
bgt copy32
|
||||
pop {r4-r5, pc}
|
||||
|
||||
copy16
|
||||
pld [r0, r1, lsl #1]
|
||||
vld1.8 {q0}, [r0], r1
|
||||
pld [r0, r1, lsl #1]
|
||||
vld1.8 {q1}, [r0], r1
|
||||
vst1.8 {q0}, [r2@128], r3
|
||||
vst1.8 {q1}, [r2@128], r3
|
||||
subs r5, r5, #2
|
||||
bgt copy16
|
||||
pop {r4-r5, pc}
|
||||
|
||||
copy8
|
||||
pld [r0, r1, lsl #1]
|
||||
vld1.8 {d0}, [r0], r1
|
||||
pld [r0, r1, lsl #1]
|
||||
vld1.8 {d2}, [r0], r1
|
||||
vst1.8 {d0}, [r2@64], r3
|
||||
vst1.8 {d2}, [r2@64], r3
|
||||
subs r5, r5, #2
|
||||
bgt copy8
|
||||
pop {r4-r5, pc}
|
||||
|
||||
copy4
|
||||
ldr r12, [r0], r1
|
||||
str r12, [r2], r3
|
||||
subs r5, r5, #1
|
||||
bgt copy4
|
||||
pop {r4-r5, pc}
|
||||
ENDP
|
||||
|
||||
END
|
||||
66
third_party/aom/aom_dsp/arm/aom_convolve_neon.c
vendored
Normal file
66
third_party/aom/aom_dsp/arm/aom_convolve_neon.c
vendored
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "./aom_dsp_rtcd.h"
|
||||
#include "aom_dsp/aom_dsp_common.h"
|
||||
#include "aom_ports/mem.h"
|
||||
|
||||
void aom_convolve8_neon(const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst,
|
||||
ptrdiff_t dst_stride, const int16_t *filter_x,
|
||||
int x_step_q4, const int16_t *filter_y, int y_step_q4,
|
||||
int w, int h) {
|
||||
/* Given our constraints: w <= 64, h <= 64, taps == 8 we can reduce the
|
||||
* maximum buffer size to 64 * 64 + 7 (+ 1 to make it divisible by 4).
|
||||
*/
|
||||
DECLARE_ALIGNED(8, uint8_t, temp[64 * 72]);
|
||||
|
||||
// Account for the vertical phase needing 3 lines prior and 4 lines post
|
||||
int intermediate_height = h + 7;
|
||||
|
||||
assert(y_step_q4 == 16);
|
||||
assert(x_step_q4 == 16);
|
||||
|
||||
/* Filter starting 3 lines back. The neon implementation will ignore the
|
||||
* given height and filter a multiple of 4 lines. Since this goes in to
|
||||
* the temp buffer which has lots of extra room and is subsequently discarded
|
||||
* this is safe if somewhat less than ideal.
|
||||
*/
|
||||
aom_convolve8_horiz_neon(src - src_stride * 3, src_stride, temp, 64, filter_x,
|
||||
x_step_q4, filter_y, y_step_q4, w,
|
||||
intermediate_height);
|
||||
|
||||
/* Step into the temp buffer 3 lines to get the actual frame data */
|
||||
aom_convolve8_vert_neon(temp + 64 * 3, 64, dst, dst_stride, filter_x,
|
||||
x_step_q4, filter_y, y_step_q4, w, h);
|
||||
}
|
||||
|
||||
void aom_convolve8_avg_neon(const uint8_t *src, ptrdiff_t src_stride,
|
||||
uint8_t *dst, ptrdiff_t dst_stride,
|
||||
const int16_t *filter_x, int x_step_q4,
|
||||
const int16_t *filter_y, int y_step_q4, int w,
|
||||
int h) {
|
||||
DECLARE_ALIGNED(8, uint8_t, temp[64 * 72]);
|
||||
int intermediate_height = h + 7;
|
||||
|
||||
assert(y_step_q4 == 16);
|
||||
assert(x_step_q4 == 16);
|
||||
|
||||
/* This implementation has the same issues as above. In addition, we only want
|
||||
* to average the values after both passes.
|
||||
*/
|
||||
aom_convolve8_horiz_neon(src - src_stride * 3, src_stride, temp, 64, filter_x,
|
||||
x_step_q4, filter_y, y_step_q4, w,
|
||||
intermediate_height);
|
||||
aom_convolve8_avg_vert_neon(temp + 64 * 3, 64, dst, dst_stride, filter_x,
|
||||
x_step_q4, filter_y, y_step_q4, w, h);
|
||||
}
|
||||
254
third_party/aom/aom_dsp/arm/avg_neon.c
vendored
Normal file
254
third_party/aom/aom_dsp/arm/avg_neon.c
vendored
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <arm_neon.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "./aom_dsp_rtcd.h"
|
||||
#include "./aom_config.h"
|
||||
|
||||
#include "aom/aom_integer.h"
|
||||
|
||||
static INLINE unsigned int horizontal_add_u16x8(const uint16x8_t v_16x8) {
|
||||
const uint32x4_t a = vpaddlq_u16(v_16x8);
|
||||
const uint64x2_t b = vpaddlq_u32(a);
|
||||
const uint32x2_t c = vadd_u32(vreinterpret_u32_u64(vget_low_u64(b)),
|
||||
vreinterpret_u32_u64(vget_high_u64(b)));
|
||||
return vget_lane_u32(c, 0);
|
||||
}
|
||||
|
||||
unsigned int aom_avg_4x4_neon(const uint8_t *s, int p) {
|
||||
uint16x8_t v_sum;
|
||||
uint32x2_t v_s0 = vdup_n_u32(0);
|
||||
uint32x2_t v_s1 = vdup_n_u32(0);
|
||||
v_s0 = vld1_lane_u32((const uint32_t *)s, v_s0, 0);
|
||||
v_s0 = vld1_lane_u32((const uint32_t *)(s + p), v_s0, 1);
|
||||
v_s1 = vld1_lane_u32((const uint32_t *)(s + 2 * p), v_s1, 0);
|
||||
v_s1 = vld1_lane_u32((const uint32_t *)(s + 3 * p), v_s1, 1);
|
||||
v_sum = vaddl_u8(vreinterpret_u8_u32(v_s0), vreinterpret_u8_u32(v_s1));
|
||||
return (horizontal_add_u16x8(v_sum) + 8) >> 4;
|
||||
}
|
||||
|
||||
unsigned int aom_avg_8x8_neon(const uint8_t *s, int p) {
|
||||
uint8x8_t v_s0 = vld1_u8(s);
|
||||
const uint8x8_t v_s1 = vld1_u8(s + p);
|
||||
uint16x8_t v_sum = vaddl_u8(v_s0, v_s1);
|
||||
|
||||
v_s0 = vld1_u8(s + 2 * p);
|
||||
v_sum = vaddw_u8(v_sum, v_s0);
|
||||
|
||||
v_s0 = vld1_u8(s + 3 * p);
|
||||
v_sum = vaddw_u8(v_sum, v_s0);
|
||||
|
||||
v_s0 = vld1_u8(s + 4 * p);
|
||||
v_sum = vaddw_u8(v_sum, v_s0);
|
||||
|
||||
v_s0 = vld1_u8(s + 5 * p);
|
||||
v_sum = vaddw_u8(v_sum, v_s0);
|
||||
|
||||
v_s0 = vld1_u8(s + 6 * p);
|
||||
v_sum = vaddw_u8(v_sum, v_s0);
|
||||
|
||||
v_s0 = vld1_u8(s + 7 * p);
|
||||
v_sum = vaddw_u8(v_sum, v_s0);
|
||||
|
||||
return (horizontal_add_u16x8(v_sum) + 32) >> 6;
|
||||
}
|
||||
|
||||
// coeff: 16 bits, dynamic range [-32640, 32640].
|
||||
// length: value range {16, 64, 256, 1024}.
|
||||
int aom_satd_neon(const int16_t *coeff, int length) {
|
||||
const int16x4_t zero = vdup_n_s16(0);
|
||||
int32x4_t accum = vdupq_n_s32(0);
|
||||
|
||||
do {
|
||||
const int16x8_t src0 = vld1q_s16(coeff);
|
||||
const int16x8_t src8 = vld1q_s16(coeff + 8);
|
||||
accum = vabal_s16(accum, vget_low_s16(src0), zero);
|
||||
accum = vabal_s16(accum, vget_high_s16(src0), zero);
|
||||
accum = vabal_s16(accum, vget_low_s16(src8), zero);
|
||||
accum = vabal_s16(accum, vget_high_s16(src8), zero);
|
||||
length -= 16;
|
||||
coeff += 16;
|
||||
} while (length != 0);
|
||||
|
||||
{
|
||||
// satd: 26 bits, dynamic range [-32640 * 1024, 32640 * 1024]
|
||||
const int64x2_t s0 = vpaddlq_s32(accum); // cascading summation of 'accum'.
|
||||
const int32x2_t s1 = vadd_s32(vreinterpret_s32_s64(vget_low_s64(s0)),
|
||||
vreinterpret_s32_s64(vget_high_s64(s0)));
|
||||
const int satd = vget_lane_s32(s1, 0);
|
||||
return satd;
|
||||
}
|
||||
}
|
||||
|
||||
void aom_int_pro_row_neon(int16_t hbuf[16], uint8_t const *ref, int ref_stride,
|
||||
int height) {
|
||||
int i;
|
||||
uint16x8_t vec_sum_lo = vdupq_n_u16(0);
|
||||
uint16x8_t vec_sum_hi = vdupq_n_u16(0);
|
||||
const int shift_factor = ((height >> 5) + 3) * -1;
|
||||
const int16x8_t vec_shift = vdupq_n_s16(shift_factor);
|
||||
|
||||
for (i = 0; i < height; i += 8) {
|
||||
const uint8x16_t vec_row1 = vld1q_u8(ref);
|
||||
const uint8x16_t vec_row2 = vld1q_u8(ref + ref_stride);
|
||||
const uint8x16_t vec_row3 = vld1q_u8(ref + ref_stride * 2);
|
||||
const uint8x16_t vec_row4 = vld1q_u8(ref + ref_stride * 3);
|
||||
const uint8x16_t vec_row5 = vld1q_u8(ref + ref_stride * 4);
|
||||
const uint8x16_t vec_row6 = vld1q_u8(ref + ref_stride * 5);
|
||||
const uint8x16_t vec_row7 = vld1q_u8(ref + ref_stride * 6);
|
||||
const uint8x16_t vec_row8 = vld1q_u8(ref + ref_stride * 7);
|
||||
|
||||
vec_sum_lo = vaddw_u8(vec_sum_lo, vget_low_u8(vec_row1));
|
||||
vec_sum_hi = vaddw_u8(vec_sum_hi, vget_high_u8(vec_row1));
|
||||
|
||||
vec_sum_lo = vaddw_u8(vec_sum_lo, vget_low_u8(vec_row2));
|
||||
vec_sum_hi = vaddw_u8(vec_sum_hi, vget_high_u8(vec_row2));
|
||||
|
||||
vec_sum_lo = vaddw_u8(vec_sum_lo, vget_low_u8(vec_row3));
|
||||
vec_sum_hi = vaddw_u8(vec_sum_hi, vget_high_u8(vec_row3));
|
||||
|
||||
vec_sum_lo = vaddw_u8(vec_sum_lo, vget_low_u8(vec_row4));
|
||||
vec_sum_hi = vaddw_u8(vec_sum_hi, vget_high_u8(vec_row4));
|
||||
|
||||
vec_sum_lo = vaddw_u8(vec_sum_lo, vget_low_u8(vec_row5));
|
||||
vec_sum_hi = vaddw_u8(vec_sum_hi, vget_high_u8(vec_row5));
|
||||
|
||||
vec_sum_lo = vaddw_u8(vec_sum_lo, vget_low_u8(vec_row6));
|
||||
vec_sum_hi = vaddw_u8(vec_sum_hi, vget_high_u8(vec_row6));
|
||||
|
||||
vec_sum_lo = vaddw_u8(vec_sum_lo, vget_low_u8(vec_row7));
|
||||
vec_sum_hi = vaddw_u8(vec_sum_hi, vget_high_u8(vec_row7));
|
||||
|
||||
vec_sum_lo = vaddw_u8(vec_sum_lo, vget_low_u8(vec_row8));
|
||||
vec_sum_hi = vaddw_u8(vec_sum_hi, vget_high_u8(vec_row8));
|
||||
|
||||
ref += ref_stride * 8;
|
||||
}
|
||||
|
||||
vec_sum_lo = vshlq_u16(vec_sum_lo, vec_shift);
|
||||
vec_sum_hi = vshlq_u16(vec_sum_hi, vec_shift);
|
||||
|
||||
vst1q_s16(hbuf, vreinterpretq_s16_u16(vec_sum_lo));
|
||||
hbuf += 8;
|
||||
vst1q_s16(hbuf, vreinterpretq_s16_u16(vec_sum_hi));
|
||||
}
|
||||
|
||||
int16_t aom_int_pro_col_neon(uint8_t const *ref, const int width) {
|
||||
int i;
|
||||
uint16x8_t vec_sum = vdupq_n_u16(0);
|
||||
|
||||
for (i = 0; i < width; i += 16) {
|
||||
const uint8x16_t vec_row = vld1q_u8(ref);
|
||||
vec_sum = vaddw_u8(vec_sum, vget_low_u8(vec_row));
|
||||
vec_sum = vaddw_u8(vec_sum, vget_high_u8(vec_row));
|
||||
ref += 16;
|
||||
}
|
||||
|
||||
return horizontal_add_u16x8(vec_sum);
|
||||
}
|
||||
|
||||
// ref, src = [0, 510] - max diff = 16-bits
|
||||
// bwl = {2, 3, 4}, width = {16, 32, 64}
|
||||
int aom_vector_var_neon(int16_t const *ref, int16_t const *src, int bwl) {
|
||||
int width = 4 << bwl;
|
||||
int32x4_t sse = vdupq_n_s32(0);
|
||||
int16x8_t total = vdupq_n_s16(0);
|
||||
|
||||
assert(width >= 8);
|
||||
assert((width % 8) == 0);
|
||||
|
||||
do {
|
||||
const int16x8_t r = vld1q_s16(ref);
|
||||
const int16x8_t s = vld1q_s16(src);
|
||||
const int16x8_t diff = vsubq_s16(r, s); // [-510, 510], 10 bits.
|
||||
const int16x4_t diff_lo = vget_low_s16(diff);
|
||||
const int16x4_t diff_hi = vget_high_s16(diff);
|
||||
sse = vmlal_s16(sse, diff_lo, diff_lo); // dynamic range 26 bits.
|
||||
sse = vmlal_s16(sse, diff_hi, diff_hi);
|
||||
total = vaddq_s16(total, diff); // dynamic range 16 bits.
|
||||
|
||||
ref += 8;
|
||||
src += 8;
|
||||
width -= 8;
|
||||
} while (width != 0);
|
||||
|
||||
{
|
||||
// Note: 'total''s pairwise addition could be implemented similarly to
|
||||
// horizontal_add_u16x8(), but one less vpaddl with 'total' when paired
|
||||
// with the summation of 'sse' performed better on a Cortex-A15.
|
||||
const int32x4_t t0 = vpaddlq_s16(total); // cascading summation of 'total'
|
||||
const int32x2_t t1 = vadd_s32(vget_low_s32(t0), vget_high_s32(t0));
|
||||
const int32x2_t t2 = vpadd_s32(t1, t1);
|
||||
const int t = vget_lane_s32(t2, 0);
|
||||
const int64x2_t s0 = vpaddlq_s32(sse); // cascading summation of 'sse'.
|
||||
const int32x2_t s1 = vadd_s32(vreinterpret_s32_s64(vget_low_s64(s0)),
|
||||
vreinterpret_s32_s64(vget_high_s64(s0)));
|
||||
const int s = vget_lane_s32(s1, 0);
|
||||
const int shift_factor = bwl + 2;
|
||||
return s - ((t * t) >> shift_factor);
|
||||
}
|
||||
}
|
||||
|
||||
void aom_minmax_8x8_neon(const uint8_t *a, int a_stride, const uint8_t *b,
|
||||
int b_stride, int *min, int *max) {
|
||||
// Load and concatenate.
|
||||
const uint8x16_t a01 = vcombine_u8(vld1_u8(a), vld1_u8(a + a_stride));
|
||||
const uint8x16_t a23 =
|
||||
vcombine_u8(vld1_u8(a + 2 * a_stride), vld1_u8(a + 3 * a_stride));
|
||||
const uint8x16_t a45 =
|
||||
vcombine_u8(vld1_u8(a + 4 * a_stride), vld1_u8(a + 5 * a_stride));
|
||||
const uint8x16_t a67 =
|
||||
vcombine_u8(vld1_u8(a + 6 * a_stride), vld1_u8(a + 7 * a_stride));
|
||||
|
||||
const uint8x16_t b01 = vcombine_u8(vld1_u8(b), vld1_u8(b + b_stride));
|
||||
const uint8x16_t b23 =
|
||||
vcombine_u8(vld1_u8(b + 2 * b_stride), vld1_u8(b + 3 * b_stride));
|
||||
const uint8x16_t b45 =
|
||||
vcombine_u8(vld1_u8(b + 4 * b_stride), vld1_u8(b + 5 * b_stride));
|
||||
const uint8x16_t b67 =
|
||||
vcombine_u8(vld1_u8(b + 6 * b_stride), vld1_u8(b + 7 * b_stride));
|
||||
|
||||
// Absolute difference.
|
||||
const uint8x16_t ab01_diff = vabdq_u8(a01, b01);
|
||||
const uint8x16_t ab23_diff = vabdq_u8(a23, b23);
|
||||
const uint8x16_t ab45_diff = vabdq_u8(a45, b45);
|
||||
const uint8x16_t ab67_diff = vabdq_u8(a67, b67);
|
||||
|
||||
// Max values between the Q vectors.
|
||||
const uint8x16_t ab0123_max = vmaxq_u8(ab01_diff, ab23_diff);
|
||||
const uint8x16_t ab4567_max = vmaxq_u8(ab45_diff, ab67_diff);
|
||||
const uint8x16_t ab0123_min = vminq_u8(ab01_diff, ab23_diff);
|
||||
const uint8x16_t ab4567_min = vminq_u8(ab45_diff, ab67_diff);
|
||||
|
||||
const uint8x16_t ab07_max = vmaxq_u8(ab0123_max, ab4567_max);
|
||||
const uint8x16_t ab07_min = vminq_u8(ab0123_min, ab4567_min);
|
||||
|
||||
// Split to D and start doing pairwise.
|
||||
uint8x8_t ab_max = vmax_u8(vget_high_u8(ab07_max), vget_low_u8(ab07_max));
|
||||
uint8x8_t ab_min = vmin_u8(vget_high_u8(ab07_min), vget_low_u8(ab07_min));
|
||||
|
||||
// Enough runs of vpmax/min propogate the max/min values to every position.
|
||||
ab_max = vpmax_u8(ab_max, ab_max);
|
||||
ab_min = vpmin_u8(ab_min, ab_min);
|
||||
|
||||
ab_max = vpmax_u8(ab_max, ab_max);
|
||||
ab_min = vpmin_u8(ab_min, ab_min);
|
||||
|
||||
ab_max = vpmax_u8(ab_max, ab_max);
|
||||
ab_min = vpmin_u8(ab_min, ab_min);
|
||||
|
||||
*min = *max = 0; // Clear high bits
|
||||
// Store directly to avoid costly neon->gpr transfer.
|
||||
vst1_lane_u8((uint8_t *)max, ab_max, 0);
|
||||
vst1_lane_u8((uint8_t *)min, ab_min, 0);
|
||||
}
|
||||
240
third_party/aom/aom_dsp/arm/bilinear_filter_media.asm
vendored
Normal file
240
third_party/aom/aom_dsp/arm/bilinear_filter_media.asm
vendored
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
;
|
||||
; Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
;
|
||||
; This source code is subject to the terms of the BSD 2 Clause License and
|
||||
; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
; was not distributed with this source code in the LICENSE file, you can
|
||||
; obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
; Media Patent License 1.0 was not distributed with this source code in the
|
||||
; PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
;
|
||||
|
||||
;
|
||||
|
||||
|
||||
EXPORT |aom_filter_block2d_bil_first_pass_media|
|
||||
EXPORT |aom_filter_block2d_bil_second_pass_media|
|
||||
|
||||
AREA |.text|, CODE, READONLY ; name this block of code
|
||||
|
||||
;-------------------------------------
|
||||
; r0 unsigned char *src_ptr,
|
||||
; r1 unsigned short *dst_ptr,
|
||||
; r2 unsigned int src_pitch,
|
||||
; r3 unsigned int height,
|
||||
; stack unsigned int width,
|
||||
; stack const short *aom_filter
|
||||
;-------------------------------------
|
||||
; The output is transposed stroed in output array to make it easy for second pass filtering.
|
||||
|aom_filter_block2d_bil_first_pass_media| PROC
|
||||
stmdb sp!, {r4 - r11, lr}
|
||||
|
||||
ldr r11, [sp, #40] ; aom_filter address
|
||||
ldr r4, [sp, #36] ; width
|
||||
|
||||
mov r12, r3 ; outer-loop counter
|
||||
|
||||
add r7, r2, r4 ; preload next row
|
||||
pld [r0, r7]
|
||||
|
||||
sub r2, r2, r4 ; src increment for height loop
|
||||
|
||||
ldr r5, [r11] ; load up filter coefficients
|
||||
|
||||
mov r3, r3, lsl #1 ; height*2
|
||||
add r3, r3, #2 ; plus 2 to make output buffer 4-bit aligned since height is actually (height+1)
|
||||
|
||||
mov r11, r1 ; save dst_ptr for each row
|
||||
|
||||
cmp r5, #128 ; if filter coef = 128, then skip the filter
|
||||
beq bil_null_1st_filter
|
||||
|
||||
|bil_height_loop_1st_v6|
|
||||
ldrb r6, [r0] ; load source data
|
||||
ldrb r7, [r0, #1]
|
||||
ldrb r8, [r0, #2]
|
||||
mov lr, r4, lsr #2 ; 4-in-parellel loop counter
|
||||
|
||||
|bil_width_loop_1st_v6|
|
||||
ldrb r9, [r0, #3]
|
||||
ldrb r10, [r0, #4]
|
||||
|
||||
pkhbt r6, r6, r7, lsl #16 ; src[1] | src[0]
|
||||
pkhbt r7, r7, r8, lsl #16 ; src[2] | src[1]
|
||||
|
||||
smuad r6, r6, r5 ; apply the filter
|
||||
pkhbt r8, r8, r9, lsl #16 ; src[3] | src[2]
|
||||
smuad r7, r7, r5
|
||||
pkhbt r9, r9, r10, lsl #16 ; src[4] | src[3]
|
||||
|
||||
smuad r8, r8, r5
|
||||
smuad r9, r9, r5
|
||||
|
||||
add r0, r0, #4
|
||||
subs lr, lr, #1
|
||||
|
||||
add r6, r6, #0x40 ; round_shift_and_clamp
|
||||
add r7, r7, #0x40
|
||||
usat r6, #16, r6, asr #7
|
||||
usat r7, #16, r7, asr #7
|
||||
|
||||
strh r6, [r1], r3 ; result is transposed and stored
|
||||
|
||||
add r8, r8, #0x40 ; round_shift_and_clamp
|
||||
strh r7, [r1], r3
|
||||
add r9, r9, #0x40
|
||||
usat r8, #16, r8, asr #7
|
||||
usat r9, #16, r9, asr #7
|
||||
|
||||
strh r8, [r1], r3 ; result is transposed and stored
|
||||
|
||||
ldrneb r6, [r0] ; load source data
|
||||
strh r9, [r1], r3
|
||||
|
||||
ldrneb r7, [r0, #1]
|
||||
ldrneb r8, [r0, #2]
|
||||
|
||||
bne bil_width_loop_1st_v6
|
||||
|
||||
add r0, r0, r2 ; move to next input row
|
||||
subs r12, r12, #1
|
||||
|
||||
add r9, r2, r4, lsl #1 ; adding back block width
|
||||
pld [r0, r9] ; preload next row
|
||||
|
||||
add r11, r11, #2 ; move over to next column
|
||||
mov r1, r11
|
||||
|
||||
bne bil_height_loop_1st_v6
|
||||
|
||||
ldmia sp!, {r4 - r11, pc}
|
||||
|
||||
|bil_null_1st_filter|
|
||||
|bil_height_loop_null_1st|
|
||||
mov lr, r4, lsr #2 ; loop counter
|
||||
|
||||
|bil_width_loop_null_1st|
|
||||
ldrb r6, [r0] ; load data
|
||||
ldrb r7, [r0, #1]
|
||||
ldrb r8, [r0, #2]
|
||||
ldrb r9, [r0, #3]
|
||||
|
||||
strh r6, [r1], r3 ; store it to immediate buffer
|
||||
add r0, r0, #4
|
||||
strh r7, [r1], r3
|
||||
subs lr, lr, #1
|
||||
strh r8, [r1], r3
|
||||
strh r9, [r1], r3
|
||||
|
||||
bne bil_width_loop_null_1st
|
||||
|
||||
subs r12, r12, #1
|
||||
add r0, r0, r2 ; move to next input line
|
||||
add r11, r11, #2 ; move over to next column
|
||||
mov r1, r11
|
||||
|
||||
bne bil_height_loop_null_1st
|
||||
|
||||
ldmia sp!, {r4 - r11, pc}
|
||||
|
||||
ENDP ; |aom_filter_block2d_bil_first_pass_media|
|
||||
|
||||
|
||||
;---------------------------------
|
||||
; r0 unsigned short *src_ptr,
|
||||
; r1 unsigned char *dst_ptr,
|
||||
; r2 int dst_pitch,
|
||||
; r3 unsigned int height,
|
||||
; stack unsigned int width,
|
||||
; stack const short *aom_filter
|
||||
;---------------------------------
|
||||
|aom_filter_block2d_bil_second_pass_media| PROC
|
||||
stmdb sp!, {r4 - r11, lr}
|
||||
|
||||
ldr r11, [sp, #40] ; aom_filter address
|
||||
ldr r4, [sp, #36] ; width
|
||||
|
||||
ldr r5, [r11] ; load up filter coefficients
|
||||
mov r12, r4 ; outer-loop counter = width, since we work on transposed data matrix
|
||||
mov r11, r1
|
||||
|
||||
cmp r5, #128 ; if filter coef = 128, then skip the filter
|
||||
beq bil_null_2nd_filter
|
||||
|
||||
|bil_height_loop_2nd|
|
||||
ldr r6, [r0] ; load the data
|
||||
ldr r8, [r0, #4]
|
||||
ldrh r10, [r0, #8]
|
||||
mov lr, r3, lsr #2 ; loop counter
|
||||
|
||||
|bil_width_loop_2nd|
|
||||
pkhtb r7, r6, r8 ; src[1] | src[2]
|
||||
pkhtb r9, r8, r10 ; src[3] | src[4]
|
||||
|
||||
smuad r6, r6, r5 ; apply filter
|
||||
smuad r8, r8, r5 ; apply filter
|
||||
|
||||
subs lr, lr, #1
|
||||
|
||||
smuadx r7, r7, r5 ; apply filter
|
||||
smuadx r9, r9, r5 ; apply filter
|
||||
|
||||
add r0, r0, #8
|
||||
|
||||
add r6, r6, #0x40 ; round_shift_and_clamp
|
||||
add r7, r7, #0x40
|
||||
usat r6, #8, r6, asr #7
|
||||
usat r7, #8, r7, asr #7
|
||||
strb r6, [r1], r2 ; the result is transposed back and stored
|
||||
|
||||
add r8, r8, #0x40 ; round_shift_and_clamp
|
||||
strb r7, [r1], r2
|
||||
add r9, r9, #0x40
|
||||
usat r8, #8, r8, asr #7
|
||||
usat r9, #8, r9, asr #7
|
||||
strb r8, [r1], r2 ; the result is transposed back and stored
|
||||
|
||||
ldrne r6, [r0] ; load data
|
||||
strb r9, [r1], r2
|
||||
ldrne r8, [r0, #4]
|
||||
ldrneh r10, [r0, #8]
|
||||
|
||||
bne bil_width_loop_2nd
|
||||
|
||||
subs r12, r12, #1
|
||||
add r0, r0, #4 ; update src for next row
|
||||
add r11, r11, #1
|
||||
mov r1, r11
|
||||
|
||||
bne bil_height_loop_2nd
|
||||
ldmia sp!, {r4 - r11, pc}
|
||||
|
||||
|bil_null_2nd_filter|
|
||||
|bil_height_loop_null_2nd|
|
||||
mov lr, r3, lsr #2
|
||||
|
||||
|bil_width_loop_null_2nd|
|
||||
ldr r6, [r0], #4 ; load data
|
||||
subs lr, lr, #1
|
||||
ldr r8, [r0], #4
|
||||
|
||||
strb r6, [r1], r2 ; store data
|
||||
mov r7, r6, lsr #16
|
||||
strb r7, [r1], r2
|
||||
mov r9, r8, lsr #16
|
||||
strb r8, [r1], r2
|
||||
strb r9, [r1], r2
|
||||
|
||||
bne bil_width_loop_null_2nd
|
||||
|
||||
subs r12, r12, #1
|
||||
add r0, r0, #4
|
||||
add r11, r11, #1
|
||||
mov r1, r11
|
||||
|
||||
bne bil_height_loop_null_2nd
|
||||
|
||||
ldmia sp!, {r4 - r11, pc}
|
||||
ENDP ; |aom_filter_block2d_second_pass_media|
|
||||
|
||||
END
|
||||
221
third_party/aom/aom_dsp/arm/fwd_txfm_neon.c
vendored
Normal file
221
third_party/aom/aom_dsp/arm/fwd_txfm_neon.c
vendored
Normal file
|
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <arm_neon.h>
|
||||
|
||||
#include "./aom_config.h"
|
||||
#include "aom_dsp/txfm_common.h"
|
||||
|
||||
void aom_fdct8x8_neon(const int16_t *input, int16_t *final_output, int stride) {
|
||||
int i;
|
||||
// stage 1
|
||||
int16x8_t input_0 = vshlq_n_s16(vld1q_s16(&input[0 * stride]), 2);
|
||||
int16x8_t input_1 = vshlq_n_s16(vld1q_s16(&input[1 * stride]), 2);
|
||||
int16x8_t input_2 = vshlq_n_s16(vld1q_s16(&input[2 * stride]), 2);
|
||||
int16x8_t input_3 = vshlq_n_s16(vld1q_s16(&input[3 * stride]), 2);
|
||||
int16x8_t input_4 = vshlq_n_s16(vld1q_s16(&input[4 * stride]), 2);
|
||||
int16x8_t input_5 = vshlq_n_s16(vld1q_s16(&input[5 * stride]), 2);
|
||||
int16x8_t input_6 = vshlq_n_s16(vld1q_s16(&input[6 * stride]), 2);
|
||||
int16x8_t input_7 = vshlq_n_s16(vld1q_s16(&input[7 * stride]), 2);
|
||||
for (i = 0; i < 2; ++i) {
|
||||
int16x8_t out_0, out_1, out_2, out_3, out_4, out_5, out_6, out_7;
|
||||
const int16x8_t v_s0 = vaddq_s16(input_0, input_7);
|
||||
const int16x8_t v_s1 = vaddq_s16(input_1, input_6);
|
||||
const int16x8_t v_s2 = vaddq_s16(input_2, input_5);
|
||||
const int16x8_t v_s3 = vaddq_s16(input_3, input_4);
|
||||
const int16x8_t v_s4 = vsubq_s16(input_3, input_4);
|
||||
const int16x8_t v_s5 = vsubq_s16(input_2, input_5);
|
||||
const int16x8_t v_s6 = vsubq_s16(input_1, input_6);
|
||||
const int16x8_t v_s7 = vsubq_s16(input_0, input_7);
|
||||
// fdct4(step, step);
|
||||
int16x8_t v_x0 = vaddq_s16(v_s0, v_s3);
|
||||
int16x8_t v_x1 = vaddq_s16(v_s1, v_s2);
|
||||
int16x8_t v_x2 = vsubq_s16(v_s1, v_s2);
|
||||
int16x8_t v_x3 = vsubq_s16(v_s0, v_s3);
|
||||
// fdct4(step, step);
|
||||
int32x4_t v_t0_lo = vaddl_s16(vget_low_s16(v_x0), vget_low_s16(v_x1));
|
||||
int32x4_t v_t0_hi = vaddl_s16(vget_high_s16(v_x0), vget_high_s16(v_x1));
|
||||
int32x4_t v_t1_lo = vsubl_s16(vget_low_s16(v_x0), vget_low_s16(v_x1));
|
||||
int32x4_t v_t1_hi = vsubl_s16(vget_high_s16(v_x0), vget_high_s16(v_x1));
|
||||
int32x4_t v_t2_lo = vmull_n_s16(vget_low_s16(v_x2), (int16_t)cospi_24_64);
|
||||
int32x4_t v_t2_hi = vmull_n_s16(vget_high_s16(v_x2), (int16_t)cospi_24_64);
|
||||
int32x4_t v_t3_lo = vmull_n_s16(vget_low_s16(v_x3), (int16_t)cospi_24_64);
|
||||
int32x4_t v_t3_hi = vmull_n_s16(vget_high_s16(v_x3), (int16_t)cospi_24_64);
|
||||
v_t2_lo = vmlal_n_s16(v_t2_lo, vget_low_s16(v_x3), (int16_t)cospi_8_64);
|
||||
v_t2_hi = vmlal_n_s16(v_t2_hi, vget_high_s16(v_x3), (int16_t)cospi_8_64);
|
||||
v_t3_lo = vmlsl_n_s16(v_t3_lo, vget_low_s16(v_x2), (int16_t)cospi_8_64);
|
||||
v_t3_hi = vmlsl_n_s16(v_t3_hi, vget_high_s16(v_x2), (int16_t)cospi_8_64);
|
||||
v_t0_lo = vmulq_n_s32(v_t0_lo, (int32_t)cospi_16_64);
|
||||
v_t0_hi = vmulq_n_s32(v_t0_hi, (int32_t)cospi_16_64);
|
||||
v_t1_lo = vmulq_n_s32(v_t1_lo, (int32_t)cospi_16_64);
|
||||
v_t1_hi = vmulq_n_s32(v_t1_hi, (int32_t)cospi_16_64);
|
||||
{
|
||||
const int16x4_t a = vrshrn_n_s32(v_t0_lo, DCT_CONST_BITS);
|
||||
const int16x4_t b = vrshrn_n_s32(v_t0_hi, DCT_CONST_BITS);
|
||||
const int16x4_t c = vrshrn_n_s32(v_t1_lo, DCT_CONST_BITS);
|
||||
const int16x4_t d = vrshrn_n_s32(v_t1_hi, DCT_CONST_BITS);
|
||||
const int16x4_t e = vrshrn_n_s32(v_t2_lo, DCT_CONST_BITS);
|
||||
const int16x4_t f = vrshrn_n_s32(v_t2_hi, DCT_CONST_BITS);
|
||||
const int16x4_t g = vrshrn_n_s32(v_t3_lo, DCT_CONST_BITS);
|
||||
const int16x4_t h = vrshrn_n_s32(v_t3_hi, DCT_CONST_BITS);
|
||||
out_0 = vcombine_s16(a, c); // 00 01 02 03 40 41 42 43
|
||||
out_2 = vcombine_s16(e, g); // 20 21 22 23 60 61 62 63
|
||||
out_4 = vcombine_s16(b, d); // 04 05 06 07 44 45 46 47
|
||||
out_6 = vcombine_s16(f, h); // 24 25 26 27 64 65 66 67
|
||||
}
|
||||
// Stage 2
|
||||
v_x0 = vsubq_s16(v_s6, v_s5);
|
||||
v_x1 = vaddq_s16(v_s6, v_s5);
|
||||
v_t0_lo = vmull_n_s16(vget_low_s16(v_x0), (int16_t)cospi_16_64);
|
||||
v_t0_hi = vmull_n_s16(vget_high_s16(v_x0), (int16_t)cospi_16_64);
|
||||
v_t1_lo = vmull_n_s16(vget_low_s16(v_x1), (int16_t)cospi_16_64);
|
||||
v_t1_hi = vmull_n_s16(vget_high_s16(v_x1), (int16_t)cospi_16_64);
|
||||
{
|
||||
const int16x4_t a = vrshrn_n_s32(v_t0_lo, DCT_CONST_BITS);
|
||||
const int16x4_t b = vrshrn_n_s32(v_t0_hi, DCT_CONST_BITS);
|
||||
const int16x4_t c = vrshrn_n_s32(v_t1_lo, DCT_CONST_BITS);
|
||||
const int16x4_t d = vrshrn_n_s32(v_t1_hi, DCT_CONST_BITS);
|
||||
const int16x8_t ab = vcombine_s16(a, b);
|
||||
const int16x8_t cd = vcombine_s16(c, d);
|
||||
// Stage 3
|
||||
v_x0 = vaddq_s16(v_s4, ab);
|
||||
v_x1 = vsubq_s16(v_s4, ab);
|
||||
v_x2 = vsubq_s16(v_s7, cd);
|
||||
v_x3 = vaddq_s16(v_s7, cd);
|
||||
}
|
||||
// Stage 4
|
||||
v_t0_lo = vmull_n_s16(vget_low_s16(v_x3), (int16_t)cospi_4_64);
|
||||
v_t0_hi = vmull_n_s16(vget_high_s16(v_x3), (int16_t)cospi_4_64);
|
||||
v_t0_lo = vmlal_n_s16(v_t0_lo, vget_low_s16(v_x0), (int16_t)cospi_28_64);
|
||||
v_t0_hi = vmlal_n_s16(v_t0_hi, vget_high_s16(v_x0), (int16_t)cospi_28_64);
|
||||
v_t1_lo = vmull_n_s16(vget_low_s16(v_x1), (int16_t)cospi_12_64);
|
||||
v_t1_hi = vmull_n_s16(vget_high_s16(v_x1), (int16_t)cospi_12_64);
|
||||
v_t1_lo = vmlal_n_s16(v_t1_lo, vget_low_s16(v_x2), (int16_t)cospi_20_64);
|
||||
v_t1_hi = vmlal_n_s16(v_t1_hi, vget_high_s16(v_x2), (int16_t)cospi_20_64);
|
||||
v_t2_lo = vmull_n_s16(vget_low_s16(v_x2), (int16_t)cospi_12_64);
|
||||
v_t2_hi = vmull_n_s16(vget_high_s16(v_x2), (int16_t)cospi_12_64);
|
||||
v_t2_lo = vmlsl_n_s16(v_t2_lo, vget_low_s16(v_x1), (int16_t)cospi_20_64);
|
||||
v_t2_hi = vmlsl_n_s16(v_t2_hi, vget_high_s16(v_x1), (int16_t)cospi_20_64);
|
||||
v_t3_lo = vmull_n_s16(vget_low_s16(v_x3), (int16_t)cospi_28_64);
|
||||
v_t3_hi = vmull_n_s16(vget_high_s16(v_x3), (int16_t)cospi_28_64);
|
||||
v_t3_lo = vmlsl_n_s16(v_t3_lo, vget_low_s16(v_x0), (int16_t)cospi_4_64);
|
||||
v_t3_hi = vmlsl_n_s16(v_t3_hi, vget_high_s16(v_x0), (int16_t)cospi_4_64);
|
||||
{
|
||||
const int16x4_t a = vrshrn_n_s32(v_t0_lo, DCT_CONST_BITS);
|
||||
const int16x4_t b = vrshrn_n_s32(v_t0_hi, DCT_CONST_BITS);
|
||||
const int16x4_t c = vrshrn_n_s32(v_t1_lo, DCT_CONST_BITS);
|
||||
const int16x4_t d = vrshrn_n_s32(v_t1_hi, DCT_CONST_BITS);
|
||||
const int16x4_t e = vrshrn_n_s32(v_t2_lo, DCT_CONST_BITS);
|
||||
const int16x4_t f = vrshrn_n_s32(v_t2_hi, DCT_CONST_BITS);
|
||||
const int16x4_t g = vrshrn_n_s32(v_t3_lo, DCT_CONST_BITS);
|
||||
const int16x4_t h = vrshrn_n_s32(v_t3_hi, DCT_CONST_BITS);
|
||||
out_1 = vcombine_s16(a, c); // 10 11 12 13 50 51 52 53
|
||||
out_3 = vcombine_s16(e, g); // 30 31 32 33 70 71 72 73
|
||||
out_5 = vcombine_s16(b, d); // 14 15 16 17 54 55 56 57
|
||||
out_7 = vcombine_s16(f, h); // 34 35 36 37 74 75 76 77
|
||||
}
|
||||
// transpose 8x8
|
||||
{
|
||||
// 00 01 02 03 40 41 42 43
|
||||
// 10 11 12 13 50 51 52 53
|
||||
// 20 21 22 23 60 61 62 63
|
||||
// 30 31 32 33 70 71 72 73
|
||||
// 04 05 06 07 44 45 46 47
|
||||
// 14 15 16 17 54 55 56 57
|
||||
// 24 25 26 27 64 65 66 67
|
||||
// 34 35 36 37 74 75 76 77
|
||||
const int32x4x2_t r02_s32 =
|
||||
vtrnq_s32(vreinterpretq_s32_s16(out_0), vreinterpretq_s32_s16(out_2));
|
||||
const int32x4x2_t r13_s32 =
|
||||
vtrnq_s32(vreinterpretq_s32_s16(out_1), vreinterpretq_s32_s16(out_3));
|
||||
const int32x4x2_t r46_s32 =
|
||||
vtrnq_s32(vreinterpretq_s32_s16(out_4), vreinterpretq_s32_s16(out_6));
|
||||
const int32x4x2_t r57_s32 =
|
||||
vtrnq_s32(vreinterpretq_s32_s16(out_5), vreinterpretq_s32_s16(out_7));
|
||||
const int16x8x2_t r01_s16 =
|
||||
vtrnq_s16(vreinterpretq_s16_s32(r02_s32.val[0]),
|
||||
vreinterpretq_s16_s32(r13_s32.val[0]));
|
||||
const int16x8x2_t r23_s16 =
|
||||
vtrnq_s16(vreinterpretq_s16_s32(r02_s32.val[1]),
|
||||
vreinterpretq_s16_s32(r13_s32.val[1]));
|
||||
const int16x8x2_t r45_s16 =
|
||||
vtrnq_s16(vreinterpretq_s16_s32(r46_s32.val[0]),
|
||||
vreinterpretq_s16_s32(r57_s32.val[0]));
|
||||
const int16x8x2_t r67_s16 =
|
||||
vtrnq_s16(vreinterpretq_s16_s32(r46_s32.val[1]),
|
||||
vreinterpretq_s16_s32(r57_s32.val[1]));
|
||||
input_0 = r01_s16.val[0];
|
||||
input_1 = r01_s16.val[1];
|
||||
input_2 = r23_s16.val[0];
|
||||
input_3 = r23_s16.val[1];
|
||||
input_4 = r45_s16.val[0];
|
||||
input_5 = r45_s16.val[1];
|
||||
input_6 = r67_s16.val[0];
|
||||
input_7 = r67_s16.val[1];
|
||||
// 00 10 20 30 40 50 60 70
|
||||
// 01 11 21 31 41 51 61 71
|
||||
// 02 12 22 32 42 52 62 72
|
||||
// 03 13 23 33 43 53 63 73
|
||||
// 04 14 24 34 44 54 64 74
|
||||
// 05 15 25 35 45 55 65 75
|
||||
// 06 16 26 36 46 56 66 76
|
||||
// 07 17 27 37 47 57 67 77
|
||||
}
|
||||
} // for
|
||||
{
|
||||
// from aom_dct_sse2.c
|
||||
// Post-condition (division by two)
|
||||
// division of two 16 bits signed numbers using shifts
|
||||
// n / 2 = (n - (n >> 15)) >> 1
|
||||
const int16x8_t sign_in0 = vshrq_n_s16(input_0, 15);
|
||||
const int16x8_t sign_in1 = vshrq_n_s16(input_1, 15);
|
||||
const int16x8_t sign_in2 = vshrq_n_s16(input_2, 15);
|
||||
const int16x8_t sign_in3 = vshrq_n_s16(input_3, 15);
|
||||
const int16x8_t sign_in4 = vshrq_n_s16(input_4, 15);
|
||||
const int16x8_t sign_in5 = vshrq_n_s16(input_5, 15);
|
||||
const int16x8_t sign_in6 = vshrq_n_s16(input_6, 15);
|
||||
const int16x8_t sign_in7 = vshrq_n_s16(input_7, 15);
|
||||
input_0 = vhsubq_s16(input_0, sign_in0);
|
||||
input_1 = vhsubq_s16(input_1, sign_in1);
|
||||
input_2 = vhsubq_s16(input_2, sign_in2);
|
||||
input_3 = vhsubq_s16(input_3, sign_in3);
|
||||
input_4 = vhsubq_s16(input_4, sign_in4);
|
||||
input_5 = vhsubq_s16(input_5, sign_in5);
|
||||
input_6 = vhsubq_s16(input_6, sign_in6);
|
||||
input_7 = vhsubq_s16(input_7, sign_in7);
|
||||
// store results
|
||||
vst1q_s16(&final_output[0 * 8], input_0);
|
||||
vst1q_s16(&final_output[1 * 8], input_1);
|
||||
vst1q_s16(&final_output[2 * 8], input_2);
|
||||
vst1q_s16(&final_output[3 * 8], input_3);
|
||||
vst1q_s16(&final_output[4 * 8], input_4);
|
||||
vst1q_s16(&final_output[5 * 8], input_5);
|
||||
vst1q_s16(&final_output[6 * 8], input_6);
|
||||
vst1q_s16(&final_output[7 * 8], input_7);
|
||||
}
|
||||
}
|
||||
|
||||
void aom_fdct8x8_1_neon(const int16_t *input, int16_t *output, int stride) {
|
||||
int r;
|
||||
int16x8_t sum = vld1q_s16(&input[0]);
|
||||
for (r = 1; r < 8; ++r) {
|
||||
const int16x8_t input_00 = vld1q_s16(&input[r * stride]);
|
||||
sum = vaddq_s16(sum, input_00);
|
||||
}
|
||||
{
|
||||
const int32x4_t a = vpaddlq_s16(sum);
|
||||
const int64x2_t b = vpaddlq_s32(a);
|
||||
const int32x2_t c = vadd_s32(vreinterpret_s32_s64(vget_low_s64(b)),
|
||||
vreinterpret_s32_s64(vget_high_s64(b)));
|
||||
output[0] = vget_lane_s16(vreinterpret_s16_s32(c), 0);
|
||||
output[1] = 0;
|
||||
}
|
||||
}
|
||||
200
third_party/aom/aom_dsp/arm/hadamard_neon.c
vendored
Normal file
200
third_party/aom/aom_dsp/arm/hadamard_neon.c
vendored
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <arm_neon.h>
|
||||
|
||||
#include "./aom_dsp_rtcd.h"
|
||||
|
||||
static void hadamard8x8_one_pass(int16x8_t *a0, int16x8_t *a1, int16x8_t *a2,
|
||||
int16x8_t *a3, int16x8_t *a4, int16x8_t *a5,
|
||||
int16x8_t *a6, int16x8_t *a7) {
|
||||
const int16x8_t b0 = vaddq_s16(*a0, *a1);
|
||||
const int16x8_t b1 = vsubq_s16(*a0, *a1);
|
||||
const int16x8_t b2 = vaddq_s16(*a2, *a3);
|
||||
const int16x8_t b3 = vsubq_s16(*a2, *a3);
|
||||
const int16x8_t b4 = vaddq_s16(*a4, *a5);
|
||||
const int16x8_t b5 = vsubq_s16(*a4, *a5);
|
||||
const int16x8_t b6 = vaddq_s16(*a6, *a7);
|
||||
const int16x8_t b7 = vsubq_s16(*a6, *a7);
|
||||
|
||||
const int16x8_t c0 = vaddq_s16(b0, b2);
|
||||
const int16x8_t c1 = vaddq_s16(b1, b3);
|
||||
const int16x8_t c2 = vsubq_s16(b0, b2);
|
||||
const int16x8_t c3 = vsubq_s16(b1, b3);
|
||||
const int16x8_t c4 = vaddq_s16(b4, b6);
|
||||
const int16x8_t c5 = vaddq_s16(b5, b7);
|
||||
const int16x8_t c6 = vsubq_s16(b4, b6);
|
||||
const int16x8_t c7 = vsubq_s16(b5, b7);
|
||||
|
||||
*a0 = vaddq_s16(c0, c4);
|
||||
*a1 = vsubq_s16(c2, c6);
|
||||
*a2 = vsubq_s16(c0, c4);
|
||||
*a3 = vaddq_s16(c2, c6);
|
||||
*a4 = vaddq_s16(c3, c7);
|
||||
*a5 = vsubq_s16(c3, c7);
|
||||
*a6 = vsubq_s16(c1, c5);
|
||||
*a7 = vaddq_s16(c1, c5);
|
||||
}
|
||||
|
||||
// TODO(johannkoenig): Make a transpose library and dedup with idct. Consider
|
||||
// reversing transpose order which may make it easier for the compiler to
|
||||
// reconcile the vtrn.64 moves.
|
||||
static void transpose8x8(int16x8_t *a0, int16x8_t *a1, int16x8_t *a2,
|
||||
int16x8_t *a3, int16x8_t *a4, int16x8_t *a5,
|
||||
int16x8_t *a6, int16x8_t *a7) {
|
||||
// Swap 64 bit elements. Goes from:
|
||||
// a0: 00 01 02 03 04 05 06 07
|
||||
// a1: 08 09 10 11 12 13 14 15
|
||||
// a2: 16 17 18 19 20 21 22 23
|
||||
// a3: 24 25 26 27 28 29 30 31
|
||||
// a4: 32 33 34 35 36 37 38 39
|
||||
// a5: 40 41 42 43 44 45 46 47
|
||||
// a6: 48 49 50 51 52 53 54 55
|
||||
// a7: 56 57 58 59 60 61 62 63
|
||||
// to:
|
||||
// a04_lo: 00 01 02 03 32 33 34 35
|
||||
// a15_lo: 08 09 10 11 40 41 42 43
|
||||
// a26_lo: 16 17 18 19 48 49 50 51
|
||||
// a37_lo: 24 25 26 27 56 57 58 59
|
||||
// a04_hi: 04 05 06 07 36 37 38 39
|
||||
// a15_hi: 12 13 14 15 44 45 46 47
|
||||
// a26_hi: 20 21 22 23 52 53 54 55
|
||||
// a37_hi: 28 29 30 31 60 61 62 63
|
||||
const int16x8_t a04_lo = vcombine_s16(vget_low_s16(*a0), vget_low_s16(*a4));
|
||||
const int16x8_t a15_lo = vcombine_s16(vget_low_s16(*a1), vget_low_s16(*a5));
|
||||
const int16x8_t a26_lo = vcombine_s16(vget_low_s16(*a2), vget_low_s16(*a6));
|
||||
const int16x8_t a37_lo = vcombine_s16(vget_low_s16(*a3), vget_low_s16(*a7));
|
||||
const int16x8_t a04_hi = vcombine_s16(vget_high_s16(*a0), vget_high_s16(*a4));
|
||||
const int16x8_t a15_hi = vcombine_s16(vget_high_s16(*a1), vget_high_s16(*a5));
|
||||
const int16x8_t a26_hi = vcombine_s16(vget_high_s16(*a2), vget_high_s16(*a6));
|
||||
const int16x8_t a37_hi = vcombine_s16(vget_high_s16(*a3), vget_high_s16(*a7));
|
||||
|
||||
// Swap 32 bit elements resulting in:
|
||||
// a0246_lo:
|
||||
// 00 01 16 17 32 33 48 49
|
||||
// 02 03 18 19 34 35 50 51
|
||||
// a1357_lo:
|
||||
// 08 09 24 25 40 41 56 57
|
||||
// 10 11 26 27 42 43 58 59
|
||||
// a0246_hi:
|
||||
// 04 05 20 21 36 37 52 53
|
||||
// 06 07 22 23 38 39 54 55
|
||||
// a1657_hi:
|
||||
// 12 13 28 29 44 45 60 61
|
||||
// 14 15 30 31 46 47 62 63
|
||||
const int32x4x2_t a0246_lo =
|
||||
vtrnq_s32(vreinterpretq_s32_s16(a04_lo), vreinterpretq_s32_s16(a26_lo));
|
||||
const int32x4x2_t a1357_lo =
|
||||
vtrnq_s32(vreinterpretq_s32_s16(a15_lo), vreinterpretq_s32_s16(a37_lo));
|
||||
const int32x4x2_t a0246_hi =
|
||||
vtrnq_s32(vreinterpretq_s32_s16(a04_hi), vreinterpretq_s32_s16(a26_hi));
|
||||
const int32x4x2_t a1357_hi =
|
||||
vtrnq_s32(vreinterpretq_s32_s16(a15_hi), vreinterpretq_s32_s16(a37_hi));
|
||||
|
||||
// Swap 16 bit elements resulting in:
|
||||
// b0:
|
||||
// 00 08 16 24 32 40 48 56
|
||||
// 01 09 17 25 33 41 49 57
|
||||
// b1:
|
||||
// 02 10 18 26 34 42 50 58
|
||||
// 03 11 19 27 35 43 51 59
|
||||
// b2:
|
||||
// 04 12 20 28 36 44 52 60
|
||||
// 05 13 21 29 37 45 53 61
|
||||
// b3:
|
||||
// 06 14 22 30 38 46 54 62
|
||||
// 07 15 23 31 39 47 55 63
|
||||
const int16x8x2_t b0 = vtrnq_s16(vreinterpretq_s16_s32(a0246_lo.val[0]),
|
||||
vreinterpretq_s16_s32(a1357_lo.val[0]));
|
||||
const int16x8x2_t b1 = vtrnq_s16(vreinterpretq_s16_s32(a0246_lo.val[1]),
|
||||
vreinterpretq_s16_s32(a1357_lo.val[1]));
|
||||
const int16x8x2_t b2 = vtrnq_s16(vreinterpretq_s16_s32(a0246_hi.val[0]),
|
||||
vreinterpretq_s16_s32(a1357_hi.val[0]));
|
||||
const int16x8x2_t b3 = vtrnq_s16(vreinterpretq_s16_s32(a0246_hi.val[1]),
|
||||
vreinterpretq_s16_s32(a1357_hi.val[1]));
|
||||
|
||||
*a0 = b0.val[0];
|
||||
*a1 = b0.val[1];
|
||||
*a2 = b1.val[0];
|
||||
*a3 = b1.val[1];
|
||||
*a4 = b2.val[0];
|
||||
*a5 = b2.val[1];
|
||||
*a6 = b3.val[0];
|
||||
*a7 = b3.val[1];
|
||||
}
|
||||
|
||||
void aom_hadamard_8x8_neon(const int16_t *src_diff, int src_stride,
|
||||
int16_t *coeff) {
|
||||
int16x8_t a0 = vld1q_s16(src_diff);
|
||||
int16x8_t a1 = vld1q_s16(src_diff + src_stride);
|
||||
int16x8_t a2 = vld1q_s16(src_diff + 2 * src_stride);
|
||||
int16x8_t a3 = vld1q_s16(src_diff + 3 * src_stride);
|
||||
int16x8_t a4 = vld1q_s16(src_diff + 4 * src_stride);
|
||||
int16x8_t a5 = vld1q_s16(src_diff + 5 * src_stride);
|
||||
int16x8_t a6 = vld1q_s16(src_diff + 6 * src_stride);
|
||||
int16x8_t a7 = vld1q_s16(src_diff + 7 * src_stride);
|
||||
|
||||
hadamard8x8_one_pass(&a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7);
|
||||
|
||||
transpose8x8(&a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7);
|
||||
|
||||
hadamard8x8_one_pass(&a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7);
|
||||
|
||||
// Skip the second transpose because it is not required.
|
||||
|
||||
vst1q_s16(coeff + 0, a0);
|
||||
vst1q_s16(coeff + 8, a1);
|
||||
vst1q_s16(coeff + 16, a2);
|
||||
vst1q_s16(coeff + 24, a3);
|
||||
vst1q_s16(coeff + 32, a4);
|
||||
vst1q_s16(coeff + 40, a5);
|
||||
vst1q_s16(coeff + 48, a6);
|
||||
vst1q_s16(coeff + 56, a7);
|
||||
}
|
||||
|
||||
void aom_hadamard_16x16_neon(const int16_t *src_diff, int src_stride,
|
||||
int16_t *coeff) {
|
||||
int i;
|
||||
|
||||
/* Rearrange 16x16 to 8x32 and remove stride.
|
||||
* Top left first. */
|
||||
aom_hadamard_8x8_neon(src_diff + 0 + 0 * src_stride, src_stride, coeff + 0);
|
||||
/* Top right. */
|
||||
aom_hadamard_8x8_neon(src_diff + 8 + 0 * src_stride, src_stride, coeff + 64);
|
||||
/* Bottom left. */
|
||||
aom_hadamard_8x8_neon(src_diff + 0 + 8 * src_stride, src_stride, coeff + 128);
|
||||
/* Bottom right. */
|
||||
aom_hadamard_8x8_neon(src_diff + 8 + 8 * src_stride, src_stride, coeff + 192);
|
||||
|
||||
for (i = 0; i < 64; i += 8) {
|
||||
const int16x8_t a0 = vld1q_s16(coeff + 0);
|
||||
const int16x8_t a1 = vld1q_s16(coeff + 64);
|
||||
const int16x8_t a2 = vld1q_s16(coeff + 128);
|
||||
const int16x8_t a3 = vld1q_s16(coeff + 192);
|
||||
|
||||
const int16x8_t b0 = vhaddq_s16(a0, a1);
|
||||
const int16x8_t b1 = vhsubq_s16(a0, a1);
|
||||
const int16x8_t b2 = vhaddq_s16(a2, a3);
|
||||
const int16x8_t b3 = vhsubq_s16(a2, a3);
|
||||
|
||||
const int16x8_t c0 = vaddq_s16(b0, b2);
|
||||
const int16x8_t c1 = vaddq_s16(b1, b3);
|
||||
const int16x8_t c2 = vsubq_s16(b0, b2);
|
||||
const int16x8_t c3 = vsubq_s16(b1, b3);
|
||||
|
||||
vst1q_s16(coeff + 0, c0);
|
||||
vst1q_s16(coeff + 64, c1);
|
||||
vst1q_s16(coeff + 128, c2);
|
||||
vst1q_s16(coeff + 192, c3);
|
||||
|
||||
coeff += 8;
|
||||
}
|
||||
}
|
||||
201
third_party/aom/aom_dsp/arm/idct16x16_1_add_neon.asm
vendored
Normal file
201
third_party/aom/aom_dsp/arm/idct16x16_1_add_neon.asm
vendored
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
;
|
||||
; Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
;
|
||||
; This source code is subject to the terms of the BSD 2 Clause License and
|
||||
; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
; was not distributed with this source code in the LICENSE file, you can
|
||||
; obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
; Media Patent License 1.0 was not distributed with this source code in the
|
||||
; PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
;
|
||||
|
||||
|
||||
|
||||
EXPORT |aom_idct16x16_1_add_neon|
|
||||
ARM
|
||||
REQUIRE8
|
||||
PRESERVE8
|
||||
|
||||
AREA ||.text||, CODE, READONLY, ALIGN=2
|
||||
|
||||
;void aom_idct16x16_1_add_neon(int16_t *input, uint8_t *dest,
|
||||
; int dest_stride)
|
||||
;
|
||||
; r0 int16_t input
|
||||
; r1 uint8_t *dest
|
||||
; r2 int dest_stride)
|
||||
|
||||
|aom_idct16x16_1_add_neon| PROC
|
||||
ldrsh r0, [r0]
|
||||
|
||||
; generate cospi_16_64 = 11585
|
||||
mov r12, #0x2d00
|
||||
add r12, #0x41
|
||||
|
||||
; out = dct_const_round_shift(input[0] * cospi_16_64)
|
||||
mul r0, r0, r12 ; input[0] * cospi_16_64
|
||||
add r0, r0, #0x2000 ; +(1 << ((DCT_CONST_BITS) - 1))
|
||||
asr r0, r0, #14 ; >> DCT_CONST_BITS
|
||||
|
||||
; out = dct_const_round_shift(out * cospi_16_64)
|
||||
mul r0, r0, r12 ; out * cospi_16_64
|
||||
mov r12, r1 ; save dest
|
||||
add r0, r0, #0x2000 ; +(1 << ((DCT_CONST_BITS) - 1))
|
||||
asr r0, r0, #14 ; >> DCT_CONST_BITS
|
||||
|
||||
; a1 = ROUND_POWER_OF_TWO(out, 6)
|
||||
add r0, r0, #32 ; + (1 <<((6) - 1))
|
||||
asr r0, r0, #6 ; >> 6
|
||||
|
||||
vdup.s16 q0, r0 ; duplicate a1
|
||||
mov r0, #8
|
||||
sub r2, #8
|
||||
|
||||
; load destination data row0 - row3
|
||||
vld1.64 {d2}, [r1], r0
|
||||
vld1.64 {d3}, [r1], r2
|
||||
vld1.64 {d4}, [r1], r0
|
||||
vld1.64 {d5}, [r1], r2
|
||||
vld1.64 {d6}, [r1], r0
|
||||
vld1.64 {d7}, [r1], r2
|
||||
vld1.64 {d16}, [r1], r0
|
||||
vld1.64 {d17}, [r1], r2
|
||||
|
||||
vaddw.u8 q9, q0, d2 ; dest[x] + a1
|
||||
vaddw.u8 q10, q0, d3 ; dest[x] + a1
|
||||
vaddw.u8 q11, q0, d4 ; dest[x] + a1
|
||||
vaddw.u8 q12, q0, d5 ; dest[x] + a1
|
||||
vqmovun.s16 d2, q9 ; clip_pixel
|
||||
vqmovun.s16 d3, q10 ; clip_pixel
|
||||
vqmovun.s16 d30, q11 ; clip_pixel
|
||||
vqmovun.s16 d31, q12 ; clip_pixel
|
||||
vst1.64 {d2}, [r12], r0
|
||||
vst1.64 {d3}, [r12], r2
|
||||
vst1.64 {d30}, [r12], r0
|
||||
vst1.64 {d31}, [r12], r2
|
||||
|
||||
vaddw.u8 q9, q0, d6 ; dest[x] + a1
|
||||
vaddw.u8 q10, q0, d7 ; dest[x] + a1
|
||||
vaddw.u8 q11, q0, d16 ; dest[x] + a1
|
||||
vaddw.u8 q12, q0, d17 ; dest[x] + a1
|
||||
vqmovun.s16 d2, q9 ; clip_pixel
|
||||
vqmovun.s16 d3, q10 ; clip_pixel
|
||||
vqmovun.s16 d30, q11 ; clip_pixel
|
||||
vqmovun.s16 d31, q12 ; clip_pixel
|
||||
vst1.64 {d2}, [r12], r0
|
||||
vst1.64 {d3}, [r12], r2
|
||||
vst1.64 {d30}, [r12], r0
|
||||
vst1.64 {d31}, [r12], r2
|
||||
|
||||
; load destination data row4 - row7
|
||||
vld1.64 {d2}, [r1], r0
|
||||
vld1.64 {d3}, [r1], r2
|
||||
vld1.64 {d4}, [r1], r0
|
||||
vld1.64 {d5}, [r1], r2
|
||||
vld1.64 {d6}, [r1], r0
|
||||
vld1.64 {d7}, [r1], r2
|
||||
vld1.64 {d16}, [r1], r0
|
||||
vld1.64 {d17}, [r1], r2
|
||||
|
||||
vaddw.u8 q9, q0, d2 ; dest[x] + a1
|
||||
vaddw.u8 q10, q0, d3 ; dest[x] + a1
|
||||
vaddw.u8 q11, q0, d4 ; dest[x] + a1
|
||||
vaddw.u8 q12, q0, d5 ; dest[x] + a1
|
||||
vqmovun.s16 d2, q9 ; clip_pixel
|
||||
vqmovun.s16 d3, q10 ; clip_pixel
|
||||
vqmovun.s16 d30, q11 ; clip_pixel
|
||||
vqmovun.s16 d31, q12 ; clip_pixel
|
||||
vst1.64 {d2}, [r12], r0
|
||||
vst1.64 {d3}, [r12], r2
|
||||
vst1.64 {d30}, [r12], r0
|
||||
vst1.64 {d31}, [r12], r2
|
||||
|
||||
vaddw.u8 q9, q0, d6 ; dest[x] + a1
|
||||
vaddw.u8 q10, q0, d7 ; dest[x] + a1
|
||||
vaddw.u8 q11, q0, d16 ; dest[x] + a1
|
||||
vaddw.u8 q12, q0, d17 ; dest[x] + a1
|
||||
vqmovun.s16 d2, q9 ; clip_pixel
|
||||
vqmovun.s16 d3, q10 ; clip_pixel
|
||||
vqmovun.s16 d30, q11 ; clip_pixel
|
||||
vqmovun.s16 d31, q12 ; clip_pixel
|
||||
vst1.64 {d2}, [r12], r0
|
||||
vst1.64 {d3}, [r12], r2
|
||||
vst1.64 {d30}, [r12], r0
|
||||
vst1.64 {d31}, [r12], r2
|
||||
|
||||
; load destination data row8 - row11
|
||||
vld1.64 {d2}, [r1], r0
|
||||
vld1.64 {d3}, [r1], r2
|
||||
vld1.64 {d4}, [r1], r0
|
||||
vld1.64 {d5}, [r1], r2
|
||||
vld1.64 {d6}, [r1], r0
|
||||
vld1.64 {d7}, [r1], r2
|
||||
vld1.64 {d16}, [r1], r0
|
||||
vld1.64 {d17}, [r1], r2
|
||||
|
||||
vaddw.u8 q9, q0, d2 ; dest[x] + a1
|
||||
vaddw.u8 q10, q0, d3 ; dest[x] + a1
|
||||
vaddw.u8 q11, q0, d4 ; dest[x] + a1
|
||||
vaddw.u8 q12, q0, d5 ; dest[x] + a1
|
||||
vqmovun.s16 d2, q9 ; clip_pixel
|
||||
vqmovun.s16 d3, q10 ; clip_pixel
|
||||
vqmovun.s16 d30, q11 ; clip_pixel
|
||||
vqmovun.s16 d31, q12 ; clip_pixel
|
||||
vst1.64 {d2}, [r12], r0
|
||||
vst1.64 {d3}, [r12], r2
|
||||
vst1.64 {d30}, [r12], r0
|
||||
vst1.64 {d31}, [r12], r2
|
||||
|
||||
vaddw.u8 q9, q0, d6 ; dest[x] + a1
|
||||
vaddw.u8 q10, q0, d7 ; dest[x] + a1
|
||||
vaddw.u8 q11, q0, d16 ; dest[x] + a1
|
||||
vaddw.u8 q12, q0, d17 ; dest[x] + a1
|
||||
vqmovun.s16 d2, q9 ; clip_pixel
|
||||
vqmovun.s16 d3, q10 ; clip_pixel
|
||||
vqmovun.s16 d30, q11 ; clip_pixel
|
||||
vqmovun.s16 d31, q12 ; clip_pixel
|
||||
vst1.64 {d2}, [r12], r0
|
||||
vst1.64 {d3}, [r12], r2
|
||||
vst1.64 {d30}, [r12], r0
|
||||
vst1.64 {d31}, [r12], r2
|
||||
|
||||
; load destination data row12 - row15
|
||||
vld1.64 {d2}, [r1], r0
|
||||
vld1.64 {d3}, [r1], r2
|
||||
vld1.64 {d4}, [r1], r0
|
||||
vld1.64 {d5}, [r1], r2
|
||||
vld1.64 {d6}, [r1], r0
|
||||
vld1.64 {d7}, [r1], r2
|
||||
vld1.64 {d16}, [r1], r0
|
||||
vld1.64 {d17}, [r1], r2
|
||||
|
||||
vaddw.u8 q9, q0, d2 ; dest[x] + a1
|
||||
vaddw.u8 q10, q0, d3 ; dest[x] + a1
|
||||
vaddw.u8 q11, q0, d4 ; dest[x] + a1
|
||||
vaddw.u8 q12, q0, d5 ; dest[x] + a1
|
||||
vqmovun.s16 d2, q9 ; clip_pixel
|
||||
vqmovun.s16 d3, q10 ; clip_pixel
|
||||
vqmovun.s16 d30, q11 ; clip_pixel
|
||||
vqmovun.s16 d31, q12 ; clip_pixel
|
||||
vst1.64 {d2}, [r12], r0
|
||||
vst1.64 {d3}, [r12], r2
|
||||
vst1.64 {d30}, [r12], r0
|
||||
vst1.64 {d31}, [r12], r2
|
||||
|
||||
vaddw.u8 q9, q0, d6 ; dest[x] + a1
|
||||
vaddw.u8 q10, q0, d7 ; dest[x] + a1
|
||||
vaddw.u8 q11, q0, d16 ; dest[x] + a1
|
||||
vaddw.u8 q12, q0, d17 ; dest[x] + a1
|
||||
vqmovun.s16 d2, q9 ; clip_pixel
|
||||
vqmovun.s16 d3, q10 ; clip_pixel
|
||||
vqmovun.s16 d30, q11 ; clip_pixel
|
||||
vqmovun.s16 d31, q12 ; clip_pixel
|
||||
vst1.64 {d2}, [r12], r0
|
||||
vst1.64 {d3}, [r12], r2
|
||||
vst1.64 {d30}, [r12], r0
|
||||
vst1.64 {d31}, [r12], r2
|
||||
|
||||
bx lr
|
||||
ENDP ; |aom_idct16x16_1_add_neon|
|
||||
|
||||
END
|
||||
59
third_party/aom/aom_dsp/arm/idct16x16_1_add_neon.c
vendored
Normal file
59
third_party/aom/aom_dsp/arm/idct16x16_1_add_neon.c
vendored
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <arm_neon.h>
|
||||
|
||||
#include "aom_dsp/inv_txfm.h"
|
||||
#include "aom_ports/mem.h"
|
||||
|
||||
void aom_idct16x16_1_add_neon(int16_t *input, uint8_t *dest, int dest_stride) {
|
||||
uint8x8_t d2u8, d3u8, d30u8, d31u8;
|
||||
uint64x1_t d2u64, d3u64, d4u64, d5u64;
|
||||
uint16x8_t q0u16, q9u16, q10u16, q11u16, q12u16;
|
||||
int16x8_t q0s16;
|
||||
uint8_t *d1, *d2;
|
||||
int16_t i, j, a1;
|
||||
int16_t out = dct_const_round_shift(input[0] * cospi_16_64);
|
||||
out = dct_const_round_shift(out * cospi_16_64);
|
||||
a1 = ROUND_POWER_OF_TWO(out, 6);
|
||||
|
||||
q0s16 = vdupq_n_s16(a1);
|
||||
q0u16 = vreinterpretq_u16_s16(q0s16);
|
||||
|
||||
for (d1 = d2 = dest, i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 2; j++) {
|
||||
d2u64 = vld1_u64((const uint64_t *)d1);
|
||||
d3u64 = vld1_u64((const uint64_t *)(d1 + 8));
|
||||
d1 += dest_stride;
|
||||
d4u64 = vld1_u64((const uint64_t *)d1);
|
||||
d5u64 = vld1_u64((const uint64_t *)(d1 + 8));
|
||||
d1 += dest_stride;
|
||||
|
||||
q9u16 = vaddw_u8(q0u16, vreinterpret_u8_u64(d2u64));
|
||||
q10u16 = vaddw_u8(q0u16, vreinterpret_u8_u64(d3u64));
|
||||
q11u16 = vaddw_u8(q0u16, vreinterpret_u8_u64(d4u64));
|
||||
q12u16 = vaddw_u8(q0u16, vreinterpret_u8_u64(d5u64));
|
||||
|
||||
d2u8 = vqmovun_s16(vreinterpretq_s16_u16(q9u16));
|
||||
d3u8 = vqmovun_s16(vreinterpretq_s16_u16(q10u16));
|
||||
d30u8 = vqmovun_s16(vreinterpretq_s16_u16(q11u16));
|
||||
d31u8 = vqmovun_s16(vreinterpretq_s16_u16(q12u16));
|
||||
|
||||
vst1_u64((uint64_t *)d2, vreinterpret_u64_u8(d2u8));
|
||||
vst1_u64((uint64_t *)(d2 + 8), vreinterpret_u64_u8(d3u8));
|
||||
d2 += dest_stride;
|
||||
vst1_u64((uint64_t *)d2, vreinterpret_u64_u8(d30u8));
|
||||
vst1_u64((uint64_t *)(d2 + 8), vreinterpret_u64_u8(d31u8));
|
||||
d2 += dest_stride;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
1182
third_party/aom/aom_dsp/arm/idct16x16_add_neon.asm
vendored
Normal file
1182
third_party/aom/aom_dsp/arm/idct16x16_add_neon.asm
vendored
Normal file
File diff suppressed because it is too large
Load diff
1295
third_party/aom/aom_dsp/arm/idct16x16_add_neon.c
vendored
Normal file
1295
third_party/aom/aom_dsp/arm/idct16x16_add_neon.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
152
third_party/aom/aom_dsp/arm/idct16x16_neon.c
vendored
Normal file
152
third_party/aom/aom_dsp/arm/idct16x16_neon.c
vendored
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include "aom_dsp/aom_dsp_common.h"
|
||||
|
||||
void aom_idct16x16_256_add_neon_pass1(const int16_t *input, int16_t *output,
|
||||
int output_stride);
|
||||
void aom_idct16x16_256_add_neon_pass2(const int16_t *src, int16_t *output,
|
||||
int16_t *pass1Output, int16_t skip_adding,
|
||||
uint8_t *dest, int dest_stride);
|
||||
void aom_idct16x16_10_add_neon_pass1(const int16_t *input, int16_t *output,
|
||||
int output_stride);
|
||||
void aom_idct16x16_10_add_neon_pass2(const int16_t *src, int16_t *output,
|
||||
int16_t *pass1Output, int16_t skip_adding,
|
||||
uint8_t *dest, int dest_stride);
|
||||
|
||||
#if HAVE_NEON_ASM
|
||||
/* For ARM NEON, d8-d15 are callee-saved registers, and need to be saved. */
|
||||
extern void aom_push_neon(int64_t *store);
|
||||
extern void aom_pop_neon(int64_t *store);
|
||||
#endif // HAVE_NEON_ASM
|
||||
|
||||
void aom_idct16x16_256_add_neon(const int16_t *input, uint8_t *dest,
|
||||
int dest_stride) {
|
||||
#if HAVE_NEON_ASM
|
||||
int64_t store_reg[8];
|
||||
#endif
|
||||
int16_t pass1_output[16 * 16] = { 0 };
|
||||
int16_t row_idct_output[16 * 16] = { 0 };
|
||||
|
||||
#if HAVE_NEON_ASM
|
||||
// save d8-d15 register values.
|
||||
aom_push_neon(store_reg);
|
||||
#endif
|
||||
|
||||
/* Parallel idct on the upper 8 rows */
|
||||
// First pass processes even elements 0, 2, 4, 6, 8, 10, 12, 14 and save the
|
||||
// stage 6 result in pass1_output.
|
||||
aom_idct16x16_256_add_neon_pass1(input, pass1_output, 8);
|
||||
|
||||
// Second pass processes odd elements 1, 3, 5, 7, 9, 11, 13, 15 and combines
|
||||
// with result in pass1(pass1_output) to calculate final result in stage 7
|
||||
// which will be saved into row_idct_output.
|
||||
aom_idct16x16_256_add_neon_pass2(input + 1, row_idct_output, pass1_output, 0,
|
||||
dest, dest_stride);
|
||||
|
||||
/* Parallel idct on the lower 8 rows */
|
||||
// First pass processes even elements 0, 2, 4, 6, 8, 10, 12, 14 and save the
|
||||
// stage 6 result in pass1_output.
|
||||
aom_idct16x16_256_add_neon_pass1(input + 8 * 16, pass1_output, 8);
|
||||
|
||||
// Second pass processes odd elements 1, 3, 5, 7, 9, 11, 13, 15 and combines
|
||||
// with result in pass1(pass1_output) to calculate final result in stage 7
|
||||
// which will be saved into row_idct_output.
|
||||
aom_idct16x16_256_add_neon_pass2(input + 8 * 16 + 1, row_idct_output + 8,
|
||||
pass1_output, 0, dest, dest_stride);
|
||||
|
||||
/* Parallel idct on the left 8 columns */
|
||||
// First pass processes even elements 0, 2, 4, 6, 8, 10, 12, 14 and save the
|
||||
// stage 6 result in pass1_output.
|
||||
aom_idct16x16_256_add_neon_pass1(row_idct_output, pass1_output, 8);
|
||||
|
||||
// Second pass processes odd elements 1, 3, 5, 7, 9, 11, 13, 15 and combines
|
||||
// with result in pass1(pass1_output) to calculate final result in stage 7.
|
||||
// Then add the result to the destination data.
|
||||
aom_idct16x16_256_add_neon_pass2(row_idct_output + 1, row_idct_output,
|
||||
pass1_output, 1, dest, dest_stride);
|
||||
|
||||
/* Parallel idct on the right 8 columns */
|
||||
// First pass processes even elements 0, 2, 4, 6, 8, 10, 12, 14 and save the
|
||||
// stage 6 result in pass1_output.
|
||||
aom_idct16x16_256_add_neon_pass1(row_idct_output + 8 * 16, pass1_output, 8);
|
||||
|
||||
// Second pass processes odd elements 1, 3, 5, 7, 9, 11, 13, 15 and combines
|
||||
// with result in pass1(pass1_output) to calculate final result in stage 7.
|
||||
// Then add the result to the destination data.
|
||||
aom_idct16x16_256_add_neon_pass2(row_idct_output + 8 * 16 + 1,
|
||||
row_idct_output + 8, pass1_output, 1,
|
||||
dest + 8, dest_stride);
|
||||
|
||||
#if HAVE_NEON_ASM
|
||||
// restore d8-d15 register values.
|
||||
aom_pop_neon(store_reg);
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void aom_idct16x16_10_add_neon(const int16_t *input, uint8_t *dest,
|
||||
int dest_stride) {
|
||||
#if HAVE_NEON_ASM
|
||||
int64_t store_reg[8];
|
||||
#endif
|
||||
int16_t pass1_output[16 * 16] = { 0 };
|
||||
int16_t row_idct_output[16 * 16] = { 0 };
|
||||
|
||||
#if HAVE_NEON_ASM
|
||||
// save d8-d15 register values.
|
||||
aom_push_neon(store_reg);
|
||||
#endif
|
||||
|
||||
/* Parallel idct on the upper 8 rows */
|
||||
// First pass processes even elements 0, 2, 4, 6, 8, 10, 12, 14 and save the
|
||||
// stage 6 result in pass1_output.
|
||||
aom_idct16x16_10_add_neon_pass1(input, pass1_output, 8);
|
||||
|
||||
// Second pass processes odd elements 1, 3, 5, 7, 9, 11, 13, 15 and combines
|
||||
// with result in pass1(pass1_output) to calculate final result in stage 7
|
||||
// which will be saved into row_idct_output.
|
||||
aom_idct16x16_10_add_neon_pass2(input + 1, row_idct_output, pass1_output, 0,
|
||||
dest, dest_stride);
|
||||
|
||||
/* Skip Parallel idct on the lower 8 rows as they are all 0s */
|
||||
|
||||
/* Parallel idct on the left 8 columns */
|
||||
// First pass processes even elements 0, 2, 4, 6, 8, 10, 12, 14 and save the
|
||||
// stage 6 result in pass1_output.
|
||||
aom_idct16x16_256_add_neon_pass1(row_idct_output, pass1_output, 8);
|
||||
|
||||
// Second pass processes odd elements 1, 3, 5, 7, 9, 11, 13, 15 and combines
|
||||
// with result in pass1(pass1_output) to calculate final result in stage 7.
|
||||
// Then add the result to the destination data.
|
||||
aom_idct16x16_256_add_neon_pass2(row_idct_output + 1, row_idct_output,
|
||||
pass1_output, 1, dest, dest_stride);
|
||||
|
||||
/* Parallel idct on the right 8 columns */
|
||||
// First pass processes even elements 0, 2, 4, 6, 8, 10, 12, 14 and save the
|
||||
// stage 6 result in pass1_output.
|
||||
aom_idct16x16_256_add_neon_pass1(row_idct_output + 8 * 16, pass1_output, 8);
|
||||
|
||||
// Second pass processes odd elements 1, 3, 5, 7, 9, 11, 13, 15 and combines
|
||||
// with result in pass1(pass1_output) to calculate final result in stage 7.
|
||||
// Then add the result to the destination data.
|
||||
aom_idct16x16_256_add_neon_pass2(row_idct_output + 8 * 16 + 1,
|
||||
row_idct_output + 8, pass1_output, 1,
|
||||
dest + 8, dest_stride);
|
||||
|
||||
#if HAVE_NEON_ASM
|
||||
// restore d8-d15 register values.
|
||||
aom_pop_neon(store_reg);
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
147
third_party/aom/aom_dsp/arm/idct32x32_1_add_neon.asm
vendored
Normal file
147
third_party/aom/aom_dsp/arm/idct32x32_1_add_neon.asm
vendored
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
;
|
||||
; Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
;
|
||||
; This source code is subject to the terms of the BSD 2 Clause License and
|
||||
; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
; was not distributed with this source code in the LICENSE file, you can
|
||||
; obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
; Media Patent License 1.0 was not distributed with this source code in the
|
||||
; PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
;
|
||||
|
||||
|
||||
EXPORT |aom_idct32x32_1_add_neon|
|
||||
ARM
|
||||
REQUIRE8
|
||||
PRESERVE8
|
||||
|
||||
AREA ||.text||, CODE, READONLY, ALIGN=2
|
||||
|
||||
;TODO(hkuang): put the following macros in a seperate
|
||||
;file so other idct function could also use them.
|
||||
MACRO
|
||||
LD_16x8 $src, $stride
|
||||
vld1.8 {q8}, [$src], $stride
|
||||
vld1.8 {q9}, [$src], $stride
|
||||
vld1.8 {q10}, [$src], $stride
|
||||
vld1.8 {q11}, [$src], $stride
|
||||
vld1.8 {q12}, [$src], $stride
|
||||
vld1.8 {q13}, [$src], $stride
|
||||
vld1.8 {q14}, [$src], $stride
|
||||
vld1.8 {q15}, [$src], $stride
|
||||
MEND
|
||||
|
||||
MACRO
|
||||
ADD_DIFF_16x8 $diff
|
||||
vqadd.u8 q8, q8, $diff
|
||||
vqadd.u8 q9, q9, $diff
|
||||
vqadd.u8 q10, q10, $diff
|
||||
vqadd.u8 q11, q11, $diff
|
||||
vqadd.u8 q12, q12, $diff
|
||||
vqadd.u8 q13, q13, $diff
|
||||
vqadd.u8 q14, q14, $diff
|
||||
vqadd.u8 q15, q15, $diff
|
||||
MEND
|
||||
|
||||
MACRO
|
||||
SUB_DIFF_16x8 $diff
|
||||
vqsub.u8 q8, q8, $diff
|
||||
vqsub.u8 q9, q9, $diff
|
||||
vqsub.u8 q10, q10, $diff
|
||||
vqsub.u8 q11, q11, $diff
|
||||
vqsub.u8 q12, q12, $diff
|
||||
vqsub.u8 q13, q13, $diff
|
||||
vqsub.u8 q14, q14, $diff
|
||||
vqsub.u8 q15, q15, $diff
|
||||
MEND
|
||||
|
||||
MACRO
|
||||
ST_16x8 $dst, $stride
|
||||
vst1.8 {q8}, [$dst], $stride
|
||||
vst1.8 {q9}, [$dst], $stride
|
||||
vst1.8 {q10},[$dst], $stride
|
||||
vst1.8 {q11},[$dst], $stride
|
||||
vst1.8 {q12},[$dst], $stride
|
||||
vst1.8 {q13},[$dst], $stride
|
||||
vst1.8 {q14},[$dst], $stride
|
||||
vst1.8 {q15},[$dst], $stride
|
||||
MEND
|
||||
|
||||
;void aom_idct32x32_1_add_neon(int16_t *input, uint8_t *dest,
|
||||
; int dest_stride)
|
||||
;
|
||||
; r0 int16_t input
|
||||
; r1 uint8_t *dest
|
||||
; r2 int dest_stride
|
||||
|
||||
|aom_idct32x32_1_add_neon| PROC
|
||||
push {lr}
|
||||
pld [r1]
|
||||
add r3, r1, #16 ; r3 dest + 16 for second loop
|
||||
ldrsh r0, [r0]
|
||||
|
||||
; generate cospi_16_64 = 11585
|
||||
mov r12, #0x2d00
|
||||
add r12, #0x41
|
||||
|
||||
; out = dct_const_round_shift(input[0] * cospi_16_64)
|
||||
mul r0, r0, r12 ; input[0] * cospi_16_64
|
||||
add r0, r0, #0x2000 ; +(1 << ((DCT_CONST_BITS) - 1))
|
||||
asr r0, r0, #14 ; >> DCT_CONST_BITS
|
||||
|
||||
; out = dct_const_round_shift(out * cospi_16_64)
|
||||
mul r0, r0, r12 ; out * cospi_16_64
|
||||
mov r12, r1 ; save dest
|
||||
add r0, r0, #0x2000 ; +(1 << ((DCT_CONST_BITS) - 1))
|
||||
asr r0, r0, #14 ; >> DCT_CONST_BITS
|
||||
|
||||
; a1 = ROUND_POWER_OF_TWO(out, 6)
|
||||
add r0, r0, #32 ; + (1 <<((6) - 1))
|
||||
asrs r0, r0, #6 ; >> 6
|
||||
bge diff_positive_32_32
|
||||
|
||||
diff_negative_32_32
|
||||
neg r0, r0
|
||||
usat r0, #8, r0
|
||||
vdup.u8 q0, r0
|
||||
mov r0, #4
|
||||
|
||||
diff_negative_32_32_loop
|
||||
sub r0, #1
|
||||
LD_16x8 r1, r2
|
||||
SUB_DIFF_16x8 q0
|
||||
ST_16x8 r12, r2
|
||||
|
||||
LD_16x8 r1, r2
|
||||
SUB_DIFF_16x8 q0
|
||||
ST_16x8 r12, r2
|
||||
cmp r0, #2
|
||||
moveq r1, r3
|
||||
moveq r12, r3
|
||||
cmp r0, #0
|
||||
bne diff_negative_32_32_loop
|
||||
pop {pc}
|
||||
|
||||
diff_positive_32_32
|
||||
usat r0, #8, r0
|
||||
vdup.u8 q0, r0
|
||||
mov r0, #4
|
||||
|
||||
diff_positive_32_32_loop
|
||||
sub r0, #1
|
||||
LD_16x8 r1, r2
|
||||
ADD_DIFF_16x8 q0
|
||||
ST_16x8 r12, r2
|
||||
|
||||
LD_16x8 r1, r2
|
||||
ADD_DIFF_16x8 q0
|
||||
ST_16x8 r12, r2
|
||||
cmp r0, #2
|
||||
moveq r1, r3
|
||||
moveq r12, r3
|
||||
cmp r0, #0
|
||||
bne diff_positive_32_32_loop
|
||||
pop {pc}
|
||||
|
||||
ENDP ; |aom_idct32x32_1_add_neon|
|
||||
END
|
||||
141
third_party/aom/aom_dsp/arm/idct32x32_1_add_neon.c
vendored
Normal file
141
third_party/aom/aom_dsp/arm/idct32x32_1_add_neon.c
vendored
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <arm_neon.h>
|
||||
|
||||
#include "./aom_config.h"
|
||||
|
||||
#include "aom_dsp/inv_txfm.h"
|
||||
#include "aom_ports/mem.h"
|
||||
|
||||
static INLINE void LD_16x8(uint8_t *d, int d_stride, uint8x16_t *q8u8,
|
||||
uint8x16_t *q9u8, uint8x16_t *q10u8,
|
||||
uint8x16_t *q11u8, uint8x16_t *q12u8,
|
||||
uint8x16_t *q13u8, uint8x16_t *q14u8,
|
||||
uint8x16_t *q15u8) {
|
||||
*q8u8 = vld1q_u8(d);
|
||||
d += d_stride;
|
||||
*q9u8 = vld1q_u8(d);
|
||||
d += d_stride;
|
||||
*q10u8 = vld1q_u8(d);
|
||||
d += d_stride;
|
||||
*q11u8 = vld1q_u8(d);
|
||||
d += d_stride;
|
||||
*q12u8 = vld1q_u8(d);
|
||||
d += d_stride;
|
||||
*q13u8 = vld1q_u8(d);
|
||||
d += d_stride;
|
||||
*q14u8 = vld1q_u8(d);
|
||||
d += d_stride;
|
||||
*q15u8 = vld1q_u8(d);
|
||||
return;
|
||||
}
|
||||
|
||||
static INLINE void ADD_DIFF_16x8(uint8x16_t qdiffu8, uint8x16_t *q8u8,
|
||||
uint8x16_t *q9u8, uint8x16_t *q10u8,
|
||||
uint8x16_t *q11u8, uint8x16_t *q12u8,
|
||||
uint8x16_t *q13u8, uint8x16_t *q14u8,
|
||||
uint8x16_t *q15u8) {
|
||||
*q8u8 = vqaddq_u8(*q8u8, qdiffu8);
|
||||
*q9u8 = vqaddq_u8(*q9u8, qdiffu8);
|
||||
*q10u8 = vqaddq_u8(*q10u8, qdiffu8);
|
||||
*q11u8 = vqaddq_u8(*q11u8, qdiffu8);
|
||||
*q12u8 = vqaddq_u8(*q12u8, qdiffu8);
|
||||
*q13u8 = vqaddq_u8(*q13u8, qdiffu8);
|
||||
*q14u8 = vqaddq_u8(*q14u8, qdiffu8);
|
||||
*q15u8 = vqaddq_u8(*q15u8, qdiffu8);
|
||||
return;
|
||||
}
|
||||
|
||||
static INLINE void SUB_DIFF_16x8(uint8x16_t qdiffu8, uint8x16_t *q8u8,
|
||||
uint8x16_t *q9u8, uint8x16_t *q10u8,
|
||||
uint8x16_t *q11u8, uint8x16_t *q12u8,
|
||||
uint8x16_t *q13u8, uint8x16_t *q14u8,
|
||||
uint8x16_t *q15u8) {
|
||||
*q8u8 = vqsubq_u8(*q8u8, qdiffu8);
|
||||
*q9u8 = vqsubq_u8(*q9u8, qdiffu8);
|
||||
*q10u8 = vqsubq_u8(*q10u8, qdiffu8);
|
||||
*q11u8 = vqsubq_u8(*q11u8, qdiffu8);
|
||||
*q12u8 = vqsubq_u8(*q12u8, qdiffu8);
|
||||
*q13u8 = vqsubq_u8(*q13u8, qdiffu8);
|
||||
*q14u8 = vqsubq_u8(*q14u8, qdiffu8);
|
||||
*q15u8 = vqsubq_u8(*q15u8, qdiffu8);
|
||||
return;
|
||||
}
|
||||
|
||||
static INLINE void ST_16x8(uint8_t *d, int d_stride, uint8x16_t *q8u8,
|
||||
uint8x16_t *q9u8, uint8x16_t *q10u8,
|
||||
uint8x16_t *q11u8, uint8x16_t *q12u8,
|
||||
uint8x16_t *q13u8, uint8x16_t *q14u8,
|
||||
uint8x16_t *q15u8) {
|
||||
vst1q_u8(d, *q8u8);
|
||||
d += d_stride;
|
||||
vst1q_u8(d, *q9u8);
|
||||
d += d_stride;
|
||||
vst1q_u8(d, *q10u8);
|
||||
d += d_stride;
|
||||
vst1q_u8(d, *q11u8);
|
||||
d += d_stride;
|
||||
vst1q_u8(d, *q12u8);
|
||||
d += d_stride;
|
||||
vst1q_u8(d, *q13u8);
|
||||
d += d_stride;
|
||||
vst1q_u8(d, *q14u8);
|
||||
d += d_stride;
|
||||
vst1q_u8(d, *q15u8);
|
||||
return;
|
||||
}
|
||||
|
||||
void aom_idct32x32_1_add_neon(int16_t *input, uint8_t *dest, int dest_stride) {
|
||||
uint8x16_t q0u8, q8u8, q9u8, q10u8, q11u8, q12u8, q13u8, q14u8, q15u8;
|
||||
int i, j, dest_stride8;
|
||||
uint8_t *d;
|
||||
int16_t a1;
|
||||
int16_t out = dct_const_round_shift(input[0] * cospi_16_64);
|
||||
|
||||
out = dct_const_round_shift(out * cospi_16_64);
|
||||
a1 = ROUND_POWER_OF_TWO(out, 6);
|
||||
|
||||
dest_stride8 = dest_stride * 8;
|
||||
if (a1 >= 0) { // diff_positive_32_32
|
||||
a1 = a1 < 0 ? 0 : a1 > 255 ? 255 : a1;
|
||||
q0u8 = vdupq_n_u8(a1);
|
||||
for (i = 0; i < 2; i++, dest += 16) { // diff_positive_32_32_loop
|
||||
d = dest;
|
||||
for (j = 0; j < 4; j++) {
|
||||
LD_16x8(d, dest_stride, &q8u8, &q9u8, &q10u8, &q11u8, &q12u8, &q13u8,
|
||||
&q14u8, &q15u8);
|
||||
ADD_DIFF_16x8(q0u8, &q8u8, &q9u8, &q10u8, &q11u8, &q12u8, &q13u8,
|
||||
&q14u8, &q15u8);
|
||||
ST_16x8(d, dest_stride, &q8u8, &q9u8, &q10u8, &q11u8, &q12u8, &q13u8,
|
||||
&q14u8, &q15u8);
|
||||
d += dest_stride8;
|
||||
}
|
||||
}
|
||||
} else { // diff_negative_32_32
|
||||
a1 = -a1;
|
||||
a1 = a1 < 0 ? 0 : a1 > 255 ? 255 : a1;
|
||||
q0u8 = vdupq_n_u8(a1);
|
||||
for (i = 0; i < 2; i++, dest += 16) { // diff_negative_32_32_loop
|
||||
d = dest;
|
||||
for (j = 0; j < 4; j++) {
|
||||
LD_16x8(d, dest_stride, &q8u8, &q9u8, &q10u8, &q11u8, &q12u8, &q13u8,
|
||||
&q14u8, &q15u8);
|
||||
SUB_DIFF_16x8(q0u8, &q8u8, &q9u8, &q10u8, &q11u8, &q12u8, &q13u8,
|
||||
&q14u8, &q15u8);
|
||||
ST_16x8(d, dest_stride, &q8u8, &q9u8, &q10u8, &q11u8, &q12u8, &q13u8,
|
||||
&q14u8, &q15u8);
|
||||
d += dest_stride8;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
1302
third_party/aom/aom_dsp/arm/idct32x32_add_neon.asm
vendored
Normal file
1302
third_party/aom/aom_dsp/arm/idct32x32_add_neon.asm
vendored
Normal file
File diff suppressed because it is too large
Load diff
686
third_party/aom/aom_dsp/arm/idct32x32_add_neon.c
vendored
Normal file
686
third_party/aom/aom_dsp/arm/idct32x32_add_neon.c
vendored
Normal file
|
|
@ -0,0 +1,686 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <arm_neon.h>
|
||||
|
||||
#include "./aom_config.h"
|
||||
#include "aom_dsp/txfm_common.h"
|
||||
|
||||
#define LOAD_FROM_TRANSPOSED(prev, first, second) \
|
||||
q14s16 = vld1q_s16(trans_buf + first * 8); \
|
||||
q13s16 = vld1q_s16(trans_buf + second * 8);
|
||||
|
||||
#define LOAD_FROM_OUTPUT(prev, first, second, qA, qB) \
|
||||
qA = vld1q_s16(out + first * 32); \
|
||||
qB = vld1q_s16(out + second * 32);
|
||||
|
||||
#define STORE_IN_OUTPUT(prev, first, second, qA, qB) \
|
||||
vst1q_s16(out + first * 32, qA); \
|
||||
vst1q_s16(out + second * 32, qB);
|
||||
|
||||
#define STORE_COMBINE_CENTER_RESULTS(r10, r9) \
|
||||
__STORE_COMBINE_CENTER_RESULTS(r10, r9, stride, q6s16, q7s16, q8s16, q9s16);
|
||||
static INLINE void __STORE_COMBINE_CENTER_RESULTS(uint8_t *p1, uint8_t *p2,
|
||||
int stride, int16x8_t q6s16,
|
||||
int16x8_t q7s16,
|
||||
int16x8_t q8s16,
|
||||
int16x8_t q9s16) {
|
||||
int16x4_t d8s16, d9s16, d10s16, d11s16;
|
||||
|
||||
d8s16 = vld1_s16((int16_t *)p1);
|
||||
p1 += stride;
|
||||
d11s16 = vld1_s16((int16_t *)p2);
|
||||
p2 -= stride;
|
||||
d9s16 = vld1_s16((int16_t *)p1);
|
||||
d10s16 = vld1_s16((int16_t *)p2);
|
||||
|
||||
q7s16 = vrshrq_n_s16(q7s16, 6);
|
||||
q8s16 = vrshrq_n_s16(q8s16, 6);
|
||||
q9s16 = vrshrq_n_s16(q9s16, 6);
|
||||
q6s16 = vrshrq_n_s16(q6s16, 6);
|
||||
|
||||
q7s16 = vreinterpretq_s16_u16(
|
||||
vaddw_u8(vreinterpretq_u16_s16(q7s16), vreinterpret_u8_s16(d9s16)));
|
||||
q8s16 = vreinterpretq_s16_u16(
|
||||
vaddw_u8(vreinterpretq_u16_s16(q8s16), vreinterpret_u8_s16(d10s16)));
|
||||
q9s16 = vreinterpretq_s16_u16(
|
||||
vaddw_u8(vreinterpretq_u16_s16(q9s16), vreinterpret_u8_s16(d11s16)));
|
||||
q6s16 = vreinterpretq_s16_u16(
|
||||
vaddw_u8(vreinterpretq_u16_s16(q6s16), vreinterpret_u8_s16(d8s16)));
|
||||
|
||||
d9s16 = vreinterpret_s16_u8(vqmovun_s16(q7s16));
|
||||
d10s16 = vreinterpret_s16_u8(vqmovun_s16(q8s16));
|
||||
d11s16 = vreinterpret_s16_u8(vqmovun_s16(q9s16));
|
||||
d8s16 = vreinterpret_s16_u8(vqmovun_s16(q6s16));
|
||||
|
||||
vst1_s16((int16_t *)p1, d9s16);
|
||||
p1 -= stride;
|
||||
vst1_s16((int16_t *)p2, d10s16);
|
||||
p2 += stride;
|
||||
vst1_s16((int16_t *)p1, d8s16);
|
||||
vst1_s16((int16_t *)p2, d11s16);
|
||||
return;
|
||||
}
|
||||
|
||||
#define STORE_COMBINE_EXTREME_RESULTS(r7, r6) \
|
||||
; \
|
||||
__STORE_COMBINE_EXTREME_RESULTS(r7, r6, stride, q4s16, q5s16, q6s16, q7s16);
|
||||
static INLINE void __STORE_COMBINE_EXTREME_RESULTS(uint8_t *p1, uint8_t *p2,
|
||||
int stride, int16x8_t q4s16,
|
||||
int16x8_t q5s16,
|
||||
int16x8_t q6s16,
|
||||
int16x8_t q7s16) {
|
||||
int16x4_t d4s16, d5s16, d6s16, d7s16;
|
||||
|
||||
d4s16 = vld1_s16((int16_t *)p1);
|
||||
p1 += stride;
|
||||
d7s16 = vld1_s16((int16_t *)p2);
|
||||
p2 -= stride;
|
||||
d5s16 = vld1_s16((int16_t *)p1);
|
||||
d6s16 = vld1_s16((int16_t *)p2);
|
||||
|
||||
q5s16 = vrshrq_n_s16(q5s16, 6);
|
||||
q6s16 = vrshrq_n_s16(q6s16, 6);
|
||||
q7s16 = vrshrq_n_s16(q7s16, 6);
|
||||
q4s16 = vrshrq_n_s16(q4s16, 6);
|
||||
|
||||
q5s16 = vreinterpretq_s16_u16(
|
||||
vaddw_u8(vreinterpretq_u16_s16(q5s16), vreinterpret_u8_s16(d5s16)));
|
||||
q6s16 = vreinterpretq_s16_u16(
|
||||
vaddw_u8(vreinterpretq_u16_s16(q6s16), vreinterpret_u8_s16(d6s16)));
|
||||
q7s16 = vreinterpretq_s16_u16(
|
||||
vaddw_u8(vreinterpretq_u16_s16(q7s16), vreinterpret_u8_s16(d7s16)));
|
||||
q4s16 = vreinterpretq_s16_u16(
|
||||
vaddw_u8(vreinterpretq_u16_s16(q4s16), vreinterpret_u8_s16(d4s16)));
|
||||
|
||||
d5s16 = vreinterpret_s16_u8(vqmovun_s16(q5s16));
|
||||
d6s16 = vreinterpret_s16_u8(vqmovun_s16(q6s16));
|
||||
d7s16 = vreinterpret_s16_u8(vqmovun_s16(q7s16));
|
||||
d4s16 = vreinterpret_s16_u8(vqmovun_s16(q4s16));
|
||||
|
||||
vst1_s16((int16_t *)p1, d5s16);
|
||||
p1 -= stride;
|
||||
vst1_s16((int16_t *)p2, d6s16);
|
||||
p2 += stride;
|
||||
vst1_s16((int16_t *)p2, d7s16);
|
||||
vst1_s16((int16_t *)p1, d4s16);
|
||||
return;
|
||||
}
|
||||
|
||||
#define DO_BUTTERFLY_STD(const_1, const_2, qA, qB) \
|
||||
DO_BUTTERFLY(q14s16, q13s16, const_1, const_2, qA, qB);
|
||||
static INLINE void DO_BUTTERFLY(int16x8_t q14s16, int16x8_t q13s16,
|
||||
int16_t first_const, int16_t second_const,
|
||||
int16x8_t *qAs16, int16x8_t *qBs16) {
|
||||
int16x4_t d30s16, d31s16;
|
||||
int32x4_t q8s32, q9s32, q10s32, q11s32, q12s32, q15s32;
|
||||
int16x4_t dCs16, dDs16, dAs16, dBs16;
|
||||
|
||||
dCs16 = vget_low_s16(q14s16);
|
||||
dDs16 = vget_high_s16(q14s16);
|
||||
dAs16 = vget_low_s16(q13s16);
|
||||
dBs16 = vget_high_s16(q13s16);
|
||||
|
||||
d30s16 = vdup_n_s16(first_const);
|
||||
d31s16 = vdup_n_s16(second_const);
|
||||
|
||||
q8s32 = vmull_s16(dCs16, d30s16);
|
||||
q10s32 = vmull_s16(dAs16, d31s16);
|
||||
q9s32 = vmull_s16(dDs16, d30s16);
|
||||
q11s32 = vmull_s16(dBs16, d31s16);
|
||||
q12s32 = vmull_s16(dCs16, d31s16);
|
||||
|
||||
q8s32 = vsubq_s32(q8s32, q10s32);
|
||||
q9s32 = vsubq_s32(q9s32, q11s32);
|
||||
|
||||
q10s32 = vmull_s16(dDs16, d31s16);
|
||||
q11s32 = vmull_s16(dAs16, d30s16);
|
||||
q15s32 = vmull_s16(dBs16, d30s16);
|
||||
|
||||
q11s32 = vaddq_s32(q12s32, q11s32);
|
||||
q10s32 = vaddq_s32(q10s32, q15s32);
|
||||
|
||||
*qAs16 = vcombine_s16(vqrshrn_n_s32(q8s32, 14), vqrshrn_n_s32(q9s32, 14));
|
||||
*qBs16 = vcombine_s16(vqrshrn_n_s32(q11s32, 14), vqrshrn_n_s32(q10s32, 14));
|
||||
return;
|
||||
}
|
||||
|
||||
static INLINE void idct32_transpose_pair(int16_t *input, int16_t *t_buf) {
|
||||
int16_t *in;
|
||||
int i;
|
||||
const int stride = 32;
|
||||
int16x4_t d16s16, d17s16, d18s16, d19s16, d20s16, d21s16, d22s16, d23s16;
|
||||
int16x4_t d24s16, d25s16, d26s16, d27s16, d28s16, d29s16, d30s16, d31s16;
|
||||
int16x8_t q8s16, q9s16, q10s16, q11s16, q12s16, q13s16, q14s16, q15s16;
|
||||
int32x4x2_t q0x2s32, q1x2s32, q2x2s32, q3x2s32;
|
||||
int16x8x2_t q0x2s16, q1x2s16, q2x2s16, q3x2s16;
|
||||
|
||||
for (i = 0; i < 4; i++, input += 8) {
|
||||
in = input;
|
||||
q8s16 = vld1q_s16(in);
|
||||
in += stride;
|
||||
q9s16 = vld1q_s16(in);
|
||||
in += stride;
|
||||
q10s16 = vld1q_s16(in);
|
||||
in += stride;
|
||||
q11s16 = vld1q_s16(in);
|
||||
in += stride;
|
||||
q12s16 = vld1q_s16(in);
|
||||
in += stride;
|
||||
q13s16 = vld1q_s16(in);
|
||||
in += stride;
|
||||
q14s16 = vld1q_s16(in);
|
||||
in += stride;
|
||||
q15s16 = vld1q_s16(in);
|
||||
|
||||
d16s16 = vget_low_s16(q8s16);
|
||||
d17s16 = vget_high_s16(q8s16);
|
||||
d18s16 = vget_low_s16(q9s16);
|
||||
d19s16 = vget_high_s16(q9s16);
|
||||
d20s16 = vget_low_s16(q10s16);
|
||||
d21s16 = vget_high_s16(q10s16);
|
||||
d22s16 = vget_low_s16(q11s16);
|
||||
d23s16 = vget_high_s16(q11s16);
|
||||
d24s16 = vget_low_s16(q12s16);
|
||||
d25s16 = vget_high_s16(q12s16);
|
||||
d26s16 = vget_low_s16(q13s16);
|
||||
d27s16 = vget_high_s16(q13s16);
|
||||
d28s16 = vget_low_s16(q14s16);
|
||||
d29s16 = vget_high_s16(q14s16);
|
||||
d30s16 = vget_low_s16(q15s16);
|
||||
d31s16 = vget_high_s16(q15s16);
|
||||
|
||||
q8s16 = vcombine_s16(d16s16, d24s16); // vswp d17, d24
|
||||
q9s16 = vcombine_s16(d18s16, d26s16); // vswp d19, d26
|
||||
q10s16 = vcombine_s16(d20s16, d28s16); // vswp d21, d28
|
||||
q11s16 = vcombine_s16(d22s16, d30s16); // vswp d23, d30
|
||||
q12s16 = vcombine_s16(d17s16, d25s16);
|
||||
q13s16 = vcombine_s16(d19s16, d27s16);
|
||||
q14s16 = vcombine_s16(d21s16, d29s16);
|
||||
q15s16 = vcombine_s16(d23s16, d31s16);
|
||||
|
||||
q0x2s32 =
|
||||
vtrnq_s32(vreinterpretq_s32_s16(q8s16), vreinterpretq_s32_s16(q10s16));
|
||||
q1x2s32 =
|
||||
vtrnq_s32(vreinterpretq_s32_s16(q9s16), vreinterpretq_s32_s16(q11s16));
|
||||
q2x2s32 =
|
||||
vtrnq_s32(vreinterpretq_s32_s16(q12s16), vreinterpretq_s32_s16(q14s16));
|
||||
q3x2s32 =
|
||||
vtrnq_s32(vreinterpretq_s32_s16(q13s16), vreinterpretq_s32_s16(q15s16));
|
||||
|
||||
q0x2s16 = vtrnq_s16(vreinterpretq_s16_s32(q0x2s32.val[0]), // q8
|
||||
vreinterpretq_s16_s32(q1x2s32.val[0])); // q9
|
||||
q1x2s16 = vtrnq_s16(vreinterpretq_s16_s32(q0x2s32.val[1]), // q10
|
||||
vreinterpretq_s16_s32(q1x2s32.val[1])); // q11
|
||||
q2x2s16 = vtrnq_s16(vreinterpretq_s16_s32(q2x2s32.val[0]), // q12
|
||||
vreinterpretq_s16_s32(q3x2s32.val[0])); // q13
|
||||
q3x2s16 = vtrnq_s16(vreinterpretq_s16_s32(q2x2s32.val[1]), // q14
|
||||
vreinterpretq_s16_s32(q3x2s32.val[1])); // q15
|
||||
|
||||
vst1q_s16(t_buf, q0x2s16.val[0]);
|
||||
t_buf += 8;
|
||||
vst1q_s16(t_buf, q0x2s16.val[1]);
|
||||
t_buf += 8;
|
||||
vst1q_s16(t_buf, q1x2s16.val[0]);
|
||||
t_buf += 8;
|
||||
vst1q_s16(t_buf, q1x2s16.val[1]);
|
||||
t_buf += 8;
|
||||
vst1q_s16(t_buf, q2x2s16.val[0]);
|
||||
t_buf += 8;
|
||||
vst1q_s16(t_buf, q2x2s16.val[1]);
|
||||
t_buf += 8;
|
||||
vst1q_s16(t_buf, q3x2s16.val[0]);
|
||||
t_buf += 8;
|
||||
vst1q_s16(t_buf, q3x2s16.val[1]);
|
||||
t_buf += 8;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static INLINE void idct32_bands_end_1st_pass(int16_t *out, int16x8_t q2s16,
|
||||
int16x8_t q3s16, int16x8_t q6s16,
|
||||
int16x8_t q7s16, int16x8_t q8s16,
|
||||
int16x8_t q9s16, int16x8_t q10s16,
|
||||
int16x8_t q11s16, int16x8_t q12s16,
|
||||
int16x8_t q13s16, int16x8_t q14s16,
|
||||
int16x8_t q15s16) {
|
||||
int16x8_t q0s16, q1s16, q4s16, q5s16;
|
||||
|
||||
STORE_IN_OUTPUT(17, 16, 17, q6s16, q7s16);
|
||||
STORE_IN_OUTPUT(17, 14, 15, q8s16, q9s16);
|
||||
|
||||
LOAD_FROM_OUTPUT(15, 30, 31, q0s16, q1s16);
|
||||
q4s16 = vaddq_s16(q2s16, q1s16);
|
||||
q5s16 = vaddq_s16(q3s16, q0s16);
|
||||
q6s16 = vsubq_s16(q3s16, q0s16);
|
||||
q7s16 = vsubq_s16(q2s16, q1s16);
|
||||
STORE_IN_OUTPUT(31, 30, 31, q6s16, q7s16);
|
||||
STORE_IN_OUTPUT(31, 0, 1, q4s16, q5s16);
|
||||
|
||||
LOAD_FROM_OUTPUT(1, 12, 13, q0s16, q1s16);
|
||||
q2s16 = vaddq_s16(q10s16, q1s16);
|
||||
q3s16 = vaddq_s16(q11s16, q0s16);
|
||||
q4s16 = vsubq_s16(q11s16, q0s16);
|
||||
q5s16 = vsubq_s16(q10s16, q1s16);
|
||||
|
||||
LOAD_FROM_OUTPUT(13, 18, 19, q0s16, q1s16);
|
||||
q8s16 = vaddq_s16(q4s16, q1s16);
|
||||
q9s16 = vaddq_s16(q5s16, q0s16);
|
||||
q6s16 = vsubq_s16(q5s16, q0s16);
|
||||
q7s16 = vsubq_s16(q4s16, q1s16);
|
||||
STORE_IN_OUTPUT(19, 18, 19, q6s16, q7s16);
|
||||
STORE_IN_OUTPUT(19, 12, 13, q8s16, q9s16);
|
||||
|
||||
LOAD_FROM_OUTPUT(13, 28, 29, q0s16, q1s16);
|
||||
q4s16 = vaddq_s16(q2s16, q1s16);
|
||||
q5s16 = vaddq_s16(q3s16, q0s16);
|
||||
q6s16 = vsubq_s16(q3s16, q0s16);
|
||||
q7s16 = vsubq_s16(q2s16, q1s16);
|
||||
STORE_IN_OUTPUT(29, 28, 29, q6s16, q7s16);
|
||||
STORE_IN_OUTPUT(29, 2, 3, q4s16, q5s16);
|
||||
|
||||
LOAD_FROM_OUTPUT(3, 10, 11, q0s16, q1s16);
|
||||
q2s16 = vaddq_s16(q12s16, q1s16);
|
||||
q3s16 = vaddq_s16(q13s16, q0s16);
|
||||
q4s16 = vsubq_s16(q13s16, q0s16);
|
||||
q5s16 = vsubq_s16(q12s16, q1s16);
|
||||
|
||||
LOAD_FROM_OUTPUT(11, 20, 21, q0s16, q1s16);
|
||||
q8s16 = vaddq_s16(q4s16, q1s16);
|
||||
q9s16 = vaddq_s16(q5s16, q0s16);
|
||||
q6s16 = vsubq_s16(q5s16, q0s16);
|
||||
q7s16 = vsubq_s16(q4s16, q1s16);
|
||||
STORE_IN_OUTPUT(21, 20, 21, q6s16, q7s16);
|
||||
STORE_IN_OUTPUT(21, 10, 11, q8s16, q9s16);
|
||||
|
||||
LOAD_FROM_OUTPUT(11, 26, 27, q0s16, q1s16);
|
||||
q4s16 = vaddq_s16(q2s16, q1s16);
|
||||
q5s16 = vaddq_s16(q3s16, q0s16);
|
||||
q6s16 = vsubq_s16(q3s16, q0s16);
|
||||
q7s16 = vsubq_s16(q2s16, q1s16);
|
||||
STORE_IN_OUTPUT(27, 26, 27, q6s16, q7s16);
|
||||
STORE_IN_OUTPUT(27, 4, 5, q4s16, q5s16);
|
||||
|
||||
LOAD_FROM_OUTPUT(5, 8, 9, q0s16, q1s16);
|
||||
q2s16 = vaddq_s16(q14s16, q1s16);
|
||||
q3s16 = vaddq_s16(q15s16, q0s16);
|
||||
q4s16 = vsubq_s16(q15s16, q0s16);
|
||||
q5s16 = vsubq_s16(q14s16, q1s16);
|
||||
|
||||
LOAD_FROM_OUTPUT(9, 22, 23, q0s16, q1s16);
|
||||
q8s16 = vaddq_s16(q4s16, q1s16);
|
||||
q9s16 = vaddq_s16(q5s16, q0s16);
|
||||
q6s16 = vsubq_s16(q5s16, q0s16);
|
||||
q7s16 = vsubq_s16(q4s16, q1s16);
|
||||
STORE_IN_OUTPUT(23, 22, 23, q6s16, q7s16);
|
||||
STORE_IN_OUTPUT(23, 8, 9, q8s16, q9s16);
|
||||
|
||||
LOAD_FROM_OUTPUT(9, 24, 25, q0s16, q1s16);
|
||||
q4s16 = vaddq_s16(q2s16, q1s16);
|
||||
q5s16 = vaddq_s16(q3s16, q0s16);
|
||||
q6s16 = vsubq_s16(q3s16, q0s16);
|
||||
q7s16 = vsubq_s16(q2s16, q1s16);
|
||||
STORE_IN_OUTPUT(25, 24, 25, q6s16, q7s16);
|
||||
STORE_IN_OUTPUT(25, 6, 7, q4s16, q5s16);
|
||||
return;
|
||||
}
|
||||
|
||||
static INLINE void idct32_bands_end_2nd_pass(
|
||||
int16_t *out, uint8_t *dest, int stride, int16x8_t q2s16, int16x8_t q3s16,
|
||||
int16x8_t q6s16, int16x8_t q7s16, int16x8_t q8s16, int16x8_t q9s16,
|
||||
int16x8_t q10s16, int16x8_t q11s16, int16x8_t q12s16, int16x8_t q13s16,
|
||||
int16x8_t q14s16, int16x8_t q15s16) {
|
||||
uint8_t *r6 = dest + 31 * stride;
|
||||
uint8_t *r7 = dest /* + 0 * stride*/;
|
||||
uint8_t *r9 = dest + 15 * stride;
|
||||
uint8_t *r10 = dest + 16 * stride;
|
||||
int str2 = stride << 1;
|
||||
int16x8_t q0s16, q1s16, q4s16, q5s16;
|
||||
|
||||
STORE_COMBINE_CENTER_RESULTS(r10, r9);
|
||||
r10 += str2;
|
||||
r9 -= str2;
|
||||
|
||||
LOAD_FROM_OUTPUT(17, 30, 31, q0s16, q1s16)
|
||||
q4s16 = vaddq_s16(q2s16, q1s16);
|
||||
q5s16 = vaddq_s16(q3s16, q0s16);
|
||||
q6s16 = vsubq_s16(q3s16, q0s16);
|
||||
q7s16 = vsubq_s16(q2s16, q1s16);
|
||||
STORE_COMBINE_EXTREME_RESULTS(r7, r6);
|
||||
r7 += str2;
|
||||
r6 -= str2;
|
||||
|
||||
LOAD_FROM_OUTPUT(31, 12, 13, q0s16, q1s16)
|
||||
q2s16 = vaddq_s16(q10s16, q1s16);
|
||||
q3s16 = vaddq_s16(q11s16, q0s16);
|
||||
q4s16 = vsubq_s16(q11s16, q0s16);
|
||||
q5s16 = vsubq_s16(q10s16, q1s16);
|
||||
|
||||
LOAD_FROM_OUTPUT(13, 18, 19, q0s16, q1s16)
|
||||
q8s16 = vaddq_s16(q4s16, q1s16);
|
||||
q9s16 = vaddq_s16(q5s16, q0s16);
|
||||
q6s16 = vsubq_s16(q5s16, q0s16);
|
||||
q7s16 = vsubq_s16(q4s16, q1s16);
|
||||
STORE_COMBINE_CENTER_RESULTS(r10, r9);
|
||||
r10 += str2;
|
||||
r9 -= str2;
|
||||
|
||||
LOAD_FROM_OUTPUT(19, 28, 29, q0s16, q1s16)
|
||||
q4s16 = vaddq_s16(q2s16, q1s16);
|
||||
q5s16 = vaddq_s16(q3s16, q0s16);
|
||||
q6s16 = vsubq_s16(q3s16, q0s16);
|
||||
q7s16 = vsubq_s16(q2s16, q1s16);
|
||||
STORE_COMBINE_EXTREME_RESULTS(r7, r6);
|
||||
r7 += str2;
|
||||
r6 -= str2;
|
||||
|
||||
LOAD_FROM_OUTPUT(29, 10, 11, q0s16, q1s16)
|
||||
q2s16 = vaddq_s16(q12s16, q1s16);
|
||||
q3s16 = vaddq_s16(q13s16, q0s16);
|
||||
q4s16 = vsubq_s16(q13s16, q0s16);
|
||||
q5s16 = vsubq_s16(q12s16, q1s16);
|
||||
|
||||
LOAD_FROM_OUTPUT(11, 20, 21, q0s16, q1s16)
|
||||
q8s16 = vaddq_s16(q4s16, q1s16);
|
||||
q9s16 = vaddq_s16(q5s16, q0s16);
|
||||
q6s16 = vsubq_s16(q5s16, q0s16);
|
||||
q7s16 = vsubq_s16(q4s16, q1s16);
|
||||
STORE_COMBINE_CENTER_RESULTS(r10, r9);
|
||||
r10 += str2;
|
||||
r9 -= str2;
|
||||
|
||||
LOAD_FROM_OUTPUT(21, 26, 27, q0s16, q1s16)
|
||||
q4s16 = vaddq_s16(q2s16, q1s16);
|
||||
q5s16 = vaddq_s16(q3s16, q0s16);
|
||||
q6s16 = vsubq_s16(q3s16, q0s16);
|
||||
q7s16 = vsubq_s16(q2s16, q1s16);
|
||||
STORE_COMBINE_EXTREME_RESULTS(r7, r6);
|
||||
r7 += str2;
|
||||
r6 -= str2;
|
||||
|
||||
LOAD_FROM_OUTPUT(27, 8, 9, q0s16, q1s16)
|
||||
q2s16 = vaddq_s16(q14s16, q1s16);
|
||||
q3s16 = vaddq_s16(q15s16, q0s16);
|
||||
q4s16 = vsubq_s16(q15s16, q0s16);
|
||||
q5s16 = vsubq_s16(q14s16, q1s16);
|
||||
|
||||
LOAD_FROM_OUTPUT(9, 22, 23, q0s16, q1s16)
|
||||
q8s16 = vaddq_s16(q4s16, q1s16);
|
||||
q9s16 = vaddq_s16(q5s16, q0s16);
|
||||
q6s16 = vsubq_s16(q5s16, q0s16);
|
||||
q7s16 = vsubq_s16(q4s16, q1s16);
|
||||
STORE_COMBINE_CENTER_RESULTS(r10, r9);
|
||||
|
||||
LOAD_FROM_OUTPUT(23, 24, 25, q0s16, q1s16)
|
||||
q4s16 = vaddq_s16(q2s16, q1s16);
|
||||
q5s16 = vaddq_s16(q3s16, q0s16);
|
||||
q6s16 = vsubq_s16(q3s16, q0s16);
|
||||
q7s16 = vsubq_s16(q2s16, q1s16);
|
||||
STORE_COMBINE_EXTREME_RESULTS(r7, r6);
|
||||
return;
|
||||
}
|
||||
|
||||
void aom_idct32x32_1024_add_neon(int16_t *input, uint8_t *dest, int stride) {
|
||||
int i, idct32_pass_loop;
|
||||
int16_t trans_buf[32 * 8];
|
||||
int16_t pass1[32 * 32];
|
||||
int16_t pass2[32 * 32];
|
||||
int16_t *out;
|
||||
int16x8_t q0s16, q1s16, q2s16, q3s16, q4s16, q5s16, q6s16, q7s16;
|
||||
int16x8_t q8s16, q9s16, q10s16, q11s16, q12s16, q13s16, q14s16, q15s16;
|
||||
|
||||
for (idct32_pass_loop = 0, out = pass1; idct32_pass_loop < 2;
|
||||
idct32_pass_loop++,
|
||||
input = pass1, // the input of pass2 is the result of pass1
|
||||
out = pass2) {
|
||||
for (i = 0; i < 4; i++, input += 32 * 8, out += 8) { // idct32_bands_loop
|
||||
idct32_transpose_pair(input, trans_buf);
|
||||
|
||||
// -----------------------------------------
|
||||
// BLOCK A: 16-19,28-31
|
||||
// -----------------------------------------
|
||||
// generate 16,17,30,31
|
||||
// part of stage 1
|
||||
LOAD_FROM_TRANSPOSED(0, 1, 31)
|
||||
DO_BUTTERFLY_STD(cospi_31_64, cospi_1_64, &q0s16, &q2s16)
|
||||
LOAD_FROM_TRANSPOSED(31, 17, 15)
|
||||
DO_BUTTERFLY_STD(cospi_15_64, cospi_17_64, &q1s16, &q3s16)
|
||||
// part of stage 2
|
||||
q4s16 = vaddq_s16(q0s16, q1s16);
|
||||
q13s16 = vsubq_s16(q0s16, q1s16);
|
||||
q6s16 = vaddq_s16(q2s16, q3s16);
|
||||
q14s16 = vsubq_s16(q2s16, q3s16);
|
||||
// part of stage 3
|
||||
DO_BUTTERFLY_STD(cospi_28_64, cospi_4_64, &q5s16, &q7s16)
|
||||
|
||||
// generate 18,19,28,29
|
||||
// part of stage 1
|
||||
LOAD_FROM_TRANSPOSED(15, 9, 23)
|
||||
DO_BUTTERFLY_STD(cospi_23_64, cospi_9_64, &q0s16, &q2s16)
|
||||
LOAD_FROM_TRANSPOSED(23, 25, 7)
|
||||
DO_BUTTERFLY_STD(cospi_7_64, cospi_25_64, &q1s16, &q3s16)
|
||||
// part of stage 2
|
||||
q13s16 = vsubq_s16(q3s16, q2s16);
|
||||
q3s16 = vaddq_s16(q3s16, q2s16);
|
||||
q14s16 = vsubq_s16(q1s16, q0s16);
|
||||
q2s16 = vaddq_s16(q1s16, q0s16);
|
||||
// part of stage 3
|
||||
DO_BUTTERFLY_STD(-cospi_4_64, -cospi_28_64, &q1s16, &q0s16)
|
||||
// part of stage 4
|
||||
q8s16 = vaddq_s16(q4s16, q2s16);
|
||||
q9s16 = vaddq_s16(q5s16, q0s16);
|
||||
q10s16 = vaddq_s16(q7s16, q1s16);
|
||||
q15s16 = vaddq_s16(q6s16, q3s16);
|
||||
q13s16 = vsubq_s16(q5s16, q0s16);
|
||||
q14s16 = vsubq_s16(q7s16, q1s16);
|
||||
STORE_IN_OUTPUT(0, 16, 31, q8s16, q15s16)
|
||||
STORE_IN_OUTPUT(31, 17, 30, q9s16, q10s16)
|
||||
// part of stage 5
|
||||
DO_BUTTERFLY_STD(cospi_24_64, cospi_8_64, &q0s16, &q1s16)
|
||||
STORE_IN_OUTPUT(30, 29, 18, q1s16, q0s16)
|
||||
// part of stage 4
|
||||
q13s16 = vsubq_s16(q4s16, q2s16);
|
||||
q14s16 = vsubq_s16(q6s16, q3s16);
|
||||
// part of stage 5
|
||||
DO_BUTTERFLY_STD(cospi_24_64, cospi_8_64, &q4s16, &q6s16)
|
||||
STORE_IN_OUTPUT(18, 19, 28, q4s16, q6s16)
|
||||
|
||||
// -----------------------------------------
|
||||
// BLOCK B: 20-23,24-27
|
||||
// -----------------------------------------
|
||||
// generate 20,21,26,27
|
||||
// part of stage 1
|
||||
LOAD_FROM_TRANSPOSED(7, 5, 27)
|
||||
DO_BUTTERFLY_STD(cospi_27_64, cospi_5_64, &q0s16, &q2s16)
|
||||
LOAD_FROM_TRANSPOSED(27, 21, 11)
|
||||
DO_BUTTERFLY_STD(cospi_11_64, cospi_21_64, &q1s16, &q3s16)
|
||||
// part of stage 2
|
||||
q13s16 = vsubq_s16(q0s16, q1s16);
|
||||
q0s16 = vaddq_s16(q0s16, q1s16);
|
||||
q14s16 = vsubq_s16(q2s16, q3s16);
|
||||
q2s16 = vaddq_s16(q2s16, q3s16);
|
||||
// part of stage 3
|
||||
DO_BUTTERFLY_STD(cospi_12_64, cospi_20_64, &q1s16, &q3s16)
|
||||
|
||||
// generate 22,23,24,25
|
||||
// part of stage 1
|
||||
LOAD_FROM_TRANSPOSED(11, 13, 19)
|
||||
DO_BUTTERFLY_STD(cospi_19_64, cospi_13_64, &q5s16, &q7s16)
|
||||
LOAD_FROM_TRANSPOSED(19, 29, 3)
|
||||
DO_BUTTERFLY_STD(cospi_3_64, cospi_29_64, &q4s16, &q6s16)
|
||||
// part of stage 2
|
||||
q14s16 = vsubq_s16(q4s16, q5s16);
|
||||
q5s16 = vaddq_s16(q4s16, q5s16);
|
||||
q13s16 = vsubq_s16(q6s16, q7s16);
|
||||
q6s16 = vaddq_s16(q6s16, q7s16);
|
||||
// part of stage 3
|
||||
DO_BUTTERFLY_STD(-cospi_20_64, -cospi_12_64, &q4s16, &q7s16)
|
||||
// part of stage 4
|
||||
q10s16 = vaddq_s16(q7s16, q1s16);
|
||||
q11s16 = vaddq_s16(q5s16, q0s16);
|
||||
q12s16 = vaddq_s16(q6s16, q2s16);
|
||||
q15s16 = vaddq_s16(q4s16, q3s16);
|
||||
// part of stage 6
|
||||
LOAD_FROM_OUTPUT(28, 16, 17, q14s16, q13s16)
|
||||
q8s16 = vaddq_s16(q14s16, q11s16);
|
||||
q9s16 = vaddq_s16(q13s16, q10s16);
|
||||
q13s16 = vsubq_s16(q13s16, q10s16);
|
||||
q11s16 = vsubq_s16(q14s16, q11s16);
|
||||
STORE_IN_OUTPUT(17, 17, 16, q9s16, q8s16)
|
||||
LOAD_FROM_OUTPUT(16, 30, 31, q14s16, q9s16)
|
||||
q8s16 = vsubq_s16(q9s16, q12s16);
|
||||
q10s16 = vaddq_s16(q14s16, q15s16);
|
||||
q14s16 = vsubq_s16(q14s16, q15s16);
|
||||
q12s16 = vaddq_s16(q9s16, q12s16);
|
||||
STORE_IN_OUTPUT(31, 30, 31, q10s16, q12s16)
|
||||
// part of stage 7
|
||||
DO_BUTTERFLY_STD(cospi_16_64, cospi_16_64, &q13s16, &q14s16)
|
||||
STORE_IN_OUTPUT(31, 25, 22, q14s16, q13s16)
|
||||
q13s16 = q11s16;
|
||||
q14s16 = q8s16;
|
||||
DO_BUTTERFLY_STD(cospi_16_64, cospi_16_64, &q13s16, &q14s16)
|
||||
STORE_IN_OUTPUT(22, 24, 23, q14s16, q13s16)
|
||||
// part of stage 4
|
||||
q14s16 = vsubq_s16(q5s16, q0s16);
|
||||
q13s16 = vsubq_s16(q6s16, q2s16);
|
||||
DO_BUTTERFLY_STD(-cospi_8_64, -cospi_24_64, &q5s16, &q6s16);
|
||||
q14s16 = vsubq_s16(q7s16, q1s16);
|
||||
q13s16 = vsubq_s16(q4s16, q3s16);
|
||||
DO_BUTTERFLY_STD(-cospi_8_64, -cospi_24_64, &q0s16, &q1s16);
|
||||
// part of stage 6
|
||||
LOAD_FROM_OUTPUT(23, 18, 19, q14s16, q13s16)
|
||||
q8s16 = vaddq_s16(q14s16, q1s16);
|
||||
q9s16 = vaddq_s16(q13s16, q6s16);
|
||||
q13s16 = vsubq_s16(q13s16, q6s16);
|
||||
q1s16 = vsubq_s16(q14s16, q1s16);
|
||||
STORE_IN_OUTPUT(19, 18, 19, q8s16, q9s16)
|
||||
LOAD_FROM_OUTPUT(19, 28, 29, q8s16, q9s16)
|
||||
q14s16 = vsubq_s16(q8s16, q5s16);
|
||||
q10s16 = vaddq_s16(q8s16, q5s16);
|
||||
q11s16 = vaddq_s16(q9s16, q0s16);
|
||||
q0s16 = vsubq_s16(q9s16, q0s16);
|
||||
STORE_IN_OUTPUT(29, 28, 29, q10s16, q11s16)
|
||||
// part of stage 7
|
||||
DO_BUTTERFLY_STD(cospi_16_64, cospi_16_64, &q13s16, &q14s16)
|
||||
STORE_IN_OUTPUT(29, 20, 27, q13s16, q14s16)
|
||||
DO_BUTTERFLY(q0s16, q1s16, cospi_16_64, cospi_16_64, &q1s16, &q0s16);
|
||||
STORE_IN_OUTPUT(27, 21, 26, q1s16, q0s16)
|
||||
|
||||
// -----------------------------------------
|
||||
// BLOCK C: 8-10,11-15
|
||||
// -----------------------------------------
|
||||
// generate 8,9,14,15
|
||||
// part of stage 2
|
||||
LOAD_FROM_TRANSPOSED(3, 2, 30)
|
||||
DO_BUTTERFLY_STD(cospi_30_64, cospi_2_64, &q0s16, &q2s16)
|
||||
LOAD_FROM_TRANSPOSED(30, 18, 14)
|
||||
DO_BUTTERFLY_STD(cospi_14_64, cospi_18_64, &q1s16, &q3s16)
|
||||
// part of stage 3
|
||||
q13s16 = vsubq_s16(q0s16, q1s16);
|
||||
q0s16 = vaddq_s16(q0s16, q1s16);
|
||||
q14s16 = vsubq_s16(q2s16, q3s16);
|
||||
q2s16 = vaddq_s16(q2s16, q3s16);
|
||||
// part of stage 4
|
||||
DO_BUTTERFLY_STD(cospi_24_64, cospi_8_64, &q1s16, &q3s16)
|
||||
|
||||
// generate 10,11,12,13
|
||||
// part of stage 2
|
||||
LOAD_FROM_TRANSPOSED(14, 10, 22)
|
||||
DO_BUTTERFLY_STD(cospi_22_64, cospi_10_64, &q5s16, &q7s16)
|
||||
LOAD_FROM_TRANSPOSED(22, 26, 6)
|
||||
DO_BUTTERFLY_STD(cospi_6_64, cospi_26_64, &q4s16, &q6s16)
|
||||
// part of stage 3
|
||||
q14s16 = vsubq_s16(q4s16, q5s16);
|
||||
q5s16 = vaddq_s16(q4s16, q5s16);
|
||||
q13s16 = vsubq_s16(q6s16, q7s16);
|
||||
q6s16 = vaddq_s16(q6s16, q7s16);
|
||||
// part of stage 4
|
||||
DO_BUTTERFLY_STD(-cospi_8_64, -cospi_24_64, &q4s16, &q7s16)
|
||||
// part of stage 5
|
||||
q8s16 = vaddq_s16(q0s16, q5s16);
|
||||
q9s16 = vaddq_s16(q1s16, q7s16);
|
||||
q13s16 = vsubq_s16(q1s16, q7s16);
|
||||
q14s16 = vsubq_s16(q3s16, q4s16);
|
||||
q10s16 = vaddq_s16(q3s16, q4s16);
|
||||
q15s16 = vaddq_s16(q2s16, q6s16);
|
||||
STORE_IN_OUTPUT(26, 8, 15, q8s16, q15s16)
|
||||
STORE_IN_OUTPUT(15, 9, 14, q9s16, q10s16)
|
||||
// part of stage 6
|
||||
DO_BUTTERFLY_STD(cospi_16_64, cospi_16_64, &q1s16, &q3s16)
|
||||
STORE_IN_OUTPUT(14, 13, 10, q3s16, q1s16)
|
||||
q13s16 = vsubq_s16(q0s16, q5s16);
|
||||
q14s16 = vsubq_s16(q2s16, q6s16);
|
||||
DO_BUTTERFLY_STD(cospi_16_64, cospi_16_64, &q1s16, &q3s16)
|
||||
STORE_IN_OUTPUT(10, 11, 12, q1s16, q3s16)
|
||||
|
||||
// -----------------------------------------
|
||||
// BLOCK D: 0-3,4-7
|
||||
// -----------------------------------------
|
||||
// generate 4,5,6,7
|
||||
// part of stage 3
|
||||
LOAD_FROM_TRANSPOSED(6, 4, 28)
|
||||
DO_BUTTERFLY_STD(cospi_28_64, cospi_4_64, &q0s16, &q2s16)
|
||||
LOAD_FROM_TRANSPOSED(28, 20, 12)
|
||||
DO_BUTTERFLY_STD(cospi_12_64, cospi_20_64, &q1s16, &q3s16)
|
||||
// part of stage 4
|
||||
q13s16 = vsubq_s16(q0s16, q1s16);
|
||||
q0s16 = vaddq_s16(q0s16, q1s16);
|
||||
q14s16 = vsubq_s16(q2s16, q3s16);
|
||||
q2s16 = vaddq_s16(q2s16, q3s16);
|
||||
// part of stage 5
|
||||
DO_BUTTERFLY_STD(cospi_16_64, cospi_16_64, &q1s16, &q3s16)
|
||||
|
||||
// generate 0,1,2,3
|
||||
// part of stage 4
|
||||
LOAD_FROM_TRANSPOSED(12, 0, 16)
|
||||
DO_BUTTERFLY_STD(cospi_16_64, cospi_16_64, &q5s16, &q7s16)
|
||||
LOAD_FROM_TRANSPOSED(16, 8, 24)
|
||||
DO_BUTTERFLY_STD(cospi_24_64, cospi_8_64, &q14s16, &q6s16)
|
||||
// part of stage 5
|
||||
q4s16 = vaddq_s16(q7s16, q6s16);
|
||||
q7s16 = vsubq_s16(q7s16, q6s16);
|
||||
q6s16 = vsubq_s16(q5s16, q14s16);
|
||||
q5s16 = vaddq_s16(q5s16, q14s16);
|
||||
// part of stage 6
|
||||
q8s16 = vaddq_s16(q4s16, q2s16);
|
||||
q9s16 = vaddq_s16(q5s16, q3s16);
|
||||
q10s16 = vaddq_s16(q6s16, q1s16);
|
||||
q11s16 = vaddq_s16(q7s16, q0s16);
|
||||
q12s16 = vsubq_s16(q7s16, q0s16);
|
||||
q13s16 = vsubq_s16(q6s16, q1s16);
|
||||
q14s16 = vsubq_s16(q5s16, q3s16);
|
||||
q15s16 = vsubq_s16(q4s16, q2s16);
|
||||
// part of stage 7
|
||||
LOAD_FROM_OUTPUT(12, 14, 15, q0s16, q1s16)
|
||||
q2s16 = vaddq_s16(q8s16, q1s16);
|
||||
q3s16 = vaddq_s16(q9s16, q0s16);
|
||||
q4s16 = vsubq_s16(q9s16, q0s16);
|
||||
q5s16 = vsubq_s16(q8s16, q1s16);
|
||||
LOAD_FROM_OUTPUT(15, 16, 17, q0s16, q1s16)
|
||||
q8s16 = vaddq_s16(q4s16, q1s16);
|
||||
q9s16 = vaddq_s16(q5s16, q0s16);
|
||||
q6s16 = vsubq_s16(q5s16, q0s16);
|
||||
q7s16 = vsubq_s16(q4s16, q1s16);
|
||||
|
||||
if (idct32_pass_loop == 0) {
|
||||
idct32_bands_end_1st_pass(out, q2s16, q3s16, q6s16, q7s16, q8s16, q9s16,
|
||||
q10s16, q11s16, q12s16, q13s16, q14s16,
|
||||
q15s16);
|
||||
} else {
|
||||
idct32_bands_end_2nd_pass(out, dest, stride, q2s16, q3s16, q6s16, q7s16,
|
||||
q8s16, q9s16, q10s16, q11s16, q12s16, q13s16,
|
||||
q14s16, q15s16);
|
||||
dest += 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
71
third_party/aom/aom_dsp/arm/idct4x4_1_add_neon.asm
vendored
Normal file
71
third_party/aom/aom_dsp/arm/idct4x4_1_add_neon.asm
vendored
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
;
|
||||
; Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
;
|
||||
; This source code is subject to the terms of the BSD 2 Clause License and
|
||||
; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
; was not distributed with this source code in the LICENSE file, you can
|
||||
; obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
; Media Patent License 1.0 was not distributed with this source code in the
|
||||
; PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
;
|
||||
|
||||
|
||||
|
||||
EXPORT |aom_idct4x4_1_add_neon|
|
||||
ARM
|
||||
REQUIRE8
|
||||
PRESERVE8
|
||||
|
||||
AREA ||.text||, CODE, READONLY, ALIGN=2
|
||||
|
||||
;void aom_idct4x4_1_add_neon(int16_t *input, uint8_t *dest,
|
||||
; int dest_stride)
|
||||
;
|
||||
; r0 int16_t input
|
||||
; r1 uint8_t *dest
|
||||
; r2 int dest_stride)
|
||||
|
||||
|aom_idct4x4_1_add_neon| PROC
|
||||
ldrsh r0, [r0]
|
||||
|
||||
; generate cospi_16_64 = 11585
|
||||
mov r12, #0x2d00
|
||||
add r12, #0x41
|
||||
|
||||
; out = dct_const_round_shift(input[0] * cospi_16_64)
|
||||
mul r0, r0, r12 ; input[0] * cospi_16_64
|
||||
add r0, r0, #0x2000 ; +(1 << ((DCT_CONST_BITS) - 1))
|
||||
asr r0, r0, #14 ; >> DCT_CONST_BITS
|
||||
|
||||
; out = dct_const_round_shift(out * cospi_16_64)
|
||||
mul r0, r0, r12 ; out * cospi_16_64
|
||||
mov r12, r1 ; save dest
|
||||
add r0, r0, #0x2000 ; +(1 << ((DCT_CONST_BITS) - 1))
|
||||
asr r0, r0, #14 ; >> DCT_CONST_BITS
|
||||
|
||||
; a1 = ROUND_POWER_OF_TWO(out, 4)
|
||||
add r0, r0, #8 ; + (1 <<((4) - 1))
|
||||
asr r0, r0, #4 ; >> 4
|
||||
|
||||
vdup.s16 q0, r0 ; duplicate a1
|
||||
|
||||
vld1.32 {d2[0]}, [r1], r2
|
||||
vld1.32 {d2[1]}, [r1], r2
|
||||
vld1.32 {d4[0]}, [r1], r2
|
||||
vld1.32 {d4[1]}, [r1]
|
||||
|
||||
vaddw.u8 q8, q0, d2 ; dest[x] + a1
|
||||
vaddw.u8 q9, q0, d4
|
||||
|
||||
vqmovun.s16 d6, q8 ; clip_pixel
|
||||
vqmovun.s16 d7, q9
|
||||
|
||||
vst1.32 {d6[0]}, [r12], r2
|
||||
vst1.32 {d6[1]}, [r12], r2
|
||||
vst1.32 {d7[0]}, [r12], r2
|
||||
vst1.32 {d7[1]}, [r12]
|
||||
|
||||
bx lr
|
||||
ENDP ; |aom_idct4x4_1_add_neon|
|
||||
|
||||
END
|
||||
47
third_party/aom/aom_dsp/arm/idct4x4_1_add_neon.c
vendored
Normal file
47
third_party/aom/aom_dsp/arm/idct4x4_1_add_neon.c
vendored
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <arm_neon.h>
|
||||
|
||||
#include "aom_dsp/inv_txfm.h"
|
||||
#include "aom_ports/mem.h"
|
||||
|
||||
void aom_idct4x4_1_add_neon(int16_t *input, uint8_t *dest, int dest_stride) {
|
||||
uint8x8_t d6u8;
|
||||
uint32x2_t d2u32 = vdup_n_u32(0);
|
||||
uint16x8_t q8u16;
|
||||
int16x8_t q0s16;
|
||||
uint8_t *d1, *d2;
|
||||
int16_t i, a1;
|
||||
int16_t out = dct_const_round_shift(input[0] * cospi_16_64);
|
||||
out = dct_const_round_shift(out * cospi_16_64);
|
||||
a1 = ROUND_POWER_OF_TWO(out, 4);
|
||||
|
||||
q0s16 = vdupq_n_s16(a1);
|
||||
|
||||
// dc_only_idct_add
|
||||
d1 = d2 = dest;
|
||||
for (i = 0; i < 2; i++) {
|
||||
d2u32 = vld1_lane_u32((const uint32_t *)d1, d2u32, 0);
|
||||
d1 += dest_stride;
|
||||
d2u32 = vld1_lane_u32((const uint32_t *)d1, d2u32, 1);
|
||||
d1 += dest_stride;
|
||||
|
||||
q8u16 = vaddw_u8(vreinterpretq_u16_s16(q0s16), vreinterpret_u8_u32(d2u32));
|
||||
d6u8 = vqmovun_s16(vreinterpretq_s16_u16(q8u16));
|
||||
|
||||
vst1_lane_u32((uint32_t *)d2, vreinterpret_u32_u8(d6u8), 0);
|
||||
d2 += dest_stride;
|
||||
vst1_lane_u32((uint32_t *)d2, vreinterpret_u32_u8(d6u8), 1);
|
||||
d2 += dest_stride;
|
||||
}
|
||||
return;
|
||||
}
|
||||
193
third_party/aom/aom_dsp/arm/idct4x4_add_neon.asm
vendored
Normal file
193
third_party/aom/aom_dsp/arm/idct4x4_add_neon.asm
vendored
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
;
|
||||
; Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
;
|
||||
; This source code is subject to the terms of the BSD 2 Clause License and
|
||||
; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
; was not distributed with this source code in the LICENSE file, you can
|
||||
; obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
; Media Patent License 1.0 was not distributed with this source code in the
|
||||
; PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
;
|
||||
|
||||
;
|
||||
|
||||
EXPORT |aom_idct4x4_16_add_neon|
|
||||
ARM
|
||||
REQUIRE8
|
||||
PRESERVE8
|
||||
|
||||
AREA ||.text||, CODE, READONLY, ALIGN=2
|
||||
|
||||
AREA Block, CODE, READONLY ; name this block of code
|
||||
;void aom_idct4x4_16_add_neon(int16_t *input, uint8_t *dest, int dest_stride)
|
||||
;
|
||||
; r0 int16_t input
|
||||
; r1 uint8_t *dest
|
||||
; r2 int dest_stride)
|
||||
|
||||
|aom_idct4x4_16_add_neon| PROC
|
||||
|
||||
; The 2D transform is done with two passes which are actually pretty
|
||||
; similar. We first transform the rows. This is done by transposing
|
||||
; the inputs, doing an SIMD column transform (the columns are the
|
||||
; transposed rows) and then transpose the results (so that it goes back
|
||||
; in normal/row positions). Then, we transform the columns by doing
|
||||
; another SIMD column transform.
|
||||
; So, two passes of a transpose followed by a column transform.
|
||||
|
||||
; load the inputs into q8-q9, d16-d19
|
||||
vld1.s16 {q8,q9}, [r0]!
|
||||
|
||||
; generate scalar constants
|
||||
; cospi_8_64 = 15137 = 0x3b21
|
||||
mov r0, #0x3b00
|
||||
add r0, #0x21
|
||||
; cospi_16_64 = 11585 = 0x2d41
|
||||
mov r3, #0x2d00
|
||||
add r3, #0x41
|
||||
; cospi_24_64 = 6270 = 0x 187e
|
||||
mov r12, #0x1800
|
||||
add r12, #0x7e
|
||||
|
||||
; transpose the input data
|
||||
; 00 01 02 03 d16
|
||||
; 10 11 12 13 d17
|
||||
; 20 21 22 23 d18
|
||||
; 30 31 32 33 d19
|
||||
vtrn.16 d16, d17
|
||||
vtrn.16 d18, d19
|
||||
|
||||
; generate constant vectors
|
||||
vdup.16 d20, r0 ; replicate cospi_8_64
|
||||
vdup.16 d21, r3 ; replicate cospi_16_64
|
||||
|
||||
; 00 10 02 12 d16
|
||||
; 01 11 03 13 d17
|
||||
; 20 30 22 32 d18
|
||||
; 21 31 23 33 d19
|
||||
vtrn.32 q8, q9
|
||||
; 00 10 20 30 d16
|
||||
; 01 11 21 31 d17
|
||||
; 02 12 22 32 d18
|
||||
; 03 13 23 33 d19
|
||||
|
||||
vdup.16 d22, r12 ; replicate cospi_24_64
|
||||
|
||||
; do the transform on transposed rows
|
||||
|
||||
; stage 1
|
||||
vadd.s16 d23, d16, d18 ; (input[0] + input[2])
|
||||
vsub.s16 d24, d16, d18 ; (input[0] - input[2])
|
||||
|
||||
vmull.s16 q15, d17, d22 ; input[1] * cospi_24_64
|
||||
vmull.s16 q1, d17, d20 ; input[1] * cospi_8_64
|
||||
|
||||
; (input[0] + input[2]) * cospi_16_64;
|
||||
; (input[0] - input[2]) * cospi_16_64;
|
||||
vmull.s16 q13, d23, d21
|
||||
vmull.s16 q14, d24, d21
|
||||
|
||||
; input[1] * cospi_24_64 - input[3] * cospi_8_64;
|
||||
; input[1] * cospi_8_64 + input[3] * cospi_24_64;
|
||||
vmlsl.s16 q15, d19, d20
|
||||
vmlal.s16 q1, d19, d22
|
||||
|
||||
; dct_const_round_shift
|
||||
vqrshrn.s32 d26, q13, #14
|
||||
vqrshrn.s32 d27, q14, #14
|
||||
vqrshrn.s32 d29, q15, #14
|
||||
vqrshrn.s32 d28, q1, #14
|
||||
|
||||
; stage 2
|
||||
; output[0] = step[0] + step[3];
|
||||
; output[1] = step[1] + step[2];
|
||||
; output[3] = step[0] - step[3];
|
||||
; output[2] = step[1] - step[2];
|
||||
vadd.s16 q8, q13, q14
|
||||
vsub.s16 q9, q13, q14
|
||||
vswp d18, d19
|
||||
|
||||
; transpose the results
|
||||
; 00 01 02 03 d16
|
||||
; 10 11 12 13 d17
|
||||
; 20 21 22 23 d18
|
||||
; 30 31 32 33 d19
|
||||
vtrn.16 d16, d17
|
||||
vtrn.16 d18, d19
|
||||
; 00 10 02 12 d16
|
||||
; 01 11 03 13 d17
|
||||
; 20 30 22 32 d18
|
||||
; 21 31 23 33 d19
|
||||
vtrn.32 q8, q9
|
||||
; 00 10 20 30 d16
|
||||
; 01 11 21 31 d17
|
||||
; 02 12 22 32 d18
|
||||
; 03 13 23 33 d19
|
||||
|
||||
; do the transform on columns
|
||||
|
||||
; stage 1
|
||||
vadd.s16 d23, d16, d18 ; (input[0] + input[2])
|
||||
vsub.s16 d24, d16, d18 ; (input[0] - input[2])
|
||||
|
||||
vmull.s16 q15, d17, d22 ; input[1] * cospi_24_64
|
||||
vmull.s16 q1, d17, d20 ; input[1] * cospi_8_64
|
||||
|
||||
; (input[0] + input[2]) * cospi_16_64;
|
||||
; (input[0] - input[2]) * cospi_16_64;
|
||||
vmull.s16 q13, d23, d21
|
||||
vmull.s16 q14, d24, d21
|
||||
|
||||
; input[1] * cospi_24_64 - input[3] * cospi_8_64;
|
||||
; input[1] * cospi_8_64 + input[3] * cospi_24_64;
|
||||
vmlsl.s16 q15, d19, d20
|
||||
vmlal.s16 q1, d19, d22
|
||||
|
||||
; dct_const_round_shift
|
||||
vqrshrn.s32 d26, q13, #14
|
||||
vqrshrn.s32 d27, q14, #14
|
||||
vqrshrn.s32 d29, q15, #14
|
||||
vqrshrn.s32 d28, q1, #14
|
||||
|
||||
; stage 2
|
||||
; output[0] = step[0] + step[3];
|
||||
; output[1] = step[1] + step[2];
|
||||
; output[3] = step[0] - step[3];
|
||||
; output[2] = step[1] - step[2];
|
||||
vadd.s16 q8, q13, q14
|
||||
vsub.s16 q9, q13, q14
|
||||
|
||||
; The results are in two registers, one of them being swapped. This will
|
||||
; be taken care of by loading the 'dest' value in a swapped fashion and
|
||||
; also storing them in the same swapped fashion.
|
||||
; temp_out[0, 1] = d16, d17 = q8
|
||||
; temp_out[2, 3] = d19, d18 = q9 swapped
|
||||
|
||||
; ROUND_POWER_OF_TWO(temp_out[j], 4)
|
||||
vrshr.s16 q8, q8, #4
|
||||
vrshr.s16 q9, q9, #4
|
||||
|
||||
vld1.32 {d26[0]}, [r1], r2
|
||||
vld1.32 {d26[1]}, [r1], r2
|
||||
vld1.32 {d27[1]}, [r1], r2
|
||||
vld1.32 {d27[0]}, [r1] ; no post-increment
|
||||
|
||||
; ROUND_POWER_OF_TWO(temp_out[j], 4) + dest[j * dest_stride + i]
|
||||
vaddw.u8 q8, q8, d26
|
||||
vaddw.u8 q9, q9, d27
|
||||
|
||||
; clip_pixel
|
||||
vqmovun.s16 d26, q8
|
||||
vqmovun.s16 d27, q9
|
||||
|
||||
; do the stores in reverse order with negative post-increment, by changing
|
||||
; the sign of the stride
|
||||
rsb r2, r2, #0
|
||||
vst1.32 {d27[0]}, [r1], r2
|
||||
vst1.32 {d27[1]}, [r1], r2
|
||||
vst1.32 {d26[1]}, [r1], r2
|
||||
vst1.32 {d26[0]}, [r1] ; no post-increment
|
||||
bx lr
|
||||
ENDP ; |aom_idct4x4_16_add_neon|
|
||||
|
||||
END
|
||||
146
third_party/aom/aom_dsp/arm/idct4x4_add_neon.c
vendored
Normal file
146
third_party/aom/aom_dsp/arm/idct4x4_add_neon.c
vendored
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <arm_neon.h>
|
||||
|
||||
#include "aom_dsp/txfm_common.h"
|
||||
|
||||
void aom_idct4x4_16_add_neon(int16_t *input, uint8_t *dest, int dest_stride) {
|
||||
uint8x8_t d26u8, d27u8;
|
||||
uint32x2_t d26u32, d27u32;
|
||||
uint16x8_t q8u16, q9u16;
|
||||
int16x4_t d16s16, d17s16, d18s16, d19s16, d20s16, d21s16;
|
||||
int16x4_t d22s16, d23s16, d24s16, d26s16, d27s16, d28s16, d29s16;
|
||||
int16x8_t q8s16, q9s16, q13s16, q14s16;
|
||||
int32x4_t q1s32, q13s32, q14s32, q15s32;
|
||||
int16x4x2_t d0x2s16, d1x2s16;
|
||||
int32x4x2_t q0x2s32;
|
||||
uint8_t *d;
|
||||
|
||||
d26u32 = d27u32 = vdup_n_u32(0);
|
||||
|
||||
q8s16 = vld1q_s16(input);
|
||||
q9s16 = vld1q_s16(input + 8);
|
||||
|
||||
d16s16 = vget_low_s16(q8s16);
|
||||
d17s16 = vget_high_s16(q8s16);
|
||||
d18s16 = vget_low_s16(q9s16);
|
||||
d19s16 = vget_high_s16(q9s16);
|
||||
|
||||
d0x2s16 = vtrn_s16(d16s16, d17s16);
|
||||
d1x2s16 = vtrn_s16(d18s16, d19s16);
|
||||
q8s16 = vcombine_s16(d0x2s16.val[0], d0x2s16.val[1]);
|
||||
q9s16 = vcombine_s16(d1x2s16.val[0], d1x2s16.val[1]);
|
||||
|
||||
d20s16 = vdup_n_s16((int16_t)cospi_8_64);
|
||||
d21s16 = vdup_n_s16((int16_t)cospi_16_64);
|
||||
|
||||
q0x2s32 =
|
||||
vtrnq_s32(vreinterpretq_s32_s16(q8s16), vreinterpretq_s32_s16(q9s16));
|
||||
d16s16 = vget_low_s16(vreinterpretq_s16_s32(q0x2s32.val[0]));
|
||||
d17s16 = vget_high_s16(vreinterpretq_s16_s32(q0x2s32.val[0]));
|
||||
d18s16 = vget_low_s16(vreinterpretq_s16_s32(q0x2s32.val[1]));
|
||||
d19s16 = vget_high_s16(vreinterpretq_s16_s32(q0x2s32.val[1]));
|
||||
|
||||
d22s16 = vdup_n_s16((int16_t)cospi_24_64);
|
||||
|
||||
// stage 1
|
||||
d23s16 = vadd_s16(d16s16, d18s16);
|
||||
d24s16 = vsub_s16(d16s16, d18s16);
|
||||
|
||||
q15s32 = vmull_s16(d17s16, d22s16);
|
||||
q1s32 = vmull_s16(d17s16, d20s16);
|
||||
q13s32 = vmull_s16(d23s16, d21s16);
|
||||
q14s32 = vmull_s16(d24s16, d21s16);
|
||||
|
||||
q15s32 = vmlsl_s16(q15s32, d19s16, d20s16);
|
||||
q1s32 = vmlal_s16(q1s32, d19s16, d22s16);
|
||||
|
||||
d26s16 = vqrshrn_n_s32(q13s32, 14);
|
||||
d27s16 = vqrshrn_n_s32(q14s32, 14);
|
||||
d29s16 = vqrshrn_n_s32(q15s32, 14);
|
||||
d28s16 = vqrshrn_n_s32(q1s32, 14);
|
||||
q13s16 = vcombine_s16(d26s16, d27s16);
|
||||
q14s16 = vcombine_s16(d28s16, d29s16);
|
||||
|
||||
// stage 2
|
||||
q8s16 = vaddq_s16(q13s16, q14s16);
|
||||
q9s16 = vsubq_s16(q13s16, q14s16);
|
||||
|
||||
d16s16 = vget_low_s16(q8s16);
|
||||
d17s16 = vget_high_s16(q8s16);
|
||||
d18s16 = vget_high_s16(q9s16); // vswp d18 d19
|
||||
d19s16 = vget_low_s16(q9s16);
|
||||
|
||||
d0x2s16 = vtrn_s16(d16s16, d17s16);
|
||||
d1x2s16 = vtrn_s16(d18s16, d19s16);
|
||||
q8s16 = vcombine_s16(d0x2s16.val[0], d0x2s16.val[1]);
|
||||
q9s16 = vcombine_s16(d1x2s16.val[0], d1x2s16.val[1]);
|
||||
|
||||
q0x2s32 =
|
||||
vtrnq_s32(vreinterpretq_s32_s16(q8s16), vreinterpretq_s32_s16(q9s16));
|
||||
d16s16 = vget_low_s16(vreinterpretq_s16_s32(q0x2s32.val[0]));
|
||||
d17s16 = vget_high_s16(vreinterpretq_s16_s32(q0x2s32.val[0]));
|
||||
d18s16 = vget_low_s16(vreinterpretq_s16_s32(q0x2s32.val[1]));
|
||||
d19s16 = vget_high_s16(vreinterpretq_s16_s32(q0x2s32.val[1]));
|
||||
|
||||
// do the transform on columns
|
||||
// stage 1
|
||||
d23s16 = vadd_s16(d16s16, d18s16);
|
||||
d24s16 = vsub_s16(d16s16, d18s16);
|
||||
|
||||
q15s32 = vmull_s16(d17s16, d22s16);
|
||||
q1s32 = vmull_s16(d17s16, d20s16);
|
||||
q13s32 = vmull_s16(d23s16, d21s16);
|
||||
q14s32 = vmull_s16(d24s16, d21s16);
|
||||
|
||||
q15s32 = vmlsl_s16(q15s32, d19s16, d20s16);
|
||||
q1s32 = vmlal_s16(q1s32, d19s16, d22s16);
|
||||
|
||||
d26s16 = vqrshrn_n_s32(q13s32, 14);
|
||||
d27s16 = vqrshrn_n_s32(q14s32, 14);
|
||||
d29s16 = vqrshrn_n_s32(q15s32, 14);
|
||||
d28s16 = vqrshrn_n_s32(q1s32, 14);
|
||||
q13s16 = vcombine_s16(d26s16, d27s16);
|
||||
q14s16 = vcombine_s16(d28s16, d29s16);
|
||||
|
||||
// stage 2
|
||||
q8s16 = vaddq_s16(q13s16, q14s16);
|
||||
q9s16 = vsubq_s16(q13s16, q14s16);
|
||||
|
||||
q8s16 = vrshrq_n_s16(q8s16, 4);
|
||||
q9s16 = vrshrq_n_s16(q9s16, 4);
|
||||
|
||||
d = dest;
|
||||
d26u32 = vld1_lane_u32((const uint32_t *)d, d26u32, 0);
|
||||
d += dest_stride;
|
||||
d26u32 = vld1_lane_u32((const uint32_t *)d, d26u32, 1);
|
||||
d += dest_stride;
|
||||
d27u32 = vld1_lane_u32((const uint32_t *)d, d27u32, 1);
|
||||
d += dest_stride;
|
||||
d27u32 = vld1_lane_u32((const uint32_t *)d, d27u32, 0);
|
||||
|
||||
q8u16 = vaddw_u8(vreinterpretq_u16_s16(q8s16), vreinterpret_u8_u32(d26u32));
|
||||
q9u16 = vaddw_u8(vreinterpretq_u16_s16(q9s16), vreinterpret_u8_u32(d27u32));
|
||||
|
||||
d26u8 = vqmovun_s16(vreinterpretq_s16_u16(q8u16));
|
||||
d27u8 = vqmovun_s16(vreinterpretq_s16_u16(q9u16));
|
||||
|
||||
d = dest;
|
||||
vst1_lane_u32((uint32_t *)d, vreinterpret_u32_u8(d26u8), 0);
|
||||
d += dest_stride;
|
||||
vst1_lane_u32((uint32_t *)d, vreinterpret_u32_u8(d26u8), 1);
|
||||
d += dest_stride;
|
||||
vst1_lane_u32((uint32_t *)d, vreinterpret_u32_u8(d27u8), 1);
|
||||
d += dest_stride;
|
||||
vst1_lane_u32((uint32_t *)d, vreinterpret_u32_u8(d27u8), 0);
|
||||
return;
|
||||
}
|
||||
91
third_party/aom/aom_dsp/arm/idct8x8_1_add_neon.asm
vendored
Normal file
91
third_party/aom/aom_dsp/arm/idct8x8_1_add_neon.asm
vendored
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
;
|
||||
; Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
;
|
||||
; This source code is subject to the terms of the BSD 2 Clause License and
|
||||
; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
; was not distributed with this source code in the LICENSE file, you can
|
||||
; obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
; Media Patent License 1.0 was not distributed with this source code in the
|
||||
; PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
;
|
||||
|
||||
|
||||
|
||||
EXPORT |aom_idct8x8_1_add_neon|
|
||||
ARM
|
||||
REQUIRE8
|
||||
PRESERVE8
|
||||
|
||||
AREA ||.text||, CODE, READONLY, ALIGN=2
|
||||
|
||||
;void aom_idct8x8_1_add_neon(int16_t *input, uint8_t *dest,
|
||||
; int dest_stride)
|
||||
;
|
||||
; r0 int16_t input
|
||||
; r1 uint8_t *dest
|
||||
; r2 int dest_stride)
|
||||
|
||||
|aom_idct8x8_1_add_neon| PROC
|
||||
ldrsh r0, [r0]
|
||||
|
||||
; generate cospi_16_64 = 11585
|
||||
mov r12, #0x2d00
|
||||
add r12, #0x41
|
||||
|
||||
; out = dct_const_round_shift(input[0] * cospi_16_64)
|
||||
mul r0, r0, r12 ; input[0] * cospi_16_64
|
||||
add r0, r0, #0x2000 ; +(1 << ((DCT_CONST_BITS) - 1))
|
||||
asr r0, r0, #14 ; >> DCT_CONST_BITS
|
||||
|
||||
; out = dct_const_round_shift(out * cospi_16_64)
|
||||
mul r0, r0, r12 ; out * cospi_16_64
|
||||
mov r12, r1 ; save dest
|
||||
add r0, r0, #0x2000 ; +(1 << ((DCT_CONST_BITS) - 1))
|
||||
asr r0, r0, #14 ; >> DCT_CONST_BITS
|
||||
|
||||
; a1 = ROUND_POWER_OF_TWO(out, 5)
|
||||
add r0, r0, #16 ; + (1 <<((5) - 1))
|
||||
asr r0, r0, #5 ; >> 5
|
||||
|
||||
vdup.s16 q0, r0 ; duplicate a1
|
||||
|
||||
; load destination data
|
||||
vld1.64 {d2}, [r1], r2
|
||||
vld1.64 {d3}, [r1], r2
|
||||
vld1.64 {d4}, [r1], r2
|
||||
vld1.64 {d5}, [r1], r2
|
||||
vld1.64 {d6}, [r1], r2
|
||||
vld1.64 {d7}, [r1], r2
|
||||
vld1.64 {d16}, [r1], r2
|
||||
vld1.64 {d17}, [r1]
|
||||
|
||||
vaddw.u8 q9, q0, d2 ; dest[x] + a1
|
||||
vaddw.u8 q10, q0, d3 ; dest[x] + a1
|
||||
vaddw.u8 q11, q0, d4 ; dest[x] + a1
|
||||
vaddw.u8 q12, q0, d5 ; dest[x] + a1
|
||||
vqmovun.s16 d2, q9 ; clip_pixel
|
||||
vqmovun.s16 d3, q10 ; clip_pixel
|
||||
vqmovun.s16 d30, q11 ; clip_pixel
|
||||
vqmovun.s16 d31, q12 ; clip_pixel
|
||||
vst1.64 {d2}, [r12], r2
|
||||
vst1.64 {d3}, [r12], r2
|
||||
vst1.64 {d30}, [r12], r2
|
||||
vst1.64 {d31}, [r12], r2
|
||||
|
||||
vaddw.u8 q9, q0, d6 ; dest[x] + a1
|
||||
vaddw.u8 q10, q0, d7 ; dest[x] + a1
|
||||
vaddw.u8 q11, q0, d16 ; dest[x] + a1
|
||||
vaddw.u8 q12, q0, d17 ; dest[x] + a1
|
||||
vqmovun.s16 d2, q9 ; clip_pixel
|
||||
vqmovun.s16 d3, q10 ; clip_pixel
|
||||
vqmovun.s16 d30, q11 ; clip_pixel
|
||||
vqmovun.s16 d31, q12 ; clip_pixel
|
||||
vst1.64 {d2}, [r12], r2
|
||||
vst1.64 {d3}, [r12], r2
|
||||
vst1.64 {d30}, [r12], r2
|
||||
vst1.64 {d31}, [r12], r2
|
||||
|
||||
bx lr
|
||||
ENDP ; |aom_idct8x8_1_add_neon|
|
||||
|
||||
END
|
||||
62
third_party/aom/aom_dsp/arm/idct8x8_1_add_neon.c
vendored
Normal file
62
third_party/aom/aom_dsp/arm/idct8x8_1_add_neon.c
vendored
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <arm_neon.h>
|
||||
|
||||
#include "aom_dsp/inv_txfm.h"
|
||||
#include "aom_ports/mem.h"
|
||||
|
||||
void aom_idct8x8_1_add_neon(int16_t *input, uint8_t *dest, int dest_stride) {
|
||||
uint8x8_t d2u8, d3u8, d30u8, d31u8;
|
||||
uint64x1_t d2u64, d3u64, d4u64, d5u64;
|
||||
uint16x8_t q0u16, q9u16, q10u16, q11u16, q12u16;
|
||||
int16x8_t q0s16;
|
||||
uint8_t *d1, *d2;
|
||||
int16_t i, a1;
|
||||
int16_t out = dct_const_round_shift(input[0] * cospi_16_64);
|
||||
out = dct_const_round_shift(out * cospi_16_64);
|
||||
a1 = ROUND_POWER_OF_TWO(out, 5);
|
||||
|
||||
q0s16 = vdupq_n_s16(a1);
|
||||
q0u16 = vreinterpretq_u16_s16(q0s16);
|
||||
|
||||
d1 = d2 = dest;
|
||||
for (i = 0; i < 2; i++) {
|
||||
d2u64 = vld1_u64((const uint64_t *)d1);
|
||||
d1 += dest_stride;
|
||||
d3u64 = vld1_u64((const uint64_t *)d1);
|
||||
d1 += dest_stride;
|
||||
d4u64 = vld1_u64((const uint64_t *)d1);
|
||||
d1 += dest_stride;
|
||||
d5u64 = vld1_u64((const uint64_t *)d1);
|
||||
d1 += dest_stride;
|
||||
|
||||
q9u16 = vaddw_u8(q0u16, vreinterpret_u8_u64(d2u64));
|
||||
q10u16 = vaddw_u8(q0u16, vreinterpret_u8_u64(d3u64));
|
||||
q11u16 = vaddw_u8(q0u16, vreinterpret_u8_u64(d4u64));
|
||||
q12u16 = vaddw_u8(q0u16, vreinterpret_u8_u64(d5u64));
|
||||
|
||||
d2u8 = vqmovun_s16(vreinterpretq_s16_u16(q9u16));
|
||||
d3u8 = vqmovun_s16(vreinterpretq_s16_u16(q10u16));
|
||||
d30u8 = vqmovun_s16(vreinterpretq_s16_u16(q11u16));
|
||||
d31u8 = vqmovun_s16(vreinterpretq_s16_u16(q12u16));
|
||||
|
||||
vst1_u64((uint64_t *)d2, vreinterpret_u64_u8(d2u8));
|
||||
d2 += dest_stride;
|
||||
vst1_u64((uint64_t *)d2, vreinterpret_u64_u8(d3u8));
|
||||
d2 += dest_stride;
|
||||
vst1_u64((uint64_t *)d2, vreinterpret_u64_u8(d30u8));
|
||||
d2 += dest_stride;
|
||||
vst1_u64((uint64_t *)d2, vreinterpret_u64_u8(d31u8));
|
||||
d2 += dest_stride;
|
||||
}
|
||||
return;
|
||||
}
|
||||
522
third_party/aom/aom_dsp/arm/idct8x8_add_neon.asm
vendored
Normal file
522
third_party/aom/aom_dsp/arm/idct8x8_add_neon.asm
vendored
Normal file
|
|
@ -0,0 +1,522 @@
|
|||
;
|
||||
; Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
;
|
||||
; This source code is subject to the terms of the BSD 2 Clause License and
|
||||
; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
; was not distributed with this source code in the LICENSE file, you can
|
||||
; obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
; Media Patent License 1.0 was not distributed with this source code in the
|
||||
; PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
;
|
||||
|
||||
;
|
||||
|
||||
EXPORT |aom_idct8x8_64_add_neon|
|
||||
EXPORT |aom_idct8x8_12_add_neon|
|
||||
ARM
|
||||
REQUIRE8
|
||||
PRESERVE8
|
||||
|
||||
AREA ||.text||, CODE, READONLY, ALIGN=2
|
||||
|
||||
; Parallel 1D IDCT on all the columns of a 8x8 16bit data matrix which are
|
||||
; loaded in q8-q15. The output will be stored back into q8-q15 registers.
|
||||
; This macro will touch q0-q7 registers and use them as buffer during
|
||||
; calculation.
|
||||
MACRO
|
||||
IDCT8x8_1D
|
||||
; stage 1
|
||||
vdup.16 d0, r3 ; duplicate cospi_28_64
|
||||
vdup.16 d1, r4 ; duplicate cospi_4_64
|
||||
vdup.16 d2, r5 ; duplicate cospi_12_64
|
||||
vdup.16 d3, r6 ; duplicate cospi_20_64
|
||||
|
||||
; input[1] * cospi_28_64
|
||||
vmull.s16 q2, d18, d0
|
||||
vmull.s16 q3, d19, d0
|
||||
|
||||
; input[5] * cospi_12_64
|
||||
vmull.s16 q5, d26, d2
|
||||
vmull.s16 q6, d27, d2
|
||||
|
||||
; input[1]*cospi_28_64-input[7]*cospi_4_64
|
||||
vmlsl.s16 q2, d30, d1
|
||||
vmlsl.s16 q3, d31, d1
|
||||
|
||||
; input[5] * cospi_12_64 - input[3] * cospi_20_64
|
||||
vmlsl.s16 q5, d22, d3
|
||||
vmlsl.s16 q6, d23, d3
|
||||
|
||||
; dct_const_round_shift(input_dc * cospi_16_64)
|
||||
vqrshrn.s32 d8, q2, #14 ; >> 14
|
||||
vqrshrn.s32 d9, q3, #14 ; >> 14
|
||||
|
||||
; dct_const_round_shift(input_dc * cospi_16_64)
|
||||
vqrshrn.s32 d10, q5, #14 ; >> 14
|
||||
vqrshrn.s32 d11, q6, #14 ; >> 14
|
||||
|
||||
; input[1] * cospi_4_64
|
||||
vmull.s16 q2, d18, d1
|
||||
vmull.s16 q3, d19, d1
|
||||
|
||||
; input[5] * cospi_20_64
|
||||
vmull.s16 q9, d26, d3
|
||||
vmull.s16 q13, d27, d3
|
||||
|
||||
; input[1]*cospi_4_64+input[7]*cospi_28_64
|
||||
vmlal.s16 q2, d30, d0
|
||||
vmlal.s16 q3, d31, d0
|
||||
|
||||
; input[5] * cospi_20_64 + input[3] * cospi_12_64
|
||||
vmlal.s16 q9, d22, d2
|
||||
vmlal.s16 q13, d23, d2
|
||||
|
||||
; dct_const_round_shift(input_dc * cospi_16_64)
|
||||
vqrshrn.s32 d14, q2, #14 ; >> 14
|
||||
vqrshrn.s32 d15, q3, #14 ; >> 14
|
||||
|
||||
; stage 2 & stage 3 - even half
|
||||
vdup.16 d0, r7 ; duplicate cospi_16_64
|
||||
|
||||
; dct_const_round_shift(input_dc * cospi_16_64)
|
||||
vqrshrn.s32 d12, q9, #14 ; >> 14
|
||||
vqrshrn.s32 d13, q13, #14 ; >> 14
|
||||
|
||||
; input[0] * cospi_16_64
|
||||
vmull.s16 q2, d16, d0
|
||||
vmull.s16 q3, d17, d0
|
||||
|
||||
; input[0] * cospi_16_64
|
||||
vmull.s16 q13, d16, d0
|
||||
vmull.s16 q15, d17, d0
|
||||
|
||||
; (input[0] + input[2]) * cospi_16_64
|
||||
vmlal.s16 q2, d24, d0
|
||||
vmlal.s16 q3, d25, d0
|
||||
|
||||
; (input[0] - input[2]) * cospi_16_64
|
||||
vmlsl.s16 q13, d24, d0
|
||||
vmlsl.s16 q15, d25, d0
|
||||
|
||||
vdup.16 d0, r8 ; duplicate cospi_24_64
|
||||
vdup.16 d1, r9 ; duplicate cospi_8_64
|
||||
|
||||
; dct_const_round_shift(input_dc * cospi_16_64)
|
||||
vqrshrn.s32 d18, q2, #14 ; >> 14
|
||||
vqrshrn.s32 d19, q3, #14 ; >> 14
|
||||
|
||||
; dct_const_round_shift(input_dc * cospi_16_64)
|
||||
vqrshrn.s32 d22, q13, #14 ; >> 14
|
||||
vqrshrn.s32 d23, q15, #14 ; >> 14
|
||||
|
||||
; input[1] * cospi_24_64 - input[3] * cospi_8_64
|
||||
; input[1] * cospi_24_64
|
||||
vmull.s16 q2, d20, d0
|
||||
vmull.s16 q3, d21, d0
|
||||
|
||||
; input[1] * cospi_8_64
|
||||
vmull.s16 q8, d20, d1
|
||||
vmull.s16 q12, d21, d1
|
||||
|
||||
; input[1] * cospi_24_64 - input[3] * cospi_8_64
|
||||
vmlsl.s16 q2, d28, d1
|
||||
vmlsl.s16 q3, d29, d1
|
||||
|
||||
; input[1] * cospi_8_64 + input[3] * cospi_24_64
|
||||
vmlal.s16 q8, d28, d0
|
||||
vmlal.s16 q12, d29, d0
|
||||
|
||||
; dct_const_round_shift(input_dc * cospi_16_64)
|
||||
vqrshrn.s32 d26, q2, #14 ; >> 14
|
||||
vqrshrn.s32 d27, q3, #14 ; >> 14
|
||||
|
||||
; dct_const_round_shift(input_dc * cospi_16_64)
|
||||
vqrshrn.s32 d30, q8, #14 ; >> 14
|
||||
vqrshrn.s32 d31, q12, #14 ; >> 14
|
||||
|
||||
vadd.s16 q0, q9, q15 ; output[0] = step[0] + step[3]
|
||||
vadd.s16 q1, q11, q13 ; output[1] = step[1] + step[2]
|
||||
vsub.s16 q2, q11, q13 ; output[2] = step[1] - step[2]
|
||||
vsub.s16 q3, q9, q15 ; output[3] = step[0] - step[3]
|
||||
|
||||
; stage 3 -odd half
|
||||
vdup.16 d16, r7 ; duplicate cospi_16_64
|
||||
|
||||
; stage 2 - odd half
|
||||
vsub.s16 q13, q4, q5 ; step2[5] = step1[4] - step1[5]
|
||||
vadd.s16 q4, q4, q5 ; step2[4] = step1[4] + step1[5]
|
||||
vsub.s16 q14, q7, q6 ; step2[6] = -step1[6] + step1[7]
|
||||
vadd.s16 q7, q7, q6 ; step2[7] = step1[6] + step1[7]
|
||||
|
||||
; step2[6] * cospi_16_64
|
||||
vmull.s16 q9, d28, d16
|
||||
vmull.s16 q10, d29, d16
|
||||
|
||||
; step2[6] * cospi_16_64
|
||||
vmull.s16 q11, d28, d16
|
||||
vmull.s16 q12, d29, d16
|
||||
|
||||
; (step2[6] - step2[5]) * cospi_16_64
|
||||
vmlsl.s16 q9, d26, d16
|
||||
vmlsl.s16 q10, d27, d16
|
||||
|
||||
; (step2[5] + step2[6]) * cospi_16_64
|
||||
vmlal.s16 q11, d26, d16
|
||||
vmlal.s16 q12, d27, d16
|
||||
|
||||
; dct_const_round_shift(input_dc * cospi_16_64)
|
||||
vqrshrn.s32 d10, q9, #14 ; >> 14
|
||||
vqrshrn.s32 d11, q10, #14 ; >> 14
|
||||
|
||||
; dct_const_round_shift(input_dc * cospi_16_64)
|
||||
vqrshrn.s32 d12, q11, #14 ; >> 14
|
||||
vqrshrn.s32 d13, q12, #14 ; >> 14
|
||||
|
||||
; stage 4
|
||||
vadd.s16 q8, q0, q7 ; output[0] = step1[0] + step1[7];
|
||||
vadd.s16 q9, q1, q6 ; output[1] = step1[1] + step1[6];
|
||||
vadd.s16 q10, q2, q5 ; output[2] = step1[2] + step1[5];
|
||||
vadd.s16 q11, q3, q4 ; output[3] = step1[3] + step1[4];
|
||||
vsub.s16 q12, q3, q4 ; output[4] = step1[3] - step1[4];
|
||||
vsub.s16 q13, q2, q5 ; output[5] = step1[2] - step1[5];
|
||||
vsub.s16 q14, q1, q6 ; output[6] = step1[1] - step1[6];
|
||||
vsub.s16 q15, q0, q7 ; output[7] = step1[0] - step1[7];
|
||||
MEND
|
||||
|
||||
; Transpose a 8x8 16bit data matrix. Datas are loaded in q8-q15.
|
||||
MACRO
|
||||
TRANSPOSE8X8
|
||||
vswp d17, d24
|
||||
vswp d23, d30
|
||||
vswp d21, d28
|
||||
vswp d19, d26
|
||||
vtrn.32 q8, q10
|
||||
vtrn.32 q9, q11
|
||||
vtrn.32 q12, q14
|
||||
vtrn.32 q13, q15
|
||||
vtrn.16 q8, q9
|
||||
vtrn.16 q10, q11
|
||||
vtrn.16 q12, q13
|
||||
vtrn.16 q14, q15
|
||||
MEND
|
||||
|
||||
AREA Block, CODE, READONLY ; name this block of code
|
||||
;void aom_idct8x8_64_add_neon(int16_t *input, uint8_t *dest, int dest_stride)
|
||||
;
|
||||
; r0 int16_t input
|
||||
; r1 uint8_t *dest
|
||||
; r2 int dest_stride)
|
||||
|
||||
|aom_idct8x8_64_add_neon| PROC
|
||||
push {r4-r9}
|
||||
vpush {d8-d15}
|
||||
vld1.s16 {q8,q9}, [r0]!
|
||||
vld1.s16 {q10,q11}, [r0]!
|
||||
vld1.s16 {q12,q13}, [r0]!
|
||||
vld1.s16 {q14,q15}, [r0]!
|
||||
|
||||
; transpose the input data
|
||||
TRANSPOSE8X8
|
||||
|
||||
; generate cospi_28_64 = 3196
|
||||
mov r3, #0x0c00
|
||||
add r3, #0x7c
|
||||
|
||||
; generate cospi_4_64 = 16069
|
||||
mov r4, #0x3e00
|
||||
add r4, #0xc5
|
||||
|
||||
; generate cospi_12_64 = 13623
|
||||
mov r5, #0x3500
|
||||
add r5, #0x37
|
||||
|
||||
; generate cospi_20_64 = 9102
|
||||
mov r6, #0x2300
|
||||
add r6, #0x8e
|
||||
|
||||
; generate cospi_16_64 = 11585
|
||||
mov r7, #0x2d00
|
||||
add r7, #0x41
|
||||
|
||||
; generate cospi_24_64 = 6270
|
||||
mov r8, #0x1800
|
||||
add r8, #0x7e
|
||||
|
||||
; generate cospi_8_64 = 15137
|
||||
mov r9, #0x3b00
|
||||
add r9, #0x21
|
||||
|
||||
; First transform rows
|
||||
IDCT8x8_1D
|
||||
|
||||
; Transpose the matrix
|
||||
TRANSPOSE8X8
|
||||
|
||||
; Then transform columns
|
||||
IDCT8x8_1D
|
||||
|
||||
; ROUND_POWER_OF_TWO(temp_out[j], 5)
|
||||
vrshr.s16 q8, q8, #5
|
||||
vrshr.s16 q9, q9, #5
|
||||
vrshr.s16 q10, q10, #5
|
||||
vrshr.s16 q11, q11, #5
|
||||
vrshr.s16 q12, q12, #5
|
||||
vrshr.s16 q13, q13, #5
|
||||
vrshr.s16 q14, q14, #5
|
||||
vrshr.s16 q15, q15, #5
|
||||
|
||||
; save dest pointer
|
||||
mov r0, r1
|
||||
|
||||
; load destination data
|
||||
vld1.64 {d0}, [r1], r2
|
||||
vld1.64 {d1}, [r1], r2
|
||||
vld1.64 {d2}, [r1], r2
|
||||
vld1.64 {d3}, [r1], r2
|
||||
vld1.64 {d4}, [r1], r2
|
||||
vld1.64 {d5}, [r1], r2
|
||||
vld1.64 {d6}, [r1], r2
|
||||
vld1.64 {d7}, [r1]
|
||||
|
||||
; ROUND_POWER_OF_TWO(temp_out[j], 5) + dest[j * dest_stride + i]
|
||||
vaddw.u8 q8, q8, d0
|
||||
vaddw.u8 q9, q9, d1
|
||||
vaddw.u8 q10, q10, d2
|
||||
vaddw.u8 q11, q11, d3
|
||||
vaddw.u8 q12, q12, d4
|
||||
vaddw.u8 q13, q13, d5
|
||||
vaddw.u8 q14, q14, d6
|
||||
vaddw.u8 q15, q15, d7
|
||||
|
||||
; clip_pixel
|
||||
vqmovun.s16 d0, q8
|
||||
vqmovun.s16 d1, q9
|
||||
vqmovun.s16 d2, q10
|
||||
vqmovun.s16 d3, q11
|
||||
vqmovun.s16 d4, q12
|
||||
vqmovun.s16 d5, q13
|
||||
vqmovun.s16 d6, q14
|
||||
vqmovun.s16 d7, q15
|
||||
|
||||
; store the data
|
||||
vst1.64 {d0}, [r0], r2
|
||||
vst1.64 {d1}, [r0], r2
|
||||
vst1.64 {d2}, [r0], r2
|
||||
vst1.64 {d3}, [r0], r2
|
||||
vst1.64 {d4}, [r0], r2
|
||||
vst1.64 {d5}, [r0], r2
|
||||
vst1.64 {d6}, [r0], r2
|
||||
vst1.64 {d7}, [r0], r2
|
||||
|
||||
vpop {d8-d15}
|
||||
pop {r4-r9}
|
||||
bx lr
|
||||
ENDP ; |aom_idct8x8_64_add_neon|
|
||||
|
||||
;void aom_idct8x8_12_add_neon(int16_t *input, uint8_t *dest, int dest_stride)
|
||||
;
|
||||
; r0 int16_t input
|
||||
; r1 uint8_t *dest
|
||||
; r2 int dest_stride)
|
||||
|
||||
|aom_idct8x8_12_add_neon| PROC
|
||||
push {r4-r9}
|
||||
vpush {d8-d15}
|
||||
vld1.s16 {q8,q9}, [r0]!
|
||||
vld1.s16 {q10,q11}, [r0]!
|
||||
vld1.s16 {q12,q13}, [r0]!
|
||||
vld1.s16 {q14,q15}, [r0]!
|
||||
|
||||
; transpose the input data
|
||||
TRANSPOSE8X8
|
||||
|
||||
; generate cospi_28_64 = 3196
|
||||
mov r3, #0x0c00
|
||||
add r3, #0x7c
|
||||
|
||||
; generate cospi_4_64 = 16069
|
||||
mov r4, #0x3e00
|
||||
add r4, #0xc5
|
||||
|
||||
; generate cospi_12_64 = 13623
|
||||
mov r5, #0x3500
|
||||
add r5, #0x37
|
||||
|
||||
; generate cospi_20_64 = 9102
|
||||
mov r6, #0x2300
|
||||
add r6, #0x8e
|
||||
|
||||
; generate cospi_16_64 = 11585
|
||||
mov r7, #0x2d00
|
||||
add r7, #0x41
|
||||
|
||||
; generate cospi_24_64 = 6270
|
||||
mov r8, #0x1800
|
||||
add r8, #0x7e
|
||||
|
||||
; generate cospi_8_64 = 15137
|
||||
mov r9, #0x3b00
|
||||
add r9, #0x21
|
||||
|
||||
; First transform rows
|
||||
; stage 1
|
||||
; The following instructions use vqrdmulh to do the
|
||||
; dct_const_round_shift(input[1] * cospi_28_64). vqrdmulh will do doubling
|
||||
; multiply and shift the result by 16 bits instead of 14 bits. So we need
|
||||
; to double the constants before multiplying to compensate this.
|
||||
mov r12, r3, lsl #1
|
||||
vdup.16 q0, r12 ; duplicate cospi_28_64*2
|
||||
mov r12, r4, lsl #1
|
||||
vdup.16 q1, r12 ; duplicate cospi_4_64*2
|
||||
|
||||
; dct_const_round_shift(input[1] * cospi_28_64)
|
||||
vqrdmulh.s16 q4, q9, q0
|
||||
|
||||
mov r12, r6, lsl #1
|
||||
rsb r12, #0
|
||||
vdup.16 q0, r12 ; duplicate -cospi_20_64*2
|
||||
|
||||
; dct_const_round_shift(input[1] * cospi_4_64)
|
||||
vqrdmulh.s16 q7, q9, q1
|
||||
|
||||
mov r12, r5, lsl #1
|
||||
vdup.16 q1, r12 ; duplicate cospi_12_64*2
|
||||
|
||||
; dct_const_round_shift(- input[3] * cospi_20_64)
|
||||
vqrdmulh.s16 q5, q11, q0
|
||||
|
||||
mov r12, r7, lsl #1
|
||||
vdup.16 q0, r12 ; duplicate cospi_16_64*2
|
||||
|
||||
; dct_const_round_shift(input[3] * cospi_12_64)
|
||||
vqrdmulh.s16 q6, q11, q1
|
||||
|
||||
; stage 2 & stage 3 - even half
|
||||
mov r12, r8, lsl #1
|
||||
vdup.16 q1, r12 ; duplicate cospi_24_64*2
|
||||
|
||||
; dct_const_round_shift(input_dc * cospi_16_64)
|
||||
vqrdmulh.s16 q9, q8, q0
|
||||
|
||||
mov r12, r9, lsl #1
|
||||
vdup.16 q0, r12 ; duplicate cospi_8_64*2
|
||||
|
||||
; dct_const_round_shift(input[1] * cospi_24_64)
|
||||
vqrdmulh.s16 q13, q10, q1
|
||||
|
||||
; dct_const_round_shift(input[1] * cospi_8_64)
|
||||
vqrdmulh.s16 q15, q10, q0
|
||||
|
||||
; stage 3 -odd half
|
||||
vdup.16 d16, r7 ; duplicate cospi_16_64
|
||||
|
||||
vadd.s16 q0, q9, q15 ; output[0] = step[0] + step[3]
|
||||
vadd.s16 q1, q9, q13 ; output[1] = step[1] + step[2]
|
||||
vsub.s16 q2, q9, q13 ; output[2] = step[1] - step[2]
|
||||
vsub.s16 q3, q9, q15 ; output[3] = step[0] - step[3]
|
||||
|
||||
; stage 2 - odd half
|
||||
vsub.s16 q13, q4, q5 ; step2[5] = step1[4] - step1[5]
|
||||
vadd.s16 q4, q4, q5 ; step2[4] = step1[4] + step1[5]
|
||||
vsub.s16 q14, q7, q6 ; step2[6] = -step1[6] + step1[7]
|
||||
vadd.s16 q7, q7, q6 ; step2[7] = step1[6] + step1[7]
|
||||
|
||||
; step2[6] * cospi_16_64
|
||||
vmull.s16 q9, d28, d16
|
||||
vmull.s16 q10, d29, d16
|
||||
|
||||
; step2[6] * cospi_16_64
|
||||
vmull.s16 q11, d28, d16
|
||||
vmull.s16 q12, d29, d16
|
||||
|
||||
; (step2[6] - step2[5]) * cospi_16_64
|
||||
vmlsl.s16 q9, d26, d16
|
||||
vmlsl.s16 q10, d27, d16
|
||||
|
||||
; (step2[5] + step2[6]) * cospi_16_64
|
||||
vmlal.s16 q11, d26, d16
|
||||
vmlal.s16 q12, d27, d16
|
||||
|
||||
; dct_const_round_shift(input_dc * cospi_16_64)
|
||||
vqrshrn.s32 d10, q9, #14 ; >> 14
|
||||
vqrshrn.s32 d11, q10, #14 ; >> 14
|
||||
|
||||
; dct_const_round_shift(input_dc * cospi_16_64)
|
||||
vqrshrn.s32 d12, q11, #14 ; >> 14
|
||||
vqrshrn.s32 d13, q12, #14 ; >> 14
|
||||
|
||||
; stage 4
|
||||
vadd.s16 q8, q0, q7 ; output[0] = step1[0] + step1[7];
|
||||
vadd.s16 q9, q1, q6 ; output[1] = step1[1] + step1[6];
|
||||
vadd.s16 q10, q2, q5 ; output[2] = step1[2] + step1[5];
|
||||
vadd.s16 q11, q3, q4 ; output[3] = step1[3] + step1[4];
|
||||
vsub.s16 q12, q3, q4 ; output[4] = step1[3] - step1[4];
|
||||
vsub.s16 q13, q2, q5 ; output[5] = step1[2] - step1[5];
|
||||
vsub.s16 q14, q1, q6 ; output[6] = step1[1] - step1[6];
|
||||
vsub.s16 q15, q0, q7 ; output[7] = step1[0] - step1[7];
|
||||
|
||||
; Transpose the matrix
|
||||
TRANSPOSE8X8
|
||||
|
||||
; Then transform columns
|
||||
IDCT8x8_1D
|
||||
|
||||
; ROUND_POWER_OF_TWO(temp_out[j], 5)
|
||||
vrshr.s16 q8, q8, #5
|
||||
vrshr.s16 q9, q9, #5
|
||||
vrshr.s16 q10, q10, #5
|
||||
vrshr.s16 q11, q11, #5
|
||||
vrshr.s16 q12, q12, #5
|
||||
vrshr.s16 q13, q13, #5
|
||||
vrshr.s16 q14, q14, #5
|
||||
vrshr.s16 q15, q15, #5
|
||||
|
||||
; save dest pointer
|
||||
mov r0, r1
|
||||
|
||||
; load destination data
|
||||
vld1.64 {d0}, [r1], r2
|
||||
vld1.64 {d1}, [r1], r2
|
||||
vld1.64 {d2}, [r1], r2
|
||||
vld1.64 {d3}, [r1], r2
|
||||
vld1.64 {d4}, [r1], r2
|
||||
vld1.64 {d5}, [r1], r2
|
||||
vld1.64 {d6}, [r1], r2
|
||||
vld1.64 {d7}, [r1]
|
||||
|
||||
; ROUND_POWER_OF_TWO(temp_out[j], 5) + dest[j * dest_stride + i]
|
||||
vaddw.u8 q8, q8, d0
|
||||
vaddw.u8 q9, q9, d1
|
||||
vaddw.u8 q10, q10, d2
|
||||
vaddw.u8 q11, q11, d3
|
||||
vaddw.u8 q12, q12, d4
|
||||
vaddw.u8 q13, q13, d5
|
||||
vaddw.u8 q14, q14, d6
|
||||
vaddw.u8 q15, q15, d7
|
||||
|
||||
; clip_pixel
|
||||
vqmovun.s16 d0, q8
|
||||
vqmovun.s16 d1, q9
|
||||
vqmovun.s16 d2, q10
|
||||
vqmovun.s16 d3, q11
|
||||
vqmovun.s16 d4, q12
|
||||
vqmovun.s16 d5, q13
|
||||
vqmovun.s16 d6, q14
|
||||
vqmovun.s16 d7, q15
|
||||
|
||||
; store the data
|
||||
vst1.64 {d0}, [r0], r2
|
||||
vst1.64 {d1}, [r0], r2
|
||||
vst1.64 {d2}, [r0], r2
|
||||
vst1.64 {d3}, [r0], r2
|
||||
vst1.64 {d4}, [r0], r2
|
||||
vst1.64 {d5}, [r0], r2
|
||||
vst1.64 {d6}, [r0], r2
|
||||
vst1.64 {d7}, [r0], r2
|
||||
|
||||
vpop {d8-d15}
|
||||
pop {r4-r9}
|
||||
bx lr
|
||||
ENDP ; |aom_idct8x8_12_add_neon|
|
||||
|
||||
END
|
||||
509
third_party/aom/aom_dsp/arm/idct8x8_add_neon.c
vendored
Normal file
509
third_party/aom/aom_dsp/arm/idct8x8_add_neon.c
vendored
Normal file
|
|
@ -0,0 +1,509 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <arm_neon.h>
|
||||
|
||||
#include "./aom_config.h"
|
||||
#include "aom_dsp/txfm_common.h"
|
||||
|
||||
static INLINE void TRANSPOSE8X8(int16x8_t *q8s16, int16x8_t *q9s16,
|
||||
int16x8_t *q10s16, int16x8_t *q11s16,
|
||||
int16x8_t *q12s16, int16x8_t *q13s16,
|
||||
int16x8_t *q14s16, int16x8_t *q15s16) {
|
||||
int16x4_t d16s16, d17s16, d18s16, d19s16, d20s16, d21s16, d22s16, d23s16;
|
||||
int16x4_t d24s16, d25s16, d26s16, d27s16, d28s16, d29s16, d30s16, d31s16;
|
||||
int32x4x2_t q0x2s32, q1x2s32, q2x2s32, q3x2s32;
|
||||
int16x8x2_t q0x2s16, q1x2s16, q2x2s16, q3x2s16;
|
||||
|
||||
d16s16 = vget_low_s16(*q8s16);
|
||||
d17s16 = vget_high_s16(*q8s16);
|
||||
d18s16 = vget_low_s16(*q9s16);
|
||||
d19s16 = vget_high_s16(*q9s16);
|
||||
d20s16 = vget_low_s16(*q10s16);
|
||||
d21s16 = vget_high_s16(*q10s16);
|
||||
d22s16 = vget_low_s16(*q11s16);
|
||||
d23s16 = vget_high_s16(*q11s16);
|
||||
d24s16 = vget_low_s16(*q12s16);
|
||||
d25s16 = vget_high_s16(*q12s16);
|
||||
d26s16 = vget_low_s16(*q13s16);
|
||||
d27s16 = vget_high_s16(*q13s16);
|
||||
d28s16 = vget_low_s16(*q14s16);
|
||||
d29s16 = vget_high_s16(*q14s16);
|
||||
d30s16 = vget_low_s16(*q15s16);
|
||||
d31s16 = vget_high_s16(*q15s16);
|
||||
|
||||
*q8s16 = vcombine_s16(d16s16, d24s16); // vswp d17, d24
|
||||
*q9s16 = vcombine_s16(d18s16, d26s16); // vswp d19, d26
|
||||
*q10s16 = vcombine_s16(d20s16, d28s16); // vswp d21, d28
|
||||
*q11s16 = vcombine_s16(d22s16, d30s16); // vswp d23, d30
|
||||
*q12s16 = vcombine_s16(d17s16, d25s16);
|
||||
*q13s16 = vcombine_s16(d19s16, d27s16);
|
||||
*q14s16 = vcombine_s16(d21s16, d29s16);
|
||||
*q15s16 = vcombine_s16(d23s16, d31s16);
|
||||
|
||||
q0x2s32 =
|
||||
vtrnq_s32(vreinterpretq_s32_s16(*q8s16), vreinterpretq_s32_s16(*q10s16));
|
||||
q1x2s32 =
|
||||
vtrnq_s32(vreinterpretq_s32_s16(*q9s16), vreinterpretq_s32_s16(*q11s16));
|
||||
q2x2s32 =
|
||||
vtrnq_s32(vreinterpretq_s32_s16(*q12s16), vreinterpretq_s32_s16(*q14s16));
|
||||
q3x2s32 =
|
||||
vtrnq_s32(vreinterpretq_s32_s16(*q13s16), vreinterpretq_s32_s16(*q15s16));
|
||||
|
||||
q0x2s16 = vtrnq_s16(vreinterpretq_s16_s32(q0x2s32.val[0]), // q8
|
||||
vreinterpretq_s16_s32(q1x2s32.val[0])); // q9
|
||||
q1x2s16 = vtrnq_s16(vreinterpretq_s16_s32(q0x2s32.val[1]), // q10
|
||||
vreinterpretq_s16_s32(q1x2s32.val[1])); // q11
|
||||
q2x2s16 = vtrnq_s16(vreinterpretq_s16_s32(q2x2s32.val[0]), // q12
|
||||
vreinterpretq_s16_s32(q3x2s32.val[0])); // q13
|
||||
q3x2s16 = vtrnq_s16(vreinterpretq_s16_s32(q2x2s32.val[1]), // q14
|
||||
vreinterpretq_s16_s32(q3x2s32.val[1])); // q15
|
||||
|
||||
*q8s16 = q0x2s16.val[0];
|
||||
*q9s16 = q0x2s16.val[1];
|
||||
*q10s16 = q1x2s16.val[0];
|
||||
*q11s16 = q1x2s16.val[1];
|
||||
*q12s16 = q2x2s16.val[0];
|
||||
*q13s16 = q2x2s16.val[1];
|
||||
*q14s16 = q3x2s16.val[0];
|
||||
*q15s16 = q3x2s16.val[1];
|
||||
return;
|
||||
}
|
||||
|
||||
static INLINE void IDCT8x8_1D(int16x8_t *q8s16, int16x8_t *q9s16,
|
||||
int16x8_t *q10s16, int16x8_t *q11s16,
|
||||
int16x8_t *q12s16, int16x8_t *q13s16,
|
||||
int16x8_t *q14s16, int16x8_t *q15s16) {
|
||||
int16x4_t d0s16, d1s16, d2s16, d3s16;
|
||||
int16x4_t d8s16, d9s16, d10s16, d11s16, d12s16, d13s16, d14s16, d15s16;
|
||||
int16x4_t d16s16, d17s16, d18s16, d19s16, d20s16, d21s16, d22s16, d23s16;
|
||||
int16x4_t d24s16, d25s16, d26s16, d27s16, d28s16, d29s16, d30s16, d31s16;
|
||||
int16x8_t q0s16, q1s16, q2s16, q3s16, q4s16, q5s16, q6s16, q7s16;
|
||||
int32x4_t q2s32, q3s32, q5s32, q6s32, q8s32, q9s32;
|
||||
int32x4_t q10s32, q11s32, q12s32, q13s32, q15s32;
|
||||
|
||||
d0s16 = vdup_n_s16((int16_t)cospi_28_64);
|
||||
d1s16 = vdup_n_s16((int16_t)cospi_4_64);
|
||||
d2s16 = vdup_n_s16((int16_t)cospi_12_64);
|
||||
d3s16 = vdup_n_s16((int16_t)cospi_20_64);
|
||||
|
||||
d16s16 = vget_low_s16(*q8s16);
|
||||
d17s16 = vget_high_s16(*q8s16);
|
||||
d18s16 = vget_low_s16(*q9s16);
|
||||
d19s16 = vget_high_s16(*q9s16);
|
||||
d20s16 = vget_low_s16(*q10s16);
|
||||
d21s16 = vget_high_s16(*q10s16);
|
||||
d22s16 = vget_low_s16(*q11s16);
|
||||
d23s16 = vget_high_s16(*q11s16);
|
||||
d24s16 = vget_low_s16(*q12s16);
|
||||
d25s16 = vget_high_s16(*q12s16);
|
||||
d26s16 = vget_low_s16(*q13s16);
|
||||
d27s16 = vget_high_s16(*q13s16);
|
||||
d28s16 = vget_low_s16(*q14s16);
|
||||
d29s16 = vget_high_s16(*q14s16);
|
||||
d30s16 = vget_low_s16(*q15s16);
|
||||
d31s16 = vget_high_s16(*q15s16);
|
||||
|
||||
q2s32 = vmull_s16(d18s16, d0s16);
|
||||
q3s32 = vmull_s16(d19s16, d0s16);
|
||||
q5s32 = vmull_s16(d26s16, d2s16);
|
||||
q6s32 = vmull_s16(d27s16, d2s16);
|
||||
|
||||
q2s32 = vmlsl_s16(q2s32, d30s16, d1s16);
|
||||
q3s32 = vmlsl_s16(q3s32, d31s16, d1s16);
|
||||
q5s32 = vmlsl_s16(q5s32, d22s16, d3s16);
|
||||
q6s32 = vmlsl_s16(q6s32, d23s16, d3s16);
|
||||
|
||||
d8s16 = vqrshrn_n_s32(q2s32, 14);
|
||||
d9s16 = vqrshrn_n_s32(q3s32, 14);
|
||||
d10s16 = vqrshrn_n_s32(q5s32, 14);
|
||||
d11s16 = vqrshrn_n_s32(q6s32, 14);
|
||||
q4s16 = vcombine_s16(d8s16, d9s16);
|
||||
q5s16 = vcombine_s16(d10s16, d11s16);
|
||||
|
||||
q2s32 = vmull_s16(d18s16, d1s16);
|
||||
q3s32 = vmull_s16(d19s16, d1s16);
|
||||
q9s32 = vmull_s16(d26s16, d3s16);
|
||||
q13s32 = vmull_s16(d27s16, d3s16);
|
||||
|
||||
q2s32 = vmlal_s16(q2s32, d30s16, d0s16);
|
||||
q3s32 = vmlal_s16(q3s32, d31s16, d0s16);
|
||||
q9s32 = vmlal_s16(q9s32, d22s16, d2s16);
|
||||
q13s32 = vmlal_s16(q13s32, d23s16, d2s16);
|
||||
|
||||
d14s16 = vqrshrn_n_s32(q2s32, 14);
|
||||
d15s16 = vqrshrn_n_s32(q3s32, 14);
|
||||
d12s16 = vqrshrn_n_s32(q9s32, 14);
|
||||
d13s16 = vqrshrn_n_s32(q13s32, 14);
|
||||
q6s16 = vcombine_s16(d12s16, d13s16);
|
||||
q7s16 = vcombine_s16(d14s16, d15s16);
|
||||
|
||||
d0s16 = vdup_n_s16((int16_t)cospi_16_64);
|
||||
|
||||
q2s32 = vmull_s16(d16s16, d0s16);
|
||||
q3s32 = vmull_s16(d17s16, d0s16);
|
||||
q13s32 = vmull_s16(d16s16, d0s16);
|
||||
q15s32 = vmull_s16(d17s16, d0s16);
|
||||
|
||||
q2s32 = vmlal_s16(q2s32, d24s16, d0s16);
|
||||
q3s32 = vmlal_s16(q3s32, d25s16, d0s16);
|
||||
q13s32 = vmlsl_s16(q13s32, d24s16, d0s16);
|
||||
q15s32 = vmlsl_s16(q15s32, d25s16, d0s16);
|
||||
|
||||
d0s16 = vdup_n_s16((int16_t)cospi_24_64);
|
||||
d1s16 = vdup_n_s16((int16_t)cospi_8_64);
|
||||
|
||||
d18s16 = vqrshrn_n_s32(q2s32, 14);
|
||||
d19s16 = vqrshrn_n_s32(q3s32, 14);
|
||||
d22s16 = vqrshrn_n_s32(q13s32, 14);
|
||||
d23s16 = vqrshrn_n_s32(q15s32, 14);
|
||||
*q9s16 = vcombine_s16(d18s16, d19s16);
|
||||
*q11s16 = vcombine_s16(d22s16, d23s16);
|
||||
|
||||
q2s32 = vmull_s16(d20s16, d0s16);
|
||||
q3s32 = vmull_s16(d21s16, d0s16);
|
||||
q8s32 = vmull_s16(d20s16, d1s16);
|
||||
q12s32 = vmull_s16(d21s16, d1s16);
|
||||
|
||||
q2s32 = vmlsl_s16(q2s32, d28s16, d1s16);
|
||||
q3s32 = vmlsl_s16(q3s32, d29s16, d1s16);
|
||||
q8s32 = vmlal_s16(q8s32, d28s16, d0s16);
|
||||
q12s32 = vmlal_s16(q12s32, d29s16, d0s16);
|
||||
|
||||
d26s16 = vqrshrn_n_s32(q2s32, 14);
|
||||
d27s16 = vqrshrn_n_s32(q3s32, 14);
|
||||
d30s16 = vqrshrn_n_s32(q8s32, 14);
|
||||
d31s16 = vqrshrn_n_s32(q12s32, 14);
|
||||
*q13s16 = vcombine_s16(d26s16, d27s16);
|
||||
*q15s16 = vcombine_s16(d30s16, d31s16);
|
||||
|
||||
q0s16 = vaddq_s16(*q9s16, *q15s16);
|
||||
q1s16 = vaddq_s16(*q11s16, *q13s16);
|
||||
q2s16 = vsubq_s16(*q11s16, *q13s16);
|
||||
q3s16 = vsubq_s16(*q9s16, *q15s16);
|
||||
|
||||
*q13s16 = vsubq_s16(q4s16, q5s16);
|
||||
q4s16 = vaddq_s16(q4s16, q5s16);
|
||||
*q14s16 = vsubq_s16(q7s16, q6s16);
|
||||
q7s16 = vaddq_s16(q7s16, q6s16);
|
||||
d26s16 = vget_low_s16(*q13s16);
|
||||
d27s16 = vget_high_s16(*q13s16);
|
||||
d28s16 = vget_low_s16(*q14s16);
|
||||
d29s16 = vget_high_s16(*q14s16);
|
||||
|
||||
d16s16 = vdup_n_s16((int16_t)cospi_16_64);
|
||||
|
||||
q9s32 = vmull_s16(d28s16, d16s16);
|
||||
q10s32 = vmull_s16(d29s16, d16s16);
|
||||
q11s32 = vmull_s16(d28s16, d16s16);
|
||||
q12s32 = vmull_s16(d29s16, d16s16);
|
||||
|
||||
q9s32 = vmlsl_s16(q9s32, d26s16, d16s16);
|
||||
q10s32 = vmlsl_s16(q10s32, d27s16, d16s16);
|
||||
q11s32 = vmlal_s16(q11s32, d26s16, d16s16);
|
||||
q12s32 = vmlal_s16(q12s32, d27s16, d16s16);
|
||||
|
||||
d10s16 = vqrshrn_n_s32(q9s32, 14);
|
||||
d11s16 = vqrshrn_n_s32(q10s32, 14);
|
||||
d12s16 = vqrshrn_n_s32(q11s32, 14);
|
||||
d13s16 = vqrshrn_n_s32(q12s32, 14);
|
||||
q5s16 = vcombine_s16(d10s16, d11s16);
|
||||
q6s16 = vcombine_s16(d12s16, d13s16);
|
||||
|
||||
*q8s16 = vaddq_s16(q0s16, q7s16);
|
||||
*q9s16 = vaddq_s16(q1s16, q6s16);
|
||||
*q10s16 = vaddq_s16(q2s16, q5s16);
|
||||
*q11s16 = vaddq_s16(q3s16, q4s16);
|
||||
*q12s16 = vsubq_s16(q3s16, q4s16);
|
||||
*q13s16 = vsubq_s16(q2s16, q5s16);
|
||||
*q14s16 = vsubq_s16(q1s16, q6s16);
|
||||
*q15s16 = vsubq_s16(q0s16, q7s16);
|
||||
return;
|
||||
}
|
||||
|
||||
void aom_idct8x8_64_add_neon(int16_t *input, uint8_t *dest, int dest_stride) {
|
||||
uint8_t *d1, *d2;
|
||||
uint8x8_t d0u8, d1u8, d2u8, d3u8;
|
||||
uint64x1_t d0u64, d1u64, d2u64, d3u64;
|
||||
int16x8_t q8s16, q9s16, q10s16, q11s16, q12s16, q13s16, q14s16, q15s16;
|
||||
uint16x8_t q8u16, q9u16, q10u16, q11u16;
|
||||
|
||||
q8s16 = vld1q_s16(input);
|
||||
q9s16 = vld1q_s16(input + 8);
|
||||
q10s16 = vld1q_s16(input + 16);
|
||||
q11s16 = vld1q_s16(input + 24);
|
||||
q12s16 = vld1q_s16(input + 32);
|
||||
q13s16 = vld1q_s16(input + 40);
|
||||
q14s16 = vld1q_s16(input + 48);
|
||||
q15s16 = vld1q_s16(input + 56);
|
||||
|
||||
TRANSPOSE8X8(&q8s16, &q9s16, &q10s16, &q11s16, &q12s16, &q13s16, &q14s16,
|
||||
&q15s16);
|
||||
|
||||
IDCT8x8_1D(&q8s16, &q9s16, &q10s16, &q11s16, &q12s16, &q13s16, &q14s16,
|
||||
&q15s16);
|
||||
|
||||
TRANSPOSE8X8(&q8s16, &q9s16, &q10s16, &q11s16, &q12s16, &q13s16, &q14s16,
|
||||
&q15s16);
|
||||
|
||||
IDCT8x8_1D(&q8s16, &q9s16, &q10s16, &q11s16, &q12s16, &q13s16, &q14s16,
|
||||
&q15s16);
|
||||
|
||||
q8s16 = vrshrq_n_s16(q8s16, 5);
|
||||
q9s16 = vrshrq_n_s16(q9s16, 5);
|
||||
q10s16 = vrshrq_n_s16(q10s16, 5);
|
||||
q11s16 = vrshrq_n_s16(q11s16, 5);
|
||||
q12s16 = vrshrq_n_s16(q12s16, 5);
|
||||
q13s16 = vrshrq_n_s16(q13s16, 5);
|
||||
q14s16 = vrshrq_n_s16(q14s16, 5);
|
||||
q15s16 = vrshrq_n_s16(q15s16, 5);
|
||||
|
||||
d1 = d2 = dest;
|
||||
|
||||
d0u64 = vld1_u64((uint64_t *)d1);
|
||||
d1 += dest_stride;
|
||||
d1u64 = vld1_u64((uint64_t *)d1);
|
||||
d1 += dest_stride;
|
||||
d2u64 = vld1_u64((uint64_t *)d1);
|
||||
d1 += dest_stride;
|
||||
d3u64 = vld1_u64((uint64_t *)d1);
|
||||
d1 += dest_stride;
|
||||
|
||||
q8u16 = vaddw_u8(vreinterpretq_u16_s16(q8s16), vreinterpret_u8_u64(d0u64));
|
||||
q9u16 = vaddw_u8(vreinterpretq_u16_s16(q9s16), vreinterpret_u8_u64(d1u64));
|
||||
q10u16 = vaddw_u8(vreinterpretq_u16_s16(q10s16), vreinterpret_u8_u64(d2u64));
|
||||
q11u16 = vaddw_u8(vreinterpretq_u16_s16(q11s16), vreinterpret_u8_u64(d3u64));
|
||||
|
||||
d0u8 = vqmovun_s16(vreinterpretq_s16_u16(q8u16));
|
||||
d1u8 = vqmovun_s16(vreinterpretq_s16_u16(q9u16));
|
||||
d2u8 = vqmovun_s16(vreinterpretq_s16_u16(q10u16));
|
||||
d3u8 = vqmovun_s16(vreinterpretq_s16_u16(q11u16));
|
||||
|
||||
vst1_u64((uint64_t *)d2, vreinterpret_u64_u8(d0u8));
|
||||
d2 += dest_stride;
|
||||
vst1_u64((uint64_t *)d2, vreinterpret_u64_u8(d1u8));
|
||||
d2 += dest_stride;
|
||||
vst1_u64((uint64_t *)d2, vreinterpret_u64_u8(d2u8));
|
||||
d2 += dest_stride;
|
||||
vst1_u64((uint64_t *)d2, vreinterpret_u64_u8(d3u8));
|
||||
d2 += dest_stride;
|
||||
|
||||
q8s16 = q12s16;
|
||||
q9s16 = q13s16;
|
||||
q10s16 = q14s16;
|
||||
q11s16 = q15s16;
|
||||
|
||||
d0u64 = vld1_u64((uint64_t *)d1);
|
||||
d1 += dest_stride;
|
||||
d1u64 = vld1_u64((uint64_t *)d1);
|
||||
d1 += dest_stride;
|
||||
d2u64 = vld1_u64((uint64_t *)d1);
|
||||
d1 += dest_stride;
|
||||
d3u64 = vld1_u64((uint64_t *)d1);
|
||||
d1 += dest_stride;
|
||||
|
||||
q8u16 = vaddw_u8(vreinterpretq_u16_s16(q8s16), vreinterpret_u8_u64(d0u64));
|
||||
q9u16 = vaddw_u8(vreinterpretq_u16_s16(q9s16), vreinterpret_u8_u64(d1u64));
|
||||
q10u16 = vaddw_u8(vreinterpretq_u16_s16(q10s16), vreinterpret_u8_u64(d2u64));
|
||||
q11u16 = vaddw_u8(vreinterpretq_u16_s16(q11s16), vreinterpret_u8_u64(d3u64));
|
||||
|
||||
d0u8 = vqmovun_s16(vreinterpretq_s16_u16(q8u16));
|
||||
d1u8 = vqmovun_s16(vreinterpretq_s16_u16(q9u16));
|
||||
d2u8 = vqmovun_s16(vreinterpretq_s16_u16(q10u16));
|
||||
d3u8 = vqmovun_s16(vreinterpretq_s16_u16(q11u16));
|
||||
|
||||
vst1_u64((uint64_t *)d2, vreinterpret_u64_u8(d0u8));
|
||||
d2 += dest_stride;
|
||||
vst1_u64((uint64_t *)d2, vreinterpret_u64_u8(d1u8));
|
||||
d2 += dest_stride;
|
||||
vst1_u64((uint64_t *)d2, vreinterpret_u64_u8(d2u8));
|
||||
d2 += dest_stride;
|
||||
vst1_u64((uint64_t *)d2, vreinterpret_u64_u8(d3u8));
|
||||
d2 += dest_stride;
|
||||
return;
|
||||
}
|
||||
|
||||
void aom_idct8x8_12_add_neon(int16_t *input, uint8_t *dest, int dest_stride) {
|
||||
uint8_t *d1, *d2;
|
||||
uint8x8_t d0u8, d1u8, d2u8, d3u8;
|
||||
int16x4_t d10s16, d11s16, d12s16, d13s16, d16s16;
|
||||
int16x4_t d26s16, d27s16, d28s16, d29s16;
|
||||
uint64x1_t d0u64, d1u64, d2u64, d3u64;
|
||||
int16x8_t q0s16, q1s16, q2s16, q3s16, q4s16, q5s16, q6s16, q7s16;
|
||||
int16x8_t q8s16, q9s16, q10s16, q11s16, q12s16, q13s16, q14s16, q15s16;
|
||||
uint16x8_t q8u16, q9u16, q10u16, q11u16;
|
||||
int32x4_t q9s32, q10s32, q11s32, q12s32;
|
||||
|
||||
q8s16 = vld1q_s16(input);
|
||||
q9s16 = vld1q_s16(input + 8);
|
||||
q10s16 = vld1q_s16(input + 16);
|
||||
q11s16 = vld1q_s16(input + 24);
|
||||
q12s16 = vld1q_s16(input + 32);
|
||||
q13s16 = vld1q_s16(input + 40);
|
||||
q14s16 = vld1q_s16(input + 48);
|
||||
q15s16 = vld1q_s16(input + 56);
|
||||
|
||||
TRANSPOSE8X8(&q8s16, &q9s16, &q10s16, &q11s16, &q12s16, &q13s16, &q14s16,
|
||||
&q15s16);
|
||||
|
||||
// First transform rows
|
||||
// stage 1
|
||||
q0s16 = vdupq_n_s16((int16_t)cospi_28_64 * 2);
|
||||
q1s16 = vdupq_n_s16((int16_t)cospi_4_64 * 2);
|
||||
|
||||
q4s16 = vqrdmulhq_s16(q9s16, q0s16);
|
||||
|
||||
q0s16 = vdupq_n_s16(-(int16_t)cospi_20_64 * 2);
|
||||
|
||||
q7s16 = vqrdmulhq_s16(q9s16, q1s16);
|
||||
|
||||
q1s16 = vdupq_n_s16((int16_t)cospi_12_64 * 2);
|
||||
|
||||
q5s16 = vqrdmulhq_s16(q11s16, q0s16);
|
||||
|
||||
q0s16 = vdupq_n_s16((int16_t)cospi_16_64 * 2);
|
||||
|
||||
q6s16 = vqrdmulhq_s16(q11s16, q1s16);
|
||||
|
||||
// stage 2 & stage 3 - even half
|
||||
q1s16 = vdupq_n_s16((int16_t)cospi_24_64 * 2);
|
||||
|
||||
q9s16 = vqrdmulhq_s16(q8s16, q0s16);
|
||||
|
||||
q0s16 = vdupq_n_s16((int16_t)cospi_8_64 * 2);
|
||||
|
||||
q13s16 = vqrdmulhq_s16(q10s16, q1s16);
|
||||
|
||||
q15s16 = vqrdmulhq_s16(q10s16, q0s16);
|
||||
|
||||
// stage 3 -odd half
|
||||
q0s16 = vaddq_s16(q9s16, q15s16);
|
||||
q1s16 = vaddq_s16(q9s16, q13s16);
|
||||
q2s16 = vsubq_s16(q9s16, q13s16);
|
||||
q3s16 = vsubq_s16(q9s16, q15s16);
|
||||
|
||||
// stage 2 - odd half
|
||||
q13s16 = vsubq_s16(q4s16, q5s16);
|
||||
q4s16 = vaddq_s16(q4s16, q5s16);
|
||||
q14s16 = vsubq_s16(q7s16, q6s16);
|
||||
q7s16 = vaddq_s16(q7s16, q6s16);
|
||||
d26s16 = vget_low_s16(q13s16);
|
||||
d27s16 = vget_high_s16(q13s16);
|
||||
d28s16 = vget_low_s16(q14s16);
|
||||
d29s16 = vget_high_s16(q14s16);
|
||||
|
||||
d16s16 = vdup_n_s16((int16_t)cospi_16_64);
|
||||
q9s32 = vmull_s16(d28s16, d16s16);
|
||||
q10s32 = vmull_s16(d29s16, d16s16);
|
||||
q11s32 = vmull_s16(d28s16, d16s16);
|
||||
q12s32 = vmull_s16(d29s16, d16s16);
|
||||
|
||||
q9s32 = vmlsl_s16(q9s32, d26s16, d16s16);
|
||||
q10s32 = vmlsl_s16(q10s32, d27s16, d16s16);
|
||||
q11s32 = vmlal_s16(q11s32, d26s16, d16s16);
|
||||
q12s32 = vmlal_s16(q12s32, d27s16, d16s16);
|
||||
|
||||
d10s16 = vqrshrn_n_s32(q9s32, 14);
|
||||
d11s16 = vqrshrn_n_s32(q10s32, 14);
|
||||
d12s16 = vqrshrn_n_s32(q11s32, 14);
|
||||
d13s16 = vqrshrn_n_s32(q12s32, 14);
|
||||
q5s16 = vcombine_s16(d10s16, d11s16);
|
||||
q6s16 = vcombine_s16(d12s16, d13s16);
|
||||
|
||||
// stage 4
|
||||
q8s16 = vaddq_s16(q0s16, q7s16);
|
||||
q9s16 = vaddq_s16(q1s16, q6s16);
|
||||
q10s16 = vaddq_s16(q2s16, q5s16);
|
||||
q11s16 = vaddq_s16(q3s16, q4s16);
|
||||
q12s16 = vsubq_s16(q3s16, q4s16);
|
||||
q13s16 = vsubq_s16(q2s16, q5s16);
|
||||
q14s16 = vsubq_s16(q1s16, q6s16);
|
||||
q15s16 = vsubq_s16(q0s16, q7s16);
|
||||
|
||||
TRANSPOSE8X8(&q8s16, &q9s16, &q10s16, &q11s16, &q12s16, &q13s16, &q14s16,
|
||||
&q15s16);
|
||||
|
||||
IDCT8x8_1D(&q8s16, &q9s16, &q10s16, &q11s16, &q12s16, &q13s16, &q14s16,
|
||||
&q15s16);
|
||||
|
||||
q8s16 = vrshrq_n_s16(q8s16, 5);
|
||||
q9s16 = vrshrq_n_s16(q9s16, 5);
|
||||
q10s16 = vrshrq_n_s16(q10s16, 5);
|
||||
q11s16 = vrshrq_n_s16(q11s16, 5);
|
||||
q12s16 = vrshrq_n_s16(q12s16, 5);
|
||||
q13s16 = vrshrq_n_s16(q13s16, 5);
|
||||
q14s16 = vrshrq_n_s16(q14s16, 5);
|
||||
q15s16 = vrshrq_n_s16(q15s16, 5);
|
||||
|
||||
d1 = d2 = dest;
|
||||
|
||||
d0u64 = vld1_u64((uint64_t *)d1);
|
||||
d1 += dest_stride;
|
||||
d1u64 = vld1_u64((uint64_t *)d1);
|
||||
d1 += dest_stride;
|
||||
d2u64 = vld1_u64((uint64_t *)d1);
|
||||
d1 += dest_stride;
|
||||
d3u64 = vld1_u64((uint64_t *)d1);
|
||||
d1 += dest_stride;
|
||||
|
||||
q8u16 = vaddw_u8(vreinterpretq_u16_s16(q8s16), vreinterpret_u8_u64(d0u64));
|
||||
q9u16 = vaddw_u8(vreinterpretq_u16_s16(q9s16), vreinterpret_u8_u64(d1u64));
|
||||
q10u16 = vaddw_u8(vreinterpretq_u16_s16(q10s16), vreinterpret_u8_u64(d2u64));
|
||||
q11u16 = vaddw_u8(vreinterpretq_u16_s16(q11s16), vreinterpret_u8_u64(d3u64));
|
||||
|
||||
d0u8 = vqmovun_s16(vreinterpretq_s16_u16(q8u16));
|
||||
d1u8 = vqmovun_s16(vreinterpretq_s16_u16(q9u16));
|
||||
d2u8 = vqmovun_s16(vreinterpretq_s16_u16(q10u16));
|
||||
d3u8 = vqmovun_s16(vreinterpretq_s16_u16(q11u16));
|
||||
|
||||
vst1_u64((uint64_t *)d2, vreinterpret_u64_u8(d0u8));
|
||||
d2 += dest_stride;
|
||||
vst1_u64((uint64_t *)d2, vreinterpret_u64_u8(d1u8));
|
||||
d2 += dest_stride;
|
||||
vst1_u64((uint64_t *)d2, vreinterpret_u64_u8(d2u8));
|
||||
d2 += dest_stride;
|
||||
vst1_u64((uint64_t *)d2, vreinterpret_u64_u8(d3u8));
|
||||
d2 += dest_stride;
|
||||
|
||||
q8s16 = q12s16;
|
||||
q9s16 = q13s16;
|
||||
q10s16 = q14s16;
|
||||
q11s16 = q15s16;
|
||||
|
||||
d0u64 = vld1_u64((uint64_t *)d1);
|
||||
d1 += dest_stride;
|
||||
d1u64 = vld1_u64((uint64_t *)d1);
|
||||
d1 += dest_stride;
|
||||
d2u64 = vld1_u64((uint64_t *)d1);
|
||||
d1 += dest_stride;
|
||||
d3u64 = vld1_u64((uint64_t *)d1);
|
||||
d1 += dest_stride;
|
||||
|
||||
q8u16 = vaddw_u8(vreinterpretq_u16_s16(q8s16), vreinterpret_u8_u64(d0u64));
|
||||
q9u16 = vaddw_u8(vreinterpretq_u16_s16(q9s16), vreinterpret_u8_u64(d1u64));
|
||||
q10u16 = vaddw_u8(vreinterpretq_u16_s16(q10s16), vreinterpret_u8_u64(d2u64));
|
||||
q11u16 = vaddw_u8(vreinterpretq_u16_s16(q11s16), vreinterpret_u8_u64(d3u64));
|
||||
|
||||
d0u8 = vqmovun_s16(vreinterpretq_s16_u16(q8u16));
|
||||
d1u8 = vqmovun_s16(vreinterpretq_s16_u16(q9u16));
|
||||
d2u8 = vqmovun_s16(vreinterpretq_s16_u16(q10u16));
|
||||
d3u8 = vqmovun_s16(vreinterpretq_s16_u16(q11u16));
|
||||
|
||||
vst1_u64((uint64_t *)d2, vreinterpret_u64_u8(d0u8));
|
||||
d2 += dest_stride;
|
||||
vst1_u64((uint64_t *)d2, vreinterpret_u64_u8(d1u8));
|
||||
d2 += dest_stride;
|
||||
vst1_u64((uint64_t *)d2, vreinterpret_u64_u8(d2u8));
|
||||
d2 += dest_stride;
|
||||
vst1_u64((uint64_t *)d2, vreinterpret_u64_u8(d3u8));
|
||||
d2 += dest_stride;
|
||||
return;
|
||||
}
|
||||
757
third_party/aom/aom_dsp/arm/intrapred_neon.c
vendored
Normal file
757
third_party/aom/aom_dsp/arm/intrapred_neon.c
vendored
Normal file
|
|
@ -0,0 +1,757 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <arm_neon.h>
|
||||
|
||||
#include "./aom_config.h"
|
||||
#include "./aom_dsp_rtcd.h"
|
||||
#include "aom/aom_integer.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// DC 4x4
|
||||
|
||||
// 'do_above' and 'do_left' facilitate branch removal when inlined.
|
||||
static INLINE void dc_4x4(uint8_t *dst, ptrdiff_t stride, const uint8_t *above,
|
||||
const uint8_t *left, int do_above, int do_left) {
|
||||
uint16x8_t sum_top;
|
||||
uint16x8_t sum_left;
|
||||
uint8x8_t dc0;
|
||||
|
||||
if (do_above) {
|
||||
const uint8x8_t A = vld1_u8(above); // top row
|
||||
const uint16x4_t p0 = vpaddl_u8(A); // cascading summation of the top
|
||||
const uint16x4_t p1 = vpadd_u16(p0, p0);
|
||||
sum_top = vcombine_u16(p1, p1);
|
||||
}
|
||||
|
||||
if (do_left) {
|
||||
const uint8x8_t L = vld1_u8(left); // left border
|
||||
const uint16x4_t p0 = vpaddl_u8(L); // cascading summation of the left
|
||||
const uint16x4_t p1 = vpadd_u16(p0, p0);
|
||||
sum_left = vcombine_u16(p1, p1);
|
||||
}
|
||||
|
||||
if (do_above && do_left) {
|
||||
const uint16x8_t sum = vaddq_u16(sum_left, sum_top);
|
||||
dc0 = vrshrn_n_u16(sum, 3);
|
||||
} else if (do_above) {
|
||||
dc0 = vrshrn_n_u16(sum_top, 2);
|
||||
} else if (do_left) {
|
||||
dc0 = vrshrn_n_u16(sum_left, 2);
|
||||
} else {
|
||||
dc0 = vdup_n_u8(0x80);
|
||||
}
|
||||
|
||||
{
|
||||
const uint8x8_t dc = vdup_lane_u8(dc0, 0);
|
||||
int i;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
vst1_lane_u32((uint32_t *)(dst + i * stride), vreinterpret_u32_u8(dc), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void aom_dc_predictor_4x4_neon(uint8_t *dst, ptrdiff_t stride,
|
||||
const uint8_t *above, const uint8_t *left) {
|
||||
dc_4x4(dst, stride, above, left, 1, 1);
|
||||
}
|
||||
|
||||
void aom_dc_left_predictor_4x4_neon(uint8_t *dst, ptrdiff_t stride,
|
||||
const uint8_t *above, const uint8_t *left) {
|
||||
(void)above;
|
||||
dc_4x4(dst, stride, NULL, left, 0, 1);
|
||||
}
|
||||
|
||||
void aom_dc_top_predictor_4x4_neon(uint8_t *dst, ptrdiff_t stride,
|
||||
const uint8_t *above, const uint8_t *left) {
|
||||
(void)left;
|
||||
dc_4x4(dst, stride, above, NULL, 1, 0);
|
||||
}
|
||||
|
||||
void aom_dc_128_predictor_4x4_neon(uint8_t *dst, ptrdiff_t stride,
|
||||
const uint8_t *above, const uint8_t *left) {
|
||||
(void)above;
|
||||
(void)left;
|
||||
dc_4x4(dst, stride, NULL, NULL, 0, 0);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// DC 8x8
|
||||
|
||||
// 'do_above' and 'do_left' facilitate branch removal when inlined.
|
||||
static INLINE void dc_8x8(uint8_t *dst, ptrdiff_t stride, const uint8_t *above,
|
||||
const uint8_t *left, int do_above, int do_left) {
|
||||
uint16x8_t sum_top;
|
||||
uint16x8_t sum_left;
|
||||
uint8x8_t dc0;
|
||||
|
||||
if (do_above) {
|
||||
const uint8x8_t A = vld1_u8(above); // top row
|
||||
const uint16x4_t p0 = vpaddl_u8(A); // cascading summation of the top
|
||||
const uint16x4_t p1 = vpadd_u16(p0, p0);
|
||||
const uint16x4_t p2 = vpadd_u16(p1, p1);
|
||||
sum_top = vcombine_u16(p2, p2);
|
||||
}
|
||||
|
||||
if (do_left) {
|
||||
const uint8x8_t L = vld1_u8(left); // left border
|
||||
const uint16x4_t p0 = vpaddl_u8(L); // cascading summation of the left
|
||||
const uint16x4_t p1 = vpadd_u16(p0, p0);
|
||||
const uint16x4_t p2 = vpadd_u16(p1, p1);
|
||||
sum_left = vcombine_u16(p2, p2);
|
||||
}
|
||||
|
||||
if (do_above && do_left) {
|
||||
const uint16x8_t sum = vaddq_u16(sum_left, sum_top);
|
||||
dc0 = vrshrn_n_u16(sum, 4);
|
||||
} else if (do_above) {
|
||||
dc0 = vrshrn_n_u16(sum_top, 3);
|
||||
} else if (do_left) {
|
||||
dc0 = vrshrn_n_u16(sum_left, 3);
|
||||
} else {
|
||||
dc0 = vdup_n_u8(0x80);
|
||||
}
|
||||
|
||||
{
|
||||
const uint8x8_t dc = vdup_lane_u8(dc0, 0);
|
||||
int i;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
vst1_u32((uint32_t *)(dst + i * stride), vreinterpret_u32_u8(dc));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void aom_dc_predictor_8x8_neon(uint8_t *dst, ptrdiff_t stride,
|
||||
const uint8_t *above, const uint8_t *left) {
|
||||
dc_8x8(dst, stride, above, left, 1, 1);
|
||||
}
|
||||
|
||||
void aom_dc_left_predictor_8x8_neon(uint8_t *dst, ptrdiff_t stride,
|
||||
const uint8_t *above, const uint8_t *left) {
|
||||
(void)above;
|
||||
dc_8x8(dst, stride, NULL, left, 0, 1);
|
||||
}
|
||||
|
||||
void aom_dc_top_predictor_8x8_neon(uint8_t *dst, ptrdiff_t stride,
|
||||
const uint8_t *above, const uint8_t *left) {
|
||||
(void)left;
|
||||
dc_8x8(dst, stride, above, NULL, 1, 0);
|
||||
}
|
||||
|
||||
void aom_dc_128_predictor_8x8_neon(uint8_t *dst, ptrdiff_t stride,
|
||||
const uint8_t *above, const uint8_t *left) {
|
||||
(void)above;
|
||||
(void)left;
|
||||
dc_8x8(dst, stride, NULL, NULL, 0, 0);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// DC 16x16
|
||||
|
||||
// 'do_above' and 'do_left' facilitate branch removal when inlined.
|
||||
static INLINE void dc_16x16(uint8_t *dst, ptrdiff_t stride,
|
||||
const uint8_t *above, const uint8_t *left,
|
||||
int do_above, int do_left) {
|
||||
uint16x8_t sum_top;
|
||||
uint16x8_t sum_left;
|
||||
uint8x8_t dc0;
|
||||
|
||||
if (do_above) {
|
||||
const uint8x16_t A = vld1q_u8(above); // top row
|
||||
const uint16x8_t p0 = vpaddlq_u8(A); // cascading summation of the top
|
||||
const uint16x4_t p1 = vadd_u16(vget_low_u16(p0), vget_high_u16(p0));
|
||||
const uint16x4_t p2 = vpadd_u16(p1, p1);
|
||||
const uint16x4_t p3 = vpadd_u16(p2, p2);
|
||||
sum_top = vcombine_u16(p3, p3);
|
||||
}
|
||||
|
||||
if (do_left) {
|
||||
const uint8x16_t L = vld1q_u8(left); // left row
|
||||
const uint16x8_t p0 = vpaddlq_u8(L); // cascading summation of the left
|
||||
const uint16x4_t p1 = vadd_u16(vget_low_u16(p0), vget_high_u16(p0));
|
||||
const uint16x4_t p2 = vpadd_u16(p1, p1);
|
||||
const uint16x4_t p3 = vpadd_u16(p2, p2);
|
||||
sum_left = vcombine_u16(p3, p3);
|
||||
}
|
||||
|
||||
if (do_above && do_left) {
|
||||
const uint16x8_t sum = vaddq_u16(sum_left, sum_top);
|
||||
dc0 = vrshrn_n_u16(sum, 5);
|
||||
} else if (do_above) {
|
||||
dc0 = vrshrn_n_u16(sum_top, 4);
|
||||
} else if (do_left) {
|
||||
dc0 = vrshrn_n_u16(sum_left, 4);
|
||||
} else {
|
||||
dc0 = vdup_n_u8(0x80);
|
||||
}
|
||||
|
||||
{
|
||||
const uint8x16_t dc = vdupq_lane_u8(dc0, 0);
|
||||
int i;
|
||||
for (i = 0; i < 16; ++i) {
|
||||
vst1q_u8(dst + i * stride, dc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void aom_dc_predictor_16x16_neon(uint8_t *dst, ptrdiff_t stride,
|
||||
const uint8_t *above, const uint8_t *left) {
|
||||
dc_16x16(dst, stride, above, left, 1, 1);
|
||||
}
|
||||
|
||||
void aom_dc_left_predictor_16x16_neon(uint8_t *dst, ptrdiff_t stride,
|
||||
const uint8_t *above,
|
||||
const uint8_t *left) {
|
||||
(void)above;
|
||||
dc_16x16(dst, stride, NULL, left, 0, 1);
|
||||
}
|
||||
|
||||
void aom_dc_top_predictor_16x16_neon(uint8_t *dst, ptrdiff_t stride,
|
||||
const uint8_t *above,
|
||||
const uint8_t *left) {
|
||||
(void)left;
|
||||
dc_16x16(dst, stride, above, NULL, 1, 0);
|
||||
}
|
||||
|
||||
void aom_dc_128_predictor_16x16_neon(uint8_t *dst, ptrdiff_t stride,
|
||||
const uint8_t *above,
|
||||
const uint8_t *left) {
|
||||
(void)above;
|
||||
(void)left;
|
||||
dc_16x16(dst, stride, NULL, NULL, 0, 0);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// DC 32x32
|
||||
|
||||
// 'do_above' and 'do_left' facilitate branch removal when inlined.
|
||||
static INLINE void dc_32x32(uint8_t *dst, ptrdiff_t stride,
|
||||
const uint8_t *above, const uint8_t *left,
|
||||
int do_above, int do_left) {
|
||||
uint16x8_t sum_top;
|
||||
uint16x8_t sum_left;
|
||||
uint8x8_t dc0;
|
||||
|
||||
if (do_above) {
|
||||
const uint8x16_t A0 = vld1q_u8(above); // top row
|
||||
const uint8x16_t A1 = vld1q_u8(above + 16);
|
||||
const uint16x8_t p0 = vpaddlq_u8(A0); // cascading summation of the top
|
||||
const uint16x8_t p1 = vpaddlq_u8(A1);
|
||||
const uint16x8_t p2 = vaddq_u16(p0, p1);
|
||||
const uint16x4_t p3 = vadd_u16(vget_low_u16(p2), vget_high_u16(p2));
|
||||
const uint16x4_t p4 = vpadd_u16(p3, p3);
|
||||
const uint16x4_t p5 = vpadd_u16(p4, p4);
|
||||
sum_top = vcombine_u16(p5, p5);
|
||||
}
|
||||
|
||||
if (do_left) {
|
||||
const uint8x16_t L0 = vld1q_u8(left); // left row
|
||||
const uint8x16_t L1 = vld1q_u8(left + 16);
|
||||
const uint16x8_t p0 = vpaddlq_u8(L0); // cascading summation of the left
|
||||
const uint16x8_t p1 = vpaddlq_u8(L1);
|
||||
const uint16x8_t p2 = vaddq_u16(p0, p1);
|
||||
const uint16x4_t p3 = vadd_u16(vget_low_u16(p2), vget_high_u16(p2));
|
||||
const uint16x4_t p4 = vpadd_u16(p3, p3);
|
||||
const uint16x4_t p5 = vpadd_u16(p4, p4);
|
||||
sum_left = vcombine_u16(p5, p5);
|
||||
}
|
||||
|
||||
if (do_above && do_left) {
|
||||
const uint16x8_t sum = vaddq_u16(sum_left, sum_top);
|
||||
dc0 = vrshrn_n_u16(sum, 6);
|
||||
} else if (do_above) {
|
||||
dc0 = vrshrn_n_u16(sum_top, 5);
|
||||
} else if (do_left) {
|
||||
dc0 = vrshrn_n_u16(sum_left, 5);
|
||||
} else {
|
||||
dc0 = vdup_n_u8(0x80);
|
||||
}
|
||||
|
||||
{
|
||||
const uint8x16_t dc = vdupq_lane_u8(dc0, 0);
|
||||
int i;
|
||||
for (i = 0; i < 32; ++i) {
|
||||
vst1q_u8(dst + i * stride, dc);
|
||||
vst1q_u8(dst + i * stride + 16, dc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void aom_dc_predictor_32x32_neon(uint8_t *dst, ptrdiff_t stride,
|
||||
const uint8_t *above, const uint8_t *left) {
|
||||
dc_32x32(dst, stride, above, left, 1, 1);
|
||||
}
|
||||
|
||||
void aom_dc_left_predictor_32x32_neon(uint8_t *dst, ptrdiff_t stride,
|
||||
const uint8_t *above,
|
||||
const uint8_t *left) {
|
||||
(void)above;
|
||||
dc_32x32(dst, stride, NULL, left, 0, 1);
|
||||
}
|
||||
|
||||
void aom_dc_top_predictor_32x32_neon(uint8_t *dst, ptrdiff_t stride,
|
||||
const uint8_t *above,
|
||||
const uint8_t *left) {
|
||||
(void)left;
|
||||
dc_32x32(dst, stride, above, NULL, 1, 0);
|
||||
}
|
||||
|
||||
void aom_dc_128_predictor_32x32_neon(uint8_t *dst, ptrdiff_t stride,
|
||||
const uint8_t *above,
|
||||
const uint8_t *left) {
|
||||
(void)above;
|
||||
(void)left;
|
||||
dc_32x32(dst, stride, NULL, NULL, 0, 0);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void aom_d135_predictor_4x4_neon(uint8_t *dst, ptrdiff_t stride,
|
||||
const uint8_t *above, const uint8_t *left) {
|
||||
const uint8x8_t XABCD_u8 = vld1_u8(above - 1);
|
||||
const uint64x1_t XABCD = vreinterpret_u64_u8(XABCD_u8);
|
||||
const uint64x1_t ____XABC = vshl_n_u64(XABCD, 32);
|
||||
const uint32x2_t zero = vdup_n_u32(0);
|
||||
const uint32x2_t IJKL = vld1_lane_u32((const uint32_t *)left, zero, 0);
|
||||
const uint8x8_t IJKL_u8 = vreinterpret_u8_u32(IJKL);
|
||||
const uint64x1_t LKJI____ = vreinterpret_u64_u8(vrev32_u8(IJKL_u8));
|
||||
const uint64x1_t LKJIXABC = vorr_u64(LKJI____, ____XABC);
|
||||
const uint8x8_t KJIXABC_ = vreinterpret_u8_u64(vshr_n_u64(LKJIXABC, 8));
|
||||
const uint8x8_t JIXABC__ = vreinterpret_u8_u64(vshr_n_u64(LKJIXABC, 16));
|
||||
const uint8_t D = vget_lane_u8(XABCD_u8, 4);
|
||||
const uint8x8_t JIXABCD_ = vset_lane_u8(D, JIXABC__, 6);
|
||||
const uint8x8_t LKJIXABC_u8 = vreinterpret_u8_u64(LKJIXABC);
|
||||
const uint8x8_t avg1 = vhadd_u8(JIXABCD_, LKJIXABC_u8);
|
||||
const uint8x8_t avg2 = vrhadd_u8(avg1, KJIXABC_);
|
||||
const uint64x1_t avg2_u64 = vreinterpret_u64_u8(avg2);
|
||||
const uint32x2_t r3 = vreinterpret_u32_u8(avg2);
|
||||
const uint32x2_t r2 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 8));
|
||||
const uint32x2_t r1 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 16));
|
||||
const uint32x2_t r0 = vreinterpret_u32_u64(vshr_n_u64(avg2_u64, 24));
|
||||
vst1_lane_u32((uint32_t *)(dst + 0 * stride), r0, 0);
|
||||
vst1_lane_u32((uint32_t *)(dst + 1 * stride), r1, 0);
|
||||
vst1_lane_u32((uint32_t *)(dst + 2 * stride), r2, 0);
|
||||
vst1_lane_u32((uint32_t *)(dst + 3 * stride), r3, 0);
|
||||
}
|
||||
|
||||
#if !HAVE_NEON_ASM
|
||||
|
||||
void aom_v_predictor_4x4_neon(uint8_t *dst, ptrdiff_t stride,
|
||||
const uint8_t *above, const uint8_t *left) {
|
||||
int i;
|
||||
uint32x2_t d0u32 = vdup_n_u32(0);
|
||||
(void)left;
|
||||
|
||||
d0u32 = vld1_lane_u32((const uint32_t *)above, d0u32, 0);
|
||||
for (i = 0; i < 4; i++, dst += stride)
|
||||
vst1_lane_u32((uint32_t *)dst, d0u32, 0);
|
||||
}
|
||||
|
||||
void aom_v_predictor_8x8_neon(uint8_t *dst, ptrdiff_t stride,
|
||||
const uint8_t *above, const uint8_t *left) {
|
||||
int i;
|
||||
uint8x8_t d0u8 = vdup_n_u8(0);
|
||||
(void)left;
|
||||
|
||||
d0u8 = vld1_u8(above);
|
||||
for (i = 0; i < 8; i++, dst += stride) vst1_u8(dst, d0u8);
|
||||
}
|
||||
|
||||
void aom_v_predictor_16x16_neon(uint8_t *dst, ptrdiff_t stride,
|
||||
const uint8_t *above, const uint8_t *left) {
|
||||
int i;
|
||||
uint8x16_t q0u8 = vdupq_n_u8(0);
|
||||
(void)left;
|
||||
|
||||
q0u8 = vld1q_u8(above);
|
||||
for (i = 0; i < 16; i++, dst += stride) vst1q_u8(dst, q0u8);
|
||||
}
|
||||
|
||||
void aom_v_predictor_32x32_neon(uint8_t *dst, ptrdiff_t stride,
|
||||
const uint8_t *above, const uint8_t *left) {
|
||||
int i;
|
||||
uint8x16_t q0u8 = vdupq_n_u8(0);
|
||||
uint8x16_t q1u8 = vdupq_n_u8(0);
|
||||
(void)left;
|
||||
|
||||
q0u8 = vld1q_u8(above);
|
||||
q1u8 = vld1q_u8(above + 16);
|
||||
for (i = 0; i < 32; i++, dst += stride) {
|
||||
vst1q_u8(dst, q0u8);
|
||||
vst1q_u8(dst + 16, q1u8);
|
||||
}
|
||||
}
|
||||
|
||||
void aom_h_predictor_4x4_neon(uint8_t *dst, ptrdiff_t stride,
|
||||
const uint8_t *above, const uint8_t *left) {
|
||||
uint8x8_t d0u8 = vdup_n_u8(0);
|
||||
uint32x2_t d1u32 = vdup_n_u32(0);
|
||||
(void)above;
|
||||
|
||||
d1u32 = vld1_lane_u32((const uint32_t *)left, d1u32, 0);
|
||||
|
||||
d0u8 = vdup_lane_u8(vreinterpret_u8_u32(d1u32), 0);
|
||||
vst1_lane_u32((uint32_t *)dst, vreinterpret_u32_u8(d0u8), 0);
|
||||
dst += stride;
|
||||
d0u8 = vdup_lane_u8(vreinterpret_u8_u32(d1u32), 1);
|
||||
vst1_lane_u32((uint32_t *)dst, vreinterpret_u32_u8(d0u8), 0);
|
||||
dst += stride;
|
||||
d0u8 = vdup_lane_u8(vreinterpret_u8_u32(d1u32), 2);
|
||||
vst1_lane_u32((uint32_t *)dst, vreinterpret_u32_u8(d0u8), 0);
|
||||
dst += stride;
|
||||
d0u8 = vdup_lane_u8(vreinterpret_u8_u32(d1u32), 3);
|
||||
vst1_lane_u32((uint32_t *)dst, vreinterpret_u32_u8(d0u8), 0);
|
||||
}
|
||||
|
||||
void aom_h_predictor_8x8_neon(uint8_t *dst, ptrdiff_t stride,
|
||||
const uint8_t *above, const uint8_t *left) {
|
||||
uint8x8_t d0u8 = vdup_n_u8(0);
|
||||
uint64x1_t d1u64 = vdup_n_u64(0);
|
||||
(void)above;
|
||||
|
||||
d1u64 = vld1_u64((const uint64_t *)left);
|
||||
|
||||
d0u8 = vdup_lane_u8(vreinterpret_u8_u64(d1u64), 0);
|
||||
vst1_u8(dst, d0u8);
|
||||
dst += stride;
|
||||
d0u8 = vdup_lane_u8(vreinterpret_u8_u64(d1u64), 1);
|
||||
vst1_u8(dst, d0u8);
|
||||
dst += stride;
|
||||
d0u8 = vdup_lane_u8(vreinterpret_u8_u64(d1u64), 2);
|
||||
vst1_u8(dst, d0u8);
|
||||
dst += stride;
|
||||
d0u8 = vdup_lane_u8(vreinterpret_u8_u64(d1u64), 3);
|
||||
vst1_u8(dst, d0u8);
|
||||
dst += stride;
|
||||
d0u8 = vdup_lane_u8(vreinterpret_u8_u64(d1u64), 4);
|
||||
vst1_u8(dst, d0u8);
|
||||
dst += stride;
|
||||
d0u8 = vdup_lane_u8(vreinterpret_u8_u64(d1u64), 5);
|
||||
vst1_u8(dst, d0u8);
|
||||
dst += stride;
|
||||
d0u8 = vdup_lane_u8(vreinterpret_u8_u64(d1u64), 6);
|
||||
vst1_u8(dst, d0u8);
|
||||
dst += stride;
|
||||
d0u8 = vdup_lane_u8(vreinterpret_u8_u64(d1u64), 7);
|
||||
vst1_u8(dst, d0u8);
|
||||
}
|
||||
|
||||
void aom_h_predictor_16x16_neon(uint8_t *dst, ptrdiff_t stride,
|
||||
const uint8_t *above, const uint8_t *left) {
|
||||
int j;
|
||||
uint8x8_t d2u8 = vdup_n_u8(0);
|
||||
uint8x16_t q0u8 = vdupq_n_u8(0);
|
||||
uint8x16_t q1u8 = vdupq_n_u8(0);
|
||||
(void)above;
|
||||
|
||||
q1u8 = vld1q_u8(left);
|
||||
d2u8 = vget_low_u8(q1u8);
|
||||
for (j = 0; j < 2; j++, d2u8 = vget_high_u8(q1u8)) {
|
||||
q0u8 = vdupq_lane_u8(d2u8, 0);
|
||||
vst1q_u8(dst, q0u8);
|
||||
dst += stride;
|
||||
q0u8 = vdupq_lane_u8(d2u8, 1);
|
||||
vst1q_u8(dst, q0u8);
|
||||
dst += stride;
|
||||
q0u8 = vdupq_lane_u8(d2u8, 2);
|
||||
vst1q_u8(dst, q0u8);
|
||||
dst += stride;
|
||||
q0u8 = vdupq_lane_u8(d2u8, 3);
|
||||
vst1q_u8(dst, q0u8);
|
||||
dst += stride;
|
||||
q0u8 = vdupq_lane_u8(d2u8, 4);
|
||||
vst1q_u8(dst, q0u8);
|
||||
dst += stride;
|
||||
q0u8 = vdupq_lane_u8(d2u8, 5);
|
||||
vst1q_u8(dst, q0u8);
|
||||
dst += stride;
|
||||
q0u8 = vdupq_lane_u8(d2u8, 6);
|
||||
vst1q_u8(dst, q0u8);
|
||||
dst += stride;
|
||||
q0u8 = vdupq_lane_u8(d2u8, 7);
|
||||
vst1q_u8(dst, q0u8);
|
||||
dst += stride;
|
||||
}
|
||||
}
|
||||
|
||||
void aom_h_predictor_32x32_neon(uint8_t *dst, ptrdiff_t stride,
|
||||
const uint8_t *above, const uint8_t *left) {
|
||||
int j, k;
|
||||
uint8x8_t d2u8 = vdup_n_u8(0);
|
||||
uint8x16_t q0u8 = vdupq_n_u8(0);
|
||||
uint8x16_t q1u8 = vdupq_n_u8(0);
|
||||
(void)above;
|
||||
|
||||
for (k = 0; k < 2; k++, left += 16) {
|
||||
q1u8 = vld1q_u8(left);
|
||||
d2u8 = vget_low_u8(q1u8);
|
||||
for (j = 0; j < 2; j++, d2u8 = vget_high_u8(q1u8)) {
|
||||
q0u8 = vdupq_lane_u8(d2u8, 0);
|
||||
vst1q_u8(dst, q0u8);
|
||||
vst1q_u8(dst + 16, q0u8);
|
||||
dst += stride;
|
||||
q0u8 = vdupq_lane_u8(d2u8, 1);
|
||||
vst1q_u8(dst, q0u8);
|
||||
vst1q_u8(dst + 16, q0u8);
|
||||
dst += stride;
|
||||
q0u8 = vdupq_lane_u8(d2u8, 2);
|
||||
vst1q_u8(dst, q0u8);
|
||||
vst1q_u8(dst + 16, q0u8);
|
||||
dst += stride;
|
||||
q0u8 = vdupq_lane_u8(d2u8, 3);
|
||||
vst1q_u8(dst, q0u8);
|
||||
vst1q_u8(dst + 16, q0u8);
|
||||
dst += stride;
|
||||
q0u8 = vdupq_lane_u8(d2u8, 4);
|
||||
vst1q_u8(dst, q0u8);
|
||||
vst1q_u8(dst + 16, q0u8);
|
||||
dst += stride;
|
||||
q0u8 = vdupq_lane_u8(d2u8, 5);
|
||||
vst1q_u8(dst, q0u8);
|
||||
vst1q_u8(dst + 16, q0u8);
|
||||
dst += stride;
|
||||
q0u8 = vdupq_lane_u8(d2u8, 6);
|
||||
vst1q_u8(dst, q0u8);
|
||||
vst1q_u8(dst + 16, q0u8);
|
||||
dst += stride;
|
||||
q0u8 = vdupq_lane_u8(d2u8, 7);
|
||||
vst1q_u8(dst, q0u8);
|
||||
vst1q_u8(dst + 16, q0u8);
|
||||
dst += stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void aom_tm_predictor_4x4_neon(uint8_t *dst, ptrdiff_t stride,
|
||||
const uint8_t *above, const uint8_t *left) {
|
||||
int i;
|
||||
uint16x8_t q1u16, q3u16;
|
||||
int16x8_t q1s16;
|
||||
uint8x8_t d0u8 = vdup_n_u8(0);
|
||||
uint32x2_t d2u32 = vdup_n_u32(0);
|
||||
|
||||
d0u8 = vld1_dup_u8(above - 1);
|
||||
d2u32 = vld1_lane_u32((const uint32_t *)above, d2u32, 0);
|
||||
q3u16 = vsubl_u8(vreinterpret_u8_u32(d2u32), d0u8);
|
||||
for (i = 0; i < 4; i++, dst += stride) {
|
||||
q1u16 = vdupq_n_u16((uint16_t)left[i]);
|
||||
q1s16 =
|
||||
vaddq_s16(vreinterpretq_s16_u16(q1u16), vreinterpretq_s16_u16(q3u16));
|
||||
d0u8 = vqmovun_s16(q1s16);
|
||||
vst1_lane_u32((uint32_t *)dst, vreinterpret_u32_u8(d0u8), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void aom_tm_predictor_8x8_neon(uint8_t *dst, ptrdiff_t stride,
|
||||
const uint8_t *above, const uint8_t *left) {
|
||||
int j;
|
||||
uint16x8_t q0u16, q3u16, q10u16;
|
||||
int16x8_t q0s16;
|
||||
uint16x4_t d20u16;
|
||||
uint8x8_t d0u8, d2u8, d30u8;
|
||||
|
||||
d0u8 = vld1_dup_u8(above - 1);
|
||||
d30u8 = vld1_u8(left);
|
||||
d2u8 = vld1_u8(above);
|
||||
q10u16 = vmovl_u8(d30u8);
|
||||
q3u16 = vsubl_u8(d2u8, d0u8);
|
||||
d20u16 = vget_low_u16(q10u16);
|
||||
for (j = 0; j < 2; j++, d20u16 = vget_high_u16(q10u16)) {
|
||||
q0u16 = vdupq_lane_u16(d20u16, 0);
|
||||
q0s16 =
|
||||
vaddq_s16(vreinterpretq_s16_u16(q3u16), vreinterpretq_s16_u16(q0u16));
|
||||
d0u8 = vqmovun_s16(q0s16);
|
||||
vst1_u64((uint64_t *)dst, vreinterpret_u64_u8(d0u8));
|
||||
dst += stride;
|
||||
q0u16 = vdupq_lane_u16(d20u16, 1);
|
||||
q0s16 =
|
||||
vaddq_s16(vreinterpretq_s16_u16(q3u16), vreinterpretq_s16_u16(q0u16));
|
||||
d0u8 = vqmovun_s16(q0s16);
|
||||
vst1_u64((uint64_t *)dst, vreinterpret_u64_u8(d0u8));
|
||||
dst += stride;
|
||||
q0u16 = vdupq_lane_u16(d20u16, 2);
|
||||
q0s16 =
|
||||
vaddq_s16(vreinterpretq_s16_u16(q3u16), vreinterpretq_s16_u16(q0u16));
|
||||
d0u8 = vqmovun_s16(q0s16);
|
||||
vst1_u64((uint64_t *)dst, vreinterpret_u64_u8(d0u8));
|
||||
dst += stride;
|
||||
q0u16 = vdupq_lane_u16(d20u16, 3);
|
||||
q0s16 =
|
||||
vaddq_s16(vreinterpretq_s16_u16(q3u16), vreinterpretq_s16_u16(q0u16));
|
||||
d0u8 = vqmovun_s16(q0s16);
|
||||
vst1_u64((uint64_t *)dst, vreinterpret_u64_u8(d0u8));
|
||||
dst += stride;
|
||||
}
|
||||
}
|
||||
|
||||
void aom_tm_predictor_16x16_neon(uint8_t *dst, ptrdiff_t stride,
|
||||
const uint8_t *above, const uint8_t *left) {
|
||||
int j, k;
|
||||
uint16x8_t q0u16, q2u16, q3u16, q8u16, q10u16;
|
||||
uint8x16_t q0u8, q1u8;
|
||||
int16x8_t q0s16, q1s16, q8s16, q11s16;
|
||||
uint16x4_t d20u16;
|
||||
uint8x8_t d2u8, d3u8, d18u8, d22u8, d23u8;
|
||||
|
||||
q0u8 = vld1q_dup_u8(above - 1);
|
||||
q1u8 = vld1q_u8(above);
|
||||
q2u16 = vsubl_u8(vget_low_u8(q1u8), vget_low_u8(q0u8));
|
||||
q3u16 = vsubl_u8(vget_high_u8(q1u8), vget_high_u8(q0u8));
|
||||
for (k = 0; k < 2; k++, left += 8) {
|
||||
d18u8 = vld1_u8(left);
|
||||
q10u16 = vmovl_u8(d18u8);
|
||||
d20u16 = vget_low_u16(q10u16);
|
||||
for (j = 0; j < 2; j++, d20u16 = vget_high_u16(q10u16)) {
|
||||
q0u16 = vdupq_lane_u16(d20u16, 0);
|
||||
q8u16 = vdupq_lane_u16(d20u16, 1);
|
||||
q1s16 =
|
||||
vaddq_s16(vreinterpretq_s16_u16(q0u16), vreinterpretq_s16_u16(q2u16));
|
||||
q0s16 =
|
||||
vaddq_s16(vreinterpretq_s16_u16(q0u16), vreinterpretq_s16_u16(q3u16));
|
||||
q11s16 =
|
||||
vaddq_s16(vreinterpretq_s16_u16(q8u16), vreinterpretq_s16_u16(q2u16));
|
||||
q8s16 =
|
||||
vaddq_s16(vreinterpretq_s16_u16(q8u16), vreinterpretq_s16_u16(q3u16));
|
||||
d2u8 = vqmovun_s16(q1s16);
|
||||
d3u8 = vqmovun_s16(q0s16);
|
||||
d22u8 = vqmovun_s16(q11s16);
|
||||
d23u8 = vqmovun_s16(q8s16);
|
||||
vst1_u64((uint64_t *)dst, vreinterpret_u64_u8(d2u8));
|
||||
vst1_u64((uint64_t *)(dst + 8), vreinterpret_u64_u8(d3u8));
|
||||
dst += stride;
|
||||
vst1_u64((uint64_t *)dst, vreinterpret_u64_u8(d22u8));
|
||||
vst1_u64((uint64_t *)(dst + 8), vreinterpret_u64_u8(d23u8));
|
||||
dst += stride;
|
||||
|
||||
q0u16 = vdupq_lane_u16(d20u16, 2);
|
||||
q8u16 = vdupq_lane_u16(d20u16, 3);
|
||||
q1s16 =
|
||||
vaddq_s16(vreinterpretq_s16_u16(q0u16), vreinterpretq_s16_u16(q2u16));
|
||||
q0s16 =
|
||||
vaddq_s16(vreinterpretq_s16_u16(q0u16), vreinterpretq_s16_u16(q3u16));
|
||||
q11s16 =
|
||||
vaddq_s16(vreinterpretq_s16_u16(q8u16), vreinterpretq_s16_u16(q2u16));
|
||||
q8s16 =
|
||||
vaddq_s16(vreinterpretq_s16_u16(q8u16), vreinterpretq_s16_u16(q3u16));
|
||||
d2u8 = vqmovun_s16(q1s16);
|
||||
d3u8 = vqmovun_s16(q0s16);
|
||||
d22u8 = vqmovun_s16(q11s16);
|
||||
d23u8 = vqmovun_s16(q8s16);
|
||||
vst1_u64((uint64_t *)dst, vreinterpret_u64_u8(d2u8));
|
||||
vst1_u64((uint64_t *)(dst + 8), vreinterpret_u64_u8(d3u8));
|
||||
dst += stride;
|
||||
vst1_u64((uint64_t *)dst, vreinterpret_u64_u8(d22u8));
|
||||
vst1_u64((uint64_t *)(dst + 8), vreinterpret_u64_u8(d23u8));
|
||||
dst += stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void aom_tm_predictor_32x32_neon(uint8_t *dst, ptrdiff_t stride,
|
||||
const uint8_t *above, const uint8_t *left) {
|
||||
int j, k;
|
||||
uint16x8_t q0u16, q3u16, q8u16, q9u16, q10u16, q11u16;
|
||||
uint8x16_t q0u8, q1u8, q2u8;
|
||||
int16x8_t q12s16, q13s16, q14s16, q15s16;
|
||||
uint16x4_t d6u16;
|
||||
uint8x8_t d0u8, d1u8, d2u8, d3u8, d26u8;
|
||||
|
||||
q0u8 = vld1q_dup_u8(above - 1);
|
||||
q1u8 = vld1q_u8(above);
|
||||
q2u8 = vld1q_u8(above + 16);
|
||||
q8u16 = vsubl_u8(vget_low_u8(q1u8), vget_low_u8(q0u8));
|
||||
q9u16 = vsubl_u8(vget_high_u8(q1u8), vget_high_u8(q0u8));
|
||||
q10u16 = vsubl_u8(vget_low_u8(q2u8), vget_low_u8(q0u8));
|
||||
q11u16 = vsubl_u8(vget_high_u8(q2u8), vget_high_u8(q0u8));
|
||||
for (k = 0; k < 4; k++, left += 8) {
|
||||
d26u8 = vld1_u8(left);
|
||||
q3u16 = vmovl_u8(d26u8);
|
||||
d6u16 = vget_low_u16(q3u16);
|
||||
for (j = 0; j < 2; j++, d6u16 = vget_high_u16(q3u16)) {
|
||||
q0u16 = vdupq_lane_u16(d6u16, 0);
|
||||
q12s16 =
|
||||
vaddq_s16(vreinterpretq_s16_u16(q0u16), vreinterpretq_s16_u16(q8u16));
|
||||
q13s16 =
|
||||
vaddq_s16(vreinterpretq_s16_u16(q0u16), vreinterpretq_s16_u16(q9u16));
|
||||
q14s16 = vaddq_s16(vreinterpretq_s16_u16(q0u16),
|
||||
vreinterpretq_s16_u16(q10u16));
|
||||
q15s16 = vaddq_s16(vreinterpretq_s16_u16(q0u16),
|
||||
vreinterpretq_s16_u16(q11u16));
|
||||
d0u8 = vqmovun_s16(q12s16);
|
||||
d1u8 = vqmovun_s16(q13s16);
|
||||
d2u8 = vqmovun_s16(q14s16);
|
||||
d3u8 = vqmovun_s16(q15s16);
|
||||
q0u8 = vcombine_u8(d0u8, d1u8);
|
||||
q1u8 = vcombine_u8(d2u8, d3u8);
|
||||
vst1q_u64((uint64_t *)dst, vreinterpretq_u64_u8(q0u8));
|
||||
vst1q_u64((uint64_t *)(dst + 16), vreinterpretq_u64_u8(q1u8));
|
||||
dst += stride;
|
||||
|
||||
q0u16 = vdupq_lane_u16(d6u16, 1);
|
||||
q12s16 =
|
||||
vaddq_s16(vreinterpretq_s16_u16(q0u16), vreinterpretq_s16_u16(q8u16));
|
||||
q13s16 =
|
||||
vaddq_s16(vreinterpretq_s16_u16(q0u16), vreinterpretq_s16_u16(q9u16));
|
||||
q14s16 = vaddq_s16(vreinterpretq_s16_u16(q0u16),
|
||||
vreinterpretq_s16_u16(q10u16));
|
||||
q15s16 = vaddq_s16(vreinterpretq_s16_u16(q0u16),
|
||||
vreinterpretq_s16_u16(q11u16));
|
||||
d0u8 = vqmovun_s16(q12s16);
|
||||
d1u8 = vqmovun_s16(q13s16);
|
||||
d2u8 = vqmovun_s16(q14s16);
|
||||
d3u8 = vqmovun_s16(q15s16);
|
||||
q0u8 = vcombine_u8(d0u8, d1u8);
|
||||
q1u8 = vcombine_u8(d2u8, d3u8);
|
||||
vst1q_u64((uint64_t *)dst, vreinterpretq_u64_u8(q0u8));
|
||||
vst1q_u64((uint64_t *)(dst + 16), vreinterpretq_u64_u8(q1u8));
|
||||
dst += stride;
|
||||
|
||||
q0u16 = vdupq_lane_u16(d6u16, 2);
|
||||
q12s16 =
|
||||
vaddq_s16(vreinterpretq_s16_u16(q0u16), vreinterpretq_s16_u16(q8u16));
|
||||
q13s16 =
|
||||
vaddq_s16(vreinterpretq_s16_u16(q0u16), vreinterpretq_s16_u16(q9u16));
|
||||
q14s16 = vaddq_s16(vreinterpretq_s16_u16(q0u16),
|
||||
vreinterpretq_s16_u16(q10u16));
|
||||
q15s16 = vaddq_s16(vreinterpretq_s16_u16(q0u16),
|
||||
vreinterpretq_s16_u16(q11u16));
|
||||
d0u8 = vqmovun_s16(q12s16);
|
||||
d1u8 = vqmovun_s16(q13s16);
|
||||
d2u8 = vqmovun_s16(q14s16);
|
||||
d3u8 = vqmovun_s16(q15s16);
|
||||
q0u8 = vcombine_u8(d0u8, d1u8);
|
||||
q1u8 = vcombine_u8(d2u8, d3u8);
|
||||
vst1q_u64((uint64_t *)dst, vreinterpretq_u64_u8(q0u8));
|
||||
vst1q_u64((uint64_t *)(dst + 16), vreinterpretq_u64_u8(q1u8));
|
||||
dst += stride;
|
||||
|
||||
q0u16 = vdupq_lane_u16(d6u16, 3);
|
||||
q12s16 =
|
||||
vaddq_s16(vreinterpretq_s16_u16(q0u16), vreinterpretq_s16_u16(q8u16));
|
||||
q13s16 =
|
||||
vaddq_s16(vreinterpretq_s16_u16(q0u16), vreinterpretq_s16_u16(q9u16));
|
||||
q14s16 = vaddq_s16(vreinterpretq_s16_u16(q0u16),
|
||||
vreinterpretq_s16_u16(q10u16));
|
||||
q15s16 = vaddq_s16(vreinterpretq_s16_u16(q0u16),
|
||||
vreinterpretq_s16_u16(q11u16));
|
||||
d0u8 = vqmovun_s16(q12s16);
|
||||
d1u8 = vqmovun_s16(q13s16);
|
||||
d2u8 = vqmovun_s16(q14s16);
|
||||
d3u8 = vqmovun_s16(q15s16);
|
||||
q0u8 = vcombine_u8(d0u8, d1u8);
|
||||
q1u8 = vcombine_u8(d2u8, d3u8);
|
||||
vst1q_u64((uint64_t *)dst, vreinterpretq_u64_u8(q0u8));
|
||||
vst1q_u64((uint64_t *)(dst + 16), vreinterpretq_u64_u8(q1u8));
|
||||
dst += stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // !HAVE_NEON_ASM
|
||||
633
third_party/aom/aom_dsp/arm/intrapred_neon_asm.asm
vendored
Normal file
633
third_party/aom/aom_dsp/arm/intrapred_neon_asm.asm
vendored
Normal file
|
|
@ -0,0 +1,633 @@
|
|||
;
|
||||
; Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
;
|
||||
; This source code is subject to the terms of the BSD 2 Clause License and
|
||||
; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
; was not distributed with this source code in the LICENSE file, you can
|
||||
; obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
; Media Patent License 1.0 was not distributed with this source code in the
|
||||
; PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
;
|
||||
|
||||
;
|
||||
|
||||
EXPORT |aom_v_predictor_4x4_neon|
|
||||
EXPORT |aom_v_predictor_8x8_neon|
|
||||
EXPORT |aom_v_predictor_16x16_neon|
|
||||
EXPORT |aom_v_predictor_32x32_neon|
|
||||
EXPORT |aom_h_predictor_4x4_neon|
|
||||
EXPORT |aom_h_predictor_8x8_neon|
|
||||
EXPORT |aom_h_predictor_16x16_neon|
|
||||
EXPORT |aom_h_predictor_32x32_neon|
|
||||
EXPORT |aom_tm_predictor_4x4_neon|
|
||||
EXPORT |aom_tm_predictor_8x8_neon|
|
||||
EXPORT |aom_tm_predictor_16x16_neon|
|
||||
EXPORT |aom_tm_predictor_32x32_neon|
|
||||
ARM
|
||||
REQUIRE8
|
||||
PRESERVE8
|
||||
|
||||
AREA ||.text||, CODE, READONLY, ALIGN=2
|
||||
|
||||
;void aom_v_predictor_4x4_neon(uint8_t *dst, ptrdiff_t y_stride,
|
||||
; const uint8_t *above,
|
||||
; const uint8_t *left)
|
||||
; r0 uint8_t *dst
|
||||
; r1 ptrdiff_t y_stride
|
||||
; r2 const uint8_t *above
|
||||
; r3 const uint8_t *left
|
||||
|
||||
|aom_v_predictor_4x4_neon| PROC
|
||||
vld1.32 {d0[0]}, [r2]
|
||||
vst1.32 {d0[0]}, [r0], r1
|
||||
vst1.32 {d0[0]}, [r0], r1
|
||||
vst1.32 {d0[0]}, [r0], r1
|
||||
vst1.32 {d0[0]}, [r0], r1
|
||||
bx lr
|
||||
ENDP ; |aom_v_predictor_4x4_neon|
|
||||
|
||||
;void aom_v_predictor_8x8_neon(uint8_t *dst, ptrdiff_t y_stride,
|
||||
; const uint8_t *above,
|
||||
; const uint8_t *left)
|
||||
; r0 uint8_t *dst
|
||||
; r1 ptrdiff_t y_stride
|
||||
; r2 const uint8_t *above
|
||||
; r3 const uint8_t *left
|
||||
|
||||
|aom_v_predictor_8x8_neon| PROC
|
||||
vld1.8 {d0}, [r2]
|
||||
vst1.8 {d0}, [r0], r1
|
||||
vst1.8 {d0}, [r0], r1
|
||||
vst1.8 {d0}, [r0], r1
|
||||
vst1.8 {d0}, [r0], r1
|
||||
vst1.8 {d0}, [r0], r1
|
||||
vst1.8 {d0}, [r0], r1
|
||||
vst1.8 {d0}, [r0], r1
|
||||
vst1.8 {d0}, [r0], r1
|
||||
bx lr
|
||||
ENDP ; |aom_v_predictor_8x8_neon|
|
||||
|
||||
;void aom_v_predictor_16x16_neon(uint8_t *dst, ptrdiff_t y_stride,
|
||||
; const uint8_t *above,
|
||||
; const uint8_t *left)
|
||||
; r0 uint8_t *dst
|
||||
; r1 ptrdiff_t y_stride
|
||||
; r2 const uint8_t *above
|
||||
; r3 const uint8_t *left
|
||||
|
||||
|aom_v_predictor_16x16_neon| PROC
|
||||
vld1.8 {q0}, [r2]
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vst1.8 {q0}, [r0], r1
|
||||
bx lr
|
||||
ENDP ; |aom_v_predictor_16x16_neon|
|
||||
|
||||
;void aom_v_predictor_32x32_neon(uint8_t *dst, ptrdiff_t y_stride,
|
||||
; const uint8_t *above,
|
||||
; const uint8_t *left)
|
||||
; r0 uint8_t *dst
|
||||
; r1 ptrdiff_t y_stride
|
||||
; r2 const uint8_t *above
|
||||
; r3 const uint8_t *left
|
||||
|
||||
|aom_v_predictor_32x32_neon| PROC
|
||||
vld1.8 {q0, q1}, [r2]
|
||||
mov r2, #2
|
||||
loop_v
|
||||
vst1.8 {q0, q1}, [r0], r1
|
||||
vst1.8 {q0, q1}, [r0], r1
|
||||
vst1.8 {q0, q1}, [r0], r1
|
||||
vst1.8 {q0, q1}, [r0], r1
|
||||
vst1.8 {q0, q1}, [r0], r1
|
||||
vst1.8 {q0, q1}, [r0], r1
|
||||
vst1.8 {q0, q1}, [r0], r1
|
||||
vst1.8 {q0, q1}, [r0], r1
|
||||
vst1.8 {q0, q1}, [r0], r1
|
||||
vst1.8 {q0, q1}, [r0], r1
|
||||
vst1.8 {q0, q1}, [r0], r1
|
||||
vst1.8 {q0, q1}, [r0], r1
|
||||
vst1.8 {q0, q1}, [r0], r1
|
||||
vst1.8 {q0, q1}, [r0], r1
|
||||
vst1.8 {q0, q1}, [r0], r1
|
||||
vst1.8 {q0, q1}, [r0], r1
|
||||
subs r2, r2, #1
|
||||
bgt loop_v
|
||||
bx lr
|
||||
ENDP ; |aom_v_predictor_32x32_neon|
|
||||
|
||||
;void aom_h_predictor_4x4_neon(uint8_t *dst, ptrdiff_t y_stride,
|
||||
; const uint8_t *above,
|
||||
; const uint8_t *left)
|
||||
; r0 uint8_t *dst
|
||||
; r1 ptrdiff_t y_stride
|
||||
; r2 const uint8_t *above
|
||||
; r3 const uint8_t *left
|
||||
|
||||
|aom_h_predictor_4x4_neon| PROC
|
||||
vld1.32 {d1[0]}, [r3]
|
||||
vdup.8 d0, d1[0]
|
||||
vst1.32 {d0[0]}, [r0], r1
|
||||
vdup.8 d0, d1[1]
|
||||
vst1.32 {d0[0]}, [r0], r1
|
||||
vdup.8 d0, d1[2]
|
||||
vst1.32 {d0[0]}, [r0], r1
|
||||
vdup.8 d0, d1[3]
|
||||
vst1.32 {d0[0]}, [r0], r1
|
||||
bx lr
|
||||
ENDP ; |aom_h_predictor_4x4_neon|
|
||||
|
||||
;void aom_h_predictor_8x8_neon(uint8_t *dst, ptrdiff_t y_stride,
|
||||
; const uint8_t *above,
|
||||
; const uint8_t *left)
|
||||
; r0 uint8_t *dst
|
||||
; r1 ptrdiff_t y_stride
|
||||
; r2 const uint8_t *above
|
||||
; r3 const uint8_t *left
|
||||
|
||||
|aom_h_predictor_8x8_neon| PROC
|
||||
vld1.64 {d1}, [r3]
|
||||
vdup.8 d0, d1[0]
|
||||
vst1.64 {d0}, [r0], r1
|
||||
vdup.8 d0, d1[1]
|
||||
vst1.64 {d0}, [r0], r1
|
||||
vdup.8 d0, d1[2]
|
||||
vst1.64 {d0}, [r0], r1
|
||||
vdup.8 d0, d1[3]
|
||||
vst1.64 {d0}, [r0], r1
|
||||
vdup.8 d0, d1[4]
|
||||
vst1.64 {d0}, [r0], r1
|
||||
vdup.8 d0, d1[5]
|
||||
vst1.64 {d0}, [r0], r1
|
||||
vdup.8 d0, d1[6]
|
||||
vst1.64 {d0}, [r0], r1
|
||||
vdup.8 d0, d1[7]
|
||||
vst1.64 {d0}, [r0], r1
|
||||
bx lr
|
||||
ENDP ; |aom_h_predictor_8x8_neon|
|
||||
|
||||
;void aom_h_predictor_16x16_neon(uint8_t *dst, ptrdiff_t y_stride,
|
||||
; const uint8_t *above,
|
||||
; const uint8_t *left)
|
||||
; r0 uint8_t *dst
|
||||
; r1 ptrdiff_t y_stride
|
||||
; r2 const uint8_t *above
|
||||
; r3 const uint8_t *left
|
||||
|
||||
|aom_h_predictor_16x16_neon| PROC
|
||||
vld1.8 {q1}, [r3]
|
||||
vdup.8 q0, d2[0]
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vdup.8 q0, d2[1]
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vdup.8 q0, d2[2]
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vdup.8 q0, d2[3]
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vdup.8 q0, d2[4]
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vdup.8 q0, d2[5]
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vdup.8 q0, d2[6]
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vdup.8 q0, d2[7]
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vdup.8 q0, d3[0]
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vdup.8 q0, d3[1]
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vdup.8 q0, d3[2]
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vdup.8 q0, d3[3]
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vdup.8 q0, d3[4]
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vdup.8 q0, d3[5]
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vdup.8 q0, d3[6]
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vdup.8 q0, d3[7]
|
||||
vst1.8 {q0}, [r0], r1
|
||||
bx lr
|
||||
ENDP ; |aom_h_predictor_16x16_neon|
|
||||
|
||||
;void aom_h_predictor_32x32_neon(uint8_t *dst, ptrdiff_t y_stride,
|
||||
; const uint8_t *above,
|
||||
; const uint8_t *left)
|
||||
; r0 uint8_t *dst
|
||||
; r1 ptrdiff_t y_stride
|
||||
; r2 const uint8_t *above
|
||||
; r3 const uint8_t *left
|
||||
|
||||
|aom_h_predictor_32x32_neon| PROC
|
||||
sub r1, r1, #16
|
||||
mov r2, #2
|
||||
loop_h
|
||||
vld1.8 {q1}, [r3]!
|
||||
vdup.8 q0, d2[0]
|
||||
vst1.8 {q0}, [r0]!
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vdup.8 q0, d2[1]
|
||||
vst1.8 {q0}, [r0]!
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vdup.8 q0, d2[2]
|
||||
vst1.8 {q0}, [r0]!
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vdup.8 q0, d2[3]
|
||||
vst1.8 {q0}, [r0]!
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vdup.8 q0, d2[4]
|
||||
vst1.8 {q0}, [r0]!
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vdup.8 q0, d2[5]
|
||||
vst1.8 {q0}, [r0]!
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vdup.8 q0, d2[6]
|
||||
vst1.8 {q0}, [r0]!
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vdup.8 q0, d2[7]
|
||||
vst1.8 {q0}, [r0]!
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vdup.8 q0, d3[0]
|
||||
vst1.8 {q0}, [r0]!
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vdup.8 q0, d3[1]
|
||||
vst1.8 {q0}, [r0]!
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vdup.8 q0, d3[2]
|
||||
vst1.8 {q0}, [r0]!
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vdup.8 q0, d3[3]
|
||||
vst1.8 {q0}, [r0]!
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vdup.8 q0, d3[4]
|
||||
vst1.8 {q0}, [r0]!
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vdup.8 q0, d3[5]
|
||||
vst1.8 {q0}, [r0]!
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vdup.8 q0, d3[6]
|
||||
vst1.8 {q0}, [r0]!
|
||||
vst1.8 {q0}, [r0], r1
|
||||
vdup.8 q0, d3[7]
|
||||
vst1.8 {q0}, [r0]!
|
||||
vst1.8 {q0}, [r0], r1
|
||||
subs r2, r2, #1
|
||||
bgt loop_h
|
||||
bx lr
|
||||
ENDP ; |aom_h_predictor_32x32_neon|
|
||||
|
||||
;void aom_tm_predictor_4x4_neon (uint8_t *dst, ptrdiff_t y_stride,
|
||||
; const uint8_t *above,
|
||||
; const uint8_t *left)
|
||||
; r0 uint8_t *dst
|
||||
; r1 ptrdiff_t y_stride
|
||||
; r2 const uint8_t *above
|
||||
; r3 const uint8_t *left
|
||||
|
||||
|aom_tm_predictor_4x4_neon| PROC
|
||||
; Load ytop_left = above[-1];
|
||||
sub r12, r2, #1
|
||||
vld1.u8 {d0[]}, [r12]
|
||||
|
||||
; Load above 4 pixels
|
||||
vld1.32 {d2[0]}, [r2]
|
||||
|
||||
; Compute above - ytop_left
|
||||
vsubl.u8 q3, d2, d0
|
||||
|
||||
; Load left row by row and compute left + (above - ytop_left)
|
||||
; 1st row and 2nd row
|
||||
vld1.u8 {d2[]}, [r3]!
|
||||
vld1.u8 {d4[]}, [r3]!
|
||||
vmovl.u8 q1, d2
|
||||
vmovl.u8 q2, d4
|
||||
vadd.s16 q1, q1, q3
|
||||
vadd.s16 q2, q2, q3
|
||||
vqmovun.s16 d0, q1
|
||||
vqmovun.s16 d1, q2
|
||||
vst1.32 {d0[0]}, [r0], r1
|
||||
vst1.32 {d1[0]}, [r0], r1
|
||||
|
||||
; 3rd row and 4th row
|
||||
vld1.u8 {d2[]}, [r3]!
|
||||
vld1.u8 {d4[]}, [r3]
|
||||
vmovl.u8 q1, d2
|
||||
vmovl.u8 q2, d4
|
||||
vadd.s16 q1, q1, q3
|
||||
vadd.s16 q2, q2, q3
|
||||
vqmovun.s16 d0, q1
|
||||
vqmovun.s16 d1, q2
|
||||
vst1.32 {d0[0]}, [r0], r1
|
||||
vst1.32 {d1[0]}, [r0], r1
|
||||
bx lr
|
||||
ENDP ; |aom_tm_predictor_4x4_neon|
|
||||
|
||||
;void aom_tm_predictor_8x8_neon (uint8_t *dst, ptrdiff_t y_stride,
|
||||
; const uint8_t *above,
|
||||
; const uint8_t *left)
|
||||
; r0 uint8_t *dst
|
||||
; r1 ptrdiff_t y_stride
|
||||
; r2 const uint8_t *above
|
||||
; r3 const uint8_t *left
|
||||
|
||||
|aom_tm_predictor_8x8_neon| PROC
|
||||
; Load ytop_left = above[-1];
|
||||
sub r12, r2, #1
|
||||
vld1.8 {d0[]}, [r12]
|
||||
|
||||
; preload 8 left
|
||||
vld1.8 {d30}, [r3]
|
||||
|
||||
; Load above 8 pixels
|
||||
vld1.64 {d2}, [r2]
|
||||
|
||||
vmovl.u8 q10, d30
|
||||
|
||||
; Compute above - ytop_left
|
||||
vsubl.u8 q3, d2, d0
|
||||
|
||||
; Load left row by row and compute left + (above - ytop_left)
|
||||
; 1st row and 2nd row
|
||||
vdup.16 q0, d20[0]
|
||||
vdup.16 q1, d20[1]
|
||||
vadd.s16 q0, q3, q0
|
||||
vadd.s16 q1, q3, q1
|
||||
|
||||
; 3rd row and 4th row
|
||||
vdup.16 q8, d20[2]
|
||||
vdup.16 q9, d20[3]
|
||||
vadd.s16 q8, q3, q8
|
||||
vadd.s16 q9, q3, q9
|
||||
|
||||
vqmovun.s16 d0, q0
|
||||
vqmovun.s16 d1, q1
|
||||
vqmovun.s16 d2, q8
|
||||
vqmovun.s16 d3, q9
|
||||
|
||||
vst1.64 {d0}, [r0], r1
|
||||
vst1.64 {d1}, [r0], r1
|
||||
vst1.64 {d2}, [r0], r1
|
||||
vst1.64 {d3}, [r0], r1
|
||||
|
||||
; 5th row and 6th row
|
||||
vdup.16 q0, d21[0]
|
||||
vdup.16 q1, d21[1]
|
||||
vadd.s16 q0, q3, q0
|
||||
vadd.s16 q1, q3, q1
|
||||
|
||||
; 7th row and 8th row
|
||||
vdup.16 q8, d21[2]
|
||||
vdup.16 q9, d21[3]
|
||||
vadd.s16 q8, q3, q8
|
||||
vadd.s16 q9, q3, q9
|
||||
|
||||
vqmovun.s16 d0, q0
|
||||
vqmovun.s16 d1, q1
|
||||
vqmovun.s16 d2, q8
|
||||
vqmovun.s16 d3, q9
|
||||
|
||||
vst1.64 {d0}, [r0], r1
|
||||
vst1.64 {d1}, [r0], r1
|
||||
vst1.64 {d2}, [r0], r1
|
||||
vst1.64 {d3}, [r0], r1
|
||||
|
||||
bx lr
|
||||
ENDP ; |aom_tm_predictor_8x8_neon|
|
||||
|
||||
;void aom_tm_predictor_16x16_neon (uint8_t *dst, ptrdiff_t y_stride,
|
||||
; const uint8_t *above,
|
||||
; const uint8_t *left)
|
||||
; r0 uint8_t *dst
|
||||
; r1 ptrdiff_t y_stride
|
||||
; r2 const uint8_t *above
|
||||
; r3 const uint8_t *left
|
||||
|
||||
|aom_tm_predictor_16x16_neon| PROC
|
||||
; Load ytop_left = above[-1];
|
||||
sub r12, r2, #1
|
||||
vld1.8 {d0[]}, [r12]
|
||||
|
||||
; Load above 8 pixels
|
||||
vld1.8 {q1}, [r2]
|
||||
|
||||
; preload 8 left into r12
|
||||
vld1.8 {d18}, [r3]!
|
||||
|
||||
; Compute above - ytop_left
|
||||
vsubl.u8 q2, d2, d0
|
||||
vsubl.u8 q3, d3, d0
|
||||
|
||||
vmovl.u8 q10, d18
|
||||
|
||||
; Load left row by row and compute left + (above - ytop_left)
|
||||
; Process 8 rows in each single loop and loop 2 times to process 16 rows.
|
||||
mov r2, #2
|
||||
|
||||
loop_16x16_neon
|
||||
; Process two rows.
|
||||
vdup.16 q0, d20[0]
|
||||
vdup.16 q8, d20[1]
|
||||
vadd.s16 q1, q0, q2
|
||||
vadd.s16 q0, q0, q3
|
||||
vadd.s16 q11, q8, q2
|
||||
vadd.s16 q8, q8, q3
|
||||
vqmovun.s16 d2, q1
|
||||
vqmovun.s16 d3, q0
|
||||
vqmovun.s16 d22, q11
|
||||
vqmovun.s16 d23, q8
|
||||
vdup.16 q0, d20[2] ; proload next 2 rows data
|
||||
vdup.16 q8, d20[3]
|
||||
vst1.64 {d2,d3}, [r0], r1
|
||||
vst1.64 {d22,d23}, [r0], r1
|
||||
|
||||
; Process two rows.
|
||||
vadd.s16 q1, q0, q2
|
||||
vadd.s16 q0, q0, q3
|
||||
vadd.s16 q11, q8, q2
|
||||
vadd.s16 q8, q8, q3
|
||||
vqmovun.s16 d2, q1
|
||||
vqmovun.s16 d3, q0
|
||||
vqmovun.s16 d22, q11
|
||||
vqmovun.s16 d23, q8
|
||||
vdup.16 q0, d21[0] ; proload next 2 rows data
|
||||
vdup.16 q8, d21[1]
|
||||
vst1.64 {d2,d3}, [r0], r1
|
||||
vst1.64 {d22,d23}, [r0], r1
|
||||
|
||||
vadd.s16 q1, q0, q2
|
||||
vadd.s16 q0, q0, q3
|
||||
vadd.s16 q11, q8, q2
|
||||
vadd.s16 q8, q8, q3
|
||||
vqmovun.s16 d2, q1
|
||||
vqmovun.s16 d3, q0
|
||||
vqmovun.s16 d22, q11
|
||||
vqmovun.s16 d23, q8
|
||||
vdup.16 q0, d21[2] ; proload next 2 rows data
|
||||
vdup.16 q8, d21[3]
|
||||
vst1.64 {d2,d3}, [r0], r1
|
||||
vst1.64 {d22,d23}, [r0], r1
|
||||
|
||||
|
||||
vadd.s16 q1, q0, q2
|
||||
vadd.s16 q0, q0, q3
|
||||
vadd.s16 q11, q8, q2
|
||||
vadd.s16 q8, q8, q3
|
||||
vqmovun.s16 d2, q1
|
||||
vqmovun.s16 d3, q0
|
||||
vqmovun.s16 d22, q11
|
||||
vqmovun.s16 d23, q8
|
||||
vld1.8 {d18}, [r3]! ; preload 8 left into r12
|
||||
vmovl.u8 q10, d18
|
||||
vst1.64 {d2,d3}, [r0], r1
|
||||
vst1.64 {d22,d23}, [r0], r1
|
||||
|
||||
subs r2, r2, #1
|
||||
bgt loop_16x16_neon
|
||||
|
||||
bx lr
|
||||
ENDP ; |aom_tm_predictor_16x16_neon|
|
||||
|
||||
;void aom_tm_predictor_32x32_neon (uint8_t *dst, ptrdiff_t y_stride,
|
||||
; const uint8_t *above,
|
||||
; const uint8_t *left)
|
||||
; r0 uint8_t *dst
|
||||
; r1 ptrdiff_t y_stride
|
||||
; r2 const uint8_t *above
|
||||
; r3 const uint8_t *left
|
||||
|
||||
|aom_tm_predictor_32x32_neon| PROC
|
||||
; Load ytop_left = above[-1];
|
||||
sub r12, r2, #1
|
||||
vld1.8 {d0[]}, [r12]
|
||||
|
||||
; Load above 32 pixels
|
||||
vld1.8 {q1}, [r2]!
|
||||
vld1.8 {q2}, [r2]
|
||||
|
||||
; preload 8 left pixels
|
||||
vld1.8 {d26}, [r3]!
|
||||
|
||||
; Compute above - ytop_left
|
||||
vsubl.u8 q8, d2, d0
|
||||
vsubl.u8 q9, d3, d0
|
||||
vsubl.u8 q10, d4, d0
|
||||
vsubl.u8 q11, d5, d0
|
||||
|
||||
vmovl.u8 q3, d26
|
||||
|
||||
; Load left row by row and compute left + (above - ytop_left)
|
||||
; Process 8 rows in each single loop and loop 4 times to process 32 rows.
|
||||
mov r2, #4
|
||||
|
||||
loop_32x32_neon
|
||||
; Process two rows.
|
||||
vdup.16 q0, d6[0]
|
||||
vdup.16 q2, d6[1]
|
||||
vadd.s16 q12, q0, q8
|
||||
vadd.s16 q13, q0, q9
|
||||
vadd.s16 q14, q0, q10
|
||||
vadd.s16 q15, q0, q11
|
||||
vqmovun.s16 d0, q12
|
||||
vqmovun.s16 d1, q13
|
||||
vadd.s16 q12, q2, q8
|
||||
vadd.s16 q13, q2, q9
|
||||
vqmovun.s16 d2, q14
|
||||
vqmovun.s16 d3, q15
|
||||
vadd.s16 q14, q2, q10
|
||||
vadd.s16 q15, q2, q11
|
||||
vst1.64 {d0-d3}, [r0], r1
|
||||
vqmovun.s16 d24, q12
|
||||
vqmovun.s16 d25, q13
|
||||
vqmovun.s16 d26, q14
|
||||
vqmovun.s16 d27, q15
|
||||
vdup.16 q1, d6[2]
|
||||
vdup.16 q2, d6[3]
|
||||
vst1.64 {d24-d27}, [r0], r1
|
||||
|
||||
; Process two rows.
|
||||
vadd.s16 q12, q1, q8
|
||||
vadd.s16 q13, q1, q9
|
||||
vadd.s16 q14, q1, q10
|
||||
vadd.s16 q15, q1, q11
|
||||
vqmovun.s16 d0, q12
|
||||
vqmovun.s16 d1, q13
|
||||
vadd.s16 q12, q2, q8
|
||||
vadd.s16 q13, q2, q9
|
||||
vqmovun.s16 d2, q14
|
||||
vqmovun.s16 d3, q15
|
||||
vadd.s16 q14, q2, q10
|
||||
vadd.s16 q15, q2, q11
|
||||
vst1.64 {d0-d3}, [r0], r1
|
||||
vqmovun.s16 d24, q12
|
||||
vqmovun.s16 d25, q13
|
||||
vqmovun.s16 d26, q14
|
||||
vqmovun.s16 d27, q15
|
||||
vdup.16 q0, d7[0]
|
||||
vdup.16 q2, d7[1]
|
||||
vst1.64 {d24-d27}, [r0], r1
|
||||
|
||||
; Process two rows.
|
||||
vadd.s16 q12, q0, q8
|
||||
vadd.s16 q13, q0, q9
|
||||
vadd.s16 q14, q0, q10
|
||||
vadd.s16 q15, q0, q11
|
||||
vqmovun.s16 d0, q12
|
||||
vqmovun.s16 d1, q13
|
||||
vadd.s16 q12, q2, q8
|
||||
vadd.s16 q13, q2, q9
|
||||
vqmovun.s16 d2, q14
|
||||
vqmovun.s16 d3, q15
|
||||
vadd.s16 q14, q2, q10
|
||||
vadd.s16 q15, q2, q11
|
||||
vst1.64 {d0-d3}, [r0], r1
|
||||
vqmovun.s16 d24, q12
|
||||
vqmovun.s16 d25, q13
|
||||
vqmovun.s16 d26, q14
|
||||
vqmovun.s16 d27, q15
|
||||
vdup.16 q0, d7[2]
|
||||
vdup.16 q2, d7[3]
|
||||
vst1.64 {d24-d27}, [r0], r1
|
||||
|
||||
; Process two rows.
|
||||
vadd.s16 q12, q0, q8
|
||||
vadd.s16 q13, q0, q9
|
||||
vadd.s16 q14, q0, q10
|
||||
vadd.s16 q15, q0, q11
|
||||
vqmovun.s16 d0, q12
|
||||
vqmovun.s16 d1, q13
|
||||
vadd.s16 q12, q2, q8
|
||||
vadd.s16 q13, q2, q9
|
||||
vqmovun.s16 d2, q14
|
||||
vqmovun.s16 d3, q15
|
||||
vadd.s16 q14, q2, q10
|
||||
vadd.s16 q15, q2, q11
|
||||
vst1.64 {d0-d3}, [r0], r1
|
||||
vqmovun.s16 d24, q12
|
||||
vqmovun.s16 d25, q13
|
||||
vld1.8 {d0}, [r3]! ; preload 8 left pixels
|
||||
vqmovun.s16 d26, q14
|
||||
vqmovun.s16 d27, q15
|
||||
vmovl.u8 q3, d0
|
||||
vst1.64 {d24-d27}, [r0], r1
|
||||
|
||||
subs r2, r2, #1
|
||||
bgt loop_32x32_neon
|
||||
|
||||
bx lr
|
||||
ENDP ; |aom_tm_predictor_32x32_neon|
|
||||
|
||||
END
|
||||
202
third_party/aom/aom_dsp/arm/loopfilter_16_neon.asm
vendored
Normal file
202
third_party/aom/aom_dsp/arm/loopfilter_16_neon.asm
vendored
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
;
|
||||
; Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
;
|
||||
; This source code is subject to the terms of the BSD 2 Clause License and
|
||||
; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
; was not distributed with this source code in the LICENSE file, you can
|
||||
; obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
; Media Patent License 1.0 was not distributed with this source code in the
|
||||
; PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
;
|
||||
|
||||
;
|
||||
|
||||
EXPORT |aom_lpf_horizontal_4_dual_neon|
|
||||
ARM
|
||||
|
||||
AREA ||.text||, CODE, READONLY, ALIGN=2
|
||||
|
||||
;void aom_lpf_horizontal_4_dual_neon(uint8_t *s, int p,
|
||||
; const uint8_t *blimit0,
|
||||
; const uint8_t *limit0,
|
||||
; const uint8_t *thresh0,
|
||||
; const uint8_t *blimit1,
|
||||
; const uint8_t *limit1,
|
||||
; const uint8_t *thresh1)
|
||||
; r0 uint8_t *s,
|
||||
; r1 int p,
|
||||
; r2 const uint8_t *blimit0,
|
||||
; r3 const uint8_t *limit0,
|
||||
; sp const uint8_t *thresh0,
|
||||
; sp+4 const uint8_t *blimit1,
|
||||
; sp+8 const uint8_t *limit1,
|
||||
; sp+12 const uint8_t *thresh1,
|
||||
|
||||
|aom_lpf_horizontal_4_dual_neon| PROC
|
||||
push {lr}
|
||||
|
||||
ldr r12, [sp, #4] ; load thresh0
|
||||
vld1.8 {d0}, [r2] ; load blimit0 to first half q
|
||||
vld1.8 {d2}, [r3] ; load limit0 to first half q
|
||||
|
||||
add r1, r1, r1 ; double pitch
|
||||
ldr r2, [sp, #8] ; load blimit1
|
||||
|
||||
vld1.8 {d4}, [r12] ; load thresh0 to first half q
|
||||
|
||||
ldr r3, [sp, #12] ; load limit1
|
||||
ldr r12, [sp, #16] ; load thresh1
|
||||
vld1.8 {d1}, [r2] ; load blimit1 to 2nd half q
|
||||
|
||||
sub r2, r0, r1, lsl #1 ; s[-4 * p]
|
||||
|
||||
vld1.8 {d3}, [r3] ; load limit1 to 2nd half q
|
||||
vld1.8 {d5}, [r12] ; load thresh1 to 2nd half q
|
||||
|
||||
vpush {d8-d15} ; save neon registers
|
||||
|
||||
add r3, r2, r1, lsr #1 ; s[-3 * p]
|
||||
|
||||
vld1.u8 {q3}, [r2@64], r1 ; p3
|
||||
vld1.u8 {q4}, [r3@64], r1 ; p2
|
||||
vld1.u8 {q5}, [r2@64], r1 ; p1
|
||||
vld1.u8 {q6}, [r3@64], r1 ; p0
|
||||
vld1.u8 {q7}, [r2@64], r1 ; q0
|
||||
vld1.u8 {q8}, [r3@64], r1 ; q1
|
||||
vld1.u8 {q9}, [r2@64] ; q2
|
||||
vld1.u8 {q10}, [r3@64] ; q3
|
||||
|
||||
sub r2, r2, r1, lsl #1
|
||||
sub r3, r3, r1, lsl #1
|
||||
|
||||
bl aom_loop_filter_neon_16
|
||||
|
||||
vst1.u8 {q5}, [r2@64], r1 ; store op1
|
||||
vst1.u8 {q6}, [r3@64], r1 ; store op0
|
||||
vst1.u8 {q7}, [r2@64], r1 ; store oq0
|
||||
vst1.u8 {q8}, [r3@64], r1 ; store oq1
|
||||
|
||||
vpop {d8-d15} ; restore neon registers
|
||||
|
||||
pop {pc}
|
||||
ENDP ; |aom_lpf_horizontal_4_dual_neon|
|
||||
|
||||
; void aom_loop_filter_neon_16();
|
||||
; This is a helper function for the loopfilters. The invidual functions do the
|
||||
; necessary load, transpose (if necessary) and store. This function uses
|
||||
; registers d8-d15, so the calling function must save those registers.
|
||||
;
|
||||
; r0-r3, r12 PRESERVE
|
||||
; q0 blimit
|
||||
; q1 limit
|
||||
; q2 thresh
|
||||
; q3 p3
|
||||
; q4 p2
|
||||
; q5 p1
|
||||
; q6 p0
|
||||
; q7 q0
|
||||
; q8 q1
|
||||
; q9 q2
|
||||
; q10 q3
|
||||
;
|
||||
; Outputs:
|
||||
; q5 op1
|
||||
; q6 op0
|
||||
; q7 oq0
|
||||
; q8 oq1
|
||||
|aom_loop_filter_neon_16| PROC
|
||||
|
||||
; filter_mask
|
||||
vabd.u8 q11, q3, q4 ; m1 = abs(p3 - p2)
|
||||
vabd.u8 q12, q4, q5 ; m2 = abs(p2 - p1)
|
||||
vabd.u8 q13, q5, q6 ; m3 = abs(p1 - p0)
|
||||
vabd.u8 q14, q8, q7 ; m4 = abs(q1 - q0)
|
||||
vabd.u8 q3, q9, q8 ; m5 = abs(q2 - q1)
|
||||
vabd.u8 q4, q10, q9 ; m6 = abs(q3 - q2)
|
||||
|
||||
; only compare the largest value to limit
|
||||
vmax.u8 q11, q11, q12 ; m7 = max(m1, m2)
|
||||
vmax.u8 q12, q13, q14 ; m8 = max(m3, m4)
|
||||
|
||||
vabd.u8 q9, q6, q7 ; abs(p0 - q0)
|
||||
|
||||
vmax.u8 q3, q3, q4 ; m9 = max(m5, m6)
|
||||
|
||||
vmov.u8 q10, #0x80
|
||||
|
||||
vmax.u8 q15, q11, q12 ; m10 = max(m7, m8)
|
||||
|
||||
vcgt.u8 q13, q13, q2 ; (abs(p1 - p0) > thresh)*-1
|
||||
vcgt.u8 q14, q14, q2 ; (abs(q1 - q0) > thresh)*-1
|
||||
vmax.u8 q15, q15, q3 ; m11 = max(m10, m9)
|
||||
|
||||
vabd.u8 q2, q5, q8 ; a = abs(p1 - q1)
|
||||
vqadd.u8 q9, q9, q9 ; b = abs(p0 - q0) * 2
|
||||
|
||||
veor q7, q7, q10 ; qs0
|
||||
|
||||
vcge.u8 q15, q1, q15 ; abs(m11) > limit
|
||||
|
||||
vshr.u8 q2, q2, #1 ; a = a / 2
|
||||
veor q6, q6, q10 ; ps0
|
||||
|
||||
veor q5, q5, q10 ; ps1
|
||||
vqadd.u8 q9, q9, q2 ; a = b + a
|
||||
|
||||
veor q8, q8, q10 ; qs1
|
||||
|
||||
vmov.u16 q4, #3
|
||||
|
||||
vsubl.s8 q2, d14, d12 ; ( qs0 - ps0)
|
||||
vsubl.s8 q11, d15, d13
|
||||
|
||||
vcge.u8 q9, q0, q9 ; a > blimit
|
||||
|
||||
vqsub.s8 q1, q5, q8 ; filter = clamp(ps1-qs1)
|
||||
vorr q14, q13, q14 ; hev
|
||||
|
||||
vmul.i16 q2, q2, q4 ; 3 * ( qs0 - ps0)
|
||||
vmul.i16 q11, q11, q4
|
||||
|
||||
vand q1, q1, q14 ; filter &= hev
|
||||
vand q15, q15, q9 ; mask
|
||||
|
||||
vmov.u8 q4, #3
|
||||
|
||||
vaddw.s8 q2, q2, d2 ; filter + 3 * (qs0 - ps0)
|
||||
vaddw.s8 q11, q11, d3
|
||||
|
||||
vmov.u8 q9, #4
|
||||
|
||||
; filter = clamp(filter + 3 * ( qs0 - ps0))
|
||||
vqmovn.s16 d2, q2
|
||||
vqmovn.s16 d3, q11
|
||||
vand q1, q1, q15 ; filter &= mask
|
||||
|
||||
vqadd.s8 q2, q1, q4 ; filter2 = clamp(filter+3)
|
||||
vqadd.s8 q1, q1, q9 ; filter1 = clamp(filter+4)
|
||||
vshr.s8 q2, q2, #3 ; filter2 >>= 3
|
||||
vshr.s8 q1, q1, #3 ; filter1 >>= 3
|
||||
|
||||
|
||||
vqadd.s8 q11, q6, q2 ; u = clamp(ps0 + filter2)
|
||||
vqsub.s8 q0, q7, q1 ; u = clamp(qs0 - filter1)
|
||||
|
||||
; outer tap adjustments
|
||||
vrshr.s8 q1, q1, #1 ; filter = ++filter1 >> 1
|
||||
|
||||
veor q7, q0, q10 ; *oq0 = u^0x80
|
||||
|
||||
vbic q1, q1, q14 ; filter &= ~hev
|
||||
|
||||
vqadd.s8 q13, q5, q1 ; u = clamp(ps1 + filter)
|
||||
vqsub.s8 q12, q8, q1 ; u = clamp(qs1 - filter)
|
||||
|
||||
veor q6, q11, q10 ; *op0 = u^0x80
|
||||
veor q5, q13, q10 ; *op1 = u^0x80
|
||||
veor q8, q12, q10 ; *oq1 = u^0x80
|
||||
|
||||
bx lr
|
||||
ENDP ; |aom_loop_filter_neon_16|
|
||||
|
||||
END
|
||||
174
third_party/aom/aom_dsp/arm/loopfilter_16_neon.c
vendored
Normal file
174
third_party/aom/aom_dsp/arm/loopfilter_16_neon.c
vendored
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <arm_neon.h>
|
||||
|
||||
#include "./aom_dsp_rtcd.h"
|
||||
#include "./aom_config.h"
|
||||
#include "aom/aom_integer.h"
|
||||
|
||||
static INLINE void loop_filter_neon_16(uint8x16_t qblimit, // blimit
|
||||
uint8x16_t qlimit, // limit
|
||||
uint8x16_t qthresh, // thresh
|
||||
uint8x16_t q3, // p3
|
||||
uint8x16_t q4, // p2
|
||||
uint8x16_t q5, // p1
|
||||
uint8x16_t q6, // p0
|
||||
uint8x16_t q7, // q0
|
||||
uint8x16_t q8, // q1
|
||||
uint8x16_t q9, // q2
|
||||
uint8x16_t q10, // q3
|
||||
uint8x16_t *q5r, // p1
|
||||
uint8x16_t *q6r, // p0
|
||||
uint8x16_t *q7r, // q0
|
||||
uint8x16_t *q8r) { // q1
|
||||
uint8x16_t q1u8, q2u8, q11u8, q12u8, q13u8, q14u8, q15u8;
|
||||
int16x8_t q2s16, q11s16;
|
||||
uint16x8_t q4u16;
|
||||
int8x16_t q0s8, q1s8, q2s8, q11s8, q12s8, q13s8;
|
||||
int8x8_t d2s8, d3s8;
|
||||
|
||||
q11u8 = vabdq_u8(q3, q4);
|
||||
q12u8 = vabdq_u8(q4, q5);
|
||||
q13u8 = vabdq_u8(q5, q6);
|
||||
q14u8 = vabdq_u8(q8, q7);
|
||||
q3 = vabdq_u8(q9, q8);
|
||||
q4 = vabdq_u8(q10, q9);
|
||||
|
||||
q11u8 = vmaxq_u8(q11u8, q12u8);
|
||||
q12u8 = vmaxq_u8(q13u8, q14u8);
|
||||
q3 = vmaxq_u8(q3, q4);
|
||||
q15u8 = vmaxq_u8(q11u8, q12u8);
|
||||
|
||||
q9 = vabdq_u8(q6, q7);
|
||||
|
||||
// aom_hevmask
|
||||
q13u8 = vcgtq_u8(q13u8, qthresh);
|
||||
q14u8 = vcgtq_u8(q14u8, qthresh);
|
||||
q15u8 = vmaxq_u8(q15u8, q3);
|
||||
|
||||
q2u8 = vabdq_u8(q5, q8);
|
||||
q9 = vqaddq_u8(q9, q9);
|
||||
|
||||
q15u8 = vcgeq_u8(qlimit, q15u8);
|
||||
|
||||
// aom_filter() function
|
||||
// convert to signed
|
||||
q10 = vdupq_n_u8(0x80);
|
||||
q8 = veorq_u8(q8, q10);
|
||||
q7 = veorq_u8(q7, q10);
|
||||
q6 = veorq_u8(q6, q10);
|
||||
q5 = veorq_u8(q5, q10);
|
||||
|
||||
q2u8 = vshrq_n_u8(q2u8, 1);
|
||||
q9 = vqaddq_u8(q9, q2u8);
|
||||
|
||||
q2s16 = vsubl_s8(vget_low_s8(vreinterpretq_s8_u8(q7)),
|
||||
vget_low_s8(vreinterpretq_s8_u8(q6)));
|
||||
q11s16 = vsubl_s8(vget_high_s8(vreinterpretq_s8_u8(q7)),
|
||||
vget_high_s8(vreinterpretq_s8_u8(q6)));
|
||||
|
||||
q9 = vcgeq_u8(qblimit, q9);
|
||||
|
||||
q1s8 = vqsubq_s8(vreinterpretq_s8_u8(q5), vreinterpretq_s8_u8(q8));
|
||||
|
||||
q14u8 = vorrq_u8(q13u8, q14u8);
|
||||
|
||||
q4u16 = vdupq_n_u16(3);
|
||||
q2s16 = vmulq_s16(q2s16, vreinterpretq_s16_u16(q4u16));
|
||||
q11s16 = vmulq_s16(q11s16, vreinterpretq_s16_u16(q4u16));
|
||||
|
||||
q1u8 = vandq_u8(vreinterpretq_u8_s8(q1s8), q14u8);
|
||||
q15u8 = vandq_u8(q15u8, q9);
|
||||
|
||||
q1s8 = vreinterpretq_s8_u8(q1u8);
|
||||
q2s16 = vaddw_s8(q2s16, vget_low_s8(q1s8));
|
||||
q11s16 = vaddw_s8(q11s16, vget_high_s8(q1s8));
|
||||
|
||||
q4 = vdupq_n_u8(3);
|
||||
q9 = vdupq_n_u8(4);
|
||||
// aom_filter = clamp(aom_filter + 3 * ( qs0 - ps0))
|
||||
d2s8 = vqmovn_s16(q2s16);
|
||||
d3s8 = vqmovn_s16(q11s16);
|
||||
q1s8 = vcombine_s8(d2s8, d3s8);
|
||||
q1u8 = vandq_u8(vreinterpretq_u8_s8(q1s8), q15u8);
|
||||
q1s8 = vreinterpretq_s8_u8(q1u8);
|
||||
|
||||
q2s8 = vqaddq_s8(q1s8, vreinterpretq_s8_u8(q4));
|
||||
q1s8 = vqaddq_s8(q1s8, vreinterpretq_s8_u8(q9));
|
||||
q2s8 = vshrq_n_s8(q2s8, 3);
|
||||
q1s8 = vshrq_n_s8(q1s8, 3);
|
||||
|
||||
q11s8 = vqaddq_s8(vreinterpretq_s8_u8(q6), q2s8);
|
||||
q0s8 = vqsubq_s8(vreinterpretq_s8_u8(q7), q1s8);
|
||||
|
||||
q1s8 = vrshrq_n_s8(q1s8, 1);
|
||||
q1s8 = vbicq_s8(q1s8, vreinterpretq_s8_u8(q14u8));
|
||||
|
||||
q13s8 = vqaddq_s8(vreinterpretq_s8_u8(q5), q1s8);
|
||||
q12s8 = vqsubq_s8(vreinterpretq_s8_u8(q8), q1s8);
|
||||
|
||||
*q8r = veorq_u8(vreinterpretq_u8_s8(q12s8), q10);
|
||||
*q7r = veorq_u8(vreinterpretq_u8_s8(q0s8), q10);
|
||||
*q6r = veorq_u8(vreinterpretq_u8_s8(q11s8), q10);
|
||||
*q5r = veorq_u8(vreinterpretq_u8_s8(q13s8), q10);
|
||||
return;
|
||||
}
|
||||
|
||||
void aom_lpf_horizontal_4_dual_neon(
|
||||
uint8_t *s, int p /* pitch */, const uint8_t *blimit0,
|
||||
const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1,
|
||||
const uint8_t *limit1, const uint8_t *thresh1) {
|
||||
uint8x8_t dblimit0, dlimit0, dthresh0, dblimit1, dlimit1, dthresh1;
|
||||
uint8x16_t qblimit, qlimit, qthresh;
|
||||
uint8x16_t q3u8, q4u8, q5u8, q6u8, q7u8, q8u8, q9u8, q10u8;
|
||||
|
||||
dblimit0 = vld1_u8(blimit0);
|
||||
dlimit0 = vld1_u8(limit0);
|
||||
dthresh0 = vld1_u8(thresh0);
|
||||
dblimit1 = vld1_u8(blimit1);
|
||||
dlimit1 = vld1_u8(limit1);
|
||||
dthresh1 = vld1_u8(thresh1);
|
||||
qblimit = vcombine_u8(dblimit0, dblimit1);
|
||||
qlimit = vcombine_u8(dlimit0, dlimit1);
|
||||
qthresh = vcombine_u8(dthresh0, dthresh1);
|
||||
|
||||
s -= (p << 2);
|
||||
|
||||
q3u8 = vld1q_u8(s);
|
||||
s += p;
|
||||
q4u8 = vld1q_u8(s);
|
||||
s += p;
|
||||
q5u8 = vld1q_u8(s);
|
||||
s += p;
|
||||
q6u8 = vld1q_u8(s);
|
||||
s += p;
|
||||
q7u8 = vld1q_u8(s);
|
||||
s += p;
|
||||
q8u8 = vld1q_u8(s);
|
||||
s += p;
|
||||
q9u8 = vld1q_u8(s);
|
||||
s += p;
|
||||
q10u8 = vld1q_u8(s);
|
||||
|
||||
loop_filter_neon_16(qblimit, qlimit, qthresh, q3u8, q4u8, q5u8, q6u8, q7u8,
|
||||
q8u8, q9u8, q10u8, &q5u8, &q6u8, &q7u8, &q8u8);
|
||||
|
||||
s -= (p * 5);
|
||||
vst1q_u8(s, q5u8);
|
||||
s += p;
|
||||
vst1q_u8(s, q6u8);
|
||||
s += p;
|
||||
vst1q_u8(s, q7u8);
|
||||
s += p;
|
||||
vst1q_u8(s, q8u8);
|
||||
return;
|
||||
}
|
||||
252
third_party/aom/aom_dsp/arm/loopfilter_4_neon.asm
vendored
Normal file
252
third_party/aom/aom_dsp/arm/loopfilter_4_neon.asm
vendored
Normal file
|
|
@ -0,0 +1,252 @@
|
|||
;
|
||||
; Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
;
|
||||
; This source code is subject to the terms of the BSD 2 Clause License and
|
||||
; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
; was not distributed with this source code in the LICENSE file, you can
|
||||
; obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
; Media Patent License 1.0 was not distributed with this source code in the
|
||||
; PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
;
|
||||
|
||||
;
|
||||
|
||||
EXPORT |aom_lpf_horizontal_4_neon|
|
||||
EXPORT |aom_lpf_vertical_4_neon|
|
||||
ARM
|
||||
|
||||
AREA ||.text||, CODE, READONLY, ALIGN=2
|
||||
|
||||
; Currently aom only works on iterations 8 at a time. The aom loop filter
|
||||
; works on 16 iterations at a time.
|
||||
;
|
||||
; void aom_lpf_horizontal_4_neon(uint8_t *s,
|
||||
; int p /* pitch */,
|
||||
; const uint8_t *blimit,
|
||||
; const uint8_t *limit,
|
||||
; const uint8_t *thresh)
|
||||
;
|
||||
; r0 uint8_t *s,
|
||||
; r1 int p, /* pitch */
|
||||
; r2 const uint8_t *blimit,
|
||||
; r3 const uint8_t *limit,
|
||||
; sp const uint8_t *thresh,
|
||||
|aom_lpf_horizontal_4_neon| PROC
|
||||
push {lr}
|
||||
|
||||
vld1.8 {d0[]}, [r2] ; duplicate *blimit
|
||||
ldr r2, [sp, #4] ; load thresh
|
||||
add r1, r1, r1 ; double pitch
|
||||
|
||||
vld1.8 {d1[]}, [r3] ; duplicate *limit
|
||||
vld1.8 {d2[]}, [r2] ; duplicate *thresh
|
||||
|
||||
sub r2, r0, r1, lsl #1 ; move src pointer down by 4 lines
|
||||
add r3, r2, r1, lsr #1 ; set to 3 lines down
|
||||
|
||||
vld1.u8 {d3}, [r2@64], r1 ; p3
|
||||
vld1.u8 {d4}, [r3@64], r1 ; p2
|
||||
vld1.u8 {d5}, [r2@64], r1 ; p1
|
||||
vld1.u8 {d6}, [r3@64], r1 ; p0
|
||||
vld1.u8 {d7}, [r2@64], r1 ; q0
|
||||
vld1.u8 {d16}, [r3@64], r1 ; q1
|
||||
vld1.u8 {d17}, [r2@64] ; q2
|
||||
vld1.u8 {d18}, [r3@64] ; q3
|
||||
|
||||
sub r2, r2, r1, lsl #1
|
||||
sub r3, r3, r1, lsl #1
|
||||
|
||||
bl aom_loop_filter_neon
|
||||
|
||||
vst1.u8 {d4}, [r2@64], r1 ; store op1
|
||||
vst1.u8 {d5}, [r3@64], r1 ; store op0
|
||||
vst1.u8 {d6}, [r2@64], r1 ; store oq0
|
||||
vst1.u8 {d7}, [r3@64], r1 ; store oq1
|
||||
|
||||
pop {pc}
|
||||
ENDP ; |aom_lpf_horizontal_4_neon|
|
||||
|
||||
; Currently aom only works on iterations 8 at a time. The aom loop filter
|
||||
; works on 16 iterations at a time.
|
||||
;
|
||||
; void aom_lpf_vertical_4_neon(uint8_t *s,
|
||||
; int p /* pitch */,
|
||||
; const uint8_t *blimit,
|
||||
; const uint8_t *limit,
|
||||
; const uint8_t *thresh)
|
||||
;
|
||||
; r0 uint8_t *s,
|
||||
; r1 int p, /* pitch */
|
||||
; r2 const uint8_t *blimit,
|
||||
; r3 const uint8_t *limit,
|
||||
; sp const uint8_t *thresh,
|
||||
|aom_lpf_vertical_4_neon| PROC
|
||||
push {lr}
|
||||
|
||||
vld1.8 {d0[]}, [r2] ; duplicate *blimit
|
||||
vld1.8 {d1[]}, [r3] ; duplicate *limit
|
||||
|
||||
ldr r3, [sp, #4] ; load thresh
|
||||
sub r2, r0, #4 ; move s pointer down by 4 columns
|
||||
|
||||
vld1.8 {d2[]}, [r3] ; duplicate *thresh
|
||||
|
||||
vld1.u8 {d3}, [r2], r1 ; load s data
|
||||
vld1.u8 {d4}, [r2], r1
|
||||
vld1.u8 {d5}, [r2], r1
|
||||
vld1.u8 {d6}, [r2], r1
|
||||
vld1.u8 {d7}, [r2], r1
|
||||
vld1.u8 {d16}, [r2], r1
|
||||
vld1.u8 {d17}, [r2], r1
|
||||
vld1.u8 {d18}, [r2]
|
||||
|
||||
;transpose to 8x16 matrix
|
||||
vtrn.32 d3, d7
|
||||
vtrn.32 d4, d16
|
||||
vtrn.32 d5, d17
|
||||
vtrn.32 d6, d18
|
||||
|
||||
vtrn.16 d3, d5
|
||||
vtrn.16 d4, d6
|
||||
vtrn.16 d7, d17
|
||||
vtrn.16 d16, d18
|
||||
|
||||
vtrn.8 d3, d4
|
||||
vtrn.8 d5, d6
|
||||
vtrn.8 d7, d16
|
||||
vtrn.8 d17, d18
|
||||
|
||||
bl aom_loop_filter_neon
|
||||
|
||||
sub r0, r0, #2
|
||||
|
||||
;store op1, op0, oq0, oq1
|
||||
vst4.8 {d4[0], d5[0], d6[0], d7[0]}, [r0], r1
|
||||
vst4.8 {d4[1], d5[1], d6[1], d7[1]}, [r0], r1
|
||||
vst4.8 {d4[2], d5[2], d6[2], d7[2]}, [r0], r1
|
||||
vst4.8 {d4[3], d5[3], d6[3], d7[3]}, [r0], r1
|
||||
vst4.8 {d4[4], d5[4], d6[4], d7[4]}, [r0], r1
|
||||
vst4.8 {d4[5], d5[5], d6[5], d7[5]}, [r0], r1
|
||||
vst4.8 {d4[6], d5[6], d6[6], d7[6]}, [r0], r1
|
||||
vst4.8 {d4[7], d5[7], d6[7], d7[7]}, [r0]
|
||||
|
||||
pop {pc}
|
||||
ENDP ; |aom_lpf_vertical_4_neon|
|
||||
|
||||
; void aom_loop_filter_neon();
|
||||
; This is a helper function for the loopfilters. The invidual functions do the
|
||||
; necessary load, transpose (if necessary) and store. The function does not use
|
||||
; registers d8-d15.
|
||||
;
|
||||
; Inputs:
|
||||
; r0-r3, r12 PRESERVE
|
||||
; d0 blimit
|
||||
; d1 limit
|
||||
; d2 thresh
|
||||
; d3 p3
|
||||
; d4 p2
|
||||
; d5 p1
|
||||
; d6 p0
|
||||
; d7 q0
|
||||
; d16 q1
|
||||
; d17 q2
|
||||
; d18 q3
|
||||
;
|
||||
; Outputs:
|
||||
; d4 op1
|
||||
; d5 op0
|
||||
; d6 oq0
|
||||
; d7 oq1
|
||||
|aom_loop_filter_neon| PROC
|
||||
; filter_mask
|
||||
vabd.u8 d19, d3, d4 ; m1 = abs(p3 - p2)
|
||||
vabd.u8 d20, d4, d5 ; m2 = abs(p2 - p1)
|
||||
vabd.u8 d21, d5, d6 ; m3 = abs(p1 - p0)
|
||||
vabd.u8 d22, d16, d7 ; m4 = abs(q1 - q0)
|
||||
vabd.u8 d3, d17, d16 ; m5 = abs(q2 - q1)
|
||||
vabd.u8 d4, d18, d17 ; m6 = abs(q3 - q2)
|
||||
|
||||
; only compare the largest value to limit
|
||||
vmax.u8 d19, d19, d20 ; m1 = max(m1, m2)
|
||||
vmax.u8 d20, d21, d22 ; m2 = max(m3, m4)
|
||||
|
||||
vabd.u8 d17, d6, d7 ; abs(p0 - q0)
|
||||
|
||||
vmax.u8 d3, d3, d4 ; m3 = max(m5, m6)
|
||||
|
||||
vmov.u8 d18, #0x80
|
||||
|
||||
vmax.u8 d23, d19, d20 ; m1 = max(m1, m2)
|
||||
|
||||
; hevmask
|
||||
vcgt.u8 d21, d21, d2 ; (abs(p1 - p0) > thresh)*-1
|
||||
vcgt.u8 d22, d22, d2 ; (abs(q1 - q0) > thresh)*-1
|
||||
vmax.u8 d23, d23, d3 ; m1 = max(m1, m3)
|
||||
|
||||
vabd.u8 d28, d5, d16 ; a = abs(p1 - q1)
|
||||
vqadd.u8 d17, d17, d17 ; b = abs(p0 - q0) * 2
|
||||
|
||||
veor d7, d7, d18 ; qs0
|
||||
|
||||
vcge.u8 d23, d1, d23 ; abs(m1) > limit
|
||||
|
||||
; filter() function
|
||||
; convert to signed
|
||||
|
||||
vshr.u8 d28, d28, #1 ; a = a / 2
|
||||
veor d6, d6, d18 ; ps0
|
||||
|
||||
veor d5, d5, d18 ; ps1
|
||||
vqadd.u8 d17, d17, d28 ; a = b + a
|
||||
|
||||
veor d16, d16, d18 ; qs1
|
||||
|
||||
vmov.u8 d19, #3
|
||||
|
||||
vsub.s8 d28, d7, d6 ; ( qs0 - ps0)
|
||||
|
||||
vcge.u8 d17, d0, d17 ; a > blimit
|
||||
|
||||
vqsub.s8 d27, d5, d16 ; filter = clamp(ps1-qs1)
|
||||
vorr d22, d21, d22 ; hevmask
|
||||
|
||||
vmull.s8 q12, d28, d19 ; 3 * ( qs0 - ps0)
|
||||
|
||||
vand d27, d27, d22 ; filter &= hev
|
||||
vand d23, d23, d17 ; filter_mask
|
||||
|
||||
vaddw.s8 q12, q12, d27 ; filter + 3 * (qs0 - ps0)
|
||||
|
||||
vmov.u8 d17, #4
|
||||
|
||||
; filter = clamp(filter + 3 * ( qs0 - ps0))
|
||||
vqmovn.s16 d27, q12
|
||||
|
||||
vand d27, d27, d23 ; filter &= mask
|
||||
|
||||
vqadd.s8 d28, d27, d19 ; filter2 = clamp(filter+3)
|
||||
vqadd.s8 d27, d27, d17 ; filter1 = clamp(filter+4)
|
||||
vshr.s8 d28, d28, #3 ; filter2 >>= 3
|
||||
vshr.s8 d27, d27, #3 ; filter1 >>= 3
|
||||
|
||||
vqadd.s8 d19, d6, d28 ; u = clamp(ps0 + filter2)
|
||||
vqsub.s8 d26, d7, d27 ; u = clamp(qs0 - filter1)
|
||||
|
||||
; outer tap adjustments
|
||||
vrshr.s8 d27, d27, #1 ; filter = ++filter1 >> 1
|
||||
|
||||
veor d6, d26, d18 ; *oq0 = u^0x80
|
||||
|
||||
vbic d27, d27, d22 ; filter &= ~hev
|
||||
|
||||
vqadd.s8 d21, d5, d27 ; u = clamp(ps1 + filter)
|
||||
vqsub.s8 d20, d16, d27 ; u = clamp(qs1 - filter)
|
||||
|
||||
veor d5, d19, d18 ; *op0 = u^0x80
|
||||
veor d4, d21, d18 ; *op1 = u^0x80
|
||||
veor d7, d20, d18 ; *oq1 = u^0x80
|
||||
|
||||
bx lr
|
||||
ENDP ; |aom_loop_filter_neon|
|
||||
|
||||
END
|
||||
250
third_party/aom/aom_dsp/arm/loopfilter_4_neon.c
vendored
Normal file
250
third_party/aom/aom_dsp/arm/loopfilter_4_neon.c
vendored
Normal file
|
|
@ -0,0 +1,250 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <arm_neon.h>
|
||||
|
||||
#include "./aom_dsp_rtcd.h"
|
||||
|
||||
static INLINE void loop_filter_neon(uint8x8_t dblimit, // flimit
|
||||
uint8x8_t dlimit, // limit
|
||||
uint8x8_t dthresh, // thresh
|
||||
uint8x8_t d3u8, // p3
|
||||
uint8x8_t d4u8, // p2
|
||||
uint8x8_t d5u8, // p1
|
||||
uint8x8_t d6u8, // p0
|
||||
uint8x8_t d7u8, // q0
|
||||
uint8x8_t d16u8, // q1
|
||||
uint8x8_t d17u8, // q2
|
||||
uint8x8_t d18u8, // q3
|
||||
uint8x8_t *d4ru8, // p1
|
||||
uint8x8_t *d5ru8, // p0
|
||||
uint8x8_t *d6ru8, // q0
|
||||
uint8x8_t *d7ru8) { // q1
|
||||
uint8x8_t d19u8, d20u8, d21u8, d22u8, d23u8, d27u8, d28u8;
|
||||
int16x8_t q12s16;
|
||||
int8x8_t d19s8, d20s8, d21s8, d26s8, d27s8, d28s8;
|
||||
|
||||
d19u8 = vabd_u8(d3u8, d4u8);
|
||||
d20u8 = vabd_u8(d4u8, d5u8);
|
||||
d21u8 = vabd_u8(d5u8, d6u8);
|
||||
d22u8 = vabd_u8(d16u8, d7u8);
|
||||
d3u8 = vabd_u8(d17u8, d16u8);
|
||||
d4u8 = vabd_u8(d18u8, d17u8);
|
||||
|
||||
d19u8 = vmax_u8(d19u8, d20u8);
|
||||
d20u8 = vmax_u8(d21u8, d22u8);
|
||||
d3u8 = vmax_u8(d3u8, d4u8);
|
||||
d23u8 = vmax_u8(d19u8, d20u8);
|
||||
|
||||
d17u8 = vabd_u8(d6u8, d7u8);
|
||||
|
||||
d21u8 = vcgt_u8(d21u8, dthresh);
|
||||
d22u8 = vcgt_u8(d22u8, dthresh);
|
||||
d23u8 = vmax_u8(d23u8, d3u8);
|
||||
|
||||
d28u8 = vabd_u8(d5u8, d16u8);
|
||||
d17u8 = vqadd_u8(d17u8, d17u8);
|
||||
|
||||
d23u8 = vcge_u8(dlimit, d23u8);
|
||||
|
||||
d18u8 = vdup_n_u8(0x80);
|
||||
d5u8 = veor_u8(d5u8, d18u8);
|
||||
d6u8 = veor_u8(d6u8, d18u8);
|
||||
d7u8 = veor_u8(d7u8, d18u8);
|
||||
d16u8 = veor_u8(d16u8, d18u8);
|
||||
|
||||
d28u8 = vshr_n_u8(d28u8, 1);
|
||||
d17u8 = vqadd_u8(d17u8, d28u8);
|
||||
|
||||
d19u8 = vdup_n_u8(3);
|
||||
|
||||
d28s8 = vsub_s8(vreinterpret_s8_u8(d7u8), vreinterpret_s8_u8(d6u8));
|
||||
|
||||
d17u8 = vcge_u8(dblimit, d17u8);
|
||||
|
||||
d27s8 = vqsub_s8(vreinterpret_s8_u8(d5u8), vreinterpret_s8_u8(d16u8));
|
||||
|
||||
d22u8 = vorr_u8(d21u8, d22u8);
|
||||
|
||||
q12s16 = vmull_s8(d28s8, vreinterpret_s8_u8(d19u8));
|
||||
|
||||
d27u8 = vand_u8(vreinterpret_u8_s8(d27s8), d22u8);
|
||||
d23u8 = vand_u8(d23u8, d17u8);
|
||||
|
||||
q12s16 = vaddw_s8(q12s16, vreinterpret_s8_u8(d27u8));
|
||||
|
||||
d17u8 = vdup_n_u8(4);
|
||||
|
||||
d27s8 = vqmovn_s16(q12s16);
|
||||
d27u8 = vand_u8(vreinterpret_u8_s8(d27s8), d23u8);
|
||||
d27s8 = vreinterpret_s8_u8(d27u8);
|
||||
|
||||
d28s8 = vqadd_s8(d27s8, vreinterpret_s8_u8(d19u8));
|
||||
d27s8 = vqadd_s8(d27s8, vreinterpret_s8_u8(d17u8));
|
||||
d28s8 = vshr_n_s8(d28s8, 3);
|
||||
d27s8 = vshr_n_s8(d27s8, 3);
|
||||
|
||||
d19s8 = vqadd_s8(vreinterpret_s8_u8(d6u8), d28s8);
|
||||
d26s8 = vqsub_s8(vreinterpret_s8_u8(d7u8), d27s8);
|
||||
|
||||
d27s8 = vrshr_n_s8(d27s8, 1);
|
||||
d27s8 = vbic_s8(d27s8, vreinterpret_s8_u8(d22u8));
|
||||
|
||||
d21s8 = vqadd_s8(vreinterpret_s8_u8(d5u8), d27s8);
|
||||
d20s8 = vqsub_s8(vreinterpret_s8_u8(d16u8), d27s8);
|
||||
|
||||
*d4ru8 = veor_u8(vreinterpret_u8_s8(d21s8), d18u8);
|
||||
*d5ru8 = veor_u8(vreinterpret_u8_s8(d19s8), d18u8);
|
||||
*d6ru8 = veor_u8(vreinterpret_u8_s8(d26s8), d18u8);
|
||||
*d7ru8 = veor_u8(vreinterpret_u8_s8(d20s8), d18u8);
|
||||
return;
|
||||
}
|
||||
|
||||
void aom_lpf_horizontal_4_neon(uint8_t *src, int pitch, const uint8_t *blimit,
|
||||
const uint8_t *limit, const uint8_t *thresh) {
|
||||
int i;
|
||||
uint8_t *s, *psrc;
|
||||
uint8x8_t dblimit, dlimit, dthresh;
|
||||
uint8x8_t d3u8, d4u8, d5u8, d6u8, d7u8, d16u8, d17u8, d18u8;
|
||||
|
||||
dblimit = vld1_u8(blimit);
|
||||
dlimit = vld1_u8(limit);
|
||||
dthresh = vld1_u8(thresh);
|
||||
|
||||
psrc = src - (pitch << 2);
|
||||
for (i = 0; i < 1; i++) {
|
||||
s = psrc + i * 8;
|
||||
|
||||
d3u8 = vld1_u8(s);
|
||||
s += pitch;
|
||||
d4u8 = vld1_u8(s);
|
||||
s += pitch;
|
||||
d5u8 = vld1_u8(s);
|
||||
s += pitch;
|
||||
d6u8 = vld1_u8(s);
|
||||
s += pitch;
|
||||
d7u8 = vld1_u8(s);
|
||||
s += pitch;
|
||||
d16u8 = vld1_u8(s);
|
||||
s += pitch;
|
||||
d17u8 = vld1_u8(s);
|
||||
s += pitch;
|
||||
d18u8 = vld1_u8(s);
|
||||
|
||||
loop_filter_neon(dblimit, dlimit, dthresh, d3u8, d4u8, d5u8, d6u8, d7u8,
|
||||
d16u8, d17u8, d18u8, &d4u8, &d5u8, &d6u8, &d7u8);
|
||||
|
||||
s -= (pitch * 5);
|
||||
vst1_u8(s, d4u8);
|
||||
s += pitch;
|
||||
vst1_u8(s, d5u8);
|
||||
s += pitch;
|
||||
vst1_u8(s, d6u8);
|
||||
s += pitch;
|
||||
vst1_u8(s, d7u8);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void aom_lpf_vertical_4_neon(uint8_t *src, int pitch, const uint8_t *blimit,
|
||||
const uint8_t *limit, const uint8_t *thresh) {
|
||||
int i, pitch8;
|
||||
uint8_t *s;
|
||||
uint8x8_t dblimit, dlimit, dthresh;
|
||||
uint8x8_t d3u8, d4u8, d5u8, d6u8, d7u8, d16u8, d17u8, d18u8;
|
||||
uint32x2x2_t d2tmp0, d2tmp1, d2tmp2, d2tmp3;
|
||||
uint16x4x2_t d2tmp4, d2tmp5, d2tmp6, d2tmp7;
|
||||
uint8x8x2_t d2tmp8, d2tmp9, d2tmp10, d2tmp11;
|
||||
uint8x8x4_t d4Result;
|
||||
|
||||
dblimit = vld1_u8(blimit);
|
||||
dlimit = vld1_u8(limit);
|
||||
dthresh = vld1_u8(thresh);
|
||||
|
||||
pitch8 = pitch * 8;
|
||||
for (i = 0; i < 1; i++, src += pitch8) {
|
||||
s = src - (i + 1) * 4;
|
||||
|
||||
d3u8 = vld1_u8(s);
|
||||
s += pitch;
|
||||
d4u8 = vld1_u8(s);
|
||||
s += pitch;
|
||||
d5u8 = vld1_u8(s);
|
||||
s += pitch;
|
||||
d6u8 = vld1_u8(s);
|
||||
s += pitch;
|
||||
d7u8 = vld1_u8(s);
|
||||
s += pitch;
|
||||
d16u8 = vld1_u8(s);
|
||||
s += pitch;
|
||||
d17u8 = vld1_u8(s);
|
||||
s += pitch;
|
||||
d18u8 = vld1_u8(s);
|
||||
|
||||
d2tmp0 = vtrn_u32(vreinterpret_u32_u8(d3u8), vreinterpret_u32_u8(d7u8));
|
||||
d2tmp1 = vtrn_u32(vreinterpret_u32_u8(d4u8), vreinterpret_u32_u8(d16u8));
|
||||
d2tmp2 = vtrn_u32(vreinterpret_u32_u8(d5u8), vreinterpret_u32_u8(d17u8));
|
||||
d2tmp3 = vtrn_u32(vreinterpret_u32_u8(d6u8), vreinterpret_u32_u8(d18u8));
|
||||
|
||||
d2tmp4 = vtrn_u16(vreinterpret_u16_u32(d2tmp0.val[0]),
|
||||
vreinterpret_u16_u32(d2tmp2.val[0]));
|
||||
d2tmp5 = vtrn_u16(vreinterpret_u16_u32(d2tmp1.val[0]),
|
||||
vreinterpret_u16_u32(d2tmp3.val[0]));
|
||||
d2tmp6 = vtrn_u16(vreinterpret_u16_u32(d2tmp0.val[1]),
|
||||
vreinterpret_u16_u32(d2tmp2.val[1]));
|
||||
d2tmp7 = vtrn_u16(vreinterpret_u16_u32(d2tmp1.val[1]),
|
||||
vreinterpret_u16_u32(d2tmp3.val[1]));
|
||||
|
||||
d2tmp8 = vtrn_u8(vreinterpret_u8_u16(d2tmp4.val[0]),
|
||||
vreinterpret_u8_u16(d2tmp5.val[0]));
|
||||
d2tmp9 = vtrn_u8(vreinterpret_u8_u16(d2tmp4.val[1]),
|
||||
vreinterpret_u8_u16(d2tmp5.val[1]));
|
||||
d2tmp10 = vtrn_u8(vreinterpret_u8_u16(d2tmp6.val[0]),
|
||||
vreinterpret_u8_u16(d2tmp7.val[0]));
|
||||
d2tmp11 = vtrn_u8(vreinterpret_u8_u16(d2tmp6.val[1]),
|
||||
vreinterpret_u8_u16(d2tmp7.val[1]));
|
||||
|
||||
d3u8 = d2tmp8.val[0];
|
||||
d4u8 = d2tmp8.val[1];
|
||||
d5u8 = d2tmp9.val[0];
|
||||
d6u8 = d2tmp9.val[1];
|
||||
d7u8 = d2tmp10.val[0];
|
||||
d16u8 = d2tmp10.val[1];
|
||||
d17u8 = d2tmp11.val[0];
|
||||
d18u8 = d2tmp11.val[1];
|
||||
|
||||
loop_filter_neon(dblimit, dlimit, dthresh, d3u8, d4u8, d5u8, d6u8, d7u8,
|
||||
d16u8, d17u8, d18u8, &d4u8, &d5u8, &d6u8, &d7u8);
|
||||
|
||||
d4Result.val[0] = d4u8;
|
||||
d4Result.val[1] = d5u8;
|
||||
d4Result.val[2] = d6u8;
|
||||
d4Result.val[3] = d7u8;
|
||||
|
||||
src -= 2;
|
||||
vst4_lane_u8(src, d4Result, 0);
|
||||
src += pitch;
|
||||
vst4_lane_u8(src, d4Result, 1);
|
||||
src += pitch;
|
||||
vst4_lane_u8(src, d4Result, 2);
|
||||
src += pitch;
|
||||
vst4_lane_u8(src, d4Result, 3);
|
||||
src += pitch;
|
||||
vst4_lane_u8(src, d4Result, 4);
|
||||
src += pitch;
|
||||
vst4_lane_u8(src, d4Result, 5);
|
||||
src += pitch;
|
||||
vst4_lane_u8(src, d4Result, 6);
|
||||
src += pitch;
|
||||
vst4_lane_u8(src, d4Result, 7);
|
||||
}
|
||||
return;
|
||||
}
|
||||
428
third_party/aom/aom_dsp/arm/loopfilter_8_neon.asm
vendored
Normal file
428
third_party/aom/aom_dsp/arm/loopfilter_8_neon.asm
vendored
Normal file
|
|
@ -0,0 +1,428 @@
|
|||
;
|
||||
; Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
;
|
||||
; This source code is subject to the terms of the BSD 2 Clause License and
|
||||
; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
; was not distributed with this source code in the LICENSE file, you can
|
||||
; obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
; Media Patent License 1.0 was not distributed with this source code in the
|
||||
; PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
;
|
||||
|
||||
;
|
||||
|
||||
EXPORT |aom_lpf_horizontal_8_neon|
|
||||
EXPORT |aom_lpf_vertical_8_neon|
|
||||
ARM
|
||||
|
||||
AREA ||.text||, CODE, READONLY, ALIGN=2
|
||||
|
||||
; Currently aom only works on iterations 8 at a time. The aom loop filter
|
||||
; works on 16 iterations at a time.
|
||||
;
|
||||
; void aom_lpf_horizontal_8_neon(uint8_t *s, int p,
|
||||
; const uint8_t *blimit,
|
||||
; const uint8_t *limit,
|
||||
; const uint8_t *thresh)
|
||||
; r0 uint8_t *s,
|
||||
; r1 int p, /* pitch */
|
||||
; r2 const uint8_t *blimit,
|
||||
; r3 const uint8_t *limit,
|
||||
; sp const uint8_t *thresh,
|
||||
|aom_lpf_horizontal_8_neon| PROC
|
||||
push {r4-r5, lr}
|
||||
|
||||
vld1.8 {d0[]}, [r2] ; duplicate *blimit
|
||||
ldr r2, [sp, #12] ; load thresh
|
||||
add r1, r1, r1 ; double pitch
|
||||
|
||||
vld1.8 {d1[]}, [r3] ; duplicate *limit
|
||||
vld1.8 {d2[]}, [r2] ; duplicate *thresh
|
||||
|
||||
sub r3, r0, r1, lsl #1 ; move src pointer down by 4 lines
|
||||
add r2, r3, r1, lsr #1 ; set to 3 lines down
|
||||
|
||||
vld1.u8 {d3}, [r3@64], r1 ; p3
|
||||
vld1.u8 {d4}, [r2@64], r1 ; p2
|
||||
vld1.u8 {d5}, [r3@64], r1 ; p1
|
||||
vld1.u8 {d6}, [r2@64], r1 ; p0
|
||||
vld1.u8 {d7}, [r3@64], r1 ; q0
|
||||
vld1.u8 {d16}, [r2@64], r1 ; q1
|
||||
vld1.u8 {d17}, [r3@64] ; q2
|
||||
vld1.u8 {d18}, [r2@64], r1 ; q3
|
||||
|
||||
sub r3, r3, r1, lsl #1
|
||||
sub r2, r2, r1, lsl #2
|
||||
|
||||
bl aom_mbloop_filter_neon
|
||||
|
||||
vst1.u8 {d0}, [r2@64], r1 ; store op2
|
||||
vst1.u8 {d1}, [r3@64], r1 ; store op1
|
||||
vst1.u8 {d2}, [r2@64], r1 ; store op0
|
||||
vst1.u8 {d3}, [r3@64], r1 ; store oq0
|
||||
vst1.u8 {d4}, [r2@64], r1 ; store oq1
|
||||
vst1.u8 {d5}, [r3@64], r1 ; store oq2
|
||||
|
||||
pop {r4-r5, pc}
|
||||
|
||||
ENDP ; |aom_lpf_horizontal_8_neon|
|
||||
|
||||
; void aom_lpf_vertical_8_neon(uint8_t *s,
|
||||
; int pitch,
|
||||
; const uint8_t *blimit,
|
||||
; const uint8_t *limit,
|
||||
; const uint8_t *thresh)
|
||||
;
|
||||
; r0 uint8_t *s,
|
||||
; r1 int pitch,
|
||||
; r2 const uint8_t *blimit,
|
||||
; r3 const uint8_t *limit,
|
||||
; sp const uint8_t *thresh,
|
||||
|aom_lpf_vertical_8_neon| PROC
|
||||
push {r4-r5, lr}
|
||||
|
||||
vld1.8 {d0[]}, [r2] ; duplicate *blimit
|
||||
vld1.8 {d1[]}, [r3] ; duplicate *limit
|
||||
|
||||
ldr r3, [sp, #12] ; load thresh
|
||||
sub r2, r0, #4 ; move s pointer down by 4 columns
|
||||
|
||||
vld1.8 {d2[]}, [r3] ; duplicate *thresh
|
||||
|
||||
vld1.u8 {d3}, [r2], r1 ; load s data
|
||||
vld1.u8 {d4}, [r2], r1
|
||||
vld1.u8 {d5}, [r2], r1
|
||||
vld1.u8 {d6}, [r2], r1
|
||||
vld1.u8 {d7}, [r2], r1
|
||||
vld1.u8 {d16}, [r2], r1
|
||||
vld1.u8 {d17}, [r2], r1
|
||||
vld1.u8 {d18}, [r2]
|
||||
|
||||
;transpose to 8x16 matrix
|
||||
vtrn.32 d3, d7
|
||||
vtrn.32 d4, d16
|
||||
vtrn.32 d5, d17
|
||||
vtrn.32 d6, d18
|
||||
|
||||
vtrn.16 d3, d5
|
||||
vtrn.16 d4, d6
|
||||
vtrn.16 d7, d17
|
||||
vtrn.16 d16, d18
|
||||
|
||||
vtrn.8 d3, d4
|
||||
vtrn.8 d5, d6
|
||||
vtrn.8 d7, d16
|
||||
vtrn.8 d17, d18
|
||||
|
||||
sub r2, r0, #3
|
||||
add r3, r0, #1
|
||||
|
||||
bl aom_mbloop_filter_neon
|
||||
|
||||
;store op2, op1, op0, oq0
|
||||
vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r2], r1
|
||||
vst4.8 {d0[1], d1[1], d2[1], d3[1]}, [r2], r1
|
||||
vst4.8 {d0[2], d1[2], d2[2], d3[2]}, [r2], r1
|
||||
vst4.8 {d0[3], d1[3], d2[3], d3[3]}, [r2], r1
|
||||
vst4.8 {d0[4], d1[4], d2[4], d3[4]}, [r2], r1
|
||||
vst4.8 {d0[5], d1[5], d2[5], d3[5]}, [r2], r1
|
||||
vst4.8 {d0[6], d1[6], d2[6], d3[6]}, [r2], r1
|
||||
vst4.8 {d0[7], d1[7], d2[7], d3[7]}, [r2]
|
||||
|
||||
;store oq1, oq2
|
||||
vst2.8 {d4[0], d5[0]}, [r3], r1
|
||||
vst2.8 {d4[1], d5[1]}, [r3], r1
|
||||
vst2.8 {d4[2], d5[2]}, [r3], r1
|
||||
vst2.8 {d4[3], d5[3]}, [r3], r1
|
||||
vst2.8 {d4[4], d5[4]}, [r3], r1
|
||||
vst2.8 {d4[5], d5[5]}, [r3], r1
|
||||
vst2.8 {d4[6], d5[6]}, [r3], r1
|
||||
vst2.8 {d4[7], d5[7]}, [r3]
|
||||
|
||||
pop {r4-r5, pc}
|
||||
ENDP ; |aom_lpf_vertical_8_neon|
|
||||
|
||||
; void aom_mbloop_filter_neon();
|
||||
; This is a helper function for the loopfilters. The invidual functions do the
|
||||
; necessary load, transpose (if necessary) and store. The function does not use
|
||||
; registers d8-d15.
|
||||
;
|
||||
; Inputs:
|
||||
; r0-r3, r12 PRESERVE
|
||||
; d0 blimit
|
||||
; d1 limit
|
||||
; d2 thresh
|
||||
; d3 p3
|
||||
; d4 p2
|
||||
; d5 p1
|
||||
; d6 p0
|
||||
; d7 q0
|
||||
; d16 q1
|
||||
; d17 q2
|
||||
; d18 q3
|
||||
;
|
||||
; Outputs:
|
||||
; d0 op2
|
||||
; d1 op1
|
||||
; d2 op0
|
||||
; d3 oq0
|
||||
; d4 oq1
|
||||
; d5 oq2
|
||||
|aom_mbloop_filter_neon| PROC
|
||||
; filter_mask
|
||||
vabd.u8 d19, d3, d4 ; m1 = abs(p3 - p2)
|
||||
vabd.u8 d20, d4, d5 ; m2 = abs(p2 - p1)
|
||||
vabd.u8 d21, d5, d6 ; m3 = abs(p1 - p0)
|
||||
vabd.u8 d22, d16, d7 ; m4 = abs(q1 - q0)
|
||||
vabd.u8 d23, d17, d16 ; m5 = abs(q2 - q1)
|
||||
vabd.u8 d24, d18, d17 ; m6 = abs(q3 - q2)
|
||||
|
||||
; only compare the largest value to limit
|
||||
vmax.u8 d19, d19, d20 ; m1 = max(m1, m2)
|
||||
vmax.u8 d20, d21, d22 ; m2 = max(m3, m4)
|
||||
|
||||
vabd.u8 d25, d6, d4 ; m7 = abs(p0 - p2)
|
||||
|
||||
vmax.u8 d23, d23, d24 ; m3 = max(m5, m6)
|
||||
|
||||
vabd.u8 d26, d7, d17 ; m8 = abs(q0 - q2)
|
||||
|
||||
vmax.u8 d19, d19, d20
|
||||
|
||||
vabd.u8 d24, d6, d7 ; m9 = abs(p0 - q0)
|
||||
vabd.u8 d27, d3, d6 ; m10 = abs(p3 - p0)
|
||||
vabd.u8 d28, d18, d7 ; m11 = abs(q3 - q0)
|
||||
|
||||
vmax.u8 d19, d19, d23
|
||||
|
||||
vabd.u8 d23, d5, d16 ; a = abs(p1 - q1)
|
||||
vqadd.u8 d24, d24, d24 ; b = abs(p0 - q0) * 2
|
||||
|
||||
; abs () > limit
|
||||
vcge.u8 d19, d1, d19
|
||||
|
||||
; only compare the largest value to thresh
|
||||
vmax.u8 d25, d25, d26 ; m4 = max(m7, m8)
|
||||
vmax.u8 d26, d27, d28 ; m5 = max(m10, m11)
|
||||
|
||||
vshr.u8 d23, d23, #1 ; a = a / 2
|
||||
|
||||
vmax.u8 d25, d25, d26 ; m4 = max(m4, m5)
|
||||
|
||||
vqadd.u8 d24, d24, d23 ; a = b + a
|
||||
|
||||
vmax.u8 d20, d20, d25 ; m2 = max(m2, m4)
|
||||
|
||||
vmov.u8 d23, #1
|
||||
vcge.u8 d24, d0, d24 ; a > blimit
|
||||
|
||||
vcgt.u8 d21, d21, d2 ; (abs(p1 - p0) > thresh)*-1
|
||||
|
||||
vcge.u8 d20, d23, d20 ; flat
|
||||
|
||||
vand d19, d19, d24 ; mask
|
||||
|
||||
vcgt.u8 d23, d22, d2 ; (abs(q1 - q0) > thresh)*-1
|
||||
|
||||
vand d20, d20, d19 ; flat & mask
|
||||
|
||||
vmov.u8 d22, #0x80
|
||||
|
||||
vorr d23, d21, d23 ; hev
|
||||
|
||||
; This instruction will truncate the "flat & mask" masks down to 4 bits
|
||||
; each to fit into one 32 bit arm register. The values are stored in
|
||||
; q10.64[0].
|
||||
vshrn.u16 d30, q10, #4
|
||||
vmov.u32 r4, d30[0] ; flat & mask 4bits
|
||||
|
||||
adds r5, r4, #1 ; Check for all 1's
|
||||
|
||||
; If mask and flat are 1's for all vectors, then we only need to execute
|
||||
; the power branch for all vectors.
|
||||
beq power_branch_only
|
||||
|
||||
cmp r4, #0 ; Check for 0, set flag for later
|
||||
|
||||
; mbfilter() function
|
||||
; filter() function
|
||||
; convert to signed
|
||||
veor d21, d7, d22 ; qs0
|
||||
veor d24, d6, d22 ; ps0
|
||||
veor d25, d5, d22 ; ps1
|
||||
veor d26, d16, d22 ; qs1
|
||||
|
||||
vmov.u8 d27, #3
|
||||
|
||||
vsub.s8 d28, d21, d24 ; ( qs0 - ps0)
|
||||
|
||||
vqsub.s8 d29, d25, d26 ; filter = clamp(ps1-qs1)
|
||||
|
||||
vmull.s8 q15, d28, d27 ; 3 * ( qs0 - ps0)
|
||||
|
||||
vand d29, d29, d23 ; filter &= hev
|
||||
|
||||
vaddw.s8 q15, q15, d29 ; filter + 3 * (qs0 - ps0)
|
||||
|
||||
vmov.u8 d29, #4
|
||||
|
||||
; filter = clamp(filter + 3 * ( qs0 - ps0))
|
||||
vqmovn.s16 d28, q15
|
||||
|
||||
vand d28, d28, d19 ; filter &= mask
|
||||
|
||||
vqadd.s8 d30, d28, d27 ; filter2 = clamp(filter+3)
|
||||
vqadd.s8 d29, d28, d29 ; filter1 = clamp(filter+4)
|
||||
vshr.s8 d30, d30, #3 ; filter2 >>= 3
|
||||
vshr.s8 d29, d29, #3 ; filter1 >>= 3
|
||||
|
||||
vqadd.s8 d24, d24, d30 ; op0 = clamp(ps0 + filter2)
|
||||
vqsub.s8 d21, d21, d29 ; oq0 = clamp(qs0 - filter1)
|
||||
|
||||
; outer tap adjustments: ++filter1 >> 1
|
||||
vrshr.s8 d29, d29, #1
|
||||
vbic d29, d29, d23 ; filter &= ~hev
|
||||
|
||||
vqadd.s8 d25, d25, d29 ; op1 = clamp(ps1 + filter)
|
||||
vqsub.s8 d26, d26, d29 ; oq1 = clamp(qs1 - filter)
|
||||
|
||||
; If mask and flat are 0's for all vectors, then we only need to execute
|
||||
; the filter branch for all vectors.
|
||||
beq filter_branch_only
|
||||
|
||||
; If mask and flat are mixed then we must perform both branches and
|
||||
; combine the data.
|
||||
veor d24, d24, d22 ; *f_op0 = u^0x80
|
||||
veor d21, d21, d22 ; *f_oq0 = u^0x80
|
||||
veor d25, d25, d22 ; *f_op1 = u^0x80
|
||||
veor d26, d26, d22 ; *f_oq1 = u^0x80
|
||||
|
||||
; At this point we have already executed the filter branch. The filter
|
||||
; branch does not set op2 or oq2, so use p2 and q2. Execute the power
|
||||
; branch and combine the data.
|
||||
vmov.u8 d23, #2
|
||||
vaddl.u8 q14, d6, d7 ; r_op2 = p0 + q0
|
||||
vmlal.u8 q14, d3, d27 ; r_op2 += p3 * 3
|
||||
vmlal.u8 q14, d4, d23 ; r_op2 += p2 * 2
|
||||
|
||||
vbif d0, d4, d20 ; op2 |= p2 & ~(flat & mask)
|
||||
|
||||
vaddw.u8 q14, d5 ; r_op2 += p1
|
||||
|
||||
vbif d1, d25, d20 ; op1 |= f_op1 & ~(flat & mask)
|
||||
|
||||
vqrshrn.u16 d30, q14, #3 ; r_op2
|
||||
|
||||
vsubw.u8 q14, d3 ; r_op1 = r_op2 - p3
|
||||
vsubw.u8 q14, d4 ; r_op1 -= p2
|
||||
vaddw.u8 q14, d5 ; r_op1 += p1
|
||||
vaddw.u8 q14, d16 ; r_op1 += q1
|
||||
|
||||
vbif d2, d24, d20 ; op0 |= f_op0 & ~(flat & mask)
|
||||
|
||||
vqrshrn.u16 d31, q14, #3 ; r_op1
|
||||
|
||||
vsubw.u8 q14, d3 ; r_op0 = r_op1 - p3
|
||||
vsubw.u8 q14, d5 ; r_op0 -= p1
|
||||
vaddw.u8 q14, d6 ; r_op0 += p0
|
||||
vaddw.u8 q14, d17 ; r_op0 += q2
|
||||
|
||||
vbit d0, d30, d20 ; op2 |= r_op2 & (flat & mask)
|
||||
|
||||
vqrshrn.u16 d23, q14, #3 ; r_op0
|
||||
|
||||
vsubw.u8 q14, d3 ; r_oq0 = r_op0 - p3
|
||||
vsubw.u8 q14, d6 ; r_oq0 -= p0
|
||||
vaddw.u8 q14, d7 ; r_oq0 += q0
|
||||
|
||||
vbit d1, d31, d20 ; op1 |= r_op1 & (flat & mask)
|
||||
|
||||
vaddw.u8 q14, d18 ; oq0 += q3
|
||||
|
||||
vbit d2, d23, d20 ; op0 |= r_op0 & (flat & mask)
|
||||
|
||||
vqrshrn.u16 d22, q14, #3 ; r_oq0
|
||||
|
||||
vsubw.u8 q14, d4 ; r_oq1 = r_oq0 - p2
|
||||
vsubw.u8 q14, d7 ; r_oq1 -= q0
|
||||
vaddw.u8 q14, d16 ; r_oq1 += q1
|
||||
|
||||
vbif d3, d21, d20 ; oq0 |= f_oq0 & ~(flat & mask)
|
||||
|
||||
vaddw.u8 q14, d18 ; r_oq1 += q3
|
||||
|
||||
vbif d4, d26, d20 ; oq1 |= f_oq1 & ~(flat & mask)
|
||||
|
||||
vqrshrn.u16 d6, q14, #3 ; r_oq1
|
||||
|
||||
vsubw.u8 q14, d5 ; r_oq2 = r_oq1 - p1
|
||||
vsubw.u8 q14, d16 ; r_oq2 -= q1
|
||||
vaddw.u8 q14, d17 ; r_oq2 += q2
|
||||
vaddw.u8 q14, d18 ; r_oq2 += q3
|
||||
|
||||
vbif d5, d17, d20 ; oq2 |= q2 & ~(flat & mask)
|
||||
|
||||
vqrshrn.u16 d7, q14, #3 ; r_oq2
|
||||
|
||||
vbit d3, d22, d20 ; oq0 |= r_oq0 & (flat & mask)
|
||||
vbit d4, d6, d20 ; oq1 |= r_oq1 & (flat & mask)
|
||||
vbit d5, d7, d20 ; oq2 |= r_oq2 & (flat & mask)
|
||||
|
||||
bx lr
|
||||
|
||||
power_branch_only
|
||||
vmov.u8 d27, #3
|
||||
vmov.u8 d21, #2
|
||||
vaddl.u8 q14, d6, d7 ; op2 = p0 + q0
|
||||
vmlal.u8 q14, d3, d27 ; op2 += p3 * 3
|
||||
vmlal.u8 q14, d4, d21 ; op2 += p2 * 2
|
||||
vaddw.u8 q14, d5 ; op2 += p1
|
||||
vqrshrn.u16 d0, q14, #3 ; op2
|
||||
|
||||
vsubw.u8 q14, d3 ; op1 = op2 - p3
|
||||
vsubw.u8 q14, d4 ; op1 -= p2
|
||||
vaddw.u8 q14, d5 ; op1 += p1
|
||||
vaddw.u8 q14, d16 ; op1 += q1
|
||||
vqrshrn.u16 d1, q14, #3 ; op1
|
||||
|
||||
vsubw.u8 q14, d3 ; op0 = op1 - p3
|
||||
vsubw.u8 q14, d5 ; op0 -= p1
|
||||
vaddw.u8 q14, d6 ; op0 += p0
|
||||
vaddw.u8 q14, d17 ; op0 += q2
|
||||
vqrshrn.u16 d2, q14, #3 ; op0
|
||||
|
||||
vsubw.u8 q14, d3 ; oq0 = op0 - p3
|
||||
vsubw.u8 q14, d6 ; oq0 -= p0
|
||||
vaddw.u8 q14, d7 ; oq0 += q0
|
||||
vaddw.u8 q14, d18 ; oq0 += q3
|
||||
vqrshrn.u16 d3, q14, #3 ; oq0
|
||||
|
||||
vsubw.u8 q14, d4 ; oq1 = oq0 - p2
|
||||
vsubw.u8 q14, d7 ; oq1 -= q0
|
||||
vaddw.u8 q14, d16 ; oq1 += q1
|
||||
vaddw.u8 q14, d18 ; oq1 += q3
|
||||
vqrshrn.u16 d4, q14, #3 ; oq1
|
||||
|
||||
vsubw.u8 q14, d5 ; oq2 = oq1 - p1
|
||||
vsubw.u8 q14, d16 ; oq2 -= q1
|
||||
vaddw.u8 q14, d17 ; oq2 += q2
|
||||
vaddw.u8 q14, d18 ; oq2 += q3
|
||||
vqrshrn.u16 d5, q14, #3 ; oq2
|
||||
|
||||
bx lr
|
||||
|
||||
filter_branch_only
|
||||
; TODO(fgalligan): See if we can rearange registers so we do not need to
|
||||
; do the 2 vswp.
|
||||
vswp d0, d4 ; op2
|
||||
vswp d5, d17 ; oq2
|
||||
veor d2, d24, d22 ; *op0 = u^0x80
|
||||
veor d3, d21, d22 ; *oq0 = u^0x80
|
||||
veor d1, d25, d22 ; *op1 = u^0x80
|
||||
veor d4, d26, d22 ; *oq1 = u^0x80
|
||||
|
||||
bx lr
|
||||
|
||||
ENDP ; |aom_mbloop_filter_neon|
|
||||
|
||||
END
|
||||
430
third_party/aom/aom_dsp/arm/loopfilter_8_neon.c
vendored
Normal file
430
third_party/aom/aom_dsp/arm/loopfilter_8_neon.c
vendored
Normal file
|
|
@ -0,0 +1,430 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <arm_neon.h>
|
||||
|
||||
#include "./aom_dsp_rtcd.h"
|
||||
|
||||
static INLINE void mbloop_filter_neon(uint8x8_t dblimit, // mblimit
|
||||
uint8x8_t dlimit, // limit
|
||||
uint8x8_t dthresh, // thresh
|
||||
uint8x8_t d3u8, // p2
|
||||
uint8x8_t d4u8, // p2
|
||||
uint8x8_t d5u8, // p1
|
||||
uint8x8_t d6u8, // p0
|
||||
uint8x8_t d7u8, // q0
|
||||
uint8x8_t d16u8, // q1
|
||||
uint8x8_t d17u8, // q2
|
||||
uint8x8_t d18u8, // q3
|
||||
uint8x8_t *d0ru8, // p1
|
||||
uint8x8_t *d1ru8, // p1
|
||||
uint8x8_t *d2ru8, // p0
|
||||
uint8x8_t *d3ru8, // q0
|
||||
uint8x8_t *d4ru8, // q1
|
||||
uint8x8_t *d5ru8) { // q1
|
||||
uint32_t flat;
|
||||
uint8x8_t d0u8, d1u8, d2u8, d19u8, d20u8, d21u8, d22u8, d23u8, d24u8;
|
||||
uint8x8_t d25u8, d26u8, d27u8, d28u8, d29u8, d30u8, d31u8;
|
||||
int16x8_t q15s16;
|
||||
uint16x8_t q10u16, q14u16;
|
||||
int8x8_t d21s8, d24s8, d25s8, d26s8, d28s8, d29s8, d30s8;
|
||||
|
||||
d19u8 = vabd_u8(d3u8, d4u8);
|
||||
d20u8 = vabd_u8(d4u8, d5u8);
|
||||
d21u8 = vabd_u8(d5u8, d6u8);
|
||||
d22u8 = vabd_u8(d16u8, d7u8);
|
||||
d23u8 = vabd_u8(d17u8, d16u8);
|
||||
d24u8 = vabd_u8(d18u8, d17u8);
|
||||
|
||||
d19u8 = vmax_u8(d19u8, d20u8);
|
||||
d20u8 = vmax_u8(d21u8, d22u8);
|
||||
|
||||
d25u8 = vabd_u8(d6u8, d4u8);
|
||||
|
||||
d23u8 = vmax_u8(d23u8, d24u8);
|
||||
|
||||
d26u8 = vabd_u8(d7u8, d17u8);
|
||||
|
||||
d19u8 = vmax_u8(d19u8, d20u8);
|
||||
|
||||
d24u8 = vabd_u8(d6u8, d7u8);
|
||||
d27u8 = vabd_u8(d3u8, d6u8);
|
||||
d28u8 = vabd_u8(d18u8, d7u8);
|
||||
|
||||
d19u8 = vmax_u8(d19u8, d23u8);
|
||||
|
||||
d23u8 = vabd_u8(d5u8, d16u8);
|
||||
d24u8 = vqadd_u8(d24u8, d24u8);
|
||||
|
||||
d19u8 = vcge_u8(dlimit, d19u8);
|
||||
|
||||
d25u8 = vmax_u8(d25u8, d26u8);
|
||||
d26u8 = vmax_u8(d27u8, d28u8);
|
||||
|
||||
d23u8 = vshr_n_u8(d23u8, 1);
|
||||
|
||||
d25u8 = vmax_u8(d25u8, d26u8);
|
||||
|
||||
d24u8 = vqadd_u8(d24u8, d23u8);
|
||||
|
||||
d20u8 = vmax_u8(d20u8, d25u8);
|
||||
|
||||
d23u8 = vdup_n_u8(1);
|
||||
d24u8 = vcge_u8(dblimit, d24u8);
|
||||
|
||||
d21u8 = vcgt_u8(d21u8, dthresh);
|
||||
|
||||
d20u8 = vcge_u8(d23u8, d20u8);
|
||||
|
||||
d19u8 = vand_u8(d19u8, d24u8);
|
||||
|
||||
d23u8 = vcgt_u8(d22u8, dthresh);
|
||||
|
||||
d20u8 = vand_u8(d20u8, d19u8);
|
||||
|
||||
d22u8 = vdup_n_u8(0x80);
|
||||
|
||||
d23u8 = vorr_u8(d21u8, d23u8);
|
||||
|
||||
q10u16 = vcombine_u16(vreinterpret_u16_u8(d20u8), vreinterpret_u16_u8(d21u8));
|
||||
|
||||
d30u8 = vshrn_n_u16(q10u16, 4);
|
||||
flat = vget_lane_u32(vreinterpret_u32_u8(d30u8), 0);
|
||||
|
||||
if (flat == 0xffffffff) { // Check for all 1's, power_branch_only
|
||||
d27u8 = vdup_n_u8(3);
|
||||
d21u8 = vdup_n_u8(2);
|
||||
q14u16 = vaddl_u8(d6u8, d7u8);
|
||||
q14u16 = vmlal_u8(q14u16, d3u8, d27u8);
|
||||
q14u16 = vmlal_u8(q14u16, d4u8, d21u8);
|
||||
q14u16 = vaddw_u8(q14u16, d5u8);
|
||||
*d0ru8 = vqrshrn_n_u16(q14u16, 3);
|
||||
|
||||
q14u16 = vsubw_u8(q14u16, d3u8);
|
||||
q14u16 = vsubw_u8(q14u16, d4u8);
|
||||
q14u16 = vaddw_u8(q14u16, d5u8);
|
||||
q14u16 = vaddw_u8(q14u16, d16u8);
|
||||
*d1ru8 = vqrshrn_n_u16(q14u16, 3);
|
||||
|
||||
q14u16 = vsubw_u8(q14u16, d3u8);
|
||||
q14u16 = vsubw_u8(q14u16, d5u8);
|
||||
q14u16 = vaddw_u8(q14u16, d6u8);
|
||||
q14u16 = vaddw_u8(q14u16, d17u8);
|
||||
*d2ru8 = vqrshrn_n_u16(q14u16, 3);
|
||||
|
||||
q14u16 = vsubw_u8(q14u16, d3u8);
|
||||
q14u16 = vsubw_u8(q14u16, d6u8);
|
||||
q14u16 = vaddw_u8(q14u16, d7u8);
|
||||
q14u16 = vaddw_u8(q14u16, d18u8);
|
||||
*d3ru8 = vqrshrn_n_u16(q14u16, 3);
|
||||
|
||||
q14u16 = vsubw_u8(q14u16, d4u8);
|
||||
q14u16 = vsubw_u8(q14u16, d7u8);
|
||||
q14u16 = vaddw_u8(q14u16, d16u8);
|
||||
q14u16 = vaddw_u8(q14u16, d18u8);
|
||||
*d4ru8 = vqrshrn_n_u16(q14u16, 3);
|
||||
|
||||
q14u16 = vsubw_u8(q14u16, d5u8);
|
||||
q14u16 = vsubw_u8(q14u16, d16u8);
|
||||
q14u16 = vaddw_u8(q14u16, d17u8);
|
||||
q14u16 = vaddw_u8(q14u16, d18u8);
|
||||
*d5ru8 = vqrshrn_n_u16(q14u16, 3);
|
||||
} else {
|
||||
d21u8 = veor_u8(d7u8, d22u8);
|
||||
d24u8 = veor_u8(d6u8, d22u8);
|
||||
d25u8 = veor_u8(d5u8, d22u8);
|
||||
d26u8 = veor_u8(d16u8, d22u8);
|
||||
|
||||
d27u8 = vdup_n_u8(3);
|
||||
|
||||
d28s8 = vsub_s8(vreinterpret_s8_u8(d21u8), vreinterpret_s8_u8(d24u8));
|
||||
d29s8 = vqsub_s8(vreinterpret_s8_u8(d25u8), vreinterpret_s8_u8(d26u8));
|
||||
|
||||
q15s16 = vmull_s8(d28s8, vreinterpret_s8_u8(d27u8));
|
||||
|
||||
d29s8 = vand_s8(d29s8, vreinterpret_s8_u8(d23u8));
|
||||
|
||||
q15s16 = vaddw_s8(q15s16, d29s8);
|
||||
|
||||
d29u8 = vdup_n_u8(4);
|
||||
|
||||
d28s8 = vqmovn_s16(q15s16);
|
||||
|
||||
d28s8 = vand_s8(d28s8, vreinterpret_s8_u8(d19u8));
|
||||
|
||||
d30s8 = vqadd_s8(d28s8, vreinterpret_s8_u8(d27u8));
|
||||
d29s8 = vqadd_s8(d28s8, vreinterpret_s8_u8(d29u8));
|
||||
d30s8 = vshr_n_s8(d30s8, 3);
|
||||
d29s8 = vshr_n_s8(d29s8, 3);
|
||||
|
||||
d24s8 = vqadd_s8(vreinterpret_s8_u8(d24u8), d30s8);
|
||||
d21s8 = vqsub_s8(vreinterpret_s8_u8(d21u8), d29s8);
|
||||
|
||||
d29s8 = vrshr_n_s8(d29s8, 1);
|
||||
d29s8 = vbic_s8(d29s8, vreinterpret_s8_u8(d23u8));
|
||||
|
||||
d25s8 = vqadd_s8(vreinterpret_s8_u8(d25u8), d29s8);
|
||||
d26s8 = vqsub_s8(vreinterpret_s8_u8(d26u8), d29s8);
|
||||
|
||||
if (flat == 0) { // filter_branch_only
|
||||
*d0ru8 = d4u8;
|
||||
*d1ru8 = veor_u8(vreinterpret_u8_s8(d25s8), d22u8);
|
||||
*d2ru8 = veor_u8(vreinterpret_u8_s8(d24s8), d22u8);
|
||||
*d3ru8 = veor_u8(vreinterpret_u8_s8(d21s8), d22u8);
|
||||
*d4ru8 = veor_u8(vreinterpret_u8_s8(d26s8), d22u8);
|
||||
*d5ru8 = d17u8;
|
||||
return;
|
||||
}
|
||||
|
||||
d21u8 = veor_u8(vreinterpret_u8_s8(d21s8), d22u8);
|
||||
d24u8 = veor_u8(vreinterpret_u8_s8(d24s8), d22u8);
|
||||
d25u8 = veor_u8(vreinterpret_u8_s8(d25s8), d22u8);
|
||||
d26u8 = veor_u8(vreinterpret_u8_s8(d26s8), d22u8);
|
||||
|
||||
d23u8 = vdup_n_u8(2);
|
||||
q14u16 = vaddl_u8(d6u8, d7u8);
|
||||
q14u16 = vmlal_u8(q14u16, d3u8, d27u8);
|
||||
q14u16 = vmlal_u8(q14u16, d4u8, d23u8);
|
||||
|
||||
d0u8 = vbsl_u8(d20u8, dblimit, d4u8);
|
||||
|
||||
q14u16 = vaddw_u8(q14u16, d5u8);
|
||||
|
||||
d1u8 = vbsl_u8(d20u8, dlimit, d25u8);
|
||||
|
||||
d30u8 = vqrshrn_n_u16(q14u16, 3);
|
||||
|
||||
q14u16 = vsubw_u8(q14u16, d3u8);
|
||||
q14u16 = vsubw_u8(q14u16, d4u8);
|
||||
q14u16 = vaddw_u8(q14u16, d5u8);
|
||||
q14u16 = vaddw_u8(q14u16, d16u8);
|
||||
|
||||
d2u8 = vbsl_u8(d20u8, dthresh, d24u8);
|
||||
|
||||
d31u8 = vqrshrn_n_u16(q14u16, 3);
|
||||
|
||||
q14u16 = vsubw_u8(q14u16, d3u8);
|
||||
q14u16 = vsubw_u8(q14u16, d5u8);
|
||||
q14u16 = vaddw_u8(q14u16, d6u8);
|
||||
q14u16 = vaddw_u8(q14u16, d17u8);
|
||||
|
||||
*d0ru8 = vbsl_u8(d20u8, d30u8, d0u8);
|
||||
|
||||
d23u8 = vqrshrn_n_u16(q14u16, 3);
|
||||
|
||||
q14u16 = vsubw_u8(q14u16, d3u8);
|
||||
q14u16 = vsubw_u8(q14u16, d6u8);
|
||||
q14u16 = vaddw_u8(q14u16, d7u8);
|
||||
|
||||
*d1ru8 = vbsl_u8(d20u8, d31u8, d1u8);
|
||||
|
||||
q14u16 = vaddw_u8(q14u16, d18u8);
|
||||
|
||||
*d2ru8 = vbsl_u8(d20u8, d23u8, d2u8);
|
||||
|
||||
d22u8 = vqrshrn_n_u16(q14u16, 3);
|
||||
|
||||
q14u16 = vsubw_u8(q14u16, d4u8);
|
||||
q14u16 = vsubw_u8(q14u16, d7u8);
|
||||
q14u16 = vaddw_u8(q14u16, d16u8);
|
||||
|
||||
d3u8 = vbsl_u8(d20u8, d3u8, d21u8);
|
||||
|
||||
q14u16 = vaddw_u8(q14u16, d18u8);
|
||||
|
||||
d4u8 = vbsl_u8(d20u8, d4u8, d26u8);
|
||||
|
||||
d6u8 = vqrshrn_n_u16(q14u16, 3);
|
||||
|
||||
q14u16 = vsubw_u8(q14u16, d5u8);
|
||||
q14u16 = vsubw_u8(q14u16, d16u8);
|
||||
q14u16 = vaddw_u8(q14u16, d17u8);
|
||||
q14u16 = vaddw_u8(q14u16, d18u8);
|
||||
|
||||
d5u8 = vbsl_u8(d20u8, d5u8, d17u8);
|
||||
|
||||
d7u8 = vqrshrn_n_u16(q14u16, 3);
|
||||
|
||||
*d3ru8 = vbsl_u8(d20u8, d22u8, d3u8);
|
||||
*d4ru8 = vbsl_u8(d20u8, d6u8, d4u8);
|
||||
*d5ru8 = vbsl_u8(d20u8, d7u8, d5u8);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void aom_lpf_horizontal_8_neon(uint8_t *src, int pitch, const uint8_t *blimit,
|
||||
const uint8_t *limit, const uint8_t *thresh) {
|
||||
int i;
|
||||
uint8_t *s, *psrc;
|
||||
uint8x8_t dblimit, dlimit, dthresh;
|
||||
uint8x8_t d0u8, d1u8, d2u8, d3u8, d4u8, d5u8, d6u8, d7u8;
|
||||
uint8x8_t d16u8, d17u8, d18u8;
|
||||
|
||||
dblimit = vld1_u8(blimit);
|
||||
dlimit = vld1_u8(limit);
|
||||
dthresh = vld1_u8(thresh);
|
||||
|
||||
psrc = src - (pitch << 2);
|
||||
for (i = 0; i < 1; i++) {
|
||||
s = psrc + i * 8;
|
||||
|
||||
d3u8 = vld1_u8(s);
|
||||
s += pitch;
|
||||
d4u8 = vld1_u8(s);
|
||||
s += pitch;
|
||||
d5u8 = vld1_u8(s);
|
||||
s += pitch;
|
||||
d6u8 = vld1_u8(s);
|
||||
s += pitch;
|
||||
d7u8 = vld1_u8(s);
|
||||
s += pitch;
|
||||
d16u8 = vld1_u8(s);
|
||||
s += pitch;
|
||||
d17u8 = vld1_u8(s);
|
||||
s += pitch;
|
||||
d18u8 = vld1_u8(s);
|
||||
|
||||
mbloop_filter_neon(dblimit, dlimit, dthresh, d3u8, d4u8, d5u8, d6u8, d7u8,
|
||||
d16u8, d17u8, d18u8, &d0u8, &d1u8, &d2u8, &d3u8, &d4u8,
|
||||
&d5u8);
|
||||
|
||||
s -= (pitch * 6);
|
||||
vst1_u8(s, d0u8);
|
||||
s += pitch;
|
||||
vst1_u8(s, d1u8);
|
||||
s += pitch;
|
||||
vst1_u8(s, d2u8);
|
||||
s += pitch;
|
||||
vst1_u8(s, d3u8);
|
||||
s += pitch;
|
||||
vst1_u8(s, d4u8);
|
||||
s += pitch;
|
||||
vst1_u8(s, d5u8);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void aom_lpf_vertical_8_neon(uint8_t *src, int pitch, const uint8_t *blimit,
|
||||
const uint8_t *limit, const uint8_t *thresh) {
|
||||
int i;
|
||||
uint8_t *s;
|
||||
uint8x8_t dblimit, dlimit, dthresh;
|
||||
uint8x8_t d0u8, d1u8, d2u8, d3u8, d4u8, d5u8, d6u8, d7u8;
|
||||
uint8x8_t d16u8, d17u8, d18u8;
|
||||
uint32x2x2_t d2tmp0, d2tmp1, d2tmp2, d2tmp3;
|
||||
uint16x4x2_t d2tmp4, d2tmp5, d2tmp6, d2tmp7;
|
||||
uint8x8x2_t d2tmp8, d2tmp9, d2tmp10, d2tmp11;
|
||||
uint8x8x4_t d4Result;
|
||||
uint8x8x2_t d2Result;
|
||||
|
||||
dblimit = vld1_u8(blimit);
|
||||
dlimit = vld1_u8(limit);
|
||||
dthresh = vld1_u8(thresh);
|
||||
|
||||
for (i = 0; i < 1; i++) {
|
||||
s = src + (i * (pitch << 3)) - 4;
|
||||
|
||||
d3u8 = vld1_u8(s);
|
||||
s += pitch;
|
||||
d4u8 = vld1_u8(s);
|
||||
s += pitch;
|
||||
d5u8 = vld1_u8(s);
|
||||
s += pitch;
|
||||
d6u8 = vld1_u8(s);
|
||||
s += pitch;
|
||||
d7u8 = vld1_u8(s);
|
||||
s += pitch;
|
||||
d16u8 = vld1_u8(s);
|
||||
s += pitch;
|
||||
d17u8 = vld1_u8(s);
|
||||
s += pitch;
|
||||
d18u8 = vld1_u8(s);
|
||||
|
||||
d2tmp0 = vtrn_u32(vreinterpret_u32_u8(d3u8), vreinterpret_u32_u8(d7u8));
|
||||
d2tmp1 = vtrn_u32(vreinterpret_u32_u8(d4u8), vreinterpret_u32_u8(d16u8));
|
||||
d2tmp2 = vtrn_u32(vreinterpret_u32_u8(d5u8), vreinterpret_u32_u8(d17u8));
|
||||
d2tmp3 = vtrn_u32(vreinterpret_u32_u8(d6u8), vreinterpret_u32_u8(d18u8));
|
||||
|
||||
d2tmp4 = vtrn_u16(vreinterpret_u16_u32(d2tmp0.val[0]),
|
||||
vreinterpret_u16_u32(d2tmp2.val[0]));
|
||||
d2tmp5 = vtrn_u16(vreinterpret_u16_u32(d2tmp1.val[0]),
|
||||
vreinterpret_u16_u32(d2tmp3.val[0]));
|
||||
d2tmp6 = vtrn_u16(vreinterpret_u16_u32(d2tmp0.val[1]),
|
||||
vreinterpret_u16_u32(d2tmp2.val[1]));
|
||||
d2tmp7 = vtrn_u16(vreinterpret_u16_u32(d2tmp1.val[1]),
|
||||
vreinterpret_u16_u32(d2tmp3.val[1]));
|
||||
|
||||
d2tmp8 = vtrn_u8(vreinterpret_u8_u16(d2tmp4.val[0]),
|
||||
vreinterpret_u8_u16(d2tmp5.val[0]));
|
||||
d2tmp9 = vtrn_u8(vreinterpret_u8_u16(d2tmp4.val[1]),
|
||||
vreinterpret_u8_u16(d2tmp5.val[1]));
|
||||
d2tmp10 = vtrn_u8(vreinterpret_u8_u16(d2tmp6.val[0]),
|
||||
vreinterpret_u8_u16(d2tmp7.val[0]));
|
||||
d2tmp11 = vtrn_u8(vreinterpret_u8_u16(d2tmp6.val[1]),
|
||||
vreinterpret_u8_u16(d2tmp7.val[1]));
|
||||
|
||||
d3u8 = d2tmp8.val[0];
|
||||
d4u8 = d2tmp8.val[1];
|
||||
d5u8 = d2tmp9.val[0];
|
||||
d6u8 = d2tmp9.val[1];
|
||||
d7u8 = d2tmp10.val[0];
|
||||
d16u8 = d2tmp10.val[1];
|
||||
d17u8 = d2tmp11.val[0];
|
||||
d18u8 = d2tmp11.val[1];
|
||||
|
||||
mbloop_filter_neon(dblimit, dlimit, dthresh, d3u8, d4u8, d5u8, d6u8, d7u8,
|
||||
d16u8, d17u8, d18u8, &d0u8, &d1u8, &d2u8, &d3u8, &d4u8,
|
||||
&d5u8);
|
||||
|
||||
d4Result.val[0] = d0u8;
|
||||
d4Result.val[1] = d1u8;
|
||||
d4Result.val[2] = d2u8;
|
||||
d4Result.val[3] = d3u8;
|
||||
|
||||
d2Result.val[0] = d4u8;
|
||||
d2Result.val[1] = d5u8;
|
||||
|
||||
s = src - 3;
|
||||
vst4_lane_u8(s, d4Result, 0);
|
||||
s += pitch;
|
||||
vst4_lane_u8(s, d4Result, 1);
|
||||
s += pitch;
|
||||
vst4_lane_u8(s, d4Result, 2);
|
||||
s += pitch;
|
||||
vst4_lane_u8(s, d4Result, 3);
|
||||
s += pitch;
|
||||
vst4_lane_u8(s, d4Result, 4);
|
||||
s += pitch;
|
||||
vst4_lane_u8(s, d4Result, 5);
|
||||
s += pitch;
|
||||
vst4_lane_u8(s, d4Result, 6);
|
||||
s += pitch;
|
||||
vst4_lane_u8(s, d4Result, 7);
|
||||
|
||||
s = src + 1;
|
||||
vst2_lane_u8(s, d2Result, 0);
|
||||
s += pitch;
|
||||
vst2_lane_u8(s, d2Result, 1);
|
||||
s += pitch;
|
||||
vst2_lane_u8(s, d2Result, 2);
|
||||
s += pitch;
|
||||
vst2_lane_u8(s, d2Result, 3);
|
||||
s += pitch;
|
||||
vst2_lane_u8(s, d2Result, 4);
|
||||
s += pitch;
|
||||
vst2_lane_u8(s, d2Result, 5);
|
||||
s += pitch;
|
||||
vst2_lane_u8(s, d2Result, 6);
|
||||
s += pitch;
|
||||
vst2_lane_u8(s, d2Result, 7);
|
||||
}
|
||||
return;
|
||||
}
|
||||
638
third_party/aom/aom_dsp/arm/loopfilter_mb_neon.asm
vendored
Normal file
638
third_party/aom/aom_dsp/arm/loopfilter_mb_neon.asm
vendored
Normal file
|
|
@ -0,0 +1,638 @@
|
|||
;
|
||||
; Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
;
|
||||
; This source code is subject to the terms of the BSD 2 Clause License and
|
||||
; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
; was not distributed with this source code in the LICENSE file, you can
|
||||
; obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
; Media Patent License 1.0 was not distributed with this source code in the
|
||||
; PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
;
|
||||
|
||||
;
|
||||
|
||||
EXPORT |aom_lpf_horizontal_edge_8_neon|
|
||||
EXPORT |aom_lpf_horizontal_edge_16_neon|
|
||||
EXPORT |aom_lpf_vertical_16_neon|
|
||||
ARM
|
||||
|
||||
AREA ||.text||, CODE, READONLY, ALIGN=2
|
||||
|
||||
; void mb_lpf_horizontal_edge(uint8_t *s, int p,
|
||||
; const uint8_t *blimit,
|
||||
; const uint8_t *limit,
|
||||
; const uint8_t *thresh,
|
||||
; int count)
|
||||
; r0 uint8_t *s,
|
||||
; r1 int p, /* pitch */
|
||||
; r2 const uint8_t *blimit,
|
||||
; r3 const uint8_t *limit,
|
||||
; sp const uint8_t *thresh,
|
||||
; r12 int count
|
||||
|mb_lpf_horizontal_edge| PROC
|
||||
push {r4-r8, lr}
|
||||
vpush {d8-d15}
|
||||
ldr r4, [sp, #88] ; load thresh
|
||||
|
||||
h_count
|
||||
vld1.8 {d16[]}, [r2] ; load *blimit
|
||||
vld1.8 {d17[]}, [r3] ; load *limit
|
||||
vld1.8 {d18[]}, [r4] ; load *thresh
|
||||
|
||||
sub r8, r0, r1, lsl #3 ; move src pointer down by 8 lines
|
||||
|
||||
vld1.u8 {d0}, [r8@64], r1 ; p7
|
||||
vld1.u8 {d1}, [r8@64], r1 ; p6
|
||||
vld1.u8 {d2}, [r8@64], r1 ; p5
|
||||
vld1.u8 {d3}, [r8@64], r1 ; p4
|
||||
vld1.u8 {d4}, [r8@64], r1 ; p3
|
||||
vld1.u8 {d5}, [r8@64], r1 ; p2
|
||||
vld1.u8 {d6}, [r8@64], r1 ; p1
|
||||
vld1.u8 {d7}, [r8@64], r1 ; p0
|
||||
vld1.u8 {d8}, [r8@64], r1 ; q0
|
||||
vld1.u8 {d9}, [r8@64], r1 ; q1
|
||||
vld1.u8 {d10}, [r8@64], r1 ; q2
|
||||
vld1.u8 {d11}, [r8@64], r1 ; q3
|
||||
vld1.u8 {d12}, [r8@64], r1 ; q4
|
||||
vld1.u8 {d13}, [r8@64], r1 ; q5
|
||||
vld1.u8 {d14}, [r8@64], r1 ; q6
|
||||
vld1.u8 {d15}, [r8@64], r1 ; q7
|
||||
|
||||
bl aom_wide_mbfilter_neon
|
||||
|
||||
tst r7, #1
|
||||
beq h_mbfilter
|
||||
|
||||
; flat && mask were not set for any of the channels. Just store the values
|
||||
; from filter.
|
||||
sub r8, r0, r1, lsl #1
|
||||
|
||||
vst1.u8 {d25}, [r8@64], r1 ; store op1
|
||||
vst1.u8 {d24}, [r8@64], r1 ; store op0
|
||||
vst1.u8 {d23}, [r8@64], r1 ; store oq0
|
||||
vst1.u8 {d26}, [r8@64], r1 ; store oq1
|
||||
|
||||
b h_next
|
||||
|
||||
h_mbfilter
|
||||
tst r7, #2
|
||||
beq h_wide_mbfilter
|
||||
|
||||
; flat2 was not set for any of the channels. Just store the values from
|
||||
; mbfilter.
|
||||
sub r8, r0, r1, lsl #1
|
||||
sub r8, r8, r1
|
||||
|
||||
vst1.u8 {d18}, [r8@64], r1 ; store op2
|
||||
vst1.u8 {d19}, [r8@64], r1 ; store op1
|
||||
vst1.u8 {d20}, [r8@64], r1 ; store op0
|
||||
vst1.u8 {d21}, [r8@64], r1 ; store oq0
|
||||
vst1.u8 {d22}, [r8@64], r1 ; store oq1
|
||||
vst1.u8 {d23}, [r8@64], r1 ; store oq2
|
||||
|
||||
b h_next
|
||||
|
||||
h_wide_mbfilter
|
||||
sub r8, r0, r1, lsl #3
|
||||
add r8, r8, r1
|
||||
|
||||
vst1.u8 {d16}, [r8@64], r1 ; store op6
|
||||
vst1.u8 {d24}, [r8@64], r1 ; store op5
|
||||
vst1.u8 {d25}, [r8@64], r1 ; store op4
|
||||
vst1.u8 {d26}, [r8@64], r1 ; store op3
|
||||
vst1.u8 {d27}, [r8@64], r1 ; store op2
|
||||
vst1.u8 {d18}, [r8@64], r1 ; store op1
|
||||
vst1.u8 {d19}, [r8@64], r1 ; store op0
|
||||
vst1.u8 {d20}, [r8@64], r1 ; store oq0
|
||||
vst1.u8 {d21}, [r8@64], r1 ; store oq1
|
||||
vst1.u8 {d22}, [r8@64], r1 ; store oq2
|
||||
vst1.u8 {d23}, [r8@64], r1 ; store oq3
|
||||
vst1.u8 {d1}, [r8@64], r1 ; store oq4
|
||||
vst1.u8 {d2}, [r8@64], r1 ; store oq5
|
||||
vst1.u8 {d3}, [r8@64], r1 ; store oq6
|
||||
|
||||
h_next
|
||||
add r0, r0, #8
|
||||
subs r12, r12, #1
|
||||
bne h_count
|
||||
|
||||
vpop {d8-d15}
|
||||
pop {r4-r8, pc}
|
||||
|
||||
ENDP ; |mb_lpf_horizontal_edge|
|
||||
|
||||
; void aom_lpf_horizontal_edge_8_neon(uint8_t *s, int pitch,
|
||||
; const uint8_t *blimit,
|
||||
; const uint8_t *limit,
|
||||
; const uint8_t *thresh)
|
||||
; r0 uint8_t *s,
|
||||
; r1 int pitch,
|
||||
; r2 const uint8_t *blimit,
|
||||
; r3 const uint8_t *limit,
|
||||
; sp const uint8_t *thresh
|
||||
|aom_lpf_horizontal_edge_8_neon| PROC
|
||||
mov r12, #1
|
||||
b mb_lpf_horizontal_edge
|
||||
ENDP ; |aom_lpf_horizontal_edge_8_neon|
|
||||
|
||||
; void aom_lpf_horizontal_edge_16_neon(uint8_t *s, int pitch,
|
||||
; const uint8_t *blimit,
|
||||
; const uint8_t *limit,
|
||||
; const uint8_t *thresh)
|
||||
; r0 uint8_t *s,
|
||||
; r1 int pitch,
|
||||
; r2 const uint8_t *blimit,
|
||||
; r3 const uint8_t *limit,
|
||||
; sp const uint8_t *thresh
|
||||
|aom_lpf_horizontal_edge_16_neon| PROC
|
||||
mov r12, #2
|
||||
b mb_lpf_horizontal_edge
|
||||
ENDP ; |aom_lpf_horizontal_edge_16_neon|
|
||||
|
||||
; void aom_lpf_vertical_16_neon(uint8_t *s, int p,
|
||||
; const uint8_t *blimit,
|
||||
; const uint8_t *limit,
|
||||
; const uint8_t *thresh)
|
||||
; r0 uint8_t *s,
|
||||
; r1 int p, /* pitch */
|
||||
; r2 const uint8_t *blimit,
|
||||
; r3 const uint8_t *limit,
|
||||
; sp const uint8_t *thresh,
|
||||
|aom_lpf_vertical_16_neon| PROC
|
||||
push {r4-r8, lr}
|
||||
vpush {d8-d15}
|
||||
ldr r4, [sp, #88] ; load thresh
|
||||
|
||||
vld1.8 {d16[]}, [r2] ; load *blimit
|
||||
vld1.8 {d17[]}, [r3] ; load *limit
|
||||
vld1.8 {d18[]}, [r4] ; load *thresh
|
||||
|
||||
sub r8, r0, #8
|
||||
|
||||
vld1.8 {d0}, [r8@64], r1
|
||||
vld1.8 {d8}, [r0@64], r1
|
||||
vld1.8 {d1}, [r8@64], r1
|
||||
vld1.8 {d9}, [r0@64], r1
|
||||
vld1.8 {d2}, [r8@64], r1
|
||||
vld1.8 {d10}, [r0@64], r1
|
||||
vld1.8 {d3}, [r8@64], r1
|
||||
vld1.8 {d11}, [r0@64], r1
|
||||
vld1.8 {d4}, [r8@64], r1
|
||||
vld1.8 {d12}, [r0@64], r1
|
||||
vld1.8 {d5}, [r8@64], r1
|
||||
vld1.8 {d13}, [r0@64], r1
|
||||
vld1.8 {d6}, [r8@64], r1
|
||||
vld1.8 {d14}, [r0@64], r1
|
||||
vld1.8 {d7}, [r8@64], r1
|
||||
vld1.8 {d15}, [r0@64], r1
|
||||
|
||||
sub r0, r0, r1, lsl #3
|
||||
|
||||
vtrn.32 q0, q2
|
||||
vtrn.32 q1, q3
|
||||
vtrn.32 q4, q6
|
||||
vtrn.32 q5, q7
|
||||
|
||||
vtrn.16 q0, q1
|
||||
vtrn.16 q2, q3
|
||||
vtrn.16 q4, q5
|
||||
vtrn.16 q6, q7
|
||||
|
||||
vtrn.8 d0, d1
|
||||
vtrn.8 d2, d3
|
||||
vtrn.8 d4, d5
|
||||
vtrn.8 d6, d7
|
||||
|
||||
vtrn.8 d8, d9
|
||||
vtrn.8 d10, d11
|
||||
vtrn.8 d12, d13
|
||||
vtrn.8 d14, d15
|
||||
|
||||
bl aom_wide_mbfilter_neon
|
||||
|
||||
tst r7, #1
|
||||
beq v_mbfilter
|
||||
|
||||
; flat && mask were not set for any of the channels. Just store the values
|
||||
; from filter.
|
||||
sub r8, r0, #2
|
||||
|
||||
vswp d23, d25
|
||||
|
||||
vst4.8 {d23[0], d24[0], d25[0], d26[0]}, [r8], r1
|
||||
vst4.8 {d23[1], d24[1], d25[1], d26[1]}, [r8], r1
|
||||
vst4.8 {d23[2], d24[2], d25[2], d26[2]}, [r8], r1
|
||||
vst4.8 {d23[3], d24[3], d25[3], d26[3]}, [r8], r1
|
||||
vst4.8 {d23[4], d24[4], d25[4], d26[4]}, [r8], r1
|
||||
vst4.8 {d23[5], d24[5], d25[5], d26[5]}, [r8], r1
|
||||
vst4.8 {d23[6], d24[6], d25[6], d26[6]}, [r8], r1
|
||||
vst4.8 {d23[7], d24[7], d25[7], d26[7]}, [r8], r1
|
||||
|
||||
b v_end
|
||||
|
||||
v_mbfilter
|
||||
tst r7, #2
|
||||
beq v_wide_mbfilter
|
||||
|
||||
; flat2 was not set for any of the channels. Just store the values from
|
||||
; mbfilter.
|
||||
sub r8, r0, #3
|
||||
|
||||
vst3.8 {d18[0], d19[0], d20[0]}, [r8], r1
|
||||
vst3.8 {d21[0], d22[0], d23[0]}, [r0], r1
|
||||
vst3.8 {d18[1], d19[1], d20[1]}, [r8], r1
|
||||
vst3.8 {d21[1], d22[1], d23[1]}, [r0], r1
|
||||
vst3.8 {d18[2], d19[2], d20[2]}, [r8], r1
|
||||
vst3.8 {d21[2], d22[2], d23[2]}, [r0], r1
|
||||
vst3.8 {d18[3], d19[3], d20[3]}, [r8], r1
|
||||
vst3.8 {d21[3], d22[3], d23[3]}, [r0], r1
|
||||
vst3.8 {d18[4], d19[4], d20[4]}, [r8], r1
|
||||
vst3.8 {d21[4], d22[4], d23[4]}, [r0], r1
|
||||
vst3.8 {d18[5], d19[5], d20[5]}, [r8], r1
|
||||
vst3.8 {d21[5], d22[5], d23[5]}, [r0], r1
|
||||
vst3.8 {d18[6], d19[6], d20[6]}, [r8], r1
|
||||
vst3.8 {d21[6], d22[6], d23[6]}, [r0], r1
|
||||
vst3.8 {d18[7], d19[7], d20[7]}, [r8], r1
|
||||
vst3.8 {d21[7], d22[7], d23[7]}, [r0], r1
|
||||
|
||||
b v_end
|
||||
|
||||
v_wide_mbfilter
|
||||
sub r8, r0, #8
|
||||
|
||||
vtrn.32 d0, d26
|
||||
vtrn.32 d16, d27
|
||||
vtrn.32 d24, d18
|
||||
vtrn.32 d25, d19
|
||||
|
||||
vtrn.16 d0, d24
|
||||
vtrn.16 d16, d25
|
||||
vtrn.16 d26, d18
|
||||
vtrn.16 d27, d19
|
||||
|
||||
vtrn.8 d0, d16
|
||||
vtrn.8 d24, d25
|
||||
vtrn.8 d26, d27
|
||||
vtrn.8 d18, d19
|
||||
|
||||
vtrn.32 d20, d1
|
||||
vtrn.32 d21, d2
|
||||
vtrn.32 d22, d3
|
||||
vtrn.32 d23, d15
|
||||
|
||||
vtrn.16 d20, d22
|
||||
vtrn.16 d21, d23
|
||||
vtrn.16 d1, d3
|
||||
vtrn.16 d2, d15
|
||||
|
||||
vtrn.8 d20, d21
|
||||
vtrn.8 d22, d23
|
||||
vtrn.8 d1, d2
|
||||
vtrn.8 d3, d15
|
||||
|
||||
vst1.8 {d0}, [r8@64], r1
|
||||
vst1.8 {d20}, [r0@64], r1
|
||||
vst1.8 {d16}, [r8@64], r1
|
||||
vst1.8 {d21}, [r0@64], r1
|
||||
vst1.8 {d24}, [r8@64], r1
|
||||
vst1.8 {d22}, [r0@64], r1
|
||||
vst1.8 {d25}, [r8@64], r1
|
||||
vst1.8 {d23}, [r0@64], r1
|
||||
vst1.8 {d26}, [r8@64], r1
|
||||
vst1.8 {d1}, [r0@64], r1
|
||||
vst1.8 {d27}, [r8@64], r1
|
||||
vst1.8 {d2}, [r0@64], r1
|
||||
vst1.8 {d18}, [r8@64], r1
|
||||
vst1.8 {d3}, [r0@64], r1
|
||||
vst1.8 {d19}, [r8@64], r1
|
||||
vst1.8 {d15}, [r0@64], r1
|
||||
|
||||
v_end
|
||||
vpop {d8-d15}
|
||||
pop {r4-r8, pc}
|
||||
|
||||
ENDP ; |aom_lpf_vertical_16_neon|
|
||||
|
||||
; void aom_wide_mbfilter_neon();
|
||||
; This is a helper function for the loopfilters. The invidual functions do the
|
||||
; necessary load, transpose (if necessary) and store.
|
||||
;
|
||||
; r0-r3 PRESERVE
|
||||
; d16 blimit
|
||||
; d17 limit
|
||||
; d18 thresh
|
||||
; d0 p7
|
||||
; d1 p6
|
||||
; d2 p5
|
||||
; d3 p4
|
||||
; d4 p3
|
||||
; d5 p2
|
||||
; d6 p1
|
||||
; d7 p0
|
||||
; d8 q0
|
||||
; d9 q1
|
||||
; d10 q2
|
||||
; d11 q3
|
||||
; d12 q4
|
||||
; d13 q5
|
||||
; d14 q6
|
||||
; d15 q7
|
||||
|aom_wide_mbfilter_neon| PROC
|
||||
mov r7, #0
|
||||
|
||||
; filter_mask
|
||||
vabd.u8 d19, d4, d5 ; abs(p3 - p2)
|
||||
vabd.u8 d20, d5, d6 ; abs(p2 - p1)
|
||||
vabd.u8 d21, d6, d7 ; abs(p1 - p0)
|
||||
vabd.u8 d22, d9, d8 ; abs(q1 - q0)
|
||||
vabd.u8 d23, d10, d9 ; abs(q2 - q1)
|
||||
vabd.u8 d24, d11, d10 ; abs(q3 - q2)
|
||||
|
||||
; only compare the largest value to limit
|
||||
vmax.u8 d19, d19, d20 ; max(abs(p3 - p2), abs(p2 - p1))
|
||||
vmax.u8 d20, d21, d22 ; max(abs(p1 - p0), abs(q1 - q0))
|
||||
vmax.u8 d23, d23, d24 ; max(abs(q2 - q1), abs(q3 - q2))
|
||||
vmax.u8 d19, d19, d20
|
||||
|
||||
vabd.u8 d24, d7, d8 ; abs(p0 - q0)
|
||||
|
||||
vmax.u8 d19, d19, d23
|
||||
|
||||
vabd.u8 d23, d6, d9 ; a = abs(p1 - q1)
|
||||
vqadd.u8 d24, d24, d24 ; b = abs(p0 - q0) * 2
|
||||
|
||||
; abs () > limit
|
||||
vcge.u8 d19, d17, d19
|
||||
|
||||
; flatmask4
|
||||
vabd.u8 d25, d7, d5 ; abs(p0 - p2)
|
||||
vabd.u8 d26, d8, d10 ; abs(q0 - q2)
|
||||
vabd.u8 d27, d4, d7 ; abs(p3 - p0)
|
||||
vabd.u8 d28, d11, d8 ; abs(q3 - q0)
|
||||
|
||||
; only compare the largest value to thresh
|
||||
vmax.u8 d25, d25, d26 ; max(abs(p0 - p2), abs(q0 - q2))
|
||||
vmax.u8 d26, d27, d28 ; max(abs(p3 - p0), abs(q3 - q0))
|
||||
vmax.u8 d25, d25, d26
|
||||
vmax.u8 d20, d20, d25
|
||||
|
||||
vshr.u8 d23, d23, #1 ; a = a / 2
|
||||
vqadd.u8 d24, d24, d23 ; a = b + a
|
||||
|
||||
vmov.u8 d30, #1
|
||||
vcge.u8 d24, d16, d24 ; (a > blimit * 2 + limit) * -1
|
||||
|
||||
vcge.u8 d20, d30, d20 ; flat
|
||||
|
||||
vand d19, d19, d24 ; mask
|
||||
|
||||
; hevmask
|
||||
vcgt.u8 d21, d21, d18 ; (abs(p1 - p0) > thresh)*-1
|
||||
vcgt.u8 d22, d22, d18 ; (abs(q1 - q0) > thresh)*-1
|
||||
vorr d21, d21, d22 ; hev
|
||||
|
||||
vand d16, d20, d19 ; flat && mask
|
||||
vmov r5, r6, d16
|
||||
|
||||
; flatmask5(1, p7, p6, p5, p4, p0, q0, q4, q5, q6, q7)
|
||||
vabd.u8 d22, d3, d7 ; abs(p4 - p0)
|
||||
vabd.u8 d23, d12, d8 ; abs(q4 - q0)
|
||||
vabd.u8 d24, d7, d2 ; abs(p0 - p5)
|
||||
vabd.u8 d25, d8, d13 ; abs(q0 - q5)
|
||||
vabd.u8 d26, d1, d7 ; abs(p6 - p0)
|
||||
vabd.u8 d27, d14, d8 ; abs(q6 - q0)
|
||||
vabd.u8 d28, d0, d7 ; abs(p7 - p0)
|
||||
vabd.u8 d29, d15, d8 ; abs(q7 - q0)
|
||||
|
||||
; only compare the largest value to thresh
|
||||
vmax.u8 d22, d22, d23 ; max(abs(p4 - p0), abs(q4 - q0))
|
||||
vmax.u8 d23, d24, d25 ; max(abs(p0 - p5), abs(q0 - q5))
|
||||
vmax.u8 d24, d26, d27 ; max(abs(p6 - p0), abs(q6 - q0))
|
||||
vmax.u8 d25, d28, d29 ; max(abs(p7 - p0), abs(q7 - q0))
|
||||
|
||||
vmax.u8 d26, d22, d23
|
||||
vmax.u8 d27, d24, d25
|
||||
vmax.u8 d23, d26, d27
|
||||
|
||||
vcge.u8 d18, d30, d23 ; flat2
|
||||
|
||||
vmov.u8 d22, #0x80
|
||||
|
||||
orrs r5, r5, r6 ; Check for 0
|
||||
orreq r7, r7, #1 ; Only do filter branch
|
||||
|
||||
vand d17, d18, d16 ; flat2 && flat && mask
|
||||
vmov r5, r6, d17
|
||||
|
||||
; mbfilter() function
|
||||
|
||||
; filter() function
|
||||
; convert to signed
|
||||
veor d23, d8, d22 ; qs0
|
||||
veor d24, d7, d22 ; ps0
|
||||
veor d25, d6, d22 ; ps1
|
||||
veor d26, d9, d22 ; qs1
|
||||
|
||||
vmov.u8 d27, #3
|
||||
|
||||
vsub.s8 d28, d23, d24 ; ( qs0 - ps0)
|
||||
vqsub.s8 d29, d25, d26 ; filter = clamp(ps1-qs1)
|
||||
vmull.s8 q15, d28, d27 ; 3 * ( qs0 - ps0)
|
||||
vand d29, d29, d21 ; filter &= hev
|
||||
vaddw.s8 q15, q15, d29 ; filter + 3 * (qs0 - ps0)
|
||||
vmov.u8 d29, #4
|
||||
|
||||
; filter = clamp(filter + 3 * ( qs0 - ps0))
|
||||
vqmovn.s16 d28, q15
|
||||
|
||||
vand d28, d28, d19 ; filter &= mask
|
||||
|
||||
vqadd.s8 d30, d28, d27 ; filter2 = clamp(filter+3)
|
||||
vqadd.s8 d29, d28, d29 ; filter1 = clamp(filter+4)
|
||||
vshr.s8 d30, d30, #3 ; filter2 >>= 3
|
||||
vshr.s8 d29, d29, #3 ; filter1 >>= 3
|
||||
|
||||
|
||||
vqadd.s8 d24, d24, d30 ; op0 = clamp(ps0 + filter2)
|
||||
vqsub.s8 d23, d23, d29 ; oq0 = clamp(qs0 - filter1)
|
||||
|
||||
; outer tap adjustments: ++filter1 >> 1
|
||||
vrshr.s8 d29, d29, #1
|
||||
vbic d29, d29, d21 ; filter &= ~hev
|
||||
|
||||
vqadd.s8 d25, d25, d29 ; op1 = clamp(ps1 + filter)
|
||||
vqsub.s8 d26, d26, d29 ; oq1 = clamp(qs1 - filter)
|
||||
|
||||
veor d24, d24, d22 ; *f_op0 = u^0x80
|
||||
veor d23, d23, d22 ; *f_oq0 = u^0x80
|
||||
veor d25, d25, d22 ; *f_op1 = u^0x80
|
||||
veor d26, d26, d22 ; *f_oq1 = u^0x80
|
||||
|
||||
tst r7, #1
|
||||
bxne lr
|
||||
|
||||
orrs r5, r5, r6 ; Check for 0
|
||||
orreq r7, r7, #2 ; Only do mbfilter branch
|
||||
|
||||
; mbfilter flat && mask branch
|
||||
; TODO(fgalligan): Can I decrease the cycles shifting to consective d's
|
||||
; and using vibt on the q's?
|
||||
vmov.u8 d29, #2
|
||||
vaddl.u8 q15, d7, d8 ; op2 = p0 + q0
|
||||
vmlal.u8 q15, d4, d27 ; op2 = p0 + q0 + p3 * 3
|
||||
vmlal.u8 q15, d5, d29 ; op2 = p0 + q0 + p3 * 3 + p2 * 2
|
||||
vaddl.u8 q10, d4, d5
|
||||
vaddw.u8 q15, d6 ; op2=p1 + p0 + q0 + p3 * 3 + p2 *2
|
||||
vaddl.u8 q14, d6, d9
|
||||
vqrshrn.u16 d18, q15, #3 ; r_op2
|
||||
|
||||
vsub.i16 q15, q10
|
||||
vaddl.u8 q10, d4, d6
|
||||
vadd.i16 q15, q14
|
||||
vaddl.u8 q14, d7, d10
|
||||
vqrshrn.u16 d19, q15, #3 ; r_op1
|
||||
|
||||
vsub.i16 q15, q10
|
||||
vadd.i16 q15, q14
|
||||
vaddl.u8 q14, d8, d11
|
||||
vqrshrn.u16 d20, q15, #3 ; r_op0
|
||||
|
||||
vsubw.u8 q15, d4 ; oq0 = op0 - p3
|
||||
vsubw.u8 q15, d7 ; oq0 -= p0
|
||||
vadd.i16 q15, q14
|
||||
vaddl.u8 q14, d9, d11
|
||||
vqrshrn.u16 d21, q15, #3 ; r_oq0
|
||||
|
||||
vsubw.u8 q15, d5 ; oq1 = oq0 - p2
|
||||
vsubw.u8 q15, d8 ; oq1 -= q0
|
||||
vadd.i16 q15, q14
|
||||
vaddl.u8 q14, d10, d11
|
||||
vqrshrn.u16 d22, q15, #3 ; r_oq1
|
||||
|
||||
vsubw.u8 q15, d6 ; oq2 = oq0 - p1
|
||||
vsubw.u8 q15, d9 ; oq2 -= q1
|
||||
vadd.i16 q15, q14
|
||||
vqrshrn.u16 d27, q15, #3 ; r_oq2
|
||||
|
||||
; Filter does not set op2 or oq2, so use p2 and q2.
|
||||
vbif d18, d5, d16 ; t_op2 |= p2 & ~(flat & mask)
|
||||
vbif d19, d25, d16 ; t_op1 |= f_op1 & ~(flat & mask)
|
||||
vbif d20, d24, d16 ; t_op0 |= f_op0 & ~(flat & mask)
|
||||
vbif d21, d23, d16 ; t_oq0 |= f_oq0 & ~(flat & mask)
|
||||
vbif d22, d26, d16 ; t_oq1 |= f_oq1 & ~(flat & mask)
|
||||
|
||||
vbit d23, d27, d16 ; t_oq2 |= r_oq2 & (flat & mask)
|
||||
vbif d23, d10, d16 ; t_oq2 |= q2 & ~(flat & mask)
|
||||
|
||||
tst r7, #2
|
||||
bxne lr
|
||||
|
||||
; wide_mbfilter flat2 && flat && mask branch
|
||||
vmov.u8 d16, #7
|
||||
vaddl.u8 q15, d7, d8 ; op6 = p0 + q0
|
||||
vaddl.u8 q12, d2, d3
|
||||
vaddl.u8 q13, d4, d5
|
||||
vaddl.u8 q14, d1, d6
|
||||
vmlal.u8 q15, d0, d16 ; op6 += p7 * 3
|
||||
vadd.i16 q12, q13
|
||||
vadd.i16 q15, q14
|
||||
vaddl.u8 q14, d2, d9
|
||||
vadd.i16 q15, q12
|
||||
vaddl.u8 q12, d0, d1
|
||||
vaddw.u8 q15, d1
|
||||
vaddl.u8 q13, d0, d2
|
||||
vadd.i16 q14, q15, q14
|
||||
vqrshrn.u16 d16, q15, #4 ; w_op6
|
||||
|
||||
vsub.i16 q15, q14, q12
|
||||
vaddl.u8 q14, d3, d10
|
||||
vqrshrn.u16 d24, q15, #4 ; w_op5
|
||||
|
||||
vsub.i16 q15, q13
|
||||
vaddl.u8 q13, d0, d3
|
||||
vadd.i16 q15, q14
|
||||
vaddl.u8 q14, d4, d11
|
||||
vqrshrn.u16 d25, q15, #4 ; w_op4
|
||||
|
||||
vadd.i16 q15, q14
|
||||
vaddl.u8 q14, d0, d4
|
||||
vsub.i16 q15, q13
|
||||
vsub.i16 q14, q15, q14
|
||||
vqrshrn.u16 d26, q15, #4 ; w_op3
|
||||
|
||||
vaddw.u8 q15, q14, d5 ; op2 += p2
|
||||
vaddl.u8 q14, d0, d5
|
||||
vaddw.u8 q15, d12 ; op2 += q4
|
||||
vbif d26, d4, d17 ; op3 |= p3 & ~(f2 & f & m)
|
||||
vqrshrn.u16 d27, q15, #4 ; w_op2
|
||||
|
||||
vsub.i16 q15, q14
|
||||
vaddl.u8 q14, d0, d6
|
||||
vaddw.u8 q15, d6 ; op1 += p1
|
||||
vaddw.u8 q15, d13 ; op1 += q5
|
||||
vbif d27, d18, d17 ; op2 |= t_op2 & ~(f2 & f & m)
|
||||
vqrshrn.u16 d18, q15, #4 ; w_op1
|
||||
|
||||
vsub.i16 q15, q14
|
||||
vaddl.u8 q14, d0, d7
|
||||
vaddw.u8 q15, d7 ; op0 += p0
|
||||
vaddw.u8 q15, d14 ; op0 += q6
|
||||
vbif d18, d19, d17 ; op1 |= t_op1 & ~(f2 & f & m)
|
||||
vqrshrn.u16 d19, q15, #4 ; w_op0
|
||||
|
||||
vsub.i16 q15, q14
|
||||
vaddl.u8 q14, d1, d8
|
||||
vaddw.u8 q15, d8 ; oq0 += q0
|
||||
vaddw.u8 q15, d15 ; oq0 += q7
|
||||
vbif d19, d20, d17 ; op0 |= t_op0 & ~(f2 & f & m)
|
||||
vqrshrn.u16 d20, q15, #4 ; w_oq0
|
||||
|
||||
vsub.i16 q15, q14
|
||||
vaddl.u8 q14, d2, d9
|
||||
vaddw.u8 q15, d9 ; oq1 += q1
|
||||
vaddl.u8 q4, d10, d15
|
||||
vaddw.u8 q15, d15 ; oq1 += q7
|
||||
vbif d20, d21, d17 ; oq0 |= t_oq0 & ~(f2 & f & m)
|
||||
vqrshrn.u16 d21, q15, #4 ; w_oq1
|
||||
|
||||
vsub.i16 q15, q14
|
||||
vaddl.u8 q14, d3, d10
|
||||
vadd.i16 q15, q4
|
||||
vaddl.u8 q4, d11, d15
|
||||
vbif d21, d22, d17 ; oq1 |= t_oq1 & ~(f2 & f & m)
|
||||
vqrshrn.u16 d22, q15, #4 ; w_oq2
|
||||
|
||||
vsub.i16 q15, q14
|
||||
vaddl.u8 q14, d4, d11
|
||||
vadd.i16 q15, q4
|
||||
vaddl.u8 q4, d12, d15
|
||||
vbif d22, d23, d17 ; oq2 |= t_oq2 & ~(f2 & f & m)
|
||||
vqrshrn.u16 d23, q15, #4 ; w_oq3
|
||||
|
||||
vsub.i16 q15, q14
|
||||
vaddl.u8 q14, d5, d12
|
||||
vadd.i16 q15, q4
|
||||
vaddl.u8 q4, d13, d15
|
||||
vbif d16, d1, d17 ; op6 |= p6 & ~(f2 & f & m)
|
||||
vqrshrn.u16 d1, q15, #4 ; w_oq4
|
||||
|
||||
vsub.i16 q15, q14
|
||||
vaddl.u8 q14, d6, d13
|
||||
vadd.i16 q15, q4
|
||||
vaddl.u8 q4, d14, d15
|
||||
vbif d24, d2, d17 ; op5 |= p5 & ~(f2 & f & m)
|
||||
vqrshrn.u16 d2, q15, #4 ; w_oq5
|
||||
|
||||
vsub.i16 q15, q14
|
||||
vbif d25, d3, d17 ; op4 |= p4 & ~(f2 & f & m)
|
||||
vadd.i16 q15, q4
|
||||
vbif d23, d11, d17 ; oq3 |= q3 & ~(f2 & f & m)
|
||||
vqrshrn.u16 d3, q15, #4 ; w_oq6
|
||||
vbif d1, d12, d17 ; oq4 |= q4 & ~(f2 & f & m)
|
||||
vbif d2, d13, d17 ; oq5 |= q5 & ~(f2 & f & m)
|
||||
vbif d3, d14, d17 ; oq6 |= q6 & ~(f2 & f & m)
|
||||
|
||||
bx lr
|
||||
ENDP ; |aom_wide_mbfilter_neon|
|
||||
|
||||
END
|
||||
49
third_party/aom/aom_dsp/arm/loopfilter_neon.c
vendored
Normal file
49
third_party/aom/aom_dsp/arm/loopfilter_neon.c
vendored
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <arm_neon.h>
|
||||
|
||||
#include "./aom_dsp_rtcd.h"
|
||||
#include "./aom_config.h"
|
||||
#include "aom/aom_integer.h"
|
||||
|
||||
void aom_lpf_vertical_4_dual_neon(uint8_t *s, int p, const uint8_t *blimit0,
|
||||
const uint8_t *limit0, const uint8_t *thresh0,
|
||||
const uint8_t *blimit1, const uint8_t *limit1,
|
||||
const uint8_t *thresh1) {
|
||||
aom_lpf_vertical_4_neon(s, p, blimit0, limit0, thresh0);
|
||||
aom_lpf_vertical_4_neon(s + 8 * p, p, blimit1, limit1, thresh1);
|
||||
}
|
||||
|
||||
#if HAVE_NEON_ASM
|
||||
void aom_lpf_horizontal_8_dual_neon(
|
||||
uint8_t *s, int p /* pitch */, const uint8_t *blimit0,
|
||||
const uint8_t *limit0, const uint8_t *thresh0, const uint8_t *blimit1,
|
||||
const uint8_t *limit1, const uint8_t *thresh1) {
|
||||
aom_lpf_horizontal_8_neon(s, p, blimit0, limit0, thresh0);
|
||||
aom_lpf_horizontal_8_neon(s + 8, p, blimit1, limit1, thresh1);
|
||||
}
|
||||
|
||||
void aom_lpf_vertical_8_dual_neon(uint8_t *s, int p, const uint8_t *blimit0,
|
||||
const uint8_t *limit0, const uint8_t *thresh0,
|
||||
const uint8_t *blimit1, const uint8_t *limit1,
|
||||
const uint8_t *thresh1) {
|
||||
aom_lpf_vertical_8_neon(s, p, blimit0, limit0, thresh0);
|
||||
aom_lpf_vertical_8_neon(s + 8 * p, p, blimit1, limit1, thresh1);
|
||||
}
|
||||
|
||||
void aom_lpf_vertical_16_dual_neon(uint8_t *s, int p, const uint8_t *blimit,
|
||||
const uint8_t *limit,
|
||||
const uint8_t *thresh) {
|
||||
aom_lpf_vertical_16_neon(s, p, blimit, limit, thresh);
|
||||
aom_lpf_vertical_16_neon(s + 8 * p, p, blimit, limit, thresh);
|
||||
}
|
||||
#endif // HAVE_NEON_ASM
|
||||
225
third_party/aom/aom_dsp/arm/sad4d_neon.c
vendored
Normal file
225
third_party/aom/aom_dsp/arm/sad4d_neon.c
vendored
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <arm_neon.h>
|
||||
|
||||
#include "./aom_config.h"
|
||||
#include "./aom_dsp_rtcd.h"
|
||||
#include "aom/aom_integer.h"
|
||||
|
||||
static INLINE unsigned int horizontal_long_add_16x8(const uint16x8_t vec_lo,
|
||||
const uint16x8_t vec_hi) {
|
||||
const uint32x4_t vec_l_lo =
|
||||
vaddl_u16(vget_low_u16(vec_lo), vget_high_u16(vec_lo));
|
||||
const uint32x4_t vec_l_hi =
|
||||
vaddl_u16(vget_low_u16(vec_hi), vget_high_u16(vec_hi));
|
||||
const uint32x4_t a = vaddq_u32(vec_l_lo, vec_l_hi);
|
||||
const uint64x2_t b = vpaddlq_u32(a);
|
||||
const uint32x2_t c = vadd_u32(vreinterpret_u32_u64(vget_low_u64(b)),
|
||||
vreinterpret_u32_u64(vget_high_u64(b)));
|
||||
return vget_lane_u32(c, 0);
|
||||
}
|
||||
|
||||
// Calculate the absolute difference of 64 bytes from vec_src_00, vec_src_16,
|
||||
// vec_src_32, vec_src_48 and ref. Accumulate partial sums in vec_sum_ref_lo
|
||||
// and vec_sum_ref_hi.
|
||||
static void sad_neon_64(const uint8x16_t vec_src_00,
|
||||
const uint8x16_t vec_src_16,
|
||||
const uint8x16_t vec_src_32,
|
||||
const uint8x16_t vec_src_48, const uint8_t *ref,
|
||||
uint16x8_t *vec_sum_ref_lo,
|
||||
uint16x8_t *vec_sum_ref_hi) {
|
||||
const uint8x16_t vec_ref_00 = vld1q_u8(ref);
|
||||
const uint8x16_t vec_ref_16 = vld1q_u8(ref + 16);
|
||||
const uint8x16_t vec_ref_32 = vld1q_u8(ref + 32);
|
||||
const uint8x16_t vec_ref_48 = vld1q_u8(ref + 48);
|
||||
|
||||
*vec_sum_ref_lo = vabal_u8(*vec_sum_ref_lo, vget_low_u8(vec_src_00),
|
||||
vget_low_u8(vec_ref_00));
|
||||
*vec_sum_ref_hi = vabal_u8(*vec_sum_ref_hi, vget_high_u8(vec_src_00),
|
||||
vget_high_u8(vec_ref_00));
|
||||
*vec_sum_ref_lo = vabal_u8(*vec_sum_ref_lo, vget_low_u8(vec_src_16),
|
||||
vget_low_u8(vec_ref_16));
|
||||
*vec_sum_ref_hi = vabal_u8(*vec_sum_ref_hi, vget_high_u8(vec_src_16),
|
||||
vget_high_u8(vec_ref_16));
|
||||
*vec_sum_ref_lo = vabal_u8(*vec_sum_ref_lo, vget_low_u8(vec_src_32),
|
||||
vget_low_u8(vec_ref_32));
|
||||
*vec_sum_ref_hi = vabal_u8(*vec_sum_ref_hi, vget_high_u8(vec_src_32),
|
||||
vget_high_u8(vec_ref_32));
|
||||
*vec_sum_ref_lo = vabal_u8(*vec_sum_ref_lo, vget_low_u8(vec_src_48),
|
||||
vget_low_u8(vec_ref_48));
|
||||
*vec_sum_ref_hi = vabal_u8(*vec_sum_ref_hi, vget_high_u8(vec_src_48),
|
||||
vget_high_u8(vec_ref_48));
|
||||
}
|
||||
|
||||
// Calculate the absolute difference of 32 bytes from vec_src_00, vec_src_16,
|
||||
// and ref. Accumulate partial sums in vec_sum_ref_lo and vec_sum_ref_hi.
|
||||
static void sad_neon_32(const uint8x16_t vec_src_00,
|
||||
const uint8x16_t vec_src_16, const uint8_t *ref,
|
||||
uint16x8_t *vec_sum_ref_lo,
|
||||
uint16x8_t *vec_sum_ref_hi) {
|
||||
const uint8x16_t vec_ref_00 = vld1q_u8(ref);
|
||||
const uint8x16_t vec_ref_16 = vld1q_u8(ref + 16);
|
||||
|
||||
*vec_sum_ref_lo = vabal_u8(*vec_sum_ref_lo, vget_low_u8(vec_src_00),
|
||||
vget_low_u8(vec_ref_00));
|
||||
*vec_sum_ref_hi = vabal_u8(*vec_sum_ref_hi, vget_high_u8(vec_src_00),
|
||||
vget_high_u8(vec_ref_00));
|
||||
*vec_sum_ref_lo = vabal_u8(*vec_sum_ref_lo, vget_low_u8(vec_src_16),
|
||||
vget_low_u8(vec_ref_16));
|
||||
*vec_sum_ref_hi = vabal_u8(*vec_sum_ref_hi, vget_high_u8(vec_src_16),
|
||||
vget_high_u8(vec_ref_16));
|
||||
}
|
||||
|
||||
void aom_sad64x64x4d_neon(const uint8_t *src, int src_stride,
|
||||
const uint8_t *const ref[4], int ref_stride,
|
||||
uint32_t *res) {
|
||||
int i;
|
||||
uint16x8_t vec_sum_ref0_lo = vdupq_n_u16(0);
|
||||
uint16x8_t vec_sum_ref0_hi = vdupq_n_u16(0);
|
||||
uint16x8_t vec_sum_ref1_lo = vdupq_n_u16(0);
|
||||
uint16x8_t vec_sum_ref1_hi = vdupq_n_u16(0);
|
||||
uint16x8_t vec_sum_ref2_lo = vdupq_n_u16(0);
|
||||
uint16x8_t vec_sum_ref2_hi = vdupq_n_u16(0);
|
||||
uint16x8_t vec_sum_ref3_lo = vdupq_n_u16(0);
|
||||
uint16x8_t vec_sum_ref3_hi = vdupq_n_u16(0);
|
||||
const uint8_t *ref0, *ref1, *ref2, *ref3;
|
||||
ref0 = ref[0];
|
||||
ref1 = ref[1];
|
||||
ref2 = ref[2];
|
||||
ref3 = ref[3];
|
||||
|
||||
for (i = 0; i < 64; ++i) {
|
||||
const uint8x16_t vec_src_00 = vld1q_u8(src);
|
||||
const uint8x16_t vec_src_16 = vld1q_u8(src + 16);
|
||||
const uint8x16_t vec_src_32 = vld1q_u8(src + 32);
|
||||
const uint8x16_t vec_src_48 = vld1q_u8(src + 48);
|
||||
|
||||
sad_neon_64(vec_src_00, vec_src_16, vec_src_32, vec_src_48, ref0,
|
||||
&vec_sum_ref0_lo, &vec_sum_ref0_hi);
|
||||
sad_neon_64(vec_src_00, vec_src_16, vec_src_32, vec_src_48, ref1,
|
||||
&vec_sum_ref1_lo, &vec_sum_ref1_hi);
|
||||
sad_neon_64(vec_src_00, vec_src_16, vec_src_32, vec_src_48, ref2,
|
||||
&vec_sum_ref2_lo, &vec_sum_ref2_hi);
|
||||
sad_neon_64(vec_src_00, vec_src_16, vec_src_32, vec_src_48, ref3,
|
||||
&vec_sum_ref3_lo, &vec_sum_ref3_hi);
|
||||
|
||||
src += src_stride;
|
||||
ref0 += ref_stride;
|
||||
ref1 += ref_stride;
|
||||
ref2 += ref_stride;
|
||||
ref3 += ref_stride;
|
||||
}
|
||||
|
||||
res[0] = horizontal_long_add_16x8(vec_sum_ref0_lo, vec_sum_ref0_hi);
|
||||
res[1] = horizontal_long_add_16x8(vec_sum_ref1_lo, vec_sum_ref1_hi);
|
||||
res[2] = horizontal_long_add_16x8(vec_sum_ref2_lo, vec_sum_ref2_hi);
|
||||
res[3] = horizontal_long_add_16x8(vec_sum_ref3_lo, vec_sum_ref3_hi);
|
||||
}
|
||||
|
||||
void aom_sad32x32x4d_neon(const uint8_t *src, int src_stride,
|
||||
const uint8_t *const ref[4], int ref_stride,
|
||||
uint32_t *res) {
|
||||
int i;
|
||||
uint16x8_t vec_sum_ref0_lo = vdupq_n_u16(0);
|
||||
uint16x8_t vec_sum_ref0_hi = vdupq_n_u16(0);
|
||||
uint16x8_t vec_sum_ref1_lo = vdupq_n_u16(0);
|
||||
uint16x8_t vec_sum_ref1_hi = vdupq_n_u16(0);
|
||||
uint16x8_t vec_sum_ref2_lo = vdupq_n_u16(0);
|
||||
uint16x8_t vec_sum_ref2_hi = vdupq_n_u16(0);
|
||||
uint16x8_t vec_sum_ref3_lo = vdupq_n_u16(0);
|
||||
uint16x8_t vec_sum_ref3_hi = vdupq_n_u16(0);
|
||||
const uint8_t *ref0, *ref1, *ref2, *ref3;
|
||||
ref0 = ref[0];
|
||||
ref1 = ref[1];
|
||||
ref2 = ref[2];
|
||||
ref3 = ref[3];
|
||||
|
||||
for (i = 0; i < 32; ++i) {
|
||||
const uint8x16_t vec_src_00 = vld1q_u8(src);
|
||||
const uint8x16_t vec_src_16 = vld1q_u8(src + 16);
|
||||
|
||||
sad_neon_32(vec_src_00, vec_src_16, ref0, &vec_sum_ref0_lo,
|
||||
&vec_sum_ref0_hi);
|
||||
sad_neon_32(vec_src_00, vec_src_16, ref1, &vec_sum_ref1_lo,
|
||||
&vec_sum_ref1_hi);
|
||||
sad_neon_32(vec_src_00, vec_src_16, ref2, &vec_sum_ref2_lo,
|
||||
&vec_sum_ref2_hi);
|
||||
sad_neon_32(vec_src_00, vec_src_16, ref3, &vec_sum_ref3_lo,
|
||||
&vec_sum_ref3_hi);
|
||||
|
||||
src += src_stride;
|
||||
ref0 += ref_stride;
|
||||
ref1 += ref_stride;
|
||||
ref2 += ref_stride;
|
||||
ref3 += ref_stride;
|
||||
}
|
||||
|
||||
res[0] = horizontal_long_add_16x8(vec_sum_ref0_lo, vec_sum_ref0_hi);
|
||||
res[1] = horizontal_long_add_16x8(vec_sum_ref1_lo, vec_sum_ref1_hi);
|
||||
res[2] = horizontal_long_add_16x8(vec_sum_ref2_lo, vec_sum_ref2_hi);
|
||||
res[3] = horizontal_long_add_16x8(vec_sum_ref3_lo, vec_sum_ref3_hi);
|
||||
}
|
||||
|
||||
void aom_sad16x16x4d_neon(const uint8_t *src, int src_stride,
|
||||
const uint8_t *const ref[4], int ref_stride,
|
||||
uint32_t *res) {
|
||||
int i;
|
||||
uint16x8_t vec_sum_ref0_lo = vdupq_n_u16(0);
|
||||
uint16x8_t vec_sum_ref0_hi = vdupq_n_u16(0);
|
||||
uint16x8_t vec_sum_ref1_lo = vdupq_n_u16(0);
|
||||
uint16x8_t vec_sum_ref1_hi = vdupq_n_u16(0);
|
||||
uint16x8_t vec_sum_ref2_lo = vdupq_n_u16(0);
|
||||
uint16x8_t vec_sum_ref2_hi = vdupq_n_u16(0);
|
||||
uint16x8_t vec_sum_ref3_lo = vdupq_n_u16(0);
|
||||
uint16x8_t vec_sum_ref3_hi = vdupq_n_u16(0);
|
||||
const uint8_t *ref0, *ref1, *ref2, *ref3;
|
||||
ref0 = ref[0];
|
||||
ref1 = ref[1];
|
||||
ref2 = ref[2];
|
||||
ref3 = ref[3];
|
||||
|
||||
for (i = 0; i < 16; ++i) {
|
||||
const uint8x16_t vec_src = vld1q_u8(src);
|
||||
const uint8x16_t vec_ref0 = vld1q_u8(ref0);
|
||||
const uint8x16_t vec_ref1 = vld1q_u8(ref1);
|
||||
const uint8x16_t vec_ref2 = vld1q_u8(ref2);
|
||||
const uint8x16_t vec_ref3 = vld1q_u8(ref3);
|
||||
|
||||
vec_sum_ref0_lo =
|
||||
vabal_u8(vec_sum_ref0_lo, vget_low_u8(vec_src), vget_low_u8(vec_ref0));
|
||||
vec_sum_ref0_hi = vabal_u8(vec_sum_ref0_hi, vget_high_u8(vec_src),
|
||||
vget_high_u8(vec_ref0));
|
||||
vec_sum_ref1_lo =
|
||||
vabal_u8(vec_sum_ref1_lo, vget_low_u8(vec_src), vget_low_u8(vec_ref1));
|
||||
vec_sum_ref1_hi = vabal_u8(vec_sum_ref1_hi, vget_high_u8(vec_src),
|
||||
vget_high_u8(vec_ref1));
|
||||
vec_sum_ref2_lo =
|
||||
vabal_u8(vec_sum_ref2_lo, vget_low_u8(vec_src), vget_low_u8(vec_ref2));
|
||||
vec_sum_ref2_hi = vabal_u8(vec_sum_ref2_hi, vget_high_u8(vec_src),
|
||||
vget_high_u8(vec_ref2));
|
||||
vec_sum_ref3_lo =
|
||||
vabal_u8(vec_sum_ref3_lo, vget_low_u8(vec_src), vget_low_u8(vec_ref3));
|
||||
vec_sum_ref3_hi = vabal_u8(vec_sum_ref3_hi, vget_high_u8(vec_src),
|
||||
vget_high_u8(vec_ref3));
|
||||
|
||||
src += src_stride;
|
||||
ref0 += ref_stride;
|
||||
ref1 += ref_stride;
|
||||
ref2 += ref_stride;
|
||||
ref3 += ref_stride;
|
||||
}
|
||||
|
||||
res[0] = horizontal_long_add_16x8(vec_sum_ref0_lo, vec_sum_ref0_hi);
|
||||
res[1] = horizontal_long_add_16x8(vec_sum_ref1_lo, vec_sum_ref1_hi);
|
||||
res[2] = horizontal_long_add_16x8(vec_sum_ref2_lo, vec_sum_ref2_hi);
|
||||
res[3] = horizontal_long_add_16x8(vec_sum_ref3_lo, vec_sum_ref3_hi);
|
||||
}
|
||||
98
third_party/aom/aom_dsp/arm/sad_media.asm
vendored
Normal file
98
third_party/aom/aom_dsp/arm/sad_media.asm
vendored
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
;
|
||||
; Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
;
|
||||
; This source code is subject to the terms of the BSD 2 Clause License and
|
||||
; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
; was not distributed with this source code in the LICENSE file, you can
|
||||
; obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
; Media Patent License 1.0 was not distributed with this source code in the
|
||||
; PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
;
|
||||
|
||||
;
|
||||
|
||||
|
||||
EXPORT |aom_sad16x16_media|
|
||||
|
||||
ARM
|
||||
REQUIRE8
|
||||
PRESERVE8
|
||||
|
||||
AREA ||.text||, CODE, READONLY, ALIGN=2
|
||||
|
||||
; r0 const unsigned char *src_ptr
|
||||
; r1 int src_stride
|
||||
; r2 const unsigned char *ref_ptr
|
||||
; r3 int ref_stride
|
||||
|aom_sad16x16_media| PROC
|
||||
stmfd sp!, {r4-r12, lr}
|
||||
|
||||
pld [r0, r1, lsl #0]
|
||||
pld [r2, r3, lsl #0]
|
||||
pld [r0, r1, lsl #1]
|
||||
pld [r2, r3, lsl #1]
|
||||
|
||||
mov r4, #0 ; sad = 0;
|
||||
mov r5, #8 ; loop count
|
||||
|
||||
loop
|
||||
; 1st row
|
||||
ldr r6, [r0, #0x0] ; load 4 src pixels (1A)
|
||||
ldr r8, [r2, #0x0] ; load 4 ref pixels (1A)
|
||||
ldr r7, [r0, #0x4] ; load 4 src pixels (1A)
|
||||
ldr r9, [r2, #0x4] ; load 4 ref pixels (1A)
|
||||
ldr r10, [r0, #0x8] ; load 4 src pixels (1B)
|
||||
ldr r11, [r0, #0xC] ; load 4 src pixels (1B)
|
||||
|
||||
usada8 r4, r8, r6, r4 ; calculate sad for 4 pixels
|
||||
usad8 r8, r7, r9 ; calculate sad for 4 pixels
|
||||
|
||||
ldr r12, [r2, #0x8] ; load 4 ref pixels (1B)
|
||||
ldr lr, [r2, #0xC] ; load 4 ref pixels (1B)
|
||||
|
||||
add r0, r0, r1 ; set src pointer to next row
|
||||
add r2, r2, r3 ; set dst pointer to next row
|
||||
|
||||
pld [r0, r1, lsl #1]
|
||||
pld [r2, r3, lsl #1]
|
||||
|
||||
usada8 r4, r10, r12, r4 ; calculate sad for 4 pixels
|
||||
usada8 r8, r11, lr, r8 ; calculate sad for 4 pixels
|
||||
|
||||
ldr r6, [r0, #0x0] ; load 4 src pixels (2A)
|
||||
ldr r7, [r0, #0x4] ; load 4 src pixels (2A)
|
||||
add r4, r4, r8 ; add partial sad values
|
||||
|
||||
; 2nd row
|
||||
ldr r8, [r2, #0x0] ; load 4 ref pixels (2A)
|
||||
ldr r9, [r2, #0x4] ; load 4 ref pixels (2A)
|
||||
ldr r10, [r0, #0x8] ; load 4 src pixels (2B)
|
||||
ldr r11, [r0, #0xC] ; load 4 src pixels (2B)
|
||||
|
||||
usada8 r4, r6, r8, r4 ; calculate sad for 4 pixels
|
||||
usad8 r8, r7, r9 ; calculate sad for 4 pixels
|
||||
|
||||
ldr r12, [r2, #0x8] ; load 4 ref pixels (2B)
|
||||
ldr lr, [r2, #0xC] ; load 4 ref pixels (2B)
|
||||
|
||||
add r0, r0, r1 ; set src pointer to next row
|
||||
add r2, r2, r3 ; set dst pointer to next row
|
||||
|
||||
usada8 r4, r10, r12, r4 ; calculate sad for 4 pixels
|
||||
usada8 r8, r11, lr, r8 ; calculate sad for 4 pixels
|
||||
|
||||
pld [r0, r1, lsl #1]
|
||||
pld [r2, r3, lsl #1]
|
||||
|
||||
subs r5, r5, #1 ; decrement loop counter
|
||||
add r4, r4, r8 ; add partial sad values
|
||||
|
||||
bne loop
|
||||
|
||||
mov r0, r4 ; return sad
|
||||
ldmfd sp!, {r4-r12, pc}
|
||||
|
||||
ENDP
|
||||
|
||||
END
|
||||
|
||||
224
third_party/aom/aom_dsp/arm/sad_neon.c
vendored
Normal file
224
third_party/aom/aom_dsp/arm/sad_neon.c
vendored
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <arm_neon.h>
|
||||
|
||||
#include "./aom_config.h"
|
||||
|
||||
#include "aom/aom_integer.h"
|
||||
|
||||
unsigned int aom_sad8x16_neon(unsigned char *src_ptr, int src_stride,
|
||||
unsigned char *ref_ptr, int ref_stride) {
|
||||
uint8x8_t d0, d8;
|
||||
uint16x8_t q12;
|
||||
uint32x4_t q1;
|
||||
uint64x2_t q3;
|
||||
uint32x2_t d5;
|
||||
int i;
|
||||
|
||||
d0 = vld1_u8(src_ptr);
|
||||
src_ptr += src_stride;
|
||||
d8 = vld1_u8(ref_ptr);
|
||||
ref_ptr += ref_stride;
|
||||
q12 = vabdl_u8(d0, d8);
|
||||
|
||||
for (i = 0; i < 15; i++) {
|
||||
d0 = vld1_u8(src_ptr);
|
||||
src_ptr += src_stride;
|
||||
d8 = vld1_u8(ref_ptr);
|
||||
ref_ptr += ref_stride;
|
||||
q12 = vabal_u8(q12, d0, d8);
|
||||
}
|
||||
|
||||
q1 = vpaddlq_u16(q12);
|
||||
q3 = vpaddlq_u32(q1);
|
||||
d5 = vadd_u32(vreinterpret_u32_u64(vget_low_u64(q3)),
|
||||
vreinterpret_u32_u64(vget_high_u64(q3)));
|
||||
|
||||
return vget_lane_u32(d5, 0);
|
||||
}
|
||||
|
||||
unsigned int aom_sad4x4_neon(unsigned char *src_ptr, int src_stride,
|
||||
unsigned char *ref_ptr, int ref_stride) {
|
||||
uint8x8_t d0, d8;
|
||||
uint16x8_t q12;
|
||||
uint32x2_t d1;
|
||||
uint64x1_t d3;
|
||||
int i;
|
||||
|
||||
d0 = vld1_u8(src_ptr);
|
||||
src_ptr += src_stride;
|
||||
d8 = vld1_u8(ref_ptr);
|
||||
ref_ptr += ref_stride;
|
||||
q12 = vabdl_u8(d0, d8);
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
d0 = vld1_u8(src_ptr);
|
||||
src_ptr += src_stride;
|
||||
d8 = vld1_u8(ref_ptr);
|
||||
ref_ptr += ref_stride;
|
||||
q12 = vabal_u8(q12, d0, d8);
|
||||
}
|
||||
|
||||
d1 = vpaddl_u16(vget_low_u16(q12));
|
||||
d3 = vpaddl_u32(d1);
|
||||
|
||||
return vget_lane_u32(vreinterpret_u32_u64(d3), 0);
|
||||
}
|
||||
|
||||
unsigned int aom_sad16x8_neon(unsigned char *src_ptr, int src_stride,
|
||||
unsigned char *ref_ptr, int ref_stride) {
|
||||
uint8x16_t q0, q4;
|
||||
uint16x8_t q12, q13;
|
||||
uint32x4_t q1;
|
||||
uint64x2_t q3;
|
||||
uint32x2_t d5;
|
||||
int i;
|
||||
|
||||
q0 = vld1q_u8(src_ptr);
|
||||
src_ptr += src_stride;
|
||||
q4 = vld1q_u8(ref_ptr);
|
||||
ref_ptr += ref_stride;
|
||||
q12 = vabdl_u8(vget_low_u8(q0), vget_low_u8(q4));
|
||||
q13 = vabdl_u8(vget_high_u8(q0), vget_high_u8(q4));
|
||||
|
||||
for (i = 0; i < 7; i++) {
|
||||
q0 = vld1q_u8(src_ptr);
|
||||
src_ptr += src_stride;
|
||||
q4 = vld1q_u8(ref_ptr);
|
||||
ref_ptr += ref_stride;
|
||||
q12 = vabal_u8(q12, vget_low_u8(q0), vget_low_u8(q4));
|
||||
q13 = vabal_u8(q13, vget_high_u8(q0), vget_high_u8(q4));
|
||||
}
|
||||
|
||||
q12 = vaddq_u16(q12, q13);
|
||||
q1 = vpaddlq_u16(q12);
|
||||
q3 = vpaddlq_u32(q1);
|
||||
d5 = vadd_u32(vreinterpret_u32_u64(vget_low_u64(q3)),
|
||||
vreinterpret_u32_u64(vget_high_u64(q3)));
|
||||
|
||||
return vget_lane_u32(d5, 0);
|
||||
}
|
||||
|
||||
static INLINE unsigned int horizontal_long_add_16x8(const uint16x8_t vec_lo,
|
||||
const uint16x8_t vec_hi) {
|
||||
const uint32x4_t vec_l_lo =
|
||||
vaddl_u16(vget_low_u16(vec_lo), vget_high_u16(vec_lo));
|
||||
const uint32x4_t vec_l_hi =
|
||||
vaddl_u16(vget_low_u16(vec_hi), vget_high_u16(vec_hi));
|
||||
const uint32x4_t a = vaddq_u32(vec_l_lo, vec_l_hi);
|
||||
const uint64x2_t b = vpaddlq_u32(a);
|
||||
const uint32x2_t c = vadd_u32(vreinterpret_u32_u64(vget_low_u64(b)),
|
||||
vreinterpret_u32_u64(vget_high_u64(b)));
|
||||
return vget_lane_u32(c, 0);
|
||||
}
|
||||
static INLINE unsigned int horizontal_add_16x8(const uint16x8_t vec_16x8) {
|
||||
const uint32x4_t a = vpaddlq_u16(vec_16x8);
|
||||
const uint64x2_t b = vpaddlq_u32(a);
|
||||
const uint32x2_t c = vadd_u32(vreinterpret_u32_u64(vget_low_u64(b)),
|
||||
vreinterpret_u32_u64(vget_high_u64(b)));
|
||||
return vget_lane_u32(c, 0);
|
||||
}
|
||||
|
||||
unsigned int aom_sad64x64_neon(const uint8_t *src, int src_stride,
|
||||
const uint8_t *ref, int ref_stride) {
|
||||
int i;
|
||||
uint16x8_t vec_accum_lo = vdupq_n_u16(0);
|
||||
uint16x8_t vec_accum_hi = vdupq_n_u16(0);
|
||||
for (i = 0; i < 64; ++i) {
|
||||
const uint8x16_t vec_src_00 = vld1q_u8(src);
|
||||
const uint8x16_t vec_src_16 = vld1q_u8(src + 16);
|
||||
const uint8x16_t vec_src_32 = vld1q_u8(src + 32);
|
||||
const uint8x16_t vec_src_48 = vld1q_u8(src + 48);
|
||||
const uint8x16_t vec_ref_00 = vld1q_u8(ref);
|
||||
const uint8x16_t vec_ref_16 = vld1q_u8(ref + 16);
|
||||
const uint8x16_t vec_ref_32 = vld1q_u8(ref + 32);
|
||||
const uint8x16_t vec_ref_48 = vld1q_u8(ref + 48);
|
||||
src += src_stride;
|
||||
ref += ref_stride;
|
||||
vec_accum_lo = vabal_u8(vec_accum_lo, vget_low_u8(vec_src_00),
|
||||
vget_low_u8(vec_ref_00));
|
||||
vec_accum_hi = vabal_u8(vec_accum_hi, vget_high_u8(vec_src_00),
|
||||
vget_high_u8(vec_ref_00));
|
||||
vec_accum_lo = vabal_u8(vec_accum_lo, vget_low_u8(vec_src_16),
|
||||
vget_low_u8(vec_ref_16));
|
||||
vec_accum_hi = vabal_u8(vec_accum_hi, vget_high_u8(vec_src_16),
|
||||
vget_high_u8(vec_ref_16));
|
||||
vec_accum_lo = vabal_u8(vec_accum_lo, vget_low_u8(vec_src_32),
|
||||
vget_low_u8(vec_ref_32));
|
||||
vec_accum_hi = vabal_u8(vec_accum_hi, vget_high_u8(vec_src_32),
|
||||
vget_high_u8(vec_ref_32));
|
||||
vec_accum_lo = vabal_u8(vec_accum_lo, vget_low_u8(vec_src_48),
|
||||
vget_low_u8(vec_ref_48));
|
||||
vec_accum_hi = vabal_u8(vec_accum_hi, vget_high_u8(vec_src_48),
|
||||
vget_high_u8(vec_ref_48));
|
||||
}
|
||||
return horizontal_long_add_16x8(vec_accum_lo, vec_accum_hi);
|
||||
}
|
||||
|
||||
unsigned int aom_sad32x32_neon(const uint8_t *src, int src_stride,
|
||||
const uint8_t *ref, int ref_stride) {
|
||||
int i;
|
||||
uint16x8_t vec_accum_lo = vdupq_n_u16(0);
|
||||
uint16x8_t vec_accum_hi = vdupq_n_u16(0);
|
||||
|
||||
for (i = 0; i < 32; ++i) {
|
||||
const uint8x16_t vec_src_00 = vld1q_u8(src);
|
||||
const uint8x16_t vec_src_16 = vld1q_u8(src + 16);
|
||||
const uint8x16_t vec_ref_00 = vld1q_u8(ref);
|
||||
const uint8x16_t vec_ref_16 = vld1q_u8(ref + 16);
|
||||
src += src_stride;
|
||||
ref += ref_stride;
|
||||
vec_accum_lo = vabal_u8(vec_accum_lo, vget_low_u8(vec_src_00),
|
||||
vget_low_u8(vec_ref_00));
|
||||
vec_accum_hi = vabal_u8(vec_accum_hi, vget_high_u8(vec_src_00),
|
||||
vget_high_u8(vec_ref_00));
|
||||
vec_accum_lo = vabal_u8(vec_accum_lo, vget_low_u8(vec_src_16),
|
||||
vget_low_u8(vec_ref_16));
|
||||
vec_accum_hi = vabal_u8(vec_accum_hi, vget_high_u8(vec_src_16),
|
||||
vget_high_u8(vec_ref_16));
|
||||
}
|
||||
return horizontal_add_16x8(vaddq_u16(vec_accum_lo, vec_accum_hi));
|
||||
}
|
||||
|
||||
unsigned int aom_sad16x16_neon(const uint8_t *src, int src_stride,
|
||||
const uint8_t *ref, int ref_stride) {
|
||||
int i;
|
||||
uint16x8_t vec_accum_lo = vdupq_n_u16(0);
|
||||
uint16x8_t vec_accum_hi = vdupq_n_u16(0);
|
||||
|
||||
for (i = 0; i < 16; ++i) {
|
||||
const uint8x16_t vec_src = vld1q_u8(src);
|
||||
const uint8x16_t vec_ref = vld1q_u8(ref);
|
||||
src += src_stride;
|
||||
ref += ref_stride;
|
||||
vec_accum_lo =
|
||||
vabal_u8(vec_accum_lo, vget_low_u8(vec_src), vget_low_u8(vec_ref));
|
||||
vec_accum_hi =
|
||||
vabal_u8(vec_accum_hi, vget_high_u8(vec_src), vget_high_u8(vec_ref));
|
||||
}
|
||||
return horizontal_add_16x8(vaddq_u16(vec_accum_lo, vec_accum_hi));
|
||||
}
|
||||
|
||||
unsigned int aom_sad8x8_neon(const uint8_t *src, int src_stride,
|
||||
const uint8_t *ref, int ref_stride) {
|
||||
int i;
|
||||
uint16x8_t vec_accum = vdupq_n_u16(0);
|
||||
|
||||
for (i = 0; i < 8; ++i) {
|
||||
const uint8x8_t vec_src = vld1_u8(src);
|
||||
const uint8x8_t vec_ref = vld1_u8(ref);
|
||||
src += src_stride;
|
||||
ref += ref_stride;
|
||||
vec_accum = vabal_u8(vec_accum, vec_src, vec_ref);
|
||||
}
|
||||
return horizontal_add_16x8(vec_accum);
|
||||
}
|
||||
39
third_party/aom/aom_dsp/arm/save_reg_neon.asm
vendored
Normal file
39
third_party/aom/aom_dsp/arm/save_reg_neon.asm
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
;
|
||||
; Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
;
|
||||
; This source code is subject to the terms of the BSD 2 Clause License and
|
||||
; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
; was not distributed with this source code in the LICENSE file, you can
|
||||
; obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
; Media Patent License 1.0 was not distributed with this source code in the
|
||||
; PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
;
|
||||
|
||||
;
|
||||
|
||||
|
||||
EXPORT |aom_push_neon|
|
||||
EXPORT |aom_pop_neon|
|
||||
|
||||
ARM
|
||||
REQUIRE8
|
||||
PRESERVE8
|
||||
|
||||
AREA ||.text||, CODE, READONLY, ALIGN=2
|
||||
|
||||
|aom_push_neon| PROC
|
||||
vst1.i64 {d8, d9, d10, d11}, [r0]!
|
||||
vst1.i64 {d12, d13, d14, d15}, [r0]!
|
||||
bx lr
|
||||
|
||||
ENDP
|
||||
|
||||
|aom_pop_neon| PROC
|
||||
vld1.i64 {d8, d9, d10, d11}, [r0]!
|
||||
vld1.i64 {d12, d13, d14, d15}, [r0]!
|
||||
bx lr
|
||||
|
||||
ENDP
|
||||
|
||||
END
|
||||
|
||||
81
third_party/aom/aom_dsp/arm/subpel_variance_media.c
vendored
Normal file
81
third_party/aom/aom_dsp/arm/subpel_variance_media.c
vendored
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include "./aom_config.h"
|
||||
#include "./aom_dsp_rtcd.h"
|
||||
#include "aom/aom_integer.h"
|
||||
#include "aom_ports/mem.h"
|
||||
|
||||
#if HAVE_MEDIA
|
||||
static const int16_t bilinear_filters_media[8][2] = { { 128, 0 }, { 112, 16 },
|
||||
{ 96, 32 }, { 80, 48 },
|
||||
{ 64, 64 }, { 48, 80 },
|
||||
{ 32, 96 }, { 16, 112 } };
|
||||
|
||||
extern void aom_filter_block2d_bil_first_pass_media(
|
||||
const uint8_t *src_ptr, uint16_t *dst_ptr, uint32_t src_pitch,
|
||||
uint32_t height, uint32_t width, const int16_t *filter);
|
||||
|
||||
extern void aom_filter_block2d_bil_second_pass_media(
|
||||
const uint16_t *src_ptr, uint8_t *dst_ptr, int32_t src_pitch,
|
||||
uint32_t height, uint32_t width, const int16_t *filter);
|
||||
|
||||
unsigned int aom_sub_pixel_variance8x8_media(
|
||||
const uint8_t *src_ptr, int src_pixels_per_line, int xoffset, int yoffset,
|
||||
const uint8_t *dst_ptr, int dst_pixels_per_line, unsigned int *sse) {
|
||||
uint16_t first_pass[10 * 8];
|
||||
uint8_t second_pass[8 * 8];
|
||||
const int16_t *HFilter, *VFilter;
|
||||
|
||||
HFilter = bilinear_filters_media[xoffset];
|
||||
VFilter = bilinear_filters_media[yoffset];
|
||||
|
||||
aom_filter_block2d_bil_first_pass_media(src_ptr, first_pass,
|
||||
src_pixels_per_line, 9, 8, HFilter);
|
||||
aom_filter_block2d_bil_second_pass_media(first_pass, second_pass, 8, 8, 8,
|
||||
VFilter);
|
||||
|
||||
return aom_variance8x8_media(second_pass, 8, dst_ptr, dst_pixels_per_line,
|
||||
sse);
|
||||
}
|
||||
|
||||
unsigned int aom_sub_pixel_variance16x16_media(
|
||||
const uint8_t *src_ptr, int src_pixels_per_line, int xoffset, int yoffset,
|
||||
const uint8_t *dst_ptr, int dst_pixels_per_line, unsigned int *sse) {
|
||||
uint16_t first_pass[36 * 16];
|
||||
uint8_t second_pass[20 * 16];
|
||||
const int16_t *HFilter, *VFilter;
|
||||
unsigned int var;
|
||||
|
||||
if (xoffset == 4 && yoffset == 0) {
|
||||
var = aom_variance_halfpixvar16x16_h_media(
|
||||
src_ptr, src_pixels_per_line, dst_ptr, dst_pixels_per_line, sse);
|
||||
} else if (xoffset == 0 && yoffset == 4) {
|
||||
var = aom_variance_halfpixvar16x16_v_media(
|
||||
src_ptr, src_pixels_per_line, dst_ptr, dst_pixels_per_line, sse);
|
||||
} else if (xoffset == 4 && yoffset == 4) {
|
||||
var = aom_variance_halfpixvar16x16_hv_media(
|
||||
src_ptr, src_pixels_per_line, dst_ptr, dst_pixels_per_line, sse);
|
||||
} else {
|
||||
HFilter = bilinear_filters_media[xoffset];
|
||||
VFilter = bilinear_filters_media[yoffset];
|
||||
|
||||
aom_filter_block2d_bil_first_pass_media(
|
||||
src_ptr, first_pass, src_pixels_per_line, 17, 16, HFilter);
|
||||
aom_filter_block2d_bil_second_pass_media(first_pass, second_pass, 16, 16,
|
||||
16, VFilter);
|
||||
|
||||
var = aom_variance16x16_media(second_pass, 16, dst_ptr, dst_pixels_per_line,
|
||||
sse);
|
||||
}
|
||||
return var;
|
||||
}
|
||||
#endif // HAVE_MEDIA
|
||||
134
third_party/aom/aom_dsp/arm/subpel_variance_neon.c
vendored
Normal file
134
third_party/aom/aom_dsp/arm/subpel_variance_neon.c
vendored
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <arm_neon.h>
|
||||
#include "./aom_dsp_rtcd.h"
|
||||
#include "./aom_config.h"
|
||||
|
||||
#include "aom_ports/mem.h"
|
||||
#include "aom/aom_integer.h"
|
||||
|
||||
#include "aom_dsp/variance.h"
|
||||
|
||||
static const uint8_t bilinear_filters[8][2] = {
|
||||
{ 128, 0 }, { 112, 16 }, { 96, 32 }, { 80, 48 },
|
||||
{ 64, 64 }, { 48, 80 }, { 32, 96 }, { 16, 112 },
|
||||
};
|
||||
|
||||
static void var_filter_block2d_bil_w8(const uint8_t *src_ptr,
|
||||
uint8_t *output_ptr,
|
||||
unsigned int src_pixels_per_line,
|
||||
int pixel_step,
|
||||
unsigned int output_height,
|
||||
unsigned int output_width,
|
||||
const uint8_t *filter) {
|
||||
const uint8x8_t f0 = vmov_n_u8(filter[0]);
|
||||
const uint8x8_t f1 = vmov_n_u8(filter[1]);
|
||||
unsigned int i;
|
||||
for (i = 0; i < output_height; ++i) {
|
||||
const uint8x8_t src_0 = vld1_u8(&src_ptr[0]);
|
||||
const uint8x8_t src_1 = vld1_u8(&src_ptr[pixel_step]);
|
||||
const uint16x8_t a = vmull_u8(src_0, f0);
|
||||
const uint16x8_t b = vmlal_u8(a, src_1, f1);
|
||||
const uint8x8_t out = vrshrn_n_u16(b, FILTER_BITS);
|
||||
vst1_u8(&output_ptr[0], out);
|
||||
// Next row...
|
||||
src_ptr += src_pixels_per_line;
|
||||
output_ptr += output_width;
|
||||
}
|
||||
}
|
||||
|
||||
static void var_filter_block2d_bil_w16(const uint8_t *src_ptr,
|
||||
uint8_t *output_ptr,
|
||||
unsigned int src_pixels_per_line,
|
||||
int pixel_step,
|
||||
unsigned int output_height,
|
||||
unsigned int output_width,
|
||||
const uint8_t *filter) {
|
||||
const uint8x8_t f0 = vmov_n_u8(filter[0]);
|
||||
const uint8x8_t f1 = vmov_n_u8(filter[1]);
|
||||
unsigned int i, j;
|
||||
for (i = 0; i < output_height; ++i) {
|
||||
for (j = 0; j < output_width; j += 16) {
|
||||
const uint8x16_t src_0 = vld1q_u8(&src_ptr[j]);
|
||||
const uint8x16_t src_1 = vld1q_u8(&src_ptr[j + pixel_step]);
|
||||
const uint16x8_t a = vmull_u8(vget_low_u8(src_0), f0);
|
||||
const uint16x8_t b = vmlal_u8(a, vget_low_u8(src_1), f1);
|
||||
const uint8x8_t out_lo = vrshrn_n_u16(b, FILTER_BITS);
|
||||
const uint16x8_t c = vmull_u8(vget_high_u8(src_0), f0);
|
||||
const uint16x8_t d = vmlal_u8(c, vget_high_u8(src_1), f1);
|
||||
const uint8x8_t out_hi = vrshrn_n_u16(d, FILTER_BITS);
|
||||
vst1q_u8(&output_ptr[j], vcombine_u8(out_lo, out_hi));
|
||||
}
|
||||
// Next row...
|
||||
src_ptr += src_pixels_per_line;
|
||||
output_ptr += output_width;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int aom_sub_pixel_variance8x8_neon(const uint8_t *src, int src_stride,
|
||||
int xoffset, int yoffset,
|
||||
const uint8_t *dst, int dst_stride,
|
||||
unsigned int *sse) {
|
||||
DECLARE_ALIGNED(16, uint8_t, temp2[8 * 8]);
|
||||
DECLARE_ALIGNED(16, uint8_t, fdata3[9 * 8]);
|
||||
|
||||
var_filter_block2d_bil_w8(src, fdata3, src_stride, 1, 9, 8,
|
||||
bilinear_filters[xoffset]);
|
||||
var_filter_block2d_bil_w8(fdata3, temp2, 8, 8, 8, 8,
|
||||
bilinear_filters[yoffset]);
|
||||
return aom_variance8x8_neon(temp2, 8, dst, dst_stride, sse);
|
||||
}
|
||||
|
||||
unsigned int aom_sub_pixel_variance16x16_neon(const uint8_t *src,
|
||||
int src_stride, int xoffset,
|
||||
int yoffset, const uint8_t *dst,
|
||||
int dst_stride,
|
||||
unsigned int *sse) {
|
||||
DECLARE_ALIGNED(16, uint8_t, temp2[16 * 16]);
|
||||
DECLARE_ALIGNED(16, uint8_t, fdata3[17 * 16]);
|
||||
|
||||
var_filter_block2d_bil_w16(src, fdata3, src_stride, 1, 17, 16,
|
||||
bilinear_filters[xoffset]);
|
||||
var_filter_block2d_bil_w16(fdata3, temp2, 16, 16, 16, 16,
|
||||
bilinear_filters[yoffset]);
|
||||
return aom_variance16x16_neon(temp2, 16, dst, dst_stride, sse);
|
||||
}
|
||||
|
||||
unsigned int aom_sub_pixel_variance32x32_neon(const uint8_t *src,
|
||||
int src_stride, int xoffset,
|
||||
int yoffset, const uint8_t *dst,
|
||||
int dst_stride,
|
||||
unsigned int *sse) {
|
||||
DECLARE_ALIGNED(16, uint8_t, temp2[32 * 32]);
|
||||
DECLARE_ALIGNED(16, uint8_t, fdata3[33 * 32]);
|
||||
|
||||
var_filter_block2d_bil_w16(src, fdata3, src_stride, 1, 33, 32,
|
||||
bilinear_filters[xoffset]);
|
||||
var_filter_block2d_bil_w16(fdata3, temp2, 32, 32, 32, 32,
|
||||
bilinear_filters[yoffset]);
|
||||
return aom_variance32x32_neon(temp2, 32, dst, dst_stride, sse);
|
||||
}
|
||||
|
||||
unsigned int aom_sub_pixel_variance64x64_neon(const uint8_t *src,
|
||||
int src_stride, int xoffset,
|
||||
int yoffset, const uint8_t *dst,
|
||||
int dst_stride,
|
||||
unsigned int *sse) {
|
||||
DECLARE_ALIGNED(16, uint8_t, temp2[64 * 64]);
|
||||
DECLARE_ALIGNED(16, uint8_t, fdata3[65 * 64]);
|
||||
|
||||
var_filter_block2d_bil_w16(src, fdata3, src_stride, 1, 65, 64,
|
||||
bilinear_filters[xoffset]);
|
||||
var_filter_block2d_bil_w16(fdata3, temp2, 64, 64, 64, 64,
|
||||
bilinear_filters[yoffset]);
|
||||
return aom_variance64x64_neon(temp2, 64, dst, dst_stride, sse);
|
||||
}
|
||||
80
third_party/aom/aom_dsp/arm/subtract_neon.c
vendored
Normal file
80
third_party/aom/aom_dsp/arm/subtract_neon.c
vendored
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <arm_neon.h>
|
||||
|
||||
#include "./aom_config.h"
|
||||
#include "aom/aom_integer.h"
|
||||
|
||||
void aom_subtract_block_neon(int rows, int cols, int16_t *diff,
|
||||
ptrdiff_t diff_stride, const uint8_t *src,
|
||||
ptrdiff_t src_stride, const uint8_t *pred,
|
||||
ptrdiff_t pred_stride) {
|
||||
int r, c;
|
||||
|
||||
if (cols > 16) {
|
||||
for (r = 0; r < rows; ++r) {
|
||||
for (c = 0; c < cols; c += 32) {
|
||||
const uint8x16_t v_src_00 = vld1q_u8(&src[c + 0]);
|
||||
const uint8x16_t v_src_16 = vld1q_u8(&src[c + 16]);
|
||||
const uint8x16_t v_pred_00 = vld1q_u8(&pred[c + 0]);
|
||||
const uint8x16_t v_pred_16 = vld1q_u8(&pred[c + 16]);
|
||||
const uint16x8_t v_diff_lo_00 =
|
||||
vsubl_u8(vget_low_u8(v_src_00), vget_low_u8(v_pred_00));
|
||||
const uint16x8_t v_diff_hi_00 =
|
||||
vsubl_u8(vget_high_u8(v_src_00), vget_high_u8(v_pred_00));
|
||||
const uint16x8_t v_diff_lo_16 =
|
||||
vsubl_u8(vget_low_u8(v_src_16), vget_low_u8(v_pred_16));
|
||||
const uint16x8_t v_diff_hi_16 =
|
||||
vsubl_u8(vget_high_u8(v_src_16), vget_high_u8(v_pred_16));
|
||||
vst1q_s16(&diff[c + 0], vreinterpretq_s16_u16(v_diff_lo_00));
|
||||
vst1q_s16(&diff[c + 8], vreinterpretq_s16_u16(v_diff_hi_00));
|
||||
vst1q_s16(&diff[c + 16], vreinterpretq_s16_u16(v_diff_lo_16));
|
||||
vst1q_s16(&diff[c + 24], vreinterpretq_s16_u16(v_diff_hi_16));
|
||||
}
|
||||
diff += diff_stride;
|
||||
pred += pred_stride;
|
||||
src += src_stride;
|
||||
}
|
||||
} else if (cols > 8) {
|
||||
for (r = 0; r < rows; ++r) {
|
||||
const uint8x16_t v_src = vld1q_u8(&src[0]);
|
||||
const uint8x16_t v_pred = vld1q_u8(&pred[0]);
|
||||
const uint16x8_t v_diff_lo =
|
||||
vsubl_u8(vget_low_u8(v_src), vget_low_u8(v_pred));
|
||||
const uint16x8_t v_diff_hi =
|
||||
vsubl_u8(vget_high_u8(v_src), vget_high_u8(v_pred));
|
||||
vst1q_s16(&diff[0], vreinterpretq_s16_u16(v_diff_lo));
|
||||
vst1q_s16(&diff[8], vreinterpretq_s16_u16(v_diff_hi));
|
||||
diff += diff_stride;
|
||||
pred += pred_stride;
|
||||
src += src_stride;
|
||||
}
|
||||
} else if (cols > 4) {
|
||||
for (r = 0; r < rows; ++r) {
|
||||
const uint8x8_t v_src = vld1_u8(&src[0]);
|
||||
const uint8x8_t v_pred = vld1_u8(&pred[0]);
|
||||
const uint16x8_t v_diff = vsubl_u8(v_src, v_pred);
|
||||
vst1q_s16(&diff[0], vreinterpretq_s16_u16(v_diff));
|
||||
diff += diff_stride;
|
||||
pred += pred_stride;
|
||||
src += src_stride;
|
||||
}
|
||||
} else {
|
||||
for (r = 0; r < rows; ++r) {
|
||||
for (c = 0; c < cols; ++c) diff[c] = src[c] - pred[c];
|
||||
|
||||
diff += diff_stride;
|
||||
pred += pred_stride;
|
||||
src += src_stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
185
third_party/aom/aom_dsp/arm/variance_halfpixvar16x16_h_media.asm
vendored
Normal file
185
third_party/aom/aom_dsp/arm/variance_halfpixvar16x16_h_media.asm
vendored
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
;
|
||||
; Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
;
|
||||
; This source code is subject to the terms of the BSD 2 Clause License and
|
||||
; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
; was not distributed with this source code in the LICENSE file, you can
|
||||
; obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
; Media Patent License 1.0 was not distributed with this source code in the
|
||||
; PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
;
|
||||
|
||||
;
|
||||
|
||||
|
||||
EXPORT |aom_variance_halfpixvar16x16_h_media|
|
||||
|
||||
ARM
|
||||
REQUIRE8
|
||||
PRESERVE8
|
||||
|
||||
AREA ||.text||, CODE, READONLY, ALIGN=2
|
||||
|
||||
; r0 unsigned char *src_ptr
|
||||
; r1 int source_stride
|
||||
; r2 unsigned char *ref_ptr
|
||||
; r3 int recon_stride
|
||||
; stack unsigned int *sse
|
||||
|aom_variance_halfpixvar16x16_h_media| PROC
|
||||
|
||||
stmfd sp!, {r4-r12, lr}
|
||||
|
||||
pld [r0, r1, lsl #0]
|
||||
pld [r2, r3, lsl #0]
|
||||
|
||||
mov r8, #0 ; initialize sum = 0
|
||||
ldr r10, c80808080
|
||||
mov r11, #0 ; initialize sse = 0
|
||||
mov r12, #16 ; set loop counter to 16 (=block height)
|
||||
mov lr, #0 ; constant zero
|
||||
loop
|
||||
; 1st 4 pixels
|
||||
ldr r4, [r0, #0] ; load 4 src pixels
|
||||
ldr r6, [r0, #1] ; load 4 src pixels with 1 byte offset
|
||||
ldr r5, [r2, #0] ; load 4 ref pixels
|
||||
|
||||
; bilinear interpolation
|
||||
mvn r6, r6
|
||||
uhsub8 r4, r4, r6
|
||||
eor r4, r4, r10
|
||||
|
||||
usub8 r6, r4, r5 ; calculate difference
|
||||
pld [r0, r1, lsl #1]
|
||||
sel r7, r6, lr ; select bytes with positive difference
|
||||
usub8 r6, r5, r4 ; calculate difference with reversed operands
|
||||
pld [r2, r3, lsl #1]
|
||||
sel r6, r6, lr ; select bytes with negative difference
|
||||
|
||||
; calculate partial sums
|
||||
usad8 r4, r7, lr ; calculate sum of positive differences
|
||||
usad8 r5, r6, lr ; calculate sum of negative differences
|
||||
orr r6, r6, r7 ; differences of all 4 pixels
|
||||
; calculate total sum
|
||||
adds r8, r8, r4 ; add positive differences to sum
|
||||
subs r8, r8, r5 ; subtract negative differences from sum
|
||||
|
||||
; calculate sse
|
||||
uxtb16 r5, r6 ; byte (two pixels) to halfwords
|
||||
uxtb16 r7, r6, ror #8 ; another two pixels to halfwords
|
||||
smlad r11, r5, r5, r11 ; dual signed multiply, add and accumulate (1)
|
||||
|
||||
; 2nd 4 pixels
|
||||
ldr r4, [r0, #4] ; load 4 src pixels
|
||||
ldr r6, [r0, #5] ; load 4 src pixels with 1 byte offset
|
||||
ldr r5, [r2, #4] ; load 4 ref pixels
|
||||
|
||||
; bilinear interpolation
|
||||
mvn r6, r6
|
||||
uhsub8 r4, r4, r6
|
||||
eor r4, r4, r10
|
||||
|
||||
smlad r11, r7, r7, r11 ; dual signed multiply, add and accumulate (2)
|
||||
|
||||
usub8 r6, r4, r5 ; calculate difference
|
||||
sel r7, r6, lr ; select bytes with positive difference
|
||||
usub8 r6, r5, r4 ; calculate difference with reversed operands
|
||||
sel r6, r6, lr ; select bytes with negative difference
|
||||
|
||||
; calculate partial sums
|
||||
usad8 r4, r7, lr ; calculate sum of positive differences
|
||||
usad8 r5, r6, lr ; calculate sum of negative differences
|
||||
orr r6, r6, r7 ; differences of all 4 pixels
|
||||
|
||||
; calculate total sum
|
||||
add r8, r8, r4 ; add positive differences to sum
|
||||
sub r8, r8, r5 ; subtract negative differences from sum
|
||||
|
||||
; calculate sse
|
||||
uxtb16 r5, r6 ; byte (two pixels) to halfwords
|
||||
uxtb16 r7, r6, ror #8 ; another two pixels to halfwords
|
||||
smlad r11, r5, r5, r11 ; dual signed multiply, add and accumulate (1)
|
||||
|
||||
; 3rd 4 pixels
|
||||
ldr r4, [r0, #8] ; load 4 src pixels
|
||||
ldr r6, [r0, #9] ; load 4 src pixels with 1 byte offset
|
||||
ldr r5, [r2, #8] ; load 4 ref pixels
|
||||
|
||||
; bilinear interpolation
|
||||
mvn r6, r6
|
||||
uhsub8 r4, r4, r6
|
||||
eor r4, r4, r10
|
||||
|
||||
smlad r11, r7, r7, r11 ; dual signed multiply, add and accumulate (2)
|
||||
|
||||
usub8 r6, r4, r5 ; calculate difference
|
||||
sel r7, r6, lr ; select bytes with positive difference
|
||||
usub8 r6, r5, r4 ; calculate difference with reversed operands
|
||||
sel r6, r6, lr ; select bytes with negative difference
|
||||
|
||||
; calculate partial sums
|
||||
usad8 r4, r7, lr ; calculate sum of positive differences
|
||||
usad8 r5, r6, lr ; calculate sum of negative differences
|
||||
orr r6, r6, r7 ; differences of all 4 pixels
|
||||
|
||||
; calculate total sum
|
||||
add r8, r8, r4 ; add positive differences to sum
|
||||
sub r8, r8, r5 ; subtract negative differences from sum
|
||||
|
||||
; calculate sse
|
||||
uxtb16 r5, r6 ; byte (two pixels) to halfwords
|
||||
uxtb16 r7, r6, ror #8 ; another two pixels to halfwords
|
||||
smlad r11, r5, r5, r11 ; dual signed multiply, add and accumulate (1)
|
||||
|
||||
; 4th 4 pixels
|
||||
ldr r4, [r0, #12] ; load 4 src pixels
|
||||
ldr r6, [r0, #13] ; load 4 src pixels with 1 byte offset
|
||||
ldr r5, [r2, #12] ; load 4 ref pixels
|
||||
|
||||
; bilinear interpolation
|
||||
mvn r6, r6
|
||||
uhsub8 r4, r4, r6
|
||||
eor r4, r4, r10
|
||||
|
||||
smlad r11, r7, r7, r11 ; dual signed multiply, add and accumulate (2)
|
||||
|
||||
usub8 r6, r4, r5 ; calculate difference
|
||||
add r0, r0, r1 ; set src_ptr to next row
|
||||
sel r7, r6, lr ; select bytes with positive difference
|
||||
usub8 r6, r5, r4 ; calculate difference with reversed operands
|
||||
add r2, r2, r3 ; set dst_ptr to next row
|
||||
sel r6, r6, lr ; select bytes with negative difference
|
||||
|
||||
; calculate partial sums
|
||||
usad8 r4, r7, lr ; calculate sum of positive differences
|
||||
usad8 r5, r6, lr ; calculate sum of negative differences
|
||||
orr r6, r6, r7 ; differences of all 4 pixels
|
||||
|
||||
; calculate total sum
|
||||
add r8, r8, r4 ; add positive differences to sum
|
||||
sub r8, r8, r5 ; subtract negative differences from sum
|
||||
|
||||
; calculate sse
|
||||
uxtb16 r5, r6 ; byte (two pixels) to halfwords
|
||||
uxtb16 r7, r6, ror #8 ; another two pixels to halfwords
|
||||
smlad r11, r5, r5, r11 ; dual signed multiply, add and accumulate (1)
|
||||
smlad r11, r7, r7, r11 ; dual signed multiply, add and accumulate (2)
|
||||
|
||||
subs r12, r12, #1
|
||||
|
||||
bne loop
|
||||
|
||||
; return stuff
|
||||
ldr r6, [sp, #40] ; get address of sse
|
||||
mul r0, r8, r8 ; sum * sum
|
||||
str r11, [r6] ; store sse
|
||||
sub r0, r11, r0, lsr #8 ; return (sse - ((sum * sum) >> 8))
|
||||
|
||||
ldmfd sp!, {r4-r12, pc}
|
||||
|
||||
ENDP
|
||||
|
||||
c80808080
|
||||
DCD 0x80808080
|
||||
|
||||
END
|
||||
|
||||
225
third_party/aom/aom_dsp/arm/variance_halfpixvar16x16_hv_media.asm
vendored
Normal file
225
third_party/aom/aom_dsp/arm/variance_halfpixvar16x16_hv_media.asm
vendored
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
;
|
||||
; Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
;
|
||||
; This source code is subject to the terms of the BSD 2 Clause License and
|
||||
; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
; was not distributed with this source code in the LICENSE file, you can
|
||||
; obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
; Media Patent License 1.0 was not distributed with this source code in the
|
||||
; PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
;
|
||||
|
||||
;
|
||||
|
||||
|
||||
EXPORT |aom_variance_halfpixvar16x16_hv_media|
|
||||
|
||||
ARM
|
||||
REQUIRE8
|
||||
PRESERVE8
|
||||
|
||||
AREA ||.text||, CODE, READONLY, ALIGN=2
|
||||
|
||||
; r0 unsigned char *src_ptr
|
||||
; r1 int source_stride
|
||||
; r2 unsigned char *ref_ptr
|
||||
; r3 int recon_stride
|
||||
; stack unsigned int *sse
|
||||
|aom_variance_halfpixvar16x16_hv_media| PROC
|
||||
|
||||
stmfd sp!, {r4-r12, lr}
|
||||
|
||||
pld [r0, r1, lsl #0]
|
||||
pld [r2, r3, lsl #0]
|
||||
|
||||
mov r8, #0 ; initialize sum = 0
|
||||
ldr r10, c80808080
|
||||
mov r11, #0 ; initialize sse = 0
|
||||
mov r12, #16 ; set loop counter to 16 (=block height)
|
||||
mov lr, #0 ; constant zero
|
||||
loop
|
||||
add r9, r0, r1 ; pointer to pixels on the next row
|
||||
; 1st 4 pixels
|
||||
ldr r4, [r0, #0] ; load source pixels a, row N
|
||||
ldr r6, [r0, #1] ; load source pixels b, row N
|
||||
ldr r5, [r9, #0] ; load source pixels c, row N+1
|
||||
ldr r7, [r9, #1] ; load source pixels d, row N+1
|
||||
|
||||
; x = (a + b + 1) >> 1, interpolate pixels horizontally on row N
|
||||
mvn r6, r6
|
||||
uhsub8 r4, r4, r6
|
||||
eor r4, r4, r10
|
||||
; y = (c + d + 1) >> 1, interpolate pixels horizontally on row N+1
|
||||
mvn r7, r7
|
||||
uhsub8 r5, r5, r7
|
||||
eor r5, r5, r10
|
||||
; z = (x + y + 1) >> 1, interpolate half pixel values vertically
|
||||
mvn r5, r5
|
||||
uhsub8 r4, r4, r5
|
||||
ldr r5, [r2, #0] ; load 4 ref pixels
|
||||
eor r4, r4, r10
|
||||
|
||||
usub8 r6, r4, r5 ; calculate difference
|
||||
pld [r0, r1, lsl #1]
|
||||
sel r7, r6, lr ; select bytes with positive difference
|
||||
usub8 r6, r5, r4 ; calculate difference with reversed operands
|
||||
pld [r2, r3, lsl #1]
|
||||
sel r6, r6, lr ; select bytes with negative difference
|
||||
|
||||
; calculate partial sums
|
||||
usad8 r4, r7, lr ; calculate sum of positive differences
|
||||
usad8 r5, r6, lr ; calculate sum of negative differences
|
||||
orr r6, r6, r7 ; differences of all 4 pixels
|
||||
; calculate total sum
|
||||
adds r8, r8, r4 ; add positive differences to sum
|
||||
subs r8, r8, r5 ; subtract negative differences from sum
|
||||
|
||||
; calculate sse
|
||||
uxtb16 r5, r6 ; byte (two pixels) to halfwords
|
||||
uxtb16 r7, r6, ror #8 ; another two pixels to halfwords
|
||||
smlad r11, r5, r5, r11 ; dual signed multiply, add and accumulate (1)
|
||||
|
||||
; 2nd 4 pixels
|
||||
ldr r4, [r0, #4] ; load source pixels a, row N
|
||||
ldr r6, [r0, #5] ; load source pixels b, row N
|
||||
ldr r5, [r9, #4] ; load source pixels c, row N+1
|
||||
|
||||
smlad r11, r7, r7, r11 ; dual signed multiply, add and accumulate (2)
|
||||
|
||||
ldr r7, [r9, #5] ; load source pixels d, row N+1
|
||||
|
||||
; x = (a + b + 1) >> 1, interpolate pixels horizontally on row N
|
||||
mvn r6, r6
|
||||
uhsub8 r4, r4, r6
|
||||
eor r4, r4, r10
|
||||
; y = (c + d + 1) >> 1, interpolate pixels horizontally on row N+1
|
||||
mvn r7, r7
|
||||
uhsub8 r5, r5, r7
|
||||
eor r5, r5, r10
|
||||
; z = (x + y + 1) >> 1, interpolate half pixel values vertically
|
||||
mvn r5, r5
|
||||
uhsub8 r4, r4, r5
|
||||
ldr r5, [r2, #4] ; load 4 ref pixels
|
||||
eor r4, r4, r10
|
||||
|
||||
usub8 r6, r4, r5 ; calculate difference
|
||||
sel r7, r6, lr ; select bytes with positive difference
|
||||
usub8 r6, r5, r4 ; calculate difference with reversed operands
|
||||
sel r6, r6, lr ; select bytes with negative difference
|
||||
|
||||
; calculate partial sums
|
||||
usad8 r4, r7, lr ; calculate sum of positive differences
|
||||
usad8 r5, r6, lr ; calculate sum of negative differences
|
||||
orr r6, r6, r7 ; differences of all 4 pixels
|
||||
|
||||
; calculate total sum
|
||||
add r8, r8, r4 ; add positive differences to sum
|
||||
sub r8, r8, r5 ; subtract negative differences from sum
|
||||
|
||||
; calculate sse
|
||||
uxtb16 r5, r6 ; byte (two pixels) to halfwords
|
||||
uxtb16 r7, r6, ror #8 ; another two pixels to halfwords
|
||||
smlad r11, r5, r5, r11 ; dual signed multiply, add and accumulate (1)
|
||||
|
||||
; 3rd 4 pixels
|
||||
ldr r4, [r0, #8] ; load source pixels a, row N
|
||||
ldr r6, [r0, #9] ; load source pixels b, row N
|
||||
ldr r5, [r9, #8] ; load source pixels c, row N+1
|
||||
|
||||
smlad r11, r7, r7, r11 ; dual signed multiply, add and accumulate (2)
|
||||
|
||||
ldr r7, [r9, #9] ; load source pixels d, row N+1
|
||||
|
||||
; x = (a + b + 1) >> 1, interpolate pixels horizontally on row N
|
||||
mvn r6, r6
|
||||
uhsub8 r4, r4, r6
|
||||
eor r4, r4, r10
|
||||
; y = (c + d + 1) >> 1, interpolate pixels horizontally on row N+1
|
||||
mvn r7, r7
|
||||
uhsub8 r5, r5, r7
|
||||
eor r5, r5, r10
|
||||
; z = (x + y + 1) >> 1, interpolate half pixel values vertically
|
||||
mvn r5, r5
|
||||
uhsub8 r4, r4, r5
|
||||
ldr r5, [r2, #8] ; load 4 ref pixels
|
||||
eor r4, r4, r10
|
||||
|
||||
usub8 r6, r4, r5 ; calculate difference
|
||||
sel r7, r6, lr ; select bytes with positive difference
|
||||
usub8 r6, r5, r4 ; calculate difference with reversed operands
|
||||
sel r6, r6, lr ; select bytes with negative difference
|
||||
|
||||
; calculate partial sums
|
||||
usad8 r4, r7, lr ; calculate sum of positive differences
|
||||
usad8 r5, r6, lr ; calculate sum of negative differences
|
||||
orr r6, r6, r7 ; differences of all 4 pixels
|
||||
|
||||
; calculate total sum
|
||||
add r8, r8, r4 ; add positive differences to sum
|
||||
sub r8, r8, r5 ; subtract negative differences from sum
|
||||
|
||||
; calculate sse
|
||||
uxtb16 r5, r6 ; byte (two pixels) to halfwords
|
||||
uxtb16 r7, r6, ror #8 ; another two pixels to halfwords
|
||||
smlad r11, r5, r5, r11 ; dual signed multiply, add and accumulate (1)
|
||||
|
||||
; 4th 4 pixels
|
||||
ldr r4, [r0, #12] ; load source pixels a, row N
|
||||
ldr r6, [r0, #13] ; load source pixels b, row N
|
||||
ldr r5, [r9, #12] ; load source pixels c, row N+1
|
||||
smlad r11, r7, r7, r11 ; dual signed multiply, add and accumulate (2)
|
||||
ldr r7, [r9, #13] ; load source pixels d, row N+1
|
||||
|
||||
; x = (a + b + 1) >> 1, interpolate pixels horizontally on row N
|
||||
mvn r6, r6
|
||||
uhsub8 r4, r4, r6
|
||||
eor r4, r4, r10
|
||||
; y = (c + d + 1) >> 1, interpolate pixels horizontally on row N+1
|
||||
mvn r7, r7
|
||||
uhsub8 r5, r5, r7
|
||||
eor r5, r5, r10
|
||||
; z = (x + y + 1) >> 1, interpolate half pixel values vertically
|
||||
mvn r5, r5
|
||||
uhsub8 r4, r4, r5
|
||||
ldr r5, [r2, #12] ; load 4 ref pixels
|
||||
eor r4, r4, r10
|
||||
|
||||
usub8 r6, r4, r5 ; calculate difference
|
||||
add r0, r0, r1 ; set src_ptr to next row
|
||||
sel r7, r6, lr ; select bytes with positive difference
|
||||
usub8 r6, r5, r4 ; calculate difference with reversed operands
|
||||
add r2, r2, r3 ; set dst_ptr to next row
|
||||
sel r6, r6, lr ; select bytes with negative difference
|
||||
|
||||
; calculate partial sums
|
||||
usad8 r4, r7, lr ; calculate sum of positive differences
|
||||
usad8 r5, r6, lr ; calculate sum of negative differences
|
||||
orr r6, r6, r7 ; differences of all 4 pixels
|
||||
|
||||
; calculate total sum
|
||||
add r8, r8, r4 ; add positive differences to sum
|
||||
sub r8, r8, r5 ; subtract negative differences from sum
|
||||
|
||||
; calculate sse
|
||||
uxtb16 r5, r6 ; byte (two pixels) to halfwords
|
||||
uxtb16 r7, r6, ror #8 ; another two pixels to halfwords
|
||||
smlad r11, r5, r5, r11 ; dual signed multiply, add and accumulate (1)
|
||||
subs r12, r12, #1
|
||||
smlad r11, r7, r7, r11 ; dual signed multiply, add and accumulate (2)
|
||||
|
||||
bne loop
|
||||
|
||||
; return stuff
|
||||
ldr r6, [sp, #40] ; get address of sse
|
||||
mul r0, r8, r8 ; sum * sum
|
||||
str r11, [r6] ; store sse
|
||||
sub r0, r11, r0, lsr #8 ; return (sse - ((sum * sum) >> 8))
|
||||
|
||||
ldmfd sp!, {r4-r12, pc}
|
||||
|
||||
ENDP
|
||||
|
||||
c80808080
|
||||
DCD 0x80808080
|
||||
|
||||
END
|
||||
187
third_party/aom/aom_dsp/arm/variance_halfpixvar16x16_v_media.asm
vendored
Normal file
187
third_party/aom/aom_dsp/arm/variance_halfpixvar16x16_v_media.asm
vendored
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
;
|
||||
; Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
;
|
||||
; This source code is subject to the terms of the BSD 2 Clause License and
|
||||
; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
; was not distributed with this source code in the LICENSE file, you can
|
||||
; obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
; Media Patent License 1.0 was not distributed with this source code in the
|
||||
; PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
;
|
||||
|
||||
;
|
||||
|
||||
|
||||
EXPORT |aom_variance_halfpixvar16x16_v_media|
|
||||
|
||||
ARM
|
||||
REQUIRE8
|
||||
PRESERVE8
|
||||
|
||||
AREA ||.text||, CODE, READONLY, ALIGN=2
|
||||
|
||||
; r0 unsigned char *src_ptr
|
||||
; r1 int source_stride
|
||||
; r2 unsigned char *ref_ptr
|
||||
; r3 int recon_stride
|
||||
; stack unsigned int *sse
|
||||
|aom_variance_halfpixvar16x16_v_media| PROC
|
||||
|
||||
stmfd sp!, {r4-r12, lr}
|
||||
|
||||
pld [r0, r1, lsl #0]
|
||||
pld [r2, r3, lsl #0]
|
||||
|
||||
mov r8, #0 ; initialize sum = 0
|
||||
ldr r10, c80808080
|
||||
mov r11, #0 ; initialize sse = 0
|
||||
mov r12, #16 ; set loop counter to 16 (=block height)
|
||||
mov lr, #0 ; constant zero
|
||||
loop
|
||||
add r9, r0, r1 ; set src pointer to next row
|
||||
; 1st 4 pixels
|
||||
ldr r4, [r0, #0] ; load 4 src pixels
|
||||
ldr r6, [r9, #0] ; load 4 src pixels from next row
|
||||
ldr r5, [r2, #0] ; load 4 ref pixels
|
||||
|
||||
; bilinear interpolation
|
||||
mvn r6, r6
|
||||
uhsub8 r4, r4, r6
|
||||
eor r4, r4, r10
|
||||
|
||||
usub8 r6, r4, r5 ; calculate difference
|
||||
pld [r0, r1, lsl #1]
|
||||
sel r7, r6, lr ; select bytes with positive difference
|
||||
usub8 r6, r5, r4 ; calculate difference with reversed operands
|
||||
pld [r2, r3, lsl #1]
|
||||
sel r6, r6, lr ; select bytes with negative difference
|
||||
|
||||
; calculate partial sums
|
||||
usad8 r4, r7, lr ; calculate sum of positive differences
|
||||
usad8 r5, r6, lr ; calculate sum of negative differences
|
||||
orr r6, r6, r7 ; differences of all 4 pixels
|
||||
; calculate total sum
|
||||
adds r8, r8, r4 ; add positive differences to sum
|
||||
subs r8, r8, r5 ; subtract negative differences from sum
|
||||
|
||||
; calculate sse
|
||||
uxtb16 r5, r6 ; byte (two pixels) to halfwords
|
||||
uxtb16 r7, r6, ror #8 ; another two pixels to halfwords
|
||||
smlad r11, r5, r5, r11 ; dual signed multiply, add and accumulate (1)
|
||||
|
||||
; 2nd 4 pixels
|
||||
ldr r4, [r0, #4] ; load 4 src pixels
|
||||
ldr r6, [r9, #4] ; load 4 src pixels from next row
|
||||
ldr r5, [r2, #4] ; load 4 ref pixels
|
||||
|
||||
; bilinear interpolation
|
||||
mvn r6, r6
|
||||
uhsub8 r4, r4, r6
|
||||
eor r4, r4, r10
|
||||
|
||||
smlad r11, r7, r7, r11 ; dual signed multiply, add and accumulate (2)
|
||||
|
||||
usub8 r6, r4, r5 ; calculate difference
|
||||
sel r7, r6, lr ; select bytes with positive difference
|
||||
usub8 r6, r5, r4 ; calculate difference with reversed operands
|
||||
sel r6, r6, lr ; select bytes with negative difference
|
||||
|
||||
; calculate partial sums
|
||||
usad8 r4, r7, lr ; calculate sum of positive differences
|
||||
usad8 r5, r6, lr ; calculate sum of negative differences
|
||||
orr r6, r6, r7 ; differences of all 4 pixels
|
||||
|
||||
; calculate total sum
|
||||
add r8, r8, r4 ; add positive differences to sum
|
||||
sub r8, r8, r5 ; subtract negative differences from sum
|
||||
|
||||
; calculate sse
|
||||
uxtb16 r5, r6 ; byte (two pixels) to halfwords
|
||||
uxtb16 r7, r6, ror #8 ; another two pixels to halfwords
|
||||
smlad r11, r5, r5, r11 ; dual signed multiply, add and accumulate (1)
|
||||
|
||||
; 3rd 4 pixels
|
||||
ldr r4, [r0, #8] ; load 4 src pixels
|
||||
ldr r6, [r9, #8] ; load 4 src pixels from next row
|
||||
ldr r5, [r2, #8] ; load 4 ref pixels
|
||||
|
||||
; bilinear interpolation
|
||||
mvn r6, r6
|
||||
uhsub8 r4, r4, r6
|
||||
eor r4, r4, r10
|
||||
|
||||
smlad r11, r7, r7, r11 ; dual signed multiply, add and accumulate (2)
|
||||
|
||||
usub8 r6, r4, r5 ; calculate difference
|
||||
sel r7, r6, lr ; select bytes with positive difference
|
||||
usub8 r6, r5, r4 ; calculate difference with reversed operands
|
||||
sel r6, r6, lr ; select bytes with negative difference
|
||||
|
||||
; calculate partial sums
|
||||
usad8 r4, r7, lr ; calculate sum of positive differences
|
||||
usad8 r5, r6, lr ; calculate sum of negative differences
|
||||
orr r6, r6, r7 ; differences of all 4 pixels
|
||||
|
||||
; calculate total sum
|
||||
add r8, r8, r4 ; add positive differences to sum
|
||||
sub r8, r8, r5 ; subtract negative differences from sum
|
||||
|
||||
; calculate sse
|
||||
uxtb16 r5, r6 ; byte (two pixels) to halfwords
|
||||
uxtb16 r7, r6, ror #8 ; another two pixels to halfwords
|
||||
smlad r11, r5, r5, r11 ; dual signed multiply, add and accumulate (1)
|
||||
|
||||
; 4th 4 pixels
|
||||
ldr r4, [r0, #12] ; load 4 src pixels
|
||||
ldr r6, [r9, #12] ; load 4 src pixels from next row
|
||||
ldr r5, [r2, #12] ; load 4 ref pixels
|
||||
|
||||
; bilinear interpolation
|
||||
mvn r6, r6
|
||||
uhsub8 r4, r4, r6
|
||||
eor r4, r4, r10
|
||||
|
||||
smlad r11, r7, r7, r11 ; dual signed multiply, add and accumulate (2)
|
||||
|
||||
usub8 r6, r4, r5 ; calculate difference
|
||||
add r0, r0, r1 ; set src_ptr to next row
|
||||
sel r7, r6, lr ; select bytes with positive difference
|
||||
usub8 r6, r5, r4 ; calculate difference with reversed operands
|
||||
add r2, r2, r3 ; set dst_ptr to next row
|
||||
sel r6, r6, lr ; select bytes with negative difference
|
||||
|
||||
; calculate partial sums
|
||||
usad8 r4, r7, lr ; calculate sum of positive differences
|
||||
usad8 r5, r6, lr ; calculate sum of negative differences
|
||||
orr r6, r6, r7 ; differences of all 4 pixels
|
||||
|
||||
; calculate total sum
|
||||
add r8, r8, r4 ; add positive differences to sum
|
||||
sub r8, r8, r5 ; subtract negative differences from sum
|
||||
|
||||
; calculate sse
|
||||
uxtb16 r5, r6 ; byte (two pixels) to halfwords
|
||||
uxtb16 r7, r6, ror #8 ; another two pixels to halfwords
|
||||
smlad r11, r5, r5, r11 ; dual signed multiply, add and accumulate (1)
|
||||
smlad r11, r7, r7, r11 ; dual signed multiply, add and accumulate (2)
|
||||
|
||||
|
||||
subs r12, r12, #1
|
||||
|
||||
bne loop
|
||||
|
||||
; return stuff
|
||||
ldr r6, [sp, #40] ; get address of sse
|
||||
mul r0, r8, r8 ; sum * sum
|
||||
str r11, [r6] ; store sse
|
||||
sub r0, r11, r0, lsr #8 ; return (sse - ((sum * sum) >> 8))
|
||||
|
||||
ldmfd sp!, {r4-r12, pc}
|
||||
|
||||
ENDP
|
||||
|
||||
c80808080
|
||||
DCD 0x80808080
|
||||
|
||||
END
|
||||
|
||||
361
third_party/aom/aom_dsp/arm/variance_media.asm
vendored
Normal file
361
third_party/aom/aom_dsp/arm/variance_media.asm
vendored
Normal file
|
|
@ -0,0 +1,361 @@
|
|||
;
|
||||
; Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
;
|
||||
; This source code is subject to the terms of the BSD 2 Clause License and
|
||||
; the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
; was not distributed with this source code in the LICENSE file, you can
|
||||
; obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
; Media Patent License 1.0 was not distributed with this source code in the
|
||||
; PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
;
|
||||
|
||||
;
|
||||
|
||||
|
||||
EXPORT |aom_variance16x16_media|
|
||||
EXPORT |aom_variance8x8_media|
|
||||
EXPORT |aom_mse16x16_media|
|
||||
|
||||
ARM
|
||||
REQUIRE8
|
||||
PRESERVE8
|
||||
|
||||
AREA ||.text||, CODE, READONLY, ALIGN=2
|
||||
|
||||
; r0 unsigned char *src_ptr
|
||||
; r1 int source_stride
|
||||
; r2 unsigned char *ref_ptr
|
||||
; r3 int recon_stride
|
||||
; stack unsigned int *sse
|
||||
|aom_variance16x16_media| PROC
|
||||
|
||||
stmfd sp!, {r4-r12, lr}
|
||||
|
||||
pld [r0, r1, lsl #0]
|
||||
pld [r2, r3, lsl #0]
|
||||
|
||||
mov r8, #0 ; initialize sum = 0
|
||||
mov r11, #0 ; initialize sse = 0
|
||||
mov r12, #16 ; set loop counter to 16 (=block height)
|
||||
|
||||
loop16x16
|
||||
; 1st 4 pixels
|
||||
ldr r4, [r0, #0] ; load 4 src pixels
|
||||
ldr r5, [r2, #0] ; load 4 ref pixels
|
||||
|
||||
mov lr, #0 ; constant zero
|
||||
|
||||
usub8 r6, r4, r5 ; calculate difference
|
||||
pld [r0, r1, lsl #1]
|
||||
sel r7, r6, lr ; select bytes with positive difference
|
||||
usub8 r9, r5, r4 ; calculate difference with reversed operands
|
||||
pld [r2, r3, lsl #1]
|
||||
sel r6, r9, lr ; select bytes with negative difference
|
||||
|
||||
; calculate partial sums
|
||||
usad8 r4, r7, lr ; calculate sum of positive differences
|
||||
usad8 r5, r6, lr ; calculate sum of negative differences
|
||||
orr r6, r6, r7 ; differences of all 4 pixels
|
||||
; calculate total sum
|
||||
adds r8, r8, r4 ; add positive differences to sum
|
||||
subs r8, r8, r5 ; subtract negative differences from sum
|
||||
|
||||
; calculate sse
|
||||
uxtb16 r5, r6 ; byte (two pixels) to halfwords
|
||||
uxtb16 r10, r6, ror #8 ; another two pixels to halfwords
|
||||
smlad r11, r5, r5, r11 ; dual signed multiply, add and accumulate (1)
|
||||
|
||||
; 2nd 4 pixels
|
||||
ldr r4, [r0, #4] ; load 4 src pixels
|
||||
ldr r5, [r2, #4] ; load 4 ref pixels
|
||||
smlad r11, r10, r10, r11 ; dual signed multiply, add and accumulate (2)
|
||||
|
||||
usub8 r6, r4, r5 ; calculate difference
|
||||
sel r7, r6, lr ; select bytes with positive difference
|
||||
usub8 r9, r5, r4 ; calculate difference with reversed operands
|
||||
sel r6, r9, lr ; select bytes with negative difference
|
||||
|
||||
; calculate partial sums
|
||||
usad8 r4, r7, lr ; calculate sum of positive differences
|
||||
usad8 r5, r6, lr ; calculate sum of negative differences
|
||||
orr r6, r6, r7 ; differences of all 4 pixels
|
||||
|
||||
; calculate total sum
|
||||
add r8, r8, r4 ; add positive differences to sum
|
||||
sub r8, r8, r5 ; subtract negative differences from sum
|
||||
|
||||
; calculate sse
|
||||
uxtb16 r5, r6 ; byte (two pixels) to halfwords
|
||||
uxtb16 r10, r6, ror #8 ; another two pixels to halfwords
|
||||
smlad r11, r5, r5, r11 ; dual signed multiply, add and accumulate (1)
|
||||
|
||||
; 3rd 4 pixels
|
||||
ldr r4, [r0, #8] ; load 4 src pixels
|
||||
ldr r5, [r2, #8] ; load 4 ref pixels
|
||||
smlad r11, r10, r10, r11 ; dual signed multiply, add and accumulate (2)
|
||||
|
||||
usub8 r6, r4, r5 ; calculate difference
|
||||
sel r7, r6, lr ; select bytes with positive difference
|
||||
usub8 r9, r5, r4 ; calculate difference with reversed operands
|
||||
sel r6, r9, lr ; select bytes with negative difference
|
||||
|
||||
; calculate partial sums
|
||||
usad8 r4, r7, lr ; calculate sum of positive differences
|
||||
usad8 r5, r6, lr ; calculate sum of negative differences
|
||||
orr r6, r6, r7 ; differences of all 4 pixels
|
||||
|
||||
; calculate total sum
|
||||
add r8, r8, r4 ; add positive differences to sum
|
||||
sub r8, r8, r5 ; subtract negative differences from sum
|
||||
|
||||
; calculate sse
|
||||
uxtb16 r5, r6 ; byte (two pixels) to halfwords
|
||||
uxtb16 r10, r6, ror #8 ; another two pixels to halfwords
|
||||
smlad r11, r5, r5, r11 ; dual signed multiply, add and accumulate (1)
|
||||
|
||||
; 4th 4 pixels
|
||||
ldr r4, [r0, #12] ; load 4 src pixels
|
||||
ldr r5, [r2, #12] ; load 4 ref pixels
|
||||
smlad r11, r10, r10, r11 ; dual signed multiply, add and accumulate (2)
|
||||
|
||||
usub8 r6, r4, r5 ; calculate difference
|
||||
add r0, r0, r1 ; set src_ptr to next row
|
||||
sel r7, r6, lr ; select bytes with positive difference
|
||||
usub8 r9, r5, r4 ; calculate difference with reversed operands
|
||||
add r2, r2, r3 ; set dst_ptr to next row
|
||||
sel r6, r9, lr ; select bytes with negative difference
|
||||
|
||||
; calculate partial sums
|
||||
usad8 r4, r7, lr ; calculate sum of positive differences
|
||||
usad8 r5, r6, lr ; calculate sum of negative differences
|
||||
orr r6, r6, r7 ; differences of all 4 pixels
|
||||
|
||||
; calculate total sum
|
||||
add r8, r8, r4 ; add positive differences to sum
|
||||
sub r8, r8, r5 ; subtract negative differences from sum
|
||||
|
||||
; calculate sse
|
||||
uxtb16 r5, r6 ; byte (two pixels) to halfwords
|
||||
uxtb16 r10, r6, ror #8 ; another two pixels to halfwords
|
||||
smlad r11, r5, r5, r11 ; dual signed multiply, add and accumulate (1)
|
||||
smlad r11, r10, r10, r11 ; dual signed multiply, add and accumulate (2)
|
||||
|
||||
|
||||
subs r12, r12, #1
|
||||
|
||||
bne loop16x16
|
||||
|
||||
; return stuff
|
||||
ldr r6, [sp, #40] ; get address of sse
|
||||
mul r0, r8, r8 ; sum * sum
|
||||
str r11, [r6] ; store sse
|
||||
sub r0, r11, r0, lsr #8 ; return (sse - ((sum * sum) >> 8))
|
||||
|
||||
ldmfd sp!, {r4-r12, pc}
|
||||
|
||||
ENDP
|
||||
|
||||
; r0 unsigned char *src_ptr
|
||||
; r1 int source_stride
|
||||
; r2 unsigned char *ref_ptr
|
||||
; r3 int recon_stride
|
||||
; stack unsigned int *sse
|
||||
|aom_variance8x8_media| PROC
|
||||
|
||||
push {r4-r10, lr}
|
||||
|
||||
pld [r0, r1, lsl #0]
|
||||
pld [r2, r3, lsl #0]
|
||||
|
||||
mov r12, #8 ; set loop counter to 8 (=block height)
|
||||
mov r4, #0 ; initialize sum = 0
|
||||
mov r5, #0 ; initialize sse = 0
|
||||
|
||||
loop8x8
|
||||
; 1st 4 pixels
|
||||
ldr r6, [r0, #0x0] ; load 4 src pixels
|
||||
ldr r7, [r2, #0x0] ; load 4 ref pixels
|
||||
|
||||
mov lr, #0 ; constant zero
|
||||
|
||||
usub8 r8, r6, r7 ; calculate difference
|
||||
pld [r0, r1, lsl #1]
|
||||
sel r10, r8, lr ; select bytes with positive difference
|
||||
usub8 r9, r7, r6 ; calculate difference with reversed operands
|
||||
pld [r2, r3, lsl #1]
|
||||
sel r8, r9, lr ; select bytes with negative difference
|
||||
|
||||
; calculate partial sums
|
||||
usad8 r6, r10, lr ; calculate sum of positive differences
|
||||
usad8 r7, r8, lr ; calculate sum of negative differences
|
||||
orr r8, r8, r10 ; differences of all 4 pixels
|
||||
; calculate total sum
|
||||
add r4, r4, r6 ; add positive differences to sum
|
||||
sub r4, r4, r7 ; subtract negative differences from sum
|
||||
|
||||
; calculate sse
|
||||
uxtb16 r7, r8 ; byte (two pixels) to halfwords
|
||||
uxtb16 r10, r8, ror #8 ; another two pixels to halfwords
|
||||
smlad r5, r7, r7, r5 ; dual signed multiply, add and accumulate (1)
|
||||
|
||||
; 2nd 4 pixels
|
||||
ldr r6, [r0, #0x4] ; load 4 src pixels
|
||||
ldr r7, [r2, #0x4] ; load 4 ref pixels
|
||||
smlad r5, r10, r10, r5 ; dual signed multiply, add and accumulate (2)
|
||||
|
||||
usub8 r8, r6, r7 ; calculate difference
|
||||
add r0, r0, r1 ; set src_ptr to next row
|
||||
sel r10, r8, lr ; select bytes with positive difference
|
||||
usub8 r9, r7, r6 ; calculate difference with reversed operands
|
||||
add r2, r2, r3 ; set dst_ptr to next row
|
||||
sel r8, r9, lr ; select bytes with negative difference
|
||||
|
||||
; calculate partial sums
|
||||
usad8 r6, r10, lr ; calculate sum of positive differences
|
||||
usad8 r7, r8, lr ; calculate sum of negative differences
|
||||
orr r8, r8, r10 ; differences of all 4 pixels
|
||||
|
||||
; calculate total sum
|
||||
add r4, r4, r6 ; add positive differences to sum
|
||||
sub r4, r4, r7 ; subtract negative differences from sum
|
||||
|
||||
; calculate sse
|
||||
uxtb16 r7, r8 ; byte (two pixels) to halfwords
|
||||
uxtb16 r10, r8, ror #8 ; another two pixels to halfwords
|
||||
smlad r5, r7, r7, r5 ; dual signed multiply, add and accumulate (1)
|
||||
subs r12, r12, #1 ; next row
|
||||
smlad r5, r10, r10, r5 ; dual signed multiply, add and accumulate (2)
|
||||
|
||||
bne loop8x8
|
||||
|
||||
; return stuff
|
||||
ldr r8, [sp, #32] ; get address of sse
|
||||
mul r1, r4, r4 ; sum * sum
|
||||
str r5, [r8] ; store sse
|
||||
sub r0, r5, r1, ASR #6 ; return (sse - ((sum * sum) >> 6))
|
||||
|
||||
pop {r4-r10, pc}
|
||||
|
||||
ENDP
|
||||
|
||||
; r0 unsigned char *src_ptr
|
||||
; r1 int source_stride
|
||||
; r2 unsigned char *ref_ptr
|
||||
; r3 int recon_stride
|
||||
; stack unsigned int *sse
|
||||
;
|
||||
;note: Based on aom_variance16x16_media. In this function, sum is never used.
|
||||
; So, we can remove this part of calculation.
|
||||
|
||||
|aom_mse16x16_media| PROC
|
||||
|
||||
push {r4-r9, lr}
|
||||
|
||||
pld [r0, r1, lsl #0]
|
||||
pld [r2, r3, lsl #0]
|
||||
|
||||
mov r12, #16 ; set loop counter to 16 (=block height)
|
||||
mov r4, #0 ; initialize sse = 0
|
||||
|
||||
loopmse
|
||||
; 1st 4 pixels
|
||||
ldr r5, [r0, #0x0] ; load 4 src pixels
|
||||
ldr r6, [r2, #0x0] ; load 4 ref pixels
|
||||
|
||||
mov lr, #0 ; constant zero
|
||||
|
||||
usub8 r8, r5, r6 ; calculate difference
|
||||
pld [r0, r1, lsl #1]
|
||||
sel r7, r8, lr ; select bytes with positive difference
|
||||
usub8 r9, r6, r5 ; calculate difference with reversed operands
|
||||
pld [r2, r3, lsl #1]
|
||||
sel r8, r9, lr ; select bytes with negative difference
|
||||
|
||||
; calculate partial sums
|
||||
usad8 r5, r7, lr ; calculate sum of positive differences
|
||||
usad8 r6, r8, lr ; calculate sum of negative differences
|
||||
orr r8, r8, r7 ; differences of all 4 pixels
|
||||
|
||||
ldr r5, [r0, #0x4] ; load 4 src pixels
|
||||
|
||||
; calculate sse
|
||||
uxtb16 r6, r8 ; byte (two pixels) to halfwords
|
||||
uxtb16 r7, r8, ror #8 ; another two pixels to halfwords
|
||||
smlad r4, r6, r6, r4 ; dual signed multiply, add and accumulate (1)
|
||||
|
||||
; 2nd 4 pixels
|
||||
ldr r6, [r2, #0x4] ; load 4 ref pixels
|
||||
smlad r4, r7, r7, r4 ; dual signed multiply, add and accumulate (2)
|
||||
|
||||
usub8 r8, r5, r6 ; calculate difference
|
||||
sel r7, r8, lr ; select bytes with positive difference
|
||||
usub8 r9, r6, r5 ; calculate difference with reversed operands
|
||||
sel r8, r9, lr ; select bytes with negative difference
|
||||
|
||||
; calculate partial sums
|
||||
usad8 r5, r7, lr ; calculate sum of positive differences
|
||||
usad8 r6, r8, lr ; calculate sum of negative differences
|
||||
orr r8, r8, r7 ; differences of all 4 pixels
|
||||
ldr r5, [r0, #0x8] ; load 4 src pixels
|
||||
; calculate sse
|
||||
uxtb16 r6, r8 ; byte (two pixels) to halfwords
|
||||
uxtb16 r7, r8, ror #8 ; another two pixels to halfwords
|
||||
smlad r4, r6, r6, r4 ; dual signed multiply, add and accumulate (1)
|
||||
|
||||
; 3rd 4 pixels
|
||||
ldr r6, [r2, #0x8] ; load 4 ref pixels
|
||||
smlad r4, r7, r7, r4 ; dual signed multiply, add and accumulate (2)
|
||||
|
||||
usub8 r8, r5, r6 ; calculate difference
|
||||
sel r7, r8, lr ; select bytes with positive difference
|
||||
usub8 r9, r6, r5 ; calculate difference with reversed operands
|
||||
sel r8, r9, lr ; select bytes with negative difference
|
||||
|
||||
; calculate partial sums
|
||||
usad8 r5, r7, lr ; calculate sum of positive differences
|
||||
usad8 r6, r8, lr ; calculate sum of negative differences
|
||||
orr r8, r8, r7 ; differences of all 4 pixels
|
||||
|
||||
ldr r5, [r0, #0xc] ; load 4 src pixels
|
||||
|
||||
; calculate sse
|
||||
uxtb16 r6, r8 ; byte (two pixels) to halfwords
|
||||
uxtb16 r7, r8, ror #8 ; another two pixels to halfwords
|
||||
smlad r4, r6, r6, r4 ; dual signed multiply, add and accumulate (1)
|
||||
|
||||
; 4th 4 pixels
|
||||
ldr r6, [r2, #0xc] ; load 4 ref pixels
|
||||
smlad r4, r7, r7, r4 ; dual signed multiply, add and accumulate (2)
|
||||
|
||||
usub8 r8, r5, r6 ; calculate difference
|
||||
add r0, r0, r1 ; set src_ptr to next row
|
||||
sel r7, r8, lr ; select bytes with positive difference
|
||||
usub8 r9, r6, r5 ; calculate difference with reversed operands
|
||||
add r2, r2, r3 ; set dst_ptr to next row
|
||||
sel r8, r9, lr ; select bytes with negative difference
|
||||
|
||||
; calculate partial sums
|
||||
usad8 r5, r7, lr ; calculate sum of positive differences
|
||||
usad8 r6, r8, lr ; calculate sum of negative differences
|
||||
orr r8, r8, r7 ; differences of all 4 pixels
|
||||
|
||||
subs r12, r12, #1 ; next row
|
||||
|
||||
; calculate sse
|
||||
uxtb16 r6, r8 ; byte (two pixels) to halfwords
|
||||
uxtb16 r7, r8, ror #8 ; another two pixels to halfwords
|
||||
smlad r4, r6, r6, r4 ; dual signed multiply, add and accumulate (1)
|
||||
smlad r4, r7, r7, r4 ; dual signed multiply, add and accumulate (2)
|
||||
|
||||
bne loopmse
|
||||
|
||||
; return stuff
|
||||
ldr r1, [sp, #28] ; get address of sse
|
||||
mov r0, r4 ; return sse
|
||||
str r4, [r1] ; store sse
|
||||
|
||||
pop {r4-r9, pc}
|
||||
|
||||
ENDP
|
||||
|
||||
END
|
||||
400
third_party/aom/aom_dsp/arm/variance_neon.c
vendored
Normal file
400
third_party/aom/aom_dsp/arm/variance_neon.c
vendored
Normal file
|
|
@ -0,0 +1,400 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <arm_neon.h>
|
||||
|
||||
#include "./aom_dsp_rtcd.h"
|
||||
#include "./aom_config.h"
|
||||
|
||||
#include "aom/aom_integer.h"
|
||||
#include "aom_ports/mem.h"
|
||||
|
||||
static INLINE int horizontal_add_s16x8(const int16x8_t v_16x8) {
|
||||
const int32x4_t a = vpaddlq_s16(v_16x8);
|
||||
const int64x2_t b = vpaddlq_s32(a);
|
||||
const int32x2_t c = vadd_s32(vreinterpret_s32_s64(vget_low_s64(b)),
|
||||
vreinterpret_s32_s64(vget_high_s64(b)));
|
||||
return vget_lane_s32(c, 0);
|
||||
}
|
||||
|
||||
static INLINE int horizontal_add_s32x4(const int32x4_t v_32x4) {
|
||||
const int64x2_t b = vpaddlq_s32(v_32x4);
|
||||
const int32x2_t c = vadd_s32(vreinterpret_s32_s64(vget_low_s64(b)),
|
||||
vreinterpret_s32_s64(vget_high_s64(b)));
|
||||
return vget_lane_s32(c, 0);
|
||||
}
|
||||
|
||||
// w * h must be less than 2048 or local variable v_sum may overflow.
|
||||
static void variance_neon_w8(const uint8_t *a, int a_stride, const uint8_t *b,
|
||||
int b_stride, int w, int h, uint32_t *sse,
|
||||
int *sum) {
|
||||
int i, j;
|
||||
int16x8_t v_sum = vdupq_n_s16(0);
|
||||
int32x4_t v_sse_lo = vdupq_n_s32(0);
|
||||
int32x4_t v_sse_hi = vdupq_n_s32(0);
|
||||
|
||||
for (i = 0; i < h; ++i) {
|
||||
for (j = 0; j < w; j += 8) {
|
||||
const uint8x8_t v_a = vld1_u8(&a[j]);
|
||||
const uint8x8_t v_b = vld1_u8(&b[j]);
|
||||
const uint16x8_t v_diff = vsubl_u8(v_a, v_b);
|
||||
const int16x8_t sv_diff = vreinterpretq_s16_u16(v_diff);
|
||||
v_sum = vaddq_s16(v_sum, sv_diff);
|
||||
v_sse_lo =
|
||||
vmlal_s16(v_sse_lo, vget_low_s16(sv_diff), vget_low_s16(sv_diff));
|
||||
v_sse_hi =
|
||||
vmlal_s16(v_sse_hi, vget_high_s16(sv_diff), vget_high_s16(sv_diff));
|
||||
}
|
||||
a += a_stride;
|
||||
b += b_stride;
|
||||
}
|
||||
|
||||
*sum = horizontal_add_s16x8(v_sum);
|
||||
*sse = (unsigned int)horizontal_add_s32x4(vaddq_s32(v_sse_lo, v_sse_hi));
|
||||
}
|
||||
|
||||
void aom_get8x8var_neon(const uint8_t *a, int a_stride, const uint8_t *b,
|
||||
int b_stride, unsigned int *sse, int *sum) {
|
||||
variance_neon_w8(a, a_stride, b, b_stride, 8, 8, sse, sum);
|
||||
}
|
||||
|
||||
void aom_get16x16var_neon(const uint8_t *a, int a_stride, const uint8_t *b,
|
||||
int b_stride, unsigned int *sse, int *sum) {
|
||||
variance_neon_w8(a, a_stride, b, b_stride, 16, 16, sse, sum);
|
||||
}
|
||||
|
||||
unsigned int aom_variance8x8_neon(const uint8_t *a, int a_stride,
|
||||
const uint8_t *b, int b_stride,
|
||||
unsigned int *sse) {
|
||||
int sum;
|
||||
variance_neon_w8(a, a_stride, b, b_stride, 8, 8, sse, &sum);
|
||||
return *sse - ((sum * sum) >> 6);
|
||||
}
|
||||
|
||||
unsigned int aom_variance16x16_neon(const uint8_t *a, int a_stride,
|
||||
const uint8_t *b, int b_stride,
|
||||
unsigned int *sse) {
|
||||
int sum;
|
||||
variance_neon_w8(a, a_stride, b, b_stride, 16, 16, sse, &sum);
|
||||
return *sse - (((unsigned int)((int64_t)sum * sum)) >> 8);
|
||||
}
|
||||
|
||||
unsigned int aom_variance32x32_neon(const uint8_t *a, int a_stride,
|
||||
const uint8_t *b, int b_stride,
|
||||
unsigned int *sse) {
|
||||
int sum;
|
||||
variance_neon_w8(a, a_stride, b, b_stride, 32, 32, sse, &sum);
|
||||
return *sse - (unsigned int)(((int64_t)sum * sum) >> 10);
|
||||
}
|
||||
|
||||
unsigned int aom_variance32x64_neon(const uint8_t *a, int a_stride,
|
||||
const uint8_t *b, int b_stride,
|
||||
unsigned int *sse) {
|
||||
int sum1, sum2;
|
||||
uint32_t sse1, sse2;
|
||||
variance_neon_w8(a, a_stride, b, b_stride, 32, 32, &sse1, &sum1);
|
||||
variance_neon_w8(a + (32 * a_stride), a_stride, b + (32 * b_stride), b_stride,
|
||||
32, 32, &sse2, &sum2);
|
||||
*sse = sse1 + sse2;
|
||||
sum1 += sum2;
|
||||
return *sse - (unsigned int)(((int64_t)sum1 * sum1) >> 11);
|
||||
}
|
||||
|
||||
unsigned int aom_variance64x32_neon(const uint8_t *a, int a_stride,
|
||||
const uint8_t *b, int b_stride,
|
||||
unsigned int *sse) {
|
||||
int sum1, sum2;
|
||||
uint32_t sse1, sse2;
|
||||
variance_neon_w8(a, a_stride, b, b_stride, 64, 16, &sse1, &sum1);
|
||||
variance_neon_w8(a + (16 * a_stride), a_stride, b + (16 * b_stride), b_stride,
|
||||
64, 16, &sse2, &sum2);
|
||||
*sse = sse1 + sse2;
|
||||
sum1 += sum2;
|
||||
return *sse - (unsigned int)(((int64_t)sum1 * sum1) >> 11);
|
||||
}
|
||||
|
||||
unsigned int aom_variance64x64_neon(const uint8_t *a, int a_stride,
|
||||
const uint8_t *b, int b_stride,
|
||||
unsigned int *sse) {
|
||||
int sum1, sum2;
|
||||
uint32_t sse1, sse2;
|
||||
|
||||
variance_neon_w8(a, a_stride, b, b_stride, 64, 16, &sse1, &sum1);
|
||||
variance_neon_w8(a + (16 * a_stride), a_stride, b + (16 * b_stride), b_stride,
|
||||
64, 16, &sse2, &sum2);
|
||||
sse1 += sse2;
|
||||
sum1 += sum2;
|
||||
|
||||
variance_neon_w8(a + (16 * 2 * a_stride), a_stride, b + (16 * 2 * b_stride),
|
||||
b_stride, 64, 16, &sse2, &sum2);
|
||||
sse1 += sse2;
|
||||
sum1 += sum2;
|
||||
|
||||
variance_neon_w8(a + (16 * 3 * a_stride), a_stride, b + (16 * 3 * b_stride),
|
||||
b_stride, 64, 16, &sse2, &sum2);
|
||||
*sse = sse1 + sse2;
|
||||
sum1 += sum2;
|
||||
return *sse - (unsigned int)(((int64_t)sum1 * sum1) >> 12);
|
||||
}
|
||||
|
||||
unsigned int aom_variance16x8_neon(const unsigned char *src_ptr,
|
||||
int source_stride,
|
||||
const unsigned char *ref_ptr,
|
||||
int recon_stride, unsigned int *sse) {
|
||||
int i;
|
||||
int16x4_t d22s16, d23s16, d24s16, d25s16, d26s16, d27s16, d28s16, d29s16;
|
||||
uint32x2_t d0u32, d10u32;
|
||||
int64x1_t d0s64, d1s64;
|
||||
uint8x16_t q0u8, q1u8, q2u8, q3u8;
|
||||
uint16x8_t q11u16, q12u16, q13u16, q14u16;
|
||||
int32x4_t q8s32, q9s32, q10s32;
|
||||
int64x2_t q0s64, q1s64, q5s64;
|
||||
|
||||
q8s32 = vdupq_n_s32(0);
|
||||
q9s32 = vdupq_n_s32(0);
|
||||
q10s32 = vdupq_n_s32(0);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
q0u8 = vld1q_u8(src_ptr);
|
||||
src_ptr += source_stride;
|
||||
q1u8 = vld1q_u8(src_ptr);
|
||||
src_ptr += source_stride;
|
||||
__builtin_prefetch(src_ptr);
|
||||
|
||||
q2u8 = vld1q_u8(ref_ptr);
|
||||
ref_ptr += recon_stride;
|
||||
q3u8 = vld1q_u8(ref_ptr);
|
||||
ref_ptr += recon_stride;
|
||||
__builtin_prefetch(ref_ptr);
|
||||
|
||||
q11u16 = vsubl_u8(vget_low_u8(q0u8), vget_low_u8(q2u8));
|
||||
q12u16 = vsubl_u8(vget_high_u8(q0u8), vget_high_u8(q2u8));
|
||||
q13u16 = vsubl_u8(vget_low_u8(q1u8), vget_low_u8(q3u8));
|
||||
q14u16 = vsubl_u8(vget_high_u8(q1u8), vget_high_u8(q3u8));
|
||||
|
||||
d22s16 = vreinterpret_s16_u16(vget_low_u16(q11u16));
|
||||
d23s16 = vreinterpret_s16_u16(vget_high_u16(q11u16));
|
||||
q8s32 = vpadalq_s16(q8s32, vreinterpretq_s16_u16(q11u16));
|
||||
q9s32 = vmlal_s16(q9s32, d22s16, d22s16);
|
||||
q10s32 = vmlal_s16(q10s32, d23s16, d23s16);
|
||||
|
||||
d24s16 = vreinterpret_s16_u16(vget_low_u16(q12u16));
|
||||
d25s16 = vreinterpret_s16_u16(vget_high_u16(q12u16));
|
||||
q8s32 = vpadalq_s16(q8s32, vreinterpretq_s16_u16(q12u16));
|
||||
q9s32 = vmlal_s16(q9s32, d24s16, d24s16);
|
||||
q10s32 = vmlal_s16(q10s32, d25s16, d25s16);
|
||||
|
||||
d26s16 = vreinterpret_s16_u16(vget_low_u16(q13u16));
|
||||
d27s16 = vreinterpret_s16_u16(vget_high_u16(q13u16));
|
||||
q8s32 = vpadalq_s16(q8s32, vreinterpretq_s16_u16(q13u16));
|
||||
q9s32 = vmlal_s16(q9s32, d26s16, d26s16);
|
||||
q10s32 = vmlal_s16(q10s32, d27s16, d27s16);
|
||||
|
||||
d28s16 = vreinterpret_s16_u16(vget_low_u16(q14u16));
|
||||
d29s16 = vreinterpret_s16_u16(vget_high_u16(q14u16));
|
||||
q8s32 = vpadalq_s16(q8s32, vreinterpretq_s16_u16(q14u16));
|
||||
q9s32 = vmlal_s16(q9s32, d28s16, d28s16);
|
||||
q10s32 = vmlal_s16(q10s32, d29s16, d29s16);
|
||||
}
|
||||
|
||||
q10s32 = vaddq_s32(q10s32, q9s32);
|
||||
q0s64 = vpaddlq_s32(q8s32);
|
||||
q1s64 = vpaddlq_s32(q10s32);
|
||||
|
||||
d0s64 = vadd_s64(vget_low_s64(q0s64), vget_high_s64(q0s64));
|
||||
d1s64 = vadd_s64(vget_low_s64(q1s64), vget_high_s64(q1s64));
|
||||
|
||||
q5s64 = vmull_s32(vreinterpret_s32_s64(d0s64), vreinterpret_s32_s64(d0s64));
|
||||
vst1_lane_u32((uint32_t *)sse, vreinterpret_u32_s64(d1s64), 0);
|
||||
|
||||
d10u32 = vshr_n_u32(vreinterpret_u32_s64(vget_low_s64(q5s64)), 7);
|
||||
d0u32 = vsub_u32(vreinterpret_u32_s64(d1s64), d10u32);
|
||||
|
||||
return vget_lane_u32(d0u32, 0);
|
||||
}
|
||||
|
||||
unsigned int aom_variance8x16_neon(const unsigned char *src_ptr,
|
||||
int source_stride,
|
||||
const unsigned char *ref_ptr,
|
||||
int recon_stride, unsigned int *sse) {
|
||||
int i;
|
||||
uint8x8_t d0u8, d2u8, d4u8, d6u8;
|
||||
int16x4_t d22s16, d23s16, d24s16, d25s16;
|
||||
uint32x2_t d0u32, d10u32;
|
||||
int64x1_t d0s64, d1s64;
|
||||
uint16x8_t q11u16, q12u16;
|
||||
int32x4_t q8s32, q9s32, q10s32;
|
||||
int64x2_t q0s64, q1s64, q5s64;
|
||||
|
||||
q8s32 = vdupq_n_s32(0);
|
||||
q9s32 = vdupq_n_s32(0);
|
||||
q10s32 = vdupq_n_s32(0);
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
d0u8 = vld1_u8(src_ptr);
|
||||
src_ptr += source_stride;
|
||||
d2u8 = vld1_u8(src_ptr);
|
||||
src_ptr += source_stride;
|
||||
__builtin_prefetch(src_ptr);
|
||||
|
||||
d4u8 = vld1_u8(ref_ptr);
|
||||
ref_ptr += recon_stride;
|
||||
d6u8 = vld1_u8(ref_ptr);
|
||||
ref_ptr += recon_stride;
|
||||
__builtin_prefetch(ref_ptr);
|
||||
|
||||
q11u16 = vsubl_u8(d0u8, d4u8);
|
||||
q12u16 = vsubl_u8(d2u8, d6u8);
|
||||
|
||||
d22s16 = vreinterpret_s16_u16(vget_low_u16(q11u16));
|
||||
d23s16 = vreinterpret_s16_u16(vget_high_u16(q11u16));
|
||||
q8s32 = vpadalq_s16(q8s32, vreinterpretq_s16_u16(q11u16));
|
||||
q9s32 = vmlal_s16(q9s32, d22s16, d22s16);
|
||||
q10s32 = vmlal_s16(q10s32, d23s16, d23s16);
|
||||
|
||||
d24s16 = vreinterpret_s16_u16(vget_low_u16(q12u16));
|
||||
d25s16 = vreinterpret_s16_u16(vget_high_u16(q12u16));
|
||||
q8s32 = vpadalq_s16(q8s32, vreinterpretq_s16_u16(q12u16));
|
||||
q9s32 = vmlal_s16(q9s32, d24s16, d24s16);
|
||||
q10s32 = vmlal_s16(q10s32, d25s16, d25s16);
|
||||
}
|
||||
|
||||
q10s32 = vaddq_s32(q10s32, q9s32);
|
||||
q0s64 = vpaddlq_s32(q8s32);
|
||||
q1s64 = vpaddlq_s32(q10s32);
|
||||
|
||||
d0s64 = vadd_s64(vget_low_s64(q0s64), vget_high_s64(q0s64));
|
||||
d1s64 = vadd_s64(vget_low_s64(q1s64), vget_high_s64(q1s64));
|
||||
|
||||
q5s64 = vmull_s32(vreinterpret_s32_s64(d0s64), vreinterpret_s32_s64(d0s64));
|
||||
vst1_lane_u32((uint32_t *)sse, vreinterpret_u32_s64(d1s64), 0);
|
||||
|
||||
d10u32 = vshr_n_u32(vreinterpret_u32_s64(vget_low_s64(q5s64)), 7);
|
||||
d0u32 = vsub_u32(vreinterpret_u32_s64(d1s64), d10u32);
|
||||
|
||||
return vget_lane_u32(d0u32, 0);
|
||||
}
|
||||
|
||||
unsigned int aom_mse16x16_neon(const unsigned char *src_ptr, int source_stride,
|
||||
const unsigned char *ref_ptr, int recon_stride,
|
||||
unsigned int *sse) {
|
||||
int i;
|
||||
int16x4_t d22s16, d23s16, d24s16, d25s16, d26s16, d27s16, d28s16, d29s16;
|
||||
int64x1_t d0s64;
|
||||
uint8x16_t q0u8, q1u8, q2u8, q3u8;
|
||||
int32x4_t q7s32, q8s32, q9s32, q10s32;
|
||||
uint16x8_t q11u16, q12u16, q13u16, q14u16;
|
||||
int64x2_t q1s64;
|
||||
|
||||
q7s32 = vdupq_n_s32(0);
|
||||
q8s32 = vdupq_n_s32(0);
|
||||
q9s32 = vdupq_n_s32(0);
|
||||
q10s32 = vdupq_n_s32(0);
|
||||
|
||||
for (i = 0; i < 8; i++) { // mse16x16_neon_loop
|
||||
q0u8 = vld1q_u8(src_ptr);
|
||||
src_ptr += source_stride;
|
||||
q1u8 = vld1q_u8(src_ptr);
|
||||
src_ptr += source_stride;
|
||||
q2u8 = vld1q_u8(ref_ptr);
|
||||
ref_ptr += recon_stride;
|
||||
q3u8 = vld1q_u8(ref_ptr);
|
||||
ref_ptr += recon_stride;
|
||||
|
||||
q11u16 = vsubl_u8(vget_low_u8(q0u8), vget_low_u8(q2u8));
|
||||
q12u16 = vsubl_u8(vget_high_u8(q0u8), vget_high_u8(q2u8));
|
||||
q13u16 = vsubl_u8(vget_low_u8(q1u8), vget_low_u8(q3u8));
|
||||
q14u16 = vsubl_u8(vget_high_u8(q1u8), vget_high_u8(q3u8));
|
||||
|
||||
d22s16 = vreinterpret_s16_u16(vget_low_u16(q11u16));
|
||||
d23s16 = vreinterpret_s16_u16(vget_high_u16(q11u16));
|
||||
q7s32 = vmlal_s16(q7s32, d22s16, d22s16);
|
||||
q8s32 = vmlal_s16(q8s32, d23s16, d23s16);
|
||||
|
||||
d24s16 = vreinterpret_s16_u16(vget_low_u16(q12u16));
|
||||
d25s16 = vreinterpret_s16_u16(vget_high_u16(q12u16));
|
||||
q9s32 = vmlal_s16(q9s32, d24s16, d24s16);
|
||||
q10s32 = vmlal_s16(q10s32, d25s16, d25s16);
|
||||
|
||||
d26s16 = vreinterpret_s16_u16(vget_low_u16(q13u16));
|
||||
d27s16 = vreinterpret_s16_u16(vget_high_u16(q13u16));
|
||||
q7s32 = vmlal_s16(q7s32, d26s16, d26s16);
|
||||
q8s32 = vmlal_s16(q8s32, d27s16, d27s16);
|
||||
|
||||
d28s16 = vreinterpret_s16_u16(vget_low_u16(q14u16));
|
||||
d29s16 = vreinterpret_s16_u16(vget_high_u16(q14u16));
|
||||
q9s32 = vmlal_s16(q9s32, d28s16, d28s16);
|
||||
q10s32 = vmlal_s16(q10s32, d29s16, d29s16);
|
||||
}
|
||||
|
||||
q7s32 = vaddq_s32(q7s32, q8s32);
|
||||
q9s32 = vaddq_s32(q9s32, q10s32);
|
||||
q10s32 = vaddq_s32(q7s32, q9s32);
|
||||
|
||||
q1s64 = vpaddlq_s32(q10s32);
|
||||
d0s64 = vadd_s64(vget_low_s64(q1s64), vget_high_s64(q1s64));
|
||||
|
||||
vst1_lane_u32((uint32_t *)sse, vreinterpret_u32_s64(d0s64), 0);
|
||||
return vget_lane_u32(vreinterpret_u32_s64(d0s64), 0);
|
||||
}
|
||||
|
||||
unsigned int aom_get4x4sse_cs_neon(const unsigned char *src_ptr,
|
||||
int source_stride,
|
||||
const unsigned char *ref_ptr,
|
||||
int recon_stride) {
|
||||
int16x4_t d22s16, d24s16, d26s16, d28s16;
|
||||
int64x1_t d0s64;
|
||||
uint8x8_t d0u8, d1u8, d2u8, d3u8, d4u8, d5u8, d6u8, d7u8;
|
||||
int32x4_t q7s32, q8s32, q9s32, q10s32;
|
||||
uint16x8_t q11u16, q12u16, q13u16, q14u16;
|
||||
int64x2_t q1s64;
|
||||
|
||||
d0u8 = vld1_u8(src_ptr);
|
||||
src_ptr += source_stride;
|
||||
d4u8 = vld1_u8(ref_ptr);
|
||||
ref_ptr += recon_stride;
|
||||
d1u8 = vld1_u8(src_ptr);
|
||||
src_ptr += source_stride;
|
||||
d5u8 = vld1_u8(ref_ptr);
|
||||
ref_ptr += recon_stride;
|
||||
d2u8 = vld1_u8(src_ptr);
|
||||
src_ptr += source_stride;
|
||||
d6u8 = vld1_u8(ref_ptr);
|
||||
ref_ptr += recon_stride;
|
||||
d3u8 = vld1_u8(src_ptr);
|
||||
src_ptr += source_stride;
|
||||
d7u8 = vld1_u8(ref_ptr);
|
||||
ref_ptr += recon_stride;
|
||||
|
||||
q11u16 = vsubl_u8(d0u8, d4u8);
|
||||
q12u16 = vsubl_u8(d1u8, d5u8);
|
||||
q13u16 = vsubl_u8(d2u8, d6u8);
|
||||
q14u16 = vsubl_u8(d3u8, d7u8);
|
||||
|
||||
d22s16 = vget_low_s16(vreinterpretq_s16_u16(q11u16));
|
||||
d24s16 = vget_low_s16(vreinterpretq_s16_u16(q12u16));
|
||||
d26s16 = vget_low_s16(vreinterpretq_s16_u16(q13u16));
|
||||
d28s16 = vget_low_s16(vreinterpretq_s16_u16(q14u16));
|
||||
|
||||
q7s32 = vmull_s16(d22s16, d22s16);
|
||||
q8s32 = vmull_s16(d24s16, d24s16);
|
||||
q9s32 = vmull_s16(d26s16, d26s16);
|
||||
q10s32 = vmull_s16(d28s16, d28s16);
|
||||
|
||||
q7s32 = vaddq_s32(q7s32, q8s32);
|
||||
q9s32 = vaddq_s32(q9s32, q10s32);
|
||||
q9s32 = vaddq_s32(q7s32, q9s32);
|
||||
|
||||
q1s64 = vpaddlq_s32(q9s32);
|
||||
d0s64 = vadd_s64(vget_low_s64(q1s64), vget_high_s64(q1s64));
|
||||
|
||||
return vget_lane_u32(vreinterpret_u32_s64(d0s64), 0);
|
||||
}
|
||||
232
third_party/aom/aom_dsp/avg.c
vendored
Normal file
232
third_party/aom/aom_dsp/avg.c
vendored
Normal file
|
|
@ -0,0 +1,232 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "./aom_dsp_rtcd.h"
|
||||
#include "aom_ports/mem.h"
|
||||
|
||||
unsigned int aom_avg_8x8_c(const uint8_t *src, int stride) {
|
||||
int i, j;
|
||||
int sum = 0;
|
||||
for (i = 0; i < 8; ++i, src += stride)
|
||||
for (j = 0; j < 8; sum += src[j], ++j) {
|
||||
}
|
||||
|
||||
return ROUND_POWER_OF_TWO(sum, 6);
|
||||
}
|
||||
|
||||
unsigned int aom_avg_4x4_c(const uint8_t *src, int stride) {
|
||||
int i, j;
|
||||
int sum = 0;
|
||||
for (i = 0; i < 4; ++i, src += stride)
|
||||
for (j = 0; j < 4; sum += src[j], ++j) {
|
||||
}
|
||||
|
||||
return ROUND_POWER_OF_TWO(sum, 4);
|
||||
}
|
||||
|
||||
// src_diff: first pass, 9 bit, dynamic range [-255, 255]
|
||||
// second pass, 12 bit, dynamic range [-2040, 2040]
|
||||
static void hadamard_col8(const int16_t *src_diff, int src_stride,
|
||||
int16_t *coeff) {
|
||||
int16_t b0 = src_diff[0 * src_stride] + src_diff[1 * src_stride];
|
||||
int16_t b1 = src_diff[0 * src_stride] - src_diff[1 * src_stride];
|
||||
int16_t b2 = src_diff[2 * src_stride] + src_diff[3 * src_stride];
|
||||
int16_t b3 = src_diff[2 * src_stride] - src_diff[3 * src_stride];
|
||||
int16_t b4 = src_diff[4 * src_stride] + src_diff[5 * src_stride];
|
||||
int16_t b5 = src_diff[4 * src_stride] - src_diff[5 * src_stride];
|
||||
int16_t b6 = src_diff[6 * src_stride] + src_diff[7 * src_stride];
|
||||
int16_t b7 = src_diff[6 * src_stride] - src_diff[7 * src_stride];
|
||||
|
||||
int16_t c0 = b0 + b2;
|
||||
int16_t c1 = b1 + b3;
|
||||
int16_t c2 = b0 - b2;
|
||||
int16_t c3 = b1 - b3;
|
||||
int16_t c4 = b4 + b6;
|
||||
int16_t c5 = b5 + b7;
|
||||
int16_t c6 = b4 - b6;
|
||||
int16_t c7 = b5 - b7;
|
||||
|
||||
coeff[0] = c0 + c4;
|
||||
coeff[7] = c1 + c5;
|
||||
coeff[3] = c2 + c6;
|
||||
coeff[4] = c3 + c7;
|
||||
coeff[2] = c0 - c4;
|
||||
coeff[6] = c1 - c5;
|
||||
coeff[1] = c2 - c6;
|
||||
coeff[5] = c3 - c7;
|
||||
}
|
||||
|
||||
// The order of the output coeff of the hadamard is not important. For
|
||||
// optimization purposes the final transpose may be skipped.
|
||||
void aom_hadamard_8x8_c(const int16_t *src_diff, int src_stride,
|
||||
int16_t *coeff) {
|
||||
int idx;
|
||||
int16_t buffer[64];
|
||||
int16_t *tmp_buf = &buffer[0];
|
||||
for (idx = 0; idx < 8; ++idx) {
|
||||
hadamard_col8(src_diff, src_stride, tmp_buf); // src_diff: 9 bit
|
||||
// dynamic range [-255, 255]
|
||||
tmp_buf += 8;
|
||||
++src_diff;
|
||||
}
|
||||
|
||||
tmp_buf = &buffer[0];
|
||||
for (idx = 0; idx < 8; ++idx) {
|
||||
hadamard_col8(tmp_buf, 8, coeff); // tmp_buf: 12 bit
|
||||
// dynamic range [-2040, 2040]
|
||||
coeff += 8; // coeff: 15 bit
|
||||
// dynamic range [-16320, 16320]
|
||||
++tmp_buf;
|
||||
}
|
||||
}
|
||||
|
||||
// In place 16x16 2D Hadamard transform
|
||||
void aom_hadamard_16x16_c(const int16_t *src_diff, int src_stride,
|
||||
int16_t *coeff) {
|
||||
int idx;
|
||||
for (idx = 0; idx < 4; ++idx) {
|
||||
// src_diff: 9 bit, dynamic range [-255, 255]
|
||||
const int16_t *src_ptr =
|
||||
src_diff + (idx >> 1) * 8 * src_stride + (idx & 0x01) * 8;
|
||||
aom_hadamard_8x8_c(src_ptr, src_stride, coeff + idx * 64);
|
||||
}
|
||||
|
||||
// coeff: 15 bit, dynamic range [-16320, 16320]
|
||||
for (idx = 0; idx < 64; ++idx) {
|
||||
int16_t a0 = coeff[0];
|
||||
int16_t a1 = coeff[64];
|
||||
int16_t a2 = coeff[128];
|
||||
int16_t a3 = coeff[192];
|
||||
|
||||
int16_t b0 = (a0 + a1) >> 1; // (a0 + a1): 16 bit, [-32640, 32640]
|
||||
int16_t b1 = (a0 - a1) >> 1; // b0-b3: 15 bit, dynamic range
|
||||
int16_t b2 = (a2 + a3) >> 1; // [-16320, 16320]
|
||||
int16_t b3 = (a2 - a3) >> 1;
|
||||
|
||||
coeff[0] = b0 + b2; // 16 bit, [-32640, 32640]
|
||||
coeff[64] = b1 + b3;
|
||||
coeff[128] = b0 - b2;
|
||||
coeff[192] = b1 - b3;
|
||||
|
||||
++coeff;
|
||||
}
|
||||
}
|
||||
|
||||
// coeff: 16 bits, dynamic range [-32640, 32640].
|
||||
// length: value range {16, 64, 256, 1024}.
|
||||
int aom_satd_c(const int16_t *coeff, int length) {
|
||||
int i;
|
||||
int satd = 0;
|
||||
for (i = 0; i < length; ++i) satd += abs(coeff[i]);
|
||||
|
||||
// satd: 26 bits, dynamic range [-32640 * 1024, 32640 * 1024]
|
||||
return satd;
|
||||
}
|
||||
|
||||
// Integer projection onto row vectors.
|
||||
// height: value range {16, 32, 64}.
|
||||
void aom_int_pro_row_c(int16_t hbuf[16], const uint8_t *ref, int ref_stride,
|
||||
int height) {
|
||||
int idx;
|
||||
const int norm_factor = height >> 1;
|
||||
for (idx = 0; idx < 16; ++idx) {
|
||||
int i;
|
||||
hbuf[idx] = 0;
|
||||
// hbuf[idx]: 14 bit, dynamic range [0, 16320].
|
||||
for (i = 0; i < height; ++i) hbuf[idx] += ref[i * ref_stride];
|
||||
// hbuf[idx]: 9 bit, dynamic range [0, 510].
|
||||
hbuf[idx] /= norm_factor;
|
||||
++ref;
|
||||
}
|
||||
}
|
||||
|
||||
// width: value range {16, 32, 64}.
|
||||
int16_t aom_int_pro_col_c(const uint8_t *ref, int width) {
|
||||
int idx;
|
||||
int16_t sum = 0;
|
||||
// sum: 14 bit, dynamic range [0, 16320]
|
||||
for (idx = 0; idx < width; ++idx) sum += ref[idx];
|
||||
return sum;
|
||||
}
|
||||
|
||||
// ref: [0 - 510]
|
||||
// src: [0 - 510]
|
||||
// bwl: {2, 3, 4}
|
||||
int aom_vector_var_c(const int16_t *ref, const int16_t *src, int bwl) {
|
||||
int i;
|
||||
int width = 4 << bwl;
|
||||
int sse = 0, mean = 0, var;
|
||||
|
||||
for (i = 0; i < width; ++i) {
|
||||
int diff = ref[i] - src[i]; // diff: dynamic range [-510, 510], 10 bits.
|
||||
mean += diff; // mean: dynamic range 16 bits.
|
||||
sse += diff * diff; // sse: dynamic range 26 bits.
|
||||
}
|
||||
|
||||
// (mean * mean): dynamic range 31 bits.
|
||||
var = sse - ((mean * mean) >> (bwl + 2));
|
||||
return var;
|
||||
}
|
||||
|
||||
void aom_minmax_8x8_c(const uint8_t *src, int src_stride, const uint8_t *ref,
|
||||
int ref_stride, int *min, int *max) {
|
||||
int i, j;
|
||||
*min = 255;
|
||||
*max = 0;
|
||||
for (i = 0; i < 8; ++i, src += src_stride, ref += ref_stride) {
|
||||
for (j = 0; j < 8; ++j) {
|
||||
int diff = abs(src[j] - ref[j]);
|
||||
*min = diff < *min ? diff : *min;
|
||||
*max = diff > *max ? diff : *max;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_HIGHBITDEPTH
|
||||
unsigned int aom_highbd_avg_8x8_c(const uint8_t *src, int stride) {
|
||||
int i, j;
|
||||
int sum = 0;
|
||||
const uint16_t *s = CONVERT_TO_SHORTPTR(src);
|
||||
for (i = 0; i < 8; ++i, s += stride)
|
||||
for (j = 0; j < 8; sum += s[j], ++j) {
|
||||
}
|
||||
|
||||
return ROUND_POWER_OF_TWO(sum, 6);
|
||||
}
|
||||
|
||||
unsigned int aom_highbd_avg_4x4_c(const uint8_t *src, int stride) {
|
||||
int i, j;
|
||||
int sum = 0;
|
||||
const uint16_t *s = CONVERT_TO_SHORTPTR(src);
|
||||
for (i = 0; i < 4; ++i, s += stride)
|
||||
for (j = 0; j < 4; sum += s[j], ++j) {
|
||||
}
|
||||
|
||||
return ROUND_POWER_OF_TWO(sum, 4);
|
||||
}
|
||||
|
||||
void aom_highbd_minmax_8x8_c(const uint8_t *s8, int p, const uint8_t *d8,
|
||||
int dp, int *min, int *max) {
|
||||
int i, j;
|
||||
const uint16_t *s = CONVERT_TO_SHORTPTR(s8);
|
||||
const uint16_t *d = CONVERT_TO_SHORTPTR(d8);
|
||||
*min = 255;
|
||||
*max = 0;
|
||||
for (i = 0; i < 8; ++i, s += p, d += dp) {
|
||||
for (j = 0; j < 8; ++j) {
|
||||
int diff = abs(s[j] - d[j]);
|
||||
*min = diff < *min ? diff : *min;
|
||||
*max = diff > *max ? diff : *max;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // CONFIG_HIGHBITDEPTH
|
||||
117
third_party/aom/aom_dsp/binary_codes_reader.c
vendored
Normal file
117
third_party/aom/aom_dsp/binary_codes_reader.c
vendored
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include "aom_dsp/bitreader.h"
|
||||
|
||||
#include "av1/common/common.h"
|
||||
|
||||
// Inverse recenters a non-negative literal v around a reference r
|
||||
static uint16_t inv_recenter_nonneg(uint16_t r, uint16_t v) {
|
||||
if (v > (r << 1))
|
||||
return v;
|
||||
else if ((v & 1) == 0)
|
||||
return (v >> 1) + r;
|
||||
else
|
||||
return r - ((v + 1) >> 1);
|
||||
}
|
||||
|
||||
// Inverse recenters a non-negative literal v in [0, n-1] around a
|
||||
// reference r also in [0, n-1]
|
||||
static uint16_t inv_recenter_finite_nonneg(uint16_t n, uint16_t r, uint16_t v) {
|
||||
if ((r << 1) <= n) {
|
||||
return inv_recenter_nonneg(r, v);
|
||||
} else {
|
||||
return n - 1 - inv_recenter_nonneg(n - 1 - r, v);
|
||||
}
|
||||
}
|
||||
|
||||
int16_t aom_read_primitive_symmetric(aom_reader *r, unsigned int mag_bits) {
|
||||
if (aom_read_bit(r, NULL)) {
|
||||
int s = aom_read_bit(r, NULL);
|
||||
int16_t x = aom_read_literal(r, mag_bits, NULL) + 1;
|
||||
return (s > 0 ? -x : x);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t aom_read_primitive_quniform(aom_reader *r, uint16_t n) {
|
||||
if (n <= 1) return 0;
|
||||
const int l = get_msb(n - 1) + 1;
|
||||
const int m = (1 << l) - n;
|
||||
const int v = aom_read_literal(r, l - 1, NULL);
|
||||
return v < m ? v : (v << 1) - m + aom_read_bit(r, NULL);
|
||||
}
|
||||
|
||||
uint16_t aom_read_primitive_refbilevel(aom_reader *r, uint16_t n, uint16_t p,
|
||||
uint16_t ref) {
|
||||
if (n <= 1) return 0;
|
||||
assert(p > 0 && p <= n);
|
||||
assert(ref < n);
|
||||
int lolimit = ref - p / 2;
|
||||
const int hilimit = lolimit + p - 1;
|
||||
if (lolimit < 0) {
|
||||
lolimit = 0;
|
||||
} else if (hilimit >= n) {
|
||||
lolimit = n - p;
|
||||
}
|
||||
int v;
|
||||
if (aom_read_bit(r, NULL)) {
|
||||
v = aom_read_primitive_quniform(r, p) + lolimit;
|
||||
} else {
|
||||
v = aom_read_primitive_quniform(r, n - p);
|
||||
if (v >= lolimit) v += p;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
// Decode finite subexponential code that for a symbol v in [0, n-1] with
|
||||
// parameter k
|
||||
uint16_t aom_read_primitive_subexpfin(aom_reader *r, uint16_t n, uint16_t k) {
|
||||
int i = 0;
|
||||
int mk = 0;
|
||||
uint16_t v;
|
||||
while (1) {
|
||||
int b = (i ? k + i - 1 : k);
|
||||
int a = (1 << b);
|
||||
if (n <= mk + 3 * a) {
|
||||
v = aom_read_primitive_quniform(r, n - mk) + mk;
|
||||
break;
|
||||
} else {
|
||||
if (aom_read_bit(r, NULL)) {
|
||||
i = i + 1;
|
||||
mk += a;
|
||||
} else {
|
||||
v = aom_read_literal(r, b, NULL) + mk;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
// Decode finite subexponential code that for a symbol v in [0, n-1] with
|
||||
// parameter k
|
||||
// based on a reference ref also in [0, n-1].
|
||||
uint16_t aom_read_primitive_refsubexpfin(aom_reader *r, uint16_t n, uint16_t k,
|
||||
uint16_t ref) {
|
||||
return inv_recenter_finite_nonneg(n, ref,
|
||||
aom_read_primitive_subexpfin(r, n, k));
|
||||
}
|
||||
|
||||
// Decode finite subexponential code that for a symbol v in [-(n-1), n-1] with
|
||||
// parameter k based on a reference ref also in [-(n-1), n-1].
|
||||
int16_t aom_read_signed_primitive_refsubexpfin(aom_reader *r, uint16_t n,
|
||||
uint16_t k, int16_t ref) {
|
||||
ref += n - 1;
|
||||
const uint16_t scaled_n = (n << 1) - 1;
|
||||
return aom_read_primitive_refsubexpfin(r, scaled_n, k, ref) - n + 1;
|
||||
}
|
||||
38
third_party/aom/aom_dsp/binary_codes_reader.h
vendored
Normal file
38
third_party/aom/aom_dsp/binary_codes_reader.h
vendored
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#ifndef AOM_DSP_BINARY_CODES_READER_H_
|
||||
#define AOM_DSP_BINARY_CODES_READER_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include "./aom_config.h"
|
||||
#include "aom/aom_integer.h"
|
||||
#include "aom_dsp/bitreader.h"
|
||||
|
||||
int16_t aom_read_primitive_symmetric(aom_reader *r, unsigned int mag_bits);
|
||||
|
||||
uint16_t aom_read_primitive_quniform(aom_reader *r, uint16_t n);
|
||||
uint16_t aom_read_primitive_refbilevel(aom_reader *r, uint16_t n, uint16_t p,
|
||||
uint16_t ref);
|
||||
uint16_t aom_read_primitive_subexpfin(aom_reader *r, uint16_t n, uint16_t k);
|
||||
uint16_t aom_read_primitive_refsubexpfin(aom_reader *r, uint16_t n, uint16_t k,
|
||||
uint16_t ref);
|
||||
int16_t aom_read_signed_primitive_refsubexpfin(aom_reader *r, uint16_t n,
|
||||
uint16_t k, int16_t ref);
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // AOM_DSP_BINARY_CODES_READER_H_
|
||||
211
third_party/aom/aom_dsp/binary_codes_writer.c
vendored
Normal file
211
third_party/aom/aom_dsp/binary_codes_writer.c
vendored
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include "aom_dsp/bitwriter.h"
|
||||
|
||||
#include "av1/common/common.h"
|
||||
|
||||
// Recenters a non-negative literal v around a reference r
|
||||
static uint16_t recenter_nonneg(uint16_t r, uint16_t v) {
|
||||
if (v > (r << 1))
|
||||
return v;
|
||||
else if (v >= r)
|
||||
return ((v - r) << 1);
|
||||
else
|
||||
return ((r - v) << 1) - 1;
|
||||
}
|
||||
|
||||
// Recenters a non-negative literal v in [0, n-1] around a
|
||||
// reference r also in [0, n-1]
|
||||
static uint16_t recenter_finite_nonneg(uint16_t n, uint16_t r, uint16_t v) {
|
||||
if ((r << 1) <= n) {
|
||||
return recenter_nonneg(r, v);
|
||||
} else {
|
||||
return recenter_nonneg(n - 1 - r, n - 1 - v);
|
||||
}
|
||||
}
|
||||
|
||||
// Codes a symbol v in [-2^mag_bits, 2^mag_bits].
|
||||
// mag_bits is number of bits for magnitude. The alphabet is of size
|
||||
// 2 * 2^mag_bits + 1, symmetric around 0, where one bit is used to
|
||||
// indicate 0 or non-zero, mag_bits bits are used to indicate magnitide
|
||||
// and 1 more bit for the sign if non-zero.
|
||||
void aom_write_primitive_symmetric(aom_writer *w, int16_t v,
|
||||
unsigned int abs_bits) {
|
||||
if (v == 0) {
|
||||
aom_write_bit(w, 0);
|
||||
} else {
|
||||
const int x = abs(v);
|
||||
const int s = v < 0;
|
||||
aom_write_bit(w, 1);
|
||||
aom_write_bit(w, s);
|
||||
aom_write_literal(w, x - 1, abs_bits);
|
||||
}
|
||||
}
|
||||
|
||||
int aom_count_primitive_symmetric(int16_t v, unsigned int abs_bits) {
|
||||
return (v == 0 ? 1 : abs_bits + 2);
|
||||
}
|
||||
|
||||
// Encodes a value v in [0, n-1] quasi-uniformly
|
||||
void aom_write_primitive_quniform(aom_writer *w, uint16_t n, uint16_t v) {
|
||||
if (n <= 1) return;
|
||||
const int l = get_msb(n - 1) + 1;
|
||||
const int m = (1 << l) - n;
|
||||
if (v < m) {
|
||||
aom_write_literal(w, v, l - 1);
|
||||
} else {
|
||||
aom_write_literal(w, m + ((v - m) >> 1), l - 1);
|
||||
aom_write_bit(w, (v - m) & 1);
|
||||
}
|
||||
}
|
||||
|
||||
int aom_count_primitive_quniform(uint16_t n, uint16_t v) {
|
||||
if (n <= 1) return 0;
|
||||
const int l = get_msb(n - 1) + 1;
|
||||
const int m = (1 << l) - n;
|
||||
return v < m ? l - 1 : l;
|
||||
}
|
||||
|
||||
// Encodes a value v in [0, n-1] based on a reference ref also in [0, n-1]
|
||||
// The closest p values of v from ref are coded using a p-ary quasi-unoform
|
||||
// short code while the remaining n-p values are coded with a longer code.
|
||||
void aom_write_primitive_refbilevel(aom_writer *w, uint16_t n, uint16_t p,
|
||||
uint16_t ref, uint16_t v) {
|
||||
if (n <= 1) return;
|
||||
assert(p > 0 && p <= n);
|
||||
assert(ref < n);
|
||||
int lolimit = ref - p / 2;
|
||||
int hilimit = lolimit + p - 1;
|
||||
if (lolimit < 0) {
|
||||
lolimit = 0;
|
||||
hilimit = p - 1;
|
||||
} else if (hilimit >= n) {
|
||||
hilimit = n - 1;
|
||||
lolimit = n - p;
|
||||
}
|
||||
if (v >= lolimit && v <= hilimit) {
|
||||
aom_write_bit(w, 1);
|
||||
v = v - lolimit;
|
||||
aom_write_primitive_quniform(w, p, v);
|
||||
} else {
|
||||
aom_write_bit(w, 0);
|
||||
if (v > hilimit) v -= p;
|
||||
aom_write_primitive_quniform(w, n - p, v);
|
||||
}
|
||||
}
|
||||
|
||||
int aom_count_primitive_refbilevel(uint16_t n, uint16_t p, uint16_t ref,
|
||||
uint16_t v) {
|
||||
if (n <= 1) return 0;
|
||||
assert(p > 0 && p <= n);
|
||||
assert(ref < n);
|
||||
int lolimit = ref - p / 2;
|
||||
int hilimit = lolimit + p - 1;
|
||||
if (lolimit < 0) {
|
||||
lolimit = 0;
|
||||
hilimit = p - 1;
|
||||
} else if (hilimit >= n) {
|
||||
hilimit = n - 1;
|
||||
lolimit = n - p;
|
||||
}
|
||||
int count = 0;
|
||||
if (v >= lolimit && v <= hilimit) {
|
||||
count++;
|
||||
v = v - lolimit;
|
||||
count += aom_count_primitive_quniform(p, v);
|
||||
} else {
|
||||
count++;
|
||||
if (v > hilimit) v -= p;
|
||||
count += aom_count_primitive_quniform(n - p, v);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
// Finite subexponential code that codes a symbol v in [0, n-1] with parameter k
|
||||
void aom_write_primitive_subexpfin(aom_writer *w, uint16_t n, uint16_t k,
|
||||
uint16_t v) {
|
||||
int i = 0;
|
||||
int mk = 0;
|
||||
while (1) {
|
||||
int b = (i ? k + i - 1 : k);
|
||||
int a = (1 << b);
|
||||
if (n <= mk + 3 * a) {
|
||||
aom_write_primitive_quniform(w, n - mk, v - mk);
|
||||
break;
|
||||
} else {
|
||||
int t = (v >= mk + a);
|
||||
aom_write_bit(w, t);
|
||||
if (t) {
|
||||
i = i + 1;
|
||||
mk += a;
|
||||
} else {
|
||||
aom_write_literal(w, v - mk, b);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int aom_count_primitive_subexpfin(uint16_t n, uint16_t k, uint16_t v) {
|
||||
int count = 0;
|
||||
int i = 0;
|
||||
int mk = 0;
|
||||
while (1) {
|
||||
int b = (i ? k + i - 1 : k);
|
||||
int a = (1 << b);
|
||||
if (n <= mk + 3 * a) {
|
||||
count += aom_count_primitive_quniform(n - mk, v - mk);
|
||||
break;
|
||||
} else {
|
||||
int t = (v >= mk + a);
|
||||
count++;
|
||||
if (t) {
|
||||
i = i + 1;
|
||||
mk += a;
|
||||
} else {
|
||||
count += b;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
// Finite subexponential code that codes a symbol v in [0, n-1] with parameter k
|
||||
// based on a reference ref also in [0, n-1].
|
||||
// Recenters symbol around r first and then uses a finite subexponential code.
|
||||
void aom_write_primitive_refsubexpfin(aom_writer *w, uint16_t n, uint16_t k,
|
||||
int16_t ref, int16_t v) {
|
||||
aom_write_primitive_subexpfin(w, n, k, recenter_finite_nonneg(n, ref, v));
|
||||
}
|
||||
|
||||
void aom_write_signed_primitive_refsubexpfin(aom_writer *w, uint16_t n,
|
||||
uint16_t k, uint16_t ref,
|
||||
uint16_t v) {
|
||||
ref += n - 1;
|
||||
v += n - 1;
|
||||
const uint16_t scaled_n = (n << 1) - 1;
|
||||
aom_write_primitive_refsubexpfin(w, scaled_n, k, ref, v);
|
||||
}
|
||||
|
||||
int aom_count_primitive_refsubexpfin(uint16_t n, uint16_t k, uint16_t ref,
|
||||
uint16_t v) {
|
||||
return aom_count_primitive_subexpfin(n, k, recenter_finite_nonneg(n, ref, v));
|
||||
}
|
||||
|
||||
int aom_count_signed_primitive_refsubexpfin(uint16_t n, uint16_t k, int16_t ref,
|
||||
int16_t v) {
|
||||
ref += n - 1;
|
||||
v += n - 1;
|
||||
const uint16_t scaled_n = (n << 1) - 1;
|
||||
return aom_count_primitive_refsubexpfin(scaled_n, k, ref, v);
|
||||
}
|
||||
70
third_party/aom/aom_dsp/binary_codes_writer.h
vendored
Normal file
70
third_party/aom/aom_dsp/binary_codes_writer.h
vendored
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#ifndef AOM_DSP_BINARY_CODES_WRITER_H_
|
||||
#define AOM_DSP_BINARY_CODES_WRITER_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include "./aom_config.h"
|
||||
#include "aom/aom_integer.h"
|
||||
#include "aom_dsp/bitwriter.h"
|
||||
|
||||
// Codes a symbol v in [-2^mag_bits, 2^mag_bits]
|
||||
// mag_bits is number of bits for magnitude. The alphabet is of size
|
||||
// 2 * 2^mag_bits + 1, symmetric around 0, where one bit is used to
|
||||
// indicate 0 or non-zero, mag_bits bits are used to indicate magnitide
|
||||
// and 1 more bit for the sign if non-zero.
|
||||
void aom_write_primitive_symmetric(aom_writer *w, int16_t v,
|
||||
unsigned int mag_bits);
|
||||
|
||||
// Encodes a value v in [0, n-1] quasi-uniformly
|
||||
void aom_write_primitive_quniform(aom_writer *w, uint16_t n, uint16_t v);
|
||||
|
||||
// Encodes a value v in [0, n-1] based on a reference ref also in [0, n-1]
|
||||
// The closest p values of v from ref are coded using a p-ary quasi-unoform
|
||||
// short code while the remaining n-p values are coded with a longer code.
|
||||
void aom_write_primitive_refbilevel(aom_writer *w, uint16_t n, uint16_t p,
|
||||
uint16_t ref, uint16_t v);
|
||||
|
||||
// Finite subexponential code that codes a symbol v in [0, n-1] with parameter k
|
||||
void aom_write_primitive_subexpfin(aom_writer *w, uint16_t n, uint16_t k,
|
||||
uint16_t v);
|
||||
|
||||
// Finite subexponential code that codes a symbol v in [0, n-1] with parameter k
|
||||
// based on a reference ref also in [0, n-1].
|
||||
void aom_write_primitive_refsubexpfin(aom_writer *w, uint16_t n, uint16_t k,
|
||||
uint16_t ref, uint16_t v);
|
||||
|
||||
// Finite subexponential code that codes a symbol v in [-(n-1), n-1] with
|
||||
// parameter k based on a reference ref also in [-(n-1), n-1].
|
||||
void aom_write_signed_primitive_refsubexpfin(aom_writer *w, uint16_t n,
|
||||
uint16_t k, int16_t ref,
|
||||
int16_t v);
|
||||
|
||||
// Functions that counts bits for the above primitives
|
||||
int aom_count_primitive_symmetric(int16_t v, unsigned int mag_bits);
|
||||
int aom_count_primitive_quniform(uint16_t n, uint16_t v);
|
||||
int aom_count_primitive_refbilevel(uint16_t n, uint16_t p, uint16_t ref,
|
||||
uint16_t v);
|
||||
int aom_count_primitive_subexpfin(uint16_t n, uint16_t k, uint16_t v);
|
||||
int aom_count_primitive_refsubexpfin(uint16_t n, uint16_t k, uint16_t ref,
|
||||
uint16_t v);
|
||||
int aom_count_signed_primitive_refsubexpfin(uint16_t n, uint16_t k, int16_t ref,
|
||||
int16_t v);
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // AOM_DSP_BINARY_CODES_WRITER_H_
|
||||
276
third_party/aom/aom_dsp/bitreader.h
vendored
Normal file
276
third_party/aom/aom_dsp/bitreader.h
vendored
Normal file
|
|
@ -0,0 +1,276 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#ifndef AOM_DSP_BITREADER_H_
|
||||
#define AOM_DSP_BITREADER_H_
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "./aom_config.h"
|
||||
#if CONFIG_EC_ADAPT && !CONFIG_EC_MULTISYMBOL
|
||||
#error "CONFIG_EC_ADAPT is enabled without enabling CONFIG_EC_MULTISYMBOL."
|
||||
#endif
|
||||
|
||||
#include "aom/aomdx.h"
|
||||
#include "aom/aom_integer.h"
|
||||
#if CONFIG_ANS
|
||||
#include "aom_dsp/ansreader.h"
|
||||
#elif CONFIG_DAALA_EC
|
||||
#include "aom_dsp/daalaboolreader.h"
|
||||
#else
|
||||
#include "aom_dsp/dkboolreader.h"
|
||||
#endif
|
||||
#include "aom_dsp/prob.h"
|
||||
#include "av1/common/odintrin.h"
|
||||
|
||||
#if CONFIG_ACCOUNTING
|
||||
#include "av1/decoder/accounting.h"
|
||||
#define ACCT_STR_NAME acct_str
|
||||
#define ACCT_STR_PARAM , const char *ACCT_STR_NAME
|
||||
#define ACCT_STR_ARG(s) , s
|
||||
#else
|
||||
#define ACCT_STR_PARAM
|
||||
#define ACCT_STR_ARG(s)
|
||||
#endif
|
||||
|
||||
#define aom_read(r, prob, ACCT_STR_NAME) \
|
||||
aom_read_(r, prob ACCT_STR_ARG(ACCT_STR_NAME))
|
||||
#define aom_read_bit(r, ACCT_STR_NAME) \
|
||||
aom_read_bit_(r ACCT_STR_ARG(ACCT_STR_NAME))
|
||||
#define aom_read_tree(r, tree, probs, ACCT_STR_NAME) \
|
||||
aom_read_tree_(r, tree, probs ACCT_STR_ARG(ACCT_STR_NAME))
|
||||
#define aom_read_literal(r, bits, ACCT_STR_NAME) \
|
||||
aom_read_literal_(r, bits ACCT_STR_ARG(ACCT_STR_NAME))
|
||||
#define aom_read_cdf(r, cdf, nsymbs, ACCT_STR_NAME) \
|
||||
aom_read_cdf_(r, cdf, nsymbs ACCT_STR_ARG(ACCT_STR_NAME))
|
||||
#define aom_read_symbol(r, cdf, nsymbs, ACCT_STR_NAME) \
|
||||
aom_read_symbol_(r, cdf, nsymbs ACCT_STR_ARG(ACCT_STR_NAME))
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if CONFIG_ANS
|
||||
typedef struct AnsDecoder aom_reader;
|
||||
#elif CONFIG_DAALA_EC
|
||||
typedef struct daala_reader aom_reader;
|
||||
#else
|
||||
typedef struct aom_dk_reader aom_reader;
|
||||
#endif
|
||||
|
||||
static INLINE int aom_reader_init(aom_reader *r, const uint8_t *buffer,
|
||||
size_t size, aom_decrypt_cb decrypt_cb,
|
||||
void *decrypt_state) {
|
||||
#if CONFIG_ANS
|
||||
(void)decrypt_cb;
|
||||
(void)decrypt_state;
|
||||
if (size > INT_MAX) return 1;
|
||||
return ans_read_init(r, buffer, (int)size);
|
||||
#elif CONFIG_DAALA_EC
|
||||
(void)decrypt_cb;
|
||||
(void)decrypt_state;
|
||||
return aom_daala_reader_init(r, buffer, (int)size);
|
||||
#else
|
||||
return aom_dk_reader_init(r, buffer, size, decrypt_cb, decrypt_state);
|
||||
#endif
|
||||
}
|
||||
|
||||
static INLINE const uint8_t *aom_reader_find_end(aom_reader *r) {
|
||||
#if CONFIG_ANS
|
||||
(void)r;
|
||||
assert(0 && "Use the raw buffer size with ANS");
|
||||
return NULL;
|
||||
#elif CONFIG_DAALA_EC
|
||||
return aom_daala_reader_find_end(r);
|
||||
#else
|
||||
return aom_dk_reader_find_end(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
static INLINE int aom_reader_has_error(aom_reader *r) {
|
||||
#if CONFIG_ANS
|
||||
return ans_reader_has_error(r);
|
||||
#elif CONFIG_DAALA_EC
|
||||
return aom_daala_reader_has_error(r);
|
||||
#else
|
||||
return aom_dk_reader_has_error(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Returns the position in the bit reader in bits.
|
||||
static INLINE uint32_t aom_reader_tell(const aom_reader *r) {
|
||||
#if CONFIG_ANS
|
||||
(void)r;
|
||||
assert(0 && "aom_reader_tell() is unimplemented for ANS");
|
||||
return 0;
|
||||
#elif CONFIG_DAALA_EC
|
||||
return aom_daala_reader_tell(r);
|
||||
#else
|
||||
return aom_dk_reader_tell(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Returns the position in the bit reader in 1/8th bits.
|
||||
static INLINE uint32_t aom_reader_tell_frac(const aom_reader *r) {
|
||||
#if CONFIG_ANS
|
||||
(void)r;
|
||||
assert(0 && "aom_reader_tell_frac() is unimplemented for ANS");
|
||||
return 0;
|
||||
#elif CONFIG_DAALA_EC
|
||||
return aom_daala_reader_tell_frac(r);
|
||||
#else
|
||||
return aom_dk_reader_tell_frac(r);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CONFIG_ACCOUNTING
|
||||
static INLINE void aom_process_accounting(const aom_reader *r ACCT_STR_PARAM) {
|
||||
if (r->accounting != NULL) {
|
||||
uint32_t tell_frac;
|
||||
tell_frac = aom_reader_tell_frac(r);
|
||||
aom_accounting_record(r->accounting, ACCT_STR_NAME,
|
||||
tell_frac - r->accounting->last_tell_frac);
|
||||
r->accounting->last_tell_frac = tell_frac;
|
||||
}
|
||||
}
|
||||
|
||||
static INLINE void aom_update_symb_counts(const aom_reader *r, int is_binary) {
|
||||
if (r->accounting != NULL) {
|
||||
r->accounting->syms.num_multi_syms += !is_binary;
|
||||
r->accounting->syms.num_binary_syms += !!is_binary;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static INLINE int aom_read_(aom_reader *r, int prob ACCT_STR_PARAM) {
|
||||
int ret;
|
||||
#if CONFIG_ANS
|
||||
ret = rabs_read(r, prob);
|
||||
#elif CONFIG_DAALA_EC
|
||||
ret = aom_daala_read(r, prob);
|
||||
#else
|
||||
ret = aom_dk_read(r, prob);
|
||||
#endif
|
||||
#if CONFIG_ACCOUNTING
|
||||
if (ACCT_STR_NAME) aom_process_accounting(r, ACCT_STR_NAME);
|
||||
aom_update_symb_counts(r, 1);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
static INLINE int aom_read_bit_(aom_reader *r ACCT_STR_PARAM) {
|
||||
int ret;
|
||||
#if CONFIG_ANS
|
||||
ret = rabs_read_bit(r); // Non trivial optimization at half probability
|
||||
#elif CONFIG_DAALA_EC && CONFIG_RAWBITS
|
||||
// Note this uses raw bits and is not the same as aom_daala_read(r, 128);
|
||||
// Calls to this function are omitted from raw symbol accounting.
|
||||
ret = aom_daala_read_bit(r);
|
||||
#else
|
||||
ret = aom_read(r, 128, NULL); // aom_prob_half
|
||||
#endif
|
||||
#if CONFIG_ACCOUNTING
|
||||
if (ACCT_STR_NAME) aom_process_accounting(r, ACCT_STR_NAME);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
static INLINE int aom_read_literal_(aom_reader *r, int bits ACCT_STR_PARAM) {
|
||||
int literal = 0, bit;
|
||||
|
||||
for (bit = bits - 1; bit >= 0; bit--) literal |= aom_read_bit(r, NULL) << bit;
|
||||
#if CONFIG_ACCOUNTING
|
||||
if (ACCT_STR_NAME) aom_process_accounting(r, ACCT_STR_NAME);
|
||||
#endif
|
||||
return literal;
|
||||
}
|
||||
|
||||
static INLINE int aom_read_tree_as_bits(aom_reader *r,
|
||||
const aom_tree_index *tree,
|
||||
const aom_prob *probs) {
|
||||
aom_tree_index i = 0;
|
||||
|
||||
while ((i = tree[i + aom_read(r, probs[i >> 1], NULL)]) > 0) continue;
|
||||
return -i;
|
||||
}
|
||||
|
||||
#if CONFIG_EC_MULTISYMBOL
|
||||
static INLINE int aom_read_cdf_(aom_reader *r, const aom_cdf_prob *cdf,
|
||||
int nsymbs ACCT_STR_PARAM) {
|
||||
int ret;
|
||||
#if CONFIG_ANS
|
||||
(void)nsymbs;
|
||||
ret = rans_read(r, cdf);
|
||||
#elif CONFIG_DAALA_EC
|
||||
ret = daala_read_symbol(r, cdf, nsymbs);
|
||||
#else
|
||||
#error \
|
||||
"CONFIG_EC_MULTISYMBOL is selected without a valid backing entropy " \
|
||||
"coder. Enable daala_ec or ans for a valid configuration."
|
||||
#endif
|
||||
|
||||
#if CONFIG_ACCOUNTING
|
||||
if (ACCT_STR_NAME) aom_process_accounting(r, ACCT_STR_NAME);
|
||||
aom_update_symb_counts(r, (nsymbs == 2));
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
static INLINE int aom_read_symbol_(aom_reader *r, aom_cdf_prob *cdf,
|
||||
int nsymbs ACCT_STR_PARAM) {
|
||||
int ret;
|
||||
ret = aom_read_cdf(r, cdf, nsymbs, ACCT_STR_NAME);
|
||||
#if CONFIG_EC_ADAPT
|
||||
update_cdf(cdf, ret, nsymbs);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
static INLINE int aom_read_tree_as_cdf(aom_reader *r,
|
||||
const aom_tree_index *tree,
|
||||
const aom_prob *probs) {
|
||||
aom_tree_index i = 0;
|
||||
do {
|
||||
aom_cdf_prob cdf[16];
|
||||
aom_tree_index index[16];
|
||||
int path[16];
|
||||
int dist[16];
|
||||
int nsymbs;
|
||||
int symb;
|
||||
nsymbs = tree_to_cdf(tree, probs, i, cdf, index, path, dist);
|
||||
symb = aom_read_cdf(r, cdf, nsymbs, NULL);
|
||||
OD_ASSERT(symb >= 0 && symb < nsymbs);
|
||||
i = index[symb];
|
||||
} while (i > 0);
|
||||
return -i;
|
||||
}
|
||||
#endif // CONFIG_EC_MULTISYMBOL
|
||||
|
||||
static INLINE int aom_read_tree_(aom_reader *r, const aom_tree_index *tree,
|
||||
const aom_prob *probs ACCT_STR_PARAM) {
|
||||
int ret;
|
||||
#if CONFIG_EC_MULTISYMBOL
|
||||
ret = aom_read_tree_as_cdf(r, tree, probs);
|
||||
#else
|
||||
ret = aom_read_tree_as_bits(r, tree, probs);
|
||||
#endif
|
||||
#if CONFIG_ACCOUNTING
|
||||
if (ACCT_STR_NAME) aom_process_accounting(r, ACCT_STR_NAME);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // AOM_DSP_BITREADER_H_
|
||||
47
third_party/aom/aom_dsp/bitreader_buffer.c
vendored
Normal file
47
third_party/aom/aom_dsp/bitreader_buffer.c
vendored
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
#include "./aom_config.h"
|
||||
#include "./bitreader_buffer.h"
|
||||
|
||||
size_t aom_rb_bytes_read(struct aom_read_bit_buffer *rb) {
|
||||
return (rb->bit_offset + 7) >> 3;
|
||||
}
|
||||
|
||||
int aom_rb_read_bit(struct aom_read_bit_buffer *rb) {
|
||||
const uint32_t off = rb->bit_offset;
|
||||
const uint32_t p = off >> 3;
|
||||
const int q = 7 - (int)(off & 0x7);
|
||||
if (rb->bit_buffer + p < rb->bit_buffer_end) {
|
||||
const int bit = (rb->bit_buffer[p] >> q) & 1;
|
||||
rb->bit_offset = off + 1;
|
||||
return bit;
|
||||
} else {
|
||||
rb->error_handler(rb->error_handler_data);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int aom_rb_read_literal(struct aom_read_bit_buffer *rb, int bits) {
|
||||
int value = 0, bit;
|
||||
for (bit = bits - 1; bit >= 0; bit--) value |= aom_rb_read_bit(rb) << bit;
|
||||
return value;
|
||||
}
|
||||
|
||||
int aom_rb_read_signed_literal(struct aom_read_bit_buffer *rb, int bits) {
|
||||
const int value = aom_rb_read_literal(rb, bits);
|
||||
return aom_rb_read_bit(rb) ? -value : value;
|
||||
}
|
||||
|
||||
int aom_rb_read_inv_signed_literal(struct aom_read_bit_buffer *rb, int bits) {
|
||||
const int nbits = sizeof(unsigned) * 8 - bits - 1;
|
||||
const unsigned value = (unsigned)aom_rb_read_literal(rb, bits + 1) << nbits;
|
||||
return ((int)value) >> nbits;
|
||||
}
|
||||
48
third_party/aom/aom_dsp/bitreader_buffer.h
vendored
Normal file
48
third_party/aom/aom_dsp/bitreader_buffer.h
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#ifndef AOM_DSP_BITREADER_BUFFER_H_
|
||||
#define AOM_DSP_BITREADER_BUFFER_H_
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "aom/aom_integer.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*aom_rb_error_handler)(void *data);
|
||||
|
||||
struct aom_read_bit_buffer {
|
||||
const uint8_t *bit_buffer;
|
||||
const uint8_t *bit_buffer_end;
|
||||
uint32_t bit_offset;
|
||||
|
||||
void *error_handler_data;
|
||||
aom_rb_error_handler error_handler;
|
||||
};
|
||||
|
||||
size_t aom_rb_bytes_read(struct aom_read_bit_buffer *rb);
|
||||
|
||||
int aom_rb_read_bit(struct aom_read_bit_buffer *rb);
|
||||
|
||||
int aom_rb_read_literal(struct aom_read_bit_buffer *rb, int bits);
|
||||
|
||||
int aom_rb_read_signed_literal(struct aom_read_bit_buffer *rb, int bits);
|
||||
|
||||
int aom_rb_read_inv_signed_literal(struct aom_read_bit_buffer *rb, int bits);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // AOM_DSP_BITREADER_BUFFER_H_
|
||||
255
third_party/aom/aom_dsp/bitwriter.h
vendored
Normal file
255
third_party/aom/aom_dsp/bitwriter.h
vendored
Normal file
|
|
@ -0,0 +1,255 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#ifndef AOM_DSP_BITWRITER_H_
|
||||
#define AOM_DSP_BITWRITER_H_
|
||||
|
||||
#include <assert.h>
|
||||
#include "./aom_config.h"
|
||||
#if CONFIG_EC_ADAPT && !CONFIG_EC_MULTISYMBOL
|
||||
#error "CONFIG_EC_ADAPT is enabled without enabling CONFIG_EC_MULTISYMBOL"
|
||||
#endif
|
||||
|
||||
#if CONFIG_ANS
|
||||
#include "aom_dsp/buf_ans.h"
|
||||
#elif CONFIG_DAALA_EC
|
||||
#include "aom_dsp/daalaboolwriter.h"
|
||||
#else
|
||||
#include "aom_dsp/dkboolwriter.h"
|
||||
#endif
|
||||
#include "aom_dsp/prob.h"
|
||||
|
||||
#if CONFIG_RD_DEBUG
|
||||
#include "av1/common/blockd.h"
|
||||
#include "av1/encoder/cost.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if CONFIG_ANS
|
||||
typedef struct BufAnsCoder aom_writer;
|
||||
#elif CONFIG_DAALA_EC
|
||||
typedef struct daala_writer aom_writer;
|
||||
#else
|
||||
typedef struct aom_dk_writer aom_writer;
|
||||
#endif
|
||||
|
||||
typedef struct TOKEN_STATS {
|
||||
int cost;
|
||||
#if CONFIG_VAR_TX
|
||||
#if CONFIG_RD_DEBUG
|
||||
int txb_coeff_cost_map[TXB_COEFF_COST_MAP_SIZE][TXB_COEFF_COST_MAP_SIZE];
|
||||
#endif
|
||||
#endif
|
||||
} TOKEN_STATS;
|
||||
|
||||
static INLINE void init_token_stats(TOKEN_STATS *token_stats) {
|
||||
#if CONFIG_VAR_TX
|
||||
#if CONFIG_RD_DEBUG
|
||||
int r, c;
|
||||
for (r = 0; r < TXB_COEFF_COST_MAP_SIZE; ++r) {
|
||||
for (c = 0; c < TXB_COEFF_COST_MAP_SIZE; ++c) {
|
||||
token_stats->txb_coeff_cost_map[r][c] = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
token_stats->cost = 0;
|
||||
}
|
||||
|
||||
static INLINE void aom_start_encode(aom_writer *bc, uint8_t *buffer) {
|
||||
#if CONFIG_ANS
|
||||
(void)bc;
|
||||
(void)buffer;
|
||||
assert(0 && "buf_ans requires a more complicated startup procedure");
|
||||
#elif CONFIG_DAALA_EC
|
||||
aom_daala_start_encode(bc, buffer);
|
||||
#else
|
||||
aom_dk_start_encode(bc, buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
static INLINE void aom_stop_encode(aom_writer *bc) {
|
||||
#if CONFIG_ANS
|
||||
(void)bc;
|
||||
assert(0 && "buf_ans requires a more complicated shutdown procedure");
|
||||
#elif CONFIG_DAALA_EC
|
||||
aom_daala_stop_encode(bc);
|
||||
#else
|
||||
aom_dk_stop_encode(bc);
|
||||
#endif
|
||||
}
|
||||
|
||||
static INLINE void aom_write(aom_writer *br, int bit, int probability) {
|
||||
#if CONFIG_ANS
|
||||
buf_rabs_write(br, bit, probability);
|
||||
#elif CONFIG_DAALA_EC
|
||||
aom_daala_write(br, bit, probability);
|
||||
#else
|
||||
aom_dk_write(br, bit, probability);
|
||||
#endif
|
||||
}
|
||||
|
||||
static INLINE void aom_write_record(aom_writer *br, int bit, int probability,
|
||||
TOKEN_STATS *token_stats) {
|
||||
aom_write(br, bit, probability);
|
||||
#if CONFIG_RD_DEBUG
|
||||
token_stats->cost += av1_cost_bit(probability, bit);
|
||||
#else
|
||||
(void)token_stats;
|
||||
#endif
|
||||
}
|
||||
|
||||
static INLINE void aom_write_bit(aom_writer *w, int bit) {
|
||||
#if CONFIG_ANS
|
||||
buf_rabs_write_bit(w, bit);
|
||||
#elif CONFIG_DAALA_EC && CONFIG_RAWBITS
|
||||
// Note this uses raw bits and is not the same as aom_daala_write(r, 128);
|
||||
aom_daala_write_bit(w, bit);
|
||||
#else
|
||||
aom_write(w, bit, 128); // aom_prob_half
|
||||
#endif
|
||||
}
|
||||
|
||||
static INLINE void aom_write_bit_record(aom_writer *w, int bit,
|
||||
TOKEN_STATS *token_stats) {
|
||||
aom_write_bit(w, bit);
|
||||
#if CONFIG_RD_DEBUG
|
||||
token_stats->cost += av1_cost_bit(128, bit); // aom_prob_half
|
||||
#else
|
||||
(void)token_stats;
|
||||
#endif
|
||||
}
|
||||
|
||||
static INLINE void aom_write_literal(aom_writer *w, int data, int bits) {
|
||||
int bit;
|
||||
|
||||
for (bit = bits - 1; bit >= 0; bit--) aom_write_bit(w, 1 & (data >> bit));
|
||||
}
|
||||
|
||||
static INLINE void aom_write_tree_as_bits(aom_writer *w,
|
||||
const aom_tree_index *tr,
|
||||
const aom_prob *probs, int bits,
|
||||
int len, aom_tree_index i) {
|
||||
do {
|
||||
const int bit = (bits >> --len) & 1;
|
||||
aom_write(w, bit, probs[i >> 1]);
|
||||
i = tr[i + bit];
|
||||
} while (len);
|
||||
}
|
||||
|
||||
static INLINE void aom_write_tree_as_bits_record(
|
||||
aom_writer *w, const aom_tree_index *tr, const aom_prob *probs, int bits,
|
||||
int len, aom_tree_index i, TOKEN_STATS *token_stats) {
|
||||
do {
|
||||
const int bit = (bits >> --len) & 1;
|
||||
aom_write_record(w, bit, probs[i >> 1], token_stats);
|
||||
i = tr[i + bit];
|
||||
} while (len);
|
||||
}
|
||||
|
||||
#if CONFIG_EC_MULTISYMBOL
|
||||
static INLINE void aom_write_cdf(aom_writer *w, int symb,
|
||||
const aom_cdf_prob *cdf, int nsymbs) {
|
||||
#if CONFIG_ANS
|
||||
(void)nsymbs;
|
||||
assert(cdf);
|
||||
const aom_cdf_prob cum_prob = symb > 0 ? cdf[symb - 1] : 0;
|
||||
const aom_cdf_prob prob = cdf[symb] - cum_prob;
|
||||
buf_rans_write(w, cum_prob, prob);
|
||||
#elif CONFIG_DAALA_EC
|
||||
daala_write_symbol(w, symb, cdf, nsymbs);
|
||||
#else
|
||||
#error \
|
||||
"CONFIG_EC_MULTISYMBOL is selected without a valid backing entropy " \
|
||||
"coder. Enable daala_ec or ans for a valid configuration."
|
||||
#endif
|
||||
}
|
||||
|
||||
static INLINE void aom_write_symbol(aom_writer *w, int symb, aom_cdf_prob *cdf,
|
||||
int nsymbs) {
|
||||
aom_write_cdf(w, symb, cdf, nsymbs);
|
||||
#if CONFIG_EC_ADAPT
|
||||
update_cdf(cdf, symb, nsymbs);
|
||||
#endif
|
||||
}
|
||||
|
||||
static INLINE void aom_write_tree_as_cdf(aom_writer *w,
|
||||
const aom_tree_index *tree,
|
||||
const aom_prob *probs, int bits,
|
||||
int len, aom_tree_index i) {
|
||||
aom_tree_index root;
|
||||
root = i;
|
||||
do {
|
||||
aom_cdf_prob cdf[16];
|
||||
aom_tree_index index[16];
|
||||
int path[16];
|
||||
int dist[16];
|
||||
int nsymbs;
|
||||
int symb;
|
||||
int j;
|
||||
/* Compute the CDF of the binary tree using the given probabilities. */
|
||||
nsymbs = tree_to_cdf(tree, probs, root, cdf, index, path, dist);
|
||||
/* Find the symbol to code. */
|
||||
symb = -1;
|
||||
for (j = 0; j < nsymbs; j++) {
|
||||
/* If this symbol codes a leaf node, */
|
||||
if (index[j] <= 0) {
|
||||
if (len == dist[j] && path[j] == bits) {
|
||||
symb = j;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (len > dist[j] && path[j] == bits >> (len - dist[j])) {
|
||||
symb = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
OD_ASSERT(symb != -1);
|
||||
aom_write_cdf(w, symb, cdf, nsymbs);
|
||||
bits &= (1 << (len - dist[symb])) - 1;
|
||||
len -= dist[symb];
|
||||
} while (len);
|
||||
}
|
||||
|
||||
#endif // CONFIG_EC_MULTISYMBOL
|
||||
|
||||
static INLINE void aom_write_tree(aom_writer *w, const aom_tree_index *tree,
|
||||
const aom_prob *probs, int bits, int len,
|
||||
aom_tree_index i) {
|
||||
#if CONFIG_EC_MULTISYMBOL
|
||||
aom_write_tree_as_cdf(w, tree, probs, bits, len, i);
|
||||
#else
|
||||
aom_write_tree_as_bits(w, tree, probs, bits, len, i);
|
||||
#endif
|
||||
}
|
||||
|
||||
static INLINE void aom_write_tree_record(aom_writer *w,
|
||||
const aom_tree_index *tree,
|
||||
const aom_prob *probs, int bits,
|
||||
int len, aom_tree_index i,
|
||||
TOKEN_STATS *token_stats) {
|
||||
#if CONFIG_EC_MULTISYMBOL
|
||||
(void)token_stats;
|
||||
aom_write_tree_as_cdf(w, tree, probs, bits, len, i);
|
||||
#else
|
||||
aom_write_tree_as_bits_record(w, tree, probs, bits, len, i, token_stats);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // AOM_DSP_BITWRITER_H_
|
||||
61
third_party/aom/aom_dsp/bitwriter_buffer.c
vendored
Normal file
61
third_party/aom/aom_dsp/bitwriter_buffer.c
vendored
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "./aom_config.h"
|
||||
#include "./bitwriter_buffer.h"
|
||||
|
||||
uint32_t aom_wb_bytes_written(const struct aom_write_bit_buffer *wb) {
|
||||
return wb->bit_offset / CHAR_BIT + (wb->bit_offset % CHAR_BIT > 0);
|
||||
}
|
||||
|
||||
void aom_wb_write_bit(struct aom_write_bit_buffer *wb, int bit) {
|
||||
const int off = (int)wb->bit_offset;
|
||||
const int p = off / CHAR_BIT;
|
||||
const int q = CHAR_BIT - 1 - off % CHAR_BIT;
|
||||
if (q == CHAR_BIT - 1) {
|
||||
// Zero next char and write bit
|
||||
wb->bit_buffer[p] = bit << q;
|
||||
} else {
|
||||
wb->bit_buffer[p] &= ~(1 << q);
|
||||
wb->bit_buffer[p] |= bit << q;
|
||||
}
|
||||
wb->bit_offset = off + 1;
|
||||
}
|
||||
|
||||
void aom_wb_overwrite_bit(struct aom_write_bit_buffer *wb, int bit) {
|
||||
// Do not zero bytes but overwrite exisiting values
|
||||
const int off = (int)wb->bit_offset;
|
||||
const int p = off / CHAR_BIT;
|
||||
const int q = CHAR_BIT - 1 - off % CHAR_BIT;
|
||||
wb->bit_buffer[p] &= ~(1 << q);
|
||||
wb->bit_buffer[p] |= bit << q;
|
||||
wb->bit_offset = off + 1;
|
||||
}
|
||||
|
||||
void aom_wb_write_literal(struct aom_write_bit_buffer *wb, int data, int bits) {
|
||||
int bit;
|
||||
for (bit = bits - 1; bit >= 0; bit--) aom_wb_write_bit(wb, (data >> bit) & 1);
|
||||
}
|
||||
|
||||
void aom_wb_overwrite_literal(struct aom_write_bit_buffer *wb, int data,
|
||||
int bits) {
|
||||
int bit;
|
||||
for (bit = bits - 1; bit >= 0; bit--)
|
||||
aom_wb_overwrite_bit(wb, (data >> bit) & 1);
|
||||
}
|
||||
|
||||
void aom_wb_write_inv_signed_literal(struct aom_write_bit_buffer *wb, int data,
|
||||
int bits) {
|
||||
aom_wb_write_literal(wb, data, bits + 1);
|
||||
}
|
||||
44
third_party/aom/aom_dsp/bitwriter_buffer.h
vendored
Normal file
44
third_party/aom/aom_dsp/bitwriter_buffer.h
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#ifndef AOM_DSP_BITWRITER_BUFFER_H_
|
||||
#define AOM_DSP_BITWRITER_BUFFER_H_
|
||||
|
||||
#include "aom/aom_integer.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct aom_write_bit_buffer {
|
||||
uint8_t *bit_buffer;
|
||||
uint32_t bit_offset;
|
||||
};
|
||||
|
||||
uint32_t aom_wb_bytes_written(const struct aom_write_bit_buffer *wb);
|
||||
|
||||
void aom_wb_write_bit(struct aom_write_bit_buffer *wb, int bit);
|
||||
|
||||
void aom_wb_overwrite_bit(struct aom_write_bit_buffer *wb, int bit);
|
||||
|
||||
void aom_wb_write_literal(struct aom_write_bit_buffer *wb, int data, int bits);
|
||||
|
||||
void aom_wb_overwrite_literal(struct aom_write_bit_buffer *wb, int data,
|
||||
int bits);
|
||||
|
||||
void aom_wb_write_inv_signed_literal(struct aom_write_bit_buffer *wb, int data,
|
||||
int bits);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // AOM_DSP_BITWRITER_BUFFER_H_
|
||||
42
third_party/aom/aom_dsp/blend.h
vendored
Normal file
42
third_party/aom/aom_dsp/blend.h
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#ifndef AOM_DSP_BLEND_H_
|
||||
#define AOM_DSP_BLEND_H_
|
||||
|
||||
#include "aom_ports/mem.h"
|
||||
|
||||
// Various blending functions and macros.
|
||||
// See also the aom_blend_* functions in aom_dsp_rtcd.h
|
||||
|
||||
// Alpha blending with alpha values from the range [0, 64], where 64
|
||||
// means use the first input and 0 means use the second input.
|
||||
|
||||
#define AOM_BLEND_A64_ROUND_BITS 6
|
||||
#define AOM_BLEND_A64_MAX_ALPHA (1 << AOM_BLEND_A64_ROUND_BITS) // 64
|
||||
|
||||
#define AOM_BLEND_A64(a, v0, v1) \
|
||||
ROUND_POWER_OF_TWO((a) * (v0) + (AOM_BLEND_A64_MAX_ALPHA - (a)) * (v1), \
|
||||
AOM_BLEND_A64_ROUND_BITS)
|
||||
|
||||
// Alpha blending with alpha values from the range [0, 256], where 256
|
||||
// means use the first input and 0 means use the second input.
|
||||
#define AOM_BLEND_A256_ROUND_BITS 8
|
||||
#define AOM_BLEND_A256_MAX_ALPHA (1 << AOM_BLEND_A256_ROUND_BITS) // 256
|
||||
|
||||
#define AOM_BLEND_A256(a, v0, v1) \
|
||||
ROUND_POWER_OF_TWO((a) * (v0) + (AOM_BLEND_A256_MAX_ALPHA - (a)) * (v1), \
|
||||
AOM_BLEND_A256_ROUND_BITS)
|
||||
|
||||
// Blending by averaging.
|
||||
#define AOM_BLEND_AVG(v0, v1) ROUND_POWER_OF_TWO((v0) + (v1), 1)
|
||||
|
||||
#endif // AOM_DSP_BLEND_H_
|
||||
71
third_party/aom/aom_dsp/blend_a64_hmask.c
vendored
Normal file
71
third_party/aom/aom_dsp/blend_a64_hmask.c
vendored
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "aom/aom_integer.h"
|
||||
#include "aom_ports/mem.h"
|
||||
#include "aom_dsp/aom_dsp_common.h"
|
||||
#include "aom_dsp/blend.h"
|
||||
|
||||
#include "./aom_dsp_rtcd.h"
|
||||
|
||||
void aom_blend_a64_hmask_c(uint8_t *dst, uint32_t dst_stride,
|
||||
const uint8_t *src0, uint32_t src0_stride,
|
||||
const uint8_t *src1, uint32_t src1_stride,
|
||||
const uint8_t *mask, int h, int w) {
|
||||
int i, j;
|
||||
|
||||
assert(IMPLIES(src0 == dst, src0_stride == dst_stride));
|
||||
assert(IMPLIES(src1 == dst, src1_stride == dst_stride));
|
||||
|
||||
assert(h >= 1);
|
||||
assert(w >= 1);
|
||||
assert(IS_POWER_OF_TWO(h));
|
||||
assert(IS_POWER_OF_TWO(w));
|
||||
|
||||
for (i = 0; i < h; ++i) {
|
||||
for (j = 0; j < w; ++j) {
|
||||
dst[i * dst_stride + j] = AOM_BLEND_A64(
|
||||
mask[j], src0[i * src0_stride + j], src1[i * src1_stride + j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_HIGHBITDEPTH
|
||||
void aom_highbd_blend_a64_hmask_c(uint8_t *dst_8, uint32_t dst_stride,
|
||||
const uint8_t *src0_8, uint32_t src0_stride,
|
||||
const uint8_t *src1_8, uint32_t src1_stride,
|
||||
const uint8_t *mask, int h, int w, int bd) {
|
||||
int i, j;
|
||||
uint16_t *dst = CONVERT_TO_SHORTPTR(dst_8);
|
||||
const uint16_t *src0 = CONVERT_TO_SHORTPTR(src0_8);
|
||||
const uint16_t *src1 = CONVERT_TO_SHORTPTR(src1_8);
|
||||
(void)bd;
|
||||
|
||||
assert(IMPLIES(src0 == dst, src0_stride == dst_stride));
|
||||
assert(IMPLIES(src1 == dst, src1_stride == dst_stride));
|
||||
|
||||
assert(h >= 1);
|
||||
assert(w >= 1);
|
||||
assert(IS_POWER_OF_TWO(h));
|
||||
assert(IS_POWER_OF_TWO(w));
|
||||
|
||||
assert(bd == 8 || bd == 10 || bd == 12);
|
||||
|
||||
for (i = 0; i < h; ++i) {
|
||||
for (j = 0; j < w; ++j) {
|
||||
dst[i * dst_stride + j] = AOM_BLEND_A64(
|
||||
mask[j], src0[i * src0_stride + j], src1[i * src1_stride + j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // CONFIG_HIGHBITDEPTH
|
||||
145
third_party/aom/aom_dsp/blend_a64_mask.c
vendored
Normal file
145
third_party/aom/aom_dsp/blend_a64_mask.c
vendored
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "aom/aom_integer.h"
|
||||
#include "aom_ports/mem.h"
|
||||
#include "aom_dsp/blend.h"
|
||||
#include "aom_dsp/aom_dsp_common.h"
|
||||
|
||||
#include "./aom_dsp_rtcd.h"
|
||||
|
||||
// Blending with alpha mask. Mask values come from the range [0, 64],
|
||||
// as described for AOM_BLEND_A64 in aom_dsp/blend.h. src0 or src1 can
|
||||
// be the same as dst, or dst can be different from both sources.
|
||||
|
||||
void aom_blend_a64_mask_c(uint8_t *dst, uint32_t dst_stride,
|
||||
const uint8_t *src0, uint32_t src0_stride,
|
||||
const uint8_t *src1, uint32_t src1_stride,
|
||||
const uint8_t *mask, uint32_t mask_stride, int h,
|
||||
int w, int subh, int subw) {
|
||||
int i, j;
|
||||
|
||||
assert(IMPLIES(src0 == dst, src0_stride == dst_stride));
|
||||
assert(IMPLIES(src1 == dst, src1_stride == dst_stride));
|
||||
|
||||
assert(h >= 1);
|
||||
assert(w >= 1);
|
||||
assert(IS_POWER_OF_TWO(h));
|
||||
assert(IS_POWER_OF_TWO(w));
|
||||
|
||||
if (subw == 0 && subh == 0) {
|
||||
for (i = 0; i < h; ++i) {
|
||||
for (j = 0; j < w; ++j) {
|
||||
const int m = mask[i * mask_stride + j];
|
||||
dst[i * dst_stride + j] = AOM_BLEND_A64(m, src0[i * src0_stride + j],
|
||||
src1[i * src1_stride + j]);
|
||||
}
|
||||
}
|
||||
} else if (subw == 1 && subh == 1) {
|
||||
for (i = 0; i < h; ++i) {
|
||||
for (j = 0; j < w; ++j) {
|
||||
const int m = ROUND_POWER_OF_TWO(
|
||||
mask[(2 * i) * mask_stride + (2 * j)] +
|
||||
mask[(2 * i + 1) * mask_stride + (2 * j)] +
|
||||
mask[(2 * i) * mask_stride + (2 * j + 1)] +
|
||||
mask[(2 * i + 1) * mask_stride + (2 * j + 1)],
|
||||
2);
|
||||
dst[i * dst_stride + j] = AOM_BLEND_A64(m, src0[i * src0_stride + j],
|
||||
src1[i * src1_stride + j]);
|
||||
}
|
||||
}
|
||||
} else if (subw == 1 && subh == 0) {
|
||||
for (i = 0; i < h; ++i) {
|
||||
for (j = 0; j < w; ++j) {
|
||||
const int m = AOM_BLEND_AVG(mask[i * mask_stride + (2 * j)],
|
||||
mask[i * mask_stride + (2 * j + 1)]);
|
||||
dst[i * dst_stride + j] = AOM_BLEND_A64(m, src0[i * src0_stride + j],
|
||||
src1[i * src1_stride + j]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < h; ++i) {
|
||||
for (j = 0; j < w; ++j) {
|
||||
const int m = AOM_BLEND_AVG(mask[(2 * i) * mask_stride + j],
|
||||
mask[(2 * i + 1) * mask_stride + j]);
|
||||
dst[i * dst_stride + j] = AOM_BLEND_A64(m, src0[i * src0_stride + j],
|
||||
src1[i * src1_stride + j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_HIGHBITDEPTH
|
||||
void aom_highbd_blend_a64_mask_c(uint8_t *dst_8, uint32_t dst_stride,
|
||||
const uint8_t *src0_8, uint32_t src0_stride,
|
||||
const uint8_t *src1_8, uint32_t src1_stride,
|
||||
const uint8_t *mask, uint32_t mask_stride,
|
||||
int h, int w, int subh, int subw, int bd) {
|
||||
int i, j;
|
||||
uint16_t *dst = CONVERT_TO_SHORTPTR(dst_8);
|
||||
const uint16_t *src0 = CONVERT_TO_SHORTPTR(src0_8);
|
||||
const uint16_t *src1 = CONVERT_TO_SHORTPTR(src1_8);
|
||||
(void)bd;
|
||||
|
||||
assert(IMPLIES(src0 == dst, src0_stride == dst_stride));
|
||||
assert(IMPLIES(src1 == dst, src1_stride == dst_stride));
|
||||
|
||||
assert(h >= 1);
|
||||
assert(w >= 1);
|
||||
assert(IS_POWER_OF_TWO(h));
|
||||
assert(IS_POWER_OF_TWO(w));
|
||||
|
||||
assert(bd == 8 || bd == 10 || bd == 12);
|
||||
|
||||
if (subw == 0 && subh == 0) {
|
||||
for (i = 0; i < h; ++i) {
|
||||
for (j = 0; j < w; ++j) {
|
||||
const int m = mask[i * mask_stride + j];
|
||||
dst[i * dst_stride + j] = AOM_BLEND_A64(m, src0[i * src0_stride + j],
|
||||
src1[i * src1_stride + j]);
|
||||
}
|
||||
}
|
||||
} else if (subw == 1 && subh == 1) {
|
||||
for (i = 0; i < h; ++i) {
|
||||
for (j = 0; j < w; ++j) {
|
||||
const int m = ROUND_POWER_OF_TWO(
|
||||
mask[(2 * i) * mask_stride + (2 * j)] +
|
||||
mask[(2 * i + 1) * mask_stride + (2 * j)] +
|
||||
mask[(2 * i) * mask_stride + (2 * j + 1)] +
|
||||
mask[(2 * i + 1) * mask_stride + (2 * j + 1)],
|
||||
2);
|
||||
dst[i * dst_stride + j] = AOM_BLEND_A64(m, src0[i * src0_stride + j],
|
||||
src1[i * src1_stride + j]);
|
||||
}
|
||||
}
|
||||
} else if (subw == 1 && subh == 0) {
|
||||
for (i = 0; i < h; ++i) {
|
||||
for (j = 0; j < w; ++j) {
|
||||
const int m = AOM_BLEND_AVG(mask[i * mask_stride + (2 * j)],
|
||||
mask[i * mask_stride + (2 * j + 1)]);
|
||||
dst[i * dst_stride + j] = AOM_BLEND_A64(m, src0[i * src0_stride + j],
|
||||
src1[i * src1_stride + j]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < h; ++i) {
|
||||
for (j = 0; j < w; ++j) {
|
||||
const int m = AOM_BLEND_AVG(mask[(2 * i) * mask_stride + j],
|
||||
mask[(2 * i + 1) * mask_stride + j]);
|
||||
dst[i * dst_stride + j] = AOM_BLEND_A64(m, src0[i * src0_stride + j],
|
||||
src1[i * src1_stride + j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // CONFIG_HIGHBITDEPTH
|
||||
73
third_party/aom/aom_dsp/blend_a64_vmask.c
vendored
Normal file
73
third_party/aom/aom_dsp/blend_a64_vmask.c
vendored
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "aom/aom_integer.h"
|
||||
#include "aom_ports/mem.h"
|
||||
#include "aom_dsp/aom_dsp_common.h"
|
||||
#include "aom_dsp/blend.h"
|
||||
|
||||
#include "./aom_dsp_rtcd.h"
|
||||
|
||||
void aom_blend_a64_vmask_c(uint8_t *dst, uint32_t dst_stride,
|
||||
const uint8_t *src0, uint32_t src0_stride,
|
||||
const uint8_t *src1, uint32_t src1_stride,
|
||||
const uint8_t *mask, int h, int w) {
|
||||
int i, j;
|
||||
|
||||
assert(IMPLIES(src0 == dst, src0_stride == dst_stride));
|
||||
assert(IMPLIES(src1 == dst, src1_stride == dst_stride));
|
||||
|
||||
assert(h >= 1);
|
||||
assert(w >= 1);
|
||||
assert(IS_POWER_OF_TWO(h));
|
||||
assert(IS_POWER_OF_TWO(w));
|
||||
|
||||
for (i = 0; i < h; ++i) {
|
||||
const int m = mask[i];
|
||||
for (j = 0; j < w; ++j) {
|
||||
dst[i * dst_stride + j] = AOM_BLEND_A64(m, src0[i * src0_stride + j],
|
||||
src1[i * src1_stride + j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_HIGHBITDEPTH
|
||||
void aom_highbd_blend_a64_vmask_c(uint8_t *dst_8, uint32_t dst_stride,
|
||||
const uint8_t *src0_8, uint32_t src0_stride,
|
||||
const uint8_t *src1_8, uint32_t src1_stride,
|
||||
const uint8_t *mask, int h, int w, int bd) {
|
||||
int i, j;
|
||||
uint16_t *dst = CONVERT_TO_SHORTPTR(dst_8);
|
||||
const uint16_t *src0 = CONVERT_TO_SHORTPTR(src0_8);
|
||||
const uint16_t *src1 = CONVERT_TO_SHORTPTR(src1_8);
|
||||
(void)bd;
|
||||
|
||||
assert(IMPLIES(src0 == dst, src0_stride == dst_stride));
|
||||
assert(IMPLIES(src1 == dst, src1_stride == dst_stride));
|
||||
|
||||
assert(h >= 1);
|
||||
assert(w >= 1);
|
||||
assert(IS_POWER_OF_TWO(h));
|
||||
assert(IS_POWER_OF_TWO(w));
|
||||
|
||||
assert(bd == 8 || bd == 10 || bd == 12);
|
||||
|
||||
for (i = 0; i < h; ++i) {
|
||||
const int m = mask[i];
|
||||
for (j = 0; j < w; ++j) {
|
||||
dst[i * dst_stride + j] = AOM_BLEND_A64(m, src0[i * src0_stride + j],
|
||||
src1[i * src1_stride + j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // CONFIG_HIGHBITDEPTH
|
||||
71
third_party/aom/aom_dsp/buf_ans.c
vendored
Normal file
71
third_party/aom/aom_dsp/buf_ans.c
vendored
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "aom_dsp/buf_ans.h"
|
||||
#include "aom_mem/aom_mem.h"
|
||||
#include "aom/internal/aom_codec_internal.h"
|
||||
|
||||
void aom_buf_ans_alloc(struct BufAnsCoder *c,
|
||||
struct aom_internal_error_info *error, int size) {
|
||||
c->error = error;
|
||||
c->size = size;
|
||||
assert(c->size > 1);
|
||||
AOM_CHECK_MEM_ERROR(error, c->buf, aom_malloc(c->size * sizeof(*c->buf)));
|
||||
// Initialize to overfull to trigger the assert in write.
|
||||
c->offset = c->size + 1;
|
||||
}
|
||||
|
||||
void aom_buf_ans_free(struct BufAnsCoder *c) {
|
||||
aom_free(c->buf);
|
||||
c->buf = NULL;
|
||||
c->size = 0;
|
||||
}
|
||||
|
||||
#if !ANS_MAX_SYMBOLS
|
||||
void aom_buf_ans_grow(struct BufAnsCoder *c) {
|
||||
struct buffered_ans_symbol *new_buf = NULL;
|
||||
int new_size = c->size * 2;
|
||||
AOM_CHECK_MEM_ERROR(c->error, new_buf,
|
||||
aom_malloc(new_size * sizeof(*new_buf)));
|
||||
memcpy(new_buf, c->buf, c->size * sizeof(*c->buf));
|
||||
aom_free(c->buf);
|
||||
c->buf = new_buf;
|
||||
c->size = new_size;
|
||||
}
|
||||
#endif
|
||||
|
||||
void aom_buf_ans_flush(struct BufAnsCoder *const c) {
|
||||
int offset;
|
||||
#if ANS_MAX_SYMBOLS
|
||||
if (c->offset == 0) return;
|
||||
#endif
|
||||
assert(c->offset > 0);
|
||||
offset = c->offset - 1;
|
||||
// Code the first symbol such that it brings the state to the smallest normal
|
||||
// state from an initial state that would have been a subnormal/refill state.
|
||||
if (c->buf[offset].method == ANS_METHOD_RANS) {
|
||||
c->ans.state += c->buf[offset].val_start;
|
||||
} else {
|
||||
c->ans.state += c->buf[offset].val_start ? c->buf[offset].prob : 0;
|
||||
}
|
||||
for (offset = offset - 1; offset >= 0; --offset) {
|
||||
if (c->buf[offset].method == ANS_METHOD_RANS) {
|
||||
rans_write(&c->ans, c->buf[offset].val_start, c->buf[offset].prob);
|
||||
} else {
|
||||
rabs_write(&c->ans, (uint8_t)c->buf[offset].val_start,
|
||||
(AnsP8)c->buf[offset].prob);
|
||||
}
|
||||
}
|
||||
c->offset = 0;
|
||||
c->output_bytes += ans_write_end(&c->ans);
|
||||
}
|
||||
133
third_party/aom/aom_dsp/buf_ans.h
vendored
Normal file
133
third_party/aom/aom_dsp/buf_ans.h
vendored
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#ifndef AOM_DSP_BUF_ANS_H_
|
||||
#define AOM_DSP_BUF_ANS_H_
|
||||
// Buffered forward ANS writer.
|
||||
// Symbols are written to the writer in forward (decode) order and serialized
|
||||
// backwards due to ANS's stack like behavior.
|
||||
|
||||
#include <assert.h>
|
||||
#include "./aom_config.h"
|
||||
#include "aom/aom_integer.h"
|
||||
#include "aom_dsp/ans.h"
|
||||
#include "aom_dsp/answriter.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
#define ANS_METHOD_RABS 0
|
||||
#define ANS_METHOD_RANS 1
|
||||
|
||||
struct buffered_ans_symbol {
|
||||
unsigned int method : 1; // one of ANS_METHOD_RABS or ANS_METHOD_RANS
|
||||
// TODO(aconverse): Should be possible to write this in terms of start for ABS
|
||||
unsigned int val_start : RANS_PROB_BITS; // Boolean value for ABS
|
||||
// start in symbol cycle for Rans
|
||||
unsigned int prob : RANS_PROB_BITS; // Probability of this symbol
|
||||
};
|
||||
|
||||
struct BufAnsCoder {
|
||||
struct aom_internal_error_info *error;
|
||||
struct buffered_ans_symbol *buf;
|
||||
struct AnsCoder ans;
|
||||
int size;
|
||||
int offset;
|
||||
int output_bytes;
|
||||
#if ANS_MAX_SYMBOLS
|
||||
int window_size;
|
||||
#endif
|
||||
};
|
||||
|
||||
// Allocate a buffered ANS coder to store size symbols.
|
||||
// When ANS_MAX_SYMBOLS is turned on, the size is the fixed size of each ANS
|
||||
// partition.
|
||||
// When ANS_MAX_SYMBOLS is turned off, size is merely an initial hint and the
|
||||
// buffer will grow on demand
|
||||
void aom_buf_ans_alloc(struct BufAnsCoder *c,
|
||||
struct aom_internal_error_info *error, int hint);
|
||||
|
||||
void aom_buf_ans_free(struct BufAnsCoder *c);
|
||||
|
||||
#if !ANS_MAX_SYMBOLS
|
||||
void aom_buf_ans_grow(struct BufAnsCoder *c);
|
||||
#endif
|
||||
|
||||
void aom_buf_ans_flush(struct BufAnsCoder *const c);
|
||||
|
||||
static INLINE void buf_ans_write_init(struct BufAnsCoder *const c,
|
||||
uint8_t *const output_buffer) {
|
||||
c->offset = 0;
|
||||
c->output_bytes = 0;
|
||||
ans_write_init(&c->ans, output_buffer);
|
||||
}
|
||||
|
||||
static INLINE void buf_rabs_write(struct BufAnsCoder *const c, uint8_t val,
|
||||
AnsP8 prob) {
|
||||
assert(c->offset <= c->size);
|
||||
#if !ANS_MAX_SYMBOLS
|
||||
if (c->offset == c->size) {
|
||||
aom_buf_ans_grow(c);
|
||||
}
|
||||
#endif
|
||||
c->buf[c->offset].method = ANS_METHOD_RABS;
|
||||
c->buf[c->offset].val_start = val;
|
||||
c->buf[c->offset].prob = prob;
|
||||
++c->offset;
|
||||
#if ANS_MAX_SYMBOLS
|
||||
if (c->offset == c->size) aom_buf_ans_flush(c);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Buffer one symbol for encoding using rANS.
|
||||
// cum_prob: The cumulative probability before this symbol (the offset of
|
||||
// the symbol in the symbol cycle)
|
||||
// prob: The probability of this symbol (l_s from the paper)
|
||||
// RANS_PRECISION takes the place of m from the paper.
|
||||
static INLINE void buf_rans_write(struct BufAnsCoder *const c,
|
||||
aom_cdf_prob cum_prob, aom_cdf_prob prob) {
|
||||
assert(c->offset <= c->size);
|
||||
#if !ANS_MAX_SYMBOLS
|
||||
if (c->offset == c->size) {
|
||||
aom_buf_ans_grow(c);
|
||||
}
|
||||
#endif
|
||||
c->buf[c->offset].method = ANS_METHOD_RANS;
|
||||
c->buf[c->offset].val_start = cum_prob;
|
||||
c->buf[c->offset].prob = prob;
|
||||
++c->offset;
|
||||
#if ANS_MAX_SYMBOLS
|
||||
if (c->offset == c->size) aom_buf_ans_flush(c);
|
||||
#endif
|
||||
}
|
||||
|
||||
static INLINE void buf_rabs_write_bit(struct BufAnsCoder *c, int bit) {
|
||||
buf_rabs_write(c, bit, 128);
|
||||
}
|
||||
|
||||
static INLINE void buf_rabs_write_literal(struct BufAnsCoder *c, int literal,
|
||||
int bits) {
|
||||
int bit;
|
||||
|
||||
assert(bits < 31);
|
||||
for (bit = bits - 1; bit >= 0; bit--)
|
||||
buf_rabs_write_bit(c, 1 & (literal >> bit));
|
||||
}
|
||||
|
||||
static INLINE int buf_ans_write_end(struct BufAnsCoder *const c) {
|
||||
assert(c->offset == 0);
|
||||
return c->output_bytes;
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
#endif // AOM_DSP_BUF_ANS_H_
|
||||
37
third_party/aom/aom_dsp/daalaboolreader.c
vendored
Normal file
37
third_party/aom/aom_dsp/daalaboolreader.c
vendored
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include "aom_dsp/daalaboolreader.h"
|
||||
|
||||
int aom_daala_reader_init(daala_reader *r, const uint8_t *buffer, int size) {
|
||||
if (size && !buffer) {
|
||||
return 1;
|
||||
}
|
||||
r->buffer_end = buffer + size;
|
||||
r->buffer = buffer;
|
||||
od_ec_dec_init(&r->ec, buffer, size - 1);
|
||||
#if CONFIG_ACCOUNTING
|
||||
r->accounting = NULL;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint8_t *aom_daala_reader_find_end(daala_reader *r) {
|
||||
return r->buffer_end;
|
||||
}
|
||||
|
||||
uint32_t aom_daala_reader_tell(const daala_reader *r) {
|
||||
return od_ec_dec_tell(&r->ec);
|
||||
}
|
||||
|
||||
uint32_t aom_daala_reader_tell_frac(const daala_reader *r) {
|
||||
return od_ec_dec_tell_frac(&r->ec);
|
||||
}
|
||||
164
third_party/aom/aom_dsp/daalaboolreader.h
vendored
Normal file
164
third_party/aom/aom_dsp/daalaboolreader.h
vendored
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#ifndef AOM_DSP_DAALABOOLREADER_H_
|
||||
#define AOM_DSP_DAALABOOLREADER_H_
|
||||
|
||||
#include "aom/aom_integer.h"
|
||||
#include "aom_dsp/entdec.h"
|
||||
#include "aom_dsp/prob.h"
|
||||
#if CONFIG_ACCOUNTING
|
||||
#include "av1/decoder/accounting.h"
|
||||
#endif
|
||||
#if CONFIG_BITSTREAM_DEBUG
|
||||
#include <stdio.h>
|
||||
#include "aom_util/debug_util.h"
|
||||
#endif // CONFIG_BITSTREAM_DEBUG
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct daala_reader {
|
||||
const uint8_t *buffer;
|
||||
const uint8_t *buffer_end;
|
||||
od_ec_dec ec;
|
||||
#if CONFIG_ACCOUNTING
|
||||
Accounting *accounting;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct daala_reader daala_reader;
|
||||
|
||||
int aom_daala_reader_init(daala_reader *r, const uint8_t *buffer, int size);
|
||||
const uint8_t *aom_daala_reader_find_end(daala_reader *r);
|
||||
uint32_t aom_daala_reader_tell(const daala_reader *r);
|
||||
uint32_t aom_daala_reader_tell_frac(const daala_reader *r);
|
||||
|
||||
static INLINE int aom_daala_read(daala_reader *r, int prob) {
|
||||
int bit;
|
||||
#if CONFIG_EC_SMALLMUL
|
||||
int p = (0x7FFFFF - (prob << 15) + prob) >> 8;
|
||||
#else
|
||||
int p = ((prob << 15) + 256 - prob) >> 8;
|
||||
#endif
|
||||
#if CONFIG_BITSTREAM_DEBUG
|
||||
/*{
|
||||
const int queue_r = bitstream_queue_get_read();
|
||||
const int frame_idx = bitstream_queue_get_frame_read();
|
||||
if (frame_idx == 0 && queue_r == 0) {
|
||||
fprintf(stderr, "\n *** bitstream queue at frame_idx_r %d queue_r %d\n",
|
||||
frame_idx, queue_r);
|
||||
}
|
||||
}*/
|
||||
#endif
|
||||
|
||||
bit = od_ec_decode_bool_q15(&r->ec, p);
|
||||
|
||||
#if CONFIG_BITSTREAM_DEBUG
|
||||
{
|
||||
int i;
|
||||
int ref_bit, ref_nsymbs;
|
||||
aom_cdf_prob ref_cdf[16];
|
||||
const int queue_r = bitstream_queue_get_read();
|
||||
const int frame_idx = bitstream_queue_get_frame_read();
|
||||
bitstream_queue_pop(&ref_bit, ref_cdf, &ref_nsymbs);
|
||||
if (ref_nsymbs != 2) {
|
||||
fprintf(stderr,
|
||||
"\n *** [bit] nsymbs error, frame_idx_r %d nsymbs %d ref_nsymbs "
|
||||
"%d queue_r %d\n",
|
||||
frame_idx, 2, ref_nsymbs, queue_r);
|
||||
assert(0);
|
||||
}
|
||||
if ((ref_nsymbs != 2) || (ref_cdf[0] != (aom_cdf_prob)p) ||
|
||||
(ref_cdf[1] != 32767)) {
|
||||
fprintf(stderr,
|
||||
"\n *** [bit] cdf error, frame_idx_r %d cdf {%d, %d} ref_cdf {%d",
|
||||
frame_idx, p, 32767, ref_cdf[0]);
|
||||
for (i = 1; i < ref_nsymbs; ++i) fprintf(stderr, ", %d", ref_cdf[i]);
|
||||
fprintf(stderr, "} queue_r %d\n", queue_r);
|
||||
assert(0);
|
||||
}
|
||||
if (bit != ref_bit) {
|
||||
fprintf(stderr,
|
||||
"\n *** [bit] symb error, frame_idx_r %d symb %d ref_symb %d "
|
||||
"queue_r %d\n",
|
||||
frame_idx, bit, ref_bit, queue_r);
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return bit;
|
||||
}
|
||||
|
||||
#if CONFIG_RAWBITS
|
||||
static INLINE int aom_daala_read_bit(daala_reader *r) {
|
||||
return od_ec_dec_bits(&r->ec, 1, "aom_bits");
|
||||
}
|
||||
#endif
|
||||
|
||||
static INLINE int aom_daala_reader_has_error(daala_reader *r) {
|
||||
return r->ec.error;
|
||||
}
|
||||
|
||||
static INLINE int daala_read_symbol(daala_reader *r, const aom_cdf_prob *cdf,
|
||||
int nsymbs) {
|
||||
int symb;
|
||||
symb = od_ec_decode_cdf_q15(&r->ec, cdf, nsymbs);
|
||||
|
||||
#if CONFIG_BITSTREAM_DEBUG
|
||||
{
|
||||
int i;
|
||||
int cdf_error = 0;
|
||||
int ref_symb, ref_nsymbs;
|
||||
aom_cdf_prob ref_cdf[16];
|
||||
const int queue_r = bitstream_queue_get_read();
|
||||
const int frame_idx = bitstream_queue_get_frame_read();
|
||||
bitstream_queue_pop(&ref_symb, ref_cdf, &ref_nsymbs);
|
||||
if (nsymbs != ref_nsymbs) {
|
||||
fprintf(stderr,
|
||||
"\n *** nsymbs error, frame_idx_r %d nsymbs %d ref_nsymbs %d "
|
||||
"queue_r %d\n",
|
||||
frame_idx, nsymbs, ref_nsymbs, queue_r);
|
||||
cdf_error = 0;
|
||||
assert(0);
|
||||
} else {
|
||||
for (i = 0; i < nsymbs; ++i)
|
||||
if (cdf[i] != ref_cdf[i]) cdf_error = 1;
|
||||
}
|
||||
if (cdf_error) {
|
||||
fprintf(stderr, "\n *** cdf error, frame_idx_r %d cdf {%d", frame_idx,
|
||||
cdf[0]);
|
||||
for (i = 1; i < nsymbs; ++i) fprintf(stderr, ", %d", cdf[i]);
|
||||
fprintf(stderr, "} ref_cdf {%d", ref_cdf[0]);
|
||||
for (i = 1; i < ref_nsymbs; ++i) fprintf(stderr, ", %d", ref_cdf[i]);
|
||||
fprintf(stderr, "} queue_r %d\n", queue_r);
|
||||
assert(0);
|
||||
}
|
||||
if (symb != ref_symb) {
|
||||
fprintf(
|
||||
stderr,
|
||||
"\n *** symb error, frame_idx_r %d symb %d ref_symb %d queue_r %d\n",
|
||||
frame_idx, symb, ref_symb, queue_r);
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return symb;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
32
third_party/aom/aom_dsp/daalaboolwriter.c
vendored
Normal file
32
third_party/aom/aom_dsp/daalaboolwriter.c
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "aom_dsp/daalaboolwriter.h"
|
||||
|
||||
void aom_daala_start_encode(daala_writer *br, uint8_t *source) {
|
||||
br->buffer = source;
|
||||
br->pos = 0;
|
||||
od_ec_enc_init(&br->ec, 62025);
|
||||
}
|
||||
|
||||
void aom_daala_stop_encode(daala_writer *br) {
|
||||
uint32_t daala_bytes;
|
||||
unsigned char *daala_data;
|
||||
daala_data = od_ec_enc_done(&br->ec, &daala_bytes);
|
||||
memcpy(br->buffer, daala_data, daala_bytes);
|
||||
br->pos = daala_bytes;
|
||||
/* Prevent ec bitstream from being detected as a superframe marker.
|
||||
Must always be added, so that rawbits knows the exact length of the
|
||||
bitstream. */
|
||||
br->buffer[br->pos++] = 0;
|
||||
od_ec_enc_clear(&br->ec);
|
||||
}
|
||||
87
third_party/aom/aom_dsp/daalaboolwriter.h
vendored
Normal file
87
third_party/aom/aom_dsp/daalaboolwriter.h
vendored
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#ifndef AOM_DSP_DAALABOOLWRITER_H_
|
||||
#define AOM_DSP_DAALABOOLWRITER_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "aom_dsp/entenc.h"
|
||||
#include "aom_dsp/prob.h"
|
||||
#if CONFIG_BITSTREAM_DEBUG
|
||||
#include "aom_util/debug_util.h"
|
||||
#endif // CONFIG_BITSTREAM_DEBUG
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct daala_writer {
|
||||
unsigned int pos;
|
||||
uint8_t *buffer;
|
||||
od_ec_enc ec;
|
||||
};
|
||||
|
||||
typedef struct daala_writer daala_writer;
|
||||
|
||||
void aom_daala_start_encode(daala_writer *w, uint8_t *buffer);
|
||||
void aom_daala_stop_encode(daala_writer *w);
|
||||
|
||||
static INLINE void aom_daala_write(daala_writer *w, int bit, int prob) {
|
||||
#if CONFIG_EC_SMALLMUL
|
||||
int p = (0x7FFFFF - (prob << 15) + prob) >> 8;
|
||||
#else
|
||||
int p = ((prob << 15) + 256 - prob) >> 8;
|
||||
#endif
|
||||
#if CONFIG_BITSTREAM_DEBUG
|
||||
aom_cdf_prob cdf[2] = { (aom_cdf_prob)p, 32767 };
|
||||
/*int queue_r = 0;
|
||||
int frame_idx_r = 0;
|
||||
int queue_w = bitstream_queue_get_write();
|
||||
int frame_idx_w = bitstream_queue_get_frame_write();
|
||||
if (frame_idx_w == frame_idx_r && queue_w == queue_r) {
|
||||
fprintf(stderr, "\n *** bitstream queue at frame_idx_w %d queue_w %d\n",
|
||||
frame_idx_w, queue_w);
|
||||
}*/
|
||||
bitstream_queue_push(bit, cdf, 2);
|
||||
#endif
|
||||
|
||||
od_ec_encode_bool_q15(&w->ec, bit, p);
|
||||
}
|
||||
|
||||
#if CONFIG_RAWBITS
|
||||
static INLINE void aom_daala_write_bit(daala_writer *w, int bit) {
|
||||
od_ec_enc_bits(&w->ec, bit, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
static INLINE void daala_write_symbol(daala_writer *w, int symb,
|
||||
const aom_cdf_prob *cdf, int nsymbs) {
|
||||
#if CONFIG_BITSTREAM_DEBUG
|
||||
/*int queue_r = 0;
|
||||
int frame_idx_r = 0;
|
||||
int queue_w = bitstream_queue_get_write();
|
||||
int frame_idx_w = bitstream_queue_get_frame_write();
|
||||
if (frame_idx_w == frame_idx_r && queue_w == queue_r) {
|
||||
fprintf(stderr, "\n *** bitstream queue at frame_idx_w %d queue_w %d\n",
|
||||
frame_idx_w, queue_w);
|
||||
}*/
|
||||
bitstream_queue_push(symb, cdf, nsymbs);
|
||||
#endif
|
||||
|
||||
od_ec_encode_cdf_q15(&w->ec, symb, cdf, nsymbs);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
110
third_party/aom/aom_dsp/dkboolreader.c
vendored
Normal file
110
third_party/aom/aom_dsp/dkboolreader.c
vendored
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "./aom_config.h"
|
||||
|
||||
#include "aom_dsp/dkboolreader.h"
|
||||
#include "aom_dsp/prob.h"
|
||||
#include "aom_dsp/aom_dsp_common.h"
|
||||
#include "aom_ports/mem.h"
|
||||
#include "aom_mem/aom_mem.h"
|
||||
#include "aom_util/endian_inl.h"
|
||||
|
||||
static INLINE int aom_dk_read_bit(struct aom_dk_reader *r) {
|
||||
return aom_dk_read(r, 128); // aom_prob_half
|
||||
}
|
||||
|
||||
int aom_dk_reader_init(struct aom_dk_reader *r, const uint8_t *buffer,
|
||||
size_t size, aom_decrypt_cb decrypt_cb,
|
||||
void *decrypt_state) {
|
||||
if (size && !buffer) {
|
||||
return 1;
|
||||
} else {
|
||||
r->buffer_end = buffer + size;
|
||||
r->buffer_start = r->buffer = buffer;
|
||||
r->value = 0;
|
||||
r->count = -8;
|
||||
r->range = 255;
|
||||
r->decrypt_cb = decrypt_cb;
|
||||
r->decrypt_state = decrypt_state;
|
||||
aom_dk_reader_fill(r);
|
||||
#if CONFIG_ACCOUNTING
|
||||
r->accounting = NULL;
|
||||
#endif
|
||||
return aom_dk_read_bit(r) != 0; // marker bit
|
||||
}
|
||||
}
|
||||
|
||||
void aom_dk_reader_fill(struct aom_dk_reader *r) {
|
||||
const uint8_t *const buffer_end = r->buffer_end;
|
||||
const uint8_t *buffer = r->buffer;
|
||||
const uint8_t *buffer_start = buffer;
|
||||
BD_VALUE value = r->value;
|
||||
int count = r->count;
|
||||
const size_t bytes_left = buffer_end - buffer;
|
||||
const size_t bits_left = bytes_left * CHAR_BIT;
|
||||
int shift = BD_VALUE_SIZE - CHAR_BIT - (count + CHAR_BIT);
|
||||
|
||||
if (r->decrypt_cb) {
|
||||
size_t n = AOMMIN(sizeof(r->clear_buffer), bytes_left);
|
||||
r->decrypt_cb(r->decrypt_state, buffer, r->clear_buffer, (int)n);
|
||||
buffer = r->clear_buffer;
|
||||
buffer_start = r->clear_buffer;
|
||||
}
|
||||
if (bits_left > BD_VALUE_SIZE) {
|
||||
const int bits = (shift & 0xfffffff8) + CHAR_BIT;
|
||||
BD_VALUE nv;
|
||||
BD_VALUE big_endian_values;
|
||||
memcpy(&big_endian_values, buffer, sizeof(BD_VALUE));
|
||||
#if SIZE_MAX == 0xffffffffffffffffULL
|
||||
big_endian_values = HToBE64(big_endian_values);
|
||||
#else
|
||||
big_endian_values = HToBE32(big_endian_values);
|
||||
#endif
|
||||
nv = big_endian_values >> (BD_VALUE_SIZE - bits);
|
||||
count += bits;
|
||||
buffer += (bits >> 3);
|
||||
value = r->value | (nv << (shift & 0x7));
|
||||
} else {
|
||||
const int bits_over = (int)(shift + CHAR_BIT - (int)bits_left);
|
||||
int loop_end = 0;
|
||||
if (bits_over >= 0) {
|
||||
count += LOTS_OF_BITS;
|
||||
loop_end = bits_over;
|
||||
}
|
||||
|
||||
if (bits_over < 0 || bits_left) {
|
||||
while (shift >= loop_end) {
|
||||
count += CHAR_BIT;
|
||||
value |= (BD_VALUE)*buffer++ << shift;
|
||||
shift -= CHAR_BIT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: Variable 'buffer' may not relate to 'r->buffer' after decryption,
|
||||
// so we increase 'r->buffer' by the amount that 'buffer' moved, rather than
|
||||
// assign 'buffer' to 'r->buffer'.
|
||||
r->buffer += buffer - buffer_start;
|
||||
r->value = value;
|
||||
r->count = count;
|
||||
}
|
||||
|
||||
const uint8_t *aom_dk_reader_find_end(struct aom_dk_reader *r) {
|
||||
// Find the end of the coded buffer
|
||||
while (r->count > CHAR_BIT && r->count < BD_VALUE_SIZE) {
|
||||
r->count -= CHAR_BIT;
|
||||
r->buffer--;
|
||||
}
|
||||
return r->buffer;
|
||||
}
|
||||
181
third_party/aom/aom_dsp/dkboolreader.h
vendored
Normal file
181
third_party/aom/aom_dsp/dkboolreader.h
vendored
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#ifndef AOM_DSP_DKBOOLREADER_H_
|
||||
#define AOM_DSP_DKBOOLREADER_H_
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "./aom_config.h"
|
||||
#if CONFIG_BITSTREAM_DEBUG
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include "aom_util/debug_util.h"
|
||||
#endif // CONFIG_BITSTREAM_DEBUG
|
||||
|
||||
#include "aom_ports/mem.h"
|
||||
#include "aom/aomdx.h"
|
||||
#include "aom/aom_integer.h"
|
||||
#include "aom_dsp/prob.h"
|
||||
#if CONFIG_ACCOUNTING
|
||||
#include "av1/decoder/accounting.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef size_t BD_VALUE;
|
||||
|
||||
#define BD_VALUE_SIZE ((int)sizeof(BD_VALUE) * CHAR_BIT)
|
||||
|
||||
// This is meant to be a large, positive constant that can still be efficiently
|
||||
// loaded as an immediate (on platforms like ARM, for example).
|
||||
// Even relatively modest values like 100 would work fine.
|
||||
#define LOTS_OF_BITS 0x40000000
|
||||
|
||||
struct aom_dk_reader {
|
||||
// Be careful when reordering this struct, it may impact the cache negatively.
|
||||
BD_VALUE value;
|
||||
unsigned int range;
|
||||
int count;
|
||||
const uint8_t *buffer_start;
|
||||
const uint8_t *buffer_end;
|
||||
const uint8_t *buffer;
|
||||
aom_decrypt_cb decrypt_cb;
|
||||
void *decrypt_state;
|
||||
uint8_t clear_buffer[sizeof(BD_VALUE) + 1];
|
||||
#if CONFIG_ACCOUNTING
|
||||
Accounting *accounting;
|
||||
#endif
|
||||
};
|
||||
|
||||
int aom_dk_reader_init(struct aom_dk_reader *r, const uint8_t *buffer,
|
||||
size_t size, aom_decrypt_cb decrypt_cb,
|
||||
void *decrypt_state);
|
||||
|
||||
void aom_dk_reader_fill(struct aom_dk_reader *r);
|
||||
|
||||
const uint8_t *aom_dk_reader_find_end(struct aom_dk_reader *r);
|
||||
|
||||
static INLINE uint32_t aom_dk_reader_tell(const struct aom_dk_reader *r) {
|
||||
const uint32_t bits_read =
|
||||
(uint32_t)((r->buffer - r->buffer_start) * CHAR_BIT);
|
||||
const int count =
|
||||
(r->count < LOTS_OF_BITS) ? r->count : r->count - LOTS_OF_BITS;
|
||||
assert(r->buffer >= r->buffer_start);
|
||||
return bits_read - (count + CHAR_BIT);
|
||||
}
|
||||
|
||||
/*The resolution of fractional-precision bit usage measurements, i.e.,
|
||||
3 => 1/8th bits.*/
|
||||
#define DK_BITRES (3)
|
||||
|
||||
static INLINE uint32_t aom_dk_reader_tell_frac(const struct aom_dk_reader *r) {
|
||||
uint32_t num_bits;
|
||||
uint32_t range;
|
||||
int l;
|
||||
int i;
|
||||
num_bits = aom_dk_reader_tell(r) << DK_BITRES;
|
||||
range = r->range;
|
||||
l = 0;
|
||||
for (i = DK_BITRES; i-- > 0;) {
|
||||
int b;
|
||||
range = range * range >> 7;
|
||||
b = (int)(range >> 8);
|
||||
l = l << 1 | b;
|
||||
range >>= b;
|
||||
}
|
||||
return num_bits - l;
|
||||
}
|
||||
|
||||
static INLINE int aom_dk_reader_has_error(struct aom_dk_reader *r) {
|
||||
// Check if we have reached the end of the buffer.
|
||||
//
|
||||
// Variable 'count' stores the number of bits in the 'value' buffer, minus
|
||||
// 8. The top byte is part of the algorithm, and the remainder is buffered
|
||||
// to be shifted into it. So if count == 8, the top 16 bits of 'value' are
|
||||
// occupied, 8 for the algorithm and 8 in the buffer.
|
||||
//
|
||||
// When reading a byte from the user's buffer, count is filled with 8 and
|
||||
// one byte is filled into the value buffer. When we reach the end of the
|
||||
// data, count is additionally filled with LOTS_OF_BITS. So when
|
||||
// count == LOTS_OF_BITS - 1, the user's data has been exhausted.
|
||||
//
|
||||
// 1 if we have tried to decode bits after the end of stream was encountered.
|
||||
// 0 No error.
|
||||
return r->count > BD_VALUE_SIZE && r->count < LOTS_OF_BITS;
|
||||
}
|
||||
|
||||
static INLINE int aom_dk_read(struct aom_dk_reader *r, int prob) {
|
||||
unsigned int bit = 0;
|
||||
BD_VALUE value;
|
||||
BD_VALUE bigsplit;
|
||||
int count;
|
||||
unsigned int range;
|
||||
unsigned int split = (r->range * prob + (256 - prob)) >> CHAR_BIT;
|
||||
|
||||
if (r->count < 0) aom_dk_reader_fill(r);
|
||||
|
||||
value = r->value;
|
||||
count = r->count;
|
||||
|
||||
bigsplit = (BD_VALUE)split << (BD_VALUE_SIZE - CHAR_BIT);
|
||||
|
||||
range = split;
|
||||
|
||||
if (value >= bigsplit) {
|
||||
range = r->range - split;
|
||||
value = value - bigsplit;
|
||||
bit = 1;
|
||||
}
|
||||
|
||||
{
|
||||
register int shift = aom_norm[range];
|
||||
range <<= shift;
|
||||
value <<= shift;
|
||||
count -= shift;
|
||||
}
|
||||
r->value = value;
|
||||
r->count = count;
|
||||
r->range = range;
|
||||
|
||||
#if CONFIG_BITSTREAM_DEBUG
|
||||
{
|
||||
int ref_bit, ref_prob;
|
||||
const int queue_r = bitstream_queue_get_read();
|
||||
const int frame_idx = bitstream_queue_get_frame_read();
|
||||
bitstream_queue_pop(&ref_bit, &ref_prob);
|
||||
if (prob != ref_prob) {
|
||||
fprintf(
|
||||
stderr,
|
||||
"\n *** prob error, frame_idx_r %d prob %d ref_prob %d queue_r %d\n",
|
||||
frame_idx, prob, ref_prob, queue_r);
|
||||
assert(0);
|
||||
}
|
||||
if ((int)bit != ref_bit) {
|
||||
fprintf(stderr, "\n *** bit error, frame_idx_r %d bit %d ref_bit %d\n",
|
||||
frame_idx, bit, ref_bit);
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
#endif // CONFIG_BITSTREAM_DEBUG
|
||||
|
||||
return bit;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // AOM_DSP_DKBOOLREADER_H_
|
||||
44
third_party/aom/aom_dsp/dkboolwriter.c
vendored
Normal file
44
third_party/aom/aom_dsp/dkboolwriter.c
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "./dkboolwriter.h"
|
||||
|
||||
static INLINE void aom_dk_write_bit(aom_dk_writer *w, int bit) {
|
||||
aom_dk_write(w, bit, 128); // aom_prob_half
|
||||
}
|
||||
|
||||
void aom_dk_start_encode(aom_dk_writer *br, uint8_t *source) {
|
||||
br->lowvalue = 0;
|
||||
br->range = 255;
|
||||
br->count = -24;
|
||||
br->buffer = source;
|
||||
br->pos = 0;
|
||||
aom_dk_write_bit(br, 0);
|
||||
}
|
||||
|
||||
void aom_dk_stop_encode(aom_dk_writer *br) {
|
||||
int i;
|
||||
|
||||
#if CONFIG_BITSTREAM_DEBUG
|
||||
bitstream_queue_set_skip_write(1);
|
||||
#endif // CONFIG_BITSTREAM_DEBUG
|
||||
|
||||
for (i = 0; i < 32; i++) aom_dk_write_bit(br, 0);
|
||||
|
||||
#if CONFIG_BITSTREAM_DEBUG
|
||||
bitstream_queue_set_skip_write(0);
|
||||
#endif // CONFIG_BITSTREAM_DEBUG
|
||||
|
||||
// Ensure there's no ambigous collision with any index marker bytes
|
||||
if ((br->buffer[br->pos - 1] & 0xe0) == 0xc0) br->buffer[br->pos++] = 0;
|
||||
}
|
||||
104
third_party/aom/aom_dsp/dkboolwriter.h
vendored
Normal file
104
third_party/aom/aom_dsp/dkboolwriter.h
vendored
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#ifndef AOM_DSP_DKBOOLWRITER_H_
|
||||
#define AOM_DSP_DKBOOLWRITER_H_
|
||||
|
||||
#include "./aom_config.h"
|
||||
|
||||
#if CONFIG_BITSTREAM_DEBUG
|
||||
#include <stdio.h>
|
||||
#include "aom_util/debug_util.h"
|
||||
#endif // CONFIG_BITSTREAM_DEBUG
|
||||
|
||||
#include "aom_dsp/prob.h"
|
||||
#include "aom_ports/mem.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct aom_dk_writer {
|
||||
unsigned int lowvalue;
|
||||
unsigned int range;
|
||||
int count;
|
||||
unsigned int pos;
|
||||
uint8_t *buffer;
|
||||
} aom_dk_writer;
|
||||
|
||||
void aom_dk_start_encode(aom_dk_writer *bc, uint8_t *buffer);
|
||||
void aom_dk_stop_encode(aom_dk_writer *bc);
|
||||
|
||||
static INLINE void aom_dk_write(aom_dk_writer *br, int bit, int probability) {
|
||||
unsigned int split;
|
||||
int count = br->count;
|
||||
unsigned int range = br->range;
|
||||
unsigned int lowvalue = br->lowvalue;
|
||||
register int shift;
|
||||
|
||||
#if CONFIG_BITSTREAM_DEBUG
|
||||
// int queue_r = 0;
|
||||
// int frame_idx_r = 0;
|
||||
// int queue_w = bitstream_queue_get_write();
|
||||
// int frame_idx_w = bitstream_queue_get_frame_write();
|
||||
// if (frame_idx_w == frame_idx_r && queue_w == queue_r) {
|
||||
// fprintf(stderr, "\n *** bitstream queue at frame_idx_w %d queue_w %d\n",
|
||||
// frame_idx_w, queue_w);
|
||||
// }
|
||||
bitstream_queue_push(bit, probability);
|
||||
#endif // CONFIG_BITSTREAM_DEBUG
|
||||
|
||||
split = 1 + (((range - 1) * probability) >> 8);
|
||||
|
||||
range = split;
|
||||
|
||||
if (bit) {
|
||||
lowvalue += split;
|
||||
range = br->range - split;
|
||||
}
|
||||
|
||||
shift = aom_norm[range];
|
||||
|
||||
range <<= shift;
|
||||
count += shift;
|
||||
|
||||
if (count >= 0) {
|
||||
int offset = shift - count;
|
||||
|
||||
if ((lowvalue << (offset - 1)) & 0x80000000) {
|
||||
int x = br->pos - 1;
|
||||
|
||||
while (x >= 0 && br->buffer[x] == 0xff) {
|
||||
br->buffer[x] = 0;
|
||||
x--;
|
||||
}
|
||||
|
||||
br->buffer[x] += 1;
|
||||
}
|
||||
|
||||
br->buffer[br->pos++] = (lowvalue >> (24 - offset));
|
||||
lowvalue <<= offset;
|
||||
shift = count;
|
||||
lowvalue &= 0xffffff;
|
||||
count -= 8;
|
||||
}
|
||||
|
||||
lowvalue <<= shift;
|
||||
br->count = count;
|
||||
br->lowvalue = lowvalue;
|
||||
br->range = range;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // AOM_DSP_DKBOOLWRITER_H_
|
||||
53
third_party/aom/aom_dsp/entcode.c
vendored
Normal file
53
third_party/aom/aom_dsp/entcode.c
vendored
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "./config.h"
|
||||
#endif
|
||||
|
||||
#include "aom_dsp/entcode.h"
|
||||
|
||||
/*Given the current total integer number of bits used and the current value of
|
||||
rng, computes the fraction number of bits used to OD_BITRES precision.
|
||||
This is used by od_ec_enc_tell_frac() and od_ec_dec_tell_frac().
|
||||
nbits_total: The number of whole bits currently used, i.e., the value
|
||||
returned by od_ec_enc_tell() or od_ec_dec_tell().
|
||||
rng: The current value of rng from either the encoder or decoder state.
|
||||
Return: The number of bits scaled by 2**OD_BITRES.
|
||||
This will always be slightly larger than the exact value (e.g., all
|
||||
rounding error is in the positive direction).*/
|
||||
uint32_t od_ec_tell_frac(uint32_t nbits_total, uint32_t rng) {
|
||||
uint32_t nbits;
|
||||
int l;
|
||||
int i;
|
||||
/*To handle the non-integral number of bits still left in the encoder/decoder
|
||||
state, we compute the worst-case number of bits of val that must be
|
||||
encoded to ensure that the value is inside the range for any possible
|
||||
subsequent bits.
|
||||
The computation here is independent of val itself (the decoder does not
|
||||
even track that value), even though the real number of bits used after
|
||||
od_ec_enc_done() may be 1 smaller if rng is a power of two and the
|
||||
corresponding trailing bits of val are all zeros.
|
||||
If we did try to track that special case, then coding a value with a
|
||||
probability of 1/(1 << n) might sometimes appear to use more than n bits.
|
||||
This may help explain the surprising result that a newly initialized
|
||||
encoder or decoder claims to have used 1 bit.*/
|
||||
nbits = nbits_total << OD_BITRES;
|
||||
l = 0;
|
||||
for (i = OD_BITRES; i-- > 0;) {
|
||||
int b;
|
||||
rng = rng * rng >> 15;
|
||||
b = (int)(rng >> 16);
|
||||
l = l << 1 | b;
|
||||
rng >>= b;
|
||||
}
|
||||
return nbits - l;
|
||||
}
|
||||
46
third_party/aom/aom_dsp/entcode.h
vendored
Normal file
46
third_party/aom/aom_dsp/entcode.h
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#if !defined(_entcode_H)
|
||||
#define _entcode_H (1)
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
#include "av1/common/odintrin.h"
|
||||
|
||||
/*OPT: od_ec_window must be at least 32 bits, but if you have fast arithmetic
|
||||
on a larger type, you can speed up the decoder by using it here.*/
|
||||
typedef uint32_t od_ec_window;
|
||||
|
||||
#define OD_EC_WINDOW_SIZE ((int)sizeof(od_ec_window) * CHAR_BIT)
|
||||
|
||||
/*The number of bits to use for the range-coded part of unsigned integers.*/
|
||||
#define OD_EC_UINT_BITS (4)
|
||||
|
||||
/*The resolution of fractional-precision bit usage measurements, i.e.,
|
||||
3 => 1/8th bits.*/
|
||||
#define OD_BITRES (3)
|
||||
|
||||
/*With CONFIG_EC_SMALLMUL, the value stored in a CDF is 32768 minus the actual
|
||||
Q15 cumulative probability (an "inverse" CDF).
|
||||
This function converts from one representation to the other (and is its own
|
||||
inverse).*/
|
||||
#if CONFIG_EC_SMALLMUL
|
||||
#define OD_ICDF(x) (32768U - (x))
|
||||
#else
|
||||
#define OD_ICDF(x) (x)
|
||||
#endif
|
||||
|
||||
/*See entcode.c for further documentation.*/
|
||||
|
||||
OD_WARN_UNUSED_RESULT uint32_t od_ec_tell_frac(uint32_t nbits_total,
|
||||
uint32_t rng);
|
||||
|
||||
#endif
|
||||
300
third_party/aom/aom_dsp/entdec.c
vendored
Normal file
300
third_party/aom/aom_dsp/entdec.c
vendored
Normal file
|
|
@ -0,0 +1,300 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "./config.h"
|
||||
#endif
|
||||
|
||||
#include "aom_dsp/entdec.h"
|
||||
|
||||
/*A range decoder.
|
||||
This is an entropy decoder based upon \cite{Mar79}, which is itself a
|
||||
rediscovery of the FIFO arithmetic code introduced by \cite{Pas76}.
|
||||
It is very similar to arithmetic encoding, except that encoding is done with
|
||||
digits in any base, instead of with bits, and so it is faster when using
|
||||
larger bases (i.e.: a byte).
|
||||
The author claims an average waste of $\frac{1}{2}\log_b(2b)$ bits, where $b$
|
||||
is the base, longer than the theoretical optimum, but to my knowledge there
|
||||
is no published justification for this claim.
|
||||
This only seems true when using near-infinite precision arithmetic so that
|
||||
the process is carried out with no rounding errors.
|
||||
|
||||
An excellent description of implementation details is available at
|
||||
http://www.arturocampos.com/ac_range.html
|
||||
A recent work \cite{MNW98} which proposes several changes to arithmetic
|
||||
encoding for efficiency actually re-discovers many of the principles
|
||||
behind range encoding, and presents a good theoretical analysis of them.
|
||||
|
||||
End of stream is handled by writing out the smallest number of bits that
|
||||
ensures that the stream will be correctly decoded regardless of the value of
|
||||
any subsequent bits.
|
||||
od_ec_dec_tell() can be used to determine how many bits were needed to decode
|
||||
all the symbols thus far; other data can be packed in the remaining bits of
|
||||
the input buffer.
|
||||
@PHDTHESIS{Pas76,
|
||||
author="Richard Clark Pasco",
|
||||
title="Source coding algorithms for fast data compression",
|
||||
school="Dept. of Electrical Engineering, Stanford University",
|
||||
address="Stanford, CA",
|
||||
month=May,
|
||||
year=1976,
|
||||
URL="http://www.richpasco.org/scaffdc.pdf"
|
||||
}
|
||||
@INPROCEEDINGS{Mar79,
|
||||
author="Martin, G.N.N.",
|
||||
title="Range encoding: an algorithm for removing redundancy from a digitised
|
||||
message",
|
||||
booktitle="Video & Data Recording Conference",
|
||||
year=1979,
|
||||
address="Southampton",
|
||||
month=Jul,
|
||||
URL="http://www.compressconsult.com/rangecoder/rngcod.pdf.gz"
|
||||
}
|
||||
@ARTICLE{MNW98,
|
||||
author="Alistair Moffat and Radford Neal and Ian H. Witten",
|
||||
title="Arithmetic Coding Revisited",
|
||||
journal="{ACM} Transactions on Information Systems",
|
||||
year=1998,
|
||||
volume=16,
|
||||
number=3,
|
||||
pages="256--294",
|
||||
month=Jul,
|
||||
URL="http://researchcommons.waikato.ac.nz/bitstream/handle/10289/78/content.pdf"
|
||||
}*/
|
||||
|
||||
/*This is meant to be a large, positive constant that can still be efficiently
|
||||
loaded as an immediate (on platforms like ARM, for example).
|
||||
Even relatively modest values like 100 would work fine.*/
|
||||
#define OD_EC_LOTS_OF_BITS (0x4000)
|
||||
|
||||
static void od_ec_dec_refill(od_ec_dec *dec) {
|
||||
int s;
|
||||
od_ec_window dif;
|
||||
int16_t cnt;
|
||||
const unsigned char *bptr;
|
||||
const unsigned char *end;
|
||||
dif = dec->dif;
|
||||
cnt = dec->cnt;
|
||||
bptr = dec->bptr;
|
||||
end = dec->end;
|
||||
s = OD_EC_WINDOW_SIZE - 9 - (cnt + 15);
|
||||
for (; s >= 0 && bptr < end; s -= 8, bptr++) {
|
||||
OD_ASSERT(s <= OD_EC_WINDOW_SIZE - 8);
|
||||
dif ^= (od_ec_window)bptr[0] << s;
|
||||
cnt += 8;
|
||||
}
|
||||
if (bptr >= end) {
|
||||
dec->tell_offs += OD_EC_LOTS_OF_BITS - cnt;
|
||||
cnt = OD_EC_LOTS_OF_BITS;
|
||||
}
|
||||
dec->dif = dif;
|
||||
dec->cnt = cnt;
|
||||
dec->bptr = bptr;
|
||||
}
|
||||
|
||||
/*Takes updated dif and range values, renormalizes them so that
|
||||
32768 <= rng < 65536 (reading more bytes from the stream into dif if
|
||||
necessary), and stores them back in the decoder context.
|
||||
dif: The new value of dif.
|
||||
rng: The new value of the range.
|
||||
ret: The value to return.
|
||||
Return: ret.
|
||||
This allows the compiler to jump to this function via a tail-call.*/
|
||||
static int od_ec_dec_normalize(od_ec_dec *dec, od_ec_window dif, unsigned rng,
|
||||
int ret) {
|
||||
int d;
|
||||
OD_ASSERT(rng <= 65535U);
|
||||
d = 16 - OD_ILOG_NZ(rng);
|
||||
dec->cnt -= d;
|
||||
#if CONFIG_EC_SMALLMUL
|
||||
/*This is equivalent to shifting in 1's instead of 0's.*/
|
||||
dec->dif = ((dif + 1) << d) - 1;
|
||||
#else
|
||||
dec->dif = dif << d;
|
||||
#endif
|
||||
dec->rng = rng << d;
|
||||
if (dec->cnt < 0) od_ec_dec_refill(dec);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*Initializes the decoder.
|
||||
buf: The input buffer to use.
|
||||
Return: 0 on success, or a negative value on error.*/
|
||||
void od_ec_dec_init(od_ec_dec *dec, const unsigned char *buf,
|
||||
uint32_t storage) {
|
||||
dec->buf = buf;
|
||||
dec->eptr = buf + storage;
|
||||
dec->end_window = 0;
|
||||
dec->nend_bits = 0;
|
||||
dec->tell_offs = 10 - (OD_EC_WINDOW_SIZE - 8);
|
||||
dec->end = buf + storage;
|
||||
dec->bptr = buf;
|
||||
#if CONFIG_EC_SMALLMUL
|
||||
dec->dif = ((od_ec_window)1 << (OD_EC_WINDOW_SIZE - 1)) - 1;
|
||||
#else
|
||||
dec->dif = 0;
|
||||
#endif
|
||||
dec->rng = 0x8000;
|
||||
dec->cnt = -15;
|
||||
dec->error = 0;
|
||||
od_ec_dec_refill(dec);
|
||||
}
|
||||
|
||||
/*Decode a single binary value.
|
||||
{EC_SMALLMUL} f: The probability that the bit is one, scaled by 32768.
|
||||
{else} f: The probability that the bit is zero, scaled by 32768.
|
||||
Return: The value decoded (0 or 1).*/
|
||||
int od_ec_decode_bool_q15(od_ec_dec *dec, unsigned f) {
|
||||
od_ec_window dif;
|
||||
od_ec_window vw;
|
||||
unsigned r;
|
||||
unsigned r_new;
|
||||
unsigned v;
|
||||
int ret;
|
||||
OD_ASSERT(0 < f);
|
||||
OD_ASSERT(f < 32768U);
|
||||
dif = dec->dif;
|
||||
r = dec->rng;
|
||||
OD_ASSERT(dif >> (OD_EC_WINDOW_SIZE - 16) < r);
|
||||
OD_ASSERT(32768U <= r);
|
||||
#if CONFIG_EC_SMALLMUL
|
||||
v = (r >> 8) * (uint32_t)f >> 7;
|
||||
vw = (od_ec_window)v << (OD_EC_WINDOW_SIZE - 16);
|
||||
ret = 1;
|
||||
r_new = v;
|
||||
if (dif >= vw) {
|
||||
r_new = r - v;
|
||||
dif -= vw;
|
||||
ret = 0;
|
||||
}
|
||||
#else
|
||||
v = f * (uint32_t)r >> 15;
|
||||
vw = (od_ec_window)v << (OD_EC_WINDOW_SIZE - 16);
|
||||
ret = 0;
|
||||
r_new = v;
|
||||
if (dif >= vw) {
|
||||
r_new = r - v;
|
||||
dif -= vw;
|
||||
ret = 1;
|
||||
}
|
||||
#endif
|
||||
return od_ec_dec_normalize(dec, dif, r_new, ret);
|
||||
}
|
||||
|
||||
/*Decodes a symbol given a cumulative distribution function (CDF) table in Q15.
|
||||
cdf: The CDF, such that symbol s falls in the range
|
||||
[s > 0 ? cdf[s - 1] : 0, cdf[s]).
|
||||
The values must be monotonically non-increasing, and cdf[nsyms - 1]
|
||||
must be 32768.
|
||||
{EC_SMALLMUL}: The CDF contains 32768 minus those values.
|
||||
nsyms: The number of symbols in the alphabet.
|
||||
This should be at most 16.
|
||||
Return: The decoded symbol s.*/
|
||||
int od_ec_decode_cdf_q15(od_ec_dec *dec, const uint16_t *cdf, int nsyms) {
|
||||
od_ec_window dif;
|
||||
unsigned r;
|
||||
unsigned c;
|
||||
unsigned u;
|
||||
unsigned v;
|
||||
int ret;
|
||||
(void)nsyms;
|
||||
dif = dec->dif;
|
||||
r = dec->rng;
|
||||
OD_ASSERT(dif >> (OD_EC_WINDOW_SIZE - 16) < r);
|
||||
OD_ASSERT(cdf[nsyms - 1] == OD_ICDF(32768U));
|
||||
OD_ASSERT(32768U <= r);
|
||||
#if CONFIG_EC_SMALLMUL
|
||||
c = (unsigned)(dif >> (OD_EC_WINDOW_SIZE - 16));
|
||||
v = r;
|
||||
ret = -1;
|
||||
do {
|
||||
u = v;
|
||||
v = (r >> 8) * (uint32_t)cdf[++ret] >> 7;
|
||||
} while (c < v);
|
||||
OD_ASSERT(v < u);
|
||||
OD_ASSERT(u <= r);
|
||||
r = u - v;
|
||||
dif -= (od_ec_window)v << (OD_EC_WINDOW_SIZE - 16);
|
||||
#else
|
||||
c = (unsigned)(dif >> (OD_EC_WINDOW_SIZE - 16));
|
||||
v = 0;
|
||||
ret = -1;
|
||||
do {
|
||||
u = v;
|
||||
v = cdf[++ret] * (uint32_t)r >> 15;
|
||||
} while (v <= c);
|
||||
OD_ASSERT(u < v);
|
||||
OD_ASSERT(v <= r);
|
||||
r = v - u;
|
||||
dif -= (od_ec_window)u << (OD_EC_WINDOW_SIZE - 16);
|
||||
#endif
|
||||
return od_ec_dec_normalize(dec, dif, r, ret);
|
||||
}
|
||||
|
||||
#if CONFIG_RAWBITS
|
||||
/*Extracts a sequence of raw bits from the stream.
|
||||
The bits must have been encoded with od_ec_enc_bits().
|
||||
ftb: The number of bits to extract.
|
||||
This must be between 0 and 25, inclusive.
|
||||
Return: The decoded bits.*/
|
||||
uint32_t od_ec_dec_bits_(od_ec_dec *dec, unsigned ftb) {
|
||||
od_ec_window window;
|
||||
int available;
|
||||
uint32_t ret;
|
||||
OD_ASSERT(ftb <= 25);
|
||||
window = dec->end_window;
|
||||
available = dec->nend_bits;
|
||||
if ((unsigned)available < ftb) {
|
||||
const unsigned char *buf;
|
||||
const unsigned char *eptr;
|
||||
buf = dec->buf;
|
||||
eptr = dec->eptr;
|
||||
OD_ASSERT(available <= OD_EC_WINDOW_SIZE - 8);
|
||||
do {
|
||||
if (eptr <= buf) {
|
||||
dec->tell_offs += OD_EC_LOTS_OF_BITS - available;
|
||||
available = OD_EC_LOTS_OF_BITS;
|
||||
break;
|
||||
}
|
||||
window |= (od_ec_window) * --eptr << available;
|
||||
available += 8;
|
||||
} while (available <= OD_EC_WINDOW_SIZE - 8);
|
||||
dec->eptr = eptr;
|
||||
}
|
||||
ret = (uint32_t)window & (((uint32_t)1 << ftb) - 1);
|
||||
window >>= ftb;
|
||||
available -= ftb;
|
||||
dec->end_window = window;
|
||||
dec->nend_bits = available;
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*Returns the number of bits "used" by the decoded symbols so far.
|
||||
This same number can be computed in either the encoder or the decoder, and is
|
||||
suitable for making coding decisions.
|
||||
Return: The number of bits.
|
||||
This will always be slightly larger than the exact value (e.g., all
|
||||
rounding error is in the positive direction).*/
|
||||
int od_ec_dec_tell(const od_ec_dec *dec) {
|
||||
return (int)(((dec->end - dec->eptr) + (dec->bptr - dec->buf)) * 8 -
|
||||
dec->cnt - dec->nend_bits + dec->tell_offs);
|
||||
}
|
||||
|
||||
/*Returns the number of bits "used" by the decoded symbols so far.
|
||||
This same number can be computed in either the encoder or the decoder, and is
|
||||
suitable for making coding decisions.
|
||||
Return: The number of bits scaled by 2**OD_BITRES.
|
||||
This will always be slightly larger than the exact value (e.g., all
|
||||
rounding error is in the positive direction).*/
|
||||
uint32_t od_ec_dec_tell_frac(const od_ec_dec *dec) {
|
||||
return od_ec_tell_frac(od_ec_dec_tell(dec), dec->rng);
|
||||
}
|
||||
91
third_party/aom/aom_dsp/entdec.h
vendored
Normal file
91
third_party/aom/aom_dsp/entdec.h
vendored
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#if !defined(_entdec_H)
|
||||
#define _entdec_H (1)
|
||||
#include <limits.h>
|
||||
#include "aom_dsp/entcode.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct od_ec_dec od_ec_dec;
|
||||
|
||||
#if defined(OD_ACCOUNTING) && OD_ACCOUNTING
|
||||
#define OD_ACC_STR , char *acc_str
|
||||
#define od_ec_dec_bits(dec, ftb, str) od_ec_dec_bits_(dec, ftb, str)
|
||||
#else
|
||||
#define OD_ACC_STR
|
||||
#define od_ec_dec_bits(dec, ftb, str) od_ec_dec_bits_(dec, ftb)
|
||||
#endif
|
||||
|
||||
/*The entropy decoder context.*/
|
||||
struct od_ec_dec {
|
||||
/*The start of the current input buffer.*/
|
||||
const unsigned char *buf;
|
||||
/*The read pointer for the raw bits.*/
|
||||
const unsigned char *eptr;
|
||||
/*Bits that will be read from/written at the end.*/
|
||||
od_ec_window end_window;
|
||||
/*Number of valid bits in end_window.*/
|
||||
int nend_bits;
|
||||
/*An offset used to keep track of tell after reaching the end of the stream.
|
||||
This is constant throughout most of the decoding process, but becomes
|
||||
important once we hit the end of the buffer and stop incrementing pointers
|
||||
(and instead pretend cnt/nend_bits have lots of bits).*/
|
||||
int32_t tell_offs;
|
||||
/*The end of the current input buffer.*/
|
||||
const unsigned char *end;
|
||||
/*The read pointer for the entropy-coded bits.*/
|
||||
const unsigned char *bptr;
|
||||
/*The difference between the coded value and the low end of the current
|
||||
range.
|
||||
{EC_SMALLMUL} The difference between the high end of the current range,
|
||||
(low + rng), and the coded value, minus 1.
|
||||
This stores up to OD_EC_WINDOW_SIZE bits of that difference, but the
|
||||
decoder only uses the top 16 bits of the window to decode the next symbol.
|
||||
As we shift up during renormalization, if we don't have enough bits left in
|
||||
the window to fill the top 16, we'll read in more bits of the coded
|
||||
value.*/
|
||||
od_ec_window dif;
|
||||
/*The number of values in the current range.*/
|
||||
uint16_t rng;
|
||||
/*The number of bits of data in the current value.*/
|
||||
int16_t cnt;
|
||||
/*Nonzero if an error occurred.*/
|
||||
int error;
|
||||
};
|
||||
|
||||
/*See entdec.c for further documentation.*/
|
||||
|
||||
void od_ec_dec_init(od_ec_dec *dec, const unsigned char *buf, uint32_t storage)
|
||||
OD_ARG_NONNULL(1) OD_ARG_NONNULL(2);
|
||||
|
||||
OD_WARN_UNUSED_RESULT int od_ec_decode_bool_q15(od_ec_dec *dec, unsigned f)
|
||||
OD_ARG_NONNULL(1);
|
||||
OD_WARN_UNUSED_RESULT int od_ec_decode_cdf_q15(od_ec_dec *dec,
|
||||
const uint16_t *cdf, int nsyms)
|
||||
OD_ARG_NONNULL(1) OD_ARG_NONNULL(2);
|
||||
|
||||
OD_WARN_UNUSED_RESULT uint32_t od_ec_dec_bits_(od_ec_dec *dec, unsigned ftb)
|
||||
OD_ARG_NONNULL(1);
|
||||
|
||||
OD_WARN_UNUSED_RESULT int od_ec_dec_tell(const od_ec_dec *dec)
|
||||
OD_ARG_NONNULL(1);
|
||||
OD_WARN_UNUSED_RESULT uint32_t od_ec_dec_tell_frac(const od_ec_dec *dec)
|
||||
OD_ARG_NONNULL(1);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
507
third_party/aom/aom_dsp/entenc.c
vendored
Normal file
507
third_party/aom/aom_dsp/entenc.c
vendored
Normal file
|
|
@ -0,0 +1,507 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "./config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "aom_dsp/entenc.h"
|
||||
|
||||
/*A range encoder.
|
||||
See entdec.c and the references for implementation details \cite{Mar79,MNW98}.
|
||||
|
||||
@INPROCEEDINGS{Mar79,
|
||||
author="Martin, G.N.N.",
|
||||
title="Range encoding: an algorithm for removing redundancy from a digitised
|
||||
message",
|
||||
booktitle="Video \& Data Recording Conference",
|
||||
year=1979,
|
||||
address="Southampton",
|
||||
month=Jul,
|
||||
URL="http://www.compressconsult.com/rangecoder/rngcod.pdf.gz"
|
||||
}
|
||||
@ARTICLE{MNW98,
|
||||
author="Alistair Moffat and Radford Neal and Ian H. Witten",
|
||||
title="Arithmetic Coding Revisited",
|
||||
journal="{ACM} Transactions on Information Systems",
|
||||
year=1998,
|
||||
volume=16,
|
||||
number=3,
|
||||
pages="256--294",
|
||||
month=Jul,
|
||||
URL="http://researchcommons.waikato.ac.nz/bitstream/handle/10289/78/content.pdf"
|
||||
}*/
|
||||
|
||||
/*Takes updated low and range values, renormalizes them so that
|
||||
32768 <= rng < 65536 (flushing bytes from low to the pre-carry buffer if
|
||||
necessary), and stores them back in the encoder context.
|
||||
low: The new value of low.
|
||||
rng: The new value of the range.*/
|
||||
static void od_ec_enc_normalize(od_ec_enc *enc, od_ec_window low,
|
||||
unsigned rng) {
|
||||
int d;
|
||||
int c;
|
||||
int s;
|
||||
c = enc->cnt;
|
||||
OD_ASSERT(rng <= 65535U);
|
||||
d = 16 - OD_ILOG_NZ(rng);
|
||||
s = c + d;
|
||||
/*TODO: Right now we flush every time we have at least one byte available.
|
||||
Instead we should use an od_ec_window and flush right before we're about to
|
||||
shift bits off the end of the window.
|
||||
For a 32-bit window this is about the same amount of work, but for a 64-bit
|
||||
window it should be a fair win.*/
|
||||
if (s >= 0) {
|
||||
uint16_t *buf;
|
||||
uint32_t storage;
|
||||
uint32_t offs;
|
||||
unsigned m;
|
||||
buf = enc->precarry_buf;
|
||||
storage = enc->precarry_storage;
|
||||
offs = enc->offs;
|
||||
if (offs + 2 > storage) {
|
||||
storage = 2 * storage + 2;
|
||||
buf = (uint16_t *)realloc(buf, sizeof(*buf) * storage);
|
||||
if (buf == NULL) {
|
||||
enc->error = -1;
|
||||
enc->offs = 0;
|
||||
return;
|
||||
}
|
||||
enc->precarry_buf = buf;
|
||||
enc->precarry_storage = storage;
|
||||
}
|
||||
c += 16;
|
||||
m = (1 << c) - 1;
|
||||
if (s >= 8) {
|
||||
OD_ASSERT(offs < storage);
|
||||
buf[offs++] = (uint16_t)(low >> c);
|
||||
low &= m;
|
||||
c -= 8;
|
||||
m >>= 8;
|
||||
}
|
||||
OD_ASSERT(offs < storage);
|
||||
buf[offs++] = (uint16_t)(low >> c);
|
||||
s = c + d - 24;
|
||||
low &= m;
|
||||
enc->offs = offs;
|
||||
}
|
||||
enc->low = low << d;
|
||||
enc->rng = rng << d;
|
||||
enc->cnt = s;
|
||||
}
|
||||
|
||||
/*Initializes the encoder.
|
||||
size: The initial size of the buffer, in bytes.*/
|
||||
void od_ec_enc_init(od_ec_enc *enc, uint32_t size) {
|
||||
od_ec_enc_reset(enc);
|
||||
enc->buf = (unsigned char *)malloc(sizeof(*enc->buf) * size);
|
||||
enc->storage = size;
|
||||
if (size > 0 && enc->buf == NULL) {
|
||||
enc->storage = 0;
|
||||
enc->error = -1;
|
||||
}
|
||||
enc->precarry_buf = (uint16_t *)malloc(sizeof(*enc->precarry_buf) * size);
|
||||
enc->precarry_storage = size;
|
||||
if (size > 0 && enc->precarry_buf == NULL) {
|
||||
enc->precarry_storage = 0;
|
||||
enc->error = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*Reinitializes the encoder.*/
|
||||
void od_ec_enc_reset(od_ec_enc *enc) {
|
||||
enc->end_offs = 0;
|
||||
enc->end_window = 0;
|
||||
enc->nend_bits = 0;
|
||||
enc->offs = 0;
|
||||
enc->low = 0;
|
||||
enc->rng = 0x8000;
|
||||
/*This is initialized to -9 so that it crosses zero after we've accumulated
|
||||
one byte + one carry bit.*/
|
||||
enc->cnt = -9;
|
||||
enc->error = 0;
|
||||
#if OD_MEASURE_EC_OVERHEAD
|
||||
enc->entropy = 0;
|
||||
enc->nb_symbols = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*Frees the buffers used by the encoder.*/
|
||||
void od_ec_enc_clear(od_ec_enc *enc) {
|
||||
free(enc->precarry_buf);
|
||||
free(enc->buf);
|
||||
}
|
||||
|
||||
/*Encodes a symbol given its frequency in Q15.
|
||||
fl: The cumulative frequency of all symbols that come before the one to be
|
||||
encoded.
|
||||
fh: The cumulative frequency of all symbols up to and including the one to
|
||||
be encoded.
|
||||
{EC_SMALLMUL} Both values are 32768 minus that.*/
|
||||
static void od_ec_encode_q15(od_ec_enc *enc, unsigned fl, unsigned fh) {
|
||||
od_ec_window l;
|
||||
unsigned r;
|
||||
unsigned u;
|
||||
unsigned v;
|
||||
l = enc->low;
|
||||
r = enc->rng;
|
||||
OD_ASSERT(32768U <= r);
|
||||
#if CONFIG_EC_SMALLMUL
|
||||
OD_ASSERT(fh < fl);
|
||||
OD_ASSERT(fl <= 32768U);
|
||||
if (fl < 32768U) {
|
||||
u = (r >> 8) * (uint32_t)fl >> 7;
|
||||
v = (r >> 8) * (uint32_t)fh >> 7;
|
||||
l += r - u;
|
||||
r = u - v;
|
||||
} else {
|
||||
r -= (r >> 8) * (uint32_t)fh >> 7;
|
||||
}
|
||||
#else
|
||||
OD_ASSERT(fl < fh);
|
||||
OD_ASSERT(fh <= 32768U);
|
||||
u = fl * (uint32_t)r >> 15;
|
||||
v = fh * (uint32_t)r >> 15;
|
||||
r = v - u;
|
||||
l += u;
|
||||
#endif
|
||||
od_ec_enc_normalize(enc, l, r);
|
||||
#if OD_MEASURE_EC_OVERHEAD
|
||||
enc->entropy -= OD_LOG2((double)(OD_ICDF(fh) - OD_ICDF(fl)) / 32768.);
|
||||
enc->nb_symbols++;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*Encode a single binary value.
|
||||
val: The value to encode (0 or 1).
|
||||
{EC_SMALLMUL} f: The probability that the val is one, scaled by 32768.
|
||||
{else} f: The probability that val is zero, scaled by 32768.*/
|
||||
void od_ec_encode_bool_q15(od_ec_enc *enc, int val, unsigned f) {
|
||||
od_ec_window l;
|
||||
unsigned r;
|
||||
unsigned v;
|
||||
OD_ASSERT(0 < f);
|
||||
OD_ASSERT(f < 32768U);
|
||||
l = enc->low;
|
||||
r = enc->rng;
|
||||
OD_ASSERT(32768U <= r);
|
||||
#if CONFIG_EC_SMALLMUL
|
||||
v = (r >> 8) * (uint32_t)f >> 7;
|
||||
if (val) l += r - v;
|
||||
r = val ? v : r - v;
|
||||
#else
|
||||
v = f * (uint32_t)r >> 15;
|
||||
if (val) l += v;
|
||||
r = val ? r - v : v;
|
||||
#endif
|
||||
od_ec_enc_normalize(enc, l, r);
|
||||
#if OD_MEASURE_EC_OVERHEAD
|
||||
enc->entropy -=
|
||||
OD_LOG2((double)(val ? 32768 - OD_ICDF(f) : OD_ICDF(f)) / 32768.);
|
||||
enc->nb_symbols++;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*Encodes a symbol given a cumulative distribution function (CDF) table in Q15.
|
||||
s: The index of the symbol to encode.
|
||||
cdf: The CDF, such that symbol s falls in the range
|
||||
[s > 0 ? cdf[s - 1] : 0, cdf[s]).
|
||||
The values must be monotonically non-decreasing, and the last value
|
||||
must be exactly 32768.
|
||||
nsyms: The number of symbols in the alphabet.
|
||||
This should be at most 16.*/
|
||||
void od_ec_encode_cdf_q15(od_ec_enc *enc, int s, const uint16_t *cdf,
|
||||
int nsyms) {
|
||||
(void)nsyms;
|
||||
OD_ASSERT(s >= 0);
|
||||
OD_ASSERT(s < nsyms);
|
||||
OD_ASSERT(cdf[nsyms - 1] == OD_ICDF(32768U));
|
||||
od_ec_encode_q15(enc, s > 0 ? cdf[s - 1] : OD_ICDF(0), cdf[s]);
|
||||
}
|
||||
|
||||
#if CONFIG_RAWBITS
|
||||
/*Encodes a sequence of raw bits in the stream.
|
||||
fl: The bits to encode.
|
||||
ftb: The number of bits to encode.
|
||||
This must be between 0 and 25, inclusive.*/
|
||||
void od_ec_enc_bits(od_ec_enc *enc, uint32_t fl, unsigned ftb) {
|
||||
od_ec_window end_window;
|
||||
int nend_bits;
|
||||
OD_ASSERT(ftb <= 25);
|
||||
OD_ASSERT(fl < (uint32_t)1 << ftb);
|
||||
#if OD_MEASURE_EC_OVERHEAD
|
||||
enc->entropy += ftb;
|
||||
#endif
|
||||
end_window = enc->end_window;
|
||||
nend_bits = enc->nend_bits;
|
||||
if (nend_bits + ftb > OD_EC_WINDOW_SIZE) {
|
||||
unsigned char *buf;
|
||||
uint32_t storage;
|
||||
uint32_t end_offs;
|
||||
buf = enc->buf;
|
||||
storage = enc->storage;
|
||||
end_offs = enc->end_offs;
|
||||
if (end_offs + (OD_EC_WINDOW_SIZE >> 3) >= storage) {
|
||||
unsigned char *new_buf;
|
||||
uint32_t new_storage;
|
||||
new_storage = 2 * storage + (OD_EC_WINDOW_SIZE >> 3);
|
||||
new_buf = (unsigned char *)malloc(sizeof(*new_buf) * new_storage);
|
||||
if (new_buf == NULL) {
|
||||
enc->error = -1;
|
||||
enc->end_offs = 0;
|
||||
return;
|
||||
}
|
||||
OD_COPY(new_buf + new_storage - end_offs, buf + storage - end_offs,
|
||||
end_offs);
|
||||
storage = new_storage;
|
||||
free(buf);
|
||||
enc->buf = buf = new_buf;
|
||||
enc->storage = storage;
|
||||
}
|
||||
do {
|
||||
OD_ASSERT(end_offs < storage);
|
||||
buf[storage - ++end_offs] = (unsigned char)end_window;
|
||||
end_window >>= 8;
|
||||
nend_bits -= 8;
|
||||
} while (nend_bits >= 8);
|
||||
enc->end_offs = end_offs;
|
||||
}
|
||||
OD_ASSERT(nend_bits + ftb <= OD_EC_WINDOW_SIZE);
|
||||
end_window |= (od_ec_window)fl << nend_bits;
|
||||
nend_bits += ftb;
|
||||
enc->end_window = end_window;
|
||||
enc->nend_bits = nend_bits;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*Overwrites a few bits at the very start of an existing stream, after they
|
||||
have already been encoded.
|
||||
This makes it possible to have a few flags up front, where it is easy for
|
||||
decoders to access them without parsing the whole stream, even if their
|
||||
values are not determined until late in the encoding process, without having
|
||||
to buffer all the intermediate symbols in the encoder.
|
||||
In order for this to work, at least nbits bits must have already been encoded
|
||||
using probabilities that are an exact power of two.
|
||||
The encoder can verify the number of encoded bits is sufficient, but cannot
|
||||
check this latter condition.
|
||||
val: The bits to encode (in the least nbits significant bits).
|
||||
They will be decoded in order from most-significant to least.
|
||||
nbits: The number of bits to overwrite.
|
||||
This must be no more than 8.*/
|
||||
void od_ec_enc_patch_initial_bits(od_ec_enc *enc, unsigned val, int nbits) {
|
||||
int shift;
|
||||
unsigned mask;
|
||||
OD_ASSERT(nbits >= 0);
|
||||
OD_ASSERT(nbits <= 8);
|
||||
OD_ASSERT(val < 1U << nbits);
|
||||
shift = 8 - nbits;
|
||||
mask = ((1U << nbits) - 1) << shift;
|
||||
if (enc->offs > 0) {
|
||||
/*The first byte has been finalized.*/
|
||||
enc->precarry_buf[0] =
|
||||
(uint16_t)((enc->precarry_buf[0] & ~mask) | val << shift);
|
||||
} else if (9 + enc->cnt + (enc->rng == 0x8000) > nbits) {
|
||||
/*The first byte has yet to be output.*/
|
||||
enc->low = (enc->low & ~((od_ec_window)mask << (16 + enc->cnt))) |
|
||||
(od_ec_window)val << (16 + enc->cnt + shift);
|
||||
} else {
|
||||
/*The encoder hasn't even encoded _nbits of data yet.*/
|
||||
enc->error = -1;
|
||||
}
|
||||
}
|
||||
|
||||
#if OD_MEASURE_EC_OVERHEAD
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
/*Indicates that there are no more symbols to encode.
|
||||
All remaining output bytes are flushed to the output buffer.
|
||||
od_ec_enc_reset() should be called before using the encoder again.
|
||||
bytes: Returns the size of the encoded data in the returned buffer.
|
||||
Return: A pointer to the start of the final buffer, or NULL if there was an
|
||||
encoding error.*/
|
||||
unsigned char *od_ec_enc_done(od_ec_enc *enc, uint32_t *nbytes) {
|
||||
unsigned char *out;
|
||||
uint32_t storage;
|
||||
uint16_t *buf;
|
||||
uint32_t offs;
|
||||
uint32_t end_offs;
|
||||
int nend_bits;
|
||||
od_ec_window m;
|
||||
od_ec_window e;
|
||||
od_ec_window l;
|
||||
unsigned r;
|
||||
int c;
|
||||
int s;
|
||||
if (enc->error) return NULL;
|
||||
#if OD_MEASURE_EC_OVERHEAD
|
||||
{
|
||||
uint32_t tell;
|
||||
/* Don't count the 1 bit we lose to raw bits as overhead. */
|
||||
tell = od_ec_enc_tell(enc) - 1;
|
||||
fprintf(stderr, "overhead: %f%%\n",
|
||||
100 * (tell - enc->entropy) / enc->entropy);
|
||||
fprintf(stderr, "efficiency: %f bits/symbol\n",
|
||||
(double)tell / enc->nb_symbols);
|
||||
}
|
||||
#endif
|
||||
/*We output the minimum number of bits that ensures that the symbols encoded
|
||||
thus far will be decoded correctly regardless of the bits that follow.*/
|
||||
l = enc->low;
|
||||
r = enc->rng;
|
||||
c = enc->cnt;
|
||||
s = 9;
|
||||
m = 0x7FFF;
|
||||
e = (l + m) & ~m;
|
||||
while ((e | m) >= l + r) {
|
||||
s++;
|
||||
m >>= 1;
|
||||
e = (l + m) & ~m;
|
||||
}
|
||||
s += c;
|
||||
offs = enc->offs;
|
||||
buf = enc->precarry_buf;
|
||||
if (s > 0) {
|
||||
unsigned n;
|
||||
storage = enc->precarry_storage;
|
||||
if (offs + ((s + 7) >> 3) > storage) {
|
||||
storage = storage * 2 + ((s + 7) >> 3);
|
||||
buf = (uint16_t *)realloc(buf, sizeof(*buf) * storage);
|
||||
if (buf == NULL) {
|
||||
enc->error = -1;
|
||||
return NULL;
|
||||
}
|
||||
enc->precarry_buf = buf;
|
||||
enc->precarry_storage = storage;
|
||||
}
|
||||
n = (1 << (c + 16)) - 1;
|
||||
do {
|
||||
OD_ASSERT(offs < storage);
|
||||
buf[offs++] = (uint16_t)(e >> (c + 16));
|
||||
e &= n;
|
||||
s -= 8;
|
||||
c -= 8;
|
||||
n >>= 8;
|
||||
} while (s > 0);
|
||||
}
|
||||
/*Make sure there's enough room for the entropy-coded bits and the raw
|
||||
bits.*/
|
||||
out = enc->buf;
|
||||
storage = enc->storage;
|
||||
end_offs = enc->end_offs;
|
||||
e = enc->end_window;
|
||||
nend_bits = enc->nend_bits;
|
||||
s = -s;
|
||||
c = OD_MAXI((nend_bits - s + 7) >> 3, 0);
|
||||
if (offs + end_offs + c > storage) {
|
||||
storage = offs + end_offs + c;
|
||||
out = (unsigned char *)realloc(out, sizeof(*out) * storage);
|
||||
if (out == NULL) {
|
||||
enc->error = -1;
|
||||
return NULL;
|
||||
}
|
||||
OD_MOVE(out + storage - end_offs, out + enc->storage - end_offs, end_offs);
|
||||
enc->buf = out;
|
||||
enc->storage = storage;
|
||||
}
|
||||
/*If we have buffered raw bits, flush them as well.*/
|
||||
while (nend_bits > s) {
|
||||
OD_ASSERT(end_offs < storage);
|
||||
out[storage - ++end_offs] = (unsigned char)e;
|
||||
e >>= 8;
|
||||
nend_bits -= 8;
|
||||
}
|
||||
*nbytes = offs + end_offs;
|
||||
/*Perform carry propagation.*/
|
||||
OD_ASSERT(offs + end_offs <= storage);
|
||||
out = out + storage - (offs + end_offs);
|
||||
c = 0;
|
||||
end_offs = offs;
|
||||
while (offs > 0) {
|
||||
offs--;
|
||||
c = buf[offs] + c;
|
||||
out[offs] = (unsigned char)c;
|
||||
c >>= 8;
|
||||
}
|
||||
/*Add any remaining raw bits to the last byte.
|
||||
There is guaranteed to be enough room, because nend_bits <= s.*/
|
||||
OD_ASSERT(nend_bits <= 0 || end_offs > 0);
|
||||
if (nend_bits > 0) out[end_offs - 1] |= (unsigned char)e;
|
||||
/*Note: Unless there's an allocation error, if you keep encoding into the
|
||||
current buffer and call this function again later, everything will work
|
||||
just fine (you won't get a new packet out, but you will get a single
|
||||
buffer with the new data appended to the old).
|
||||
However, this function is O(N) where N is the amount of data coded so far,
|
||||
so calling it more than once for a given packet is a bad idea.*/
|
||||
return out;
|
||||
}
|
||||
|
||||
/*Returns the number of bits "used" by the encoded symbols so far.
|
||||
This same number can be computed in either the encoder or the decoder, and is
|
||||
suitable for making coding decisions.
|
||||
Warning: The value returned by this function can decrease compared to an
|
||||
earlier call, even after encoding more data, if there is an encoding error
|
||||
(i.e., a failure to allocate enough space for the output buffer).
|
||||
Return: The number of bits.
|
||||
This will always be slightly larger than the exact value (e.g., all
|
||||
rounding error is in the positive direction).*/
|
||||
int od_ec_enc_tell(const od_ec_enc *enc) {
|
||||
/*The 10 here counteracts the offset of -9 baked into cnt, and adds 1 extra
|
||||
bit, which we reserve for terminating the stream.*/
|
||||
return (enc->offs + enc->end_offs) * 8 + enc->cnt + enc->nend_bits + 10;
|
||||
}
|
||||
|
||||
/*Returns the number of bits "used" by the encoded symbols so far.
|
||||
This same number can be computed in either the encoder or the decoder, and is
|
||||
suitable for making coding decisions.
|
||||
Warning: The value returned by this function can decrease compared to an
|
||||
earlier call, even after encoding more data, if there is an encoding error
|
||||
(i.e., a failure to allocate enough space for the output buffer).
|
||||
Return: The number of bits scaled by 2**OD_BITRES.
|
||||
This will always be slightly larger than the exact value (e.g., all
|
||||
rounding error is in the positive direction).*/
|
||||
uint32_t od_ec_enc_tell_frac(const od_ec_enc *enc) {
|
||||
return od_ec_tell_frac(od_ec_enc_tell(enc), enc->rng);
|
||||
}
|
||||
|
||||
/*Saves a entropy coder checkpoint to dst.
|
||||
This allows an encoder to reverse a series of entropy coder
|
||||
decisions if it decides that the information would have been
|
||||
better coded some other way.*/
|
||||
void od_ec_enc_checkpoint(od_ec_enc *dst, const od_ec_enc *src) {
|
||||
OD_COPY(dst, src, 1);
|
||||
}
|
||||
|
||||
/*Restores an entropy coder checkpoint saved by od_ec_enc_checkpoint.
|
||||
This can only be used to restore from checkpoints earlier in the target
|
||||
state's history: you can not switch backwards and forwards or otherwise
|
||||
switch to a state which isn't a casual ancestor of the current state.
|
||||
Restore is also incompatible with patching the initial bits, as the
|
||||
changes will remain in the restored version.*/
|
||||
void od_ec_enc_rollback(od_ec_enc *dst, const od_ec_enc *src) {
|
||||
unsigned char *buf;
|
||||
uint32_t storage;
|
||||
uint16_t *precarry_buf;
|
||||
uint32_t precarry_storage;
|
||||
OD_ASSERT(dst->storage >= src->storage);
|
||||
OD_ASSERT(dst->precarry_storage >= src->precarry_storage);
|
||||
buf = dst->buf;
|
||||
storage = dst->storage;
|
||||
precarry_buf = dst->precarry_buf;
|
||||
precarry_storage = dst->precarry_storage;
|
||||
OD_COPY(dst, src, 1);
|
||||
dst->buf = buf;
|
||||
dst->storage = storage;
|
||||
dst->precarry_buf = precarry_buf;
|
||||
dst->precarry_storage = precarry_storage;
|
||||
}
|
||||
91
third_party/aom/aom_dsp/entenc.h
vendored
Normal file
91
third_party/aom/aom_dsp/entenc.h
vendored
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#if !defined(_entenc_H)
|
||||
#define _entenc_H (1)
|
||||
#include <stddef.h>
|
||||
#include "aom_dsp/entcode.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct od_ec_enc od_ec_enc;
|
||||
|
||||
#define OD_MEASURE_EC_OVERHEAD (0)
|
||||
|
||||
/*The entropy encoder context.*/
|
||||
struct od_ec_enc {
|
||||
/*Buffered output.
|
||||
This contains only the raw bits until the final call to od_ec_enc_done(),
|
||||
where all the arithmetic-coded data gets prepended to it.*/
|
||||
unsigned char *buf;
|
||||
/*The size of the buffer.*/
|
||||
uint32_t storage;
|
||||
/*The offset at which the last byte containing raw bits was written.*/
|
||||
uint32_t end_offs;
|
||||
/*Bits that will be read from/written at the end.*/
|
||||
od_ec_window end_window;
|
||||
/*Number of valid bits in end_window.*/
|
||||
int nend_bits;
|
||||
/*A buffer for output bytes with their associated carry flags.*/
|
||||
uint16_t *precarry_buf;
|
||||
/*The size of the pre-carry buffer.*/
|
||||
uint32_t precarry_storage;
|
||||
/*The offset at which the next entropy-coded byte will be written.*/
|
||||
uint32_t offs;
|
||||
/*The low end of the current range.*/
|
||||
od_ec_window low;
|
||||
/*The number of values in the current range.*/
|
||||
uint16_t rng;
|
||||
/*The number of bits of data in the current value.*/
|
||||
int16_t cnt;
|
||||
/*Nonzero if an error occurred.*/
|
||||
int error;
|
||||
#if OD_MEASURE_EC_OVERHEAD
|
||||
double entropy;
|
||||
int nb_symbols;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*See entenc.c for further documentation.*/
|
||||
|
||||
void od_ec_enc_init(od_ec_enc *enc, uint32_t size) OD_ARG_NONNULL(1);
|
||||
void od_ec_enc_reset(od_ec_enc *enc) OD_ARG_NONNULL(1);
|
||||
void od_ec_enc_clear(od_ec_enc *enc) OD_ARG_NONNULL(1);
|
||||
|
||||
void od_ec_encode_bool_q15(od_ec_enc *enc, int val, unsigned f_q15)
|
||||
OD_ARG_NONNULL(1);
|
||||
void od_ec_encode_cdf_q15(od_ec_enc *enc, int s, const uint16_t *cdf, int nsyms)
|
||||
OD_ARG_NONNULL(1) OD_ARG_NONNULL(3);
|
||||
|
||||
void od_ec_enc_bits(od_ec_enc *enc, uint32_t fl, unsigned ftb)
|
||||
OD_ARG_NONNULL(1);
|
||||
|
||||
void od_ec_enc_patch_initial_bits(od_ec_enc *enc, unsigned val, int nbits)
|
||||
OD_ARG_NONNULL(1);
|
||||
OD_WARN_UNUSED_RESULT unsigned char *od_ec_enc_done(od_ec_enc *enc,
|
||||
uint32_t *nbytes)
|
||||
OD_ARG_NONNULL(1) OD_ARG_NONNULL(2);
|
||||
|
||||
OD_WARN_UNUSED_RESULT int od_ec_enc_tell(const od_ec_enc *enc)
|
||||
OD_ARG_NONNULL(1);
|
||||
OD_WARN_UNUSED_RESULT uint32_t od_ec_enc_tell_frac(const od_ec_enc *enc)
|
||||
OD_ARG_NONNULL(1);
|
||||
|
||||
void od_ec_enc_checkpoint(od_ec_enc *dst, const od_ec_enc *src);
|
||||
void od_ec_enc_rollback(od_ec_enc *dst, const od_ec_enc *src);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
493
third_party/aom/aom_dsp/fastssim.c
vendored
Normal file
493
third_party/aom/aom_dsp/fastssim.c
vendored
Normal file
|
|
@ -0,0 +1,493 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*
|
||||
* This code was originally written by: Nathan E. Egge, at the Daala
|
||||
* project.
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "./aom_config.h"
|
||||
#include "./aom_dsp_rtcd.h"
|
||||
#include "aom_dsp/ssim.h"
|
||||
#include "aom_ports/system_state.h"
|
||||
|
||||
typedef struct fs_level fs_level;
|
||||
typedef struct fs_ctx fs_ctx;
|
||||
|
||||
#define SSIM_C1 (255 * 255 * 0.01 * 0.01)
|
||||
#define SSIM_C2 (255 * 255 * 0.03 * 0.03)
|
||||
#if CONFIG_HIGHBITDEPTH
|
||||
#define SSIM_C1_10 (1023 * 1023 * 0.01 * 0.01)
|
||||
#define SSIM_C1_12 (4095 * 4095 * 0.01 * 0.01)
|
||||
#define SSIM_C2_10 (1023 * 1023 * 0.03 * 0.03)
|
||||
#define SSIM_C2_12 (4095 * 4095 * 0.03 * 0.03)
|
||||
#endif
|
||||
#define FS_MINI(_a, _b) ((_a) < (_b) ? (_a) : (_b))
|
||||
#define FS_MAXI(_a, _b) ((_a) > (_b) ? (_a) : (_b))
|
||||
|
||||
struct fs_level {
|
||||
uint32_t *im1;
|
||||
uint32_t *im2;
|
||||
double *ssim;
|
||||
int w;
|
||||
int h;
|
||||
};
|
||||
|
||||
struct fs_ctx {
|
||||
fs_level *level;
|
||||
int nlevels;
|
||||
unsigned *col_buf;
|
||||
};
|
||||
|
||||
static void fs_ctx_init(fs_ctx *_ctx, int _w, int _h, int _nlevels) {
|
||||
unsigned char *data;
|
||||
size_t data_size;
|
||||
int lw;
|
||||
int lh;
|
||||
int l;
|
||||
lw = (_w + 1) >> 1;
|
||||
lh = (_h + 1) >> 1;
|
||||
data_size =
|
||||
_nlevels * sizeof(fs_level) + 2 * (lw + 8) * 8 * sizeof(*_ctx->col_buf);
|
||||
for (l = 0; l < _nlevels; l++) {
|
||||
size_t im_size;
|
||||
size_t level_size;
|
||||
im_size = lw * (size_t)lh;
|
||||
level_size = 2 * im_size * sizeof(*_ctx->level[l].im1);
|
||||
level_size += sizeof(*_ctx->level[l].ssim) - 1;
|
||||
level_size /= sizeof(*_ctx->level[l].ssim);
|
||||
level_size += im_size;
|
||||
level_size *= sizeof(*_ctx->level[l].ssim);
|
||||
data_size += level_size;
|
||||
lw = (lw + 1) >> 1;
|
||||
lh = (lh + 1) >> 1;
|
||||
}
|
||||
data = (unsigned char *)malloc(data_size);
|
||||
_ctx->level = (fs_level *)data;
|
||||
_ctx->nlevels = _nlevels;
|
||||
data += _nlevels * sizeof(*_ctx->level);
|
||||
lw = (_w + 1) >> 1;
|
||||
lh = (_h + 1) >> 1;
|
||||
for (l = 0; l < _nlevels; l++) {
|
||||
size_t im_size;
|
||||
size_t level_size;
|
||||
_ctx->level[l].w = lw;
|
||||
_ctx->level[l].h = lh;
|
||||
im_size = lw * (size_t)lh;
|
||||
level_size = 2 * im_size * sizeof(*_ctx->level[l].im1);
|
||||
level_size += sizeof(*_ctx->level[l].ssim) - 1;
|
||||
level_size /= sizeof(*_ctx->level[l].ssim);
|
||||
level_size *= sizeof(*_ctx->level[l].ssim);
|
||||
_ctx->level[l].im1 = (uint32_t *)data;
|
||||
_ctx->level[l].im2 = _ctx->level[l].im1 + im_size;
|
||||
data += level_size;
|
||||
_ctx->level[l].ssim = (double *)data;
|
||||
data += im_size * sizeof(*_ctx->level[l].ssim);
|
||||
lw = (lw + 1) >> 1;
|
||||
lh = (lh + 1) >> 1;
|
||||
}
|
||||
_ctx->col_buf = (unsigned *)data;
|
||||
}
|
||||
|
||||
static void fs_ctx_clear(fs_ctx *_ctx) { free(_ctx->level); }
|
||||
|
||||
static void fs_downsample_level(fs_ctx *_ctx, int _l) {
|
||||
const uint32_t *src1;
|
||||
const uint32_t *src2;
|
||||
uint32_t *dst1;
|
||||
uint32_t *dst2;
|
||||
int w2;
|
||||
int h2;
|
||||
int w;
|
||||
int h;
|
||||
int i;
|
||||
int j;
|
||||
w = _ctx->level[_l].w;
|
||||
h = _ctx->level[_l].h;
|
||||
dst1 = _ctx->level[_l].im1;
|
||||
dst2 = _ctx->level[_l].im2;
|
||||
w2 = _ctx->level[_l - 1].w;
|
||||
h2 = _ctx->level[_l - 1].h;
|
||||
src1 = _ctx->level[_l - 1].im1;
|
||||
src2 = _ctx->level[_l - 1].im2;
|
||||
for (j = 0; j < h; j++) {
|
||||
int j0offs;
|
||||
int j1offs;
|
||||
j0offs = 2 * j * w2;
|
||||
j1offs = FS_MINI(2 * j + 1, h2) * w2;
|
||||
for (i = 0; i < w; i++) {
|
||||
int i0;
|
||||
int i1;
|
||||
i0 = 2 * i;
|
||||
i1 = FS_MINI(i0 + 1, w2);
|
||||
dst1[j * w + i] = src1[j0offs + i0] + src1[j0offs + i1] +
|
||||
src1[j1offs + i0] + src1[j1offs + i1];
|
||||
dst2[j * w + i] = src2[j0offs + i0] + src2[j0offs + i1] +
|
||||
src2[j1offs + i0] + src2[j1offs + i1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void fs_downsample_level0(fs_ctx *_ctx, const uint8_t *_src1,
|
||||
int _s1ystride, const uint8_t *_src2,
|
||||
int _s2ystride, int _w, int _h, uint32_t bd,
|
||||
uint32_t shift) {
|
||||
uint32_t *dst1;
|
||||
uint32_t *dst2;
|
||||
int w;
|
||||
int h;
|
||||
int i;
|
||||
int j;
|
||||
w = _ctx->level[0].w;
|
||||
h = _ctx->level[0].h;
|
||||
dst1 = _ctx->level[0].im1;
|
||||
dst2 = _ctx->level[0].im2;
|
||||
for (j = 0; j < h; j++) {
|
||||
int j0;
|
||||
int j1;
|
||||
j0 = 2 * j;
|
||||
j1 = FS_MINI(j0 + 1, _h);
|
||||
for (i = 0; i < w; i++) {
|
||||
int i0;
|
||||
int i1;
|
||||
i0 = 2 * i;
|
||||
i1 = FS_MINI(i0 + 1, _w);
|
||||
if (bd == 8 && shift == 0) {
|
||||
dst1[j * w + i] =
|
||||
_src1[j0 * _s1ystride + i0] + _src1[j0 * _s1ystride + i1] +
|
||||
_src1[j1 * _s1ystride + i0] + _src1[j1 * _s1ystride + i1];
|
||||
dst2[j * w + i] =
|
||||
_src2[j0 * _s2ystride + i0] + _src2[j0 * _s2ystride + i1] +
|
||||
_src2[j1 * _s2ystride + i0] + _src2[j1 * _s2ystride + i1];
|
||||
} else {
|
||||
uint16_t *src1s = CONVERT_TO_SHORTPTR(_src1);
|
||||
uint16_t *src2s = CONVERT_TO_SHORTPTR(_src2);
|
||||
dst1[j * w + i] = (src1s[j0 * _s1ystride + i0] >> shift) +
|
||||
(src1s[j0 * _s1ystride + i1] >> shift) +
|
||||
(src1s[j1 * _s1ystride + i0] >> shift) +
|
||||
(src1s[j1 * _s1ystride + i1] >> shift);
|
||||
dst2[j * w + i] = (src2s[j0 * _s2ystride + i0] >> shift) +
|
||||
(src2s[j0 * _s2ystride + i1] >> shift) +
|
||||
(src2s[j1 * _s2ystride + i0] >> shift) +
|
||||
(src2s[j1 * _s2ystride + i1] >> shift);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void fs_apply_luminance(fs_ctx *_ctx, int _l, int bit_depth) {
|
||||
unsigned *col_sums_x;
|
||||
unsigned *col_sums_y;
|
||||
uint32_t *im1;
|
||||
uint32_t *im2;
|
||||
double *ssim;
|
||||
double c1;
|
||||
int w;
|
||||
int h;
|
||||
int j0offs;
|
||||
int j1offs;
|
||||
int i;
|
||||
int j;
|
||||
double ssim_c1 = SSIM_C1;
|
||||
#if CONFIG_HIGHBITDEPTH
|
||||
if (bit_depth == 10) ssim_c1 = SSIM_C1_10;
|
||||
if (bit_depth == 12) ssim_c1 = SSIM_C1_12;
|
||||
#else
|
||||
assert(bit_depth == 8);
|
||||
(void)bit_depth;
|
||||
#endif
|
||||
w = _ctx->level[_l].w;
|
||||
h = _ctx->level[_l].h;
|
||||
col_sums_x = _ctx->col_buf;
|
||||
col_sums_y = col_sums_x + w;
|
||||
im1 = _ctx->level[_l].im1;
|
||||
im2 = _ctx->level[_l].im2;
|
||||
for (i = 0; i < w; i++) col_sums_x[i] = 5 * im1[i];
|
||||
for (i = 0; i < w; i++) col_sums_y[i] = 5 * im2[i];
|
||||
for (j = 1; j < 4; j++) {
|
||||
j1offs = FS_MINI(j, h - 1) * w;
|
||||
for (i = 0; i < w; i++) col_sums_x[i] += im1[j1offs + i];
|
||||
for (i = 0; i < w; i++) col_sums_y[i] += im2[j1offs + i];
|
||||
}
|
||||
ssim = _ctx->level[_l].ssim;
|
||||
c1 = (double)(ssim_c1 * 4096 * (1 << 4 * _l));
|
||||
for (j = 0; j < h; j++) {
|
||||
unsigned mux;
|
||||
unsigned muy;
|
||||
int i0;
|
||||
int i1;
|
||||
mux = 5 * col_sums_x[0];
|
||||
muy = 5 * col_sums_y[0];
|
||||
for (i = 1; i < 4; i++) {
|
||||
i1 = FS_MINI(i, w - 1);
|
||||
mux += col_sums_x[i1];
|
||||
muy += col_sums_y[i1];
|
||||
}
|
||||
for (i = 0; i < w; i++) {
|
||||
ssim[j * w + i] *= (2 * mux * (double)muy + c1) /
|
||||
(mux * (double)mux + muy * (double)muy + c1);
|
||||
if (i + 1 < w) {
|
||||
i0 = FS_MAXI(0, i - 4);
|
||||
i1 = FS_MINI(i + 4, w - 1);
|
||||
mux += col_sums_x[i1] - col_sums_x[i0];
|
||||
muy += col_sums_x[i1] - col_sums_x[i0];
|
||||
}
|
||||
}
|
||||
if (j + 1 < h) {
|
||||
j0offs = FS_MAXI(0, j - 4) * w;
|
||||
for (i = 0; i < w; i++) col_sums_x[i] -= im1[j0offs + i];
|
||||
for (i = 0; i < w; i++) col_sums_y[i] -= im2[j0offs + i];
|
||||
j1offs = FS_MINI(j + 4, h - 1) * w;
|
||||
for (i = 0; i < w; i++) col_sums_x[i] += im1[j1offs + i];
|
||||
for (i = 0; i < w; i++) col_sums_y[i] += im2[j1offs + i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define FS_COL_SET(_col, _joffs, _ioffs) \
|
||||
do { \
|
||||
unsigned gx; \
|
||||
unsigned gy; \
|
||||
gx = gx_buf[((j + (_joffs)) & 7) * stride + i + (_ioffs)]; \
|
||||
gy = gy_buf[((j + (_joffs)) & 7) * stride + i + (_ioffs)]; \
|
||||
col_sums_gx2[(_col)] = gx * (double)gx; \
|
||||
col_sums_gy2[(_col)] = gy * (double)gy; \
|
||||
col_sums_gxgy[(_col)] = gx * (double)gy; \
|
||||
} while (0)
|
||||
|
||||
#define FS_COL_ADD(_col, _joffs, _ioffs) \
|
||||
do { \
|
||||
unsigned gx; \
|
||||
unsigned gy; \
|
||||
gx = gx_buf[((j + (_joffs)) & 7) * stride + i + (_ioffs)]; \
|
||||
gy = gy_buf[((j + (_joffs)) & 7) * stride + i + (_ioffs)]; \
|
||||
col_sums_gx2[(_col)] += gx * (double)gx; \
|
||||
col_sums_gy2[(_col)] += gy * (double)gy; \
|
||||
col_sums_gxgy[(_col)] += gx * (double)gy; \
|
||||
} while (0)
|
||||
|
||||
#define FS_COL_SUB(_col, _joffs, _ioffs) \
|
||||
do { \
|
||||
unsigned gx; \
|
||||
unsigned gy; \
|
||||
gx = gx_buf[((j + (_joffs)) & 7) * stride + i + (_ioffs)]; \
|
||||
gy = gy_buf[((j + (_joffs)) & 7) * stride + i + (_ioffs)]; \
|
||||
col_sums_gx2[(_col)] -= gx * (double)gx; \
|
||||
col_sums_gy2[(_col)] -= gy * (double)gy; \
|
||||
col_sums_gxgy[(_col)] -= gx * (double)gy; \
|
||||
} while (0)
|
||||
|
||||
#define FS_COL_COPY(_col1, _col2) \
|
||||
do { \
|
||||
col_sums_gx2[(_col1)] = col_sums_gx2[(_col2)]; \
|
||||
col_sums_gy2[(_col1)] = col_sums_gy2[(_col2)]; \
|
||||
col_sums_gxgy[(_col1)] = col_sums_gxgy[(_col2)]; \
|
||||
} while (0)
|
||||
|
||||
#define FS_COL_HALVE(_col1, _col2) \
|
||||
do { \
|
||||
col_sums_gx2[(_col1)] = col_sums_gx2[(_col2)] * 0.5; \
|
||||
col_sums_gy2[(_col1)] = col_sums_gy2[(_col2)] * 0.5; \
|
||||
col_sums_gxgy[(_col1)] = col_sums_gxgy[(_col2)] * 0.5; \
|
||||
} while (0)
|
||||
|
||||
#define FS_COL_DOUBLE(_col1, _col2) \
|
||||
do { \
|
||||
col_sums_gx2[(_col1)] = col_sums_gx2[(_col2)] * 2; \
|
||||
col_sums_gy2[(_col1)] = col_sums_gy2[(_col2)] * 2; \
|
||||
col_sums_gxgy[(_col1)] = col_sums_gxgy[(_col2)] * 2; \
|
||||
} while (0)
|
||||
|
||||
static void fs_calc_structure(fs_ctx *_ctx, int _l, int bit_depth) {
|
||||
uint32_t *im1;
|
||||
uint32_t *im2;
|
||||
unsigned *gx_buf;
|
||||
unsigned *gy_buf;
|
||||
double *ssim;
|
||||
double col_sums_gx2[8];
|
||||
double col_sums_gy2[8];
|
||||
double col_sums_gxgy[8];
|
||||
double c2;
|
||||
int stride;
|
||||
int w;
|
||||
int h;
|
||||
int i;
|
||||
int j;
|
||||
double ssim_c2 = SSIM_C2;
|
||||
#if CONFIG_HIGHBITDEPTH
|
||||
if (bit_depth == 10) ssim_c2 = SSIM_C2_10;
|
||||
if (bit_depth == 12) ssim_c2 = SSIM_C2_12;
|
||||
#else
|
||||
assert(bit_depth == 8);
|
||||
(void)bit_depth;
|
||||
#endif
|
||||
|
||||
w = _ctx->level[_l].w;
|
||||
h = _ctx->level[_l].h;
|
||||
im1 = _ctx->level[_l].im1;
|
||||
im2 = _ctx->level[_l].im2;
|
||||
ssim = _ctx->level[_l].ssim;
|
||||
gx_buf = _ctx->col_buf;
|
||||
stride = w + 8;
|
||||
gy_buf = gx_buf + 8 * stride;
|
||||
memset(gx_buf, 0, 2 * 8 * stride * sizeof(*gx_buf));
|
||||
c2 = ssim_c2 * (1 << 4 * _l) * 16 * 104;
|
||||
for (j = 0; j < h + 4; j++) {
|
||||
if (j < h - 1) {
|
||||
for (i = 0; i < w - 1; i++) {
|
||||
unsigned g1;
|
||||
unsigned g2;
|
||||
unsigned gx;
|
||||
unsigned gy;
|
||||
g1 = abs((int)im1[(j + 1) * w + i + 1] - (int)im1[j * w + i]);
|
||||
g2 = abs((int)im1[(j + 1) * w + i] - (int)im1[j * w + i + 1]);
|
||||
gx = 4 * FS_MAXI(g1, g2) + FS_MINI(g1, g2);
|
||||
g1 = abs((int)im2[(j + 1) * w + i + 1] - (int)im2[j * w + i]);
|
||||
g2 = abs((int)im2[(j + 1) * w + i] - (int)im2[j * w + i + 1]);
|
||||
gy = 4 * FS_MAXI(g1, g2) + FS_MINI(g1, g2);
|
||||
gx_buf[(j & 7) * stride + i + 4] = gx;
|
||||
gy_buf[(j & 7) * stride + i + 4] = gy;
|
||||
}
|
||||
} else {
|
||||
memset(gx_buf + (j & 7) * stride, 0, stride * sizeof(*gx_buf));
|
||||
memset(gy_buf + (j & 7) * stride, 0, stride * sizeof(*gy_buf));
|
||||
}
|
||||
if (j >= 4) {
|
||||
int k;
|
||||
col_sums_gx2[3] = col_sums_gx2[2] = col_sums_gx2[1] = col_sums_gx2[0] = 0;
|
||||
col_sums_gy2[3] = col_sums_gy2[2] = col_sums_gy2[1] = col_sums_gy2[0] = 0;
|
||||
col_sums_gxgy[3] = col_sums_gxgy[2] = col_sums_gxgy[1] =
|
||||
col_sums_gxgy[0] = 0;
|
||||
for (i = 4; i < 8; i++) {
|
||||
FS_COL_SET(i, -1, 0);
|
||||
FS_COL_ADD(i, 0, 0);
|
||||
for (k = 1; k < 8 - i; k++) {
|
||||
FS_COL_DOUBLE(i, i);
|
||||
FS_COL_ADD(i, -k - 1, 0);
|
||||
FS_COL_ADD(i, k, 0);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < w; i++) {
|
||||
double mugx2;
|
||||
double mugy2;
|
||||
double mugxgy;
|
||||
mugx2 = col_sums_gx2[0];
|
||||
for (k = 1; k < 8; k++) mugx2 += col_sums_gx2[k];
|
||||
mugy2 = col_sums_gy2[0];
|
||||
for (k = 1; k < 8; k++) mugy2 += col_sums_gy2[k];
|
||||
mugxgy = col_sums_gxgy[0];
|
||||
for (k = 1; k < 8; k++) mugxgy += col_sums_gxgy[k];
|
||||
ssim[(j - 4) * w + i] = (2 * mugxgy + c2) / (mugx2 + mugy2 + c2);
|
||||
if (i + 1 < w) {
|
||||
FS_COL_SET(0, -1, 1);
|
||||
FS_COL_ADD(0, 0, 1);
|
||||
FS_COL_SUB(2, -3, 2);
|
||||
FS_COL_SUB(2, 2, 2);
|
||||
FS_COL_HALVE(1, 2);
|
||||
FS_COL_SUB(3, -4, 3);
|
||||
FS_COL_SUB(3, 3, 3);
|
||||
FS_COL_HALVE(2, 3);
|
||||
FS_COL_COPY(3, 4);
|
||||
FS_COL_DOUBLE(4, 5);
|
||||
FS_COL_ADD(4, -4, 5);
|
||||
FS_COL_ADD(4, 3, 5);
|
||||
FS_COL_DOUBLE(5, 6);
|
||||
FS_COL_ADD(5, -3, 6);
|
||||
FS_COL_ADD(5, 2, 6);
|
||||
FS_COL_DOUBLE(6, 7);
|
||||
FS_COL_ADD(6, -2, 7);
|
||||
FS_COL_ADD(6, 1, 7);
|
||||
FS_COL_SET(7, -1, 8);
|
||||
FS_COL_ADD(7, 0, 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define FS_NLEVELS (4)
|
||||
|
||||
/*These weights were derived from the default weights found in Wang's original
|
||||
Matlab implementation: {0.0448, 0.2856, 0.2363, 0.1333}.
|
||||
We drop the finest scale and renormalize the rest to sum to 1.*/
|
||||
|
||||
static const double FS_WEIGHTS[FS_NLEVELS] = {
|
||||
0.2989654541015625, 0.3141326904296875, 0.2473602294921875, 0.1395416259765625
|
||||
};
|
||||
|
||||
static double fs_average(fs_ctx *_ctx, int _l) {
|
||||
double *ssim;
|
||||
double ret;
|
||||
int w;
|
||||
int h;
|
||||
int i;
|
||||
int j;
|
||||
w = _ctx->level[_l].w;
|
||||
h = _ctx->level[_l].h;
|
||||
ssim = _ctx->level[_l].ssim;
|
||||
ret = 0;
|
||||
for (j = 0; j < h; j++)
|
||||
for (i = 0; i < w; i++) ret += ssim[j * w + i];
|
||||
return pow(ret / (w * h), FS_WEIGHTS[_l]);
|
||||
}
|
||||
|
||||
static double convert_ssim_db(double _ssim, double _weight) {
|
||||
assert(_weight >= _ssim);
|
||||
if ((_weight - _ssim) < 1e-10) return MAX_SSIM_DB;
|
||||
return 10 * (log10(_weight) - log10(_weight - _ssim));
|
||||
}
|
||||
|
||||
static double calc_ssim(const uint8_t *_src, int _systride, const uint8_t *_dst,
|
||||
int _dystride, int _w, int _h, uint32_t _bd,
|
||||
uint32_t _shift) {
|
||||
fs_ctx ctx;
|
||||
double ret;
|
||||
int l;
|
||||
ret = 1;
|
||||
fs_ctx_init(&ctx, _w, _h, FS_NLEVELS);
|
||||
fs_downsample_level0(&ctx, _src, _systride, _dst, _dystride, _w, _h, _bd,
|
||||
_shift);
|
||||
for (l = 0; l < FS_NLEVELS - 1; l++) {
|
||||
fs_calc_structure(&ctx, l, _bd);
|
||||
ret *= fs_average(&ctx, l);
|
||||
fs_downsample_level(&ctx, l + 1);
|
||||
}
|
||||
fs_calc_structure(&ctx, l, _bd);
|
||||
fs_apply_luminance(&ctx, l, _bd);
|
||||
ret *= fs_average(&ctx, l);
|
||||
fs_ctx_clear(&ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
double aom_calc_fastssim(const YV12_BUFFER_CONFIG *source,
|
||||
const YV12_BUFFER_CONFIG *dest, double *ssim_y,
|
||||
double *ssim_u, double *ssim_v, uint32_t bd,
|
||||
uint32_t in_bd) {
|
||||
double ssimv;
|
||||
uint32_t bd_shift = 0;
|
||||
aom_clear_system_state();
|
||||
assert(bd >= in_bd);
|
||||
|
||||
bd_shift = bd - in_bd;
|
||||
|
||||
*ssim_y = calc_ssim(source->y_buffer, source->y_stride, dest->y_buffer,
|
||||
dest->y_stride, source->y_crop_width,
|
||||
source->y_crop_height, in_bd, bd_shift);
|
||||
*ssim_u = calc_ssim(source->u_buffer, source->uv_stride, dest->u_buffer,
|
||||
dest->uv_stride, source->uv_crop_width,
|
||||
source->uv_crop_height, in_bd, bd_shift);
|
||||
*ssim_v = calc_ssim(source->v_buffer, source->uv_stride, dest->v_buffer,
|
||||
dest->uv_stride, source->uv_crop_width,
|
||||
source->uv_crop_height, in_bd, bd_shift);
|
||||
ssimv = (*ssim_y) * .8 + .1 * ((*ssim_u) + (*ssim_v));
|
||||
return convert_ssim_db(ssimv, 1.0);
|
||||
}
|
||||
809
third_party/aom/aom_dsp/fwd_txfm.c
vendored
Normal file
809
third_party/aom/aom_dsp/fwd_txfm.c
vendored
Normal file
|
|
@ -0,0 +1,809 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#include "aom_dsp/fwd_txfm.h"
|
||||
#include <assert.h>
|
||||
#include "./aom_dsp_rtcd.h"
|
||||
|
||||
void aom_fdct4x4_c(const int16_t *input, tran_low_t *output, int stride) {
|
||||
// The 2D transform is done with two passes which are actually pretty
|
||||
// similar. In the first one, we transform the columns and transpose
|
||||
// the results. In the second one, we transform the rows. To achieve that,
|
||||
// as the first pass results are transposed, we transpose the columns (that
|
||||
// is the transposed rows) and transpose the results (so that it goes back
|
||||
// in normal/row positions).
|
||||
int pass;
|
||||
// We need an intermediate buffer between passes.
|
||||
tran_low_t intermediate[4 * 4];
|
||||
const tran_low_t *in_low = NULL;
|
||||
tran_low_t *out = intermediate;
|
||||
// Do the two transform/transpose passes
|
||||
for (pass = 0; pass < 2; ++pass) {
|
||||
tran_high_t in_high[4]; // canbe16
|
||||
tran_high_t step[4]; // canbe16
|
||||
tran_high_t temp1, temp2; // needs32
|
||||
int i;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
// Load inputs.
|
||||
if (pass == 0) {
|
||||
in_high[0] = input[0 * stride] * 16;
|
||||
in_high[1] = input[1 * stride] * 16;
|
||||
in_high[2] = input[2 * stride] * 16;
|
||||
in_high[3] = input[3 * stride] * 16;
|
||||
if (i == 0 && in_high[0]) {
|
||||
++in_high[0];
|
||||
}
|
||||
} else {
|
||||
assert(in_low != NULL);
|
||||
in_high[0] = in_low[0 * 4];
|
||||
in_high[1] = in_low[1 * 4];
|
||||
in_high[2] = in_low[2 * 4];
|
||||
in_high[3] = in_low[3 * 4];
|
||||
++in_low;
|
||||
}
|
||||
// Transform.
|
||||
step[0] = in_high[0] + in_high[3];
|
||||
step[1] = in_high[1] + in_high[2];
|
||||
step[2] = in_high[1] - in_high[2];
|
||||
step[3] = in_high[0] - in_high[3];
|
||||
temp1 = (step[0] + step[1]) * cospi_16_64;
|
||||
temp2 = (step[0] - step[1]) * cospi_16_64;
|
||||
out[0] = (tran_low_t)fdct_round_shift(temp1);
|
||||
out[2] = (tran_low_t)fdct_round_shift(temp2);
|
||||
temp1 = step[2] * cospi_24_64 + step[3] * cospi_8_64;
|
||||
temp2 = -step[2] * cospi_8_64 + step[3] * cospi_24_64;
|
||||
out[1] = (tran_low_t)fdct_round_shift(temp1);
|
||||
out[3] = (tran_low_t)fdct_round_shift(temp2);
|
||||
// Do next column (which is a transposed row in second/horizontal pass)
|
||||
++input;
|
||||
out += 4;
|
||||
}
|
||||
// Setup in/out for next pass.
|
||||
in_low = intermediate;
|
||||
out = output;
|
||||
}
|
||||
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
for (j = 0; j < 4; ++j) output[j + i * 4] = (output[j + i * 4] + 1) >> 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void aom_fdct4x4_1_c(const int16_t *input, tran_low_t *output, int stride) {
|
||||
int r, c;
|
||||
tran_low_t sum = 0;
|
||||
for (r = 0; r < 4; ++r)
|
||||
for (c = 0; c < 4; ++c) sum += input[r * stride + c];
|
||||
|
||||
output[0] = sum << 1;
|
||||
}
|
||||
|
||||
void aom_fdct8x8_c(const int16_t *input, tran_low_t *final_output, int stride) {
|
||||
int i, j;
|
||||
tran_low_t intermediate[64];
|
||||
int pass;
|
||||
tran_low_t *output = intermediate;
|
||||
const tran_low_t *in = NULL;
|
||||
|
||||
// Transform columns
|
||||
for (pass = 0; pass < 2; ++pass) {
|
||||
tran_high_t s0, s1, s2, s3, s4, s5, s6, s7; // canbe16
|
||||
tran_high_t t0, t1, t2, t3; // needs32
|
||||
tran_high_t x0, x1, x2, x3; // canbe16
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
// stage 1
|
||||
if (pass == 0) {
|
||||
s0 = (input[0 * stride] + input[7 * stride]) * 4;
|
||||
s1 = (input[1 * stride] + input[6 * stride]) * 4;
|
||||
s2 = (input[2 * stride] + input[5 * stride]) * 4;
|
||||
s3 = (input[3 * stride] + input[4 * stride]) * 4;
|
||||
s4 = (input[3 * stride] - input[4 * stride]) * 4;
|
||||
s5 = (input[2 * stride] - input[5 * stride]) * 4;
|
||||
s6 = (input[1 * stride] - input[6 * stride]) * 4;
|
||||
s7 = (input[0 * stride] - input[7 * stride]) * 4;
|
||||
++input;
|
||||
} else {
|
||||
s0 = in[0 * 8] + in[7 * 8];
|
||||
s1 = in[1 * 8] + in[6 * 8];
|
||||
s2 = in[2 * 8] + in[5 * 8];
|
||||
s3 = in[3 * 8] + in[4 * 8];
|
||||
s4 = in[3 * 8] - in[4 * 8];
|
||||
s5 = in[2 * 8] - in[5 * 8];
|
||||
s6 = in[1 * 8] - in[6 * 8];
|
||||
s7 = in[0 * 8] - in[7 * 8];
|
||||
++in;
|
||||
}
|
||||
|
||||
// fdct4(step, step);
|
||||
x0 = s0 + s3;
|
||||
x1 = s1 + s2;
|
||||
x2 = s1 - s2;
|
||||
x3 = s0 - s3;
|
||||
t0 = (x0 + x1) * cospi_16_64;
|
||||
t1 = (x0 - x1) * cospi_16_64;
|
||||
t2 = x2 * cospi_24_64 + x3 * cospi_8_64;
|
||||
t3 = -x2 * cospi_8_64 + x3 * cospi_24_64;
|
||||
output[0] = (tran_low_t)fdct_round_shift(t0);
|
||||
output[2] = (tran_low_t)fdct_round_shift(t2);
|
||||
output[4] = (tran_low_t)fdct_round_shift(t1);
|
||||
output[6] = (tran_low_t)fdct_round_shift(t3);
|
||||
|
||||
// Stage 2
|
||||
t0 = (s6 - s5) * cospi_16_64;
|
||||
t1 = (s6 + s5) * cospi_16_64;
|
||||
t2 = fdct_round_shift(t0);
|
||||
t3 = fdct_round_shift(t1);
|
||||
|
||||
// Stage 3
|
||||
x0 = s4 + t2;
|
||||
x1 = s4 - t2;
|
||||
x2 = s7 - t3;
|
||||
x3 = s7 + t3;
|
||||
|
||||
// Stage 4
|
||||
t0 = x0 * cospi_28_64 + x3 * cospi_4_64;
|
||||
t1 = x1 * cospi_12_64 + x2 * cospi_20_64;
|
||||
t2 = x2 * cospi_12_64 + x1 * -cospi_20_64;
|
||||
t3 = x3 * cospi_28_64 + x0 * -cospi_4_64;
|
||||
output[1] = (tran_low_t)fdct_round_shift(t0);
|
||||
output[3] = (tran_low_t)fdct_round_shift(t2);
|
||||
output[5] = (tran_low_t)fdct_round_shift(t1);
|
||||
output[7] = (tran_low_t)fdct_round_shift(t3);
|
||||
output += 8;
|
||||
}
|
||||
in = intermediate;
|
||||
output = final_output;
|
||||
}
|
||||
|
||||
// Rows
|
||||
for (i = 0; i < 8; ++i) {
|
||||
for (j = 0; j < 8; ++j) final_output[j + i * 8] /= 2;
|
||||
}
|
||||
}
|
||||
|
||||
void aom_fdct8x8_1_c(const int16_t *input, tran_low_t *output, int stride) {
|
||||
int r, c;
|
||||
tran_low_t sum = 0;
|
||||
for (r = 0; r < 8; ++r)
|
||||
for (c = 0; c < 8; ++c) sum += input[r * stride + c];
|
||||
|
||||
output[0] = sum;
|
||||
}
|
||||
|
||||
void aom_fdct16x16_c(const int16_t *input, tran_low_t *output, int stride) {
|
||||
// The 2D transform is done with two passes which are actually pretty
|
||||
// similar. In the first one, we transform the columns and transpose
|
||||
// the results. In the second one, we transform the rows. To achieve that,
|
||||
// as the first pass results are transposed, we transpose the columns (that
|
||||
// is the transposed rows) and transpose the results (so that it goes back
|
||||
// in normal/row positions).
|
||||
int pass;
|
||||
// We need an intermediate buffer between passes.
|
||||
tran_low_t intermediate[256];
|
||||
const tran_low_t *in_low = NULL;
|
||||
tran_low_t *out = intermediate;
|
||||
// Do the two transform/transpose passes
|
||||
for (pass = 0; pass < 2; ++pass) {
|
||||
tran_high_t step1[8]; // canbe16
|
||||
tran_high_t step2[8]; // canbe16
|
||||
tran_high_t step3[8]; // canbe16
|
||||
tran_high_t in_high[8]; // canbe16
|
||||
tran_high_t temp1, temp2; // needs32
|
||||
int i;
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (0 == pass) {
|
||||
// Calculate input for the first 8 results.
|
||||
in_high[0] = (input[0 * stride] + input[15 * stride]) * 4;
|
||||
in_high[1] = (input[1 * stride] + input[14 * stride]) * 4;
|
||||
in_high[2] = (input[2 * stride] + input[13 * stride]) * 4;
|
||||
in_high[3] = (input[3 * stride] + input[12 * stride]) * 4;
|
||||
in_high[4] = (input[4 * stride] + input[11 * stride]) * 4;
|
||||
in_high[5] = (input[5 * stride] + input[10 * stride]) * 4;
|
||||
in_high[6] = (input[6 * stride] + input[9 * stride]) * 4;
|
||||
in_high[7] = (input[7 * stride] + input[8 * stride]) * 4;
|
||||
// Calculate input for the next 8 results.
|
||||
step1[0] = (input[7 * stride] - input[8 * stride]) * 4;
|
||||
step1[1] = (input[6 * stride] - input[9 * stride]) * 4;
|
||||
step1[2] = (input[5 * stride] - input[10 * stride]) * 4;
|
||||
step1[3] = (input[4 * stride] - input[11 * stride]) * 4;
|
||||
step1[4] = (input[3 * stride] - input[12 * stride]) * 4;
|
||||
step1[5] = (input[2 * stride] - input[13 * stride]) * 4;
|
||||
step1[6] = (input[1 * stride] - input[14 * stride]) * 4;
|
||||
step1[7] = (input[0 * stride] - input[15 * stride]) * 4;
|
||||
} else {
|
||||
// Calculate input for the first 8 results.
|
||||
assert(in_low != NULL);
|
||||
in_high[0] = ((in_low[0 * 16] + 1) >> 2) + ((in_low[15 * 16] + 1) >> 2);
|
||||
in_high[1] = ((in_low[1 * 16] + 1) >> 2) + ((in_low[14 * 16] + 1) >> 2);
|
||||
in_high[2] = ((in_low[2 * 16] + 1) >> 2) + ((in_low[13 * 16] + 1) >> 2);
|
||||
in_high[3] = ((in_low[3 * 16] + 1) >> 2) + ((in_low[12 * 16] + 1) >> 2);
|
||||
in_high[4] = ((in_low[4 * 16] + 1) >> 2) + ((in_low[11 * 16] + 1) >> 2);
|
||||
in_high[5] = ((in_low[5 * 16] + 1) >> 2) + ((in_low[10 * 16] + 1) >> 2);
|
||||
in_high[6] = ((in_low[6 * 16] + 1) >> 2) + ((in_low[9 * 16] + 1) >> 2);
|
||||
in_high[7] = ((in_low[7 * 16] + 1) >> 2) + ((in_low[8 * 16] + 1) >> 2);
|
||||
// Calculate input for the next 8 results.
|
||||
step1[0] = ((in_low[7 * 16] + 1) >> 2) - ((in_low[8 * 16] + 1) >> 2);
|
||||
step1[1] = ((in_low[6 * 16] + 1) >> 2) - ((in_low[9 * 16] + 1) >> 2);
|
||||
step1[2] = ((in_low[5 * 16] + 1) >> 2) - ((in_low[10 * 16] + 1) >> 2);
|
||||
step1[3] = ((in_low[4 * 16] + 1) >> 2) - ((in_low[11 * 16] + 1) >> 2);
|
||||
step1[4] = ((in_low[3 * 16] + 1) >> 2) - ((in_low[12 * 16] + 1) >> 2);
|
||||
step1[5] = ((in_low[2 * 16] + 1) >> 2) - ((in_low[13 * 16] + 1) >> 2);
|
||||
step1[6] = ((in_low[1 * 16] + 1) >> 2) - ((in_low[14 * 16] + 1) >> 2);
|
||||
step1[7] = ((in_low[0 * 16] + 1) >> 2) - ((in_low[15 * 16] + 1) >> 2);
|
||||
in_low++;
|
||||
}
|
||||
// Work on the first eight values; fdct8(input, even_results);
|
||||
{
|
||||
tran_high_t s0, s1, s2, s3, s4, s5, s6, s7; // canbe16
|
||||
tran_high_t t0, t1, t2, t3; // needs32
|
||||
tran_high_t x0, x1, x2, x3; // canbe16
|
||||
|
||||
// stage 1
|
||||
s0 = in_high[0] + in_high[7];
|
||||
s1 = in_high[1] + in_high[6];
|
||||
s2 = in_high[2] + in_high[5];
|
||||
s3 = in_high[3] + in_high[4];
|
||||
s4 = in_high[3] - in_high[4];
|
||||
s5 = in_high[2] - in_high[5];
|
||||
s6 = in_high[1] - in_high[6];
|
||||
s7 = in_high[0] - in_high[7];
|
||||
|
||||
// fdct4(step, step);
|
||||
x0 = s0 + s3;
|
||||
x1 = s1 + s2;
|
||||
x2 = s1 - s2;
|
||||
x3 = s0 - s3;
|
||||
t0 = (x0 + x1) * cospi_16_64;
|
||||
t1 = (x0 - x1) * cospi_16_64;
|
||||
t2 = x3 * cospi_8_64 + x2 * cospi_24_64;
|
||||
t3 = x3 * cospi_24_64 - x2 * cospi_8_64;
|
||||
out[0] = (tran_low_t)fdct_round_shift(t0);
|
||||
out[4] = (tran_low_t)fdct_round_shift(t2);
|
||||
out[8] = (tran_low_t)fdct_round_shift(t1);
|
||||
out[12] = (tran_low_t)fdct_round_shift(t3);
|
||||
|
||||
// Stage 2
|
||||
t0 = (s6 - s5) * cospi_16_64;
|
||||
t1 = (s6 + s5) * cospi_16_64;
|
||||
t2 = fdct_round_shift(t0);
|
||||
t3 = fdct_round_shift(t1);
|
||||
|
||||
// Stage 3
|
||||
x0 = s4 + t2;
|
||||
x1 = s4 - t2;
|
||||
x2 = s7 - t3;
|
||||
x3 = s7 + t3;
|
||||
|
||||
// Stage 4
|
||||
t0 = x0 * cospi_28_64 + x3 * cospi_4_64;
|
||||
t1 = x1 * cospi_12_64 + x2 * cospi_20_64;
|
||||
t2 = x2 * cospi_12_64 + x1 * -cospi_20_64;
|
||||
t3 = x3 * cospi_28_64 + x0 * -cospi_4_64;
|
||||
out[2] = (tran_low_t)fdct_round_shift(t0);
|
||||
out[6] = (tran_low_t)fdct_round_shift(t2);
|
||||
out[10] = (tran_low_t)fdct_round_shift(t1);
|
||||
out[14] = (tran_low_t)fdct_round_shift(t3);
|
||||
}
|
||||
// Work on the next eight values; step1 -> odd_results
|
||||
{
|
||||
// step 2
|
||||
temp1 = (step1[5] - step1[2]) * cospi_16_64;
|
||||
temp2 = (step1[4] - step1[3]) * cospi_16_64;
|
||||
step2[2] = fdct_round_shift(temp1);
|
||||
step2[3] = fdct_round_shift(temp2);
|
||||
temp1 = (step1[4] + step1[3]) * cospi_16_64;
|
||||
temp2 = (step1[5] + step1[2]) * cospi_16_64;
|
||||
step2[4] = fdct_round_shift(temp1);
|
||||
step2[5] = fdct_round_shift(temp2);
|
||||
// step 3
|
||||
step3[0] = step1[0] + step2[3];
|
||||
step3[1] = step1[1] + step2[2];
|
||||
step3[2] = step1[1] - step2[2];
|
||||
step3[3] = step1[0] - step2[3];
|
||||
step3[4] = step1[7] - step2[4];
|
||||
step3[5] = step1[6] - step2[5];
|
||||
step3[6] = step1[6] + step2[5];
|
||||
step3[7] = step1[7] + step2[4];
|
||||
// step 4
|
||||
temp1 = step3[1] * -cospi_8_64 + step3[6] * cospi_24_64;
|
||||
temp2 = step3[2] * cospi_24_64 + step3[5] * cospi_8_64;
|
||||
step2[1] = fdct_round_shift(temp1);
|
||||
step2[2] = fdct_round_shift(temp2);
|
||||
temp1 = step3[2] * cospi_8_64 - step3[5] * cospi_24_64;
|
||||
temp2 = step3[1] * cospi_24_64 + step3[6] * cospi_8_64;
|
||||
step2[5] = fdct_round_shift(temp1);
|
||||
step2[6] = fdct_round_shift(temp2);
|
||||
// step 5
|
||||
step1[0] = step3[0] + step2[1];
|
||||
step1[1] = step3[0] - step2[1];
|
||||
step1[2] = step3[3] + step2[2];
|
||||
step1[3] = step3[3] - step2[2];
|
||||
step1[4] = step3[4] - step2[5];
|
||||
step1[5] = step3[4] + step2[5];
|
||||
step1[6] = step3[7] - step2[6];
|
||||
step1[7] = step3[7] + step2[6];
|
||||
// step 6
|
||||
temp1 = step1[0] * cospi_30_64 + step1[7] * cospi_2_64;
|
||||
temp2 = step1[1] * cospi_14_64 + step1[6] * cospi_18_64;
|
||||
out[1] = (tran_low_t)fdct_round_shift(temp1);
|
||||
out[9] = (tran_low_t)fdct_round_shift(temp2);
|
||||
temp1 = step1[2] * cospi_22_64 + step1[5] * cospi_10_64;
|
||||
temp2 = step1[3] * cospi_6_64 + step1[4] * cospi_26_64;
|
||||
out[5] = (tran_low_t)fdct_round_shift(temp1);
|
||||
out[13] = (tran_low_t)fdct_round_shift(temp2);
|
||||
temp1 = step1[3] * -cospi_26_64 + step1[4] * cospi_6_64;
|
||||
temp2 = step1[2] * -cospi_10_64 + step1[5] * cospi_22_64;
|
||||
out[3] = (tran_low_t)fdct_round_shift(temp1);
|
||||
out[11] = (tran_low_t)fdct_round_shift(temp2);
|
||||
temp1 = step1[1] * -cospi_18_64 + step1[6] * cospi_14_64;
|
||||
temp2 = step1[0] * -cospi_2_64 + step1[7] * cospi_30_64;
|
||||
out[7] = (tran_low_t)fdct_round_shift(temp1);
|
||||
out[15] = (tran_low_t)fdct_round_shift(temp2);
|
||||
}
|
||||
// Do next column (which is a transposed row in second/horizontal pass)
|
||||
input++;
|
||||
out += 16;
|
||||
}
|
||||
// Setup in/out for next pass.
|
||||
in_low = intermediate;
|
||||
out = output;
|
||||
}
|
||||
}
|
||||
|
||||
void aom_fdct16x16_1_c(const int16_t *input, tran_low_t *output, int stride) {
|
||||
int r, c;
|
||||
int sum = 0;
|
||||
for (r = 0; r < 16; ++r)
|
||||
for (c = 0; c < 16; ++c) sum += input[r * stride + c];
|
||||
|
||||
output[0] = (tran_low_t)(sum >> 1);
|
||||
}
|
||||
|
||||
static INLINE tran_high_t dct_32_round(tran_high_t input) {
|
||||
tran_high_t rv = ROUND_POWER_OF_TWO(input, DCT_CONST_BITS);
|
||||
// TODO(debargha, peter.derivaz): Find new bounds for this assert,
|
||||
// and make the bounds consts.
|
||||
// assert(-131072 <= rv && rv <= 131071);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static INLINE tran_high_t half_round_shift(tran_high_t input) {
|
||||
tran_high_t rv = (input + 1 + (input < 0)) >> 2;
|
||||
return rv;
|
||||
}
|
||||
|
||||
void aom_fdct32(const tran_high_t *input, tran_high_t *output, int round) {
|
||||
tran_high_t step[32];
|
||||
// Stage 1
|
||||
step[0] = input[0] + input[(32 - 1)];
|
||||
step[1] = input[1] + input[(32 - 2)];
|
||||
step[2] = input[2] + input[(32 - 3)];
|
||||
step[3] = input[3] + input[(32 - 4)];
|
||||
step[4] = input[4] + input[(32 - 5)];
|
||||
step[5] = input[5] + input[(32 - 6)];
|
||||
step[6] = input[6] + input[(32 - 7)];
|
||||
step[7] = input[7] + input[(32 - 8)];
|
||||
step[8] = input[8] + input[(32 - 9)];
|
||||
step[9] = input[9] + input[(32 - 10)];
|
||||
step[10] = input[10] + input[(32 - 11)];
|
||||
step[11] = input[11] + input[(32 - 12)];
|
||||
step[12] = input[12] + input[(32 - 13)];
|
||||
step[13] = input[13] + input[(32 - 14)];
|
||||
step[14] = input[14] + input[(32 - 15)];
|
||||
step[15] = input[15] + input[(32 - 16)];
|
||||
step[16] = -input[16] + input[(32 - 17)];
|
||||
step[17] = -input[17] + input[(32 - 18)];
|
||||
step[18] = -input[18] + input[(32 - 19)];
|
||||
step[19] = -input[19] + input[(32 - 20)];
|
||||
step[20] = -input[20] + input[(32 - 21)];
|
||||
step[21] = -input[21] + input[(32 - 22)];
|
||||
step[22] = -input[22] + input[(32 - 23)];
|
||||
step[23] = -input[23] + input[(32 - 24)];
|
||||
step[24] = -input[24] + input[(32 - 25)];
|
||||
step[25] = -input[25] + input[(32 - 26)];
|
||||
step[26] = -input[26] + input[(32 - 27)];
|
||||
step[27] = -input[27] + input[(32 - 28)];
|
||||
step[28] = -input[28] + input[(32 - 29)];
|
||||
step[29] = -input[29] + input[(32 - 30)];
|
||||
step[30] = -input[30] + input[(32 - 31)];
|
||||
step[31] = -input[31] + input[(32 - 32)];
|
||||
|
||||
// Stage 2
|
||||
output[0] = step[0] + step[16 - 1];
|
||||
output[1] = step[1] + step[16 - 2];
|
||||
output[2] = step[2] + step[16 - 3];
|
||||
output[3] = step[3] + step[16 - 4];
|
||||
output[4] = step[4] + step[16 - 5];
|
||||
output[5] = step[5] + step[16 - 6];
|
||||
output[6] = step[6] + step[16 - 7];
|
||||
output[7] = step[7] + step[16 - 8];
|
||||
output[8] = -step[8] + step[16 - 9];
|
||||
output[9] = -step[9] + step[16 - 10];
|
||||
output[10] = -step[10] + step[16 - 11];
|
||||
output[11] = -step[11] + step[16 - 12];
|
||||
output[12] = -step[12] + step[16 - 13];
|
||||
output[13] = -step[13] + step[16 - 14];
|
||||
output[14] = -step[14] + step[16 - 15];
|
||||
output[15] = -step[15] + step[16 - 16];
|
||||
|
||||
output[16] = step[16];
|
||||
output[17] = step[17];
|
||||
output[18] = step[18];
|
||||
output[19] = step[19];
|
||||
|
||||
output[20] = dct_32_round((-step[20] + step[27]) * cospi_16_64);
|
||||
output[21] = dct_32_round((-step[21] + step[26]) * cospi_16_64);
|
||||
output[22] = dct_32_round((-step[22] + step[25]) * cospi_16_64);
|
||||
output[23] = dct_32_round((-step[23] + step[24]) * cospi_16_64);
|
||||
|
||||
output[24] = dct_32_round((step[24] + step[23]) * cospi_16_64);
|
||||
output[25] = dct_32_round((step[25] + step[22]) * cospi_16_64);
|
||||
output[26] = dct_32_round((step[26] + step[21]) * cospi_16_64);
|
||||
output[27] = dct_32_round((step[27] + step[20]) * cospi_16_64);
|
||||
|
||||
output[28] = step[28];
|
||||
output[29] = step[29];
|
||||
output[30] = step[30];
|
||||
output[31] = step[31];
|
||||
|
||||
// dump the magnitude by 4, hence the intermediate values are within
|
||||
// the range of 16 bits.
|
||||
if (round) {
|
||||
output[0] = half_round_shift(output[0]);
|
||||
output[1] = half_round_shift(output[1]);
|
||||
output[2] = half_round_shift(output[2]);
|
||||
output[3] = half_round_shift(output[3]);
|
||||
output[4] = half_round_shift(output[4]);
|
||||
output[5] = half_round_shift(output[5]);
|
||||
output[6] = half_round_shift(output[6]);
|
||||
output[7] = half_round_shift(output[7]);
|
||||
output[8] = half_round_shift(output[8]);
|
||||
output[9] = half_round_shift(output[9]);
|
||||
output[10] = half_round_shift(output[10]);
|
||||
output[11] = half_round_shift(output[11]);
|
||||
output[12] = half_round_shift(output[12]);
|
||||
output[13] = half_round_shift(output[13]);
|
||||
output[14] = half_round_shift(output[14]);
|
||||
output[15] = half_round_shift(output[15]);
|
||||
|
||||
output[16] = half_round_shift(output[16]);
|
||||
output[17] = half_round_shift(output[17]);
|
||||
output[18] = half_round_shift(output[18]);
|
||||
output[19] = half_round_shift(output[19]);
|
||||
output[20] = half_round_shift(output[20]);
|
||||
output[21] = half_round_shift(output[21]);
|
||||
output[22] = half_round_shift(output[22]);
|
||||
output[23] = half_round_shift(output[23]);
|
||||
output[24] = half_round_shift(output[24]);
|
||||
output[25] = half_round_shift(output[25]);
|
||||
output[26] = half_round_shift(output[26]);
|
||||
output[27] = half_round_shift(output[27]);
|
||||
output[28] = half_round_shift(output[28]);
|
||||
output[29] = half_round_shift(output[29]);
|
||||
output[30] = half_round_shift(output[30]);
|
||||
output[31] = half_round_shift(output[31]);
|
||||
}
|
||||
|
||||
// Stage 3
|
||||
step[0] = output[0] + output[(8 - 1)];
|
||||
step[1] = output[1] + output[(8 - 2)];
|
||||
step[2] = output[2] + output[(8 - 3)];
|
||||
step[3] = output[3] + output[(8 - 4)];
|
||||
step[4] = -output[4] + output[(8 - 5)];
|
||||
step[5] = -output[5] + output[(8 - 6)];
|
||||
step[6] = -output[6] + output[(8 - 7)];
|
||||
step[7] = -output[7] + output[(8 - 8)];
|
||||
step[8] = output[8];
|
||||
step[9] = output[9];
|
||||
step[10] = dct_32_round((-output[10] + output[13]) * cospi_16_64);
|
||||
step[11] = dct_32_round((-output[11] + output[12]) * cospi_16_64);
|
||||
step[12] = dct_32_round((output[12] + output[11]) * cospi_16_64);
|
||||
step[13] = dct_32_round((output[13] + output[10]) * cospi_16_64);
|
||||
step[14] = output[14];
|
||||
step[15] = output[15];
|
||||
|
||||
step[16] = output[16] + output[23];
|
||||
step[17] = output[17] + output[22];
|
||||
step[18] = output[18] + output[21];
|
||||
step[19] = output[19] + output[20];
|
||||
step[20] = -output[20] + output[19];
|
||||
step[21] = -output[21] + output[18];
|
||||
step[22] = -output[22] + output[17];
|
||||
step[23] = -output[23] + output[16];
|
||||
step[24] = -output[24] + output[31];
|
||||
step[25] = -output[25] + output[30];
|
||||
step[26] = -output[26] + output[29];
|
||||
step[27] = -output[27] + output[28];
|
||||
step[28] = output[28] + output[27];
|
||||
step[29] = output[29] + output[26];
|
||||
step[30] = output[30] + output[25];
|
||||
step[31] = output[31] + output[24];
|
||||
|
||||
// Stage 4
|
||||
output[0] = step[0] + step[3];
|
||||
output[1] = step[1] + step[2];
|
||||
output[2] = -step[2] + step[1];
|
||||
output[3] = -step[3] + step[0];
|
||||
output[4] = step[4];
|
||||
output[5] = dct_32_round((-step[5] + step[6]) * cospi_16_64);
|
||||
output[6] = dct_32_round((step[6] + step[5]) * cospi_16_64);
|
||||
output[7] = step[7];
|
||||
output[8] = step[8] + step[11];
|
||||
output[9] = step[9] + step[10];
|
||||
output[10] = -step[10] + step[9];
|
||||
output[11] = -step[11] + step[8];
|
||||
output[12] = -step[12] + step[15];
|
||||
output[13] = -step[13] + step[14];
|
||||
output[14] = step[14] + step[13];
|
||||
output[15] = step[15] + step[12];
|
||||
|
||||
output[16] = step[16];
|
||||
output[17] = step[17];
|
||||
output[18] = dct_32_round(step[18] * -cospi_8_64 + step[29] * cospi_24_64);
|
||||
output[19] = dct_32_round(step[19] * -cospi_8_64 + step[28] * cospi_24_64);
|
||||
output[20] = dct_32_round(step[20] * -cospi_24_64 + step[27] * -cospi_8_64);
|
||||
output[21] = dct_32_round(step[21] * -cospi_24_64 + step[26] * -cospi_8_64);
|
||||
output[22] = step[22];
|
||||
output[23] = step[23];
|
||||
output[24] = step[24];
|
||||
output[25] = step[25];
|
||||
output[26] = dct_32_round(step[26] * cospi_24_64 + step[21] * -cospi_8_64);
|
||||
output[27] = dct_32_round(step[27] * cospi_24_64 + step[20] * -cospi_8_64);
|
||||
output[28] = dct_32_round(step[28] * cospi_8_64 + step[19] * cospi_24_64);
|
||||
output[29] = dct_32_round(step[29] * cospi_8_64 + step[18] * cospi_24_64);
|
||||
output[30] = step[30];
|
||||
output[31] = step[31];
|
||||
|
||||
// Stage 5
|
||||
step[0] = dct_32_round((output[0] + output[1]) * cospi_16_64);
|
||||
step[1] = dct_32_round((-output[1] + output[0]) * cospi_16_64);
|
||||
step[2] = dct_32_round(output[2] * cospi_24_64 + output[3] * cospi_8_64);
|
||||
step[3] = dct_32_round(output[3] * cospi_24_64 - output[2] * cospi_8_64);
|
||||
step[4] = output[4] + output[5];
|
||||
step[5] = -output[5] + output[4];
|
||||
step[6] = -output[6] + output[7];
|
||||
step[7] = output[7] + output[6];
|
||||
step[8] = output[8];
|
||||
step[9] = dct_32_round(output[9] * -cospi_8_64 + output[14] * cospi_24_64);
|
||||
step[10] = dct_32_round(output[10] * -cospi_24_64 + output[13] * -cospi_8_64);
|
||||
step[11] = output[11];
|
||||
step[12] = output[12];
|
||||
step[13] = dct_32_round(output[13] * cospi_24_64 + output[10] * -cospi_8_64);
|
||||
step[14] = dct_32_round(output[14] * cospi_8_64 + output[9] * cospi_24_64);
|
||||
step[15] = output[15];
|
||||
|
||||
step[16] = output[16] + output[19];
|
||||
step[17] = output[17] + output[18];
|
||||
step[18] = -output[18] + output[17];
|
||||
step[19] = -output[19] + output[16];
|
||||
step[20] = -output[20] + output[23];
|
||||
step[21] = -output[21] + output[22];
|
||||
step[22] = output[22] + output[21];
|
||||
step[23] = output[23] + output[20];
|
||||
step[24] = output[24] + output[27];
|
||||
step[25] = output[25] + output[26];
|
||||
step[26] = -output[26] + output[25];
|
||||
step[27] = -output[27] + output[24];
|
||||
step[28] = -output[28] + output[31];
|
||||
step[29] = -output[29] + output[30];
|
||||
step[30] = output[30] + output[29];
|
||||
step[31] = output[31] + output[28];
|
||||
|
||||
// Stage 6
|
||||
output[0] = step[0];
|
||||
output[1] = step[1];
|
||||
output[2] = step[2];
|
||||
output[3] = step[3];
|
||||
output[4] = dct_32_round(step[4] * cospi_28_64 + step[7] * cospi_4_64);
|
||||
output[5] = dct_32_round(step[5] * cospi_12_64 + step[6] * cospi_20_64);
|
||||
output[6] = dct_32_round(step[6] * cospi_12_64 + step[5] * -cospi_20_64);
|
||||
output[7] = dct_32_round(step[7] * cospi_28_64 + step[4] * -cospi_4_64);
|
||||
output[8] = step[8] + step[9];
|
||||
output[9] = -step[9] + step[8];
|
||||
output[10] = -step[10] + step[11];
|
||||
output[11] = step[11] + step[10];
|
||||
output[12] = step[12] + step[13];
|
||||
output[13] = -step[13] + step[12];
|
||||
output[14] = -step[14] + step[15];
|
||||
output[15] = step[15] + step[14];
|
||||
|
||||
output[16] = step[16];
|
||||
output[17] = dct_32_round(step[17] * -cospi_4_64 + step[30] * cospi_28_64);
|
||||
output[18] = dct_32_round(step[18] * -cospi_28_64 + step[29] * -cospi_4_64);
|
||||
output[19] = step[19];
|
||||
output[20] = step[20];
|
||||
output[21] = dct_32_round(step[21] * -cospi_20_64 + step[26] * cospi_12_64);
|
||||
output[22] = dct_32_round(step[22] * -cospi_12_64 + step[25] * -cospi_20_64);
|
||||
output[23] = step[23];
|
||||
output[24] = step[24];
|
||||
output[25] = dct_32_round(step[25] * cospi_12_64 + step[22] * -cospi_20_64);
|
||||
output[26] = dct_32_round(step[26] * cospi_20_64 + step[21] * cospi_12_64);
|
||||
output[27] = step[27];
|
||||
output[28] = step[28];
|
||||
output[29] = dct_32_round(step[29] * cospi_28_64 + step[18] * -cospi_4_64);
|
||||
output[30] = dct_32_round(step[30] * cospi_4_64 + step[17] * cospi_28_64);
|
||||
output[31] = step[31];
|
||||
|
||||
// Stage 7
|
||||
step[0] = output[0];
|
||||
step[1] = output[1];
|
||||
step[2] = output[2];
|
||||
step[3] = output[3];
|
||||
step[4] = output[4];
|
||||
step[5] = output[5];
|
||||
step[6] = output[6];
|
||||
step[7] = output[7];
|
||||
step[8] = dct_32_round(output[8] * cospi_30_64 + output[15] * cospi_2_64);
|
||||
step[9] = dct_32_round(output[9] * cospi_14_64 + output[14] * cospi_18_64);
|
||||
step[10] = dct_32_round(output[10] * cospi_22_64 + output[13] * cospi_10_64);
|
||||
step[11] = dct_32_round(output[11] * cospi_6_64 + output[12] * cospi_26_64);
|
||||
step[12] = dct_32_round(output[12] * cospi_6_64 + output[11] * -cospi_26_64);
|
||||
step[13] = dct_32_round(output[13] * cospi_22_64 + output[10] * -cospi_10_64);
|
||||
step[14] = dct_32_round(output[14] * cospi_14_64 + output[9] * -cospi_18_64);
|
||||
step[15] = dct_32_round(output[15] * cospi_30_64 + output[8] * -cospi_2_64);
|
||||
|
||||
step[16] = output[16] + output[17];
|
||||
step[17] = -output[17] + output[16];
|
||||
step[18] = -output[18] + output[19];
|
||||
step[19] = output[19] + output[18];
|
||||
step[20] = output[20] + output[21];
|
||||
step[21] = -output[21] + output[20];
|
||||
step[22] = -output[22] + output[23];
|
||||
step[23] = output[23] + output[22];
|
||||
step[24] = output[24] + output[25];
|
||||
step[25] = -output[25] + output[24];
|
||||
step[26] = -output[26] + output[27];
|
||||
step[27] = output[27] + output[26];
|
||||
step[28] = output[28] + output[29];
|
||||
step[29] = -output[29] + output[28];
|
||||
step[30] = -output[30] + output[31];
|
||||
step[31] = output[31] + output[30];
|
||||
|
||||
// Final stage --- outputs indices are bit-reversed.
|
||||
output[0] = step[0];
|
||||
output[16] = step[1];
|
||||
output[8] = step[2];
|
||||
output[24] = step[3];
|
||||
output[4] = step[4];
|
||||
output[20] = step[5];
|
||||
output[12] = step[6];
|
||||
output[28] = step[7];
|
||||
output[2] = step[8];
|
||||
output[18] = step[9];
|
||||
output[10] = step[10];
|
||||
output[26] = step[11];
|
||||
output[6] = step[12];
|
||||
output[22] = step[13];
|
||||
output[14] = step[14];
|
||||
output[30] = step[15];
|
||||
|
||||
output[1] = dct_32_round(step[16] * cospi_31_64 + step[31] * cospi_1_64);
|
||||
output[17] = dct_32_round(step[17] * cospi_15_64 + step[30] * cospi_17_64);
|
||||
output[9] = dct_32_round(step[18] * cospi_23_64 + step[29] * cospi_9_64);
|
||||
output[25] = dct_32_round(step[19] * cospi_7_64 + step[28] * cospi_25_64);
|
||||
output[5] = dct_32_round(step[20] * cospi_27_64 + step[27] * cospi_5_64);
|
||||
output[21] = dct_32_round(step[21] * cospi_11_64 + step[26] * cospi_21_64);
|
||||
output[13] = dct_32_round(step[22] * cospi_19_64 + step[25] * cospi_13_64);
|
||||
output[29] = dct_32_round(step[23] * cospi_3_64 + step[24] * cospi_29_64);
|
||||
output[3] = dct_32_round(step[24] * cospi_3_64 + step[23] * -cospi_29_64);
|
||||
output[19] = dct_32_round(step[25] * cospi_19_64 + step[22] * -cospi_13_64);
|
||||
output[11] = dct_32_round(step[26] * cospi_11_64 + step[21] * -cospi_21_64);
|
||||
output[27] = dct_32_round(step[27] * cospi_27_64 + step[20] * -cospi_5_64);
|
||||
output[7] = dct_32_round(step[28] * cospi_7_64 + step[19] * -cospi_25_64);
|
||||
output[23] = dct_32_round(step[29] * cospi_23_64 + step[18] * -cospi_9_64);
|
||||
output[15] = dct_32_round(step[30] * cospi_15_64 + step[17] * -cospi_17_64);
|
||||
output[31] = dct_32_round(step[31] * cospi_31_64 + step[16] * -cospi_1_64);
|
||||
}
|
||||
|
||||
void aom_fdct32x32_c(const int16_t *input, tran_low_t *out, int stride) {
|
||||
int i, j;
|
||||
tran_high_t output[32 * 32];
|
||||
|
||||
// Columns
|
||||
for (i = 0; i < 32; ++i) {
|
||||
tran_high_t temp_in[32], temp_out[32];
|
||||
for (j = 0; j < 32; ++j) temp_in[j] = input[j * stride + i] * 4;
|
||||
aom_fdct32(temp_in, temp_out, 0);
|
||||
for (j = 0; j < 32; ++j)
|
||||
output[j * 32 + i] = (temp_out[j] + 1 + (temp_out[j] > 0)) >> 2;
|
||||
}
|
||||
|
||||
// Rows
|
||||
for (i = 0; i < 32; ++i) {
|
||||
tran_high_t temp_in[32], temp_out[32];
|
||||
for (j = 0; j < 32; ++j) temp_in[j] = output[j + i * 32];
|
||||
aom_fdct32(temp_in, temp_out, 0);
|
||||
for (j = 0; j < 32; ++j)
|
||||
out[j + i * 32] =
|
||||
(tran_low_t)((temp_out[j] + 1 + (temp_out[j] < 0)) >> 2);
|
||||
}
|
||||
}
|
||||
|
||||
// Note that although we use dct_32_round in dct32 computation flow,
|
||||
// this 2d fdct32x32 for rate-distortion optimization loop is operating
|
||||
// within 16 bits precision.
|
||||
void aom_fdct32x32_rd_c(const int16_t *input, tran_low_t *out, int stride) {
|
||||
int i, j;
|
||||
tran_high_t output[32 * 32];
|
||||
|
||||
// Columns
|
||||
for (i = 0; i < 32; ++i) {
|
||||
tran_high_t temp_in[32], temp_out[32];
|
||||
for (j = 0; j < 32; ++j) temp_in[j] = input[j * stride + i] * 4;
|
||||
aom_fdct32(temp_in, temp_out, 0);
|
||||
for (j = 0; j < 32; ++j)
|
||||
// TODO(cd): see quality impact of only doing
|
||||
// output[j * 32 + i] = (temp_out[j] + 1) >> 2;
|
||||
// PS: also change code in aom_dsp/x86/aom_dct_sse2.c
|
||||
output[j * 32 + i] = (temp_out[j] + 1 + (temp_out[j] > 0)) >> 2;
|
||||
}
|
||||
|
||||
// Rows
|
||||
for (i = 0; i < 32; ++i) {
|
||||
tran_high_t temp_in[32], temp_out[32];
|
||||
for (j = 0; j < 32; ++j) temp_in[j] = output[j + i * 32];
|
||||
aom_fdct32(temp_in, temp_out, 1);
|
||||
for (j = 0; j < 32; ++j) out[j + i * 32] = (tran_low_t)temp_out[j];
|
||||
}
|
||||
}
|
||||
|
||||
void aom_fdct32x32_1_c(const int16_t *input, tran_low_t *output, int stride) {
|
||||
int r, c;
|
||||
int sum = 0;
|
||||
for (r = 0; r < 32; ++r)
|
||||
for (c = 0; c < 32; ++c) sum += input[r * stride + c];
|
||||
|
||||
output[0] = (tran_low_t)(sum >> 3);
|
||||
}
|
||||
|
||||
#if CONFIG_HIGHBITDEPTH
|
||||
void aom_highbd_fdct4x4_c(const int16_t *input, tran_low_t *output,
|
||||
int stride) {
|
||||
aom_fdct4x4_c(input, output, stride);
|
||||
}
|
||||
|
||||
void aom_highbd_fdct8x8_c(const int16_t *input, tran_low_t *final_output,
|
||||
int stride) {
|
||||
aom_fdct8x8_c(input, final_output, stride);
|
||||
}
|
||||
|
||||
void aom_highbd_fdct8x8_1_c(const int16_t *input, tran_low_t *final_output,
|
||||
int stride) {
|
||||
aom_fdct8x8_1_c(input, final_output, stride);
|
||||
}
|
||||
|
||||
void aom_highbd_fdct16x16_c(const int16_t *input, tran_low_t *output,
|
||||
int stride) {
|
||||
aom_fdct16x16_c(input, output, stride);
|
||||
}
|
||||
|
||||
void aom_highbd_fdct16x16_1_c(const int16_t *input, tran_low_t *output,
|
||||
int stride) {
|
||||
aom_fdct16x16_1_c(input, output, stride);
|
||||
}
|
||||
|
||||
void aom_highbd_fdct32x32_c(const int16_t *input, tran_low_t *out, int stride) {
|
||||
aom_fdct32x32_c(input, out, stride);
|
||||
}
|
||||
|
||||
void aom_highbd_fdct32x32_rd_c(const int16_t *input, tran_low_t *out,
|
||||
int stride) {
|
||||
aom_fdct32x32_rd_c(input, out, stride);
|
||||
}
|
||||
|
||||
void aom_highbd_fdct32x32_1_c(const int16_t *input, tran_low_t *out,
|
||||
int stride) {
|
||||
aom_fdct32x32_1_c(input, out, stride);
|
||||
}
|
||||
#endif // CONFIG_HIGHBITDEPTH
|
||||
29
third_party/aom/aom_dsp/fwd_txfm.h
vendored
Normal file
29
third_party/aom/aom_dsp/fwd_txfm.h
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
|
||||
*
|
||||
* This source code is subject to the terms of the BSD 2 Clause License and
|
||||
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
|
||||
* was not distributed with this source code in the LICENSE file, you can
|
||||
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
|
||||
* Media Patent License 1.0 was not distributed with this source code in the
|
||||
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
|
||||
*/
|
||||
|
||||
#ifndef AOM_DSP_FWD_TXFM_H_
|
||||
#define AOM_DSP_FWD_TXFM_H_
|
||||
|
||||
#include "aom_dsp/txfm_common.h"
|
||||
|
||||
static INLINE tran_high_t saturate_int16(tran_high_t value) {
|
||||
tran_high_t result;
|
||||
result = value > INT16_MAX ? INT16_MAX : value;
|
||||
return result < INT16_MIN ? INT16_MIN : result;
|
||||
}
|
||||
|
||||
static INLINE tran_high_t fdct_round_shift(tran_high_t input) {
|
||||
tran_high_t rv = ROUND_POWER_OF_TWO(input, DCT_CONST_BITS);
|
||||
return rv;
|
||||
}
|
||||
|
||||
void aom_fdct32(const tran_high_t *input, tran_high_t *output, int round);
|
||||
#endif // AOM_DSP_FWD_TXFM_H_
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue