FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/nellymoserenc.c
Date: 2021-09-24 20:55:06
Exec Total Coverage
Lines: 117 178 65.7%
Branches: 44 108 40.7%

Line Branch Exec Source
1 /*
2 * Nellymoser encoder
3 * This code is developed as part of Google Summer of Code 2008 Program.
4 *
5 * Copyright (c) 2008 Bartlomiej Wolowiec
6 *
7 * This file is part of FFmpeg.
8 *
9 * FFmpeg is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * FFmpeg is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with FFmpeg; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24 /**
25 * @file
26 * Nellymoser encoder
27 * by Bartlomiej Wolowiec
28 *
29 * Generic codec information: libavcodec/nellymoserdec.c
30 *
31 * Some information also from: http://samples.mplayerhq.hu/A-codecs/Nelly_Moser/ASAO/ASAO.zip
32 * (Copyright Joseph Artsimovich and UAB "DKD")
33 *
34 * for more information about nellymoser format, visit:
35 * http://wiki.multimedia.cx/index.php?title=Nellymoser
36 */
37
38 #include "libavutil/common.h"
39 #include "libavutil/float_dsp.h"
40 #include "libavutil/mathematics.h"
41 #include "libavutil/thread.h"
42
43 #include "audio_frame_queue.h"
44 #include "avcodec.h"
45 #include "encode.h"
46 #include "fft.h"
47 #include "internal.h"
48 #include "nellymoser.h"
49 #include "sinewin.h"
50
51 #define BITSTREAM_WRITER_LE
52 #include "put_bits.h"
53
54 #define POW_TABLE_SIZE (1<<11)
55 #define POW_TABLE_OFFSET 3
56 #define OPT_SIZE ((1<<15) + 3000)
57
58 typedef struct NellyMoserEncodeContext {
59 AVCodecContext *avctx;
60 int last_frame;
61 AVFloatDSPContext *fdsp;
62 FFTContext mdct_ctx;
63 AudioFrameQueue afq;
64 DECLARE_ALIGNED(32, float, mdct_out)[NELLY_SAMPLES];
65 DECLARE_ALIGNED(32, float, in_buff)[NELLY_SAMPLES];
66 DECLARE_ALIGNED(32, float, buf)[3 * NELLY_BUF_LEN]; ///< sample buffer
67 float (*opt )[OPT_SIZE];
68 uint8_t (*path)[OPT_SIZE];
69 } NellyMoserEncodeContext;
70
71 static float pow_table[POW_TABLE_SIZE]; ///< pow(2, -i / 2048.0 - 3.0);
72
73 static const uint8_t sf_lut[96] = {
74 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4,
75 5, 5, 5, 6, 7, 7, 8, 8, 9, 10, 11, 11, 12, 13, 13, 14,
76 15, 15, 16, 17, 17, 18, 19, 19, 20, 21, 22, 22, 23, 24, 25, 26,
77 27, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 37, 38, 39, 40,
78 41, 41, 42, 43, 44, 45, 45, 46, 47, 48, 49, 50, 51, 52, 52, 53,
79 54, 55, 55, 56, 57, 57, 58, 59, 59, 60, 60, 60, 61, 61, 61, 62,
80 };
81
82 static const uint8_t sf_delta_lut[78] = {
83 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4,
84 4, 5, 5, 5, 6, 6, 7, 7, 8, 8, 9, 10, 10, 11, 11, 12,
85 13, 13, 14, 15, 16, 17, 17, 18, 19, 19, 20, 21, 21, 22, 22, 23,
86 23, 24, 24, 25, 25, 25, 26, 26, 26, 26, 27, 27, 27, 27, 27, 28,
87 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 30,
88 };
89
90 static const uint8_t quant_lut[230] = {
91 0,
92
93 0, 1, 2,
94
95 0, 1, 2, 3, 4, 5, 6,
96
97 0, 1, 1, 2, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11,
98 12, 13, 13, 13, 14,
99
100 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8,
101 8, 9, 10, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
102 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 29,
103 30,
104
105 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3,
106 4, 4, 4, 5, 5, 5, 6, 6, 7, 7, 7, 8, 8, 9, 9, 9,
107 10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15,
108 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 20, 20, 20,
109 21, 21, 22, 22, 23, 23, 24, 25, 26, 26, 27, 28, 29, 30, 31, 32,
110 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 42, 43, 44, 44, 45, 45,
111 46, 47, 47, 48, 48, 49, 49, 50, 50, 50, 51, 51, 51, 52, 52, 52,
112 53, 53, 53, 54, 54, 54, 55, 55, 55, 56, 56, 56, 57, 57, 57, 57,
113 58, 58, 58, 58, 59, 59, 59, 59, 60, 60, 60, 60, 60, 61, 61, 61,
114 61, 61, 61, 61, 62,
115 };
116
117 static const float quant_lut_mul[7] = { 0.0, 0.0, 2.0, 2.0, 5.0, 12.0, 36.6 };
118 static const float quant_lut_add[7] = { 0.0, 0.0, 2.0, 7.0, 21.0, 56.0, 157.0 };
119 static const uint8_t quant_lut_offset[8] = { 0, 0, 1, 4, 11, 32, 81, 230 };
120
121 376 static void apply_mdct(NellyMoserEncodeContext *s)
122 {
123 376 float *in0 = s->buf;
124 376 float *in1 = s->buf + NELLY_BUF_LEN;
125 376 float *in2 = s->buf + 2 * NELLY_BUF_LEN;
126
127 376 s->fdsp->vector_fmul (s->in_buff, in0, ff_sine_128, NELLY_BUF_LEN);
128 376 s->fdsp->vector_fmul_reverse(s->in_buff + NELLY_BUF_LEN, in1, ff_sine_128, NELLY_BUF_LEN);
129 376 s->mdct_ctx.mdct_calc(&s->mdct_ctx, s->mdct_out, s->in_buff);
130
131 376 s->fdsp->vector_fmul (s->in_buff, in1, ff_sine_128, NELLY_BUF_LEN);
132 376 s->fdsp->vector_fmul_reverse(s->in_buff + NELLY_BUF_LEN, in2, ff_sine_128, NELLY_BUF_LEN);
133 376 s->mdct_ctx.mdct_calc(&s->mdct_ctx, s->mdct_out + NELLY_BUF_LEN, s->in_buff);
134 376 }
135
136 1 static av_cold int encode_end(AVCodecContext *avctx)
137 {
138 1 NellyMoserEncodeContext *s = avctx->priv_data;
139
140 1 ff_mdct_end(&s->mdct_ctx);
141
142 1 av_freep(&s->opt);
143 1 av_freep(&s->path);
144 1 ff_af_queue_close(&s->afq);
145 1 av_freep(&s->fdsp);
146
147 1 return 0;
148 }
149
150 1 static av_cold void nellymoser_init_static(void)
151 {
152 /* faster way of doing
153 for (int i = 0; i < POW_TABLE_SIZE; i++)
154 pow_table[i] = 2^(-i / 2048.0 - 3.0 + POW_TABLE_OFFSET); */
155 1 pow_table[0] = 1;
156 1 pow_table[1024] = M_SQRT1_2;
157
2/2
✓ Branch 0 taken 512 times.
✓ Branch 1 taken 1 times.
513 for (int i = 1; i < 513; i++) {
158 512 double tmp = exp2(-i / 2048.0);
159 512 pow_table[i] = tmp;
160 512 pow_table[1024-i] = M_SQRT1_2 / tmp;
161 512 pow_table[1024+i] = tmp * M_SQRT1_2;
162 512 pow_table[2048-i] = 0.5 / tmp;
163 }
164 /* Generate overlap window */
165 1 ff_init_ff_sine_windows(7);
166 1 }
167
168 1 static av_cold int encode_init(AVCodecContext *avctx)
169 {
170 static AVOnce init_static_once = AV_ONCE_INIT;
171 1 NellyMoserEncodeContext *s = avctx->priv_data;
172 int ret;
173
174
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (avctx->channels != 1) {
175 av_log(avctx, AV_LOG_ERROR, "Nellymoser supports only 1 channel\n");
176 return AVERROR(EINVAL);
177 }
178
179
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (avctx->sample_rate != 8000 && avctx->sample_rate != 16000 &&
180 avctx->sample_rate != 11025 &&
181 avctx->sample_rate != 22050 && avctx->sample_rate != 44100 &&
182 avctx->strict_std_compliance >= FF_COMPLIANCE_NORMAL) {
183 av_log(avctx, AV_LOG_ERROR, "Nellymoser works only with 8000, 16000, 11025, 22050 and 44100 sample rate\n");
184 return AVERROR(EINVAL);
185 }
186
187 1 avctx->frame_size = NELLY_SAMPLES;
188 1 avctx->initial_padding = NELLY_BUF_LEN;
189 1 ff_af_queue_init(avctx, &s->afq);
190 1 s->avctx = avctx;
191
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if ((ret = ff_mdct_init(&s->mdct_ctx, 8, 0, 32768.0)) < 0)
192 return ret;
193 1 s->fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT);
194
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!s->fdsp)
195 return AVERROR(ENOMEM);
196
197
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (s->avctx->trellis) {
198 s->opt = av_malloc(NELLY_BANDS * OPT_SIZE * sizeof(float ));
199 s->path = av_malloc(NELLY_BANDS * OPT_SIZE * sizeof(uint8_t));
200 if (!s->opt || !s->path)
201 return AVERROR(ENOMEM);
202 }
203
204 1 ff_thread_once(&init_static_once, nellymoser_init_static);
205
206 1 return 0;
207 }
208
209 #define find_best(val, table, LUT, LUT_add, LUT_size) \
210 best_idx = \
211 LUT[av_clip ((lrintf(val) >> 8) + LUT_add, 0, LUT_size - 1)]; \
212 if (fabs(val - table[best_idx]) > fabs(val - table[best_idx + 1])) \
213 best_idx++;
214
215 376 static void get_exponent_greedy(NellyMoserEncodeContext *s, float *cand, int *idx_table)
216 {
217 376 int band, best_idx, power_idx = 0;
218 float power_candidate;
219
220 //base exponent
221
2/2
✓ Branch 0 taken 208 times.
✓ Branch 1 taken 168 times.
376 find_best(cand[0], ff_nelly_init_table, sf_lut, -20, 96);
222 376 idx_table[0] = best_idx;
223 376 power_idx = ff_nelly_init_table[best_idx];
224
225
2/2
✓ Branch 0 taken 8272 times.
✓ Branch 1 taken 376 times.
8648 for (band = 1; band < NELLY_BANDS; band++) {
226 8272 power_candidate = cand[band] - power_idx;
227
2/2
✓ Branch 0 taken 5822 times.
✓ Branch 1 taken 2450 times.
8272 find_best(power_candidate, ff_nelly_delta_table, sf_delta_lut, 37, 78);
228 8272 idx_table[band] = best_idx;
229 8272 power_idx += ff_nelly_delta_table[best_idx];
230 }
231 376 }
232
233 static inline float distance(float x, float y, int band)
234 {
235 //return pow(fabs(x-y), 2.0);
236 float tmp = x - y;
237 return tmp * tmp;
238 }
239
240 static void get_exponent_dynamic(NellyMoserEncodeContext *s, float *cand, int *idx_table)
241 {
242 int i, j, band, best_idx;
243 float power_candidate, best_val;
244
245 float (*opt )[OPT_SIZE] = s->opt ;
246 uint8_t(*path)[OPT_SIZE] = s->path;
247
248 for (i = 0; i < NELLY_BANDS * OPT_SIZE; i++) {
249 opt[0][i] = INFINITY;
250 }
251
252 for (i = 0; i < 64; i++) {
253 opt[0][ff_nelly_init_table[i]] = distance(cand[0], ff_nelly_init_table[i], 0);
254 path[0][ff_nelly_init_table[i]] = i;
255 }
256
257 for (band = 1; band < NELLY_BANDS; band++) {
258 int q, c = 0;
259 float tmp;
260 int idx_min, idx_max, idx;
261 power_candidate = cand[band];
262 for (q = 1000; !c && q < OPT_SIZE; q <<= 2) {
263 idx_min = FFMAX(0, cand[band] - q);
264 idx_max = FFMIN(OPT_SIZE, cand[band - 1] + q);
265 for (i = FFMAX(0, cand[band - 1] - q); i < FFMIN(OPT_SIZE, cand[band - 1] + q); i++) {
266 if ( isinf(opt[band - 1][i]) )
267 continue;
268 for (j = 0; j < 32; j++) {
269 idx = i + ff_nelly_delta_table[j];
270 if (idx > idx_max)
271 break;
272 if (idx >= idx_min) {
273 tmp = opt[band - 1][i] + distance(idx, power_candidate, band);
274 if (opt[band][idx] > tmp) {
275 opt[band][idx] = tmp;
276 path[band][idx] = j;
277 c = 1;
278 }
279 }
280 }
281 }
282 }
283 av_assert1(c); //FIXME
284 }
285
286 best_val = INFINITY;
287 best_idx = -1;
288 band = NELLY_BANDS - 1;
289 for (i = 0; i < OPT_SIZE; i++) {
290 if (best_val > opt[band][i]) {
291 best_val = opt[band][i];
292 best_idx = i;
293 }
294 }
295 for (band = NELLY_BANDS - 1; band >= 0; band--) {
296 idx_table[band] = path[band][best_idx];
297 if (band) {
298 best_idx -= ff_nelly_delta_table[path[band][best_idx]];
299 }
300 }
301 }
302
303 /**
304 * Encode NELLY_SAMPLES samples. It assumes, that samples contains 3 * NELLY_BUF_LEN values
305 * @param s encoder context
306 * @param output output buffer
307 * @param output_size size of output buffer
308 */
309 376 static void encode_block(NellyMoserEncodeContext *s, unsigned char *output, int output_size)
310 {
311 PutBitContext pb;
312 376 int i, j, band, block, best_idx, power_idx = 0;
313 float power_val, coeff, coeff_sum;
314 float pows[NELLY_FILL_LEN];
315 int bits[NELLY_BUF_LEN], idx_table[NELLY_BANDS];
316 float cand[NELLY_BANDS];
317
318 376 apply_mdct(s);
319
320 376 init_put_bits(&pb, output, output_size);
321
322 376 i = 0;
323
2/2
✓ Branch 0 taken 8648 times.
✓ Branch 1 taken 376 times.
9024 for (band = 0; band < NELLY_BANDS; band++) {
324 8648 coeff_sum = 0;
325
2/2
✓ Branch 0 taken 46624 times.
✓ Branch 1 taken 8648 times.
55272 for (j = 0; j < ff_nelly_band_sizes_table[band]; i++, j++) {
326 46624 coeff_sum += s->mdct_out[i ] * s->mdct_out[i ]
327 46624 + s->mdct_out[i + NELLY_BUF_LEN] * s->mdct_out[i + NELLY_BUF_LEN];
328 }
329 8648 cand[band] =
330
2/2
✓ Branch 0 taken 2655 times.
✓ Branch 1 taken 5993 times.
8648 log2(FFMAX(1.0, coeff_sum / (ff_nelly_band_sizes_table[band] << 7))) * 1024.0;
331 }
332
333
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 376 times.
376 if (s->avctx->trellis) {
334 get_exponent_dynamic(s, cand, idx_table);
335 } else {
336 376 get_exponent_greedy(s, cand, idx_table);
337 }
338
339 376 i = 0;
340
2/2
✓ Branch 0 taken 8648 times.
✓ Branch 1 taken 376 times.
9024 for (band = 0; band < NELLY_BANDS; band++) {
341
2/2
✓ Branch 0 taken 8272 times.
✓ Branch 1 taken 376 times.
8648 if (band) {
342 8272 power_idx += ff_nelly_delta_table[idx_table[band]];
343 8272 put_bits(&pb, 5, idx_table[band]);
344 } else {
345 376 power_idx = ff_nelly_init_table[idx_table[0]];
346 376 put_bits(&pb, 6, idx_table[0]);
347 }
348 8648 power_val = pow_table[power_idx & 0x7FF] / (1 << ((power_idx >> 11) + POW_TABLE_OFFSET));
349
2/2
✓ Branch 0 taken 46624 times.
✓ Branch 1 taken 8648 times.
55272 for (j = 0; j < ff_nelly_band_sizes_table[band]; i++, j++) {
350 46624 s->mdct_out[i] *= power_val;
351 46624 s->mdct_out[i + NELLY_BUF_LEN] *= power_val;
352 46624 pows[i] = power_idx;
353 }
354 }
355
356 376 ff_nelly_get_sample_bits(pows, bits);
357
358
2/2
✓ Branch 0 taken 752 times.
✓ Branch 1 taken 376 times.
1128 for (block = 0; block < 2; block++) {
359
2/2
✓ Branch 0 taken 93248 times.
✓ Branch 1 taken 752 times.
94000 for (i = 0; i < NELLY_FILL_LEN; i++) {
360
2/2
✓ Branch 0 taken 76548 times.
✓ Branch 1 taken 16700 times.
93248 if (bits[i] > 0) {
361 76548 const float *table = ff_nelly_dequantization_table + (1 << bits[i]) - 1;
362 76548 coeff = s->mdct_out[block * NELLY_BUF_LEN + i];
363 76548 best_idx =
364 76548 quant_lut[av_clip (
365 76548 coeff * quant_lut_mul[bits[i]] + quant_lut_add[bits[i]],
366 76548 quant_lut_offset[bits[i]],
367 76548 quant_lut_offset[bits[i]+1] - 1
368 )];
369
2/2
✓ Branch 0 taken 52418 times.
✓ Branch 1 taken 24130 times.
76548 if (fabs(coeff - table[best_idx]) > fabs(coeff - table[best_idx + 1]))
370 52418 best_idx++;
371
372 76548 put_bits(&pb, bits[i], best_idx);
373 }
374 }
375
2/2
✓ Branch 0 taken 376 times.
✓ Branch 1 taken 376 times.
752 if (!block)
376 376 put_bits(&pb, NELLY_HEADER_BITS + NELLY_DETAIL_BITS - put_bits_count(&pb), 0);
377 }
378
379 376 flush_put_bits(&pb);
380 376 memset(put_bits_ptr(&pb), 0, output + output_size - put_bits_ptr(&pb));
381 376 }
382
383 377 static int encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
384 const AVFrame *frame, int *got_packet_ptr)
385 {
386 377 NellyMoserEncodeContext *s = avctx->priv_data;
387 int ret;
388
389
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 376 times.
377 if (s->last_frame)
390 1 return 0;
391
392 376 memcpy(s->buf, s->buf + NELLY_SAMPLES, NELLY_BUF_LEN * sizeof(*s->buf));
393
2/2
✓ Branch 0 taken 375 times.
✓ Branch 1 taken 1 times.
376 if (frame) {
394 375 memcpy(s->buf + NELLY_BUF_LEN, frame->data[0],
395 375 frame->nb_samples * sizeof(*s->buf));
396
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 375 times.
375 if (frame->nb_samples < NELLY_SAMPLES) {
397 memset(s->buf + NELLY_BUF_LEN + frame->nb_samples, 0,
398 (NELLY_SAMPLES - frame->nb_samples) * sizeof(*s->buf));
399 if (frame->nb_samples >= NELLY_BUF_LEN)
400 s->last_frame = 1;
401 }
402
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 375 times.
375 if ((ret = ff_af_queue_add(&s->afq, frame)) < 0)
403 return ret;
404 } else {
405 1 memset(s->buf + NELLY_BUF_LEN, 0, NELLY_SAMPLES * sizeof(*s->buf));
406 1 s->last_frame = 1;
407 }
408
409
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 376 times.
376 if ((ret = ff_get_encode_buffer(avctx, avpkt, NELLY_BLOCK_LEN, 0)) < 0)
410 return ret;
411 376 encode_block(s, avpkt->data, avpkt->size);
412
413 /* Get the next frame pts/duration */
414 376 ff_af_queue_remove(&s->afq, avctx->frame_size, &avpkt->pts,
415 &avpkt->duration);
416
417 376 *got_packet_ptr = 1;
418 376 return 0;
419 }
420
421 const AVCodec ff_nellymoser_encoder = {
422 .name = "nellymoser",
423 .long_name = NULL_IF_CONFIG_SMALL("Nellymoser Asao"),
424 .type = AVMEDIA_TYPE_AUDIO,
425 .id = AV_CODEC_ID_NELLYMOSER,
426 .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
427 AV_CODEC_CAP_SMALL_LAST_FRAME,
428 .priv_data_size = sizeof(NellyMoserEncodeContext),
429 .init = encode_init,
430 .encode2 = encode_frame,
431 .close = encode_end,
432 .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT,
433 AV_SAMPLE_FMT_NONE },
434 .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
435 };
436