GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavcodec/ra144enc.c Lines: 216 222 97.3 %
Date: 2020-10-23 17:01:47 Branches: 102 108 94.4 %

Line Branch Exec Source
1
/*
2
 * Real Audio 1.0 (14.4K) encoder
3
 * Copyright (c) 2010 Francesco Lavra <francescolavra@interfree.it>
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
 * @file
24
 * Real Audio 1.0 (14.4K) encoder
25
 * @author Francesco Lavra <francescolavra@interfree.it>
26
 */
27
28
#include <float.h>
29
30
#include "avcodec.h"
31
#include "audio_frame_queue.h"
32
#include "celp_filters.h"
33
#include "internal.h"
34
#include "mathops.h"
35
#include "put_bits.h"
36
#include "ra144.h"
37
38
1
static av_cold int ra144_encode_close(AVCodecContext *avctx)
39
{
40
1
    RA144Context *ractx = avctx->priv_data;
41
1
    ff_lpc_end(&ractx->lpc_ctx);
42
1
    ff_af_queue_close(&ractx->afq);
43
1
    return 0;
44
}
45
46
47
1
static av_cold int ra144_encode_init(AVCodecContext * avctx)
48
{
49
    RA144Context *ractx;
50
    int ret;
51
52
1
    if (avctx->channels != 1) {
53
        av_log(avctx, AV_LOG_ERROR, "invalid number of channels: %d\n",
54
               avctx->channels);
55
        return -1;
56
    }
57
1
    avctx->frame_size = NBLOCKS * BLOCKSIZE;
58
1
    avctx->initial_padding = avctx->frame_size;
59
1
    avctx->bit_rate = 8000;
60
1
    ractx = avctx->priv_data;
61
1
    ractx->lpc_coef[0] = ractx->lpc_tables[0];
62
1
    ractx->lpc_coef[1] = ractx->lpc_tables[1];
63
1
    ractx->avctx = avctx;
64
1
    ff_audiodsp_init(&ractx->adsp);
65
1
    ret = ff_lpc_init(&ractx->lpc_ctx, avctx->frame_size, LPC_ORDER,
66
                      FF_LPC_TYPE_LEVINSON);
67
1
    if (ret < 0)
68
        return ret;
69
70
1
    ff_af_queue_init(avctx, &ractx->afq);
71
72
1
    return 0;
73
}
74
75
76
/**
77
 * Quantize a value by searching a sorted table for the element with the
78
 * nearest value
79
 *
80
 * @param value value to quantize
81
 * @param table array containing the quantization table
82
 * @param size size of the quantization table
83
 * @return index of the quantization table corresponding to the element with the
84
 *         nearest value
85
 */
86
3612
static int quantize(int value, const int16_t *table, unsigned int size)
87
{
88
3612
    unsigned int low = 0, high = size - 1;
89
90
14245
    while (1) {
91
17857
        int index = (low + high) >> 1;
92
17857
        int error = table[index] - value;
93
94
17857
        if (index == low)
95
3612
            return table[high] + error > value ? low : high;
96
14245
        if (error > 0) {
97
5875
            high = index;
98
        } else {
99
8370
            low = index;
100
        }
101
    }
102
}
103
104
105
/**
106
 * Orthogonalize a vector to another vector
107
 *
108
 * @param v vector to orthogonalize
109
 * @param u vector against which orthogonalization is performed
110
 */
111
461357
static void orthogonalize(float *v, const float *u)
112
{
113
    int i;
114
461357
    float num = 0, den = 0;
115
116
18915637
    for (i = 0; i < BLOCKSIZE; i++) {
117
18454280
        num += v[i] * u[i];
118
18454280
        den += u[i] * u[i];
119
    }
120
461357
    num /= den;
121
18915637
    for (i = 0; i < BLOCKSIZE; i++)
122
18454280
        v[i] -= num * u[i];
123
461357
}
124
125
126
/**
127
 * Calculate match score and gain of an LPC-filtered vector with respect to
128
 * input data, possibly orthogonalizing it to up to two other vectors.
129
 *
130
 * @param work array used to calculate the filtered vector
131
 * @param coefs coefficients of the LPC filter
132
 * @param vect original vector
133
 * @param ortho1 first vector against which orthogonalization is performed
134
 * @param ortho2 second vector against which orthogonalization is performed
135
 * @param data input data
136
 * @param score pointer to variable where match score is returned
137
 * @param gain pointer to variable where gain is returned
138
 */
