xref: /third_party/ffmpeg/libavcodec/cbs_vp9.c (revision cabdff1a)
1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * This file is part of FFmpeg.
3cabdff1aSopenharmony_ci *
4cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
5cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
6cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
7cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
8cabdff1aSopenharmony_ci *
9cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
10cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
11cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12cabdff1aSopenharmony_ci * Lesser General Public License for more details.
13cabdff1aSopenharmony_ci *
14cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
15cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
16cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17cabdff1aSopenharmony_ci */
18cabdff1aSopenharmony_ci
19cabdff1aSopenharmony_ci#include "libavutil/avassert.h"
20cabdff1aSopenharmony_ci
21cabdff1aSopenharmony_ci#include "cbs.h"
22cabdff1aSopenharmony_ci#include "cbs_internal.h"
23cabdff1aSopenharmony_ci#include "cbs_vp9.h"
24cabdff1aSopenharmony_ci
25cabdff1aSopenharmony_ci
26cabdff1aSopenharmony_cistatic int cbs_vp9_read_s(CodedBitstreamContext *ctx, GetBitContext *gbc,
27cabdff1aSopenharmony_ci                          int width, const char *name,
28cabdff1aSopenharmony_ci                          const int *subscripts, int32_t *write_to)
29cabdff1aSopenharmony_ci{
30cabdff1aSopenharmony_ci    uint32_t magnitude;
31cabdff1aSopenharmony_ci    int position, sign;
32cabdff1aSopenharmony_ci    int32_t value;
33cabdff1aSopenharmony_ci
34cabdff1aSopenharmony_ci    if (ctx->trace_enable)
35cabdff1aSopenharmony_ci        position = get_bits_count(gbc);
36cabdff1aSopenharmony_ci
37cabdff1aSopenharmony_ci    if (get_bits_left(gbc) < width + 1) {
38cabdff1aSopenharmony_ci        av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid signed value at "
39cabdff1aSopenharmony_ci               "%s: bitstream ended.\n", name);
40cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
41cabdff1aSopenharmony_ci    }
42cabdff1aSopenharmony_ci
43cabdff1aSopenharmony_ci    magnitude = get_bits(gbc, width);
44cabdff1aSopenharmony_ci    sign      = get_bits1(gbc);
45cabdff1aSopenharmony_ci    value     = sign ? -(int32_t)magnitude : magnitude;
46cabdff1aSopenharmony_ci
47cabdff1aSopenharmony_ci    if (ctx->trace_enable) {
48cabdff1aSopenharmony_ci        char bits[33];
49cabdff1aSopenharmony_ci        int i;
50cabdff1aSopenharmony_ci        for (i = 0; i < width; i++)
51cabdff1aSopenharmony_ci            bits[i] = magnitude >> (width - i - 1) & 1 ? '1' : '0';
52cabdff1aSopenharmony_ci        bits[i] = sign ? '1' : '0';
53cabdff1aSopenharmony_ci        bits[i + 1] = 0;
54cabdff1aSopenharmony_ci
55cabdff1aSopenharmony_ci        ff_cbs_trace_syntax_element(ctx, position, name, subscripts,
56cabdff1aSopenharmony_ci                                    bits, value);
57cabdff1aSopenharmony_ci    }
58cabdff1aSopenharmony_ci
59cabdff1aSopenharmony_ci    *write_to = value;
60cabdff1aSopenharmony_ci    return 0;
61cabdff1aSopenharmony_ci}
62cabdff1aSopenharmony_ci
63cabdff1aSopenharmony_cistatic int cbs_vp9_write_s(CodedBitstreamContext *ctx, PutBitContext *pbc,
64cabdff1aSopenharmony_ci                           int width, const char *name,
65cabdff1aSopenharmony_ci                           const int *subscripts, int32_t value)
66cabdff1aSopenharmony_ci{
67cabdff1aSopenharmony_ci    uint32_t magnitude;
68cabdff1aSopenharmony_ci    int sign;
69cabdff1aSopenharmony_ci
70cabdff1aSopenharmony_ci    if (put_bits_left(pbc) < width + 1)
71cabdff1aSopenharmony_ci        return AVERROR(ENOSPC);
72cabdff1aSopenharmony_ci
73cabdff1aSopenharmony_ci    sign      = value < 0;
74cabdff1aSopenharmony_ci    magnitude = sign ? -value : value;
75cabdff1aSopenharmony_ci
76cabdff1aSopenharmony_ci    if (ctx->trace_enable) {
77cabdff1aSopenharmony_ci        char bits[33];
78cabdff1aSopenharmony_ci        int i;
79cabdff1aSopenharmony_ci        for (i = 0; i < width; i++)
80cabdff1aSopenharmony_ci            bits[i] = magnitude >> (width - i - 1) & 1 ? '1' : '0';
81cabdff1aSopenharmony_ci        bits[i] = sign ? '1' : '0';
82cabdff1aSopenharmony_ci        bits[i + 1] = 0;
83cabdff1aSopenharmony_ci
84cabdff1aSopenharmony_ci        ff_cbs_trace_syntax_element(ctx, put_bits_count(pbc),
85cabdff1aSopenharmony_ci                                    name, subscripts, bits, value);
86cabdff1aSopenharmony_ci    }
87cabdff1aSopenharmony_ci
88cabdff1aSopenharmony_ci    put_bits(pbc, width, magnitude);
89cabdff1aSopenharmony_ci    put_bits(pbc, 1, sign);
90cabdff1aSopenharmony_ci
91cabdff1aSopenharmony_ci    return 0;
92cabdff1aSopenharmony_ci}
93cabdff1aSopenharmony_ci
94cabdff1aSopenharmony_cistatic int cbs_vp9_read_increment(CodedBitstreamContext *ctx, GetBitContext *gbc,
95cabdff1aSopenharmony_ci                                  uint32_t range_min, uint32_t range_max,
96cabdff1aSopenharmony_ci                                  const char *name, uint32_t *write_to)
97cabdff1aSopenharmony_ci{
98cabdff1aSopenharmony_ci    uint32_t value;
99cabdff1aSopenharmony_ci    int position, i;
100cabdff1aSopenharmony_ci    char bits[8];
101cabdff1aSopenharmony_ci
102cabdff1aSopenharmony_ci    av_assert0(range_min <= range_max && range_max - range_min < sizeof(bits) - 1);
103cabdff1aSopenharmony_ci    if (ctx->trace_enable)
104cabdff1aSopenharmony_ci        position = get_bits_count(gbc);
105cabdff1aSopenharmony_ci
106cabdff1aSopenharmony_ci    for (i = 0, value = range_min; value < range_max;) {
107cabdff1aSopenharmony_ci        if (get_bits_left(gbc) < 1) {
108cabdff1aSopenharmony_ci            av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid increment value at "
109cabdff1aSopenharmony_ci                   "%s: bitstream ended.\n", name);
110cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
111cabdff1aSopenharmony_ci        }
112cabdff1aSopenharmony_ci        if (get_bits1(gbc)) {
113cabdff1aSopenharmony_ci            bits[i++] = '1';
114cabdff1aSopenharmony_ci            ++value;
115cabdff1aSopenharmony_ci        } else {
116cabdff1aSopenharmony_ci            bits[i++] = '0';
117cabdff1aSopenharmony_ci            break;
118cabdff1aSopenharmony_ci        }
119cabdff1aSopenharmony_ci    }
120cabdff1aSopenharmony_ci
121cabdff1aSopenharmony_ci    if (ctx->trace_enable) {
122cabdff1aSopenharmony_ci        bits[i] = 0;
123cabdff1aSopenharmony_ci        ff_cbs_trace_syntax_element(ctx, position, name, NULL, bits, value);
124cabdff1aSopenharmony_ci    }
125cabdff1aSopenharmony_ci
126cabdff1aSopenharmony_ci    *write_to = value;
127cabdff1aSopenharmony_ci    return 0;
128cabdff1aSopenharmony_ci}
129cabdff1aSopenharmony_ci
130cabdff1aSopenharmony_cistatic int cbs_vp9_write_increment(CodedBitstreamContext *ctx, PutBitContext *pbc,
131cabdff1aSopenharmony_ci                                   uint32_t range_min, uint32_t range_max,
132cabdff1aSopenharmony_ci                                   const char *name, uint32_t value)
133cabdff1aSopenharmony_ci{
134cabdff1aSopenharmony_ci    int len;
135cabdff1aSopenharmony_ci
136cabdff1aSopenharmony_ci    av_assert0(range_min <= range_max && range_max - range_min < 8);
137cabdff1aSopenharmony_ci    if (value < range_min || value > range_max) {
138cabdff1aSopenharmony_ci        av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: "
139cabdff1aSopenharmony_ci               "%"PRIu32", but must be in [%"PRIu32",%"PRIu32"].\n",
140cabdff1aSopenharmony_ci               name, value, range_min, range_max);
141cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
142cabdff1aSopenharmony_ci    }
143cabdff1aSopenharmony_ci
144cabdff1aSopenharmony_ci    if (value == range_max)
145cabdff1aSopenharmony_ci        len = range_max - range_min;
146cabdff1aSopenharmony_ci    else
147cabdff1aSopenharmony_ci        len = value - range_min + 1;
148cabdff1aSopenharmony_ci    if (put_bits_left(pbc) < len)
149cabdff1aSopenharmony_ci        return AVERROR(ENOSPC);
150cabdff1aSopenharmony_ci
151cabdff1aSopenharmony_ci    if (ctx->trace_enable) {
152cabdff1aSopenharmony_ci        char bits[8];
153cabdff1aSopenharmony_ci        int i;
154cabdff1aSopenharmony_ci        for (i = 0; i < len; i++) {
155cabdff1aSopenharmony_ci            if (range_min + i == value)
156cabdff1aSopenharmony_ci                bits[i] = '0';
157cabdff1aSopenharmony_ci            else
158cabdff1aSopenharmony_ci                bits[i] = '1';
159cabdff1aSopenharmony_ci        }
160cabdff1aSopenharmony_ci        bits[i] = 0;
161cabdff1aSopenharmony_ci        ff_cbs_trace_syntax_element(ctx, put_bits_count(pbc),
162cabdff1aSopenharmony_ci                                    name, NULL, bits, value);
163cabdff1aSopenharmony_ci    }
164cabdff1aSopenharmony_ci
165cabdff1aSopenharmony_ci    if (len > 0)
166cabdff1aSopenharmony_ci        put_bits(pbc, len, (1 << len) - 1 - (value != range_max));
167cabdff1aSopenharmony_ci
168cabdff1aSopenharmony_ci    return 0;
169cabdff1aSopenharmony_ci}
170cabdff1aSopenharmony_ci
171cabdff1aSopenharmony_cistatic int cbs_vp9_read_le(CodedBitstreamContext *ctx, GetBitContext *gbc,
172cabdff1aSopenharmony_ci                           int width, const char *name,
173cabdff1aSopenharmony_ci                           const int *subscripts, uint32_t *write_to)
174cabdff1aSopenharmony_ci{
175cabdff1aSopenharmony_ci    uint32_t value;
176cabdff1aSopenharmony_ci    int position, b;
177cabdff1aSopenharmony_ci
178cabdff1aSopenharmony_ci    av_assert0(width % 8 == 0);
179cabdff1aSopenharmony_ci
180cabdff1aSopenharmony_ci    if (ctx->trace_enable)
181cabdff1aSopenharmony_ci        position = get_bits_count(gbc);
182cabdff1aSopenharmony_ci
183cabdff1aSopenharmony_ci    if (get_bits_left(gbc) < width) {
184cabdff1aSopenharmony_ci        av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid le value at "
185cabdff1aSopenharmony_ci               "%s: bitstream ended.\n", name);
186cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
187cabdff1aSopenharmony_ci    }
188cabdff1aSopenharmony_ci
189cabdff1aSopenharmony_ci    value = 0;
190cabdff1aSopenharmony_ci    for (b = 0; b < width; b += 8)
191cabdff1aSopenharmony_ci        value |= get_bits(gbc, 8) << b;
192cabdff1aSopenharmony_ci
193cabdff1aSopenharmony_ci    if (ctx->trace_enable) {
194cabdff1aSopenharmony_ci        char bits[33];
195cabdff1aSopenharmony_ci        int i;
196cabdff1aSopenharmony_ci        for (b = 0; b < width; b += 8)
197cabdff1aSopenharmony_ci            for (i = 0; i < 8; i++)
198cabdff1aSopenharmony_ci                bits[b + i] = value >> (b + i) & 1 ? '1' : '0';
199cabdff1aSopenharmony_ci        bits[b] = 0;
200cabdff1aSopenharmony_ci
201cabdff1aSopenharmony_ci        ff_cbs_trace_syntax_element(ctx, position, name, subscripts,
202cabdff1aSopenharmony_ci                                    bits, value);
203cabdff1aSopenharmony_ci    }
204cabdff1aSopenharmony_ci
205cabdff1aSopenharmony_ci    *write_to = value;
206cabdff1aSopenharmony_ci    return 0;
207cabdff1aSopenharmony_ci}
208cabdff1aSopenharmony_ci
209cabdff1aSopenharmony_cistatic int cbs_vp9_write_le(CodedBitstreamContext *ctx, PutBitContext *pbc,
210cabdff1aSopenharmony_ci                            int width, const char *name,
211cabdff1aSopenharmony_ci                            const int *subscripts, uint32_t value)
212cabdff1aSopenharmony_ci{
213cabdff1aSopenharmony_ci    int b;
214cabdff1aSopenharmony_ci
215cabdff1aSopenharmony_ci    av_assert0(width % 8 == 0);
216cabdff1aSopenharmony_ci
217cabdff1aSopenharmony_ci    if (put_bits_left(pbc) < width)
218cabdff1aSopenharmony_ci        return AVERROR(ENOSPC);
219cabdff1aSopenharmony_ci
220cabdff1aSopenharmony_ci    if (ctx->trace_enable) {
221cabdff1aSopenharmony_ci        char bits[33];
222cabdff1aSopenharmony_ci        int i;
223cabdff1aSopenharmony_ci        for (b = 0; b < width; b += 8)
224cabdff1aSopenharmony_ci            for (i = 0; i < 8; i++)
225cabdff1aSopenharmony_ci                bits[b + i] = value >> (b + i) & 1 ? '1' : '0';
226cabdff1aSopenharmony_ci        bits[b] = 0;
227cabdff1aSopenharmony_ci
228cabdff1aSopenharmony_ci        ff_cbs_trace_syntax_element(ctx, put_bits_count(pbc),
229cabdff1aSopenharmony_ci                                    name, subscripts, bits, value);
230cabdff1aSopenharmony_ci    }
231cabdff1aSopenharmony_ci
232cabdff1aSopenharmony_ci    for (b = 0; b < width; b += 8)
233cabdff1aSopenharmony_ci        put_bits(pbc, 8, value >> b & 0xff);
234cabdff1aSopenharmony_ci
235cabdff1aSopenharmony_ci    return 0;
236cabdff1aSopenharmony_ci}
237cabdff1aSopenharmony_ci
238cabdff1aSopenharmony_ci#define HEADER(name) do { \
239cabdff1aSopenharmony_ci        ff_cbs_trace_header(ctx, name); \
240cabdff1aSopenharmony_ci    } while (0)
241cabdff1aSopenharmony_ci
242cabdff1aSopenharmony_ci#define CHECK(call) do { \
243cabdff1aSopenharmony_ci        err = (call); \
244cabdff1aSopenharmony_ci        if (err < 0) \
245cabdff1aSopenharmony_ci            return err; \
246cabdff1aSopenharmony_ci    } while (0)
247cabdff1aSopenharmony_ci
248cabdff1aSopenharmony_ci#define FUNC_NAME(rw, codec, name) cbs_ ## codec ## _ ## rw ## _ ## name
249cabdff1aSopenharmony_ci#define FUNC_VP9(rw, name) FUNC_NAME(rw, vp9, name)
250cabdff1aSopenharmony_ci#define FUNC(name) FUNC_VP9(READWRITE, name)
251cabdff1aSopenharmony_ci
252cabdff1aSopenharmony_ci#define SUBSCRIPTS(subs, ...) (subs > 0 ? ((int[subs + 1]){ subs, __VA_ARGS__ }) : NULL)
253cabdff1aSopenharmony_ci
254cabdff1aSopenharmony_ci#define f(width, name) \
255cabdff1aSopenharmony_ci        xf(width, name, current->name, 0, )
256cabdff1aSopenharmony_ci#define s(width, name) \
257cabdff1aSopenharmony_ci        xs(width, name, current->name, 0, )
258cabdff1aSopenharmony_ci#define fs(width, name, subs, ...) \
259cabdff1aSopenharmony_ci        xf(width, name, current->name, subs, __VA_ARGS__)
260cabdff1aSopenharmony_ci#define ss(width, name, subs, ...) \
261cabdff1aSopenharmony_ci        xs(width, name, current->name, subs, __VA_ARGS__)
262cabdff1aSopenharmony_ci
263cabdff1aSopenharmony_ci#define READ
264cabdff1aSopenharmony_ci#define READWRITE read
265cabdff1aSopenharmony_ci#define RWContext GetBitContext
266cabdff1aSopenharmony_ci
267cabdff1aSopenharmony_ci#define xf(width, name, var, subs, ...) do { \
268cabdff1aSopenharmony_ci        uint32_t value; \
269cabdff1aSopenharmony_ci        CHECK(ff_cbs_read_unsigned(ctx, rw, width, #name, \
270cabdff1aSopenharmony_ci                                   SUBSCRIPTS(subs, __VA_ARGS__), \
271cabdff1aSopenharmony_ci                                   &value, 0, (1 << width) - 1)); \
272cabdff1aSopenharmony_ci        var = value; \
273cabdff1aSopenharmony_ci    } while (0)
274cabdff1aSopenharmony_ci#define xs(width, name, var, subs, ...) do { \
275cabdff1aSopenharmony_ci        int32_t value; \
276cabdff1aSopenharmony_ci        CHECK(cbs_vp9_read_s(ctx, rw, width, #name, \
277cabdff1aSopenharmony_ci                             SUBSCRIPTS(subs, __VA_ARGS__), &value)); \
278cabdff1aSopenharmony_ci        var = value; \
279cabdff1aSopenharmony_ci    } while (0)
280cabdff1aSopenharmony_ci
281cabdff1aSopenharmony_ci
282cabdff1aSopenharmony_ci#define increment(name, min, max) do { \
283cabdff1aSopenharmony_ci        uint32_t value; \
284cabdff1aSopenharmony_ci        CHECK(cbs_vp9_read_increment(ctx, rw, min, max, #name, &value)); \
285cabdff1aSopenharmony_ci        current->name = value; \
286cabdff1aSopenharmony_ci    } while (0)
287cabdff1aSopenharmony_ci
288cabdff1aSopenharmony_ci#define fle(width, name, subs, ...) do { \
289cabdff1aSopenharmony_ci        CHECK(cbs_vp9_read_le(ctx, rw, width, #name, \
290cabdff1aSopenharmony_ci                              SUBSCRIPTS(subs, __VA_ARGS__), &current->name)); \
291cabdff1aSopenharmony_ci    } while (0)
292cabdff1aSopenharmony_ci
293cabdff1aSopenharmony_ci#define delta_q(name) do { \
294cabdff1aSopenharmony_ci        uint8_t delta_coded; \
295cabdff1aSopenharmony_ci        int8_t delta_q; \
296cabdff1aSopenharmony_ci        xf(1, name.delta_coded, delta_coded, 0, ); \
297cabdff1aSopenharmony_ci        if (delta_coded) \
298cabdff1aSopenharmony_ci            xs(4, name.delta_q, delta_q, 0, ); \
299cabdff1aSopenharmony_ci        else \
300cabdff1aSopenharmony_ci            delta_q = 0; \
301cabdff1aSopenharmony_ci        current->name = delta_q; \
302cabdff1aSopenharmony_ci    } while (0)
303cabdff1aSopenharmony_ci
304cabdff1aSopenharmony_ci#define prob(name, subs, ...) do { \
305cabdff1aSopenharmony_ci        uint8_t prob_coded; \
306cabdff1aSopenharmony_ci        uint8_t prob; \
307cabdff1aSopenharmony_ci        xf(1, name.prob_coded, prob_coded, subs, __VA_ARGS__); \
308cabdff1aSopenharmony_ci        if (prob_coded) \
309cabdff1aSopenharmony_ci            xf(8, name.prob, prob, subs, __VA_ARGS__); \
310cabdff1aSopenharmony_ci        else \
311cabdff1aSopenharmony_ci            prob = 255; \
312cabdff1aSopenharmony_ci        current->name = prob; \
313cabdff1aSopenharmony_ci    } while (0)
314cabdff1aSopenharmony_ci
315cabdff1aSopenharmony_ci#define fixed(width, name, value) do { \
316cabdff1aSopenharmony_ci        av_unused uint32_t fixed_value; \
317cabdff1aSopenharmony_ci        CHECK(ff_cbs_read_unsigned(ctx, rw, width, #name, \
318cabdff1aSopenharmony_ci                                   0, &fixed_value, value, value)); \
319cabdff1aSopenharmony_ci    } while (0)
320cabdff1aSopenharmony_ci
321cabdff1aSopenharmony_ci#define infer(name, value) do { \
322cabdff1aSopenharmony_ci        current->name = value; \
323cabdff1aSopenharmony_ci    } while (0)
324cabdff1aSopenharmony_ci
325cabdff1aSopenharmony_ci#define byte_alignment(rw) (get_bits_count(rw) % 8)
326cabdff1aSopenharmony_ci
327cabdff1aSopenharmony_ci#include "cbs_vp9_syntax_template.c"
328cabdff1aSopenharmony_ci
329cabdff1aSopenharmony_ci#undef READ
330cabdff1aSopenharmony_ci#undef READWRITE
331cabdff1aSopenharmony_ci#undef RWContext
332cabdff1aSopenharmony_ci#undef xf
333cabdff1aSopenharmony_ci#undef xs
334cabdff1aSopenharmony_ci#undef increment
335cabdff1aSopenharmony_ci#undef fle
336cabdff1aSopenharmony_ci#undef delta_q
337cabdff1aSopenharmony_ci#undef prob
338cabdff1aSopenharmony_ci#undef fixed
339cabdff1aSopenharmony_ci#undef infer
340cabdff1aSopenharmony_ci#undef byte_alignment
341cabdff1aSopenharmony_ci
342cabdff1aSopenharmony_ci
343cabdff1aSopenharmony_ci#define WRITE
344cabdff1aSopenharmony_ci#define READWRITE write
345cabdff1aSopenharmony_ci#define RWContext PutBitContext
346cabdff1aSopenharmony_ci
347cabdff1aSopenharmony_ci#define xf(width, name, var, subs, ...) do { \
348cabdff1aSopenharmony_ci        CHECK(ff_cbs_write_unsigned(ctx, rw, width, #name, \
349cabdff1aSopenharmony_ci                                    SUBSCRIPTS(subs, __VA_ARGS__), \
350cabdff1aSopenharmony_ci                                    var, 0, (1 << width) - 1)); \
351cabdff1aSopenharmony_ci    } while (0)
352cabdff1aSopenharmony_ci#define xs(width, name, var, subs, ...) do { \
353cabdff1aSopenharmony_ci        CHECK(cbs_vp9_write_s(ctx, rw, width, #name, \
354cabdff1aSopenharmony_ci                              SUBSCRIPTS(subs, __VA_ARGS__), var)); \
355cabdff1aSopenharmony_ci    } while (0)
356cabdff1aSopenharmony_ci
357cabdff1aSopenharmony_ci#define increment(name, min, max) do { \
358cabdff1aSopenharmony_ci        CHECK(cbs_vp9_write_increment(ctx, rw, min, max, #name, current->name)); \
359cabdff1aSopenharmony_ci    } while (0)
360cabdff1aSopenharmony_ci
361cabdff1aSopenharmony_ci#define fle(width, name, subs, ...) do { \
362cabdff1aSopenharmony_ci        CHECK(cbs_vp9_write_le(ctx, rw, width, #name, \
363cabdff1aSopenharmony_ci                               SUBSCRIPTS(subs, __VA_ARGS__), current->name)); \
364cabdff1aSopenharmony_ci    } while (0)
365cabdff1aSopenharmony_ci
366cabdff1aSopenharmony_ci#define delta_q(name) do { \
367cabdff1aSopenharmony_ci        xf(1, name.delta_coded, !!current->name, 0, ); \
368cabdff1aSopenharmony_ci        if (current->name) \
369cabdff1aSopenharmony_ci            xs(4, name.delta_q, current->name, 0, ); \
370cabdff1aSopenharmony_ci    } while (0)
371cabdff1aSopenharmony_ci
372cabdff1aSopenharmony_ci#define prob(name, subs, ...) do { \
373cabdff1aSopenharmony_ci        xf(1, name.prob_coded, current->name != 255, subs, __VA_ARGS__); \
374cabdff1aSopenharmony_ci        if (current->name != 255) \
375cabdff1aSopenharmony_ci            xf(8, name.prob, current->name, subs, __VA_ARGS__); \
376cabdff1aSopenharmony_ci    } while (0)
377cabdff1aSopenharmony_ci
378cabdff1aSopenharmony_ci#define fixed(width, name, value) do { \
379cabdff1aSopenharmony_ci        CHECK(ff_cbs_write_unsigned(ctx, rw, width, #name, \
380cabdff1aSopenharmony_ci                                    0, value, value, value)); \
381cabdff1aSopenharmony_ci    } while (0)
382cabdff1aSopenharmony_ci
383cabdff1aSopenharmony_ci#define infer(name, value) do { \
384cabdff1aSopenharmony_ci        if (current->name != (value)) { \
385cabdff1aSopenharmony_ci            av_log(ctx->log_ctx, AV_LOG_WARNING, "Warning: " \
386cabdff1aSopenharmony_ci                   "%s does not match inferred value: " \
387cabdff1aSopenharmony_ci                   "%"PRId64", but should be %"PRId64".\n", \
388cabdff1aSopenharmony_ci                   #name, (int64_t)current->name, (int64_t)(value)); \
389cabdff1aSopenharmony_ci        } \
390cabdff1aSopenharmony_ci    } while (0)
391cabdff1aSopenharmony_ci
392cabdff1aSopenharmony_ci#define byte_alignment(rw) (put_bits_count(rw) % 8)
393cabdff1aSopenharmony_ci
394cabdff1aSopenharmony_ci#include "cbs_vp9_syntax_template.c"
395cabdff1aSopenharmony_ci
396cabdff1aSopenharmony_ci#undef WRITE
397cabdff1aSopenharmony_ci#undef READWRITE
398cabdff1aSopenharmony_ci#undef RWContext
399cabdff1aSopenharmony_ci#undef xf
400cabdff1aSopenharmony_ci#undef xs
401cabdff1aSopenharmony_ci#undef increment
402cabdff1aSopenharmony_ci#undef fle
403cabdff1aSopenharmony_ci#undef delta_q
404cabdff1aSopenharmony_ci#undef prob
405cabdff1aSopenharmony_ci#undef fixed
406cabdff1aSopenharmony_ci#undef infer
407cabdff1aSopenharmony_ci#undef byte_alignment
408cabdff1aSopenharmony_ci
409cabdff1aSopenharmony_ci
410cabdff1aSopenharmony_cistatic int cbs_vp9_split_fragment(CodedBitstreamContext *ctx,
411cabdff1aSopenharmony_ci                                  CodedBitstreamFragment *frag,
412cabdff1aSopenharmony_ci                                  int header)
413cabdff1aSopenharmony_ci{
414cabdff1aSopenharmony_ci    uint8_t superframe_header;
415cabdff1aSopenharmony_ci    int err;
416cabdff1aSopenharmony_ci
417cabdff1aSopenharmony_ci    if (frag->data_size == 0)
418cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
419cabdff1aSopenharmony_ci
420cabdff1aSopenharmony_ci    // Last byte in the packet.
421cabdff1aSopenharmony_ci    superframe_header = frag->data[frag->data_size - 1];
422cabdff1aSopenharmony_ci
423cabdff1aSopenharmony_ci    if ((superframe_header & 0xe0) == 0xc0) {
424cabdff1aSopenharmony_ci        VP9RawSuperframeIndex sfi;
425cabdff1aSopenharmony_ci        GetBitContext gbc;
426cabdff1aSopenharmony_ci        size_t index_size, pos;
427cabdff1aSopenharmony_ci        int i;
428cabdff1aSopenharmony_ci
429cabdff1aSopenharmony_ci        index_size = 2 + (((superframe_header & 0x18) >> 3) + 1) *
430cabdff1aSopenharmony_ci                          ((superframe_header & 0x07) + 1);
431cabdff1aSopenharmony_ci
432cabdff1aSopenharmony_ci        if (index_size > frag->data_size)
433cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
434cabdff1aSopenharmony_ci
435cabdff1aSopenharmony_ci        err = init_get_bits(&gbc, frag->data + frag->data_size - index_size,
436cabdff1aSopenharmony_ci                            8 * index_size);
437cabdff1aSopenharmony_ci        if (err < 0)
438cabdff1aSopenharmony_ci            return err;
439cabdff1aSopenharmony_ci
440cabdff1aSopenharmony_ci        err = cbs_vp9_read_superframe_index(ctx, &gbc, &sfi);
441cabdff1aSopenharmony_ci        if (err < 0)
442cabdff1aSopenharmony_ci            return err;
443cabdff1aSopenharmony_ci
444cabdff1aSopenharmony_ci        pos = 0;
445cabdff1aSopenharmony_ci        for (i = 0; i <= sfi.frames_in_superframe_minus_1; i++) {
446cabdff1aSopenharmony_ci            if (pos + sfi.frame_sizes[i] + index_size > frag->data_size) {
447cabdff1aSopenharmony_ci                av_log(ctx->log_ctx, AV_LOG_ERROR, "Frame %d too large "
448cabdff1aSopenharmony_ci                       "in superframe: %"PRIu32" bytes.\n",
449cabdff1aSopenharmony_ci                       i, sfi.frame_sizes[i]);
450cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
451cabdff1aSopenharmony_ci            }
452cabdff1aSopenharmony_ci
453cabdff1aSopenharmony_ci            err = ff_cbs_append_unit_data(frag, 0,
454cabdff1aSopenharmony_ci                                          frag->data + pos,
455cabdff1aSopenharmony_ci                                          sfi.frame_sizes[i],
456cabdff1aSopenharmony_ci                                          frag->data_ref);
457cabdff1aSopenharmony_ci            if (err < 0)
458cabdff1aSopenharmony_ci                return err;
459cabdff1aSopenharmony_ci
460cabdff1aSopenharmony_ci            pos += sfi.frame_sizes[i];
461cabdff1aSopenharmony_ci        }
462cabdff1aSopenharmony_ci        if (pos + index_size != frag->data_size) {
463cabdff1aSopenharmony_ci            av_log(ctx->log_ctx, AV_LOG_WARNING, "Extra padding at "
464cabdff1aSopenharmony_ci                   "end of superframe: %"SIZE_SPECIFIER" bytes.\n",
465cabdff1aSopenharmony_ci                   frag->data_size - (pos + index_size));
466cabdff1aSopenharmony_ci        }
467cabdff1aSopenharmony_ci
468cabdff1aSopenharmony_ci        return 0;
469cabdff1aSopenharmony_ci
470cabdff1aSopenharmony_ci    } else {
471cabdff1aSopenharmony_ci        err = ff_cbs_append_unit_data(frag, 0,
472cabdff1aSopenharmony_ci                                      frag->data, frag->data_size,
473cabdff1aSopenharmony_ci                                      frag->data_ref);
474cabdff1aSopenharmony_ci        if (err < 0)
475cabdff1aSopenharmony_ci            return err;
476cabdff1aSopenharmony_ci    }
477cabdff1aSopenharmony_ci
478cabdff1aSopenharmony_ci    return 0;
479cabdff1aSopenharmony_ci}
480cabdff1aSopenharmony_ci
481cabdff1aSopenharmony_cistatic int cbs_vp9_read_unit(CodedBitstreamContext *ctx,
482cabdff1aSopenharmony_ci                             CodedBitstreamUnit *unit)
483cabdff1aSopenharmony_ci{
484cabdff1aSopenharmony_ci    VP9RawFrame *frame;
485cabdff1aSopenharmony_ci    GetBitContext gbc;
486cabdff1aSopenharmony_ci    int err, pos;
487cabdff1aSopenharmony_ci
488cabdff1aSopenharmony_ci    err = init_get_bits(&gbc, unit->data, 8 * unit->data_size);
489cabdff1aSopenharmony_ci    if (err < 0)
490cabdff1aSopenharmony_ci        return err;
491cabdff1aSopenharmony_ci
492cabdff1aSopenharmony_ci    err = ff_cbs_alloc_unit_content2(ctx, unit);
493cabdff1aSopenharmony_ci    if (err < 0)
494cabdff1aSopenharmony_ci        return err;
495cabdff1aSopenharmony_ci    frame = unit->content;
496cabdff1aSopenharmony_ci
497cabdff1aSopenharmony_ci    err = cbs_vp9_read_frame(ctx, &gbc, frame);
498cabdff1aSopenharmony_ci    if (err < 0)
499cabdff1aSopenharmony_ci        return err;
500cabdff1aSopenharmony_ci
501cabdff1aSopenharmony_ci    pos = get_bits_count(&gbc);
502cabdff1aSopenharmony_ci    av_assert0(pos % 8 == 0);
503cabdff1aSopenharmony_ci    pos /= 8;
504cabdff1aSopenharmony_ci    av_assert0(pos <= unit->data_size);
505cabdff1aSopenharmony_ci
506cabdff1aSopenharmony_ci    if (pos == unit->data_size) {
507cabdff1aSopenharmony_ci        // No data (e.g. a show-existing-frame frame).
508cabdff1aSopenharmony_ci    } else {
509cabdff1aSopenharmony_ci        frame->data_ref = av_buffer_ref(unit->data_ref);
510cabdff1aSopenharmony_ci        if (!frame->data_ref)
511cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
512cabdff1aSopenharmony_ci
513cabdff1aSopenharmony_ci        frame->data      = unit->data      + pos;
514cabdff1aSopenharmony_ci        frame->data_size = unit->data_size - pos;
515cabdff1aSopenharmony_ci    }
516cabdff1aSopenharmony_ci
517cabdff1aSopenharmony_ci    return 0;
518cabdff1aSopenharmony_ci}
519cabdff1aSopenharmony_ci
520cabdff1aSopenharmony_cistatic int cbs_vp9_write_unit(CodedBitstreamContext *ctx,
521cabdff1aSopenharmony_ci                              CodedBitstreamUnit *unit,
522cabdff1aSopenharmony_ci                              PutBitContext *pbc)
523cabdff1aSopenharmony_ci{
524cabdff1aSopenharmony_ci    VP9RawFrame *frame = unit->content;
525cabdff1aSopenharmony_ci    int err;
526cabdff1aSopenharmony_ci
527cabdff1aSopenharmony_ci    err = cbs_vp9_write_frame(ctx, pbc, frame);
528cabdff1aSopenharmony_ci    if (err < 0)
529cabdff1aSopenharmony_ci        return err;
530cabdff1aSopenharmony_ci
531cabdff1aSopenharmony_ci    // Frame must be byte-aligned.
532cabdff1aSopenharmony_ci    av_assert0(put_bits_count(pbc) % 8 == 0);
533cabdff1aSopenharmony_ci
534cabdff1aSopenharmony_ci    if (frame->data) {
535cabdff1aSopenharmony_ci        if (frame->data_size > put_bits_left(pbc) / 8)
536cabdff1aSopenharmony_ci            return AVERROR(ENOSPC);
537cabdff1aSopenharmony_ci
538cabdff1aSopenharmony_ci        flush_put_bits(pbc);
539cabdff1aSopenharmony_ci        memcpy(put_bits_ptr(pbc), frame->data, frame->data_size);
540cabdff1aSopenharmony_ci        skip_put_bytes(pbc, frame->data_size);
541cabdff1aSopenharmony_ci    }
542cabdff1aSopenharmony_ci
543cabdff1aSopenharmony_ci    return 0;
544cabdff1aSopenharmony_ci}
545cabdff1aSopenharmony_ci
546cabdff1aSopenharmony_cistatic int cbs_vp9_assemble_fragment(CodedBitstreamContext *ctx,
547cabdff1aSopenharmony_ci                                     CodedBitstreamFragment *frag)
548cabdff1aSopenharmony_ci{
549cabdff1aSopenharmony_ci    int err;
550cabdff1aSopenharmony_ci
551cabdff1aSopenharmony_ci    if (frag->nb_units == 1) {
552cabdff1aSopenharmony_ci        // Output is just the content of the single frame.
553cabdff1aSopenharmony_ci
554cabdff1aSopenharmony_ci        CodedBitstreamUnit *frame = &frag->units[0];
555cabdff1aSopenharmony_ci
556cabdff1aSopenharmony_ci        frag->data_ref = av_buffer_ref(frame->data_ref);
557cabdff1aSopenharmony_ci        if (!frag->data_ref)
558cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
559cabdff1aSopenharmony_ci
560cabdff1aSopenharmony_ci        frag->data      = frame->data;
561cabdff1aSopenharmony_ci        frag->data_size = frame->data_size;
562cabdff1aSopenharmony_ci
563cabdff1aSopenharmony_ci    } else {
564cabdff1aSopenharmony_ci        // Build superframe out of frames.
565cabdff1aSopenharmony_ci
566cabdff1aSopenharmony_ci        VP9RawSuperframeIndex sfi;
567cabdff1aSopenharmony_ci        PutBitContext pbc;
568cabdff1aSopenharmony_ci        AVBufferRef *ref;
569cabdff1aSopenharmony_ci        uint8_t *data;
570cabdff1aSopenharmony_ci        size_t size, max, pos;
571cabdff1aSopenharmony_ci        int i, size_len;
572cabdff1aSopenharmony_ci
573cabdff1aSopenharmony_ci        if (frag->nb_units > 8) {
574cabdff1aSopenharmony_ci            av_log(ctx->log_ctx, AV_LOG_ERROR, "Too many frames to "
575cabdff1aSopenharmony_ci                   "make superframe: %d.\n", frag->nb_units);
576cabdff1aSopenharmony_ci            return AVERROR(EINVAL);
577cabdff1aSopenharmony_ci        }
578cabdff1aSopenharmony_ci
579cabdff1aSopenharmony_ci        max = 0;
580cabdff1aSopenharmony_ci        for (i = 0; i < frag->nb_units; i++)
581cabdff1aSopenharmony_ci            if (max < frag->units[i].data_size)
582cabdff1aSopenharmony_ci                max = frag->units[i].data_size;
583cabdff1aSopenharmony_ci
584cabdff1aSopenharmony_ci        if (max < 2)
585cabdff1aSopenharmony_ci            size_len = 1;
586cabdff1aSopenharmony_ci        else
587cabdff1aSopenharmony_ci            size_len = av_log2(max) / 8 + 1;
588cabdff1aSopenharmony_ci        av_assert0(size_len <= 4);
589cabdff1aSopenharmony_ci
590cabdff1aSopenharmony_ci        sfi.superframe_marker            = VP9_SUPERFRAME_MARKER;
591cabdff1aSopenharmony_ci        sfi.bytes_per_framesize_minus_1  = size_len - 1;
592cabdff1aSopenharmony_ci        sfi.frames_in_superframe_minus_1 = frag->nb_units - 1;
593cabdff1aSopenharmony_ci
594cabdff1aSopenharmony_ci        size = 2;
595cabdff1aSopenharmony_ci        for (i = 0; i < frag->nb_units; i++) {
596cabdff1aSopenharmony_ci            size += size_len + frag->units[i].data_size;
597cabdff1aSopenharmony_ci            sfi.frame_sizes[i] = frag->units[i].data_size;
598cabdff1aSopenharmony_ci        }
599cabdff1aSopenharmony_ci
600cabdff1aSopenharmony_ci        ref = av_buffer_alloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
601cabdff1aSopenharmony_ci        if (!ref)
602cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
603cabdff1aSopenharmony_ci        data = ref->data;
604cabdff1aSopenharmony_ci        memset(data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
605cabdff1aSopenharmony_ci
606cabdff1aSopenharmony_ci        pos = 0;
607cabdff1aSopenharmony_ci        for (i = 0; i < frag->nb_units; i++) {
608cabdff1aSopenharmony_ci            av_assert0(size - pos > frag->units[i].data_size);
609cabdff1aSopenharmony_ci            memcpy(data + pos, frag->units[i].data,
610cabdff1aSopenharmony_ci                   frag->units[i].data_size);
611cabdff1aSopenharmony_ci            pos += frag->units[i].data_size;
612cabdff1aSopenharmony_ci        }
613cabdff1aSopenharmony_ci        av_assert0(size - pos == 2 + frag->nb_units * size_len);
614cabdff1aSopenharmony_ci
615cabdff1aSopenharmony_ci        init_put_bits(&pbc, data + pos, size - pos);
616cabdff1aSopenharmony_ci
617cabdff1aSopenharmony_ci        err = cbs_vp9_write_superframe_index(ctx, &pbc, &sfi);
618cabdff1aSopenharmony_ci        if (err < 0) {
619cabdff1aSopenharmony_ci            av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to write "
620cabdff1aSopenharmony_ci                   "superframe index.\n");
621cabdff1aSopenharmony_ci            av_buffer_unref(&ref);
622cabdff1aSopenharmony_ci            return err;
623cabdff1aSopenharmony_ci        }
624cabdff1aSopenharmony_ci
625cabdff1aSopenharmony_ci        av_assert0(put_bits_left(&pbc) == 0);
626cabdff1aSopenharmony_ci        flush_put_bits(&pbc);
627cabdff1aSopenharmony_ci
628cabdff1aSopenharmony_ci        frag->data_ref  = ref;
629cabdff1aSopenharmony_ci        frag->data      = data;
630cabdff1aSopenharmony_ci        frag->data_size = size;
631cabdff1aSopenharmony_ci    }
632cabdff1aSopenharmony_ci
633cabdff1aSopenharmony_ci    return 0;
634cabdff1aSopenharmony_ci}
635cabdff1aSopenharmony_ci
636cabdff1aSopenharmony_cistatic void cbs_vp9_flush(CodedBitstreamContext *ctx)
637cabdff1aSopenharmony_ci{
638cabdff1aSopenharmony_ci    CodedBitstreamVP9Context *vp9 = ctx->priv_data;
639cabdff1aSopenharmony_ci
640cabdff1aSopenharmony_ci    memset(vp9->ref, 0, sizeof(vp9->ref));
641cabdff1aSopenharmony_ci}
642cabdff1aSopenharmony_ci
643cabdff1aSopenharmony_cistatic const CodedBitstreamUnitTypeDescriptor cbs_vp9_unit_types[] = {
644cabdff1aSopenharmony_ci    CBS_UNIT_TYPE_INTERNAL_REF(0, VP9RawFrame, data),
645cabdff1aSopenharmony_ci    CBS_UNIT_TYPE_END_OF_LIST
646cabdff1aSopenharmony_ci};
647cabdff1aSopenharmony_ci
648cabdff1aSopenharmony_ciconst CodedBitstreamType ff_cbs_type_vp9 = {
649cabdff1aSopenharmony_ci    .codec_id          = AV_CODEC_ID_VP9,
650cabdff1aSopenharmony_ci
651cabdff1aSopenharmony_ci    .priv_data_size    = sizeof(CodedBitstreamVP9Context),
652cabdff1aSopenharmony_ci
653cabdff1aSopenharmony_ci    .unit_types        = cbs_vp9_unit_types,
654cabdff1aSopenharmony_ci
655cabdff1aSopenharmony_ci    .split_fragment    = &cbs_vp9_split_fragment,
656cabdff1aSopenharmony_ci    .read_unit         = &cbs_vp9_read_unit,
657cabdff1aSopenharmony_ci    .write_unit        = &cbs_vp9_write_unit,
658cabdff1aSopenharmony_ci
659cabdff1aSopenharmony_ci    .flush             = &cbs_vp9_flush,
660cabdff1aSopenharmony_ci
661cabdff1aSopenharmony_ci    .assemble_fragment = &cbs_vp9_assemble_fragment,
662cabdff1aSopenharmony_ci};
663