1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * Copyright (c) 2014 RISC OS Open Ltd
3cabdff1aSopenharmony_ci * Author: Ben Avison <bavison@riscosopen.org>
4cabdff1aSopenharmony_ci *
5cabdff1aSopenharmony_ci * This file is part of FFmpeg.
6cabdff1aSopenharmony_ci *
7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
11cabdff1aSopenharmony_ci *
12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15cabdff1aSopenharmony_ci * Lesser General Public License for more details.
16cabdff1aSopenharmony_ci *
17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20cabdff1aSopenharmony_ci */
21cabdff1aSopenharmony_ci
22cabdff1aSopenharmony_ci#include <stdint.h>
23cabdff1aSopenharmony_ci
24cabdff1aSopenharmony_ci#include "libavutil/arm/cpu.h"
25cabdff1aSopenharmony_ci#include "libavutil/attributes.h"
26cabdff1aSopenharmony_ci#include "libavcodec/mlpdsp.h"
27cabdff1aSopenharmony_ci
28cabdff1aSopenharmony_civoid ff_mlp_filter_channel_arm(int32_t *state, const int32_t *coeff,
29cabdff1aSopenharmony_ci                               int firorder, int iirorder,
30cabdff1aSopenharmony_ci                               unsigned int filter_shift, int32_t mask,
31cabdff1aSopenharmony_ci                               int blocksize, int32_t *sample_buffer);
32cabdff1aSopenharmony_civoid ff_mlp_rematrix_channel_arm(int32_t *samples,
33cabdff1aSopenharmony_ci                                 const int32_t *coeffs,
34cabdff1aSopenharmony_ci                                 const uint8_t *bypassed_lsbs,
35cabdff1aSopenharmony_ci                                 const int8_t *noise_buffer,
36cabdff1aSopenharmony_ci                                 int index,
37cabdff1aSopenharmony_ci                                 unsigned int dest_ch,
38cabdff1aSopenharmony_ci                                 uint16_t blockpos,
39cabdff1aSopenharmony_ci                                 unsigned int maxchan,
40cabdff1aSopenharmony_ci                                 int matrix_noise_shift,
41cabdff1aSopenharmony_ci                                 int access_unit_size_pow2,
42cabdff1aSopenharmony_ci                                 int32_t mask);
43cabdff1aSopenharmony_ci
44cabdff1aSopenharmony_ci#define DECLARE_PACK(order,channels,shift) \
45cabdff1aSopenharmony_ci    int32_t ff_mlp_pack_output_##order##order_##channels##ch_##shift##shift_armv6(int32_t, uint16_t, int32_t (*)[], void *, uint8_t*, int8_t *, uint8_t, int);
46cabdff1aSopenharmony_ci#define ENUMERATE_PACK(order,channels,shift) \
47cabdff1aSopenharmony_ci    ff_mlp_pack_output_##order##order_##channels##ch_##shift##shift_armv6,
48cabdff1aSopenharmony_ci#define PACK_CHANNELS(macro,order,channels) \
49cabdff1aSopenharmony_ci        macro(order,channels,0) \
50cabdff1aSopenharmony_ci        macro(order,channels,1) \
51cabdff1aSopenharmony_ci        macro(order,channels,2) \
52cabdff1aSopenharmony_ci        macro(order,channels,3) \
53cabdff1aSopenharmony_ci        macro(order,channels,4) \
54cabdff1aSopenharmony_ci        macro(order,channels,5) \
55cabdff1aSopenharmony_ci        macro(order,channels,mixed)
56cabdff1aSopenharmony_ci#define PACK_ORDER(macro,order) \
57cabdff1aSopenharmony_ci        PACK_CHANNELS(macro,order,2) \
58cabdff1aSopenharmony_ci        PACK_CHANNELS(macro,order,6) \
59cabdff1aSopenharmony_ci        PACK_CHANNELS(macro,order,8)
60cabdff1aSopenharmony_ci#define PACK_ALL(macro) \
61cabdff1aSopenharmony_ci        PACK_ORDER(macro,outof) \
62cabdff1aSopenharmony_ci        PACK_ORDER(macro,in)
63cabdff1aSopenharmony_ciPACK_ALL(DECLARE_PACK)
64cabdff1aSopenharmony_ci
65cabdff1aSopenharmony_ci#define ff_mlp_pack_output_outoforder_2ch_mixedshift_armv6 0
66cabdff1aSopenharmony_ci#define ff_mlp_pack_output_outoforder_6ch_mixedshift_armv6 0
67cabdff1aSopenharmony_ci#define ff_mlp_pack_output_outoforder_8ch_mixedshift_armv6 0
68cabdff1aSopenharmony_ci#if CONFIG_THUMB
69cabdff1aSopenharmony_ci#define ff_mlp_pack_output_outoforder_2ch_0shift_armv6 0
70cabdff1aSopenharmony_ci#define ff_mlp_pack_output_outoforder_2ch_1shift_armv6 0
71cabdff1aSopenharmony_ci#define ff_mlp_pack_output_outoforder_2ch_2shift_armv6 0
72cabdff1aSopenharmony_ci#define ff_mlp_pack_output_outoforder_2ch_3shift_armv6 0
73cabdff1aSopenharmony_ci#define ff_mlp_pack_output_outoforder_2ch_4shift_armv6 0
74cabdff1aSopenharmony_ci#define ff_mlp_pack_output_outoforder_2ch_5shift_armv6 0
75cabdff1aSopenharmony_ci#define ff_mlp_pack_output_outoforder_6ch_0shift_armv6 0
76cabdff1aSopenharmony_ci#define ff_mlp_pack_output_outoforder_6ch_1shift_armv6 0
77cabdff1aSopenharmony_ci#define ff_mlp_pack_output_outoforder_6ch_2shift_armv6 0
78cabdff1aSopenharmony_ci#define ff_mlp_pack_output_outoforder_6ch_3shift_armv6 0
79cabdff1aSopenharmony_ci#define ff_mlp_pack_output_outoforder_6ch_4shift_armv6 0
80cabdff1aSopenharmony_ci#define ff_mlp_pack_output_outoforder_6ch_5shift_armv6 0
81cabdff1aSopenharmony_ci#define ff_mlp_pack_output_outoforder_8ch_0shift_armv6 0
82cabdff1aSopenharmony_ci#define ff_mlp_pack_output_outoforder_8ch_1shift_armv6 0
83cabdff1aSopenharmony_ci#define ff_mlp_pack_output_outoforder_8ch_2shift_armv6 0
84cabdff1aSopenharmony_ci#define ff_mlp_pack_output_outoforder_8ch_3shift_armv6 0
85cabdff1aSopenharmony_ci#define ff_mlp_pack_output_outoforder_8ch_4shift_armv6 0
86cabdff1aSopenharmony_ci#define ff_mlp_pack_output_outoforder_8ch_5shift_armv6 0
87cabdff1aSopenharmony_ci#endif
88cabdff1aSopenharmony_ci
89cabdff1aSopenharmony_cistatic int32_t (*mlp_select_pack_output_armv6(uint8_t *ch_assign,
90cabdff1aSopenharmony_ci                                              int8_t *output_shift,
91cabdff1aSopenharmony_ci                                              uint8_t max_matrix_channel,
92cabdff1aSopenharmony_ci                                              int is32))(int32_t, uint16_t, int32_t (*)[], void *, uint8_t*, int8_t *, uint8_t, int)
93cabdff1aSopenharmony_ci{
94cabdff1aSopenharmony_ci    int ch_index;
95cabdff1aSopenharmony_ci    int shift = output_shift[0] < 0 || output_shift[0] > 5 ? 6 : output_shift[0];
96cabdff1aSopenharmony_ci    int inorder = 1;
97cabdff1aSopenharmony_ci    static int32_t (*const routine[2*3*7])(int32_t, uint16_t, int32_t (*)[], void *, uint8_t*, int8_t *, uint8_t, int) = {
98cabdff1aSopenharmony_ci            PACK_ALL(ENUMERATE_PACK)
99cabdff1aSopenharmony_ci    };
100cabdff1aSopenharmony_ci    int i;
101cabdff1aSopenharmony_ci
102cabdff1aSopenharmony_ci    if (!is32) // don't support 16-bit output (it's not used by TrueHD)
103cabdff1aSopenharmony_ci        return ff_mlp_pack_output;
104cabdff1aSopenharmony_ci
105cabdff1aSopenharmony_ci    switch (max_matrix_channel) {
106cabdff1aSopenharmony_ci    case 1:
107cabdff1aSopenharmony_ci        ch_index = 0;
108cabdff1aSopenharmony_ci        break;
109cabdff1aSopenharmony_ci    case 5:
110cabdff1aSopenharmony_ci        ch_index = 1;
111cabdff1aSopenharmony_ci        break;
112cabdff1aSopenharmony_ci    case 7:
113cabdff1aSopenharmony_ci        ch_index = 2;
114cabdff1aSopenharmony_ci        break;
115cabdff1aSopenharmony_ci    default:
116cabdff1aSopenharmony_ci        return ff_mlp_pack_output;
117cabdff1aSopenharmony_ci    }
118cabdff1aSopenharmony_ci
119cabdff1aSopenharmony_ci    for (i = 0; i <= max_matrix_channel; i++) {
120cabdff1aSopenharmony_ci        if (shift != 6 && output_shift[i] != shift)
121cabdff1aSopenharmony_ci            shift = 6; // indicate mixed shifts
122cabdff1aSopenharmony_ci        if (ch_assign[i] != i)
123cabdff1aSopenharmony_ci            inorder = 0;
124cabdff1aSopenharmony_ci    }
125cabdff1aSopenharmony_ci#if CONFIG_THUMB
126cabdff1aSopenharmony_ci    if (!inorder)
127cabdff1aSopenharmony_ci        return ff_mlp_pack_output; // can't currently handle an order array except in ARM mode
128cabdff1aSopenharmony_ci#else
129cabdff1aSopenharmony_ci    if (shift == 6 && !inorder)
130cabdff1aSopenharmony_ci        return ff_mlp_pack_output; // can't currently handle both an order array and a shift array
131cabdff1aSopenharmony_ci#endif
132cabdff1aSopenharmony_ci
133cabdff1aSopenharmony_ci    return routine[(inorder*3+ch_index)*7+shift];
134cabdff1aSopenharmony_ci}
135cabdff1aSopenharmony_ci
136cabdff1aSopenharmony_ciav_cold void ff_mlpdsp_init_arm(MLPDSPContext *c)
137cabdff1aSopenharmony_ci{
138cabdff1aSopenharmony_ci    int cpu_flags = av_get_cpu_flags();
139cabdff1aSopenharmony_ci
140cabdff1aSopenharmony_ci    if (have_armv5te(cpu_flags)) {
141cabdff1aSopenharmony_ci        c->mlp_filter_channel = ff_mlp_filter_channel_arm;
142cabdff1aSopenharmony_ci        c->mlp_rematrix_channel = ff_mlp_rematrix_channel_arm;
143cabdff1aSopenharmony_ci    }
144cabdff1aSopenharmony_ci    if (have_armv6(cpu_flags))
145cabdff1aSopenharmony_ci        c->mlp_select_pack_output = mlp_select_pack_output_armv6;
146cabdff1aSopenharmony_ci}
147