139
461132
static void get_match_score(float *work, const float *coefs, float *vect,
140
                            const float *ortho1, const float *ortho2,
141
                            const float *data, float *score, float *gain)
142
{
143
    float c, g;
144
    int i;
145
146
461132
    ff_celp_lp_synthesis_filterf(work, coefs, vect, BLOCKSIZE, LPC_ORDER);
147
461132
    if (ortho1)
148
306432
        orthogonalize(work, ortho1);
149
461132
    if (ortho2)
150
153728
        orthogonalize(work, ortho2);
151
461132
    c = g = 0;
152
18906412
    for (i = 0; i < BLOCKSIZE; i++) {
153
18445280
        g += work[i] * work[i];
154
18445280
        c += data[i] * work[i];
155
    }
156
461132
    if (c <= 0) {
157
232992
        *score = 0;
158
232992
        return;
159
    }
160
228140
    *gain = c / g;
161
228140
    *score = *gain * c;
162
}
163
164
165
/**
166
 * Create a vector from the adaptive codebook at a given lag value
167
 *
168
 * @param vect array where vector is stored
169
 * @param cb adaptive codebook
170
 * @param lag lag value
171
 */
172
154105
static void create_adapt_vect(float *vect, const int16_t *cb, int lag)
173
{
174
    int i;
175
176
154105
    cb += BUFFERSIZE - lag;
177
6061026
    for (i = 0; i < FFMIN(BLOCKSIZE, lag); i++)
178
5906921
        vect[i] = cb[i];
179
154105
    if (lag < BLOCKSIZE)
180
281796
        for (i = 0; i < BLOCKSIZE - lag; i++)
181
257279
            vect[lag + i] = cb[i];
182
154105
}
183
184
185
/**
186
 * Search the adaptive codebook for the best entry and gain and remove its
187
 * contribution from input data
188
 *
189
 * @param adapt_cb array from which the adaptive codebook is extracted
190
 * @param work array used to calculate LPC-filtered vectors
191
 * @param coefs coefficients of the LPC filter
192
 * @param data input data
193
 * @return index of the best entry of the adaptive codebook
194
 */
195
1204
static int adaptive_cb_search(const int16_t *adapt_cb, float *work,
196
                              const float *coefs, float *data)
197
{
198
1204
    int i, av_uninit(best_vect);
199
1204
    float score, gain, best_score, av_uninit(best_gain);
200
    float exc[BLOCKSIZE];
201
202
1204
    gain = best_score = 0;
203
154112
    for (i = BLOCKSIZE / 2; i <= BUFFERSIZE; i++) {
204
152908
        create_adapt_vect(exc, adapt_cb, i);
205
152908
        get_match_score(work, coefs, exc, NULL, NULL, data, &score, &gain);
206
152908
        if (score > best_score) {
207
5528
            best_score = score;
208
5528
            best_vect = i;
209
5528
            best_gain = gain;
210
        }
211
    }
212
1204
    if (!best_score)
213
7
        return 0;
214
215
    /**
216
     * Re-calculate the filtered vector from the vector with maximum match score
217
     * and remove its contribution from input data.
218
     */
219
1197
    create_adapt_vect(exc, adapt_cb, best_vect);
220
1197
    ff_celp_lp_synthesis_filterf(work, coefs, exc, BLOCKSIZE, LPC_ORDER);
221
49077
    for (i = 0; i < BLOCKSIZE; i++)
222
47880
        data[i] -= best_gain * work[i];
223
1197
    return best_vect - BLOCKSIZE / 2 + 1;
224
}
225
226
227
/**
228
 * Find the best vector of a fixed codebook by applying an LPC filter to
229
 * codebook entries, possibly orthogonalizing them to up to two other vectors
230
 * and matching the results with input data.
231
 *
232
 * @param work array used to calculate the filtered vectors
233
 * @param coefs coefficients of the LPC filter
234
 * @param cb fixed codebook
235
 * @param ortho1 first vector against which orthogonalization is performed
236
 * @param ortho2 second vector against which orthogonalization is performed
237
 * @param data input data
238
 * @param idx pointer to variable where the index of the best codebook entry is
239
 *        returned
240
 * @param gain pointer to variable where the gain of the best codebook entry is
241
 *        returned
242
 */
