xref: /third_party/ffmpeg/libavcodec/vorbis.c (revision cabdff1a)
1cabdff1aSopenharmony_ci/**
2cabdff1aSopenharmony_ci * @file
3cabdff1aSopenharmony_ci * Common code for Vorbis I encoder and decoder
4cabdff1aSopenharmony_ci * @author Denes Balatoni  ( dbalatoni programozo hu )
5cabdff1aSopenharmony_ci *
6cabdff1aSopenharmony_ci * This file is part of FFmpeg.
7cabdff1aSopenharmony_ci *
8cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
9cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
10cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
11cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
12cabdff1aSopenharmony_ci *
13cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
14cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
15cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16cabdff1aSopenharmony_ci * Lesser General Public License for more details.
17cabdff1aSopenharmony_ci *
18cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
19cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
20cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21cabdff1aSopenharmony_ci */
22cabdff1aSopenharmony_ci
23cabdff1aSopenharmony_ci/**
24cabdff1aSopenharmony_ci * @file
25cabdff1aSopenharmony_ci * Common code for Vorbis I encoder and decoder
26cabdff1aSopenharmony_ci * @author Denes Balatoni  ( dbalatoni programozo hu )
27cabdff1aSopenharmony_ci */
28cabdff1aSopenharmony_ci
29cabdff1aSopenharmony_ci#include "libavutil/common.h"
30cabdff1aSopenharmony_ci
31cabdff1aSopenharmony_ci#include "avcodec.h"
32cabdff1aSopenharmony_ci#include "vorbis.h"
33cabdff1aSopenharmony_ci
34cabdff1aSopenharmony_ci
35cabdff1aSopenharmony_ci/* Helper functions */
36cabdff1aSopenharmony_ci
37cabdff1aSopenharmony_ci// x^(1/n)
38cabdff1aSopenharmony_ciunsigned int ff_vorbis_nth_root(unsigned int x, unsigned int n)
39cabdff1aSopenharmony_ci{
40cabdff1aSopenharmony_ci    unsigned int ret = 0, i, j;
41cabdff1aSopenharmony_ci
42cabdff1aSopenharmony_ci    do {
43cabdff1aSopenharmony_ci        ++ret;
44cabdff1aSopenharmony_ci        for (i = 0, j = ret; i < n - 1; i++)
45cabdff1aSopenharmony_ci            j *= ret;
46cabdff1aSopenharmony_ci    } while (j <= x);
47cabdff1aSopenharmony_ci
48cabdff1aSopenharmony_ci    return ret - 1;
49cabdff1aSopenharmony_ci}
50cabdff1aSopenharmony_ci
51cabdff1aSopenharmony_ci// Generate vlc codes from vorbis huffman code lengths
52cabdff1aSopenharmony_ci
53cabdff1aSopenharmony_ci// the two bits[p] > 32 checks should be redundant, all calling code should
54cabdff1aSopenharmony_ci// already ensure that, but since it allows overwriting the stack it seems
55cabdff1aSopenharmony_ci// reasonable to check redundantly.
56cabdff1aSopenharmony_ciint ff_vorbis_len2vlc(uint8_t *bits, uint32_t *codes, unsigned num)
57cabdff1aSopenharmony_ci{
58cabdff1aSopenharmony_ci    uint32_t exit_at_level[33] = { 404 };
59cabdff1aSopenharmony_ci    unsigned i, j, p, code;
60cabdff1aSopenharmony_ci
61cabdff1aSopenharmony_ci    for (p = 0; (p < num) && (bits[p] == 0); ++p)
62cabdff1aSopenharmony_ci        ;
63cabdff1aSopenharmony_ci    if (p == num)
64cabdff1aSopenharmony_ci        return 0;
65cabdff1aSopenharmony_ci
66cabdff1aSopenharmony_ci    codes[p] = 0;
67cabdff1aSopenharmony_ci    if (bits[p] > 32)
68cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
69cabdff1aSopenharmony_ci    for (i = 0; i < bits[p]; ++i)
70cabdff1aSopenharmony_ci        exit_at_level[i+1] = 1u << i;
71cabdff1aSopenharmony_ci
72cabdff1aSopenharmony_ci    ++p;
73cabdff1aSopenharmony_ci
74cabdff1aSopenharmony_ci    for (i = p; (i < num) && (bits[i] == 0); ++i)
75cabdff1aSopenharmony_ci        ;
76cabdff1aSopenharmony_ci    if (i == num)
77cabdff1aSopenharmony_ci        return 0;
78cabdff1aSopenharmony_ci
79cabdff1aSopenharmony_ci    for (; p < num; ++p) {
80cabdff1aSopenharmony_ci        if (bits[p] > 32)
81cabdff1aSopenharmony_ci             return AVERROR_INVALIDDATA;
82cabdff1aSopenharmony_ci        if (bits[p] == 0)
83cabdff1aSopenharmony_ci             continue;
84cabdff1aSopenharmony_ci        // find corresponding exit(node which the tree can grow further from)
85cabdff1aSopenharmony_ci        for (i = bits[p]; i > 0; --i)
86cabdff1aSopenharmony_ci            if (exit_at_level[i])
87cabdff1aSopenharmony_ci                break;
88cabdff1aSopenharmony_ci        if (!i) // overspecified tree
89cabdff1aSopenharmony_ci             return AVERROR_INVALIDDATA;
90cabdff1aSopenharmony_ci        code = exit_at_level[i];
91cabdff1aSopenharmony_ci        exit_at_level[i] = 0;
92cabdff1aSopenharmony_ci        // construct code (append 0s to end) and introduce new exits
93cabdff1aSopenharmony_ci        for (j = i + 1 ;j <= bits[p]; ++j)
94cabdff1aSopenharmony_ci            exit_at_level[j] = code + (1u << (j - 1));
95cabdff1aSopenharmony_ci        codes[p] = code;
96cabdff1aSopenharmony_ci    }
97cabdff1aSopenharmony_ci
98cabdff1aSopenharmony_ci    //no exits should be left (underspecified tree - ie. unused valid vlcs - not allowed by SPEC)
99cabdff1aSopenharmony_ci    for (p = 1; p < 33; p++)
100cabdff1aSopenharmony_ci        if (exit_at_level[p])
101cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
102cabdff1aSopenharmony_ci
103cabdff1aSopenharmony_ci    return 0;
104cabdff1aSopenharmony_ci}
105cabdff1aSopenharmony_ci
106cabdff1aSopenharmony_ciint ff_vorbis_ready_floor1_list(AVCodecContext *avctx,
107cabdff1aSopenharmony_ci                                vorbis_floor1_entry *list, int values)
108cabdff1aSopenharmony_ci{
109cabdff1aSopenharmony_ci    int i;
110cabdff1aSopenharmony_ci    list[0].sort = 0;
111cabdff1aSopenharmony_ci    list[1].sort = 1;
112cabdff1aSopenharmony_ci    for (i = 2; i < values; i++) {
113cabdff1aSopenharmony_ci        int j;
114cabdff1aSopenharmony_ci        list[i].low  = 0;
115cabdff1aSopenharmony_ci        list[i].high = 1;
116cabdff1aSopenharmony_ci        list[i].sort = i;
117cabdff1aSopenharmony_ci        for (j = 2; j < i; j++) {
118cabdff1aSopenharmony_ci            int tmp = list[j].x;
119cabdff1aSopenharmony_ci            if (tmp < list[i].x) {
120cabdff1aSopenharmony_ci                if (tmp > list[list[i].low].x)
121cabdff1aSopenharmony_ci                    list[i].low  =  j;
122cabdff1aSopenharmony_ci            } else {
123cabdff1aSopenharmony_ci                if (tmp < list[list[i].high].x)
124cabdff1aSopenharmony_ci                    list[i].high = j;
125cabdff1aSopenharmony_ci            }
126cabdff1aSopenharmony_ci        }
127cabdff1aSopenharmony_ci    }
128cabdff1aSopenharmony_ci    for (i = 0; i < values - 1; i++) {
129cabdff1aSopenharmony_ci        int j;
130cabdff1aSopenharmony_ci        for (j = i + 1; j < values; j++) {
131cabdff1aSopenharmony_ci            if (list[i].x == list[j].x) {
132cabdff1aSopenharmony_ci                av_log(avctx, AV_LOG_ERROR,
133cabdff1aSopenharmony_ci                       "Duplicate value found in floor 1 X coordinates\n");
134cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
135cabdff1aSopenharmony_ci            }
136cabdff1aSopenharmony_ci            if (list[list[i].sort].x > list[list[j].sort].x) {
137cabdff1aSopenharmony_ci                int tmp = list[i].sort;
138cabdff1aSopenharmony_ci                list[i].sort = list[j].sort;
139cabdff1aSopenharmony_ci                list[j].sort = tmp;
140cabdff1aSopenharmony_ci            }
141cabdff1aSopenharmony_ci        }
142cabdff1aSopenharmony_ci    }
143cabdff1aSopenharmony_ci    return 0;
144cabdff1aSopenharmony_ci}
145cabdff1aSopenharmony_ci
146cabdff1aSopenharmony_cistatic inline void render_line_unrolled(intptr_t x, int y, int x1,
147cabdff1aSopenharmony_ci                                        intptr_t sy, int ady, int adx,
148cabdff1aSopenharmony_ci                                        float *buf)
149cabdff1aSopenharmony_ci{
150cabdff1aSopenharmony_ci    int err = -adx;
151cabdff1aSopenharmony_ci    x -= x1 - 1;
152cabdff1aSopenharmony_ci    buf += x1 - 1;
153cabdff1aSopenharmony_ci    while (++x < 0) {
154cabdff1aSopenharmony_ci        err += ady;
155cabdff1aSopenharmony_ci        if (err >= 0) {
156cabdff1aSopenharmony_ci            err += ady - adx;
157cabdff1aSopenharmony_ci            y   += sy;
158cabdff1aSopenharmony_ci            buf[x++] = ff_vorbis_floor1_inverse_db_table[av_clip_uint8(y)];
159cabdff1aSopenharmony_ci        }
160cabdff1aSopenharmony_ci        buf[x] = ff_vorbis_floor1_inverse_db_table[av_clip_uint8(y)];
161cabdff1aSopenharmony_ci    }
162cabdff1aSopenharmony_ci    if (x <= 0) {
163cabdff1aSopenharmony_ci        if (err + ady >= 0)
164cabdff1aSopenharmony_ci            y += sy;
165cabdff1aSopenharmony_ci        buf[x] = ff_vorbis_floor1_inverse_db_table[av_clip_uint8(y)];
166cabdff1aSopenharmony_ci    }
167cabdff1aSopenharmony_ci}
168cabdff1aSopenharmony_ci
169cabdff1aSopenharmony_cistatic void render_line(int x0, int y0, int x1, int y1, float *buf)
170cabdff1aSopenharmony_ci{
171cabdff1aSopenharmony_ci    int dy  = y1 - y0;
172cabdff1aSopenharmony_ci    int adx = x1 - x0;
173cabdff1aSopenharmony_ci    int ady = FFABS(dy);
174cabdff1aSopenharmony_ci    int sy  = dy < 0 ? -1 : 1;
175cabdff1aSopenharmony_ci    buf[x0] = ff_vorbis_floor1_inverse_db_table[av_clip_uint8(y0)];
176cabdff1aSopenharmony_ci    if (ady*2 <= adx) { // optimized common case
177cabdff1aSopenharmony_ci        render_line_unrolled(x0, y0, x1, sy, ady, adx, buf);
178cabdff1aSopenharmony_ci    } else {
179cabdff1aSopenharmony_ci        int base  = dy / adx;
180cabdff1aSopenharmony_ci        int x     = x0;
181cabdff1aSopenharmony_ci        int y     = y0;
182cabdff1aSopenharmony_ci        int err   = -adx;
183cabdff1aSopenharmony_ci        ady -= FFABS(base) * adx;
184cabdff1aSopenharmony_ci        while (++x < x1) {
185cabdff1aSopenharmony_ci            y += base;
186cabdff1aSopenharmony_ci            err += ady;
187cabdff1aSopenharmony_ci            if (err >= 0) {
188cabdff1aSopenharmony_ci                err -= adx;
189cabdff1aSopenharmony_ci                y   += sy;
190cabdff1aSopenharmony_ci            }
191cabdff1aSopenharmony_ci            buf[x] = ff_vorbis_floor1_inverse_db_table[av_clip_uint8(y)];
192cabdff1aSopenharmony_ci        }
193cabdff1aSopenharmony_ci    }
194cabdff1aSopenharmony_ci}
195cabdff1aSopenharmony_ci
196cabdff1aSopenharmony_civoid ff_vorbis_floor1_render_list(vorbis_floor1_entry * list, int values,
197cabdff1aSopenharmony_ci                                  uint16_t *y_list, int *flag,
198cabdff1aSopenharmony_ci                                  int multiplier, float *out, int samples)
199cabdff1aSopenharmony_ci{
200cabdff1aSopenharmony_ci    int lx, ly, i;
201cabdff1aSopenharmony_ci    lx = 0;
202cabdff1aSopenharmony_ci    ly = y_list[0] * multiplier;
203cabdff1aSopenharmony_ci    for (i = 1; i < values; i++) {
204cabdff1aSopenharmony_ci        int pos = list[i].sort;
205cabdff1aSopenharmony_ci        if (flag[pos]) {
206cabdff1aSopenharmony_ci            int x1 = list[pos].x;
207cabdff1aSopenharmony_ci            int y1 = y_list[pos] * multiplier;
208cabdff1aSopenharmony_ci            if (lx < samples)
209cabdff1aSopenharmony_ci                render_line(lx, ly, FFMIN(x1,samples), y1, out);
210cabdff1aSopenharmony_ci            lx = x1;
211cabdff1aSopenharmony_ci            ly = y1;
212cabdff1aSopenharmony_ci        }
213cabdff1aSopenharmony_ci        if (lx >= samples)
214cabdff1aSopenharmony_ci            break;
215cabdff1aSopenharmony_ci    }
216cabdff1aSopenharmony_ci    if (lx < samples)
217cabdff1aSopenharmony_ci        render_line(lx, ly, samples, ly, out);
218cabdff1aSopenharmony_ci}
219