FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/nellymoserenc.c
Date: 2026-10-08 18:39:17
Exec Total Coverage
Lines: 169 190 88.9%
Functions: 9 9 100.0%
Branches: 94 120 78.3%

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/mem.h"
42 #include "libavutil/thread.h"
43 #include "libavutil/tx.h"
44
45 #include "audio_frame_queue.h"
46 #include "avcodec.h"
47 #include "codec_internal.h"
48 #include "encode.h"
49 #include "nellymoser.h"
50 #include "sinewin.h"
51
52 #define BITSTREAM_WRITER_LE
53 #include "put_bits.h"
54
55 #define POW_TABLE_SIZE (1<<11)
56 #define POW_TABLE_OFFSET 3
57 #define OPT_SIZE ((1<<15) + 3000)
58
59 typedef struct NellyMoserEncodeContext {
60 AVCodecContext *avctx;
61 int last_frame;
62 AVFloatDSPContext *fdsp;
63 AVTXContext *mdct_ctx;
64 av_tx_fn mdct_fn;
65 AudioFrameQueue afq;
66 DECLARE_ALIGNED(32, float, mdct_out)[NELLY_SAMPLES];
67 DECLARE_ALIGNED(32, float, in_buff)[NELLY_SAMPLES];
68 DECLARE_ALIGNED(32, float, buf)[3 * NELLY_BUF_LEN]; ///< sample buffer
69 float (*opt )[OPT_SIZE];
70 uint8_t (*path)[OPT_SIZE];
71 } NellyMoserEncodeContext;
72
73 static float pow_table[POW_TABLE_SIZE]; ///< pow(2, -i / 2048.0 - 3.0);
74
75 static const uint8_t sf_lut[96] = {
76 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4,
77 5, 5, 5, 6, 7, 7, 8, 8, 9, 10, 11, 11, 12, 13, 13, 14,
78 15, 15, 16, 17, 17, 18, 19, 19, 20, 21, 22, 22, 23, 24, 25, 26,
79 27, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 37, 38, 39, 40,
80 41, 41, 42, 43, 44, 45, 45, 46, 47, 48, 49, 50, 51, 52, 52, 53,
81 54, 55, 55, 56, 57, 57, 58, 59, 59, 60, 60, 60, 61, 61, 61, 62,
82 };
83
84 static const uint8_t sf_delta_lut[78] = {
85 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4,
86 4, 5, 5, 5, 6, 6, 7, 7, 8, 8, 9, 10, 10, 11, 11, 12,
87 13, 13, 14, 15, 16, 17, 17, 18, 19, 19, 20, 21, 21, 22, 22, 23,
88 23, 24, 24, 25, 25, 25, 26, 26, 26, 26, 27, 27, 27, 27, 27, 28,
89 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 30,
90 };
91
92 static const uint8_t quant_lut[230] = {
93 0,
94
95 0, 1, 2,
96
97 0, 1, 2, 3, 4, 5, 6,
98
99 0, 1, 1, 2, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11,
100 12, 13, 13, 13, 14,
101
102 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8,
103 8, 9, 10, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
104 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 29,
105 30,
106
107 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3,
108 4, 4, 4, 5, 5, 5, 6, 6, 7, 7, 7, 8, 8, 9, 9, 9,
109 10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15,
110 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 20, 20, 20,
111 21, 21, 22, 22, 23, 23, 24, 25, 26, 26, 27, 28, 29, 30, 31, 32,
112 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 42, 43, 44, 44, 45, 45,
113 46, 47, 47, 48, 48, 49, 49, 50, 50, 50, 51, 51, 51, 52, 52, 52,
114 53, 53, 53, 54, 54, 54, 55, 55, 55, 56, 56, 56, 57, 57, 57, 57,
115 58, 58, 58, 58, 59, 59, 59, 59, 60, 60, 60, 60, 60, 61, 61, 61,
116 61, 61, 61, 61, 62,
117 };
118
119 static const float quant_lut_mul[7] = { 0.0, 0.0, 2.0, 2.0, 5.0, 12.0, 36.6 };
120 static const float quant_lut_add[7] = { 0.0, 0.0, 2.0, 7.0, 21.0, 56.0, 157.0 };
121 static const uint8_t quant_lut_offset[8] = { 0, 0, 1, 4, 11, 32, 81, 230 };
122
123 752 static void apply_mdct(NellyMoserEncodeContext *s)
124 {
125 752 float *in0 = s->buf;
126 752 float *in1 = s->buf + NELLY_BUF_LEN;
127 752 float *in2 = s->buf + 2 * NELLY_BUF_LEN;
128
129 752 s->fdsp->vector_fmul (s->in_buff, in0, ff_sine_128, NELLY_BUF_LEN);
130 752 s->fdsp->vector_fmul_reverse(s->in_buff + NELLY_BUF_LEN, in1, ff_sine_128, NELLY_BUF_LEN);
131 752 s->mdct_fn(s->mdct_ctx, s->mdct_out, s->in_buff, sizeof(float));
132
133 752 s->fdsp->vector_fmul (s->in_buff, in1, ff_sine_128, NELLY_BUF_LEN);
134 752 s->fdsp->vector_fmul_reverse(s->in_buff + NELLY_BUF_LEN, in2, ff_sine_128, NELLY_BUF_LEN);
135 752 s->mdct_fn(s->mdct_ctx, s->mdct_out + NELLY_BUF_LEN, s->in_buff, sizeof(float));
136 752 }
137
138 2 static av_cold int encode_end(AVCodecContext *avctx)
139 {
140 2 NellyMoserEncodeContext *s = avctx->priv_data;
141
142 2 av_tx_uninit(&s->mdct_ctx);
143
144 2 av_freep(&s->opt);
145 2 av_freep(&s->path);
146 2 ff_af_queue_close(&s->afq);
147 2 av_freep(&s->fdsp);
148
149 2 return 0;
150 }
151
152 2 static av_cold void nellymoser_init_static(void)
153 {
154 /* faster way of doing
155 for (int i = 0; i < POW_TABLE_SIZE; i++)
156 pow_table[i] = 2^(-i / 2048.0 - 3.0 + POW_TABLE_OFFSET); */
157 2 pow_table[0] = 1;
158 2 pow_table[1024] = M_SQRT1_2;
159
2/2
✓ Branch 0 taken 1024 times.
✓ Branch 1 taken 2 times.
1026 for (int i = 1; i < 513; i++) {
160 1024 double tmp = exp2(-i / 2048.0);
161 1024 pow_table[i] = tmp;
162 1024 pow_table[1024-i] = M_SQRT1_2 / tmp;
163 1024 pow_table[1024+i] = tmp * M_SQRT1_2;
164 1024 pow_table[2048-i] = 0.5 / tmp;
165 }
166 /* Generate overlap window */
167 2 ff_init_ff_sine_windows(7);
168 2 }
169
170 2 static av_cold int encode_init(AVCodecContext *avctx)
171 {
172 static AVOnce init_static_once = AV_ONCE_INIT;
173 2 NellyMoserEncodeContext *s = avctx->priv_data;
174 2 float scale = 32768.0;
175 int ret;
176
177
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (avctx->sample_rate != 8000 && avctx->sample_rate != 16000 &&
178 ✗ avctx->sample_rate != 11025 &&
179 ✗ avctx->sample_rate != 22050 && avctx->sample_rate != 44100 &&
180 ✗ avctx->strict_std_compliance >= FF_COMPLIANCE_NORMAL) {
181 ✗ av_log(avctx, AV_LOG_ERROR, "Nellymoser works only with 8000, 16000, 11025, 22050 and 44100 sample rate\n");
182 ✗ return AVERROR(EINVAL);
183 }
184
185 2 avctx->frame_size = NELLY_SAMPLES;
186 2 avctx->initial_padding = NELLY_BUF_LEN;
187 2 ff_af_queue_init(avctx, &s->afq);
188 2 s->avctx = avctx;
189
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if ((ret = av_tx_init(&s->mdct_ctx, &s->mdct_fn, AV_TX_FLOAT_MDCT, 0, 128, &scale, 0)) < 0)
190 ✗ return ret;
191 2 s->fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT);
192
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!s->fdsp)
193 ✗ return AVERROR(ENOMEM);
194
195
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (s->avctx->trellis) {
196 1 s->opt = av_malloc(NELLY_BANDS * OPT_SIZE * sizeof(float ));
197 1 s->path = av_malloc(NELLY_BANDS * OPT_SIZE * sizeof(uint8_t));
198
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (!s->opt || !s->path)
199 ✗ return AVERROR(ENOMEM);
200 }
201
202 2 ff_thread_once(&init_static_once, nellymoser_init_static);
203
204 2 return 0;
205 }
206
207 #define find_best(val, table, LUT, LUT_add, LUT_size) \
208 best_idx = \
209 LUT[av_clip ((lrintf(val) >> 8) + LUT_add, 0, LUT_size - 1)]; \
210 if (fabs(val - table[best_idx]) > fabs(val - table[best_idx + 1])) \
211 best_idx++;
212
213 376 static void get_exponent_greedy(NellyMoserEncodeContext *s, float *cand, int *idx_table)
214 {
215 376 int band, best_idx, power_idx = 0;
216 float power_candidate;
217
218 //base exponent
219
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);
220 376 idx_table[0] = best_idx;
221 376 power_idx = ff_nelly_init_table[best_idx];
222
223
2/2
✓ Branch 0 taken 8272 times.
✓ Branch 1 taken 376 times.
8648 for (band = 1; band < NELLY_BANDS; band++) {
224 8272 power_candidate = cand[band] - power_idx;
225
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);
226 8272 idx_table[band] = best_idx;
227 8272 power_idx += ff_nelly_delta_table[best_idx];
228 }
229 376 }
230
231 72699160 static inline float distance(float x, float y, int band)
232 {
233 //return pow(fabs(x-y), 2.0);
234 72699160 float tmp = x - y;
235 72699160 return tmp * tmp;
236 }
237
238 376 static int get_exponent_dynamic(NellyMoserEncodeContext *s, float *cand, int *idx_table)
239 {
240 int i, j, band, best_idx;
241 float power_candidate, best_val;
242
243 376 float (*opt )[OPT_SIZE] = s->opt ;
244 376 uint8_t(*path)[OPT_SIZE] = s->path;
245
246
2/2
✓ Branch 0 taken 8648 times.
✓ Branch 1 taken 376 times.
9024 for (band = 0; band < NELLY_BANDS; band++)
247
2/2
✓ Branch 0 taken 309321664 times.
✓ Branch 1 taken 8648 times.
309330312 for (i = 0; i < OPT_SIZE; i++)
248 309321664 opt[band][i] = INFINITY;
249
250
2/2
✓ Branch 0 taken 24064 times.
✓ Branch 1 taken 376 times.
24440 for (i = 0; i < 64; i++) {
251 24064 opt[0][ff_nelly_init_table[i]] = distance(cand[0], ff_nelly_init_table[i], 0);
252 24064 path[0][ff_nelly_init_table[i]] = i;
253 }
254
255
2/2
✓ Branch 0 taken 8272 times.
✓ Branch 1 taken 376 times.
8648 for (band = 1; band < NELLY_BANDS; band++) {
256 8272 int q, c = 0;
257 float tmp;
258 int idx_min, idx_max, idx;
259 8272 power_candidate = cand[band];
260
3/4
✓ Branch 0 taken 10116 times.
✓ Branch 1 taken 8272 times.
✓ Branch 2 taken 10116 times.
✗ Branch 3 not taken.
18388 for (q = 1000; !c && q < 2 * OPT_SIZE; q <<= 2) {
261
2/2
✓ Branch 0 taken 3380 times.
✓ Branch 1 taken 6736 times.
10116 idx_min = FFMAX(0, cand[band] - q);
262
2/2
✓ Branch 0 taken 9737 times.
✓ Branch 1 taken 379 times.
10116 idx_max = FFMIN(OPT_SIZE - 1, cand[band - 1] + q);
263
6/6
✓ Branch 0 taken 3275 times.
✓ Branch 1 taken 6841 times.
✓ Branch 2 taken 30912292 times.
✓ Branch 3 taken 9076647 times.
✓ Branch 4 taken 39978823 times.
✓ Branch 5 taken 10116 times.
39988939 for (i = FFMAX(0, cand[band - 1] - q); i < FFMIN(OPT_SIZE, cand[band - 1] + q); i++) {
264
4/4
✓ Branch 0 taken 30561031 times.
✓ Branch 1 taken 9417792 times.
✓ Branch 2 taken 30561031 times.
✓ Branch 3 taken 9417792 times.
39978823 if ( isinf(opt[band - 1][i]) )
265 30561031 continue;
266
2/2
✓ Branch 0 taken 211153121 times.
✓ Branch 1 taken 469360 times.
211622481 for (j = 0; j < 32; j++) {
267 211153121 idx = i + ff_nelly_delta_table[j];
268
2/2
✓ Branch 0 taken 8948432 times.
✓ Branch 1 taken 202204689 times.
211153121 if (idx > idx_max)
269 8948432 break;
270
2/2
✓ Branch 0 taken 72675096 times.
✓ Branch 1 taken 129529593 times.
202204689 if (idx >= idx_min) {
271 72675096 tmp = opt[band - 1][i] + distance(idx, power_candidate, band);
272
2/2
✓ Branch 0 taken 41382849 times.
✓ Branch 1 taken 31292247 times.
72675096 if (opt[band][idx] > tmp) {
273 41382849 opt[band][idx] = tmp;
274 41382849 path[band][idx] = j;
275 41382849 c = 1;
276 }
277 }
278 }
279 }
280 }
281 }
282
283 376 best_val = INFINITY;
284 376 best_idx = -1;
285 376 band = NELLY_BANDS - 1;
286
2/2
✓ Branch 0 taken 13448768 times.
✓ Branch 1 taken 376 times.
13449144 for (i = 0; i < OPT_SIZE; i++) {
287
2/2
✓ Branch 0 taken 35943 times.
✓ Branch 1 taken 13412825 times.
13448768 if (best_val > opt[band][i]) {
288 35943 best_val = opt[band][i];
289 35943 best_idx = i;
290 }
291 }
292
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 376 times.
376 if (best_idx < 0)
293 ✗ return AVERROR(EINVAL);
294
2/2
✓ Branch 0 taken 8648 times.
✓ Branch 1 taken 376 times.
9024 for (band = NELLY_BANDS - 1; band >= 0; band--) {
295 8648 idx_table[band] = path[band][best_idx];
296
2/2
✓ Branch 0 taken 8272 times.
✓ Branch 1 taken 376 times.
8648 if (band) {
297 8272 best_idx -= ff_nelly_delta_table[path[band][best_idx]];
298 }
299 }
300 376 return 0;
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 752 static int encode_block(NellyMoserEncodeContext *s, unsigned char *output, int output_size)
310 {
311 PutBitContext pb;
312 752 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 752 apply_mdct(s);
319
320 752 init_put_bits(&pb, output, output_size);
321
322 752 i = 0;
323
2/2
✓ Branch 0 taken 17296 times.
✓ Branch 1 taken 752 times.
18048 for (band = 0; band < NELLY_BANDS; band++) {
324 17296 coeff_sum = 0;
325
2/2
✓ Branch 0 taken 93248 times.
✓ Branch 1 taken 17296 times.
110544 for (j = 0; j < ff_nelly_band_sizes_table[band]; i++, j++) {
326 93248 coeff_sum += s->mdct_out[i ] * s->mdct_out[i ]
327 93248 + s->mdct_out[i + NELLY_BUF_LEN] * s->mdct_out[i + NELLY_BUF_LEN];
328 }
329 17296 cand[band] =
330
2/2
✓ Branch 0 taken 5310 times.
✓ Branch 1 taken 11986 times.
17296 log2(FFMAX(1.0, coeff_sum / (ff_nelly_band_sizes_table[band] << 7))) * 1024.0;
331
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17296 times.
17296 if (!isfinite(cand[band])) {
332 ✗ av_log(s->avctx, AV_LOG_ERROR, "Input contains NaN/+-Inf\n");
333 ✗ return AVERROR(EINVAL);
334 }
335 }
336
337
2/2
✓ Branch 0 taken 376 times.
✓ Branch 1 taken 376 times.
752 if (s->avctx->trellis) {
338 376 int ret = get_exponent_dynamic(s, cand, idx_table);
339
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 376 times.
376 if (ret < 0)
340 ✗ return ret;
341 } else {
342 376 get_exponent_greedy(s, cand, idx_table);
343 }
344
345 752 i = 0;
346
2/2
✓ Branch 0 taken 17296 times.
✓ Branch 1 taken 752 times.
18048 for (band = 0; band < NELLY_BANDS; band++) {
347
2/2
✓ Branch 0 taken 16544 times.
✓ Branch 1 taken 752 times.
17296 if (band) {
348 16544 power_idx += ff_nelly_delta_table[idx_table[band]];
349 16544 put_bits(&pb, 5, idx_table[band]);
350 } else {
351 752 power_idx = ff_nelly_init_table[idx_table[0]];
352 752 put_bits(&pb, 6, idx_table[0]);
353 }
354
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17296 times.
17296 if (power_idx >= (31 - POW_TABLE_OFFSET) << 11)
355 ✗ return AVERROR(EINVAL);
356 17296 power_val = pow_table[power_idx & 0x7FF] / (1 << ((power_idx >> 11) + POW_TABLE_OFFSET));
357
2/2
✓ Branch 0 taken 93248 times.
✓ Branch 1 taken 17296 times.
110544 for (j = 0; j < ff_nelly_band_sizes_table[band]; i++, j++) {
358 93248 s->mdct_out[i] *= power_val;
359 93248 s->mdct_out[i + NELLY_BUF_LEN] *= power_val;
360 93248 pows[i] = power_idx;
361 }
362 }
363
364 752 ff_nelly_get_sample_bits(pows, bits);
365
366
2/2
✓ Branch 0 taken 1504 times.
✓ Branch 1 taken 752 times.
2256 for (block = 0; block < 2; block++) {
367
2/2
✓ Branch 0 taken 186496 times.
✓ Branch 1 taken 1504 times.
188000 for (i = 0; i < NELLY_FILL_LEN; i++) {
368
2/2
✓ Branch 0 taken 153444 times.
✓ Branch 1 taken 33052 times.
186496 if (bits[i] > 0) {
369 153444 const float *table = ff_nelly_dequantization_table + (1 << bits[i]) - 1;
370 153444 coeff = s->mdct_out[block * NELLY_BUF_LEN + i];
371 153444 best_idx =
372 153444 quant_lut[av_clip (
373 153444 coeff * quant_lut_mul[bits[i]] + quant_lut_add[bits[i]],
374 153444 quant_lut_offset[bits[i]],
375 153444 quant_lut_offset[bits[i]+1] - 1
376 )];
377
2/2
✓ Branch 0 taken 104988 times.
✓ Branch 1 taken 48456 times.
153444 if (fabs(coeff - table[best_idx]) > fabs(coeff - table[best_idx + 1]))
378 104988 best_idx++;
379
380 153444 put_bits(&pb, bits[i], best_idx);
381 }
382 }
383
2/2
✓ Branch 0 taken 752 times.
✓ Branch 1 taken 752 times.
1504 if (!block)
384 752 put_bits(&pb, NELLY_HEADER_BITS + NELLY_DETAIL_BITS - put_bits_count(&pb), 0);
385 }
386
387 752 flush_put_bits(&pb);
388 752 memset(put_bits_ptr(&pb), 0, output + output_size - put_bits_ptr(&pb));
389 752 return 0;
390 }
391
392 754 static int encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
393 const AVFrame *frame, int *got_packet_ptr)
394 {
395 754 NellyMoserEncodeContext *s = avctx->priv_data;
396 int ret;
397
398
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 752 times.
754 if (s->last_frame)
399 2 return 0;
400
401 752 memcpy(s->buf, s->buf + NELLY_SAMPLES, NELLY_BUF_LEN * sizeof(*s->buf));
402
2/2
✓ Branch 0 taken 750 times.
✓ Branch 1 taken 2 times.
752 if (frame) {
403 750 memcpy(s->buf + NELLY_BUF_LEN, frame->data[0],
404 750 frame->nb_samples * sizeof(*s->buf));
405
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 750 times.
750 if (frame->nb_samples < NELLY_SAMPLES) {
406 ✗ memset(s->buf + NELLY_BUF_LEN + frame->nb_samples, 0,
407 ✗ (NELLY_SAMPLES - frame->nb_samples) * sizeof(*s->buf));
408 ✗ if (frame->nb_samples >= NELLY_BUF_LEN)
409 ✗ s->last_frame = 1;
410 }
411
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 750 times.
750 if ((ret = ff_af_queue_add(&s->afq, frame)) < 0)
412 ✗ return ret;
413 } else {
414 2 memset(s->buf + NELLY_BUF_LEN, 0, NELLY_SAMPLES * sizeof(*s->buf));
415 2 s->last_frame = 1;
416 }
417
418
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 752 times.
752 if ((ret = ff_get_encode_buffer(avctx, avpkt, NELLY_BLOCK_LEN, 0)) < 0)
419 ✗ return ret;
420
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 752 times.
752 if ((ret = encode_block(s, avpkt->data, avpkt->size)) < 0)
421 ✗ return ret;
422
423 /* Get the next frame pts/duration */
424 752 ret = ff_af_queue_remove(&s->afq, avctx->frame_size, avpkt);
425
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 752 times.
752 if (ret < 0)
426 ✗ return ret;
427
428 752 *got_packet_ptr = 1;
429 752 return 0;
430 }
431
432 const FFCodec ff_nellymoser_encoder = {
433 .p.name = "nellymoser",
434 CODEC_LONG_NAME("Nellymoser Asao"),
435 .p.type = AVMEDIA_TYPE_AUDIO,
436 .p.id = AV_CODEC_ID_NELLYMOSER,
437 .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
438 AV_CODEC_CAP_SMALL_LAST_FRAME,
439 .priv_data_size = sizeof(NellyMoserEncodeContext),
440 .init = encode_init,
441 FF_CODEC_ENCODE_CB(encode_frame),
442 .close = encode_end,
443 CODEC_SAMPLEFMTS(AV_SAMPLE_FMT_FLT),
444 CODEC_CH_LAYOUTS(AV_CHANNEL_LAYOUT_MONO),
445 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
446 };
447