243
2408
static void find_best_vect(float *work, const float *coefs,
244
                           const int8_t cb[][BLOCKSIZE], const float *ortho1,
245
                           const float *ortho2, float *data, int *idx,
246
                           float *gain)
247
{
248
    int i, j;
249
    float g, score, best_score;
250
    float vect[BLOCKSIZE];
251
252
2408
    *idx = *gain = best_score = 0;
253
310632
    for (i = 0; i < FIXED_CB_SIZE; i++) {
254
12637184
        for (j = 0; j < BLOCKSIZE; j++)
255
12328960
            vect[j] = cb[i][j];
256
308224
        get_match_score(work, coefs, vect, ortho1, ortho2, data, &score, &g);
257
308224
        if (score > best_score) {
258
14127
            best_score = score;
259
14127
            *idx = i;
260
14127
            *gain = g;
261
        }
262
    }
263
2408
}
264
265
266
/**
267
 * Search the two fixed codebooks for the best entry and gain
268
 *
269
 * @param work array used to calculate LPC-filtered vectors
270
 * @param coefs coefficients of the LPC filter
271
 * @param data input data
272
 * @param cba_idx index of the best entry of the adaptive codebook
273
 * @param cb1_idx pointer to variable where the index of the best entry of the
274
 *        first fixed codebook is returned
275
 * @param cb2_idx pointer to variable where the index of the best entry of the
276
 *        second fixed codebook is returned
277
 */
278
1204
static void fixed_cb_search(float *work, const float *coefs, float *data,
279
                            int cba_idx, int *cb1_idx, int *cb2_idx)
280
{
281
    int i, ortho_cb1;
282
    float gain;
283
    float cba_vect[BLOCKSIZE], cb1_vect[BLOCKSIZE];
284
    float vect[BLOCKSIZE];
285
286
    /**
287
     * The filtered vector from the adaptive codebook can be retrieved from
288
     * work, because this function is called just after adaptive_cb_search().
289
     */
290
1204
    if (cba_idx)
291
1197
        memcpy(cba_vect, work, sizeof(cba_vect));
292
293
1204
    find_best_vect(work, coefs, ff_cb1_vects, cba_idx ? cba_vect : NULL, NULL,
294
                   data, cb1_idx, &gain);
295
296
    /**
297
     * Re-calculate the filtered vector from the vector with maximum match score
298
     * and remove its contribution from input data.
299
     */
300
1204
    if (gain) {
301
49241
        for (i = 0; i < BLOCKSIZE; i++)
302
48040
            vect[i] = ff_cb1_vects[*cb1_idx][i];
303
1201
        ff_celp_lp_synthesis_filterf(work, coefs, vect, BLOCKSIZE, LPC_ORDER);
304
1201
        if (cba_idx)
305
1197
            orthogonalize(work, cba_vect);
306
49241
        for (i = 0; i < BLOCKSIZE; i++)
307
48040
            data[i] -= gain * work[i];
308
1201
        memcpy(cb1_vect, work, sizeof(cb1_vect));
309
1201
        ortho_cb1 = 1;
310
    } else
311
3
        ortho_cb1 = 0;
312
313

1204
    find_best_vect(work, coefs, ff_cb2_vects, cba_idx ? cba_vect : NULL,
314
                   ortho_cb1 ? cb1_vect : NULL, data, cb2_idx, &gain);
315
1204
}
316
317
318
/**
319
 * Encode a subblock of the current frame
320
 *
321
 * @param ractx encoder context
322
 * @param sblock_data input data of the subblock
323
 * @param lpc_coefs coefficients of the LPC filter
324
 * @param rms RMS of the reflection coefficients
325
 * @param pb pointer to PutBitContext of the current frame
326
 */
327
1204
static void ra144_encode_subblock(RA144Context *ractx,
328
                                  const int16_t *sblock_data,
329
                                  const int16_t *lpc_coefs, unsigned int rms,
330
                                  PutBitContext *pb)
