FFmpeg
dcaadpcm.c
Go to the documentation of this file.
1 /*
2  * DCA ADPCM engine
3  * Copyright (C) 2017 Daniil Cherednik
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 
23 #include "libavutil/mem.h"
24 #include "dcaadpcm.h"
25 #include "dcaenc.h"
26 #include "dca_core.h"
27 #include "mathops.h"
28 
30 
31 //assume we have DCA_ADPCM_COEFFS values before x
32 static inline int64_t calc_corr(const int32_t *x, int len, int j, int k)
33 {
34  int n;
35  int64_t s = 0;
36  for (n = 0; n < len; n++)
37  s += MUL64(x[n-j], x[n-k]);
38  return s;
39 }
40 
41 static inline int64_t apply_filter(const int16_t a[DCA_ADPCM_COEFFS], const int64_t corr[15], const int32_t aa[10])
42 {
43  int64_t err = 0;
44  int64_t tmp = 0;
45 
46  err = corr[0];
47 
48  tmp += MUL64(a[0], corr[1]);
49  tmp += MUL64(a[1], corr[2]);
50  tmp += MUL64(a[2], corr[3]);
51  tmp += MUL64(a[3], corr[4]);
52 
53  tmp = norm__(tmp, 13);
54  tmp += tmp;
55 
56  err -= tmp;
57  tmp = 0;
58 
59  tmp += MUL64(corr[5], aa[0]);
60  tmp += MUL64(corr[6], aa[1]);
61  tmp += MUL64(corr[7], aa[2]);
62  tmp += MUL64(corr[8], aa[3]);
63 
64  tmp += MUL64(corr[9], aa[4]);
65  tmp += MUL64(corr[10], aa[5]);
66  tmp += MUL64(corr[11], aa[6]);
67 
68  tmp += MUL64(corr[12], aa[7]);
69  tmp += MUL64(corr[13], aa[8]);
70 
71  tmp += MUL64(corr[14], aa[9]);
72 
73  tmp = norm__(tmp, 26);
74 
75  err += tmp;
76 
77  return llabs(err);
78 }
79 
80 static int64_t find_best_filter(const DCAADPCMEncContext *s, const int32_t *in, int len)
81 {
82  const premultiplied_coeffs *precalc_data = s->private_data;
83  int i, j, k = 0;
84  int vq = -1;
85  int64_t err;
86  int64_t min_err = 1ll << 62;
87  int64_t corr[15];
88 
89  for (i = 0; i <= DCA_ADPCM_COEFFS; i++)
90  for (j = i; j <= DCA_ADPCM_COEFFS; j++)
91  corr[k++] = calc_corr(in+4, len, i, j);
92 
93  for (i = 0; i < DCA_ADPCM_VQCODEBOOK_SZ; i++) {
94  err = apply_filter(ff_dca_adpcm_vb[i], corr, *precalc_data);
95  if (err < min_err) {
96  min_err = err;
97  vq = i;
98  }
99  precalc_data++;
100  }
101 
102  return vq;
103 }
104 
105 static inline int64_t calc_prediction_gain(int pred_vq, const int32_t *in, int32_t *out, int len)
106 {
107  int i;
108  int32_t error;
109 
110  int64_t signal_energy = 0;
111  int64_t error_energy = 0;
112 
113  for (i = 0; i < len; i++) {
114  error = in[DCA_ADPCM_COEFFS + i] - ff_dcaadpcm_predict(pred_vq, in + i);
115  out[i] = error;
116  signal_energy += MUL64(in[DCA_ADPCM_COEFFS + i], in[DCA_ADPCM_COEFFS + i]);
117  error_energy += MUL64(error, error);
118  }
119 
120  if (!error_energy)
121  return -1;
122 
123  return signal_energy / error_energy;
124 }
125 
127 {
128  int pred_vq, i;
129  int32_t input_buffer[16 + DCA_ADPCM_COEFFS];
130  int32_t input_buffer2[16 + DCA_ADPCM_COEFFS];
131 
132  int32_t max = 0;
133  int shift_bits;
134  uint64_t pg = 0;
135 
136  for (i = 0; i < len + DCA_ADPCM_COEFFS; i++)
137  max |= FFABS(in[i]);
138 
139  // normalize input to simplify apply_filter
140  shift_bits = av_log2(max) - 11;
141 
142  for (i = 0; i < len + DCA_ADPCM_COEFFS; i++) {
143  input_buffer[i] = norm__(in[i], 7);
144  input_buffer2[i] = norm__(in[i], shift_bits);
145  }
146 
147  pred_vq = find_best_filter(s, input_buffer2, len);
148 
149  if (pred_vq < 0)
150  return -1;
151 
152  pg = calc_prediction_gain(pred_vq, input_buffer, diff, len);
153 
154  // Greater than 10db (10*log(10)) prediction gain to use ADPCM.
155  // TODO: Tune it.
156  if (pg < 10)
157  return -1;
158 
159  for (i = 0; i < len; i++)
160  diff[i] <<= 7;
161 
162  return pred_vq;
163 }
164 
166 {
167  int i, j, k;
168 
169  for (i = 0; i < DCA_ADPCM_VQCODEBOOK_SZ; i++) {
170  int id = 0;
171  int32_t t = 0;
172  for (j = 0; j < DCA_ADPCM_COEFFS; j++) {
173  for (k = j; k < DCA_ADPCM_COEFFS; k++) {
175  if (j != k)
176  t *= 2;
177  (*data)[id++] = t;
178  }
179  }
180  data++;
181  }
182 }
183 
184 int ff_dcaadpcm_do_real(int pred_vq_index,
185  softfloat quant, int32_t scale_factor, int32_t step_size,
186  const int32_t *prev_hist, const int32_t *in, int32_t *next_hist, int32_t *out,
187  int len, int32_t peak)
188 {
189  int i;
190  int64_t delta;
191  int32_t dequant_delta;
192  int32_t work_bufer[16 + DCA_ADPCM_COEFFS];
193 
194  memcpy(work_bufer, prev_hist, sizeof(int32_t) * DCA_ADPCM_COEFFS);
195 
196  for (i = 0; i < len; i++) {
197  work_bufer[DCA_ADPCM_COEFFS + i] = ff_dcaadpcm_predict(pred_vq_index, &work_bufer[i]);
198 
199  delta = (int64_t)in[i] - ((int64_t)work_bufer[DCA_ADPCM_COEFFS + i] << 7);
200 
201  out[i] = quantize_value(av_clip64(delta, -peak, peak), quant);
202 
203  ff_dca_core_dequantize(&dequant_delta, &out[i], step_size, scale_factor, 0, 1);
204 
205  work_bufer[DCA_ADPCM_COEFFS+i] += dequant_delta;
206  }
207 
208  memcpy(next_hist, &work_bufer[len], sizeof(int32_t) * DCA_ADPCM_COEFFS);
209 
210  return 0;
211 }
212 
214 {
215  if (!s)
216  return -1;
217 
218  s->private_data = av_malloc(sizeof(premultiplied_coeffs) * DCA_ADPCM_VQCODEBOOK_SZ);
219  if (!s->private_data)
220  return AVERROR(ENOMEM);
221 
222  precalc(s->private_data);
223  return 0;
224 }
225 
227 {
228  if (!s)
229  return;
230 
231  av_freep(&s->private_data);
232 }
error
static void error(const char *err)
Definition: target_bsf_fuzzer.c:32
find_best_filter
static int64_t find_best_filter(const DCAADPCMEncContext *s, const int32_t *in, int len)
Definition: dcaadpcm.c:80
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
ff_dcaadpcm_do_real
int ff_dcaadpcm_do_real(int pred_vq_index, softfloat quant, int32_t scale_factor, int32_t step_size, const int32_t *prev_hist, const int32_t *in, int32_t *next_hist, int32_t *out, int len, int32_t peak)
Definition: dcaadpcm.c:184
DCAADPCMEncContext
Definition: dcaadpcm.h:29
out
FILE * out
Definition: movenc.c:55
ff_dcaadpcm_free
av_cold void ff_dcaadpcm_free(DCAADPCMEncContext *s)
Definition: dcaadpcm.c:226
tmp
static uint8_t tmp[11]
Definition: aes_ctr.c:28
data
const char data[16]
Definition: mxf.c:148
max
#define max(a, b)
Definition: cuda_runtime.h:33
quantize_value
static int32_t quantize_value(int32_t value, softfloat quant)
Definition: dcaenc.h:149
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:30
dca_core.h
av_clip64
#define av_clip64
Definition: common.h:102
quant
static const uint8_t quant[64]
Definition: vmixdec.c:71
av_cold
#define av_cold
Definition: attributes.h:90
ff_dcaadpcm_predict
static int64_t ff_dcaadpcm_predict(int pred_vq_index, const int32_t *input)
Definition: dcaadpcm.h:33
s
#define s(width, name)
Definition: cbs_vp9.c:198
DCA_ADPCM_COEFFS
#define DCA_ADPCM_COEFFS
Definition: dcadata.h:28
apply_filter
static int64_t apply_filter(const int16_t a[DCA_ADPCM_COEFFS], const int64_t corr[15], const int32_t aa[10])
Definition: dcaadpcm.c:41
FFABS
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition: common.h:73
softfloat
Definition: dcaenc.h:29
mathops.h
DCA_ADPCM_VQCODEBOOK_SZ
#define DCA_ADPCM_VQCODEBOOK_SZ
Definition: dcadata.h:29
ff_dcaadpcm_subband_analysis
int ff_dcaadpcm_subband_analysis(const DCAADPCMEncContext *s, const int32_t *in, int len, int *diff)
Definition: dcaadpcm.c:126
dcaadpcm.h
dcaenc.h
diff
static av_always_inline int diff(const struct color_info *a, const struct color_info *b, const int trans_thresh)
Definition: vf_paletteuse.c:165
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
delta
float delta
Definition: vorbis_enc_data.h:430
len
int len
Definition: vorbis_enc_data.h:426
norm__
static int32_t norm__(int64_t a, int bits)
Definition: dcamath.h:27
ff_dca_adpcm_vb
const int16_t ff_dca_adpcm_vb[DCA_ADPCM_VQCODEBOOK_SZ][DCA_ADPCM_COEFFS]
Definition: dcadata.c:60
ff_dca_core_dequantize
static void ff_dca_core_dequantize(int32_t *output, const int32_t *input, int32_t step_size, int32_t scale, int residual, int len)
Definition: dca_core.h:226
ff_dcaadpcm_init
av_cold int ff_dcaadpcm_init(DCAADPCMEncContext *s)
Definition: dcaadpcm.c:213
MUL64
#define MUL64(a, b)
Definition: mathops.h:55
precalc
static void precalc(premultiplied_coeffs *data)
Definition: dcaadpcm.c:165
mem.h
premultiplied_coeffs
int32_t premultiplied_coeffs[10]
Definition: dcaadpcm.c:29
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
int32_t
int32_t
Definition: audioconvert.c:56
av_log2
int av_log2(unsigned v)
Definition: intmath.c:26
calc_prediction_gain
static int64_t calc_prediction_gain(int pred_vq, const int32_t *in, int32_t *out, int len)
Definition: dcaadpcm.c:105
calc_corr
static int64_t calc_corr(const int32_t *x, int len, int j, int k)
Definition: dcaadpcm.c:32