1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * Copyright (c) CMU 1993 Computer Science, Speech Group
3cabdff1aSopenharmony_ci *                        Chengxiang Lu and Alex Hauptmann
4cabdff1aSopenharmony_ci * Copyright (c) 2005 Steve Underwood <steveu at coppice.org>
5cabdff1aSopenharmony_ci * Copyright (c) 2009 Kenan Gillet
6cabdff1aSopenharmony_ci * Copyright (c) 2010 Martin Storsjo
7cabdff1aSopenharmony_ci *
8cabdff1aSopenharmony_ci * This file is part of FFmpeg.
9cabdff1aSopenharmony_ci *
10cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
11cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
12cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
13cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
14cabdff1aSopenharmony_ci *
15cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
16cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
17cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18cabdff1aSopenharmony_ci * Lesser General Public License for more details.
19cabdff1aSopenharmony_ci *
20cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
21cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
22cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23cabdff1aSopenharmony_ci */
24cabdff1aSopenharmony_ci
25cabdff1aSopenharmony_ci/**
26cabdff1aSopenharmony_ci * @file
27cabdff1aSopenharmony_ci * G.722 ADPCM audio encoder
28cabdff1aSopenharmony_ci */
29cabdff1aSopenharmony_ci
30cabdff1aSopenharmony_ci#include "libavutil/avassert.h"
31cabdff1aSopenharmony_ci#include "libavutil/channel_layout.h"
32cabdff1aSopenharmony_ci#include "avcodec.h"
33cabdff1aSopenharmony_ci#include "codec_internal.h"
34cabdff1aSopenharmony_ci#include "encode.h"
35cabdff1aSopenharmony_ci#include "internal.h"
36cabdff1aSopenharmony_ci#include "g722.h"
37cabdff1aSopenharmony_ci#include "libavutil/common.h"
38cabdff1aSopenharmony_ci
39cabdff1aSopenharmony_ci#define FREEZE_INTERVAL 128
40cabdff1aSopenharmony_ci
41cabdff1aSopenharmony_ci/* This is an arbitrary value. Allowing insanely large values leads to strange
42cabdff1aSopenharmony_ci   problems, so we limit it to a reasonable value */
43cabdff1aSopenharmony_ci#define MAX_FRAME_SIZE 32768
44cabdff1aSopenharmony_ci
45cabdff1aSopenharmony_ci/* We clip the value of avctx->trellis to prevent data type overflows and
46cabdff1aSopenharmony_ci   undefined behavior. Using larger values is insanely slow anyway. */
47cabdff1aSopenharmony_ci#define MIN_TRELLIS 0
48cabdff1aSopenharmony_ci#define MAX_TRELLIS 16
49cabdff1aSopenharmony_ci
50cabdff1aSopenharmony_cistatic av_cold int g722_encode_close(AVCodecContext *avctx)
51cabdff1aSopenharmony_ci{
52cabdff1aSopenharmony_ci    G722Context *c = avctx->priv_data;
53cabdff1aSopenharmony_ci    int i;
54cabdff1aSopenharmony_ci    for (i = 0; i < 2; i++) {
55cabdff1aSopenharmony_ci        av_freep(&c->paths[i]);
56cabdff1aSopenharmony_ci        av_freep(&c->node_buf[i]);
57cabdff1aSopenharmony_ci        av_freep(&c->nodep_buf[i]);
58cabdff1aSopenharmony_ci    }
59cabdff1aSopenharmony_ci    return 0;
60cabdff1aSopenharmony_ci}
61cabdff1aSopenharmony_ci
62cabdff1aSopenharmony_cistatic av_cold int g722_encode_init(AVCodecContext * avctx)
63cabdff1aSopenharmony_ci{
64cabdff1aSopenharmony_ci    G722Context *c = avctx->priv_data;
65cabdff1aSopenharmony_ci
66cabdff1aSopenharmony_ci    c->band[0].scale_factor = 8;
67cabdff1aSopenharmony_ci    c->band[1].scale_factor = 2;
68cabdff1aSopenharmony_ci    c->prev_samples_pos = 22;
69cabdff1aSopenharmony_ci
70cabdff1aSopenharmony_ci    if (avctx->frame_size) {
71cabdff1aSopenharmony_ci        /* validate frame size */
72cabdff1aSopenharmony_ci        if (avctx->frame_size & 1 || avctx->frame_size > MAX_FRAME_SIZE) {
73cabdff1aSopenharmony_ci            int new_frame_size;
74cabdff1aSopenharmony_ci
75cabdff1aSopenharmony_ci            if (avctx->frame_size == 1)
76cabdff1aSopenharmony_ci                new_frame_size = 2;
77cabdff1aSopenharmony_ci            else if (avctx->frame_size > MAX_FRAME_SIZE)
78cabdff1aSopenharmony_ci                new_frame_size = MAX_FRAME_SIZE;
79cabdff1aSopenharmony_ci            else
80cabdff1aSopenharmony_ci                new_frame_size = avctx->frame_size - 1;
81cabdff1aSopenharmony_ci
82cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_WARNING, "Requested frame size is not "
83cabdff1aSopenharmony_ci                   "allowed. Using %d instead of %d\n", new_frame_size,
84cabdff1aSopenharmony_ci                   avctx->frame_size);
85cabdff1aSopenharmony_ci            avctx->frame_size = new_frame_size;
86cabdff1aSopenharmony_ci        }
87cabdff1aSopenharmony_ci    } else {
88cabdff1aSopenharmony_ci        /* This is arbitrary. We use 320 because it's 20ms @ 16kHz, which is
89cabdff1aSopenharmony_ci           a common packet size for VoIP applications */
90cabdff1aSopenharmony_ci        avctx->frame_size = 320;
91cabdff1aSopenharmony_ci    }
92cabdff1aSopenharmony_ci    avctx->initial_padding = 22;
93cabdff1aSopenharmony_ci
94cabdff1aSopenharmony_ci    if (avctx->trellis) {
95cabdff1aSopenharmony_ci        /* validate trellis */
96cabdff1aSopenharmony_ci        if (avctx->trellis < MIN_TRELLIS || avctx->trellis > MAX_TRELLIS) {
97cabdff1aSopenharmony_ci            int new_trellis = av_clip(avctx->trellis, MIN_TRELLIS, MAX_TRELLIS);
98cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_WARNING, "Requested trellis value is not "
99cabdff1aSopenharmony_ci                   "allowed. Using %d instead of %d\n", new_trellis,
100cabdff1aSopenharmony_ci                   avctx->trellis);
101cabdff1aSopenharmony_ci            avctx->trellis = new_trellis;
102cabdff1aSopenharmony_ci        }
103cabdff1aSopenharmony_ci        if (avctx->trellis) {
104cabdff1aSopenharmony_ci            int frontier = 1 << avctx->trellis;
105cabdff1aSopenharmony_ci            int max_paths = frontier * FREEZE_INTERVAL;
106cabdff1aSopenharmony_ci
107cabdff1aSopenharmony_ci            for (int i = 0; i < 2; i++) {
108cabdff1aSopenharmony_ci                c->paths[i]     = av_calloc(max_paths, sizeof(**c->paths));
109cabdff1aSopenharmony_ci                c->node_buf[i]  = av_calloc(frontier, 2 * sizeof(**c->node_buf));
110cabdff1aSopenharmony_ci                c->nodep_buf[i] = av_calloc(frontier, 2 * sizeof(**c->nodep_buf));
111cabdff1aSopenharmony_ci                if (!c->paths[i] || !c->node_buf[i] || !c->nodep_buf[i])
112cabdff1aSopenharmony_ci                    return AVERROR(ENOMEM);
113cabdff1aSopenharmony_ci            }
114cabdff1aSopenharmony_ci        }
115cabdff1aSopenharmony_ci    }
116cabdff1aSopenharmony_ci
117cabdff1aSopenharmony_ci    ff_g722dsp_init(&c->dsp);
118cabdff1aSopenharmony_ci
119cabdff1aSopenharmony_ci    return 0;
120cabdff1aSopenharmony_ci}
121cabdff1aSopenharmony_ci
122cabdff1aSopenharmony_cistatic const int16_t low_quant[33] = {
123cabdff1aSopenharmony_ci      35,   72,  110,  150,  190,  233,  276,  323,
124cabdff1aSopenharmony_ci     370,  422,  473,  530,  587,  650,  714,  786,
125cabdff1aSopenharmony_ci     858,  940, 1023, 1121, 1219, 1339, 1458, 1612,
126cabdff1aSopenharmony_ci    1765, 1980, 2195, 2557, 2919
127cabdff1aSopenharmony_ci};
128cabdff1aSopenharmony_ci
129cabdff1aSopenharmony_cistatic inline void filter_samples(G722Context *c, const int16_t *samples,
130cabdff1aSopenharmony_ci                                  int *xlow, int *xhigh)
131cabdff1aSopenharmony_ci{
132cabdff1aSopenharmony_ci    int xout[2];
133cabdff1aSopenharmony_ci    c->prev_samples[c->prev_samples_pos++] = samples[0];
134cabdff1aSopenharmony_ci    c->prev_samples[c->prev_samples_pos++] = samples[1];
135cabdff1aSopenharmony_ci    c->dsp.apply_qmf(c->prev_samples + c->prev_samples_pos - 24, xout);
136cabdff1aSopenharmony_ci    *xlow  = xout[0] + xout[1] >> 14;
137cabdff1aSopenharmony_ci    *xhigh = xout[0] - xout[1] >> 14;
138cabdff1aSopenharmony_ci    if (c->prev_samples_pos >= PREV_SAMPLES_BUF_SIZE) {
139cabdff1aSopenharmony_ci        memmove(c->prev_samples,
140cabdff1aSopenharmony_ci                c->prev_samples + c->prev_samples_pos - 22,
141cabdff1aSopenharmony_ci                22 * sizeof(c->prev_samples[0]));
142cabdff1aSopenharmony_ci        c->prev_samples_pos = 22;
143cabdff1aSopenharmony_ci    }
144cabdff1aSopenharmony_ci}
145cabdff1aSopenharmony_ci
146cabdff1aSopenharmony_cistatic inline int encode_high(const struct G722Band *state, int xhigh)
147cabdff1aSopenharmony_ci{
148cabdff1aSopenharmony_ci    int diff = av_clip_int16(xhigh - state->s_predictor);
149cabdff1aSopenharmony_ci    int pred = 141 * state->scale_factor >> 8;
150cabdff1aSopenharmony_ci           /* = diff >= 0 ? (diff < pred) + 2 : diff >= -pred */
151cabdff1aSopenharmony_ci    return ((diff ^ (diff >> (sizeof(diff)*8-1))) < pred) + 2*(diff >= 0);
152cabdff1aSopenharmony_ci}
153cabdff1aSopenharmony_ci
154cabdff1aSopenharmony_cistatic inline int encode_low(const struct G722Band* state, int xlow)
155cabdff1aSopenharmony_ci{
156cabdff1aSopenharmony_ci    int diff  = av_clip_int16(xlow - state->s_predictor);
157cabdff1aSopenharmony_ci           /* = diff >= 0 ? diff : -(diff + 1) */
158cabdff1aSopenharmony_ci    int limit = diff ^ (diff >> (sizeof(diff)*8-1));
159cabdff1aSopenharmony_ci    int i = 0;
160cabdff1aSopenharmony_ci    limit = limit + 1 << 10;
161cabdff1aSopenharmony_ci    if (limit > low_quant[8] * state->scale_factor)
162cabdff1aSopenharmony_ci        i = 9;
163cabdff1aSopenharmony_ci    while (i < 29 && limit > low_quant[i] * state->scale_factor)
164cabdff1aSopenharmony_ci        i++;
165cabdff1aSopenharmony_ci    return (diff < 0 ? (i < 2 ? 63 : 33) : 61) - i;
166cabdff1aSopenharmony_ci}
167cabdff1aSopenharmony_ci
168cabdff1aSopenharmony_cistatic void g722_encode_trellis(G722Context *c, int trellis,
169cabdff1aSopenharmony_ci                                uint8_t *dst, int nb_samples,
170cabdff1aSopenharmony_ci                                const int16_t *samples)
171cabdff1aSopenharmony_ci{
172cabdff1aSopenharmony_ci    int i, j, k;
173cabdff1aSopenharmony_ci    int frontier = 1 << trellis;
174cabdff1aSopenharmony_ci    struct TrellisNode **nodes[2];
175cabdff1aSopenharmony_ci    struct TrellisNode **nodes_next[2];
176cabdff1aSopenharmony_ci    int pathn[2] = {0, 0}, froze = -1;
177cabdff1aSopenharmony_ci    struct TrellisPath *p[2];
178cabdff1aSopenharmony_ci
179cabdff1aSopenharmony_ci    for (i = 0; i < 2; i++) {
180cabdff1aSopenharmony_ci        nodes[i] = c->nodep_buf[i];
181cabdff1aSopenharmony_ci        nodes_next[i] = c->nodep_buf[i] + frontier;
182cabdff1aSopenharmony_ci        memset(c->nodep_buf[i], 0, 2 * frontier * sizeof(*c->nodep_buf[i]));
183cabdff1aSopenharmony_ci        nodes[i][0] = c->node_buf[i] + frontier;
184cabdff1aSopenharmony_ci        nodes[i][0]->ssd = 0;
185cabdff1aSopenharmony_ci        nodes[i][0]->path = 0;
186cabdff1aSopenharmony_ci        nodes[i][0]->state = c->band[i];
187cabdff1aSopenharmony_ci    }
188cabdff1aSopenharmony_ci
189cabdff1aSopenharmony_ci    for (i = 0; i < nb_samples >> 1; i++) {
190cabdff1aSopenharmony_ci        int xlow, xhigh;
191cabdff1aSopenharmony_ci        struct TrellisNode *next[2];
192cabdff1aSopenharmony_ci        int heap_pos[2] = {0, 0};
193cabdff1aSopenharmony_ci
194cabdff1aSopenharmony_ci        for (j = 0; j < 2; j++) {
195cabdff1aSopenharmony_ci            next[j] = c->node_buf[j] + frontier*(i & 1);
196cabdff1aSopenharmony_ci            memset(nodes_next[j], 0, frontier * sizeof(**nodes_next));
197cabdff1aSopenharmony_ci        }
198cabdff1aSopenharmony_ci
199cabdff1aSopenharmony_ci        filter_samples(c, &samples[2*i], &xlow, &xhigh);
200cabdff1aSopenharmony_ci
201cabdff1aSopenharmony_ci        for (j = 0; j < frontier && nodes[0][j]; j++) {
202cabdff1aSopenharmony_ci            /* Only k >> 2 affects the future adaptive state, therefore testing
203cabdff1aSopenharmony_ci             * small steps that don't change k >> 2 is useless, the original
204cabdff1aSopenharmony_ci             * value from encode_low is better than them. Since we step k
205cabdff1aSopenharmony_ci             * in steps of 4, make sure range is a multiple of 4, so that
206cabdff1aSopenharmony_ci             * we don't miss the original value from encode_low. */
207cabdff1aSopenharmony_ci            int range = j < frontier/2 ? 4 : 0;
208cabdff1aSopenharmony_ci            struct TrellisNode *cur_node = nodes[0][j];
209cabdff1aSopenharmony_ci
210cabdff1aSopenharmony_ci            int ilow = encode_low(&cur_node->state, xlow);
211cabdff1aSopenharmony_ci
212cabdff1aSopenharmony_ci            for (k = ilow - range; k <= ilow + range && k <= 63; k += 4) {
213cabdff1aSopenharmony_ci                int decoded, dec_diff, pos;
214cabdff1aSopenharmony_ci                uint32_t ssd;
215cabdff1aSopenharmony_ci                struct TrellisNode* node;
216cabdff1aSopenharmony_ci
217cabdff1aSopenharmony_ci                if (k < 0)
218cabdff1aSopenharmony_ci                    continue;
219cabdff1aSopenharmony_ci
220cabdff1aSopenharmony_ci                decoded = av_clip_intp2((cur_node->state.scale_factor *
221cabdff1aSopenharmony_ci                                  ff_g722_low_inv_quant6[k] >> 10)
222cabdff1aSopenharmony_ci                                + cur_node->state.s_predictor, 14);
223cabdff1aSopenharmony_ci                dec_diff = xlow - decoded;
224cabdff1aSopenharmony_ci
225cabdff1aSopenharmony_ci#define STORE_NODE(index, UPDATE, VALUE)\
226cabdff1aSopenharmony_ci                ssd = cur_node->ssd + dec_diff*dec_diff;\
227cabdff1aSopenharmony_ci                /* Check for wraparound. Using 64 bit ssd counters would \
228cabdff1aSopenharmony_ci                 * be simpler, but is slower on x86 32 bit. */\
229cabdff1aSopenharmony_ci                if (ssd < cur_node->ssd)\
230cabdff1aSopenharmony_ci                    continue;\
231cabdff1aSopenharmony_ci                if (heap_pos[index] < frontier) {\
232cabdff1aSopenharmony_ci                    pos = heap_pos[index]++;\
233cabdff1aSopenharmony_ci                    av_assert2(pathn[index] < FREEZE_INTERVAL * frontier);\
234cabdff1aSopenharmony_ci                    node = nodes_next[index][pos] = next[index]++;\
235cabdff1aSopenharmony_ci                    node->path = pathn[index]++;\
236cabdff1aSopenharmony_ci                } else {\
237cabdff1aSopenharmony_ci                    /* Try to replace one of the leaf nodes with the new \
238cabdff1aSopenharmony_ci                     * one, but not always testing the same leaf position */\
239cabdff1aSopenharmony_ci                    pos = (frontier>>1) + (heap_pos[index] & ((frontier>>1) - 1));\
240cabdff1aSopenharmony_ci                    if (ssd >= nodes_next[index][pos]->ssd)\
241cabdff1aSopenharmony_ci                        continue;\
242cabdff1aSopenharmony_ci                    heap_pos[index]++;\
243cabdff1aSopenharmony_ci                    node = nodes_next[index][pos];\
244cabdff1aSopenharmony_ci                }\
245cabdff1aSopenharmony_ci                node->ssd = ssd;\
246cabdff1aSopenharmony_ci                node->state = cur_node->state;\
247cabdff1aSopenharmony_ci                UPDATE;\
248cabdff1aSopenharmony_ci                c->paths[index][node->path].value = VALUE;\
249cabdff1aSopenharmony_ci                c->paths[index][node->path].prev = cur_node->path;\
250cabdff1aSopenharmony_ci                /* Sift the newly inserted node up in the heap to restore \
251cabdff1aSopenharmony_ci                 * the heap property */\
252cabdff1aSopenharmony_ci                while (pos > 0) {\
253cabdff1aSopenharmony_ci                    int parent = (pos - 1) >> 1;\
254cabdff1aSopenharmony_ci                    if (nodes_next[index][parent]->ssd <= ssd)\
255cabdff1aSopenharmony_ci                        break;\
256cabdff1aSopenharmony_ci                    FFSWAP(struct TrellisNode*, nodes_next[index][parent],\
257cabdff1aSopenharmony_ci                                                nodes_next[index][pos]);\
258cabdff1aSopenharmony_ci                    pos = parent;\
259cabdff1aSopenharmony_ci                }
260cabdff1aSopenharmony_ci                STORE_NODE(0, ff_g722_update_low_predictor(&node->state, k >> 2), k);
261cabdff1aSopenharmony_ci            }
262cabdff1aSopenharmony_ci        }
263cabdff1aSopenharmony_ci
264cabdff1aSopenharmony_ci        for (j = 0; j < frontier && nodes[1][j]; j++) {
265cabdff1aSopenharmony_ci            int ihigh;
266cabdff1aSopenharmony_ci            struct TrellisNode *cur_node = nodes[1][j];
267cabdff1aSopenharmony_ci
268cabdff1aSopenharmony_ci            /* We don't try to get any initial guess for ihigh via
269cabdff1aSopenharmony_ci             * encode_high - since there's only 4 possible values, test
270cabdff1aSopenharmony_ci             * them all. Testing all of these gives a much, much larger
271cabdff1aSopenharmony_ci             * gain than testing a larger range around ilow. */
272cabdff1aSopenharmony_ci            for (ihigh = 0; ihigh < 4; ihigh++) {
273cabdff1aSopenharmony_ci                int dhigh, decoded, dec_diff, pos;
274cabdff1aSopenharmony_ci                uint32_t ssd;
275cabdff1aSopenharmony_ci                struct TrellisNode* node;
276cabdff1aSopenharmony_ci
277cabdff1aSopenharmony_ci                dhigh = cur_node->state.scale_factor *
278cabdff1aSopenharmony_ci                        ff_g722_high_inv_quant[ihigh] >> 10;
279cabdff1aSopenharmony_ci                decoded = av_clip_intp2(dhigh + cur_node->state.s_predictor, 14);
280cabdff1aSopenharmony_ci                dec_diff = xhigh - decoded;
281cabdff1aSopenharmony_ci
282cabdff1aSopenharmony_ci                STORE_NODE(1, ff_g722_update_high_predictor(&node->state, dhigh, ihigh), ihigh);
283cabdff1aSopenharmony_ci            }
284cabdff1aSopenharmony_ci        }
285cabdff1aSopenharmony_ci
286cabdff1aSopenharmony_ci        for (j = 0; j < 2; j++) {
287cabdff1aSopenharmony_ci            FFSWAP(struct TrellisNode**, nodes[j], nodes_next[j]);
288cabdff1aSopenharmony_ci
289cabdff1aSopenharmony_ci            if (nodes[j][0]->ssd > (1 << 16)) {
290cabdff1aSopenharmony_ci                for (k = 1; k < frontier && nodes[j][k]; k++)
291cabdff1aSopenharmony_ci                    nodes[j][k]->ssd -= nodes[j][0]->ssd;
292cabdff1aSopenharmony_ci                nodes[j][0]->ssd = 0;
293cabdff1aSopenharmony_ci            }
294cabdff1aSopenharmony_ci        }
295cabdff1aSopenharmony_ci
296cabdff1aSopenharmony_ci        if (i == froze + FREEZE_INTERVAL) {
297cabdff1aSopenharmony_ci            p[0] = &c->paths[0][nodes[0][0]->path];
298cabdff1aSopenharmony_ci            p[1] = &c->paths[1][nodes[1][0]->path];
299cabdff1aSopenharmony_ci            for (j = i; j > froze; j--) {
300cabdff1aSopenharmony_ci                dst[j] = p[1]->value << 6 | p[0]->value;
301cabdff1aSopenharmony_ci                p[0] = &c->paths[0][p[0]->prev];
302cabdff1aSopenharmony_ci                p[1] = &c->paths[1][p[1]->prev];
303cabdff1aSopenharmony_ci            }
304cabdff1aSopenharmony_ci            froze = i;
305cabdff1aSopenharmony_ci            pathn[0] = pathn[1] = 0;
306cabdff1aSopenharmony_ci            memset(nodes[0] + 1, 0, (frontier - 1)*sizeof(**nodes));
307cabdff1aSopenharmony_ci            memset(nodes[1] + 1, 0, (frontier - 1)*sizeof(**nodes));
308cabdff1aSopenharmony_ci        }
309cabdff1aSopenharmony_ci    }
310cabdff1aSopenharmony_ci
311cabdff1aSopenharmony_ci    p[0] = &c->paths[0][nodes[0][0]->path];
312cabdff1aSopenharmony_ci    p[1] = &c->paths[1][nodes[1][0]->path];
313cabdff1aSopenharmony_ci    for (j = i; j > froze; j--) {
314cabdff1aSopenharmony_ci        dst[j] = p[1]->value << 6 | p[0]->value;
315cabdff1aSopenharmony_ci        p[0] = &c->paths[0][p[0]->prev];
316cabdff1aSopenharmony_ci        p[1] = &c->paths[1][p[1]->prev];
317cabdff1aSopenharmony_ci    }
318cabdff1aSopenharmony_ci    c->band[0] = nodes[0][0]->state;
319cabdff1aSopenharmony_ci    c->band[1] = nodes[1][0]->state;
320cabdff1aSopenharmony_ci}
321cabdff1aSopenharmony_ci
322cabdff1aSopenharmony_cistatic av_always_inline void encode_byte(G722Context *c, uint8_t *dst,
323cabdff1aSopenharmony_ci                                         const int16_t *samples)
324cabdff1aSopenharmony_ci{
325cabdff1aSopenharmony_ci    int xlow, xhigh, ilow, ihigh;
326cabdff1aSopenharmony_ci    filter_samples(c, samples, &xlow, &xhigh);
327cabdff1aSopenharmony_ci    ihigh = encode_high(&c->band[1], xhigh);
328cabdff1aSopenharmony_ci    ilow  = encode_low (&c->band[0], xlow);
329cabdff1aSopenharmony_ci    ff_g722_update_high_predictor(&c->band[1], c->band[1].scale_factor *
330cabdff1aSopenharmony_ci                                ff_g722_high_inv_quant[ihigh] >> 10, ihigh);
331cabdff1aSopenharmony_ci    ff_g722_update_low_predictor(&c->band[0], ilow >> 2);
332cabdff1aSopenharmony_ci    *dst = ihigh << 6 | ilow;
333cabdff1aSopenharmony_ci}
334cabdff1aSopenharmony_ci
335cabdff1aSopenharmony_cistatic void g722_encode_no_trellis(G722Context *c,
336cabdff1aSopenharmony_ci                                   uint8_t *dst, int nb_samples,
337cabdff1aSopenharmony_ci                                   const int16_t *samples)
338cabdff1aSopenharmony_ci{
339cabdff1aSopenharmony_ci    int i;
340cabdff1aSopenharmony_ci    for (i = 0; i < nb_samples; i += 2)
341cabdff1aSopenharmony_ci        encode_byte(c, dst++, &samples[i]);
342cabdff1aSopenharmony_ci}
343cabdff1aSopenharmony_ci
344cabdff1aSopenharmony_cistatic int g722_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
345cabdff1aSopenharmony_ci                             const AVFrame *frame, int *got_packet_ptr)
346cabdff1aSopenharmony_ci{
347cabdff1aSopenharmony_ci    G722Context *c = avctx->priv_data;
348cabdff1aSopenharmony_ci    const int16_t *samples = (const int16_t *)frame->data[0];
349cabdff1aSopenharmony_ci    int nb_samples, out_size, ret;
350cabdff1aSopenharmony_ci
351cabdff1aSopenharmony_ci    out_size = (frame->nb_samples + 1) / 2;
352cabdff1aSopenharmony_ci    if ((ret = ff_get_encode_buffer(avctx, avpkt, out_size, 0)) < 0)
353cabdff1aSopenharmony_ci        return ret;
354cabdff1aSopenharmony_ci
355cabdff1aSopenharmony_ci    nb_samples = frame->nb_samples - (frame->nb_samples & 1);
356cabdff1aSopenharmony_ci
357cabdff1aSopenharmony_ci    if (avctx->trellis)
358cabdff1aSopenharmony_ci        g722_encode_trellis(c, avctx->trellis, avpkt->data, nb_samples, samples);
359cabdff1aSopenharmony_ci    else
360cabdff1aSopenharmony_ci        g722_encode_no_trellis(c, avpkt->data, nb_samples, samples);
361cabdff1aSopenharmony_ci
362cabdff1aSopenharmony_ci    /* handle last frame with odd frame_size */
363cabdff1aSopenharmony_ci    if (nb_samples < frame->nb_samples) {
364cabdff1aSopenharmony_ci        int16_t last_samples[2] = { samples[nb_samples], samples[nb_samples] };
365cabdff1aSopenharmony_ci        encode_byte(c, &avpkt->data[nb_samples >> 1], last_samples);
366cabdff1aSopenharmony_ci    }
367cabdff1aSopenharmony_ci
368cabdff1aSopenharmony_ci    if (frame->pts != AV_NOPTS_VALUE)
369cabdff1aSopenharmony_ci        avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->initial_padding);
370cabdff1aSopenharmony_ci    *got_packet_ptr = 1;
371cabdff1aSopenharmony_ci    return 0;
372cabdff1aSopenharmony_ci}
373cabdff1aSopenharmony_ci
374cabdff1aSopenharmony_ciconst FFCodec ff_adpcm_g722_encoder = {
375cabdff1aSopenharmony_ci    .p.name          = "g722",
376cabdff1aSopenharmony_ci    .p.long_name     = NULL_IF_CONFIG_SMALL("G.722 ADPCM"),
377cabdff1aSopenharmony_ci    .p.type          = AVMEDIA_TYPE_AUDIO,
378cabdff1aSopenharmony_ci    .p.id            = AV_CODEC_ID_ADPCM_G722,
379cabdff1aSopenharmony_ci    .p.capabilities  = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME,
380cabdff1aSopenharmony_ci    .priv_data_size  = sizeof(G722Context),
381cabdff1aSopenharmony_ci    .init            = g722_encode_init,
382cabdff1aSopenharmony_ci    .close           = g722_encode_close,
383cabdff1aSopenharmony_ci    FF_CODEC_ENCODE_CB(g722_encode_frame),
384cabdff1aSopenharmony_ci    .p.sample_fmts   = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE },
385cabdff1aSopenharmony_ci#if FF_API_OLD_CHANNEL_LAYOUT
386cabdff1aSopenharmony_ci    .p.channel_layouts = (const uint64_t[]){ AV_CH_LAYOUT_MONO, 0 },
387cabdff1aSopenharmony_ci#endif
388cabdff1aSopenharmony_ci    .p.ch_layouts   = (const AVChannelLayout[]){
389cabdff1aSopenharmony_ci        AV_CHANNEL_LAYOUT_MONO, { 0 }
390cabdff1aSopenharmony_ci    },
391cabdff1aSopenharmony_ci    .caps_internal   = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
392cabdff1aSopenharmony_ci};
393