331
{
332
1204
    float data[BLOCKSIZE] = { 0 }, work[LPC_ORDER + BLOCKSIZE];
333
    float coefs[LPC_ORDER];
334
    float zero[BLOCKSIZE], cba[BLOCKSIZE], cb1[BLOCKSIZE], cb2[BLOCKSIZE];
335
    int cba_idx, cb1_idx, cb2_idx, gain;
336
    int i, n;
337
    unsigned m[3];
338
    float g[3];
339
    float error, best_error;
340
341
13244
    for (i = 0; i < LPC_ORDER; i++) {
342
12040
        work[i] = ractx->curr_sblock[BLOCKSIZE + i];
343
12040
        coefs[i] = lpc_coefs[i] * (1/4096.0);
344
    }
345
346
    /**
347
     * Calculate the zero-input response of the LPC filter and subtract it from
348
     * input data.
349
     */
350
1204
    ff_celp_lp_synthesis_filterf(work + LPC_ORDER, coefs, data, BLOCKSIZE,
351
                                 LPC_ORDER);
352
49364
    for (i = 0; i < BLOCKSIZE; i++) {
353
48160
        zero[i] = work[LPC_ORDER + i];
354
48160
        data[i] = sblock_data[i] - zero[i];
355
    }
356
357
    /**
358
     * Codebook search is performed without taking into account the contribution
359
     * of the previous subblock, since it has been just subtracted from input
360
     * data.
361
     */
362
1204
    memset(work, 0, LPC_ORDER * sizeof(*work));
363
364
1204
    cba_idx = adaptive_cb_search(ractx->adapt_cb, work + LPC_ORDER, coefs,
365
                                 data);
366
1204
    if (cba_idx) {
367
        /**
368
         * The filtered vector from the adaptive codebook can be retrieved from
369
         * work, see implementation of adaptive_cb_search().
370
         */
371
1197
        memcpy(cba, work + LPC_ORDER, sizeof(cba));
372
373
1197
        ff_copy_and_dup(ractx->buffer_a, ractx->adapt_cb, cba_idx + BLOCKSIZE / 2 - 1);
374
1197
        m[0] = (ff_irms(&ractx->adsp, ractx->buffer_a) * rms) >> 12;
375
    }
376
1204
    fixed_cb_search(work + LPC_ORDER, coefs, data, cba_idx, &cb1_idx, &cb2_idx);
377
49364
    for (i = 0; i < BLOCKSIZE; i++) {
378
48160
        cb1[i] = ff_cb1_vects[cb1_idx][i];
379
48160
        cb2[i] = ff_cb2_vects[cb2_idx][i];
380
    }
381
1204
    ff_celp_lp_synthesis_filterf(work + LPC_ORDER, coefs, cb1, BLOCKSIZE,
382
                                 LPC_ORDER);
383
1204
    memcpy(cb1, work + LPC_ORDER, sizeof(cb1));
384
1204
    m[1] = (ff_cb1_base[cb1_idx] * rms) >> 8;
385
1204
    ff_celp_lp_synthesis_filterf(work + LPC_ORDER, coefs, cb2, BLOCKSIZE,
386
                                 LPC_ORDER);
387
1204
    memcpy(cb2, work + LPC_ORDER, sizeof(cb2));
388
1204
    m[2] = (ff_cb2_base[cb2_idx] * rms) >> 8;
389
1204
    best_error = FLT_MAX;
390
1204
    gain = 0;
391
309428
    for (n = 0; n < 256; n++) {
392
308224
        g[1] = ((ff_gain_val_tab[n][1] * m[1]) >> ff_gain_exp_tab[n]) *
393
               (1/4096.0);
394
308224
        g[2] = ((ff_gain_val_tab[n][2] * m[2]) >> ff_gain_exp_tab[n]) *
395
               (1/4096.0);
396
308224
        error = 0;
397
308224
        if (cba_idx) {
398
306432
            g[0] = ((ff_gain_val_tab[n][0] * m[0]) >> ff_gain_exp_tab[n]) *
399
                   (1/4096.0);
400
12563712
            for (i = 0; i < BLOCKSIZE; i++) {
401
12257280
                data[i] = zero[i] + g[0] * cba[i] + g[1] * cb1[i] +
402
12257280
                          g[2] * cb2[i];
403
12257280
                error += (data[i] - sblock_data[i]) *
404
12257280
                         (data[i] - sblock_data[i]);
405
            }
406
        } else {
407
73472
            for (i = 0; i < BLOCKSIZE; i++) {
408
71680
                data[i] = zero[i] + g[1] * cb1[i] + g[2] * cb2[i];
409
71680
                error += (data[i] - sblock_data[i]) *
410
71680
                         (data[i] - sblock_data[i]);
411
            }
412
        }
413
308224
        if (error < best_error) {
414
45662
            best_error = error;
415
45662
            gain = n;
416
        }
417
    }
418
1204
    put_bits(pb, 7, cba_idx);
419
1204
    put_bits(pb, 8, gain);
420
1204
    put_bits(pb, 7, cb1_idx);
421
1204
    put_bits(pb, 7, cb2_idx);
422
1204
    ff_subblock_synthesis(ractx, lpc_coefs, cba_idx, cb1_idx, cb2_idx, rms,
423
                          gain);
424
1204
}
425
426
427
302
static int ra144_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
428
                              const AVFrame *frame, int *got_packet_ptr)
429
{
430
    static const uint8_t sizes[LPC_ORDER] = {64, 32, 32, 16, 16, 8, 8, 8, 8, 4};
431
    static const uint8_t bit_sizes[LPC_ORDER] = {6, 5, 5, 4, 4, 3, 3, 3, 3, 2};
432
302
    RA144Context *ractx = avctx->priv_data;
433
    PutBitContext pb;
434
    int32_t lpc_data[NBLOCKS * BLOCKSIZE];
435
    int32_t lpc_coefs[LPC_ORDER][MAX_LPC_ORDER];
436
    int shift[LPC_ORDER];
437
    int16_t block_coefs[NBLOCKS][LPC_ORDER];
438
    int lpc_refl[LPC_ORDER];    /**< reflection coefficients of the frame */
439
    unsigned int refl_rms[NBLOCKS]; /**< RMS of the reflection coefficients */
440
302
    const int16_t *samples = frame ? (const int16_t *)frame->data[0] : NULL;
441
302
    int energy = 0;
442
    int i, idx, ret;
443
444
302
    if (ractx->last_frame)
445
1
        return 0;
446
447
301
    if ((ret = ff_alloc_packet2(avctx, avpkt, FRAME_SIZE, 0)) < 0)
448
        return ret;
449
450
    /**
451
     * Since the LPC coefficients are calculated on a frame centered over the
452
     * fourth subframe, to encode a given frame, data from the next frame is
453
     * needed. In each call to this function, the previous frame (whose data are
454
     * saved in the encoder context) is encoded, and data from the current frame
455
     * are saved in the encoder context to be used in the next function call.
456
     */
457
30401
    for (i = 0; i < (2 * BLOCKSIZE + BLOCKSIZE / 2); i++) {
458
30100
        lpc_data[i] = ractx->curr_block[BLOCKSIZE + BLOCKSIZE / 2 + i];
459
30100
        energy += (lpc_data[i] * lpc_data[i]) >> 4;
460
    }
461
301
    if (frame) {
462
        int j;
463

18300
        for (j = 0; j < frame->nb_samples && i < NBLOCKS * BLOCKSIZE; i++, j++) {
464
18000
            lpc_data[i] = samples[j] >> 2;
465
18000
            energy += (lpc_data[i] * lpc_data[i]) >> 4;
466
        }
467
    }
468
301
    if (i < NBLOCKS * BLOCKSIZE)
469
1
        memset(&lpc_data[i], 0, (NBLOCKS * BLOCKSIZE - i) * sizeof(*lpc_data));
470
301
    energy = ff_energy_tab[quantize(ff_t_sqrt(energy >> 5) >> 10, ff_energy_tab,
471
                                    32)];
472
473
301
    ff_lpc_calc_coefs(&ractx->lpc_ctx, lpc_data, NBLOCKS * BLOCKSIZE, LPC_ORDER,
474
                      LPC_ORDER, 16, lpc_coefs, shift, FF_LPC_TYPE_LEVINSON,
475
                      0, ORDER_METHOD_EST, 0, 12, 0);
476
3311
    for (i = 0; i < LPC_ORDER; i++)
477
3010
        block_coefs[NBLOCKS - 1][i] = -lpc_coefs[LPC_ORDER - 1][i]
478
3010
                                       * (1 << (12 - shift[LPC_ORDER - 1]));
479
480
    /**
481
     * TODO: apply perceptual weighting of the input speech through bandwidth
482
     * expansion of the LPC filter.
483
     */
484
485
301
    if (ff_eval_refl(lpc_refl, block_coefs[NBLOCKS - 1], avctx)) {
486
        /**
487
         * The filter is unstable: use the coefficients of the previous frame.
488
         */
489
73
        ff_int_to_int16(block_coefs[NBLOCKS - 1], ractx->lpc_coef[1]);
490
73
        if (ff_eval_refl(lpc_refl, block_coefs[NBLOCKS - 1], avctx)) {
491
            /* the filter is still unstable. set reflection coeffs to zero. */
492
            memset(lpc_refl, 0, sizeof(lpc_refl));
493
        }
494
    }
495
301
    init_put_bits(&pb, avpkt->data, avpkt->size);
496
3311
    for (i = 0; i < LPC_ORDER; i++) {
497
3010
        idx = quantize(lpc_refl[i], ff_lpc_refl_cb[i], sizes[i]);
498
3010
        put_bits(&pb, bit_sizes[i], idx);
499
3010
        lpc_refl[i] = ff_lpc_refl_cb[i][idx];
500
    }
501
301
    ractx->lpc_refl_rms[0] = ff_rms(lpc_refl);
502
301
    ff_eval_coefs(ractx->lpc_coef[0], lpc_refl);
503
301
    refl_rms[0] = ff_interp(ractx, block_coefs[0], 1, 1, ractx->old_energy);
504
602
    refl_rms[1] = ff_interp(ractx, block_coefs[1], 2,
505
301
                            energy <= ractx->old_energy,
506
301
                            ff_t_sqrt(energy * ractx->old_energy) >> 12);
507
301
    refl_rms[2] = ff_interp(ractx, block_coefs[2], 3, 0, energy);
508
301
    refl_rms[3] = ff_rescale_rms(ractx->lpc_refl_rms[0], energy);
509
301
    ff_int_to_int16(block_coefs[NBLOCKS - 1], ractx->lpc_coef[0]);
510
301
    put_bits(&pb, 5, quantize(energy, ff_energy_tab, 32));
511
1505
    for (i = 0; i < NBLOCKS; i++)
512
1204
        ra144_encode_subblock(ractx, ractx->curr_block + i * BLOCKSIZE,
513
1204
                              block_coefs[i], refl_rms[i], &pb);
514
301
    flush_put_bits(&pb);
515
301
    ractx->old_energy = energy;
516
301
    ractx->lpc_refl_rms[1] = ractx->lpc_refl_rms[0];
517
301
    FFSWAP(unsigned int *, ractx->lpc_coef[0], ractx->lpc_coef[1]);
518
519
    /* copy input samples to current block for processing in next call */
520
301
    i = 0;
521
301
    if (frame) {
522
48300
        for (; i < frame->nb_samples; i++)
523
48000
            ractx->curr_block[i] = samples[i] >> 2;
524
525
300
        if ((ret = ff_af_queue_add(&ractx->afq, frame)) < 0)
526
            return ret;
527
    } else
528
1
        ractx->last_frame = 1;
529
301
    memset(&ractx->curr_block[i], 0,
530
301
           (NBLOCKS * BLOCKSIZE - i) * sizeof(*ractx->curr_block));
531
532
    /* Get the next frame pts/duration */
533
301
    ff_af_queue_remove(&ractx->afq, avctx->frame_size, &avpkt->pts,
534
                       &avpkt->duration);
535
536
301
    avpkt->size = FRAME_SIZE;
537
301
    *got_packet_ptr = 1;
538
301
    return 0;
539
}
540
541
542
AVCodec ff_ra_144_encoder = {
543
    .name           = "real_144",
544
    .long_name      = NULL_IF_CONFIG_SMALL("RealAudio 1.0 (14.4K)"),
545
    .type           = AVMEDIA_TYPE_AUDIO,
546
    .id             = AV_CODEC_ID_RA_144,
547
    .priv_data_size = sizeof(RA144Context),
548
    .init           = ra144_encode_init,
549
    .encode2        = ra144_encode_frame,
550
    .close          = ra144_encode_close,
551
    .capabilities   = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SMALL_LAST_FRAME,
552
    .sample_fmts    = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16,
553
                                                     AV_SAMPLE_FMT_NONE },
554
    .supported_samplerates = (const int[]){ 8000, 0 },
555
    .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, 0 },
556
};