1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * VP7/VP8 compatible video decoder
3cabdff1aSopenharmony_ci *
4cabdff1aSopenharmony_ci * Copyright (C) 2010 David Conrad
5cabdff1aSopenharmony_ci * Copyright (C) 2010 Ronald S. Bultje
6cabdff1aSopenharmony_ci * Copyright (C) 2010 Fiona Glaser
7cabdff1aSopenharmony_ci * Copyright (C) 2012 Daniel Kang
8cabdff1aSopenharmony_ci * Copyright (C) 2014 Peter Ross
9cabdff1aSopenharmony_ci *
10cabdff1aSopenharmony_ci * This file is part of FFmpeg.
11cabdff1aSopenharmony_ci *
12cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
13cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
14cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
15cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
16cabdff1aSopenharmony_ci *
17cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
18cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
19cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20cabdff1aSopenharmony_ci * Lesser General Public License for more details.
21cabdff1aSopenharmony_ci *
22cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
23cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
24cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25cabdff1aSopenharmony_ci */
26cabdff1aSopenharmony_ci
27cabdff1aSopenharmony_ci#include "config_components.h"
28cabdff1aSopenharmony_ci
29cabdff1aSopenharmony_ci#include "libavutil/imgutils.h"
30cabdff1aSopenharmony_ci#include "libavutil/mem_internal.h"
31cabdff1aSopenharmony_ci
32cabdff1aSopenharmony_ci#include "avcodec.h"
33cabdff1aSopenharmony_ci#include "codec_internal.h"
34cabdff1aSopenharmony_ci#include "hwconfig.h"
35cabdff1aSopenharmony_ci#include "internal.h"
36cabdff1aSopenharmony_ci#include "mathops.h"
37cabdff1aSopenharmony_ci#include "rectangle.h"
38cabdff1aSopenharmony_ci#include "thread.h"
39cabdff1aSopenharmony_ci#include "threadframe.h"
40cabdff1aSopenharmony_ci#include "vp8.h"
41cabdff1aSopenharmony_ci#include "vp8data.h"
42cabdff1aSopenharmony_ci
43cabdff1aSopenharmony_ci#if ARCH_ARM
44cabdff1aSopenharmony_ci#   include "arm/vp8.h"
45cabdff1aSopenharmony_ci#endif
46cabdff1aSopenharmony_ci
47cabdff1aSopenharmony_ci#if CONFIG_VP7_DECODER && CONFIG_VP8_DECODER
48cabdff1aSopenharmony_ci#define VPX(vp7, f) (vp7 ? vp7_ ## f : vp8_ ## f)
49cabdff1aSopenharmony_ci#elif CONFIG_VP7_DECODER
50cabdff1aSopenharmony_ci#define VPX(vp7, f) vp7_ ## f
51cabdff1aSopenharmony_ci#else // CONFIG_VP8_DECODER
52cabdff1aSopenharmony_ci#define VPX(vp7, f) vp8_ ## f
53cabdff1aSopenharmony_ci#endif
54cabdff1aSopenharmony_ci
55cabdff1aSopenharmony_cistatic void free_buffers(VP8Context *s)
56cabdff1aSopenharmony_ci{
57cabdff1aSopenharmony_ci    int i;
58cabdff1aSopenharmony_ci    if (s->thread_data)
59cabdff1aSopenharmony_ci        for (i = 0; i < MAX_THREADS; i++) {
60cabdff1aSopenharmony_ci#if HAVE_THREADS
61cabdff1aSopenharmony_ci            pthread_cond_destroy(&s->thread_data[i].cond);
62cabdff1aSopenharmony_ci            pthread_mutex_destroy(&s->thread_data[i].lock);
63cabdff1aSopenharmony_ci#endif
64cabdff1aSopenharmony_ci            av_freep(&s->thread_data[i].filter_strength);
65cabdff1aSopenharmony_ci        }
66cabdff1aSopenharmony_ci    av_freep(&s->thread_data);
67cabdff1aSopenharmony_ci    av_freep(&s->macroblocks_base);
68cabdff1aSopenharmony_ci    av_freep(&s->intra4x4_pred_mode_top);
69cabdff1aSopenharmony_ci    av_freep(&s->top_nnz);
70cabdff1aSopenharmony_ci    av_freep(&s->top_border);
71cabdff1aSopenharmony_ci
72cabdff1aSopenharmony_ci    s->macroblocks = NULL;
73cabdff1aSopenharmony_ci}
74cabdff1aSopenharmony_ci
75cabdff1aSopenharmony_cistatic int vp8_alloc_frame(VP8Context *s, VP8Frame *f, int ref)
76cabdff1aSopenharmony_ci{
77cabdff1aSopenharmony_ci    int ret;
78cabdff1aSopenharmony_ci    if ((ret = ff_thread_get_ext_buffer(s->avctx, &f->tf,
79cabdff1aSopenharmony_ci                                        ref ? AV_GET_BUFFER_FLAG_REF : 0)) < 0)
80cabdff1aSopenharmony_ci        return ret;
81cabdff1aSopenharmony_ci    if (!(f->seg_map = av_buffer_allocz(s->mb_width * s->mb_height)))
82cabdff1aSopenharmony_ci        goto fail;
83cabdff1aSopenharmony_ci    if (s->avctx->hwaccel) {
84cabdff1aSopenharmony_ci        const AVHWAccel *hwaccel = s->avctx->hwaccel;
85cabdff1aSopenharmony_ci        if (hwaccel->frame_priv_data_size) {
86cabdff1aSopenharmony_ci            f->hwaccel_priv_buf = av_buffer_allocz(hwaccel->frame_priv_data_size);
87cabdff1aSopenharmony_ci            if (!f->hwaccel_priv_buf)
88cabdff1aSopenharmony_ci                goto fail;
89cabdff1aSopenharmony_ci            f->hwaccel_picture_private = f->hwaccel_priv_buf->data;
90cabdff1aSopenharmony_ci        }
91cabdff1aSopenharmony_ci    }
92cabdff1aSopenharmony_ci    return 0;
93cabdff1aSopenharmony_ci
94cabdff1aSopenharmony_cifail:
95cabdff1aSopenharmony_ci    av_buffer_unref(&f->seg_map);
96cabdff1aSopenharmony_ci    ff_thread_release_ext_buffer(s->avctx, &f->tf);
97cabdff1aSopenharmony_ci    return AVERROR(ENOMEM);
98cabdff1aSopenharmony_ci}
99cabdff1aSopenharmony_ci
100cabdff1aSopenharmony_cistatic void vp8_release_frame(VP8Context *s, VP8Frame *f)
101cabdff1aSopenharmony_ci{
102cabdff1aSopenharmony_ci    av_buffer_unref(&f->seg_map);
103cabdff1aSopenharmony_ci    av_buffer_unref(&f->hwaccel_priv_buf);
104cabdff1aSopenharmony_ci    f->hwaccel_picture_private = NULL;
105cabdff1aSopenharmony_ci    ff_thread_release_ext_buffer(s->avctx, &f->tf);
106cabdff1aSopenharmony_ci}
107cabdff1aSopenharmony_ci
108cabdff1aSopenharmony_ci#if CONFIG_VP8_DECODER
109cabdff1aSopenharmony_cistatic int vp8_ref_frame(VP8Context *s, VP8Frame *dst, VP8Frame *src)
110cabdff1aSopenharmony_ci{
111cabdff1aSopenharmony_ci    int ret;
112cabdff1aSopenharmony_ci
113cabdff1aSopenharmony_ci    vp8_release_frame(s, dst);
114cabdff1aSopenharmony_ci
115cabdff1aSopenharmony_ci    if ((ret = ff_thread_ref_frame(&dst->tf, &src->tf)) < 0)
116cabdff1aSopenharmony_ci        return ret;
117cabdff1aSopenharmony_ci    if (src->seg_map &&
118cabdff1aSopenharmony_ci        !(dst->seg_map = av_buffer_ref(src->seg_map))) {
119cabdff1aSopenharmony_ci        vp8_release_frame(s, dst);
120cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
121cabdff1aSopenharmony_ci    }
122cabdff1aSopenharmony_ci    if (src->hwaccel_picture_private) {
123cabdff1aSopenharmony_ci        dst->hwaccel_priv_buf = av_buffer_ref(src->hwaccel_priv_buf);
124cabdff1aSopenharmony_ci        if (!dst->hwaccel_priv_buf)
125cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
126cabdff1aSopenharmony_ci        dst->hwaccel_picture_private = dst->hwaccel_priv_buf->data;
127cabdff1aSopenharmony_ci    }
128cabdff1aSopenharmony_ci
129cabdff1aSopenharmony_ci    return 0;
130cabdff1aSopenharmony_ci}
131cabdff1aSopenharmony_ci#endif /* CONFIG_VP8_DECODER */
132cabdff1aSopenharmony_ci
133cabdff1aSopenharmony_cistatic void vp8_decode_flush_impl(AVCodecContext *avctx, int free_mem)
134cabdff1aSopenharmony_ci{
135cabdff1aSopenharmony_ci    VP8Context *s = avctx->priv_data;
136cabdff1aSopenharmony_ci    int i;
137cabdff1aSopenharmony_ci
138cabdff1aSopenharmony_ci    for (i = 0; i < FF_ARRAY_ELEMS(s->frames); i++)
139cabdff1aSopenharmony_ci        vp8_release_frame(s, &s->frames[i]);
140cabdff1aSopenharmony_ci    memset(s->framep, 0, sizeof(s->framep));
141cabdff1aSopenharmony_ci
142cabdff1aSopenharmony_ci    if (free_mem)
143cabdff1aSopenharmony_ci        free_buffers(s);
144cabdff1aSopenharmony_ci}
145cabdff1aSopenharmony_ci
146cabdff1aSopenharmony_cistatic void vp8_decode_flush(AVCodecContext *avctx)
147cabdff1aSopenharmony_ci{
148cabdff1aSopenharmony_ci    vp8_decode_flush_impl(avctx, 0);
149cabdff1aSopenharmony_ci}
150cabdff1aSopenharmony_ci
151cabdff1aSopenharmony_cistatic VP8Frame *vp8_find_free_buffer(VP8Context *s)
152cabdff1aSopenharmony_ci{
153cabdff1aSopenharmony_ci    VP8Frame *frame = NULL;
154cabdff1aSopenharmony_ci    int i;
155cabdff1aSopenharmony_ci
156cabdff1aSopenharmony_ci    // find a free buffer
157cabdff1aSopenharmony_ci    for (i = 0; i < 5; i++)
158cabdff1aSopenharmony_ci        if (&s->frames[i] != s->framep[VP56_FRAME_CURRENT]  &&
159cabdff1aSopenharmony_ci            &s->frames[i] != s->framep[VP56_FRAME_PREVIOUS] &&
160cabdff1aSopenharmony_ci            &s->frames[i] != s->framep[VP56_FRAME_GOLDEN]   &&
161cabdff1aSopenharmony_ci            &s->frames[i] != s->framep[VP56_FRAME_GOLDEN2]) {
162cabdff1aSopenharmony_ci            frame = &s->frames[i];
163cabdff1aSopenharmony_ci            break;
164cabdff1aSopenharmony_ci        }
165cabdff1aSopenharmony_ci    if (i == 5) {
166cabdff1aSopenharmony_ci        av_log(s->avctx, AV_LOG_FATAL, "Ran out of free frames!\n");
167cabdff1aSopenharmony_ci        abort();
168cabdff1aSopenharmony_ci    }
169cabdff1aSopenharmony_ci    if (frame->tf.f->buf[0])
170cabdff1aSopenharmony_ci        vp8_release_frame(s, frame);
171cabdff1aSopenharmony_ci
172cabdff1aSopenharmony_ci    return frame;
173cabdff1aSopenharmony_ci}
174cabdff1aSopenharmony_ci
175cabdff1aSopenharmony_cistatic enum AVPixelFormat get_pixel_format(VP8Context *s)
176cabdff1aSopenharmony_ci{
177cabdff1aSopenharmony_ci    enum AVPixelFormat pix_fmts[] = {
178cabdff1aSopenharmony_ci#if CONFIG_VP8_VAAPI_HWACCEL
179cabdff1aSopenharmony_ci        AV_PIX_FMT_VAAPI,
180cabdff1aSopenharmony_ci#endif
181cabdff1aSopenharmony_ci#if CONFIG_VP8_NVDEC_HWACCEL
182cabdff1aSopenharmony_ci        AV_PIX_FMT_CUDA,
183cabdff1aSopenharmony_ci#endif
184cabdff1aSopenharmony_ci        AV_PIX_FMT_YUV420P,
185cabdff1aSopenharmony_ci        AV_PIX_FMT_NONE,
186cabdff1aSopenharmony_ci    };
187cabdff1aSopenharmony_ci
188cabdff1aSopenharmony_ci    return ff_get_format(s->avctx, pix_fmts);
189cabdff1aSopenharmony_ci}
190cabdff1aSopenharmony_ci
191cabdff1aSopenharmony_cistatic av_always_inline
192cabdff1aSopenharmony_ciint update_dimensions(VP8Context *s, int width, int height, int is_vp7)
193cabdff1aSopenharmony_ci{
194cabdff1aSopenharmony_ci    AVCodecContext *avctx = s->avctx;
195cabdff1aSopenharmony_ci    int i, ret, dim_reset = 0;
196cabdff1aSopenharmony_ci
197cabdff1aSopenharmony_ci    if (width  != s->avctx->width || ((width+15)/16 != s->mb_width || (height+15)/16 != s->mb_height) && s->macroblocks_base ||
198cabdff1aSopenharmony_ci        height != s->avctx->height) {
199cabdff1aSopenharmony_ci        vp8_decode_flush_impl(s->avctx, 1);
200cabdff1aSopenharmony_ci
201cabdff1aSopenharmony_ci        ret = ff_set_dimensions(s->avctx, width, height);
202cabdff1aSopenharmony_ci        if (ret < 0)
203cabdff1aSopenharmony_ci            return ret;
204cabdff1aSopenharmony_ci
205cabdff1aSopenharmony_ci        dim_reset = (s->macroblocks_base != NULL);
206cabdff1aSopenharmony_ci    }
207cabdff1aSopenharmony_ci
208cabdff1aSopenharmony_ci    if ((s->pix_fmt == AV_PIX_FMT_NONE || dim_reset) &&
209cabdff1aSopenharmony_ci         !s->actually_webp && !is_vp7) {
210cabdff1aSopenharmony_ci        s->pix_fmt = get_pixel_format(s);
211cabdff1aSopenharmony_ci        if (s->pix_fmt < 0)
212cabdff1aSopenharmony_ci            return AVERROR(EINVAL);
213cabdff1aSopenharmony_ci        avctx->pix_fmt = s->pix_fmt;
214cabdff1aSopenharmony_ci    }
215cabdff1aSopenharmony_ci
216cabdff1aSopenharmony_ci    s->mb_width  = (s->avctx->coded_width  + 15) / 16;
217cabdff1aSopenharmony_ci    s->mb_height = (s->avctx->coded_height + 15) / 16;
218cabdff1aSopenharmony_ci
219cabdff1aSopenharmony_ci    s->mb_layout = is_vp7 || avctx->active_thread_type == FF_THREAD_SLICE &&
220cabdff1aSopenharmony_ci                   avctx->thread_count > 1;
221cabdff1aSopenharmony_ci    if (!s->mb_layout) { // Frame threading and one thread
222cabdff1aSopenharmony_ci        s->macroblocks_base       = av_mallocz((s->mb_width + s->mb_height * 2 + 1) *
223cabdff1aSopenharmony_ci                                               sizeof(*s->macroblocks));
224cabdff1aSopenharmony_ci        s->intra4x4_pred_mode_top = av_mallocz(s->mb_width * 4);
225cabdff1aSopenharmony_ci    } else // Sliced threading
226cabdff1aSopenharmony_ci        s->macroblocks_base = av_mallocz((s->mb_width + 2) * (s->mb_height + 2) *
227cabdff1aSopenharmony_ci                                         sizeof(*s->macroblocks));
228cabdff1aSopenharmony_ci    s->top_nnz     = av_mallocz(s->mb_width * sizeof(*s->top_nnz));
229cabdff1aSopenharmony_ci    s->top_border  = av_mallocz((s->mb_width + 1) * sizeof(*s->top_border));
230cabdff1aSopenharmony_ci    s->thread_data = av_mallocz(MAX_THREADS * sizeof(VP8ThreadData));
231cabdff1aSopenharmony_ci
232cabdff1aSopenharmony_ci    if (!s->macroblocks_base || !s->top_nnz || !s->top_border ||
233cabdff1aSopenharmony_ci        !s->thread_data || (!s->intra4x4_pred_mode_top && !s->mb_layout)) {
234cabdff1aSopenharmony_ci        free_buffers(s);
235cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
236cabdff1aSopenharmony_ci    }
237cabdff1aSopenharmony_ci
238cabdff1aSopenharmony_ci    for (i = 0; i < MAX_THREADS; i++) {
239cabdff1aSopenharmony_ci        s->thread_data[i].filter_strength =
240cabdff1aSopenharmony_ci            av_mallocz(s->mb_width * sizeof(*s->thread_data[0].filter_strength));
241cabdff1aSopenharmony_ci        if (!s->thread_data[i].filter_strength) {
242cabdff1aSopenharmony_ci            free_buffers(s);
243cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
244cabdff1aSopenharmony_ci        }
245cabdff1aSopenharmony_ci#if HAVE_THREADS
246cabdff1aSopenharmony_ci        pthread_mutex_init(&s->thread_data[i].lock, NULL);
247cabdff1aSopenharmony_ci        pthread_cond_init(&s->thread_data[i].cond, NULL);
248cabdff1aSopenharmony_ci#endif
249cabdff1aSopenharmony_ci    }
250cabdff1aSopenharmony_ci
251cabdff1aSopenharmony_ci    s->macroblocks = s->macroblocks_base + 1;
252cabdff1aSopenharmony_ci
253cabdff1aSopenharmony_ci    return 0;
254cabdff1aSopenharmony_ci}
255cabdff1aSopenharmony_ci
256cabdff1aSopenharmony_cistatic int vp7_update_dimensions(VP8Context *s, int width, int height)
257cabdff1aSopenharmony_ci{
258cabdff1aSopenharmony_ci    return update_dimensions(s, width, height, IS_VP7);
259cabdff1aSopenharmony_ci}
260cabdff1aSopenharmony_ci
261cabdff1aSopenharmony_cistatic int vp8_update_dimensions(VP8Context *s, int width, int height)
262cabdff1aSopenharmony_ci{
263cabdff1aSopenharmony_ci    return update_dimensions(s, width, height, IS_VP8);
264cabdff1aSopenharmony_ci}
265cabdff1aSopenharmony_ci
266cabdff1aSopenharmony_ci
267cabdff1aSopenharmony_cistatic void parse_segment_info(VP8Context *s)
268cabdff1aSopenharmony_ci{
269cabdff1aSopenharmony_ci    VP56RangeCoder *c = &s->c;
270cabdff1aSopenharmony_ci    int i;
271cabdff1aSopenharmony_ci
272cabdff1aSopenharmony_ci    s->segmentation.update_map = vp8_rac_get(c);
273cabdff1aSopenharmony_ci    s->segmentation.update_feature_data = vp8_rac_get(c);
274cabdff1aSopenharmony_ci
275cabdff1aSopenharmony_ci    if (s->segmentation.update_feature_data) {
276cabdff1aSopenharmony_ci        s->segmentation.absolute_vals = vp8_rac_get(c);
277cabdff1aSopenharmony_ci
278cabdff1aSopenharmony_ci        for (i = 0; i < 4; i++)
279cabdff1aSopenharmony_ci            s->segmentation.base_quant[i]   = vp8_rac_get_sint(c, 7);
280cabdff1aSopenharmony_ci
281cabdff1aSopenharmony_ci        for (i = 0; i < 4; i++)
282cabdff1aSopenharmony_ci            s->segmentation.filter_level[i] = vp8_rac_get_sint(c, 6);
283cabdff1aSopenharmony_ci    }
284cabdff1aSopenharmony_ci    if (s->segmentation.update_map)
285cabdff1aSopenharmony_ci        for (i = 0; i < 3; i++)
286cabdff1aSopenharmony_ci            s->prob->segmentid[i] = vp8_rac_get(c) ? vp8_rac_get_uint(c, 8) : 255;
287cabdff1aSopenharmony_ci}
288cabdff1aSopenharmony_ci
289cabdff1aSopenharmony_cistatic void update_lf_deltas(VP8Context *s)
290cabdff1aSopenharmony_ci{
291cabdff1aSopenharmony_ci    VP56RangeCoder *c = &s->c;
292cabdff1aSopenharmony_ci    int i;
293cabdff1aSopenharmony_ci
294cabdff1aSopenharmony_ci    for (i = 0; i < 4; i++) {
295cabdff1aSopenharmony_ci        if (vp8_rac_get(c)) {
296cabdff1aSopenharmony_ci            s->lf_delta.ref[i] = vp8_rac_get_uint(c, 6);
297cabdff1aSopenharmony_ci
298cabdff1aSopenharmony_ci            if (vp8_rac_get(c))
299cabdff1aSopenharmony_ci                s->lf_delta.ref[i] = -s->lf_delta.ref[i];
300cabdff1aSopenharmony_ci        }
301cabdff1aSopenharmony_ci    }
302cabdff1aSopenharmony_ci
303cabdff1aSopenharmony_ci    for (i = MODE_I4x4; i <= VP8_MVMODE_SPLIT; i++) {
304cabdff1aSopenharmony_ci        if (vp8_rac_get(c)) {
305cabdff1aSopenharmony_ci            s->lf_delta.mode[i] = vp8_rac_get_uint(c, 6);
306cabdff1aSopenharmony_ci
307cabdff1aSopenharmony_ci            if (vp8_rac_get(c))
308cabdff1aSopenharmony_ci                s->lf_delta.mode[i] = -s->lf_delta.mode[i];
309cabdff1aSopenharmony_ci        }
310cabdff1aSopenharmony_ci    }
311cabdff1aSopenharmony_ci}
312cabdff1aSopenharmony_ci
313cabdff1aSopenharmony_cistatic int setup_partitions(VP8Context *s, const uint8_t *buf, int buf_size)
314cabdff1aSopenharmony_ci{
315cabdff1aSopenharmony_ci    const uint8_t *sizes = buf;
316cabdff1aSopenharmony_ci    int i;
317cabdff1aSopenharmony_ci    int ret;
318cabdff1aSopenharmony_ci
319cabdff1aSopenharmony_ci    s->num_coeff_partitions = 1 << vp8_rac_get_uint(&s->c, 2);
320cabdff1aSopenharmony_ci
321cabdff1aSopenharmony_ci    buf      += 3 * (s->num_coeff_partitions - 1);
322cabdff1aSopenharmony_ci    buf_size -= 3 * (s->num_coeff_partitions - 1);
323cabdff1aSopenharmony_ci    if (buf_size < 0)
324cabdff1aSopenharmony_ci        return -1;
325cabdff1aSopenharmony_ci
326cabdff1aSopenharmony_ci    for (i = 0; i < s->num_coeff_partitions - 1; i++) {
327cabdff1aSopenharmony_ci        int size = AV_RL24(sizes + 3 * i);
328cabdff1aSopenharmony_ci        if (buf_size - size < 0)
329cabdff1aSopenharmony_ci            return -1;
330cabdff1aSopenharmony_ci        s->coeff_partition_size[i] = size;
331cabdff1aSopenharmony_ci
332cabdff1aSopenharmony_ci        ret = ff_vp56_init_range_decoder(&s->coeff_partition[i], buf, size);
333cabdff1aSopenharmony_ci        if (ret < 0)
334cabdff1aSopenharmony_ci            return ret;
335cabdff1aSopenharmony_ci        buf      += size;
336cabdff1aSopenharmony_ci        buf_size -= size;
337cabdff1aSopenharmony_ci    }
338cabdff1aSopenharmony_ci
339cabdff1aSopenharmony_ci    s->coeff_partition_size[i] = buf_size;
340cabdff1aSopenharmony_ci    ff_vp56_init_range_decoder(&s->coeff_partition[i], buf, buf_size);
341cabdff1aSopenharmony_ci
342cabdff1aSopenharmony_ci    return 0;
343cabdff1aSopenharmony_ci}
344cabdff1aSopenharmony_ci
345cabdff1aSopenharmony_cistatic void vp7_get_quants(VP8Context *s)
346cabdff1aSopenharmony_ci{
347cabdff1aSopenharmony_ci    VP56RangeCoder *c = &s->c;
348cabdff1aSopenharmony_ci
349cabdff1aSopenharmony_ci    int yac_qi  = vp8_rac_get_uint(c, 7);
350cabdff1aSopenharmony_ci    int ydc_qi  = vp8_rac_get(c) ? vp8_rac_get_uint(c, 7) : yac_qi;
351cabdff1aSopenharmony_ci    int y2dc_qi = vp8_rac_get(c) ? vp8_rac_get_uint(c, 7) : yac_qi;
352cabdff1aSopenharmony_ci    int y2ac_qi = vp8_rac_get(c) ? vp8_rac_get_uint(c, 7) : yac_qi;
353cabdff1aSopenharmony_ci    int uvdc_qi = vp8_rac_get(c) ? vp8_rac_get_uint(c, 7) : yac_qi;
354cabdff1aSopenharmony_ci    int uvac_qi = vp8_rac_get(c) ? vp8_rac_get_uint(c, 7) : yac_qi;
355cabdff1aSopenharmony_ci
356cabdff1aSopenharmony_ci    s->qmat[0].luma_qmul[0]    =       vp7_ydc_qlookup[ydc_qi];
357cabdff1aSopenharmony_ci    s->qmat[0].luma_qmul[1]    =       vp7_yac_qlookup[yac_qi];
358cabdff1aSopenharmony_ci    s->qmat[0].luma_dc_qmul[0] =       vp7_y2dc_qlookup[y2dc_qi];
359cabdff1aSopenharmony_ci    s->qmat[0].luma_dc_qmul[1] =       vp7_y2ac_qlookup[y2ac_qi];
360cabdff1aSopenharmony_ci    s->qmat[0].chroma_qmul[0]  = FFMIN(vp7_ydc_qlookup[uvdc_qi], 132);
361cabdff1aSopenharmony_ci    s->qmat[0].chroma_qmul[1]  =       vp7_yac_qlookup[uvac_qi];
362cabdff1aSopenharmony_ci}
363cabdff1aSopenharmony_ci
364cabdff1aSopenharmony_cistatic void vp8_get_quants(VP8Context *s)
365cabdff1aSopenharmony_ci{
366cabdff1aSopenharmony_ci    VP56RangeCoder *c = &s->c;
367cabdff1aSopenharmony_ci    int i, base_qi;
368cabdff1aSopenharmony_ci
369cabdff1aSopenharmony_ci    s->quant.yac_qi     = vp8_rac_get_uint(c, 7);
370cabdff1aSopenharmony_ci    s->quant.ydc_delta  = vp8_rac_get_sint(c, 4);
371cabdff1aSopenharmony_ci    s->quant.y2dc_delta = vp8_rac_get_sint(c, 4);
372cabdff1aSopenharmony_ci    s->quant.y2ac_delta = vp8_rac_get_sint(c, 4);
373cabdff1aSopenharmony_ci    s->quant.uvdc_delta = vp8_rac_get_sint(c, 4);
374cabdff1aSopenharmony_ci    s->quant.uvac_delta = vp8_rac_get_sint(c, 4);
375cabdff1aSopenharmony_ci
376cabdff1aSopenharmony_ci    for (i = 0; i < 4; i++) {
377cabdff1aSopenharmony_ci        if (s->segmentation.enabled) {
378cabdff1aSopenharmony_ci            base_qi = s->segmentation.base_quant[i];
379cabdff1aSopenharmony_ci            if (!s->segmentation.absolute_vals)
380cabdff1aSopenharmony_ci                base_qi += s->quant.yac_qi;
381cabdff1aSopenharmony_ci        } else
382cabdff1aSopenharmony_ci            base_qi = s->quant.yac_qi;
383cabdff1aSopenharmony_ci
384cabdff1aSopenharmony_ci        s->qmat[i].luma_qmul[0]    = vp8_dc_qlookup[av_clip_uintp2(base_qi + s->quant.ydc_delta,  7)];
385cabdff1aSopenharmony_ci        s->qmat[i].luma_qmul[1]    = vp8_ac_qlookup[av_clip_uintp2(base_qi,              7)];
386cabdff1aSopenharmony_ci        s->qmat[i].luma_dc_qmul[0] = vp8_dc_qlookup[av_clip_uintp2(base_qi + s->quant.y2dc_delta, 7)] * 2;
387cabdff1aSopenharmony_ci        /* 101581>>16 is equivalent to 155/100 */
388cabdff1aSopenharmony_ci        s->qmat[i].luma_dc_qmul[1] = vp8_ac_qlookup[av_clip_uintp2(base_qi + s->quant.y2ac_delta, 7)] * 101581 >> 16;
389cabdff1aSopenharmony_ci        s->qmat[i].chroma_qmul[0]  = vp8_dc_qlookup[av_clip_uintp2(base_qi + s->quant.uvdc_delta, 7)];
390cabdff1aSopenharmony_ci        s->qmat[i].chroma_qmul[1]  = vp8_ac_qlookup[av_clip_uintp2(base_qi + s->quant.uvac_delta, 7)];
391cabdff1aSopenharmony_ci
392cabdff1aSopenharmony_ci        s->qmat[i].luma_dc_qmul[1] = FFMAX(s->qmat[i].luma_dc_qmul[1], 8);
393cabdff1aSopenharmony_ci        s->qmat[i].chroma_qmul[0]  = FFMIN(s->qmat[i].chroma_qmul[0], 132);
394cabdff1aSopenharmony_ci    }
395cabdff1aSopenharmony_ci}
396cabdff1aSopenharmony_ci
397cabdff1aSopenharmony_ci/**
398cabdff1aSopenharmony_ci * Determine which buffers golden and altref should be updated with after this frame.
399cabdff1aSopenharmony_ci * The spec isn't clear here, so I'm going by my understanding of what libvpx does
400cabdff1aSopenharmony_ci *
401cabdff1aSopenharmony_ci * Intra frames update all 3 references
402cabdff1aSopenharmony_ci * Inter frames update VP56_FRAME_PREVIOUS if the update_last flag is set
403cabdff1aSopenharmony_ci * If the update (golden|altref) flag is set, it's updated with the current frame
404cabdff1aSopenharmony_ci *      if update_last is set, and VP56_FRAME_PREVIOUS otherwise.
405cabdff1aSopenharmony_ci * If the flag is not set, the number read means:
406cabdff1aSopenharmony_ci *      0: no update
407cabdff1aSopenharmony_ci *      1: VP56_FRAME_PREVIOUS
408cabdff1aSopenharmony_ci *      2: update golden with altref, or update altref with golden
409cabdff1aSopenharmony_ci */
410cabdff1aSopenharmony_cistatic VP56Frame ref_to_update(VP8Context *s, int update, VP56Frame ref)
411cabdff1aSopenharmony_ci{
412cabdff1aSopenharmony_ci    VP56RangeCoder *c = &s->c;
413cabdff1aSopenharmony_ci
414cabdff1aSopenharmony_ci    if (update)
415cabdff1aSopenharmony_ci        return VP56_FRAME_CURRENT;
416cabdff1aSopenharmony_ci
417cabdff1aSopenharmony_ci    switch (vp8_rac_get_uint(c, 2)) {
418cabdff1aSopenharmony_ci    case 1:
419cabdff1aSopenharmony_ci        return VP56_FRAME_PREVIOUS;
420cabdff1aSopenharmony_ci    case 2:
421cabdff1aSopenharmony_ci        return (ref == VP56_FRAME_GOLDEN) ? VP56_FRAME_GOLDEN2 : VP56_FRAME_GOLDEN;
422cabdff1aSopenharmony_ci    }
423cabdff1aSopenharmony_ci    return VP56_FRAME_NONE;
424cabdff1aSopenharmony_ci}
425cabdff1aSopenharmony_ci
426cabdff1aSopenharmony_cistatic void vp78_reset_probability_tables(VP8Context *s)
427cabdff1aSopenharmony_ci{
428cabdff1aSopenharmony_ci    int i, j;
429cabdff1aSopenharmony_ci    for (i = 0; i < 4; i++)
430cabdff1aSopenharmony_ci        for (j = 0; j < 16; j++)
431cabdff1aSopenharmony_ci            memcpy(s->prob->token[i][j], vp8_token_default_probs[i][vp8_coeff_band[j]],
432cabdff1aSopenharmony_ci                   sizeof(s->prob->token[i][j]));
433cabdff1aSopenharmony_ci}
434cabdff1aSopenharmony_ci
435cabdff1aSopenharmony_cistatic void vp78_update_probability_tables(VP8Context *s)
436cabdff1aSopenharmony_ci{
437cabdff1aSopenharmony_ci    VP56RangeCoder *c = &s->c;
438cabdff1aSopenharmony_ci    int i, j, k, l, m;
439cabdff1aSopenharmony_ci
440cabdff1aSopenharmony_ci    for (i = 0; i < 4; i++)
441cabdff1aSopenharmony_ci        for (j = 0; j < 8; j++)
442cabdff1aSopenharmony_ci            for (k = 0; k < 3; k++)
443cabdff1aSopenharmony_ci                for (l = 0; l < NUM_DCT_TOKENS-1; l++)
444cabdff1aSopenharmony_ci                    if (vp56_rac_get_prob_branchy(c, vp8_token_update_probs[i][j][k][l])) {
445cabdff1aSopenharmony_ci                        int prob = vp8_rac_get_uint(c, 8);
446cabdff1aSopenharmony_ci                        for (m = 0; vp8_coeff_band_indexes[j][m] >= 0; m++)
447cabdff1aSopenharmony_ci                            s->prob->token[i][vp8_coeff_band_indexes[j][m]][k][l] = prob;
448cabdff1aSopenharmony_ci                    }
449cabdff1aSopenharmony_ci}
450cabdff1aSopenharmony_ci
451cabdff1aSopenharmony_ci#define VP7_MVC_SIZE 17
452cabdff1aSopenharmony_ci#define VP8_MVC_SIZE 19
453cabdff1aSopenharmony_ci
454cabdff1aSopenharmony_cistatic void vp78_update_pred16x16_pred8x8_mvc_probabilities(VP8Context *s,
455cabdff1aSopenharmony_ci                                                            int mvc_size)
456cabdff1aSopenharmony_ci{
457cabdff1aSopenharmony_ci    VP56RangeCoder *c = &s->c;
458cabdff1aSopenharmony_ci    int i, j;
459cabdff1aSopenharmony_ci
460cabdff1aSopenharmony_ci    if (vp8_rac_get(c))
461cabdff1aSopenharmony_ci        for (i = 0; i < 4; i++)
462cabdff1aSopenharmony_ci            s->prob->pred16x16[i] = vp8_rac_get_uint(c, 8);
463cabdff1aSopenharmony_ci    if (vp8_rac_get(c))
464cabdff1aSopenharmony_ci        for (i = 0; i < 3; i++)
465cabdff1aSopenharmony_ci            s->prob->pred8x8c[i]  = vp8_rac_get_uint(c, 8);
466cabdff1aSopenharmony_ci
467cabdff1aSopenharmony_ci    // 17.2 MV probability update
468cabdff1aSopenharmony_ci    for (i = 0; i < 2; i++)
469cabdff1aSopenharmony_ci        for (j = 0; j < mvc_size; j++)
470cabdff1aSopenharmony_ci            if (vp56_rac_get_prob_branchy(c, vp8_mv_update_prob[i][j]))
471cabdff1aSopenharmony_ci                s->prob->mvc[i][j] = vp8_rac_get_nn(c);
472cabdff1aSopenharmony_ci}
473cabdff1aSopenharmony_ci
474cabdff1aSopenharmony_cistatic void update_refs(VP8Context *s)
475cabdff1aSopenharmony_ci{
476cabdff1aSopenharmony_ci    VP56RangeCoder *c = &s->c;
477cabdff1aSopenharmony_ci
478cabdff1aSopenharmony_ci    int update_golden = vp8_rac_get(c);
479cabdff1aSopenharmony_ci    int update_altref = vp8_rac_get(c);
480cabdff1aSopenharmony_ci
481cabdff1aSopenharmony_ci    s->update_golden = ref_to_update(s, update_golden, VP56_FRAME_GOLDEN);
482cabdff1aSopenharmony_ci    s->update_altref = ref_to_update(s, update_altref, VP56_FRAME_GOLDEN2);
483cabdff1aSopenharmony_ci}
484cabdff1aSopenharmony_ci
485cabdff1aSopenharmony_cistatic void copy_chroma(AVFrame *dst, AVFrame *src, int width, int height)
486cabdff1aSopenharmony_ci{
487cabdff1aSopenharmony_ci    int i, j;
488cabdff1aSopenharmony_ci
489cabdff1aSopenharmony_ci    for (j = 1; j < 3; j++) {
490cabdff1aSopenharmony_ci        for (i = 0; i < height / 2; i++)
491cabdff1aSopenharmony_ci            memcpy(dst->data[j] + i * dst->linesize[j],
492cabdff1aSopenharmony_ci                   src->data[j] + i * src->linesize[j], width / 2);
493cabdff1aSopenharmony_ci    }
494cabdff1aSopenharmony_ci}
495cabdff1aSopenharmony_ci
496cabdff1aSopenharmony_cistatic void fade(uint8_t *dst, ptrdiff_t dst_linesize,
497cabdff1aSopenharmony_ci                 const uint8_t *src, ptrdiff_t src_linesize,
498cabdff1aSopenharmony_ci                 int width, int height,
499cabdff1aSopenharmony_ci                 int alpha, int beta)
500cabdff1aSopenharmony_ci{
501cabdff1aSopenharmony_ci    int i, j;
502cabdff1aSopenharmony_ci    for (j = 0; j < height; j++) {
503cabdff1aSopenharmony_ci        const uint8_t *src2 = src + j * src_linesize;
504cabdff1aSopenharmony_ci        uint8_t *dst2 = dst + j * dst_linesize;
505cabdff1aSopenharmony_ci        for (i = 0; i < width; i++) {
506cabdff1aSopenharmony_ci            uint8_t y = src2[i];
507cabdff1aSopenharmony_ci            dst2[i] = av_clip_uint8(y + ((y * beta) >> 8) + alpha);
508cabdff1aSopenharmony_ci        }
509cabdff1aSopenharmony_ci    }
510cabdff1aSopenharmony_ci}
511cabdff1aSopenharmony_ci
512cabdff1aSopenharmony_cistatic int vp7_fade_frame(VP8Context *s, int alpha, int beta)
513cabdff1aSopenharmony_ci{
514cabdff1aSopenharmony_ci    int ret;
515cabdff1aSopenharmony_ci
516cabdff1aSopenharmony_ci    if (!s->keyframe && (alpha || beta)) {
517cabdff1aSopenharmony_ci        int width  = s->mb_width * 16;
518cabdff1aSopenharmony_ci        int height = s->mb_height * 16;
519cabdff1aSopenharmony_ci        AVFrame *src, *dst;
520cabdff1aSopenharmony_ci
521cabdff1aSopenharmony_ci        if (!s->framep[VP56_FRAME_PREVIOUS] ||
522cabdff1aSopenharmony_ci            !s->framep[VP56_FRAME_GOLDEN]) {
523cabdff1aSopenharmony_ci            av_log(s->avctx, AV_LOG_WARNING, "Discarding interframe without a prior keyframe!\n");
524cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
525cabdff1aSopenharmony_ci        }
526cabdff1aSopenharmony_ci
527cabdff1aSopenharmony_ci        dst =
528cabdff1aSopenharmony_ci        src = s->framep[VP56_FRAME_PREVIOUS]->tf.f;
529cabdff1aSopenharmony_ci
530cabdff1aSopenharmony_ci        /* preserve the golden frame, write a new previous frame */
531cabdff1aSopenharmony_ci        if (s->framep[VP56_FRAME_GOLDEN] == s->framep[VP56_FRAME_PREVIOUS]) {
532cabdff1aSopenharmony_ci            s->framep[VP56_FRAME_PREVIOUS] = vp8_find_free_buffer(s);
533cabdff1aSopenharmony_ci            if ((ret = vp8_alloc_frame(s, s->framep[VP56_FRAME_PREVIOUS], 1)) < 0)
534cabdff1aSopenharmony_ci                return ret;
535cabdff1aSopenharmony_ci
536cabdff1aSopenharmony_ci            dst = s->framep[VP56_FRAME_PREVIOUS]->tf.f;
537cabdff1aSopenharmony_ci
538cabdff1aSopenharmony_ci            copy_chroma(dst, src, width, height);
539cabdff1aSopenharmony_ci        }
540cabdff1aSopenharmony_ci
541cabdff1aSopenharmony_ci        fade(dst->data[0], dst->linesize[0],
542cabdff1aSopenharmony_ci             src->data[0], src->linesize[0],
543cabdff1aSopenharmony_ci             width, height, alpha, beta);
544cabdff1aSopenharmony_ci    }
545cabdff1aSopenharmony_ci
546cabdff1aSopenharmony_ci    return 0;
547cabdff1aSopenharmony_ci}
548cabdff1aSopenharmony_ci
549cabdff1aSopenharmony_cistatic int vp7_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_size)
550cabdff1aSopenharmony_ci{
551cabdff1aSopenharmony_ci    VP56RangeCoder *c = &s->c;
552cabdff1aSopenharmony_ci    int part1_size, hscale, vscale, i, j, ret;
553cabdff1aSopenharmony_ci    int width  = s->avctx->width;
554cabdff1aSopenharmony_ci    int height = s->avctx->height;
555cabdff1aSopenharmony_ci    int alpha = 0;
556cabdff1aSopenharmony_ci    int beta  = 0;
557cabdff1aSopenharmony_ci
558cabdff1aSopenharmony_ci    if (buf_size < 4) {
559cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
560cabdff1aSopenharmony_ci    }
561cabdff1aSopenharmony_ci
562cabdff1aSopenharmony_ci    s->profile = (buf[0] >> 1) & 7;
563cabdff1aSopenharmony_ci    if (s->profile > 1) {
564cabdff1aSopenharmony_ci        avpriv_request_sample(s->avctx, "Unknown profile %d", s->profile);
565cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
566cabdff1aSopenharmony_ci    }
567cabdff1aSopenharmony_ci
568cabdff1aSopenharmony_ci    s->keyframe  = !(buf[0] & 1);
569cabdff1aSopenharmony_ci    s->invisible = 0;
570cabdff1aSopenharmony_ci    part1_size   = AV_RL24(buf) >> 4;
571cabdff1aSopenharmony_ci
572cabdff1aSopenharmony_ci    if (buf_size < 4 - s->profile + part1_size) {
573cabdff1aSopenharmony_ci        av_log(s->avctx, AV_LOG_ERROR, "Buffer size %d is too small, needed : %d\n", buf_size, 4 - s->profile + part1_size);
574cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
575cabdff1aSopenharmony_ci    }
576cabdff1aSopenharmony_ci
577cabdff1aSopenharmony_ci    buf      += 4 - s->profile;
578cabdff1aSopenharmony_ci    buf_size -= 4 - s->profile;
579cabdff1aSopenharmony_ci
580cabdff1aSopenharmony_ci    memcpy(s->put_pixels_tab, s->vp8dsp.put_vp8_epel_pixels_tab, sizeof(s->put_pixels_tab));
581cabdff1aSopenharmony_ci
582cabdff1aSopenharmony_ci    ret = ff_vp56_init_range_decoder(c, buf, part1_size);
583cabdff1aSopenharmony_ci    if (ret < 0)
584cabdff1aSopenharmony_ci        return ret;
585cabdff1aSopenharmony_ci    buf      += part1_size;
586cabdff1aSopenharmony_ci    buf_size -= part1_size;
587cabdff1aSopenharmony_ci
588cabdff1aSopenharmony_ci    /* A. Dimension information (keyframes only) */
589cabdff1aSopenharmony_ci    if (s->keyframe) {
590cabdff1aSopenharmony_ci        width  = vp8_rac_get_uint(c, 12);
591cabdff1aSopenharmony_ci        height = vp8_rac_get_uint(c, 12);
592cabdff1aSopenharmony_ci        hscale = vp8_rac_get_uint(c, 2);
593cabdff1aSopenharmony_ci        vscale = vp8_rac_get_uint(c, 2);
594cabdff1aSopenharmony_ci        if (hscale || vscale)
595cabdff1aSopenharmony_ci            avpriv_request_sample(s->avctx, "Upscaling");
596cabdff1aSopenharmony_ci
597cabdff1aSopenharmony_ci        s->update_golden = s->update_altref = VP56_FRAME_CURRENT;
598cabdff1aSopenharmony_ci        vp78_reset_probability_tables(s);
599cabdff1aSopenharmony_ci        memcpy(s->prob->pred16x16, vp8_pred16x16_prob_inter,
600cabdff1aSopenharmony_ci               sizeof(s->prob->pred16x16));
601cabdff1aSopenharmony_ci        memcpy(s->prob->pred8x8c, vp8_pred8x8c_prob_inter,
602cabdff1aSopenharmony_ci               sizeof(s->prob->pred8x8c));
603cabdff1aSopenharmony_ci        for (i = 0; i < 2; i++)
604cabdff1aSopenharmony_ci            memcpy(s->prob->mvc[i], vp7_mv_default_prob[i],
605cabdff1aSopenharmony_ci                   sizeof(vp7_mv_default_prob[i]));
606cabdff1aSopenharmony_ci        memset(&s->segmentation, 0, sizeof(s->segmentation));
607cabdff1aSopenharmony_ci        memset(&s->lf_delta, 0, sizeof(s->lf_delta));
608cabdff1aSopenharmony_ci        memcpy(s->prob[0].scan, ff_zigzag_scan, sizeof(s->prob[0].scan));
609cabdff1aSopenharmony_ci    }
610cabdff1aSopenharmony_ci
611cabdff1aSopenharmony_ci    if (s->keyframe || s->profile > 0)
612cabdff1aSopenharmony_ci        memset(s->inter_dc_pred, 0 , sizeof(s->inter_dc_pred));
613cabdff1aSopenharmony_ci
614cabdff1aSopenharmony_ci    /* B. Decoding information for all four macroblock-level features */
615cabdff1aSopenharmony_ci    for (i = 0; i < 4; i++) {
616cabdff1aSopenharmony_ci        s->feature_enabled[i] = vp8_rac_get(c);
617cabdff1aSopenharmony_ci        if (s->feature_enabled[i]) {
618cabdff1aSopenharmony_ci             s->feature_present_prob[i] = vp8_rac_get_uint(c, 8);
619cabdff1aSopenharmony_ci
620cabdff1aSopenharmony_ci             for (j = 0; j < 3; j++)
621cabdff1aSopenharmony_ci                 s->feature_index_prob[i][j] =
622cabdff1aSopenharmony_ci                     vp8_rac_get(c) ? vp8_rac_get_uint(c, 8) : 255;
623cabdff1aSopenharmony_ci
624cabdff1aSopenharmony_ci             if (vp7_feature_value_size[s->profile][i])
625cabdff1aSopenharmony_ci                 for (j = 0; j < 4; j++)
626cabdff1aSopenharmony_ci                     s->feature_value[i][j] =
627cabdff1aSopenharmony_ci                        vp8_rac_get(c) ? vp8_rac_get_uint(c, vp7_feature_value_size[s->profile][i]) : 0;
628cabdff1aSopenharmony_ci        }
629cabdff1aSopenharmony_ci    }
630cabdff1aSopenharmony_ci
631cabdff1aSopenharmony_ci    s->segmentation.enabled    = 0;
632cabdff1aSopenharmony_ci    s->segmentation.update_map = 0;
633cabdff1aSopenharmony_ci    s->lf_delta.enabled        = 0;
634cabdff1aSopenharmony_ci
635cabdff1aSopenharmony_ci    s->num_coeff_partitions = 1;
636cabdff1aSopenharmony_ci    ret = ff_vp56_init_range_decoder(&s->coeff_partition[0], buf, buf_size);
637cabdff1aSopenharmony_ci    if (ret < 0)
638cabdff1aSopenharmony_ci        return ret;
639cabdff1aSopenharmony_ci
640cabdff1aSopenharmony_ci    if (!s->macroblocks_base || /* first frame */
641cabdff1aSopenharmony_ci        width != s->avctx->width || height != s->avctx->height ||
642cabdff1aSopenharmony_ci        (width + 15) / 16 != s->mb_width || (height + 15) / 16 != s->mb_height) {
643cabdff1aSopenharmony_ci        if ((ret = vp7_update_dimensions(s, width, height)) < 0)
644cabdff1aSopenharmony_ci            return ret;
645cabdff1aSopenharmony_ci    }
646cabdff1aSopenharmony_ci
647cabdff1aSopenharmony_ci    /* C. Dequantization indices */
648cabdff1aSopenharmony_ci    vp7_get_quants(s);
649cabdff1aSopenharmony_ci
650cabdff1aSopenharmony_ci    /* D. Golden frame update flag (a Flag) for interframes only */
651cabdff1aSopenharmony_ci    if (!s->keyframe) {
652cabdff1aSopenharmony_ci        s->update_golden = vp8_rac_get(c) ? VP56_FRAME_CURRENT : VP56_FRAME_NONE;
653cabdff1aSopenharmony_ci        s->sign_bias[VP56_FRAME_GOLDEN] = 0;
654cabdff1aSopenharmony_ci    }
655cabdff1aSopenharmony_ci
656cabdff1aSopenharmony_ci    s->update_last          = 1;
657cabdff1aSopenharmony_ci    s->update_probabilities = 1;
658cabdff1aSopenharmony_ci    s->fade_present         = 1;
659cabdff1aSopenharmony_ci
660cabdff1aSopenharmony_ci    if (s->profile > 0) {
661cabdff1aSopenharmony_ci        s->update_probabilities = vp8_rac_get(c);
662cabdff1aSopenharmony_ci        if (!s->update_probabilities)
663cabdff1aSopenharmony_ci            s->prob[1] = s->prob[0];
664cabdff1aSopenharmony_ci
665cabdff1aSopenharmony_ci        if (!s->keyframe)
666cabdff1aSopenharmony_ci            s->fade_present = vp8_rac_get(c);
667cabdff1aSopenharmony_ci    }
668cabdff1aSopenharmony_ci
669cabdff1aSopenharmony_ci    if (vpX_rac_is_end(c))
670cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
671cabdff1aSopenharmony_ci    /* E. Fading information for previous frame */
672cabdff1aSopenharmony_ci    if (s->fade_present && vp8_rac_get(c)) {
673cabdff1aSopenharmony_ci        alpha = (int8_t) vp8_rac_get_uint(c, 8);
674cabdff1aSopenharmony_ci        beta  = (int8_t) vp8_rac_get_uint(c, 8);
675cabdff1aSopenharmony_ci    }
676cabdff1aSopenharmony_ci
677cabdff1aSopenharmony_ci    /* F. Loop filter type */
678cabdff1aSopenharmony_ci    if (!s->profile)
679cabdff1aSopenharmony_ci        s->filter.simple = vp8_rac_get(c);
680cabdff1aSopenharmony_ci
681cabdff1aSopenharmony_ci    /* G. DCT coefficient ordering specification */
682cabdff1aSopenharmony_ci    if (vp8_rac_get(c))
683cabdff1aSopenharmony_ci        for (i = 1; i < 16; i++)
684cabdff1aSopenharmony_ci            s->prob[0].scan[i] = ff_zigzag_scan[vp8_rac_get_uint(c, 4)];
685cabdff1aSopenharmony_ci
686cabdff1aSopenharmony_ci    /* H. Loop filter levels  */
687cabdff1aSopenharmony_ci    if (s->profile > 0)
688cabdff1aSopenharmony_ci        s->filter.simple = vp8_rac_get(c);
689cabdff1aSopenharmony_ci    s->filter.level     = vp8_rac_get_uint(c, 6);
690cabdff1aSopenharmony_ci    s->filter.sharpness = vp8_rac_get_uint(c, 3);
691cabdff1aSopenharmony_ci
692cabdff1aSopenharmony_ci    /* I. DCT coefficient probability update; 13.3 Token Probability Updates */
693cabdff1aSopenharmony_ci    vp78_update_probability_tables(s);
694cabdff1aSopenharmony_ci
695cabdff1aSopenharmony_ci    s->mbskip_enabled = 0;
696cabdff1aSopenharmony_ci
697cabdff1aSopenharmony_ci    /* J. The remaining frame header data occurs ONLY FOR INTERFRAMES */
698cabdff1aSopenharmony_ci    if (!s->keyframe) {
699cabdff1aSopenharmony_ci        s->prob->intra  = vp8_rac_get_uint(c, 8);
700cabdff1aSopenharmony_ci        s->prob->last   = vp8_rac_get_uint(c, 8);
701cabdff1aSopenharmony_ci        vp78_update_pred16x16_pred8x8_mvc_probabilities(s, VP7_MVC_SIZE);
702cabdff1aSopenharmony_ci    }
703cabdff1aSopenharmony_ci
704cabdff1aSopenharmony_ci    if (vpX_rac_is_end(c))
705cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
706cabdff1aSopenharmony_ci
707cabdff1aSopenharmony_ci    if ((ret = vp7_fade_frame(s, alpha, beta)) < 0)
708cabdff1aSopenharmony_ci        return ret;
709cabdff1aSopenharmony_ci
710cabdff1aSopenharmony_ci    return 0;
711cabdff1aSopenharmony_ci}
712cabdff1aSopenharmony_ci
713cabdff1aSopenharmony_cistatic int vp8_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_size)
714cabdff1aSopenharmony_ci{
715cabdff1aSopenharmony_ci    VP56RangeCoder *c = &s->c;
716cabdff1aSopenharmony_ci    int header_size, hscale, vscale, ret;
717cabdff1aSopenharmony_ci    int width  = s->avctx->width;
718cabdff1aSopenharmony_ci    int height = s->avctx->height;
719cabdff1aSopenharmony_ci
720cabdff1aSopenharmony_ci    if (buf_size < 3) {
721cabdff1aSopenharmony_ci        av_log(s->avctx, AV_LOG_ERROR, "Insufficent data (%d) for header\n", buf_size);
722cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
723cabdff1aSopenharmony_ci    }
724cabdff1aSopenharmony_ci
725cabdff1aSopenharmony_ci    s->keyframe  = !(buf[0] & 1);
726cabdff1aSopenharmony_ci    s->profile   =  (buf[0]>>1) & 7;
727cabdff1aSopenharmony_ci    s->invisible = !(buf[0] & 0x10);
728cabdff1aSopenharmony_ci    header_size  = AV_RL24(buf) >> 5;
729cabdff1aSopenharmony_ci    buf      += 3;
730cabdff1aSopenharmony_ci    buf_size -= 3;
731cabdff1aSopenharmony_ci
732cabdff1aSopenharmony_ci    s->header_partition_size = header_size;
733cabdff1aSopenharmony_ci
734cabdff1aSopenharmony_ci    if (s->profile > 3)
735cabdff1aSopenharmony_ci        av_log(s->avctx, AV_LOG_WARNING, "Unknown profile %d\n", s->profile);
736cabdff1aSopenharmony_ci
737cabdff1aSopenharmony_ci    if (!s->profile)
738cabdff1aSopenharmony_ci        memcpy(s->put_pixels_tab, s->vp8dsp.put_vp8_epel_pixels_tab,
739cabdff1aSopenharmony_ci               sizeof(s->put_pixels_tab));
740cabdff1aSopenharmony_ci    else    // profile 1-3 use bilinear, 4+ aren't defined so whatever
741cabdff1aSopenharmony_ci        memcpy(s->put_pixels_tab, s->vp8dsp.put_vp8_bilinear_pixels_tab,
742cabdff1aSopenharmony_ci               sizeof(s->put_pixels_tab));
743cabdff1aSopenharmony_ci
744cabdff1aSopenharmony_ci    if (header_size > buf_size - 7 * s->keyframe) {
745cabdff1aSopenharmony_ci        av_log(s->avctx, AV_LOG_ERROR, "Header size larger than data provided\n");
746cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
747cabdff1aSopenharmony_ci    }
748cabdff1aSopenharmony_ci
749cabdff1aSopenharmony_ci    if (s->keyframe) {
750cabdff1aSopenharmony_ci        if (AV_RL24(buf) != 0x2a019d) {
751cabdff1aSopenharmony_ci            av_log(s->avctx, AV_LOG_ERROR,
752cabdff1aSopenharmony_ci                   "Invalid start code 0x%x\n", AV_RL24(buf));
753cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
754cabdff1aSopenharmony_ci        }
755cabdff1aSopenharmony_ci        width     = AV_RL16(buf + 3) & 0x3fff;
756cabdff1aSopenharmony_ci        height    = AV_RL16(buf + 5) & 0x3fff;
757cabdff1aSopenharmony_ci        hscale    = buf[4] >> 6;
758cabdff1aSopenharmony_ci        vscale    = buf[6] >> 6;
759cabdff1aSopenharmony_ci        buf      += 7;
760cabdff1aSopenharmony_ci        buf_size -= 7;
761cabdff1aSopenharmony_ci
762cabdff1aSopenharmony_ci        if (hscale || vscale)
763cabdff1aSopenharmony_ci            avpriv_request_sample(s->avctx, "Upscaling");
764cabdff1aSopenharmony_ci
765cabdff1aSopenharmony_ci        s->update_golden = s->update_altref = VP56_FRAME_CURRENT;
766cabdff1aSopenharmony_ci        vp78_reset_probability_tables(s);
767cabdff1aSopenharmony_ci        memcpy(s->prob->pred16x16, vp8_pred16x16_prob_inter,
768cabdff1aSopenharmony_ci               sizeof(s->prob->pred16x16));
769cabdff1aSopenharmony_ci        memcpy(s->prob->pred8x8c, vp8_pred8x8c_prob_inter,
770cabdff1aSopenharmony_ci               sizeof(s->prob->pred8x8c));
771cabdff1aSopenharmony_ci        memcpy(s->prob->mvc, vp8_mv_default_prob,
772cabdff1aSopenharmony_ci               sizeof(s->prob->mvc));
773cabdff1aSopenharmony_ci        memset(&s->segmentation, 0, sizeof(s->segmentation));
774cabdff1aSopenharmony_ci        memset(&s->lf_delta, 0, sizeof(s->lf_delta));
775cabdff1aSopenharmony_ci    }
776cabdff1aSopenharmony_ci
777cabdff1aSopenharmony_ci    ret = ff_vp56_init_range_decoder(c, buf, header_size);
778cabdff1aSopenharmony_ci    if (ret < 0)
779cabdff1aSopenharmony_ci        return ret;
780cabdff1aSopenharmony_ci    buf      += header_size;
781cabdff1aSopenharmony_ci    buf_size -= header_size;
782cabdff1aSopenharmony_ci
783cabdff1aSopenharmony_ci    if (s->keyframe) {
784cabdff1aSopenharmony_ci        s->colorspace = vp8_rac_get(c);
785cabdff1aSopenharmony_ci        if (s->colorspace)
786cabdff1aSopenharmony_ci            av_log(s->avctx, AV_LOG_WARNING, "Unspecified colorspace\n");
787cabdff1aSopenharmony_ci        s->fullrange = vp8_rac_get(c);
788cabdff1aSopenharmony_ci    }
789cabdff1aSopenharmony_ci
790cabdff1aSopenharmony_ci    if ((s->segmentation.enabled = vp8_rac_get(c)))
791cabdff1aSopenharmony_ci        parse_segment_info(s);
792cabdff1aSopenharmony_ci    else
793cabdff1aSopenharmony_ci        s->segmentation.update_map = 0; // FIXME: move this to some init function?
794cabdff1aSopenharmony_ci
795cabdff1aSopenharmony_ci    s->filter.simple    = vp8_rac_get(c);
796cabdff1aSopenharmony_ci    s->filter.level     = vp8_rac_get_uint(c, 6);
797cabdff1aSopenharmony_ci    s->filter.sharpness = vp8_rac_get_uint(c, 3);
798cabdff1aSopenharmony_ci
799cabdff1aSopenharmony_ci    if ((s->lf_delta.enabled = vp8_rac_get(c))) {
800cabdff1aSopenharmony_ci        s->lf_delta.update = vp8_rac_get(c);
801cabdff1aSopenharmony_ci        if (s->lf_delta.update)
802cabdff1aSopenharmony_ci            update_lf_deltas(s);
803cabdff1aSopenharmony_ci    }
804cabdff1aSopenharmony_ci
805cabdff1aSopenharmony_ci    if (setup_partitions(s, buf, buf_size)) {
806cabdff1aSopenharmony_ci        av_log(s->avctx, AV_LOG_ERROR, "Invalid partitions\n");
807cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
808cabdff1aSopenharmony_ci    }
809cabdff1aSopenharmony_ci
810cabdff1aSopenharmony_ci    if (!s->macroblocks_base || /* first frame */
811cabdff1aSopenharmony_ci        width != s->avctx->width || height != s->avctx->height ||
812cabdff1aSopenharmony_ci        (width+15)/16 != s->mb_width || (height+15)/16 != s->mb_height)
813cabdff1aSopenharmony_ci        if ((ret = vp8_update_dimensions(s, width, height)) < 0)
814cabdff1aSopenharmony_ci            return ret;
815cabdff1aSopenharmony_ci
816cabdff1aSopenharmony_ci    vp8_get_quants(s);
817cabdff1aSopenharmony_ci
818cabdff1aSopenharmony_ci    if (!s->keyframe) {
819cabdff1aSopenharmony_ci        update_refs(s);
820cabdff1aSopenharmony_ci        s->sign_bias[VP56_FRAME_GOLDEN]               = vp8_rac_get(c);
821cabdff1aSopenharmony_ci        s->sign_bias[VP56_FRAME_GOLDEN2 /* altref */] = vp8_rac_get(c);
822cabdff1aSopenharmony_ci    }
823cabdff1aSopenharmony_ci
824cabdff1aSopenharmony_ci    // if we aren't saving this frame's probabilities for future frames,
825cabdff1aSopenharmony_ci    // make a copy of the current probabilities
826cabdff1aSopenharmony_ci    if (!(s->update_probabilities = vp8_rac_get(c)))
827cabdff1aSopenharmony_ci        s->prob[1] = s->prob[0];
828cabdff1aSopenharmony_ci
829cabdff1aSopenharmony_ci    s->update_last = s->keyframe || vp8_rac_get(c);
830cabdff1aSopenharmony_ci
831cabdff1aSopenharmony_ci    vp78_update_probability_tables(s);
832cabdff1aSopenharmony_ci
833cabdff1aSopenharmony_ci    if ((s->mbskip_enabled = vp8_rac_get(c)))
834cabdff1aSopenharmony_ci        s->prob->mbskip = vp8_rac_get_uint(c, 8);
835cabdff1aSopenharmony_ci
836cabdff1aSopenharmony_ci    if (!s->keyframe) {
837cabdff1aSopenharmony_ci        s->prob->intra  = vp8_rac_get_uint(c, 8);
838cabdff1aSopenharmony_ci        s->prob->last   = vp8_rac_get_uint(c, 8);
839cabdff1aSopenharmony_ci        s->prob->golden = vp8_rac_get_uint(c, 8);
840cabdff1aSopenharmony_ci        vp78_update_pred16x16_pred8x8_mvc_probabilities(s, VP8_MVC_SIZE);
841cabdff1aSopenharmony_ci    }
842cabdff1aSopenharmony_ci
843cabdff1aSopenharmony_ci    // Record the entropy coder state here so that hwaccels can use it.
844cabdff1aSopenharmony_ci    s->c.code_word = vp56_rac_renorm(&s->c);
845cabdff1aSopenharmony_ci    s->coder_state_at_header_end.input     = s->c.buffer - (-s->c.bits / 8);
846cabdff1aSopenharmony_ci    s->coder_state_at_header_end.range     = s->c.high;
847cabdff1aSopenharmony_ci    s->coder_state_at_header_end.value     = s->c.code_word >> 16;
848cabdff1aSopenharmony_ci    s->coder_state_at_header_end.bit_count = -s->c.bits % 8;
849cabdff1aSopenharmony_ci
850cabdff1aSopenharmony_ci    return 0;
851cabdff1aSopenharmony_ci}
852cabdff1aSopenharmony_ci
853cabdff1aSopenharmony_cistatic av_always_inline
854cabdff1aSopenharmony_civoid clamp_mv(VP8mvbounds *s, VP56mv *dst, const VP56mv *src)
855cabdff1aSopenharmony_ci{
856cabdff1aSopenharmony_ci    dst->x = av_clip(src->x, av_clip(s->mv_min.x, INT16_MIN, INT16_MAX),
857cabdff1aSopenharmony_ci                             av_clip(s->mv_max.x, INT16_MIN, INT16_MAX));
858cabdff1aSopenharmony_ci    dst->y = av_clip(src->y, av_clip(s->mv_min.y, INT16_MIN, INT16_MAX),
859cabdff1aSopenharmony_ci                             av_clip(s->mv_max.y, INT16_MIN, INT16_MAX));
860cabdff1aSopenharmony_ci}
861cabdff1aSopenharmony_ci
862cabdff1aSopenharmony_ci/**
863cabdff1aSopenharmony_ci * Motion vector coding, 17.1.
864cabdff1aSopenharmony_ci */
865cabdff1aSopenharmony_cistatic av_always_inline int read_mv_component(VP56RangeCoder *c, const uint8_t *p, int vp7)
866cabdff1aSopenharmony_ci{
867cabdff1aSopenharmony_ci    int bit, x = 0;
868cabdff1aSopenharmony_ci
869cabdff1aSopenharmony_ci    if (vp56_rac_get_prob_branchy(c, p[0])) {
870cabdff1aSopenharmony_ci        int i;
871cabdff1aSopenharmony_ci
872cabdff1aSopenharmony_ci        for (i = 0; i < 3; i++)
873cabdff1aSopenharmony_ci            x += vp56_rac_get_prob(c, p[9 + i]) << i;
874cabdff1aSopenharmony_ci        for (i = (vp7 ? 7 : 9); i > 3; i--)
875cabdff1aSopenharmony_ci            x += vp56_rac_get_prob(c, p[9 + i]) << i;
876cabdff1aSopenharmony_ci        if (!(x & (vp7 ? 0xF0 : 0xFFF0)) || vp56_rac_get_prob(c, p[12]))
877cabdff1aSopenharmony_ci            x += 8;
878cabdff1aSopenharmony_ci    } else {
879cabdff1aSopenharmony_ci        // small_mvtree
880cabdff1aSopenharmony_ci        const uint8_t *ps = p + 2;
881cabdff1aSopenharmony_ci        bit = vp56_rac_get_prob(c, *ps);
882cabdff1aSopenharmony_ci        ps += 1 + 3 * bit;
883cabdff1aSopenharmony_ci        x  += 4 * bit;
884cabdff1aSopenharmony_ci        bit = vp56_rac_get_prob(c, *ps);
885cabdff1aSopenharmony_ci        ps += 1 + bit;
886cabdff1aSopenharmony_ci        x  += 2 * bit;
887cabdff1aSopenharmony_ci        x  += vp56_rac_get_prob(c, *ps);
888cabdff1aSopenharmony_ci    }
889cabdff1aSopenharmony_ci
890cabdff1aSopenharmony_ci    return (x && vp56_rac_get_prob(c, p[1])) ? -x : x;
891cabdff1aSopenharmony_ci}
892cabdff1aSopenharmony_ci
893cabdff1aSopenharmony_cistatic int vp7_read_mv_component(VP56RangeCoder *c, const uint8_t *p)
894cabdff1aSopenharmony_ci{
895cabdff1aSopenharmony_ci    return read_mv_component(c, p, 1);
896cabdff1aSopenharmony_ci}
897cabdff1aSopenharmony_ci
898cabdff1aSopenharmony_cistatic int vp8_read_mv_component(VP56RangeCoder *c, const uint8_t *p)
899cabdff1aSopenharmony_ci{
900cabdff1aSopenharmony_ci    return read_mv_component(c, p, 0);
901cabdff1aSopenharmony_ci}
902cabdff1aSopenharmony_ci
903cabdff1aSopenharmony_cistatic av_always_inline
904cabdff1aSopenharmony_ciconst uint8_t *get_submv_prob(uint32_t left, uint32_t top, int is_vp7)
905cabdff1aSopenharmony_ci{
906cabdff1aSopenharmony_ci    if (is_vp7)
907cabdff1aSopenharmony_ci        return vp7_submv_prob;
908cabdff1aSopenharmony_ci
909cabdff1aSopenharmony_ci    if (left == top)
910cabdff1aSopenharmony_ci        return vp8_submv_prob[4 - !!left];
911cabdff1aSopenharmony_ci    if (!top)
912cabdff1aSopenharmony_ci        return vp8_submv_prob[2];
913cabdff1aSopenharmony_ci    return vp8_submv_prob[1 - !!left];
914cabdff1aSopenharmony_ci}
915cabdff1aSopenharmony_ci
916cabdff1aSopenharmony_ci/**
917cabdff1aSopenharmony_ci * Split motion vector prediction, 16.4.
918cabdff1aSopenharmony_ci * @returns the number of motion vectors parsed (2, 4 or 16)
919cabdff1aSopenharmony_ci */
920cabdff1aSopenharmony_cistatic av_always_inline
921cabdff1aSopenharmony_ciint decode_splitmvs(VP8Context *s, VP56RangeCoder *c, VP8Macroblock *mb,
922cabdff1aSopenharmony_ci                    int layout, int is_vp7)
923cabdff1aSopenharmony_ci{
924cabdff1aSopenharmony_ci    int part_idx;
925cabdff1aSopenharmony_ci    int n, num;
926cabdff1aSopenharmony_ci    VP8Macroblock *top_mb;
927cabdff1aSopenharmony_ci    VP8Macroblock *left_mb = &mb[-1];
928cabdff1aSopenharmony_ci    const uint8_t *mbsplits_left = vp8_mbsplits[left_mb->partitioning];
929cabdff1aSopenharmony_ci    const uint8_t *mbsplits_top, *mbsplits_cur, *firstidx;
930cabdff1aSopenharmony_ci    VP56mv *top_mv;
931cabdff1aSopenharmony_ci    VP56mv *left_mv = left_mb->bmv;
932cabdff1aSopenharmony_ci    VP56mv *cur_mv  = mb->bmv;
933cabdff1aSopenharmony_ci
934cabdff1aSopenharmony_ci    if (!layout) // layout is inlined, s->mb_layout is not
935cabdff1aSopenharmony_ci        top_mb = &mb[2];
936cabdff1aSopenharmony_ci    else
937cabdff1aSopenharmony_ci        top_mb = &mb[-s->mb_width - 1];
938cabdff1aSopenharmony_ci    mbsplits_top = vp8_mbsplits[top_mb->partitioning];
939cabdff1aSopenharmony_ci    top_mv       = top_mb->bmv;
940cabdff1aSopenharmony_ci
941cabdff1aSopenharmony_ci    if (vp56_rac_get_prob_branchy(c, vp8_mbsplit_prob[0])) {
942cabdff1aSopenharmony_ci        if (vp56_rac_get_prob_branchy(c, vp8_mbsplit_prob[1]))
943cabdff1aSopenharmony_ci            part_idx = VP8_SPLITMVMODE_16x8 + vp56_rac_get_prob(c, vp8_mbsplit_prob[2]);
944cabdff1aSopenharmony_ci        else
945cabdff1aSopenharmony_ci            part_idx = VP8_SPLITMVMODE_8x8;
946cabdff1aSopenharmony_ci    } else {
947cabdff1aSopenharmony_ci        part_idx = VP8_SPLITMVMODE_4x4;
948cabdff1aSopenharmony_ci    }
949cabdff1aSopenharmony_ci
950cabdff1aSopenharmony_ci    num              = vp8_mbsplit_count[part_idx];
951cabdff1aSopenharmony_ci    mbsplits_cur     = vp8_mbsplits[part_idx],
952cabdff1aSopenharmony_ci    firstidx         = vp8_mbfirstidx[part_idx];
953cabdff1aSopenharmony_ci    mb->partitioning = part_idx;
954cabdff1aSopenharmony_ci
955cabdff1aSopenharmony_ci    for (n = 0; n < num; n++) {
956cabdff1aSopenharmony_ci        int k = firstidx[n];
957cabdff1aSopenharmony_ci        uint32_t left, above;
958cabdff1aSopenharmony_ci        const uint8_t *submv_prob;
959cabdff1aSopenharmony_ci
960cabdff1aSopenharmony_ci        if (!(k & 3))
961cabdff1aSopenharmony_ci            left = AV_RN32A(&left_mv[mbsplits_left[k + 3]]);
962cabdff1aSopenharmony_ci        else
963cabdff1aSopenharmony_ci            left = AV_RN32A(&cur_mv[mbsplits_cur[k - 1]]);
964cabdff1aSopenharmony_ci        if (k <= 3)
965cabdff1aSopenharmony_ci            above = AV_RN32A(&top_mv[mbsplits_top[k + 12]]);
966cabdff1aSopenharmony_ci        else
967cabdff1aSopenharmony_ci            above = AV_RN32A(&cur_mv[mbsplits_cur[k - 4]]);
968cabdff1aSopenharmony_ci
969cabdff1aSopenharmony_ci        submv_prob = get_submv_prob(left, above, is_vp7);
970cabdff1aSopenharmony_ci
971cabdff1aSopenharmony_ci        if (vp56_rac_get_prob_branchy(c, submv_prob[0])) {
972cabdff1aSopenharmony_ci            if (vp56_rac_get_prob_branchy(c, submv_prob[1])) {
973cabdff1aSopenharmony_ci                if (vp56_rac_get_prob_branchy(c, submv_prob[2])) {
974cabdff1aSopenharmony_ci                    mb->bmv[n].y = mb->mv.y +
975cabdff1aSopenharmony_ci                                   read_mv_component(c, s->prob->mvc[0], is_vp7);
976cabdff1aSopenharmony_ci                    mb->bmv[n].x = mb->mv.x +
977cabdff1aSopenharmony_ci                                   read_mv_component(c, s->prob->mvc[1], is_vp7);
978cabdff1aSopenharmony_ci                } else {
979cabdff1aSopenharmony_ci                    AV_ZERO32(&mb->bmv[n]);
980cabdff1aSopenharmony_ci                }
981cabdff1aSopenharmony_ci            } else {
982cabdff1aSopenharmony_ci                AV_WN32A(&mb->bmv[n], above);
983cabdff1aSopenharmony_ci            }
984cabdff1aSopenharmony_ci        } else {
985cabdff1aSopenharmony_ci            AV_WN32A(&mb->bmv[n], left);
986cabdff1aSopenharmony_ci        }
987cabdff1aSopenharmony_ci    }
988cabdff1aSopenharmony_ci
989cabdff1aSopenharmony_ci    return num;
990cabdff1aSopenharmony_ci}
991cabdff1aSopenharmony_ci
992cabdff1aSopenharmony_ci/**
993cabdff1aSopenharmony_ci * The vp7 reference decoder uses a padding macroblock column (added to right
994cabdff1aSopenharmony_ci * edge of the frame) to guard against illegal macroblock offsets. The
995cabdff1aSopenharmony_ci * algorithm has bugs that permit offsets to straddle the padding column.
996cabdff1aSopenharmony_ci * This function replicates those bugs.
997cabdff1aSopenharmony_ci *
998cabdff1aSopenharmony_ci * @param[out] edge_x macroblock x address
999cabdff1aSopenharmony_ci * @param[out] edge_y macroblock y address
1000cabdff1aSopenharmony_ci *
1001cabdff1aSopenharmony_ci * @return macroblock offset legal (boolean)
1002cabdff1aSopenharmony_ci */
1003cabdff1aSopenharmony_cistatic int vp7_calculate_mb_offset(int mb_x, int mb_y, int mb_width,
1004cabdff1aSopenharmony_ci                                   int xoffset, int yoffset, int boundary,
1005cabdff1aSopenharmony_ci                                   int *edge_x, int *edge_y)
1006cabdff1aSopenharmony_ci{
1007cabdff1aSopenharmony_ci    int vwidth = mb_width + 1;
1008cabdff1aSopenharmony_ci    int new = (mb_y + yoffset) * vwidth + mb_x + xoffset;
1009cabdff1aSopenharmony_ci    if (new < boundary || new % vwidth == vwidth - 1)
1010cabdff1aSopenharmony_ci        return 0;
1011cabdff1aSopenharmony_ci    *edge_y = new / vwidth;
1012cabdff1aSopenharmony_ci    *edge_x = new % vwidth;
1013cabdff1aSopenharmony_ci    return 1;
1014cabdff1aSopenharmony_ci}
1015cabdff1aSopenharmony_ci
1016cabdff1aSopenharmony_cistatic const VP56mv *get_bmv_ptr(const VP8Macroblock *mb, int subblock)
1017cabdff1aSopenharmony_ci{
1018cabdff1aSopenharmony_ci    return &mb->bmv[mb->mode == VP8_MVMODE_SPLIT ? vp8_mbsplits[mb->partitioning][subblock] : 0];
1019cabdff1aSopenharmony_ci}
1020cabdff1aSopenharmony_ci
1021cabdff1aSopenharmony_cistatic av_always_inline
1022cabdff1aSopenharmony_civoid vp7_decode_mvs(VP8Context *s, VP8Macroblock *mb,
1023cabdff1aSopenharmony_ci                    int mb_x, int mb_y, int layout)
1024cabdff1aSopenharmony_ci{
1025cabdff1aSopenharmony_ci    VP8Macroblock *mb_edge[12];
1026cabdff1aSopenharmony_ci    enum { CNT_ZERO, CNT_NEAREST, CNT_NEAR };
1027cabdff1aSopenharmony_ci    enum { VP8_EDGE_TOP, VP8_EDGE_LEFT, VP8_EDGE_TOPLEFT };
1028cabdff1aSopenharmony_ci    int idx = CNT_ZERO;
1029cabdff1aSopenharmony_ci    VP56mv near_mv[3];
1030cabdff1aSopenharmony_ci    uint8_t cnt[3] = { 0 };
1031cabdff1aSopenharmony_ci    VP56RangeCoder *c = &s->c;
1032cabdff1aSopenharmony_ci    int i;
1033cabdff1aSopenharmony_ci
1034cabdff1aSopenharmony_ci    AV_ZERO32(&near_mv[0]);
1035cabdff1aSopenharmony_ci    AV_ZERO32(&near_mv[1]);
1036cabdff1aSopenharmony_ci    AV_ZERO32(&near_mv[2]);
1037cabdff1aSopenharmony_ci
1038cabdff1aSopenharmony_ci    for (i = 0; i < VP7_MV_PRED_COUNT; i++) {
1039cabdff1aSopenharmony_ci        const VP7MVPred * pred = &vp7_mv_pred[i];
1040cabdff1aSopenharmony_ci        int edge_x, edge_y;
1041cabdff1aSopenharmony_ci
1042cabdff1aSopenharmony_ci        if (vp7_calculate_mb_offset(mb_x, mb_y, s->mb_width, pred->xoffset,
1043cabdff1aSopenharmony_ci                                    pred->yoffset, !s->profile, &edge_x, &edge_y)) {
1044cabdff1aSopenharmony_ci            VP8Macroblock *edge = mb_edge[i] = (s->mb_layout == 1)
1045cabdff1aSopenharmony_ci                                             ? s->macroblocks_base + 1 + edge_x +
1046cabdff1aSopenharmony_ci                                               (s->mb_width + 1) * (edge_y + 1)
1047cabdff1aSopenharmony_ci                                             : s->macroblocks + edge_x +
1048cabdff1aSopenharmony_ci                                               (s->mb_height - edge_y - 1) * 2;
1049cabdff1aSopenharmony_ci            uint32_t mv = AV_RN32A(get_bmv_ptr(edge, vp7_mv_pred[i].subblock));
1050cabdff1aSopenharmony_ci            if (mv) {
1051cabdff1aSopenharmony_ci                if (AV_RN32A(&near_mv[CNT_NEAREST])) {
1052cabdff1aSopenharmony_ci                    if (mv == AV_RN32A(&near_mv[CNT_NEAREST])) {
1053cabdff1aSopenharmony_ci                        idx = CNT_NEAREST;
1054cabdff1aSopenharmony_ci                    } else if (AV_RN32A(&near_mv[CNT_NEAR])) {
1055cabdff1aSopenharmony_ci                        if (mv != AV_RN32A(&near_mv[CNT_NEAR]))
1056cabdff1aSopenharmony_ci                            continue;
1057cabdff1aSopenharmony_ci                        idx = CNT_NEAR;
1058cabdff1aSopenharmony_ci                    } else {
1059cabdff1aSopenharmony_ci                        AV_WN32A(&near_mv[CNT_NEAR], mv);
1060cabdff1aSopenharmony_ci                        idx = CNT_NEAR;
1061cabdff1aSopenharmony_ci                    }
1062cabdff1aSopenharmony_ci                } else {
1063cabdff1aSopenharmony_ci                    AV_WN32A(&near_mv[CNT_NEAREST], mv);
1064cabdff1aSopenharmony_ci                    idx = CNT_NEAREST;
1065cabdff1aSopenharmony_ci                }
1066cabdff1aSopenharmony_ci            } else {
1067cabdff1aSopenharmony_ci                idx = CNT_ZERO;
1068cabdff1aSopenharmony_ci            }
1069cabdff1aSopenharmony_ci        } else {
1070cabdff1aSopenharmony_ci            idx = CNT_ZERO;
1071cabdff1aSopenharmony_ci        }
1072cabdff1aSopenharmony_ci        cnt[idx] += vp7_mv_pred[i].score;
1073cabdff1aSopenharmony_ci    }
1074cabdff1aSopenharmony_ci
1075cabdff1aSopenharmony_ci    mb->partitioning = VP8_SPLITMVMODE_NONE;
1076cabdff1aSopenharmony_ci
1077cabdff1aSopenharmony_ci    if (vp56_rac_get_prob_branchy(c, vp7_mode_contexts[cnt[CNT_ZERO]][0])) {
1078cabdff1aSopenharmony_ci        mb->mode = VP8_MVMODE_MV;
1079cabdff1aSopenharmony_ci
1080cabdff1aSopenharmony_ci        if (vp56_rac_get_prob_branchy(c, vp7_mode_contexts[cnt[CNT_NEAREST]][1])) {
1081cabdff1aSopenharmony_ci
1082cabdff1aSopenharmony_ci            if (vp56_rac_get_prob_branchy(c, vp7_mode_contexts[cnt[CNT_NEAR]][2])) {
1083cabdff1aSopenharmony_ci
1084cabdff1aSopenharmony_ci                if (cnt[CNT_NEAREST] > cnt[CNT_NEAR])
1085cabdff1aSopenharmony_ci                    AV_WN32A(&mb->mv, cnt[CNT_ZERO] > cnt[CNT_NEAREST] ? 0 : AV_RN32A(&near_mv[CNT_NEAREST]));
1086cabdff1aSopenharmony_ci                else
1087cabdff1aSopenharmony_ci                    AV_WN32A(&mb->mv, cnt[CNT_ZERO] > cnt[CNT_NEAR]    ? 0 : AV_RN32A(&near_mv[CNT_NEAR]));
1088cabdff1aSopenharmony_ci
1089cabdff1aSopenharmony_ci                if (vp56_rac_get_prob_branchy(c, vp7_mode_contexts[cnt[CNT_NEAR]][3])) {
1090cabdff1aSopenharmony_ci                    mb->mode = VP8_MVMODE_SPLIT;
1091cabdff1aSopenharmony_ci                    mb->mv = mb->bmv[decode_splitmvs(s, c, mb, layout, IS_VP7) - 1];
1092cabdff1aSopenharmony_ci                } else {
1093cabdff1aSopenharmony_ci                    mb->mv.y += vp7_read_mv_component(c, s->prob->mvc[0]);
1094cabdff1aSopenharmony_ci                    mb->mv.x += vp7_read_mv_component(c, s->prob->mvc[1]);
1095cabdff1aSopenharmony_ci                    mb->bmv[0] = mb->mv;
1096cabdff1aSopenharmony_ci                }
1097cabdff1aSopenharmony_ci            } else {
1098cabdff1aSopenharmony_ci                mb->mv = near_mv[CNT_NEAR];
1099cabdff1aSopenharmony_ci                mb->bmv[0] = mb->mv;
1100cabdff1aSopenharmony_ci            }
1101cabdff1aSopenharmony_ci        } else {
1102cabdff1aSopenharmony_ci            mb->mv = near_mv[CNT_NEAREST];
1103cabdff1aSopenharmony_ci            mb->bmv[0] = mb->mv;
1104cabdff1aSopenharmony_ci        }
1105cabdff1aSopenharmony_ci    } else {
1106cabdff1aSopenharmony_ci        mb->mode = VP8_MVMODE_ZERO;
1107cabdff1aSopenharmony_ci        AV_ZERO32(&mb->mv);
1108cabdff1aSopenharmony_ci        mb->bmv[0] = mb->mv;
1109cabdff1aSopenharmony_ci    }
1110cabdff1aSopenharmony_ci}
1111cabdff1aSopenharmony_ci
1112cabdff1aSopenharmony_cistatic av_always_inline
1113cabdff1aSopenharmony_civoid vp8_decode_mvs(VP8Context *s, VP8mvbounds *mv_bounds, VP8Macroblock *mb,
1114cabdff1aSopenharmony_ci                    int mb_x, int mb_y, int layout)
1115cabdff1aSopenharmony_ci{
1116cabdff1aSopenharmony_ci    VP8Macroblock *mb_edge[3] = { 0      /* top */,
1117cabdff1aSopenharmony_ci                                  mb - 1 /* left */,
1118cabdff1aSopenharmony_ci                                  0      /* top-left */ };
1119cabdff1aSopenharmony_ci    enum { CNT_ZERO, CNT_NEAREST, CNT_NEAR, CNT_SPLITMV };
1120cabdff1aSopenharmony_ci    enum { VP8_EDGE_TOP, VP8_EDGE_LEFT, VP8_EDGE_TOPLEFT };
1121cabdff1aSopenharmony_ci    int idx = CNT_ZERO;
1122cabdff1aSopenharmony_ci    int cur_sign_bias = s->sign_bias[mb->ref_frame];
1123cabdff1aSopenharmony_ci    int8_t *sign_bias = s->sign_bias;
1124cabdff1aSopenharmony_ci    VP56mv near_mv[4];
1125cabdff1aSopenharmony_ci    uint8_t cnt[4] = { 0 };
1126cabdff1aSopenharmony_ci    VP56RangeCoder *c = &s->c;
1127cabdff1aSopenharmony_ci
1128cabdff1aSopenharmony_ci    if (!layout) { // layout is inlined (s->mb_layout is not)
1129cabdff1aSopenharmony_ci        mb_edge[0] = mb + 2;
1130cabdff1aSopenharmony_ci        mb_edge[2] = mb + 1;
1131cabdff1aSopenharmony_ci    } else {
1132cabdff1aSopenharmony_ci        mb_edge[0] = mb - s->mb_width - 1;
1133cabdff1aSopenharmony_ci        mb_edge[2] = mb - s->mb_width - 2;
1134cabdff1aSopenharmony_ci    }
1135cabdff1aSopenharmony_ci
1136cabdff1aSopenharmony_ci    AV_ZERO32(&near_mv[0]);
1137cabdff1aSopenharmony_ci    AV_ZERO32(&near_mv[1]);
1138cabdff1aSopenharmony_ci    AV_ZERO32(&near_mv[2]);
1139cabdff1aSopenharmony_ci
1140cabdff1aSopenharmony_ci    /* Process MB on top, left and top-left */
1141cabdff1aSopenharmony_ci#define MV_EDGE_CHECK(n)                                                      \
1142cabdff1aSopenharmony_ci    {                                                                         \
1143cabdff1aSopenharmony_ci        VP8Macroblock *edge = mb_edge[n];                                     \
1144cabdff1aSopenharmony_ci        int edge_ref = edge->ref_frame;                                       \
1145cabdff1aSopenharmony_ci        if (edge_ref != VP56_FRAME_CURRENT) {                                 \
1146cabdff1aSopenharmony_ci            uint32_t mv = AV_RN32A(&edge->mv);                                \
1147cabdff1aSopenharmony_ci            if (mv) {                                                         \
1148cabdff1aSopenharmony_ci                if (cur_sign_bias != sign_bias[edge_ref]) {                   \
1149cabdff1aSopenharmony_ci                    /* SWAR negate of the values in mv. */                    \
1150cabdff1aSopenharmony_ci                    mv = ~mv;                                                 \
1151cabdff1aSopenharmony_ci                    mv = ((mv & 0x7fff7fff) +                                 \
1152cabdff1aSopenharmony_ci                          0x00010001) ^ (mv & 0x80008000);                    \
1153cabdff1aSopenharmony_ci                }                                                             \
1154cabdff1aSopenharmony_ci                if (!n || mv != AV_RN32A(&near_mv[idx]))                      \
1155cabdff1aSopenharmony_ci                    AV_WN32A(&near_mv[++idx], mv);                            \
1156cabdff1aSopenharmony_ci                cnt[idx] += 1 + (n != 2);                                     \
1157cabdff1aSopenharmony_ci            } else                                                            \
1158cabdff1aSopenharmony_ci                cnt[CNT_ZERO] += 1 + (n != 2);                                \
1159cabdff1aSopenharmony_ci        }                                                                     \
1160cabdff1aSopenharmony_ci    }
1161cabdff1aSopenharmony_ci
1162cabdff1aSopenharmony_ci    MV_EDGE_CHECK(0)
1163cabdff1aSopenharmony_ci    MV_EDGE_CHECK(1)
1164cabdff1aSopenharmony_ci    MV_EDGE_CHECK(2)
1165cabdff1aSopenharmony_ci
1166cabdff1aSopenharmony_ci    mb->partitioning = VP8_SPLITMVMODE_NONE;
1167cabdff1aSopenharmony_ci    if (vp56_rac_get_prob_branchy(c, vp8_mode_contexts[cnt[CNT_ZERO]][0])) {
1168cabdff1aSopenharmony_ci        mb->mode = VP8_MVMODE_MV;
1169cabdff1aSopenharmony_ci
1170cabdff1aSopenharmony_ci        /* If we have three distinct MVs, merge first and last if they're the same */
1171cabdff1aSopenharmony_ci        if (cnt[CNT_SPLITMV] &&
1172cabdff1aSopenharmony_ci            AV_RN32A(&near_mv[1 + VP8_EDGE_TOP]) == AV_RN32A(&near_mv[1 + VP8_EDGE_TOPLEFT]))
1173cabdff1aSopenharmony_ci            cnt[CNT_NEAREST] += 1;
1174cabdff1aSopenharmony_ci
1175cabdff1aSopenharmony_ci        /* Swap near and nearest if necessary */
1176cabdff1aSopenharmony_ci        if (cnt[CNT_NEAR] > cnt[CNT_NEAREST]) {
1177cabdff1aSopenharmony_ci            FFSWAP(uint8_t,     cnt[CNT_NEAREST],     cnt[CNT_NEAR]);
1178cabdff1aSopenharmony_ci            FFSWAP( VP56mv, near_mv[CNT_NEAREST], near_mv[CNT_NEAR]);
1179cabdff1aSopenharmony_ci        }
1180cabdff1aSopenharmony_ci
1181cabdff1aSopenharmony_ci        if (vp56_rac_get_prob_branchy(c, vp8_mode_contexts[cnt[CNT_NEAREST]][1])) {
1182cabdff1aSopenharmony_ci            if (vp56_rac_get_prob_branchy(c, vp8_mode_contexts[cnt[CNT_NEAR]][2])) {
1183cabdff1aSopenharmony_ci                /* Choose the best mv out of 0,0 and the nearest mv */
1184cabdff1aSopenharmony_ci                clamp_mv(mv_bounds, &mb->mv, &near_mv[CNT_ZERO + (cnt[CNT_NEAREST] >= cnt[CNT_ZERO])]);
1185cabdff1aSopenharmony_ci                cnt[CNT_SPLITMV] = ((mb_edge[VP8_EDGE_LEFT]->mode    == VP8_MVMODE_SPLIT) +
1186cabdff1aSopenharmony_ci                                    (mb_edge[VP8_EDGE_TOP]->mode     == VP8_MVMODE_SPLIT)) * 2 +
1187cabdff1aSopenharmony_ci                                    (mb_edge[VP8_EDGE_TOPLEFT]->mode == VP8_MVMODE_SPLIT);
1188cabdff1aSopenharmony_ci
1189cabdff1aSopenharmony_ci                if (vp56_rac_get_prob_branchy(c, vp8_mode_contexts[cnt[CNT_SPLITMV]][3])) {
1190cabdff1aSopenharmony_ci                    mb->mode = VP8_MVMODE_SPLIT;
1191cabdff1aSopenharmony_ci                    mb->mv = mb->bmv[decode_splitmvs(s, c, mb, layout, IS_VP8) - 1];
1192cabdff1aSopenharmony_ci                } else {
1193cabdff1aSopenharmony_ci                    mb->mv.y  += vp8_read_mv_component(c, s->prob->mvc[0]);
1194cabdff1aSopenharmony_ci                    mb->mv.x  += vp8_read_mv_component(c, s->prob->mvc[1]);
1195cabdff1aSopenharmony_ci                    mb->bmv[0] = mb->mv;
1196cabdff1aSopenharmony_ci                }
1197cabdff1aSopenharmony_ci            } else {
1198cabdff1aSopenharmony_ci                clamp_mv(mv_bounds, &mb->mv, &near_mv[CNT_NEAR]);
1199cabdff1aSopenharmony_ci                mb->bmv[0] = mb->mv;
1200cabdff1aSopenharmony_ci            }
1201cabdff1aSopenharmony_ci        } else {
1202cabdff1aSopenharmony_ci            clamp_mv(mv_bounds, &mb->mv, &near_mv[CNT_NEAREST]);
1203cabdff1aSopenharmony_ci            mb->bmv[0] = mb->mv;
1204cabdff1aSopenharmony_ci        }
1205cabdff1aSopenharmony_ci    } else {
1206cabdff1aSopenharmony_ci        mb->mode = VP8_MVMODE_ZERO;
1207cabdff1aSopenharmony_ci        AV_ZERO32(&mb->mv);
1208cabdff1aSopenharmony_ci        mb->bmv[0] = mb->mv;
1209cabdff1aSopenharmony_ci    }
1210cabdff1aSopenharmony_ci}
1211cabdff1aSopenharmony_ci
1212cabdff1aSopenharmony_cistatic av_always_inline
1213cabdff1aSopenharmony_civoid decode_intra4x4_modes(VP8Context *s, VP56RangeCoder *c, VP8Macroblock *mb,
1214cabdff1aSopenharmony_ci                           int mb_x, int keyframe, int layout)
1215cabdff1aSopenharmony_ci{
1216cabdff1aSopenharmony_ci    uint8_t *intra4x4 = mb->intra4x4_pred_mode_mb;
1217cabdff1aSopenharmony_ci
1218cabdff1aSopenharmony_ci    if (layout) {
1219cabdff1aSopenharmony_ci        VP8Macroblock *mb_top = mb - s->mb_width - 1;
1220cabdff1aSopenharmony_ci        memcpy(mb->intra4x4_pred_mode_top, mb_top->intra4x4_pred_mode_top, 4);
1221cabdff1aSopenharmony_ci    }
1222cabdff1aSopenharmony_ci    if (keyframe) {
1223cabdff1aSopenharmony_ci        int x, y;
1224cabdff1aSopenharmony_ci        uint8_t *top;
1225cabdff1aSopenharmony_ci        uint8_t *const left = s->intra4x4_pred_mode_left;
1226cabdff1aSopenharmony_ci        if (layout)
1227cabdff1aSopenharmony_ci            top = mb->intra4x4_pred_mode_top;
1228cabdff1aSopenharmony_ci        else
1229cabdff1aSopenharmony_ci            top = s->intra4x4_pred_mode_top + 4 * mb_x;
1230cabdff1aSopenharmony_ci        for (y = 0; y < 4; y++) {
1231cabdff1aSopenharmony_ci            for (x = 0; x < 4; x++) {
1232cabdff1aSopenharmony_ci                const uint8_t *ctx;
1233cabdff1aSopenharmony_ci                ctx       = vp8_pred4x4_prob_intra[top[x]][left[y]];
1234cabdff1aSopenharmony_ci                *intra4x4 = vp8_rac_get_tree(c, vp8_pred4x4_tree, ctx);
1235cabdff1aSopenharmony_ci                left[y]   = top[x] = *intra4x4;
1236cabdff1aSopenharmony_ci                intra4x4++;
1237cabdff1aSopenharmony_ci            }
1238cabdff1aSopenharmony_ci        }
1239cabdff1aSopenharmony_ci    } else {
1240cabdff1aSopenharmony_ci        int i;
1241cabdff1aSopenharmony_ci        for (i = 0; i < 16; i++)
1242cabdff1aSopenharmony_ci            intra4x4[i] = vp8_rac_get_tree(c, vp8_pred4x4_tree,
1243cabdff1aSopenharmony_ci                                           vp8_pred4x4_prob_inter);
1244cabdff1aSopenharmony_ci    }
1245cabdff1aSopenharmony_ci}
1246cabdff1aSopenharmony_ci
1247cabdff1aSopenharmony_cistatic av_always_inline
1248cabdff1aSopenharmony_civoid decode_mb_mode(VP8Context *s, VP8mvbounds *mv_bounds,
1249cabdff1aSopenharmony_ci                    VP8Macroblock *mb, int mb_x, int mb_y,
1250cabdff1aSopenharmony_ci                    uint8_t *segment, uint8_t *ref, int layout, int is_vp7)
1251cabdff1aSopenharmony_ci{
1252cabdff1aSopenharmony_ci    VP56RangeCoder *c = &s->c;
1253cabdff1aSopenharmony_ci    static const char * const vp7_feature_name[] = { "q-index",
1254cabdff1aSopenharmony_ci                                                     "lf-delta",
1255cabdff1aSopenharmony_ci                                                     "partial-golden-update",
1256cabdff1aSopenharmony_ci                                                     "blit-pitch" };
1257cabdff1aSopenharmony_ci    if (is_vp7) {
1258cabdff1aSopenharmony_ci        int i;
1259cabdff1aSopenharmony_ci        *segment = 0;
1260cabdff1aSopenharmony_ci        for (i = 0; i < 4; i++) {
1261cabdff1aSopenharmony_ci            if (s->feature_enabled[i]) {
1262cabdff1aSopenharmony_ci                if (vp56_rac_get_prob_branchy(c, s->feature_present_prob[i])) {
1263cabdff1aSopenharmony_ci                      int index = vp8_rac_get_tree(c, vp7_feature_index_tree,
1264cabdff1aSopenharmony_ci                                                   s->feature_index_prob[i]);
1265cabdff1aSopenharmony_ci                      av_log(s->avctx, AV_LOG_WARNING,
1266cabdff1aSopenharmony_ci                             "Feature %s present in macroblock (value 0x%x)\n",
1267cabdff1aSopenharmony_ci                             vp7_feature_name[i], s->feature_value[i][index]);
1268cabdff1aSopenharmony_ci                }
1269cabdff1aSopenharmony_ci           }
1270cabdff1aSopenharmony_ci        }
1271cabdff1aSopenharmony_ci    } else if (s->segmentation.update_map) {
1272cabdff1aSopenharmony_ci        int bit  = vp56_rac_get_prob(c, s->prob->segmentid[0]);
1273cabdff1aSopenharmony_ci        *segment = vp56_rac_get_prob(c, s->prob->segmentid[1+bit]) + 2*bit;
1274cabdff1aSopenharmony_ci    } else if (s->segmentation.enabled)
1275cabdff1aSopenharmony_ci        *segment = ref ? *ref : *segment;
1276cabdff1aSopenharmony_ci    mb->segment = *segment;
1277cabdff1aSopenharmony_ci
1278cabdff1aSopenharmony_ci    mb->skip = s->mbskip_enabled ? vp56_rac_get_prob(c, s->prob->mbskip) : 0;
1279cabdff1aSopenharmony_ci
1280cabdff1aSopenharmony_ci    if (s->keyframe) {
1281cabdff1aSopenharmony_ci        mb->mode = vp8_rac_get_tree(c, vp8_pred16x16_tree_intra,
1282cabdff1aSopenharmony_ci                                    vp8_pred16x16_prob_intra);
1283cabdff1aSopenharmony_ci
1284cabdff1aSopenharmony_ci        if (mb->mode == MODE_I4x4) {
1285cabdff1aSopenharmony_ci            decode_intra4x4_modes(s, c, mb, mb_x, 1, layout);
1286cabdff1aSopenharmony_ci        } else {
1287cabdff1aSopenharmony_ci            const uint32_t modes = (is_vp7 ? vp7_pred4x4_mode
1288cabdff1aSopenharmony_ci                                           : vp8_pred4x4_mode)[mb->mode] * 0x01010101u;
1289cabdff1aSopenharmony_ci            if (s->mb_layout)
1290cabdff1aSopenharmony_ci                AV_WN32A(mb->intra4x4_pred_mode_top, modes);
1291cabdff1aSopenharmony_ci            else
1292cabdff1aSopenharmony_ci                AV_WN32A(s->intra4x4_pred_mode_top + 4 * mb_x, modes);
1293cabdff1aSopenharmony_ci            AV_WN32A(s->intra4x4_pred_mode_left, modes);
1294cabdff1aSopenharmony_ci        }
1295cabdff1aSopenharmony_ci
1296cabdff1aSopenharmony_ci        mb->chroma_pred_mode = vp8_rac_get_tree(c, vp8_pred8x8c_tree,
1297cabdff1aSopenharmony_ci                                                vp8_pred8x8c_prob_intra);
1298cabdff1aSopenharmony_ci        mb->ref_frame        = VP56_FRAME_CURRENT;
1299cabdff1aSopenharmony_ci    } else if (vp56_rac_get_prob_branchy(c, s->prob->intra)) {
1300cabdff1aSopenharmony_ci        // inter MB, 16.2
1301cabdff1aSopenharmony_ci        if (vp56_rac_get_prob_branchy(c, s->prob->last))
1302cabdff1aSopenharmony_ci            mb->ref_frame =
1303cabdff1aSopenharmony_ci                (!is_vp7 && vp56_rac_get_prob(c, s->prob->golden)) ? VP56_FRAME_GOLDEN2 /* altref */
1304cabdff1aSopenharmony_ci                                                                   : VP56_FRAME_GOLDEN;
1305cabdff1aSopenharmony_ci        else
1306cabdff1aSopenharmony_ci            mb->ref_frame = VP56_FRAME_PREVIOUS;
1307cabdff1aSopenharmony_ci        s->ref_count[mb->ref_frame - 1]++;
1308cabdff1aSopenharmony_ci
1309cabdff1aSopenharmony_ci        // motion vectors, 16.3
1310cabdff1aSopenharmony_ci        if (is_vp7)
1311cabdff1aSopenharmony_ci            vp7_decode_mvs(s, mb, mb_x, mb_y, layout);
1312cabdff1aSopenharmony_ci        else
1313cabdff1aSopenharmony_ci            vp8_decode_mvs(s, mv_bounds, mb, mb_x, mb_y, layout);
1314cabdff1aSopenharmony_ci    } else {
1315cabdff1aSopenharmony_ci        // intra MB, 16.1
1316cabdff1aSopenharmony_ci        mb->mode = vp8_rac_get_tree(c, vp8_pred16x16_tree_inter, s->prob->pred16x16);
1317cabdff1aSopenharmony_ci
1318cabdff1aSopenharmony_ci        if (mb->mode == MODE_I4x4)
1319cabdff1aSopenharmony_ci            decode_intra4x4_modes(s, c, mb, mb_x, 0, layout);
1320cabdff1aSopenharmony_ci
1321cabdff1aSopenharmony_ci        mb->chroma_pred_mode = vp8_rac_get_tree(c, vp8_pred8x8c_tree,
1322cabdff1aSopenharmony_ci                                                s->prob->pred8x8c);
1323cabdff1aSopenharmony_ci        mb->ref_frame        = VP56_FRAME_CURRENT;
1324cabdff1aSopenharmony_ci        mb->partitioning     = VP8_SPLITMVMODE_NONE;
1325cabdff1aSopenharmony_ci        AV_ZERO32(&mb->bmv[0]);
1326cabdff1aSopenharmony_ci    }
1327cabdff1aSopenharmony_ci}
1328cabdff1aSopenharmony_ci
1329cabdff1aSopenharmony_ci/**
1330cabdff1aSopenharmony_ci * @param r     arithmetic bitstream reader context
1331cabdff1aSopenharmony_ci * @param block destination for block coefficients
1332cabdff1aSopenharmony_ci * @param probs probabilities to use when reading trees from the bitstream
1333cabdff1aSopenharmony_ci * @param i     initial coeff index, 0 unless a separate DC block is coded
1334cabdff1aSopenharmony_ci * @param qmul  array holding the dc/ac dequant factor at position 0/1
1335cabdff1aSopenharmony_ci *
1336cabdff1aSopenharmony_ci * @return 0 if no coeffs were decoded
1337cabdff1aSopenharmony_ci *         otherwise, the index of the last coeff decoded plus one
1338cabdff1aSopenharmony_ci */
1339cabdff1aSopenharmony_cistatic av_always_inline
1340cabdff1aSopenharmony_ciint decode_block_coeffs_internal(VP56RangeCoder *r, int16_t block[16],
1341cabdff1aSopenharmony_ci                                 uint8_t probs[16][3][NUM_DCT_TOKENS - 1],
1342cabdff1aSopenharmony_ci                                 int i, uint8_t *token_prob, int16_t qmul[2],
1343cabdff1aSopenharmony_ci                                 const uint8_t scan[16], int vp7)
1344cabdff1aSopenharmony_ci{
1345cabdff1aSopenharmony_ci    VP56RangeCoder c = *r;
1346cabdff1aSopenharmony_ci    goto skip_eob;
1347cabdff1aSopenharmony_ci    do {
1348cabdff1aSopenharmony_ci        int coeff;
1349cabdff1aSopenharmony_cirestart:
1350cabdff1aSopenharmony_ci        if (!vp56_rac_get_prob_branchy(&c, token_prob[0]))   // DCT_EOB
1351cabdff1aSopenharmony_ci            break;
1352cabdff1aSopenharmony_ci
1353cabdff1aSopenharmony_ciskip_eob:
1354cabdff1aSopenharmony_ci        if (!vp56_rac_get_prob_branchy(&c, token_prob[1])) { // DCT_0
1355cabdff1aSopenharmony_ci            if (++i == 16)
1356cabdff1aSopenharmony_ci                break; // invalid input; blocks should end with EOB
1357cabdff1aSopenharmony_ci            token_prob = probs[i][0];
1358cabdff1aSopenharmony_ci            if (vp7)
1359cabdff1aSopenharmony_ci                goto restart;
1360cabdff1aSopenharmony_ci            goto skip_eob;
1361cabdff1aSopenharmony_ci        }
1362cabdff1aSopenharmony_ci
1363cabdff1aSopenharmony_ci        if (!vp56_rac_get_prob_branchy(&c, token_prob[2])) { // DCT_1
1364cabdff1aSopenharmony_ci            coeff = 1;
1365cabdff1aSopenharmony_ci            token_prob = probs[i + 1][1];
1366cabdff1aSopenharmony_ci        } else {
1367cabdff1aSopenharmony_ci            if (!vp56_rac_get_prob_branchy(&c, token_prob[3])) { // DCT 2,3,4
1368cabdff1aSopenharmony_ci                coeff = vp56_rac_get_prob_branchy(&c, token_prob[4]);
1369cabdff1aSopenharmony_ci                if (coeff)
1370cabdff1aSopenharmony_ci                    coeff += vp56_rac_get_prob(&c, token_prob[5]);
1371cabdff1aSopenharmony_ci                coeff += 2;
1372cabdff1aSopenharmony_ci            } else {
1373cabdff1aSopenharmony_ci                // DCT_CAT*
1374cabdff1aSopenharmony_ci                if (!vp56_rac_get_prob_branchy(&c, token_prob[6])) {
1375cabdff1aSopenharmony_ci                    if (!vp56_rac_get_prob_branchy(&c, token_prob[7])) { // DCT_CAT1
1376cabdff1aSopenharmony_ci                        coeff = 5 + vp56_rac_get_prob(&c, vp8_dct_cat1_prob[0]);
1377cabdff1aSopenharmony_ci                    } else {                                    // DCT_CAT2
1378cabdff1aSopenharmony_ci                        coeff  = 7;
1379cabdff1aSopenharmony_ci                        coeff += vp56_rac_get_prob(&c, vp8_dct_cat2_prob[0]) << 1;
1380cabdff1aSopenharmony_ci                        coeff += vp56_rac_get_prob(&c, vp8_dct_cat2_prob[1]);
1381cabdff1aSopenharmony_ci                    }
1382cabdff1aSopenharmony_ci                } else {    // DCT_CAT3 and up
1383cabdff1aSopenharmony_ci                    int a   = vp56_rac_get_prob(&c, token_prob[8]);
1384cabdff1aSopenharmony_ci                    int b   = vp56_rac_get_prob(&c, token_prob[9 + a]);
1385cabdff1aSopenharmony_ci                    int cat = (a << 1) + b;
1386cabdff1aSopenharmony_ci                    coeff  = 3 + (8 << cat);
1387cabdff1aSopenharmony_ci                    coeff += vp8_rac_get_coeff(&c, ff_vp8_dct_cat_prob[cat]);
1388cabdff1aSopenharmony_ci                }
1389cabdff1aSopenharmony_ci            }
1390cabdff1aSopenharmony_ci            token_prob = probs[i + 1][2];
1391cabdff1aSopenharmony_ci        }
1392cabdff1aSopenharmony_ci        block[scan[i]] = (vp8_rac_get(&c) ? -coeff : coeff) * qmul[!!i];
1393cabdff1aSopenharmony_ci    } while (++i < 16);
1394cabdff1aSopenharmony_ci
1395cabdff1aSopenharmony_ci    *r = c;
1396cabdff1aSopenharmony_ci    return i;
1397cabdff1aSopenharmony_ci}
1398cabdff1aSopenharmony_ci
1399cabdff1aSopenharmony_cistatic av_always_inline
1400cabdff1aSopenharmony_ciint inter_predict_dc(int16_t block[16], int16_t pred[2])
1401cabdff1aSopenharmony_ci{
1402cabdff1aSopenharmony_ci    int16_t dc = block[0];
1403cabdff1aSopenharmony_ci    int ret = 0;
1404cabdff1aSopenharmony_ci
1405cabdff1aSopenharmony_ci    if (pred[1] > 3) {
1406cabdff1aSopenharmony_ci        dc += pred[0];
1407cabdff1aSopenharmony_ci        ret = 1;
1408cabdff1aSopenharmony_ci    }
1409cabdff1aSopenharmony_ci
1410cabdff1aSopenharmony_ci    if (!pred[0] | !dc | ((int32_t)pred[0] ^ (int32_t)dc) >> 31) {
1411cabdff1aSopenharmony_ci        block[0] = pred[0] = dc;
1412cabdff1aSopenharmony_ci        pred[1] = 0;
1413cabdff1aSopenharmony_ci    } else {
1414cabdff1aSopenharmony_ci        if (pred[0] == dc)
1415cabdff1aSopenharmony_ci            pred[1]++;
1416cabdff1aSopenharmony_ci        block[0] = pred[0] = dc;
1417cabdff1aSopenharmony_ci    }
1418cabdff1aSopenharmony_ci
1419cabdff1aSopenharmony_ci    return ret;
1420cabdff1aSopenharmony_ci}
1421cabdff1aSopenharmony_ci
1422cabdff1aSopenharmony_cistatic int vp7_decode_block_coeffs_internal(VP56RangeCoder *r,
1423cabdff1aSopenharmony_ci                                            int16_t block[16],
1424cabdff1aSopenharmony_ci                                            uint8_t probs[16][3][NUM_DCT_TOKENS - 1],
1425cabdff1aSopenharmony_ci                                            int i, uint8_t *token_prob,
1426cabdff1aSopenharmony_ci                                            int16_t qmul[2],
1427cabdff1aSopenharmony_ci                                            const uint8_t scan[16])
1428cabdff1aSopenharmony_ci{
1429cabdff1aSopenharmony_ci    return decode_block_coeffs_internal(r, block, probs, i,
1430cabdff1aSopenharmony_ci                                        token_prob, qmul, scan, IS_VP7);
1431cabdff1aSopenharmony_ci}
1432cabdff1aSopenharmony_ci
1433cabdff1aSopenharmony_ci#ifndef vp8_decode_block_coeffs_internal
1434cabdff1aSopenharmony_cistatic int vp8_decode_block_coeffs_internal(VP56RangeCoder *r,
1435cabdff1aSopenharmony_ci                                            int16_t block[16],
1436cabdff1aSopenharmony_ci                                            uint8_t probs[16][3][NUM_DCT_TOKENS - 1],
1437cabdff1aSopenharmony_ci                                            int i, uint8_t *token_prob,
1438cabdff1aSopenharmony_ci                                            int16_t qmul[2])
1439cabdff1aSopenharmony_ci{
1440cabdff1aSopenharmony_ci    return decode_block_coeffs_internal(r, block, probs, i,
1441cabdff1aSopenharmony_ci                                        token_prob, qmul, ff_zigzag_scan, IS_VP8);
1442cabdff1aSopenharmony_ci}
1443cabdff1aSopenharmony_ci#endif
1444cabdff1aSopenharmony_ci
1445cabdff1aSopenharmony_ci/**
1446cabdff1aSopenharmony_ci * @param c          arithmetic bitstream reader context
1447cabdff1aSopenharmony_ci * @param block      destination for block coefficients
1448cabdff1aSopenharmony_ci * @param probs      probabilities to use when reading trees from the bitstream
1449cabdff1aSopenharmony_ci * @param i          initial coeff index, 0 unless a separate DC block is coded
1450cabdff1aSopenharmony_ci * @param zero_nhood the initial prediction context for number of surrounding
1451cabdff1aSopenharmony_ci *                   all-zero blocks (only left/top, so 0-2)
1452cabdff1aSopenharmony_ci * @param qmul       array holding the dc/ac dequant factor at position 0/1
1453cabdff1aSopenharmony_ci * @param scan       scan pattern (VP7 only)
1454cabdff1aSopenharmony_ci *
1455cabdff1aSopenharmony_ci * @return 0 if no coeffs were decoded
1456cabdff1aSopenharmony_ci *         otherwise, the index of the last coeff decoded plus one
1457cabdff1aSopenharmony_ci */
1458cabdff1aSopenharmony_cistatic av_always_inline
1459cabdff1aSopenharmony_ciint decode_block_coeffs(VP56RangeCoder *c, int16_t block[16],
1460cabdff1aSopenharmony_ci                        uint8_t probs[16][3][NUM_DCT_TOKENS - 1],
1461cabdff1aSopenharmony_ci                        int i, int zero_nhood, int16_t qmul[2],
1462cabdff1aSopenharmony_ci                        const uint8_t scan[16], int vp7)
1463cabdff1aSopenharmony_ci{
1464cabdff1aSopenharmony_ci    uint8_t *token_prob = probs[i][zero_nhood];
1465cabdff1aSopenharmony_ci    if (!vp56_rac_get_prob_branchy(c, token_prob[0]))   // DCT_EOB
1466cabdff1aSopenharmony_ci        return 0;
1467cabdff1aSopenharmony_ci    return vp7 ? vp7_decode_block_coeffs_internal(c, block, probs, i,
1468cabdff1aSopenharmony_ci                                                  token_prob, qmul, scan)
1469cabdff1aSopenharmony_ci               : vp8_decode_block_coeffs_internal(c, block, probs, i,
1470cabdff1aSopenharmony_ci                                                  token_prob, qmul);
1471cabdff1aSopenharmony_ci}
1472cabdff1aSopenharmony_ci
1473cabdff1aSopenharmony_cistatic av_always_inline
1474cabdff1aSopenharmony_civoid decode_mb_coeffs(VP8Context *s, VP8ThreadData *td, VP56RangeCoder *c,
1475cabdff1aSopenharmony_ci                      VP8Macroblock *mb, uint8_t t_nnz[9], uint8_t l_nnz[9],
1476cabdff1aSopenharmony_ci                      int is_vp7)
1477cabdff1aSopenharmony_ci{
1478cabdff1aSopenharmony_ci    int i, x, y, luma_start = 0, luma_ctx = 3;
1479cabdff1aSopenharmony_ci    int nnz_pred, nnz, nnz_total = 0;
1480cabdff1aSopenharmony_ci    int segment = mb->segment;
1481cabdff1aSopenharmony_ci    int block_dc = 0;
1482cabdff1aSopenharmony_ci
1483cabdff1aSopenharmony_ci    if (mb->mode != MODE_I4x4 && (is_vp7 || mb->mode != VP8_MVMODE_SPLIT)) {
1484cabdff1aSopenharmony_ci        nnz_pred = t_nnz[8] + l_nnz[8];
1485cabdff1aSopenharmony_ci
1486cabdff1aSopenharmony_ci        // decode DC values and do hadamard
1487cabdff1aSopenharmony_ci        nnz = decode_block_coeffs(c, td->block_dc, s->prob->token[1], 0,
1488cabdff1aSopenharmony_ci                                  nnz_pred, s->qmat[segment].luma_dc_qmul,
1489cabdff1aSopenharmony_ci                                  ff_zigzag_scan, is_vp7);
1490cabdff1aSopenharmony_ci        l_nnz[8] = t_nnz[8] = !!nnz;
1491cabdff1aSopenharmony_ci
1492cabdff1aSopenharmony_ci        if (is_vp7 && mb->mode > MODE_I4x4) {
1493cabdff1aSopenharmony_ci            nnz |=  inter_predict_dc(td->block_dc,
1494cabdff1aSopenharmony_ci                                     s->inter_dc_pred[mb->ref_frame - 1]);
1495cabdff1aSopenharmony_ci        }
1496cabdff1aSopenharmony_ci
1497cabdff1aSopenharmony_ci        if (nnz) {
1498cabdff1aSopenharmony_ci            nnz_total += nnz;
1499cabdff1aSopenharmony_ci            block_dc   = 1;
1500cabdff1aSopenharmony_ci            if (nnz == 1)
1501cabdff1aSopenharmony_ci                s->vp8dsp.vp8_luma_dc_wht_dc(td->block, td->block_dc);
1502cabdff1aSopenharmony_ci            else
1503cabdff1aSopenharmony_ci                s->vp8dsp.vp8_luma_dc_wht(td->block, td->block_dc);
1504cabdff1aSopenharmony_ci        }
1505cabdff1aSopenharmony_ci        luma_start = 1;
1506cabdff1aSopenharmony_ci        luma_ctx   = 0;
1507cabdff1aSopenharmony_ci    }
1508cabdff1aSopenharmony_ci
1509cabdff1aSopenharmony_ci    // luma blocks
1510cabdff1aSopenharmony_ci    for (y = 0; y < 4; y++)
1511cabdff1aSopenharmony_ci        for (x = 0; x < 4; x++) {
1512cabdff1aSopenharmony_ci            nnz_pred = l_nnz[y] + t_nnz[x];
1513cabdff1aSopenharmony_ci            nnz = decode_block_coeffs(c, td->block[y][x],
1514cabdff1aSopenharmony_ci                                      s->prob->token[luma_ctx],
1515cabdff1aSopenharmony_ci                                      luma_start, nnz_pred,
1516cabdff1aSopenharmony_ci                                      s->qmat[segment].luma_qmul,
1517cabdff1aSopenharmony_ci                                      s->prob[0].scan, is_vp7);
1518cabdff1aSopenharmony_ci            /* nnz+block_dc may be one more than the actual last index,
1519cabdff1aSopenharmony_ci             * but we don't care */
1520cabdff1aSopenharmony_ci            td->non_zero_count_cache[y][x] = nnz + block_dc;
1521cabdff1aSopenharmony_ci            t_nnz[x] = l_nnz[y] = !!nnz;
1522cabdff1aSopenharmony_ci            nnz_total += nnz;
1523cabdff1aSopenharmony_ci        }
1524cabdff1aSopenharmony_ci
1525cabdff1aSopenharmony_ci    // chroma blocks
1526cabdff1aSopenharmony_ci    // TODO: what to do about dimensions? 2nd dim for luma is x,
1527cabdff1aSopenharmony_ci    // but for chroma it's (y<<1)|x
1528cabdff1aSopenharmony_ci    for (i = 4; i < 6; i++)
1529cabdff1aSopenharmony_ci        for (y = 0; y < 2; y++)
1530cabdff1aSopenharmony_ci            for (x = 0; x < 2; x++) {
1531cabdff1aSopenharmony_ci                nnz_pred = l_nnz[i + 2 * y] + t_nnz[i + 2 * x];
1532cabdff1aSopenharmony_ci                nnz = decode_block_coeffs(c, td->block[i][(y << 1) + x],
1533cabdff1aSopenharmony_ci                                          s->prob->token[2], 0, nnz_pred,
1534cabdff1aSopenharmony_ci                                          s->qmat[segment].chroma_qmul,
1535cabdff1aSopenharmony_ci                                          s->prob[0].scan, is_vp7);
1536cabdff1aSopenharmony_ci                td->non_zero_count_cache[i][(y << 1) + x] = nnz;
1537cabdff1aSopenharmony_ci                t_nnz[i + 2 * x] = l_nnz[i + 2 * y] = !!nnz;
1538cabdff1aSopenharmony_ci                nnz_total += nnz;
1539cabdff1aSopenharmony_ci            }
1540cabdff1aSopenharmony_ci
1541cabdff1aSopenharmony_ci    // if there were no coded coeffs despite the macroblock not being marked skip,
1542cabdff1aSopenharmony_ci    // we MUST not do the inner loop filter and should not do IDCT
1543cabdff1aSopenharmony_ci    // Since skip isn't used for bitstream prediction, just manually set it.
1544cabdff1aSopenharmony_ci    if (!nnz_total)
1545cabdff1aSopenharmony_ci        mb->skip = 1;
1546cabdff1aSopenharmony_ci}
1547cabdff1aSopenharmony_ci
1548cabdff1aSopenharmony_cistatic av_always_inline
1549cabdff1aSopenharmony_civoid backup_mb_border(uint8_t *top_border, uint8_t *src_y,
1550cabdff1aSopenharmony_ci                      uint8_t *src_cb, uint8_t *src_cr,
1551cabdff1aSopenharmony_ci                      ptrdiff_t linesize, ptrdiff_t uvlinesize, int simple)
1552cabdff1aSopenharmony_ci{
1553cabdff1aSopenharmony_ci    AV_COPY128(top_border, src_y + 15 * linesize);
1554cabdff1aSopenharmony_ci    if (!simple) {
1555cabdff1aSopenharmony_ci        AV_COPY64(top_border + 16, src_cb + 7 * uvlinesize);
1556cabdff1aSopenharmony_ci        AV_COPY64(top_border + 24, src_cr + 7 * uvlinesize);
1557cabdff1aSopenharmony_ci    }
1558cabdff1aSopenharmony_ci}
1559cabdff1aSopenharmony_ci
1560cabdff1aSopenharmony_cistatic av_always_inline
1561cabdff1aSopenharmony_civoid xchg_mb_border(uint8_t *top_border, uint8_t *src_y, uint8_t *src_cb,
1562cabdff1aSopenharmony_ci                    uint8_t *src_cr, ptrdiff_t linesize, ptrdiff_t uvlinesize, int mb_x,
1563cabdff1aSopenharmony_ci                    int mb_y, int mb_width, int simple, int xchg)
1564cabdff1aSopenharmony_ci{
1565cabdff1aSopenharmony_ci    uint8_t *top_border_m1 = top_border - 32;     // for TL prediction
1566cabdff1aSopenharmony_ci    src_y  -= linesize;
1567cabdff1aSopenharmony_ci    src_cb -= uvlinesize;
1568cabdff1aSopenharmony_ci    src_cr -= uvlinesize;
1569cabdff1aSopenharmony_ci
1570cabdff1aSopenharmony_ci#define XCHG(a, b, xchg)                                                      \
1571cabdff1aSopenharmony_ci    do {                                                                      \
1572cabdff1aSopenharmony_ci        if (xchg)                                                             \
1573cabdff1aSopenharmony_ci            AV_SWAP64(b, a);                                                  \
1574cabdff1aSopenharmony_ci        else                                                                  \
1575cabdff1aSopenharmony_ci            AV_COPY64(b, a);                                                  \
1576cabdff1aSopenharmony_ci    } while (0)
1577cabdff1aSopenharmony_ci
1578cabdff1aSopenharmony_ci    XCHG(top_border_m1 + 8, src_y - 8, xchg);
1579cabdff1aSopenharmony_ci    XCHG(top_border, src_y, xchg);
1580cabdff1aSopenharmony_ci    XCHG(top_border + 8, src_y + 8, 1);
1581cabdff1aSopenharmony_ci    if (mb_x < mb_width - 1)
1582cabdff1aSopenharmony_ci        XCHG(top_border + 32, src_y + 16, 1);
1583cabdff1aSopenharmony_ci
1584cabdff1aSopenharmony_ci    // only copy chroma for normal loop filter
1585cabdff1aSopenharmony_ci    // or to initialize the top row to 127
1586cabdff1aSopenharmony_ci    if (!simple || !mb_y) {
1587cabdff1aSopenharmony_ci        XCHG(top_border_m1 + 16, src_cb - 8, xchg);
1588cabdff1aSopenharmony_ci        XCHG(top_border_m1 + 24, src_cr - 8, xchg);
1589cabdff1aSopenharmony_ci        XCHG(top_border + 16, src_cb, 1);
1590cabdff1aSopenharmony_ci        XCHG(top_border + 24, src_cr, 1);
1591cabdff1aSopenharmony_ci    }
1592cabdff1aSopenharmony_ci}
1593cabdff1aSopenharmony_ci
1594cabdff1aSopenharmony_cistatic av_always_inline
1595cabdff1aSopenharmony_ciint check_dc_pred8x8_mode(int mode, int mb_x, int mb_y)
1596cabdff1aSopenharmony_ci{
1597cabdff1aSopenharmony_ci    if (!mb_x)
1598cabdff1aSopenharmony_ci        return mb_y ? TOP_DC_PRED8x8 : DC_128_PRED8x8;
1599cabdff1aSopenharmony_ci    else
1600cabdff1aSopenharmony_ci        return mb_y ? mode : LEFT_DC_PRED8x8;
1601cabdff1aSopenharmony_ci}
1602cabdff1aSopenharmony_ci
1603cabdff1aSopenharmony_cistatic av_always_inline
1604cabdff1aSopenharmony_ciint check_tm_pred8x8_mode(int mode, int mb_x, int mb_y, int vp7)
1605cabdff1aSopenharmony_ci{
1606cabdff1aSopenharmony_ci    if (!mb_x)
1607cabdff1aSopenharmony_ci        return mb_y ? VERT_PRED8x8 : (vp7 ? DC_128_PRED8x8 : DC_129_PRED8x8);
1608cabdff1aSopenharmony_ci    else
1609cabdff1aSopenharmony_ci        return mb_y ? mode : HOR_PRED8x8;
1610cabdff1aSopenharmony_ci}
1611cabdff1aSopenharmony_ci
1612cabdff1aSopenharmony_cistatic av_always_inline
1613cabdff1aSopenharmony_ciint check_intra_pred8x8_mode_emuedge(int mode, int mb_x, int mb_y, int vp7)
1614cabdff1aSopenharmony_ci{
1615cabdff1aSopenharmony_ci    switch (mode) {
1616cabdff1aSopenharmony_ci    case DC_PRED8x8:
1617cabdff1aSopenharmony_ci        return check_dc_pred8x8_mode(mode, mb_x, mb_y);
1618cabdff1aSopenharmony_ci    case VERT_PRED8x8:
1619cabdff1aSopenharmony_ci        return !mb_y ? (vp7 ? DC_128_PRED8x8 : DC_127_PRED8x8) : mode;
1620cabdff1aSopenharmony_ci    case HOR_PRED8x8:
1621cabdff1aSopenharmony_ci        return !mb_x ? (vp7 ? DC_128_PRED8x8 : DC_129_PRED8x8) : mode;
1622cabdff1aSopenharmony_ci    case PLANE_PRED8x8: /* TM */
1623cabdff1aSopenharmony_ci        return check_tm_pred8x8_mode(mode, mb_x, mb_y, vp7);
1624cabdff1aSopenharmony_ci    }
1625cabdff1aSopenharmony_ci    return mode;
1626cabdff1aSopenharmony_ci}
1627cabdff1aSopenharmony_ci
1628cabdff1aSopenharmony_cistatic av_always_inline
1629cabdff1aSopenharmony_ciint check_tm_pred4x4_mode(int mode, int mb_x, int mb_y, int vp7)
1630cabdff1aSopenharmony_ci{
1631cabdff1aSopenharmony_ci    if (!mb_x) {
1632cabdff1aSopenharmony_ci        return mb_y ? VERT_VP8_PRED : (vp7 ? DC_128_PRED : DC_129_PRED);
1633cabdff1aSopenharmony_ci    } else {
1634cabdff1aSopenharmony_ci        return mb_y ? mode : HOR_VP8_PRED;
1635cabdff1aSopenharmony_ci    }
1636cabdff1aSopenharmony_ci}
1637cabdff1aSopenharmony_ci
1638cabdff1aSopenharmony_cistatic av_always_inline
1639cabdff1aSopenharmony_ciint check_intra_pred4x4_mode_emuedge(int mode, int mb_x, int mb_y,
1640cabdff1aSopenharmony_ci                                     int *copy_buf, int vp7)
1641cabdff1aSopenharmony_ci{
1642cabdff1aSopenharmony_ci    switch (mode) {
1643cabdff1aSopenharmony_ci    case VERT_PRED:
1644cabdff1aSopenharmony_ci        if (!mb_x && mb_y) {
1645cabdff1aSopenharmony_ci            *copy_buf = 1;
1646cabdff1aSopenharmony_ci            return mode;
1647cabdff1aSopenharmony_ci        }
1648cabdff1aSopenharmony_ci        /* fall-through */
1649cabdff1aSopenharmony_ci    case DIAG_DOWN_LEFT_PRED:
1650cabdff1aSopenharmony_ci    case VERT_LEFT_PRED:
1651cabdff1aSopenharmony_ci        return !mb_y ? (vp7 ? DC_128_PRED : DC_127_PRED) : mode;
1652cabdff1aSopenharmony_ci    case HOR_PRED:
1653cabdff1aSopenharmony_ci        if (!mb_y) {
1654cabdff1aSopenharmony_ci            *copy_buf = 1;
1655cabdff1aSopenharmony_ci            return mode;
1656cabdff1aSopenharmony_ci        }
1657cabdff1aSopenharmony_ci        /* fall-through */
1658cabdff1aSopenharmony_ci    case HOR_UP_PRED:
1659cabdff1aSopenharmony_ci        return !mb_x ? (vp7 ? DC_128_PRED : DC_129_PRED) : mode;
1660cabdff1aSopenharmony_ci    case TM_VP8_PRED:
1661cabdff1aSopenharmony_ci        return check_tm_pred4x4_mode(mode, mb_x, mb_y, vp7);
1662cabdff1aSopenharmony_ci    case DC_PRED: /* 4x4 DC doesn't use the same "H.264-style" exceptions
1663cabdff1aSopenharmony_ci                   * as 16x16/8x8 DC */
1664cabdff1aSopenharmony_ci    case DIAG_DOWN_RIGHT_PRED:
1665cabdff1aSopenharmony_ci    case VERT_RIGHT_PRED:
1666cabdff1aSopenharmony_ci    case HOR_DOWN_PRED:
1667cabdff1aSopenharmony_ci        if (!mb_y || !mb_x)
1668cabdff1aSopenharmony_ci            *copy_buf = 1;
1669cabdff1aSopenharmony_ci        return mode;
1670cabdff1aSopenharmony_ci    }
1671cabdff1aSopenharmony_ci    return mode;
1672cabdff1aSopenharmony_ci}
1673cabdff1aSopenharmony_ci
1674cabdff1aSopenharmony_cistatic av_always_inline
1675cabdff1aSopenharmony_civoid intra_predict(VP8Context *s, VP8ThreadData *td, uint8_t *dst[3],
1676cabdff1aSopenharmony_ci                   VP8Macroblock *mb, int mb_x, int mb_y, int is_vp7)
1677cabdff1aSopenharmony_ci{
1678cabdff1aSopenharmony_ci    int x, y, mode, nnz;
1679cabdff1aSopenharmony_ci    uint32_t tr;
1680cabdff1aSopenharmony_ci
1681cabdff1aSopenharmony_ci    /* for the first row, we need to run xchg_mb_border to init the top edge
1682cabdff1aSopenharmony_ci     * to 127 otherwise, skip it if we aren't going to deblock */
1683cabdff1aSopenharmony_ci    if (mb_y && (s->deblock_filter || !mb_y) && td->thread_nr == 0)
1684cabdff1aSopenharmony_ci        xchg_mb_border(s->top_border[mb_x + 1], dst[0], dst[1], dst[2],
1685cabdff1aSopenharmony_ci                       s->linesize, s->uvlinesize, mb_x, mb_y, s->mb_width,
1686cabdff1aSopenharmony_ci                       s->filter.simple, 1);
1687cabdff1aSopenharmony_ci
1688cabdff1aSopenharmony_ci    if (mb->mode < MODE_I4x4) {
1689cabdff1aSopenharmony_ci        mode = check_intra_pred8x8_mode_emuedge(mb->mode, mb_x, mb_y, is_vp7);
1690cabdff1aSopenharmony_ci        s->hpc.pred16x16[mode](dst[0], s->linesize);
1691cabdff1aSopenharmony_ci    } else {
1692cabdff1aSopenharmony_ci        uint8_t *ptr = dst[0];
1693cabdff1aSopenharmony_ci        uint8_t *intra4x4 = mb->intra4x4_pred_mode_mb;
1694cabdff1aSopenharmony_ci        const uint8_t lo = is_vp7 ? 128 : 127;
1695cabdff1aSopenharmony_ci        const uint8_t hi = is_vp7 ? 128 : 129;
1696cabdff1aSopenharmony_ci        uint8_t tr_top[4] = { lo, lo, lo, lo };
1697cabdff1aSopenharmony_ci
1698cabdff1aSopenharmony_ci        // all blocks on the right edge of the macroblock use bottom edge
1699cabdff1aSopenharmony_ci        // the top macroblock for their topright edge
1700cabdff1aSopenharmony_ci        uint8_t *tr_right = ptr - s->linesize + 16;
1701cabdff1aSopenharmony_ci
1702cabdff1aSopenharmony_ci        // if we're on the right edge of the frame, said edge is extended
1703cabdff1aSopenharmony_ci        // from the top macroblock
1704cabdff1aSopenharmony_ci        if (mb_y && mb_x == s->mb_width - 1) {
1705cabdff1aSopenharmony_ci            tr       = tr_right[-1] * 0x01010101u;
1706cabdff1aSopenharmony_ci            tr_right = (uint8_t *) &tr;
1707cabdff1aSopenharmony_ci        }
1708cabdff1aSopenharmony_ci
1709cabdff1aSopenharmony_ci        if (mb->skip)
1710cabdff1aSopenharmony_ci            AV_ZERO128(td->non_zero_count_cache);
1711cabdff1aSopenharmony_ci
1712cabdff1aSopenharmony_ci        for (y = 0; y < 4; y++) {
1713cabdff1aSopenharmony_ci            uint8_t *topright = ptr + 4 - s->linesize;
1714cabdff1aSopenharmony_ci            for (x = 0; x < 4; x++) {
1715cabdff1aSopenharmony_ci                int copy = 0;
1716cabdff1aSopenharmony_ci                ptrdiff_t linesize = s->linesize;
1717cabdff1aSopenharmony_ci                uint8_t *dst = ptr + 4 * x;
1718cabdff1aSopenharmony_ci                LOCAL_ALIGNED(4, uint8_t, copy_dst, [5 * 8]);
1719cabdff1aSopenharmony_ci
1720cabdff1aSopenharmony_ci                if ((y == 0 || x == 3) && mb_y == 0) {
1721cabdff1aSopenharmony_ci                    topright = tr_top;
1722cabdff1aSopenharmony_ci                } else if (x == 3)
1723cabdff1aSopenharmony_ci                    topright = tr_right;
1724cabdff1aSopenharmony_ci
1725cabdff1aSopenharmony_ci                mode = check_intra_pred4x4_mode_emuedge(intra4x4[x], mb_x + x,
1726cabdff1aSopenharmony_ci                                                        mb_y + y, &copy, is_vp7);
1727cabdff1aSopenharmony_ci                if (copy) {
1728cabdff1aSopenharmony_ci                    dst      = copy_dst + 12;
1729cabdff1aSopenharmony_ci                    linesize = 8;
1730cabdff1aSopenharmony_ci                    if (!(mb_y + y)) {
1731cabdff1aSopenharmony_ci                        copy_dst[3] = lo;
1732cabdff1aSopenharmony_ci                        AV_WN32A(copy_dst + 4, lo * 0x01010101U);
1733cabdff1aSopenharmony_ci                    } else {
1734cabdff1aSopenharmony_ci                        AV_COPY32(copy_dst + 4, ptr + 4 * x - s->linesize);
1735cabdff1aSopenharmony_ci                        if (!(mb_x + x)) {
1736cabdff1aSopenharmony_ci                            copy_dst[3] = hi;
1737cabdff1aSopenharmony_ci                        } else {
1738cabdff1aSopenharmony_ci                            copy_dst[3] = ptr[4 * x - s->linesize - 1];
1739cabdff1aSopenharmony_ci                        }
1740cabdff1aSopenharmony_ci                    }
1741cabdff1aSopenharmony_ci                    if (!(mb_x + x)) {
1742cabdff1aSopenharmony_ci                        copy_dst[11] =
1743cabdff1aSopenharmony_ci                        copy_dst[19] =
1744cabdff1aSopenharmony_ci                        copy_dst[27] =
1745cabdff1aSopenharmony_ci                        copy_dst[35] = hi;
1746cabdff1aSopenharmony_ci                    } else {
1747cabdff1aSopenharmony_ci                        copy_dst[11] = ptr[4 * x                   - 1];
1748cabdff1aSopenharmony_ci                        copy_dst[19] = ptr[4 * x + s->linesize     - 1];
1749cabdff1aSopenharmony_ci                        copy_dst[27] = ptr[4 * x + s->linesize * 2 - 1];
1750cabdff1aSopenharmony_ci                        copy_dst[35] = ptr[4 * x + s->linesize * 3 - 1];
1751cabdff1aSopenharmony_ci                    }
1752cabdff1aSopenharmony_ci                }
1753cabdff1aSopenharmony_ci                s->hpc.pred4x4[mode](dst, topright, linesize);
1754cabdff1aSopenharmony_ci                if (copy) {
1755cabdff1aSopenharmony_ci                    AV_COPY32(ptr + 4 * x,                   copy_dst + 12);
1756cabdff1aSopenharmony_ci                    AV_COPY32(ptr + 4 * x + s->linesize,     copy_dst + 20);
1757cabdff1aSopenharmony_ci                    AV_COPY32(ptr + 4 * x + s->linesize * 2, copy_dst + 28);
1758cabdff1aSopenharmony_ci                    AV_COPY32(ptr + 4 * x + s->linesize * 3, copy_dst + 36);
1759cabdff1aSopenharmony_ci                }
1760cabdff1aSopenharmony_ci
1761cabdff1aSopenharmony_ci                nnz = td->non_zero_count_cache[y][x];
1762cabdff1aSopenharmony_ci                if (nnz) {
1763cabdff1aSopenharmony_ci                    if (nnz == 1)
1764cabdff1aSopenharmony_ci                        s->vp8dsp.vp8_idct_dc_add(ptr + 4 * x,
1765cabdff1aSopenharmony_ci                                                  td->block[y][x], s->linesize);
1766cabdff1aSopenharmony_ci                    else
1767cabdff1aSopenharmony_ci                        s->vp8dsp.vp8_idct_add(ptr + 4 * x,
1768cabdff1aSopenharmony_ci                                               td->block[y][x], s->linesize);
1769cabdff1aSopenharmony_ci                }
1770cabdff1aSopenharmony_ci                topright += 4;
1771cabdff1aSopenharmony_ci            }
1772cabdff1aSopenharmony_ci
1773cabdff1aSopenharmony_ci            ptr      += 4 * s->linesize;
1774cabdff1aSopenharmony_ci            intra4x4 += 4;
1775cabdff1aSopenharmony_ci        }
1776cabdff1aSopenharmony_ci    }
1777cabdff1aSopenharmony_ci
1778cabdff1aSopenharmony_ci    mode = check_intra_pred8x8_mode_emuedge(mb->chroma_pred_mode,
1779cabdff1aSopenharmony_ci                                            mb_x, mb_y, is_vp7);
1780cabdff1aSopenharmony_ci    s->hpc.pred8x8[mode](dst[1], s->uvlinesize);
1781cabdff1aSopenharmony_ci    s->hpc.pred8x8[mode](dst[2], s->uvlinesize);
1782cabdff1aSopenharmony_ci
1783cabdff1aSopenharmony_ci    if (mb_y && (s->deblock_filter || !mb_y) && td->thread_nr == 0)
1784cabdff1aSopenharmony_ci        xchg_mb_border(s->top_border[mb_x + 1], dst[0], dst[1], dst[2],
1785cabdff1aSopenharmony_ci                       s->linesize, s->uvlinesize, mb_x, mb_y, s->mb_width,
1786cabdff1aSopenharmony_ci                       s->filter.simple, 0);
1787cabdff1aSopenharmony_ci}
1788cabdff1aSopenharmony_ci
1789cabdff1aSopenharmony_cistatic const uint8_t subpel_idx[3][8] = {
1790cabdff1aSopenharmony_ci    { 0, 1, 2, 1, 2, 1, 2, 1 }, // nr. of left extra pixels,
1791cabdff1aSopenharmony_ci                                // also function pointer index
1792cabdff1aSopenharmony_ci    { 0, 3, 5, 3, 5, 3, 5, 3 }, // nr. of extra pixels required
1793cabdff1aSopenharmony_ci    { 0, 2, 3, 2, 3, 2, 3, 2 }, // nr. of right extra pixels
1794cabdff1aSopenharmony_ci};
1795cabdff1aSopenharmony_ci
1796cabdff1aSopenharmony_ci/**
1797cabdff1aSopenharmony_ci * luma MC function
1798cabdff1aSopenharmony_ci *
1799cabdff1aSopenharmony_ci * @param s        VP8 decoding context
1800cabdff1aSopenharmony_ci * @param dst      target buffer for block data at block position
1801cabdff1aSopenharmony_ci * @param ref      reference picture buffer at origin (0, 0)
1802cabdff1aSopenharmony_ci * @param mv       motion vector (relative to block position) to get pixel data from
1803cabdff1aSopenharmony_ci * @param x_off    horizontal position of block from origin (0, 0)
1804cabdff1aSopenharmony_ci * @param y_off    vertical position of block from origin (0, 0)
1805cabdff1aSopenharmony_ci * @param block_w  width of block (16, 8 or 4)
1806cabdff1aSopenharmony_ci * @param block_h  height of block (always same as block_w)
1807cabdff1aSopenharmony_ci * @param width    width of src/dst plane data
1808cabdff1aSopenharmony_ci * @param height   height of src/dst plane data
1809cabdff1aSopenharmony_ci * @param linesize size of a single line of plane data, including padding
1810cabdff1aSopenharmony_ci * @param mc_func  motion compensation function pointers (bilinear or sixtap MC)
1811cabdff1aSopenharmony_ci */
1812cabdff1aSopenharmony_cistatic av_always_inline
1813cabdff1aSopenharmony_civoid vp8_mc_luma(VP8Context *s, VP8ThreadData *td, uint8_t *dst,
1814cabdff1aSopenharmony_ci                 ThreadFrame *ref, const VP56mv *mv,
1815cabdff1aSopenharmony_ci                 int x_off, int y_off, int block_w, int block_h,
1816cabdff1aSopenharmony_ci                 int width, int height, ptrdiff_t linesize,
1817cabdff1aSopenharmony_ci                 vp8_mc_func mc_func[3][3])
1818cabdff1aSopenharmony_ci{
1819cabdff1aSopenharmony_ci    uint8_t *src = ref->f->data[0];
1820cabdff1aSopenharmony_ci
1821cabdff1aSopenharmony_ci    if (AV_RN32A(mv)) {
1822cabdff1aSopenharmony_ci        ptrdiff_t src_linesize = linesize;
1823cabdff1aSopenharmony_ci
1824cabdff1aSopenharmony_ci        int mx = (mv->x * 2) & 7, mx_idx = subpel_idx[0][mx];
1825cabdff1aSopenharmony_ci        int my = (mv->y * 2) & 7, my_idx = subpel_idx[0][my];
1826cabdff1aSopenharmony_ci
1827cabdff1aSopenharmony_ci        x_off += mv->x >> 2;
1828cabdff1aSopenharmony_ci        y_off += mv->y >> 2;
1829cabdff1aSopenharmony_ci
1830cabdff1aSopenharmony_ci        // edge emulation
1831cabdff1aSopenharmony_ci        ff_thread_await_progress(ref, (3 + y_off + block_h + subpel_idx[2][my]) >> 4, 0);
1832cabdff1aSopenharmony_ci        src += y_off * linesize + x_off;
1833cabdff1aSopenharmony_ci        if (x_off < mx_idx || x_off >= width  - block_w - subpel_idx[2][mx] ||
1834cabdff1aSopenharmony_ci            y_off < my_idx || y_off >= height - block_h - subpel_idx[2][my]) {
1835cabdff1aSopenharmony_ci            s->vdsp.emulated_edge_mc(td->edge_emu_buffer,
1836cabdff1aSopenharmony_ci                                     src - my_idx * linesize - mx_idx,
1837cabdff1aSopenharmony_ci                                     EDGE_EMU_LINESIZE, linesize,
1838cabdff1aSopenharmony_ci                                     block_w + subpel_idx[1][mx],
1839cabdff1aSopenharmony_ci                                     block_h + subpel_idx[1][my],
1840cabdff1aSopenharmony_ci                                     x_off - mx_idx, y_off - my_idx,
1841cabdff1aSopenharmony_ci                                     width, height);
1842cabdff1aSopenharmony_ci            src = td->edge_emu_buffer + mx_idx + EDGE_EMU_LINESIZE * my_idx;
1843cabdff1aSopenharmony_ci            src_linesize = EDGE_EMU_LINESIZE;
1844cabdff1aSopenharmony_ci        }
1845cabdff1aSopenharmony_ci        mc_func[my_idx][mx_idx](dst, linesize, src, src_linesize, block_h, mx, my);
1846cabdff1aSopenharmony_ci    } else {
1847cabdff1aSopenharmony_ci        ff_thread_await_progress(ref, (3 + y_off + block_h) >> 4, 0);
1848cabdff1aSopenharmony_ci        mc_func[0][0](dst, linesize, src + y_off * linesize + x_off,
1849cabdff1aSopenharmony_ci                      linesize, block_h, 0, 0);
1850cabdff1aSopenharmony_ci    }
1851cabdff1aSopenharmony_ci}
1852cabdff1aSopenharmony_ci
1853cabdff1aSopenharmony_ci/**
1854cabdff1aSopenharmony_ci * chroma MC function
1855cabdff1aSopenharmony_ci *
1856cabdff1aSopenharmony_ci * @param s        VP8 decoding context
1857cabdff1aSopenharmony_ci * @param dst1     target buffer for block data at block position (U plane)
1858cabdff1aSopenharmony_ci * @param dst2     target buffer for block data at block position (V plane)
1859cabdff1aSopenharmony_ci * @param ref      reference picture buffer at origin (0, 0)
1860cabdff1aSopenharmony_ci * @param mv       motion vector (relative to block position) to get pixel data from
1861cabdff1aSopenharmony_ci * @param x_off    horizontal position of block from origin (0, 0)
1862cabdff1aSopenharmony_ci * @param y_off    vertical position of block from origin (0, 0)
1863cabdff1aSopenharmony_ci * @param block_w  width of block (16, 8 or 4)
1864cabdff1aSopenharmony_ci * @param block_h  height of block (always same as block_w)
1865cabdff1aSopenharmony_ci * @param width    width of src/dst plane data
1866cabdff1aSopenharmony_ci * @param height   height of src/dst plane data
1867cabdff1aSopenharmony_ci * @param linesize size of a single line of plane data, including padding
1868cabdff1aSopenharmony_ci * @param mc_func  motion compensation function pointers (bilinear or sixtap MC)
1869cabdff1aSopenharmony_ci */
1870cabdff1aSopenharmony_cistatic av_always_inline
1871cabdff1aSopenharmony_civoid vp8_mc_chroma(VP8Context *s, VP8ThreadData *td, uint8_t *dst1,
1872cabdff1aSopenharmony_ci                   uint8_t *dst2, ThreadFrame *ref, const VP56mv *mv,
1873cabdff1aSopenharmony_ci                   int x_off, int y_off, int block_w, int block_h,
1874cabdff1aSopenharmony_ci                   int width, int height, ptrdiff_t linesize,
1875cabdff1aSopenharmony_ci                   vp8_mc_func mc_func[3][3])
1876cabdff1aSopenharmony_ci{
1877cabdff1aSopenharmony_ci    uint8_t *src1 = ref->f->data[1], *src2 = ref->f->data[2];
1878cabdff1aSopenharmony_ci
1879cabdff1aSopenharmony_ci    if (AV_RN32A(mv)) {
1880cabdff1aSopenharmony_ci        int mx = mv->x & 7, mx_idx = subpel_idx[0][mx];
1881cabdff1aSopenharmony_ci        int my = mv->y & 7, my_idx = subpel_idx[0][my];
1882cabdff1aSopenharmony_ci
1883cabdff1aSopenharmony_ci        x_off += mv->x >> 3;
1884cabdff1aSopenharmony_ci        y_off += mv->y >> 3;
1885cabdff1aSopenharmony_ci
1886cabdff1aSopenharmony_ci        // edge emulation
1887cabdff1aSopenharmony_ci        src1 += y_off * linesize + x_off;
1888cabdff1aSopenharmony_ci        src2 += y_off * linesize + x_off;
1889cabdff1aSopenharmony_ci        ff_thread_await_progress(ref, (3 + y_off + block_h + subpel_idx[2][my]) >> 3, 0);
1890cabdff1aSopenharmony_ci        if (x_off < mx_idx || x_off >= width  - block_w - subpel_idx[2][mx] ||
1891cabdff1aSopenharmony_ci            y_off < my_idx || y_off >= height - block_h - subpel_idx[2][my]) {
1892cabdff1aSopenharmony_ci            s->vdsp.emulated_edge_mc(td->edge_emu_buffer,
1893cabdff1aSopenharmony_ci                                     src1 - my_idx * linesize - mx_idx,
1894cabdff1aSopenharmony_ci                                     EDGE_EMU_LINESIZE, linesize,
1895cabdff1aSopenharmony_ci                                     block_w + subpel_idx[1][mx],
1896cabdff1aSopenharmony_ci                                     block_h + subpel_idx[1][my],
1897cabdff1aSopenharmony_ci                                     x_off - mx_idx, y_off - my_idx, width, height);
1898cabdff1aSopenharmony_ci            src1 = td->edge_emu_buffer + mx_idx + EDGE_EMU_LINESIZE * my_idx;
1899cabdff1aSopenharmony_ci            mc_func[my_idx][mx_idx](dst1, linesize, src1, EDGE_EMU_LINESIZE, block_h, mx, my);
1900cabdff1aSopenharmony_ci
1901cabdff1aSopenharmony_ci            s->vdsp.emulated_edge_mc(td->edge_emu_buffer,
1902cabdff1aSopenharmony_ci                                     src2 - my_idx * linesize - mx_idx,
1903cabdff1aSopenharmony_ci                                     EDGE_EMU_LINESIZE, linesize,
1904cabdff1aSopenharmony_ci                                     block_w + subpel_idx[1][mx],
1905cabdff1aSopenharmony_ci                                     block_h + subpel_idx[1][my],
1906cabdff1aSopenharmony_ci                                     x_off - mx_idx, y_off - my_idx, width, height);
1907cabdff1aSopenharmony_ci            src2 = td->edge_emu_buffer + mx_idx + EDGE_EMU_LINESIZE * my_idx;
1908cabdff1aSopenharmony_ci            mc_func[my_idx][mx_idx](dst2, linesize, src2, EDGE_EMU_LINESIZE, block_h, mx, my);
1909cabdff1aSopenharmony_ci        } else {
1910cabdff1aSopenharmony_ci            mc_func[my_idx][mx_idx](dst1, linesize, src1, linesize, block_h, mx, my);
1911cabdff1aSopenharmony_ci            mc_func[my_idx][mx_idx](dst2, linesize, src2, linesize, block_h, mx, my);
1912cabdff1aSopenharmony_ci        }
1913cabdff1aSopenharmony_ci    } else {
1914cabdff1aSopenharmony_ci        ff_thread_await_progress(ref, (3 + y_off + block_h) >> 3, 0);
1915cabdff1aSopenharmony_ci        mc_func[0][0](dst1, linesize, src1 + y_off * linesize + x_off, linesize, block_h, 0, 0);
1916cabdff1aSopenharmony_ci        mc_func[0][0](dst2, linesize, src2 + y_off * linesize + x_off, linesize, block_h, 0, 0);
1917cabdff1aSopenharmony_ci    }
1918cabdff1aSopenharmony_ci}
1919cabdff1aSopenharmony_ci
1920cabdff1aSopenharmony_cistatic av_always_inline
1921cabdff1aSopenharmony_civoid vp8_mc_part(VP8Context *s, VP8ThreadData *td, uint8_t *dst[3],
1922cabdff1aSopenharmony_ci                 ThreadFrame *ref_frame, int x_off, int y_off,
1923cabdff1aSopenharmony_ci                 int bx_off, int by_off, int block_w, int block_h,
1924cabdff1aSopenharmony_ci                 int width, int height, VP56mv *mv)
1925cabdff1aSopenharmony_ci{
1926cabdff1aSopenharmony_ci    VP56mv uvmv = *mv;
1927cabdff1aSopenharmony_ci
1928cabdff1aSopenharmony_ci    /* Y */
1929cabdff1aSopenharmony_ci    vp8_mc_luma(s, td, dst[0] + by_off * s->linesize + bx_off,
1930cabdff1aSopenharmony_ci                ref_frame, mv, x_off + bx_off, y_off + by_off,
1931cabdff1aSopenharmony_ci                block_w, block_h, width, height, s->linesize,
1932cabdff1aSopenharmony_ci                s->put_pixels_tab[block_w == 8]);
1933cabdff1aSopenharmony_ci
1934cabdff1aSopenharmony_ci    /* U/V */
1935cabdff1aSopenharmony_ci    if (s->profile == 3) {
1936cabdff1aSopenharmony_ci        /* this block only applies VP8; it is safe to check
1937cabdff1aSopenharmony_ci         * only the profile, as VP7 profile <= 1 */
1938cabdff1aSopenharmony_ci        uvmv.x &= ~7;
1939cabdff1aSopenharmony_ci        uvmv.y &= ~7;
1940cabdff1aSopenharmony_ci    }
1941cabdff1aSopenharmony_ci    x_off   >>= 1;
1942cabdff1aSopenharmony_ci    y_off   >>= 1;
1943cabdff1aSopenharmony_ci    bx_off  >>= 1;
1944cabdff1aSopenharmony_ci    by_off  >>= 1;
1945cabdff1aSopenharmony_ci    width   >>= 1;
1946cabdff1aSopenharmony_ci    height  >>= 1;
1947cabdff1aSopenharmony_ci    block_w >>= 1;
1948cabdff1aSopenharmony_ci    block_h >>= 1;
1949cabdff1aSopenharmony_ci    vp8_mc_chroma(s, td, dst[1] + by_off * s->uvlinesize + bx_off,
1950cabdff1aSopenharmony_ci                  dst[2] + by_off * s->uvlinesize + bx_off, ref_frame,
1951cabdff1aSopenharmony_ci                  &uvmv, x_off + bx_off, y_off + by_off,
1952cabdff1aSopenharmony_ci                  block_w, block_h, width, height, s->uvlinesize,
1953cabdff1aSopenharmony_ci                  s->put_pixels_tab[1 + (block_w == 4)]);
1954cabdff1aSopenharmony_ci}
1955cabdff1aSopenharmony_ci
1956cabdff1aSopenharmony_ci/* Fetch pixels for estimated mv 4 macroblocks ahead.
1957cabdff1aSopenharmony_ci * Optimized for 64-byte cache lines. Inspired by ffh264 prefetch_motion. */
1958cabdff1aSopenharmony_cistatic av_always_inline
1959cabdff1aSopenharmony_civoid prefetch_motion(VP8Context *s, VP8Macroblock *mb, int mb_x, int mb_y,
1960cabdff1aSopenharmony_ci                     int mb_xy, int ref)
1961cabdff1aSopenharmony_ci{
1962cabdff1aSopenharmony_ci    /* Don't prefetch refs that haven't been used very often this frame. */
1963cabdff1aSopenharmony_ci    if (s->ref_count[ref - 1] > (mb_xy >> 5)) {
1964cabdff1aSopenharmony_ci        int x_off = mb_x << 4, y_off = mb_y << 4;
1965cabdff1aSopenharmony_ci        int mx = (mb->mv.x >> 2) + x_off + 8;
1966cabdff1aSopenharmony_ci        int my = (mb->mv.y >> 2) + y_off;
1967cabdff1aSopenharmony_ci        uint8_t **src = s->framep[ref]->tf.f->data;
1968cabdff1aSopenharmony_ci        int off = mx + (my + (mb_x & 3) * 4) * s->linesize + 64;
1969cabdff1aSopenharmony_ci        /* For threading, a ff_thread_await_progress here might be useful, but
1970cabdff1aSopenharmony_ci         * it actually slows down the decoder. Since a bad prefetch doesn't
1971cabdff1aSopenharmony_ci         * generate bad decoder output, we don't run it here. */
1972cabdff1aSopenharmony_ci        s->vdsp.prefetch(src[0] + off, s->linesize, 4);
1973cabdff1aSopenharmony_ci        off = (mx >> 1) + ((my >> 1) + (mb_x & 7)) * s->uvlinesize + 64;
1974cabdff1aSopenharmony_ci        s->vdsp.prefetch(src[1] + off, src[2] - src[1], 2);
1975cabdff1aSopenharmony_ci    }
1976cabdff1aSopenharmony_ci}
1977cabdff1aSopenharmony_ci
1978cabdff1aSopenharmony_ci/**
1979cabdff1aSopenharmony_ci * Apply motion vectors to prediction buffer, chapter 18.
1980cabdff1aSopenharmony_ci */
1981cabdff1aSopenharmony_cistatic av_always_inline
1982cabdff1aSopenharmony_civoid inter_predict(VP8Context *s, VP8ThreadData *td, uint8_t *dst[3],
1983cabdff1aSopenharmony_ci                   VP8Macroblock *mb, int mb_x, int mb_y)
1984cabdff1aSopenharmony_ci{
1985cabdff1aSopenharmony_ci    int x_off = mb_x << 4, y_off = mb_y << 4;
1986cabdff1aSopenharmony_ci    int width = 16 * s->mb_width, height = 16 * s->mb_height;
1987cabdff1aSopenharmony_ci    ThreadFrame *ref = &s->framep[mb->ref_frame]->tf;
1988cabdff1aSopenharmony_ci    VP56mv *bmv = mb->bmv;
1989cabdff1aSopenharmony_ci
1990cabdff1aSopenharmony_ci    switch (mb->partitioning) {
1991cabdff1aSopenharmony_ci    case VP8_SPLITMVMODE_NONE:
1992cabdff1aSopenharmony_ci        vp8_mc_part(s, td, dst, ref, x_off, y_off,
1993cabdff1aSopenharmony_ci                    0, 0, 16, 16, width, height, &mb->mv);
1994cabdff1aSopenharmony_ci        break;
1995cabdff1aSopenharmony_ci    case VP8_SPLITMVMODE_4x4: {
1996cabdff1aSopenharmony_ci        int x, y;
1997cabdff1aSopenharmony_ci        VP56mv uvmv;
1998cabdff1aSopenharmony_ci
1999cabdff1aSopenharmony_ci        /* Y */
2000cabdff1aSopenharmony_ci        for (y = 0; y < 4; y++) {
2001cabdff1aSopenharmony_ci            for (x = 0; x < 4; x++) {
2002cabdff1aSopenharmony_ci                vp8_mc_luma(s, td, dst[0] + 4 * y * s->linesize + x * 4,
2003cabdff1aSopenharmony_ci                            ref, &bmv[4 * y + x],
2004cabdff1aSopenharmony_ci                            4 * x + x_off, 4 * y + y_off, 4, 4,
2005cabdff1aSopenharmony_ci                            width, height, s->linesize,
2006cabdff1aSopenharmony_ci                            s->put_pixels_tab[2]);
2007cabdff1aSopenharmony_ci            }
2008cabdff1aSopenharmony_ci        }
2009cabdff1aSopenharmony_ci
2010cabdff1aSopenharmony_ci        /* U/V */
2011cabdff1aSopenharmony_ci        x_off  >>= 1;
2012cabdff1aSopenharmony_ci        y_off  >>= 1;
2013cabdff1aSopenharmony_ci        width  >>= 1;
2014cabdff1aSopenharmony_ci        height >>= 1;
2015cabdff1aSopenharmony_ci        for (y = 0; y < 2; y++) {
2016cabdff1aSopenharmony_ci            for (x = 0; x < 2; x++) {
2017cabdff1aSopenharmony_ci                uvmv.x = mb->bmv[2 * y       * 4 + 2 * x    ].x +
2018cabdff1aSopenharmony_ci                         mb->bmv[2 * y       * 4 + 2 * x + 1].x +
2019cabdff1aSopenharmony_ci                         mb->bmv[(2 * y + 1) * 4 + 2 * x    ].x +
2020cabdff1aSopenharmony_ci                         mb->bmv[(2 * y + 1) * 4 + 2 * x + 1].x;
2021cabdff1aSopenharmony_ci                uvmv.y = mb->bmv[2 * y       * 4 + 2 * x    ].y +
2022cabdff1aSopenharmony_ci                         mb->bmv[2 * y       * 4 + 2 * x + 1].y +
2023cabdff1aSopenharmony_ci                         mb->bmv[(2 * y + 1) * 4 + 2 * x    ].y +
2024cabdff1aSopenharmony_ci                         mb->bmv[(2 * y + 1) * 4 + 2 * x + 1].y;
2025cabdff1aSopenharmony_ci                uvmv.x = (uvmv.x + 2 + FF_SIGNBIT(uvmv.x)) >> 2;
2026cabdff1aSopenharmony_ci                uvmv.y = (uvmv.y + 2 + FF_SIGNBIT(uvmv.y)) >> 2;
2027cabdff1aSopenharmony_ci                if (s->profile == 3) {
2028cabdff1aSopenharmony_ci                    uvmv.x &= ~7;
2029cabdff1aSopenharmony_ci                    uvmv.y &= ~7;
2030cabdff1aSopenharmony_ci                }
2031cabdff1aSopenharmony_ci                vp8_mc_chroma(s, td, dst[1] + 4 * y * s->uvlinesize + x * 4,
2032cabdff1aSopenharmony_ci                              dst[2] + 4 * y * s->uvlinesize + x * 4, ref,
2033cabdff1aSopenharmony_ci                              &uvmv, 4 * x + x_off, 4 * y + y_off, 4, 4,
2034cabdff1aSopenharmony_ci                              width, height, s->uvlinesize,
2035cabdff1aSopenharmony_ci                              s->put_pixels_tab[2]);
2036cabdff1aSopenharmony_ci            }
2037cabdff1aSopenharmony_ci        }
2038cabdff1aSopenharmony_ci        break;
2039cabdff1aSopenharmony_ci    }
2040cabdff1aSopenharmony_ci    case VP8_SPLITMVMODE_16x8:
2041cabdff1aSopenharmony_ci        vp8_mc_part(s, td, dst, ref, x_off, y_off,
2042cabdff1aSopenharmony_ci                    0, 0, 16, 8, width, height, &bmv[0]);
2043cabdff1aSopenharmony_ci        vp8_mc_part(s, td, dst, ref, x_off, y_off,
2044cabdff1aSopenharmony_ci                    0, 8, 16, 8, width, height, &bmv[1]);
2045cabdff1aSopenharmony_ci        break;
2046cabdff1aSopenharmony_ci    case VP8_SPLITMVMODE_8x16:
2047cabdff1aSopenharmony_ci        vp8_mc_part(s, td, dst, ref, x_off, y_off,
2048cabdff1aSopenharmony_ci                    0, 0, 8, 16, width, height, &bmv[0]);
2049cabdff1aSopenharmony_ci        vp8_mc_part(s, td, dst, ref, x_off, y_off,
2050cabdff1aSopenharmony_ci                    8, 0, 8, 16, width, height, &bmv[1]);
2051cabdff1aSopenharmony_ci        break;
2052cabdff1aSopenharmony_ci    case VP8_SPLITMVMODE_8x8:
2053cabdff1aSopenharmony_ci        vp8_mc_part(s, td, dst, ref, x_off, y_off,
2054cabdff1aSopenharmony_ci                    0, 0, 8, 8, width, height, &bmv[0]);
2055cabdff1aSopenharmony_ci        vp8_mc_part(s, td, dst, ref, x_off, y_off,
2056cabdff1aSopenharmony_ci                    8, 0, 8, 8, width, height, &bmv[1]);
2057cabdff1aSopenharmony_ci        vp8_mc_part(s, td, dst, ref, x_off, y_off,
2058cabdff1aSopenharmony_ci                    0, 8, 8, 8, width, height, &bmv[2]);
2059cabdff1aSopenharmony_ci        vp8_mc_part(s, td, dst, ref, x_off, y_off,
2060cabdff1aSopenharmony_ci                    8, 8, 8, 8, width, height, &bmv[3]);
2061cabdff1aSopenharmony_ci        break;
2062cabdff1aSopenharmony_ci    }
2063cabdff1aSopenharmony_ci}
2064cabdff1aSopenharmony_ci
2065cabdff1aSopenharmony_cistatic av_always_inline
2066cabdff1aSopenharmony_civoid idct_mb(VP8Context *s, VP8ThreadData *td, uint8_t *dst[3], VP8Macroblock *mb)
2067cabdff1aSopenharmony_ci{
2068cabdff1aSopenharmony_ci    int x, y, ch;
2069cabdff1aSopenharmony_ci
2070cabdff1aSopenharmony_ci    if (mb->mode != MODE_I4x4) {
2071cabdff1aSopenharmony_ci        uint8_t *y_dst = dst[0];
2072cabdff1aSopenharmony_ci        for (y = 0; y < 4; y++) {
2073cabdff1aSopenharmony_ci            uint32_t nnz4 = AV_RL32(td->non_zero_count_cache[y]);
2074cabdff1aSopenharmony_ci            if (nnz4) {
2075cabdff1aSopenharmony_ci                if (nnz4 & ~0x01010101) {
2076cabdff1aSopenharmony_ci                    for (x = 0; x < 4; x++) {
2077cabdff1aSopenharmony_ci                        if ((uint8_t) nnz4 == 1)
2078cabdff1aSopenharmony_ci                            s->vp8dsp.vp8_idct_dc_add(y_dst + 4 * x,
2079cabdff1aSopenharmony_ci                                                      td->block[y][x],
2080cabdff1aSopenharmony_ci                                                      s->linesize);
2081cabdff1aSopenharmony_ci                        else if ((uint8_t) nnz4 > 1)
2082cabdff1aSopenharmony_ci                            s->vp8dsp.vp8_idct_add(y_dst + 4 * x,
2083cabdff1aSopenharmony_ci                                                   td->block[y][x],
2084cabdff1aSopenharmony_ci                                                   s->linesize);
2085cabdff1aSopenharmony_ci                        nnz4 >>= 8;
2086cabdff1aSopenharmony_ci                        if (!nnz4)
2087cabdff1aSopenharmony_ci                            break;
2088cabdff1aSopenharmony_ci                    }
2089cabdff1aSopenharmony_ci                } else {
2090cabdff1aSopenharmony_ci                    s->vp8dsp.vp8_idct_dc_add4y(y_dst, td->block[y], s->linesize);
2091cabdff1aSopenharmony_ci                }
2092cabdff1aSopenharmony_ci            }
2093cabdff1aSopenharmony_ci            y_dst += 4 * s->linesize;
2094cabdff1aSopenharmony_ci        }
2095cabdff1aSopenharmony_ci    }
2096cabdff1aSopenharmony_ci
2097cabdff1aSopenharmony_ci    for (ch = 0; ch < 2; ch++) {
2098cabdff1aSopenharmony_ci        uint32_t nnz4 = AV_RL32(td->non_zero_count_cache[4 + ch]);
2099cabdff1aSopenharmony_ci        if (nnz4) {
2100cabdff1aSopenharmony_ci            uint8_t *ch_dst = dst[1 + ch];
2101cabdff1aSopenharmony_ci            if (nnz4 & ~0x01010101) {
2102cabdff1aSopenharmony_ci                for (y = 0; y < 2; y++) {
2103cabdff1aSopenharmony_ci                    for (x = 0; x < 2; x++) {
2104cabdff1aSopenharmony_ci                        if ((uint8_t) nnz4 == 1)
2105cabdff1aSopenharmony_ci                            s->vp8dsp.vp8_idct_dc_add(ch_dst + 4 * x,
2106cabdff1aSopenharmony_ci                                                      td->block[4 + ch][(y << 1) + x],
2107cabdff1aSopenharmony_ci                                                      s->uvlinesize);
2108cabdff1aSopenharmony_ci                        else if ((uint8_t) nnz4 > 1)
2109cabdff1aSopenharmony_ci                            s->vp8dsp.vp8_idct_add(ch_dst + 4 * x,
2110cabdff1aSopenharmony_ci                                                   td->block[4 + ch][(y << 1) + x],
2111cabdff1aSopenharmony_ci                                                   s->uvlinesize);
2112cabdff1aSopenharmony_ci                        nnz4 >>= 8;
2113cabdff1aSopenharmony_ci                        if (!nnz4)
2114cabdff1aSopenharmony_ci                            goto chroma_idct_end;
2115cabdff1aSopenharmony_ci                    }
2116cabdff1aSopenharmony_ci                    ch_dst += 4 * s->uvlinesize;
2117cabdff1aSopenharmony_ci                }
2118cabdff1aSopenharmony_ci            } else {
2119cabdff1aSopenharmony_ci                s->vp8dsp.vp8_idct_dc_add4uv(ch_dst, td->block[4 + ch], s->uvlinesize);
2120cabdff1aSopenharmony_ci            }
2121cabdff1aSopenharmony_ci        }
2122cabdff1aSopenharmony_cichroma_idct_end:
2123cabdff1aSopenharmony_ci        ;
2124cabdff1aSopenharmony_ci    }
2125cabdff1aSopenharmony_ci}
2126cabdff1aSopenharmony_ci
2127cabdff1aSopenharmony_cistatic av_always_inline
2128cabdff1aSopenharmony_civoid filter_level_for_mb(VP8Context *s, VP8Macroblock *mb,
2129cabdff1aSopenharmony_ci                         VP8FilterStrength *f, int is_vp7)
2130cabdff1aSopenharmony_ci{
2131cabdff1aSopenharmony_ci    int interior_limit, filter_level;
2132cabdff1aSopenharmony_ci
2133cabdff1aSopenharmony_ci    if (s->segmentation.enabled) {
2134cabdff1aSopenharmony_ci        filter_level = s->segmentation.filter_level[mb->segment];
2135cabdff1aSopenharmony_ci        if (!s->segmentation.absolute_vals)
2136cabdff1aSopenharmony_ci            filter_level += s->filter.level;
2137cabdff1aSopenharmony_ci    } else
2138cabdff1aSopenharmony_ci        filter_level = s->filter.level;
2139cabdff1aSopenharmony_ci
2140cabdff1aSopenharmony_ci    if (s->lf_delta.enabled) {
2141cabdff1aSopenharmony_ci        filter_level += s->lf_delta.ref[mb->ref_frame];
2142cabdff1aSopenharmony_ci        filter_level += s->lf_delta.mode[mb->mode];
2143cabdff1aSopenharmony_ci    }
2144cabdff1aSopenharmony_ci
2145cabdff1aSopenharmony_ci    filter_level = av_clip_uintp2(filter_level, 6);
2146cabdff1aSopenharmony_ci
2147cabdff1aSopenharmony_ci    interior_limit = filter_level;
2148cabdff1aSopenharmony_ci    if (s->filter.sharpness) {
2149cabdff1aSopenharmony_ci        interior_limit >>= (s->filter.sharpness + 3) >> 2;
2150cabdff1aSopenharmony_ci        interior_limit = FFMIN(interior_limit, 9 - s->filter.sharpness);
2151cabdff1aSopenharmony_ci    }
2152cabdff1aSopenharmony_ci    interior_limit = FFMAX(interior_limit, 1);
2153cabdff1aSopenharmony_ci
2154cabdff1aSopenharmony_ci    f->filter_level = filter_level;
2155cabdff1aSopenharmony_ci    f->inner_limit = interior_limit;
2156cabdff1aSopenharmony_ci    f->inner_filter = is_vp7 || !mb->skip || mb->mode == MODE_I4x4 ||
2157cabdff1aSopenharmony_ci                      mb->mode == VP8_MVMODE_SPLIT;
2158cabdff1aSopenharmony_ci}
2159cabdff1aSopenharmony_ci
2160cabdff1aSopenharmony_cistatic av_always_inline
2161cabdff1aSopenharmony_civoid filter_mb(VP8Context *s, uint8_t *dst[3], VP8FilterStrength *f,
2162cabdff1aSopenharmony_ci               int mb_x, int mb_y, int is_vp7)
2163cabdff1aSopenharmony_ci{
2164cabdff1aSopenharmony_ci    int mbedge_lim, bedge_lim_y, bedge_lim_uv, hev_thresh;
2165cabdff1aSopenharmony_ci    int filter_level = f->filter_level;
2166cabdff1aSopenharmony_ci    int inner_limit = f->inner_limit;
2167cabdff1aSopenharmony_ci    int inner_filter = f->inner_filter;
2168cabdff1aSopenharmony_ci    ptrdiff_t linesize   = s->linesize;
2169cabdff1aSopenharmony_ci    ptrdiff_t uvlinesize = s->uvlinesize;
2170cabdff1aSopenharmony_ci    static const uint8_t hev_thresh_lut[2][64] = {
2171cabdff1aSopenharmony_ci        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
2172cabdff1aSopenharmony_ci          2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2173cabdff1aSopenharmony_ci          3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2174cabdff1aSopenharmony_ci          3, 3, 3, 3 },
2175cabdff1aSopenharmony_ci        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
2176cabdff1aSopenharmony_ci          1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2177cabdff1aSopenharmony_ci          2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2178cabdff1aSopenharmony_ci          2, 2, 2, 2 }
2179cabdff1aSopenharmony_ci    };
2180cabdff1aSopenharmony_ci
2181cabdff1aSopenharmony_ci    if (!filter_level)
2182cabdff1aSopenharmony_ci        return;
2183cabdff1aSopenharmony_ci
2184cabdff1aSopenharmony_ci    if (is_vp7) {
2185cabdff1aSopenharmony_ci        bedge_lim_y  = filter_level;
2186cabdff1aSopenharmony_ci        bedge_lim_uv = filter_level * 2;
2187cabdff1aSopenharmony_ci        mbedge_lim   = filter_level + 2;
2188cabdff1aSopenharmony_ci    } else {
2189cabdff1aSopenharmony_ci        bedge_lim_y  =
2190cabdff1aSopenharmony_ci        bedge_lim_uv = filter_level * 2 + inner_limit;
2191cabdff1aSopenharmony_ci        mbedge_lim   = bedge_lim_y + 4;
2192cabdff1aSopenharmony_ci    }
2193cabdff1aSopenharmony_ci
2194cabdff1aSopenharmony_ci    hev_thresh = hev_thresh_lut[s->keyframe][filter_level];
2195cabdff1aSopenharmony_ci
2196cabdff1aSopenharmony_ci    if (mb_x) {
2197cabdff1aSopenharmony_ci        s->vp8dsp.vp8_h_loop_filter16y(dst[0], linesize,
2198cabdff1aSopenharmony_ci                                       mbedge_lim, inner_limit, hev_thresh);
2199cabdff1aSopenharmony_ci        s->vp8dsp.vp8_h_loop_filter8uv(dst[1], dst[2], uvlinesize,
2200cabdff1aSopenharmony_ci                                       mbedge_lim, inner_limit, hev_thresh);
2201cabdff1aSopenharmony_ci    }
2202cabdff1aSopenharmony_ci
2203cabdff1aSopenharmony_ci#define H_LOOP_FILTER_16Y_INNER(cond)                                         \
2204cabdff1aSopenharmony_ci    if (cond && inner_filter) {                                               \
2205cabdff1aSopenharmony_ci        s->vp8dsp.vp8_h_loop_filter16y_inner(dst[0] +  4, linesize,           \
2206cabdff1aSopenharmony_ci                                             bedge_lim_y, inner_limit,        \
2207cabdff1aSopenharmony_ci                                             hev_thresh);                     \
2208cabdff1aSopenharmony_ci        s->vp8dsp.vp8_h_loop_filter16y_inner(dst[0] +  8, linesize,           \
2209cabdff1aSopenharmony_ci                                             bedge_lim_y, inner_limit,        \
2210cabdff1aSopenharmony_ci                                             hev_thresh);                     \
2211cabdff1aSopenharmony_ci        s->vp8dsp.vp8_h_loop_filter16y_inner(dst[0] + 12, linesize,           \
2212cabdff1aSopenharmony_ci                                             bedge_lim_y, inner_limit,        \
2213cabdff1aSopenharmony_ci                                             hev_thresh);                     \
2214cabdff1aSopenharmony_ci        s->vp8dsp.vp8_h_loop_filter8uv_inner(dst[1] +  4, dst[2] + 4,         \
2215cabdff1aSopenharmony_ci                                             uvlinesize,  bedge_lim_uv,       \
2216cabdff1aSopenharmony_ci                                             inner_limit, hev_thresh);        \
2217cabdff1aSopenharmony_ci    }
2218cabdff1aSopenharmony_ci
2219cabdff1aSopenharmony_ci    H_LOOP_FILTER_16Y_INNER(!is_vp7)
2220cabdff1aSopenharmony_ci
2221cabdff1aSopenharmony_ci    if (mb_y) {
2222cabdff1aSopenharmony_ci        s->vp8dsp.vp8_v_loop_filter16y(dst[0], linesize,
2223cabdff1aSopenharmony_ci                                       mbedge_lim, inner_limit, hev_thresh);
2224cabdff1aSopenharmony_ci        s->vp8dsp.vp8_v_loop_filter8uv(dst[1], dst[2], uvlinesize,
2225cabdff1aSopenharmony_ci                                       mbedge_lim, inner_limit, hev_thresh);
2226cabdff1aSopenharmony_ci    }
2227cabdff1aSopenharmony_ci
2228cabdff1aSopenharmony_ci    if (inner_filter) {
2229cabdff1aSopenharmony_ci        s->vp8dsp.vp8_v_loop_filter16y_inner(dst[0] +  4 * linesize,
2230cabdff1aSopenharmony_ci                                             linesize, bedge_lim_y,
2231cabdff1aSopenharmony_ci                                             inner_limit, hev_thresh);
2232cabdff1aSopenharmony_ci        s->vp8dsp.vp8_v_loop_filter16y_inner(dst[0] +  8 * linesize,
2233cabdff1aSopenharmony_ci                                             linesize, bedge_lim_y,
2234cabdff1aSopenharmony_ci                                             inner_limit, hev_thresh);
2235cabdff1aSopenharmony_ci        s->vp8dsp.vp8_v_loop_filter16y_inner(dst[0] + 12 * linesize,
2236cabdff1aSopenharmony_ci                                             linesize, bedge_lim_y,
2237cabdff1aSopenharmony_ci                                             inner_limit, hev_thresh);
2238cabdff1aSopenharmony_ci        s->vp8dsp.vp8_v_loop_filter8uv_inner(dst[1] +  4 * uvlinesize,
2239cabdff1aSopenharmony_ci                                             dst[2] +  4 * uvlinesize,
2240cabdff1aSopenharmony_ci                                             uvlinesize, bedge_lim_uv,
2241cabdff1aSopenharmony_ci                                             inner_limit, hev_thresh);
2242cabdff1aSopenharmony_ci    }
2243cabdff1aSopenharmony_ci
2244cabdff1aSopenharmony_ci    H_LOOP_FILTER_16Y_INNER(is_vp7)
2245cabdff1aSopenharmony_ci}
2246cabdff1aSopenharmony_ci
2247cabdff1aSopenharmony_cistatic av_always_inline
2248cabdff1aSopenharmony_civoid filter_mb_simple(VP8Context *s, uint8_t *dst, VP8FilterStrength *f,
2249cabdff1aSopenharmony_ci                      int mb_x, int mb_y)
2250cabdff1aSopenharmony_ci{
2251cabdff1aSopenharmony_ci    int mbedge_lim, bedge_lim;
2252cabdff1aSopenharmony_ci    int filter_level = f->filter_level;
2253cabdff1aSopenharmony_ci    int inner_limit  = f->inner_limit;
2254cabdff1aSopenharmony_ci    int inner_filter = f->inner_filter;
2255cabdff1aSopenharmony_ci    ptrdiff_t linesize = s->linesize;
2256cabdff1aSopenharmony_ci
2257cabdff1aSopenharmony_ci    if (!filter_level)
2258cabdff1aSopenharmony_ci        return;
2259cabdff1aSopenharmony_ci
2260cabdff1aSopenharmony_ci    bedge_lim  = 2 * filter_level + inner_limit;
2261cabdff1aSopenharmony_ci    mbedge_lim = bedge_lim + 4;
2262cabdff1aSopenharmony_ci
2263cabdff1aSopenharmony_ci    if (mb_x)
2264cabdff1aSopenharmony_ci        s->vp8dsp.vp8_h_loop_filter_simple(dst, linesize, mbedge_lim);
2265cabdff1aSopenharmony_ci    if (inner_filter) {
2266cabdff1aSopenharmony_ci        s->vp8dsp.vp8_h_loop_filter_simple(dst +  4, linesize, bedge_lim);
2267cabdff1aSopenharmony_ci        s->vp8dsp.vp8_h_loop_filter_simple(dst +  8, linesize, bedge_lim);
2268cabdff1aSopenharmony_ci        s->vp8dsp.vp8_h_loop_filter_simple(dst + 12, linesize, bedge_lim);
2269cabdff1aSopenharmony_ci    }
2270cabdff1aSopenharmony_ci
2271cabdff1aSopenharmony_ci    if (mb_y)
2272cabdff1aSopenharmony_ci        s->vp8dsp.vp8_v_loop_filter_simple(dst, linesize, mbedge_lim);
2273cabdff1aSopenharmony_ci    if (inner_filter) {
2274cabdff1aSopenharmony_ci        s->vp8dsp.vp8_v_loop_filter_simple(dst +  4 * linesize, linesize, bedge_lim);
2275cabdff1aSopenharmony_ci        s->vp8dsp.vp8_v_loop_filter_simple(dst +  8 * linesize, linesize, bedge_lim);
2276cabdff1aSopenharmony_ci        s->vp8dsp.vp8_v_loop_filter_simple(dst + 12 * linesize, linesize, bedge_lim);
2277cabdff1aSopenharmony_ci    }
2278cabdff1aSopenharmony_ci}
2279cabdff1aSopenharmony_ci
2280cabdff1aSopenharmony_ci#define MARGIN (16 << 2)
2281cabdff1aSopenharmony_cistatic av_always_inline
2282cabdff1aSopenharmony_ciint vp78_decode_mv_mb_modes(AVCodecContext *avctx, VP8Frame *curframe,
2283cabdff1aSopenharmony_ci                                    VP8Frame *prev_frame, int is_vp7)
2284cabdff1aSopenharmony_ci{
2285cabdff1aSopenharmony_ci    VP8Context *s = avctx->priv_data;
2286cabdff1aSopenharmony_ci    int mb_x, mb_y;
2287cabdff1aSopenharmony_ci
2288cabdff1aSopenharmony_ci    s->mv_bounds.mv_min.y = -MARGIN;
2289cabdff1aSopenharmony_ci    s->mv_bounds.mv_max.y = ((s->mb_height - 1) << 6) + MARGIN;
2290cabdff1aSopenharmony_ci    for (mb_y = 0; mb_y < s->mb_height; mb_y++) {
2291cabdff1aSopenharmony_ci        VP8Macroblock *mb = s->macroblocks_base +
2292cabdff1aSopenharmony_ci                            ((s->mb_width + 1) * (mb_y + 1) + 1);
2293cabdff1aSopenharmony_ci        int mb_xy = mb_y * s->mb_width;
2294cabdff1aSopenharmony_ci
2295cabdff1aSopenharmony_ci        AV_WN32A(s->intra4x4_pred_mode_left, DC_PRED * 0x01010101);
2296cabdff1aSopenharmony_ci
2297cabdff1aSopenharmony_ci        s->mv_bounds.mv_min.x = -MARGIN;
2298cabdff1aSopenharmony_ci        s->mv_bounds.mv_max.x = ((s->mb_width - 1) << 6) + MARGIN;
2299cabdff1aSopenharmony_ci
2300cabdff1aSopenharmony_ci        for (mb_x = 0; mb_x < s->mb_width; mb_x++, mb_xy++, mb++) {
2301cabdff1aSopenharmony_ci            if (vpX_rac_is_end(&s->c)) {
2302cabdff1aSopenharmony_ci                return AVERROR_INVALIDDATA;
2303cabdff1aSopenharmony_ci            }
2304cabdff1aSopenharmony_ci            if (mb_y == 0)
2305cabdff1aSopenharmony_ci                AV_WN32A((mb - s->mb_width - 1)->intra4x4_pred_mode_top,
2306cabdff1aSopenharmony_ci                         DC_PRED * 0x01010101);
2307cabdff1aSopenharmony_ci            decode_mb_mode(s, &s->mv_bounds, mb, mb_x, mb_y, curframe->seg_map->data + mb_xy,
2308cabdff1aSopenharmony_ci                           prev_frame && prev_frame->seg_map ?
2309cabdff1aSopenharmony_ci                           prev_frame->seg_map->data + mb_xy : NULL, 1, is_vp7);
2310cabdff1aSopenharmony_ci            s->mv_bounds.mv_min.x -= 64;
2311cabdff1aSopenharmony_ci            s->mv_bounds.mv_max.x -= 64;
2312cabdff1aSopenharmony_ci        }
2313cabdff1aSopenharmony_ci        s->mv_bounds.mv_min.y -= 64;
2314cabdff1aSopenharmony_ci        s->mv_bounds.mv_max.y -= 64;
2315cabdff1aSopenharmony_ci    }
2316cabdff1aSopenharmony_ci    return 0;
2317cabdff1aSopenharmony_ci}
2318cabdff1aSopenharmony_ci
2319cabdff1aSopenharmony_cistatic int vp7_decode_mv_mb_modes(AVCodecContext *avctx, VP8Frame *cur_frame,
2320cabdff1aSopenharmony_ci                                   VP8Frame *prev_frame)
2321cabdff1aSopenharmony_ci{
2322cabdff1aSopenharmony_ci    return vp78_decode_mv_mb_modes(avctx, cur_frame, prev_frame, IS_VP7);
2323cabdff1aSopenharmony_ci}
2324cabdff1aSopenharmony_ci
2325cabdff1aSopenharmony_cistatic int vp8_decode_mv_mb_modes(AVCodecContext *avctx, VP8Frame *cur_frame,
2326cabdff1aSopenharmony_ci                                   VP8Frame *prev_frame)
2327cabdff1aSopenharmony_ci{
2328cabdff1aSopenharmony_ci    return vp78_decode_mv_mb_modes(avctx, cur_frame, prev_frame, IS_VP8);
2329cabdff1aSopenharmony_ci}
2330cabdff1aSopenharmony_ci
2331cabdff1aSopenharmony_ci#if HAVE_THREADS
2332cabdff1aSopenharmony_ci#define check_thread_pos(td, otd, mb_x_check, mb_y_check)                     \
2333cabdff1aSopenharmony_ci    do {                                                                      \
2334cabdff1aSopenharmony_ci        int tmp = (mb_y_check << 16) | (mb_x_check & 0xFFFF);                 \
2335cabdff1aSopenharmony_ci        if (atomic_load(&otd->thread_mb_pos) < tmp) {                         \
2336cabdff1aSopenharmony_ci            pthread_mutex_lock(&otd->lock);                                   \
2337cabdff1aSopenharmony_ci            atomic_store(&td->wait_mb_pos, tmp);                              \
2338cabdff1aSopenharmony_ci            do {                                                              \
2339cabdff1aSopenharmony_ci                if (atomic_load(&otd->thread_mb_pos) >= tmp)                  \
2340cabdff1aSopenharmony_ci                    break;                                                    \
2341cabdff1aSopenharmony_ci                pthread_cond_wait(&otd->cond, &otd->lock);                    \
2342cabdff1aSopenharmony_ci            } while (1);                                                      \
2343cabdff1aSopenharmony_ci            atomic_store(&td->wait_mb_pos, INT_MAX);                          \
2344cabdff1aSopenharmony_ci            pthread_mutex_unlock(&otd->lock);                                 \
2345cabdff1aSopenharmony_ci        }                                                                     \
2346cabdff1aSopenharmony_ci    } while (0)
2347cabdff1aSopenharmony_ci
2348cabdff1aSopenharmony_ci#define update_pos(td, mb_y, mb_x)                                            \
2349cabdff1aSopenharmony_ci    do {                                                                      \
2350cabdff1aSopenharmony_ci        int pos              = (mb_y << 16) | (mb_x & 0xFFFF);                \
2351cabdff1aSopenharmony_ci        int sliced_threading = (avctx->active_thread_type == FF_THREAD_SLICE) && \
2352cabdff1aSopenharmony_ci                               (num_jobs > 1);                                \
2353cabdff1aSopenharmony_ci        int is_null          = !next_td || !prev_td;                          \
2354cabdff1aSopenharmony_ci        int pos_check        = (is_null) ? 1 :                                \
2355cabdff1aSopenharmony_ci            (next_td != td && pos >= atomic_load(&next_td->wait_mb_pos)) ||   \
2356cabdff1aSopenharmony_ci            (prev_td != td && pos >= atomic_load(&prev_td->wait_mb_pos));     \
2357cabdff1aSopenharmony_ci        atomic_store(&td->thread_mb_pos, pos);                                \
2358cabdff1aSopenharmony_ci        if (sliced_threading && pos_check) {                                  \
2359cabdff1aSopenharmony_ci            pthread_mutex_lock(&td->lock);                                    \
2360cabdff1aSopenharmony_ci            pthread_cond_broadcast(&td->cond);                                \
2361cabdff1aSopenharmony_ci            pthread_mutex_unlock(&td->lock);                                  \
2362cabdff1aSopenharmony_ci        }                                                                     \
2363cabdff1aSopenharmony_ci    } while (0)
2364cabdff1aSopenharmony_ci#else
2365cabdff1aSopenharmony_ci#define check_thread_pos(td, otd, mb_x_check, mb_y_check) while(0)
2366cabdff1aSopenharmony_ci#define update_pos(td, mb_y, mb_x) while(0)
2367cabdff1aSopenharmony_ci#endif
2368cabdff1aSopenharmony_ci
2369cabdff1aSopenharmony_cistatic av_always_inline int decode_mb_row_no_filter(AVCodecContext *avctx, void *tdata,
2370cabdff1aSopenharmony_ci                                        int jobnr, int threadnr, int is_vp7)
2371cabdff1aSopenharmony_ci{
2372cabdff1aSopenharmony_ci    VP8Context *s = avctx->priv_data;
2373cabdff1aSopenharmony_ci    VP8ThreadData *prev_td, *next_td, *td = &s->thread_data[threadnr];
2374cabdff1aSopenharmony_ci    int mb_y = atomic_load(&td->thread_mb_pos) >> 16;
2375cabdff1aSopenharmony_ci    int mb_x, mb_xy = mb_y * s->mb_width;
2376cabdff1aSopenharmony_ci    int num_jobs = s->num_jobs;
2377cabdff1aSopenharmony_ci    VP8Frame *curframe = s->curframe, *prev_frame = s->prev_frame;
2378cabdff1aSopenharmony_ci    VP56RangeCoder *c  = &s->coeff_partition[mb_y & (s->num_coeff_partitions - 1)];
2379cabdff1aSopenharmony_ci    VP8Macroblock *mb;
2380cabdff1aSopenharmony_ci    uint8_t *dst[3] = {
2381cabdff1aSopenharmony_ci        curframe->tf.f->data[0] + 16 * mb_y * s->linesize,
2382cabdff1aSopenharmony_ci        curframe->tf.f->data[1] +  8 * mb_y * s->uvlinesize,
2383cabdff1aSopenharmony_ci        curframe->tf.f->data[2] +  8 * mb_y * s->uvlinesize
2384cabdff1aSopenharmony_ci    };
2385cabdff1aSopenharmony_ci
2386cabdff1aSopenharmony_ci    if (vpX_rac_is_end(c))
2387cabdff1aSopenharmony_ci         return AVERROR_INVALIDDATA;
2388cabdff1aSopenharmony_ci
2389cabdff1aSopenharmony_ci    if (mb_y == 0)
2390cabdff1aSopenharmony_ci        prev_td = td;
2391cabdff1aSopenharmony_ci    else
2392cabdff1aSopenharmony_ci        prev_td = &s->thread_data[(jobnr + num_jobs - 1) % num_jobs];
2393cabdff1aSopenharmony_ci    if (mb_y == s->mb_height - 1)
2394cabdff1aSopenharmony_ci        next_td = td;
2395cabdff1aSopenharmony_ci    else
2396cabdff1aSopenharmony_ci        next_td = &s->thread_data[(jobnr + 1) % num_jobs];
2397cabdff1aSopenharmony_ci    if (s->mb_layout == 1)
2398cabdff1aSopenharmony_ci        mb = s->macroblocks_base + ((s->mb_width + 1) * (mb_y + 1) + 1);
2399cabdff1aSopenharmony_ci    else {
2400cabdff1aSopenharmony_ci        // Make sure the previous frame has read its segmentation map,
2401cabdff1aSopenharmony_ci        // if we re-use the same map.
2402cabdff1aSopenharmony_ci        if (prev_frame && s->segmentation.enabled &&
2403cabdff1aSopenharmony_ci            !s->segmentation.update_map)
2404cabdff1aSopenharmony_ci            ff_thread_await_progress(&prev_frame->tf, mb_y, 0);
2405cabdff1aSopenharmony_ci        mb = s->macroblocks + (s->mb_height - mb_y - 1) * 2;
2406cabdff1aSopenharmony_ci        memset(mb - 1, 0, sizeof(*mb)); // zero left macroblock
2407cabdff1aSopenharmony_ci        AV_WN32A(s->intra4x4_pred_mode_left, DC_PRED * 0x01010101);
2408cabdff1aSopenharmony_ci    }
2409cabdff1aSopenharmony_ci
2410cabdff1aSopenharmony_ci    if (!is_vp7 || mb_y == 0)
2411cabdff1aSopenharmony_ci        memset(td->left_nnz, 0, sizeof(td->left_nnz));
2412cabdff1aSopenharmony_ci
2413cabdff1aSopenharmony_ci    td->mv_bounds.mv_min.x = -MARGIN;
2414cabdff1aSopenharmony_ci    td->mv_bounds.mv_max.x = ((s->mb_width - 1) << 6) + MARGIN;
2415cabdff1aSopenharmony_ci
2416cabdff1aSopenharmony_ci    for (mb_x = 0; mb_x < s->mb_width; mb_x++, mb_xy++, mb++) {
2417cabdff1aSopenharmony_ci        if (vpX_rac_is_end(c))
2418cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
2419cabdff1aSopenharmony_ci        // Wait for previous thread to read mb_x+2, and reach mb_y-1.
2420cabdff1aSopenharmony_ci        if (prev_td != td) {
2421cabdff1aSopenharmony_ci            if (threadnr != 0) {
2422cabdff1aSopenharmony_ci                check_thread_pos(td, prev_td,
2423cabdff1aSopenharmony_ci                                 mb_x + (is_vp7 ? 2 : 1),
2424cabdff1aSopenharmony_ci                                 mb_y - (is_vp7 ? 2 : 1));
2425cabdff1aSopenharmony_ci            } else {
2426cabdff1aSopenharmony_ci                check_thread_pos(td, prev_td,
2427cabdff1aSopenharmony_ci                                 mb_x + (is_vp7 ? 2 : 1) + s->mb_width + 3,
2428cabdff1aSopenharmony_ci                                 mb_y - (is_vp7 ? 2 : 1));
2429cabdff1aSopenharmony_ci            }
2430cabdff1aSopenharmony_ci        }
2431cabdff1aSopenharmony_ci
2432cabdff1aSopenharmony_ci        s->vdsp.prefetch(dst[0] + (mb_x & 3) * 4 * s->linesize + 64,
2433cabdff1aSopenharmony_ci                         s->linesize, 4);
2434cabdff1aSopenharmony_ci        s->vdsp.prefetch(dst[1] + (mb_x & 7) * s->uvlinesize + 64,
2435cabdff1aSopenharmony_ci                         dst[2] - dst[1], 2);
2436cabdff1aSopenharmony_ci
2437cabdff1aSopenharmony_ci        if (!s->mb_layout)
2438cabdff1aSopenharmony_ci            decode_mb_mode(s, &td->mv_bounds, mb, mb_x, mb_y, curframe->seg_map->data + mb_xy,
2439cabdff1aSopenharmony_ci                           prev_frame && prev_frame->seg_map ?
2440cabdff1aSopenharmony_ci                           prev_frame->seg_map->data + mb_xy : NULL, 0, is_vp7);
2441cabdff1aSopenharmony_ci
2442cabdff1aSopenharmony_ci        prefetch_motion(s, mb, mb_x, mb_y, mb_xy, VP56_FRAME_PREVIOUS);
2443cabdff1aSopenharmony_ci
2444cabdff1aSopenharmony_ci        if (!mb->skip)
2445cabdff1aSopenharmony_ci            decode_mb_coeffs(s, td, c, mb, s->top_nnz[mb_x], td->left_nnz, is_vp7);
2446cabdff1aSopenharmony_ci
2447cabdff1aSopenharmony_ci        if (mb->mode <= MODE_I4x4)
2448cabdff1aSopenharmony_ci            intra_predict(s, td, dst, mb, mb_x, mb_y, is_vp7);
2449cabdff1aSopenharmony_ci        else
2450cabdff1aSopenharmony_ci            inter_predict(s, td, dst, mb, mb_x, mb_y);
2451cabdff1aSopenharmony_ci
2452cabdff1aSopenharmony_ci        prefetch_motion(s, mb, mb_x, mb_y, mb_xy, VP56_FRAME_GOLDEN);
2453cabdff1aSopenharmony_ci
2454cabdff1aSopenharmony_ci        if (!mb->skip) {
2455cabdff1aSopenharmony_ci            idct_mb(s, td, dst, mb);
2456cabdff1aSopenharmony_ci        } else {
2457cabdff1aSopenharmony_ci            AV_ZERO64(td->left_nnz);
2458cabdff1aSopenharmony_ci            AV_WN64(s->top_nnz[mb_x], 0);   // array of 9, so unaligned
2459cabdff1aSopenharmony_ci
2460cabdff1aSopenharmony_ci            /* Reset DC block predictors if they would exist
2461cabdff1aSopenharmony_ci             * if the mb had coefficients */
2462cabdff1aSopenharmony_ci            if (mb->mode != MODE_I4x4 && mb->mode != VP8_MVMODE_SPLIT) {
2463cabdff1aSopenharmony_ci                td->left_nnz[8]     = 0;
2464cabdff1aSopenharmony_ci                s->top_nnz[mb_x][8] = 0;
2465cabdff1aSopenharmony_ci            }
2466cabdff1aSopenharmony_ci        }
2467cabdff1aSopenharmony_ci
2468cabdff1aSopenharmony_ci        if (s->deblock_filter)
2469cabdff1aSopenharmony_ci            filter_level_for_mb(s, mb, &td->filter_strength[mb_x], is_vp7);
2470cabdff1aSopenharmony_ci
2471cabdff1aSopenharmony_ci        if (s->deblock_filter && num_jobs != 1 && threadnr == num_jobs - 1) {
2472cabdff1aSopenharmony_ci            if (s->filter.simple)
2473cabdff1aSopenharmony_ci                backup_mb_border(s->top_border[mb_x + 1], dst[0],
2474cabdff1aSopenharmony_ci                                 NULL, NULL, s->linesize, 0, 1);
2475cabdff1aSopenharmony_ci            else
2476cabdff1aSopenharmony_ci                backup_mb_border(s->top_border[mb_x + 1], dst[0],
2477cabdff1aSopenharmony_ci                                 dst[1], dst[2], s->linesize, s->uvlinesize, 0);
2478cabdff1aSopenharmony_ci        }
2479cabdff1aSopenharmony_ci
2480cabdff1aSopenharmony_ci        prefetch_motion(s, mb, mb_x, mb_y, mb_xy, VP56_FRAME_GOLDEN2);
2481cabdff1aSopenharmony_ci
2482cabdff1aSopenharmony_ci        dst[0]      += 16;
2483cabdff1aSopenharmony_ci        dst[1]      += 8;
2484cabdff1aSopenharmony_ci        dst[2]      += 8;
2485cabdff1aSopenharmony_ci        td->mv_bounds.mv_min.x -= 64;
2486cabdff1aSopenharmony_ci        td->mv_bounds.mv_max.x -= 64;
2487cabdff1aSopenharmony_ci
2488cabdff1aSopenharmony_ci        if (mb_x == s->mb_width + 1) {
2489cabdff1aSopenharmony_ci            update_pos(td, mb_y, s->mb_width + 3);
2490cabdff1aSopenharmony_ci        } else {
2491cabdff1aSopenharmony_ci            update_pos(td, mb_y, mb_x);
2492cabdff1aSopenharmony_ci        }
2493cabdff1aSopenharmony_ci    }
2494cabdff1aSopenharmony_ci    return 0;
2495cabdff1aSopenharmony_ci}
2496cabdff1aSopenharmony_ci
2497cabdff1aSopenharmony_cistatic int vp7_decode_mb_row_no_filter(AVCodecContext *avctx, void *tdata,
2498cabdff1aSopenharmony_ci                                        int jobnr, int threadnr)
2499cabdff1aSopenharmony_ci{
2500cabdff1aSopenharmony_ci    return decode_mb_row_no_filter(avctx, tdata, jobnr, threadnr, 1);
2501cabdff1aSopenharmony_ci}
2502cabdff1aSopenharmony_ci
2503cabdff1aSopenharmony_cistatic int vp8_decode_mb_row_no_filter(AVCodecContext *avctx, void *tdata,
2504cabdff1aSopenharmony_ci                                        int jobnr, int threadnr)
2505cabdff1aSopenharmony_ci{
2506cabdff1aSopenharmony_ci    return decode_mb_row_no_filter(avctx, tdata, jobnr, threadnr, 0);
2507cabdff1aSopenharmony_ci}
2508cabdff1aSopenharmony_ci
2509cabdff1aSopenharmony_cistatic av_always_inline void filter_mb_row(AVCodecContext *avctx, void *tdata,
2510cabdff1aSopenharmony_ci                              int jobnr, int threadnr, int is_vp7)
2511cabdff1aSopenharmony_ci{
2512cabdff1aSopenharmony_ci    VP8Context *s = avctx->priv_data;
2513cabdff1aSopenharmony_ci    VP8ThreadData *td = &s->thread_data[threadnr];
2514cabdff1aSopenharmony_ci    int mb_x, mb_y = atomic_load(&td->thread_mb_pos) >> 16, num_jobs = s->num_jobs;
2515cabdff1aSopenharmony_ci    AVFrame *curframe = s->curframe->tf.f;
2516cabdff1aSopenharmony_ci    VP8Macroblock *mb;
2517cabdff1aSopenharmony_ci    VP8ThreadData *prev_td, *next_td;
2518cabdff1aSopenharmony_ci    uint8_t *dst[3] = {
2519cabdff1aSopenharmony_ci        curframe->data[0] + 16 * mb_y * s->linesize,
2520cabdff1aSopenharmony_ci        curframe->data[1] +  8 * mb_y * s->uvlinesize,
2521cabdff1aSopenharmony_ci        curframe->data[2] +  8 * mb_y * s->uvlinesize
2522cabdff1aSopenharmony_ci    };
2523cabdff1aSopenharmony_ci
2524cabdff1aSopenharmony_ci    if (s->mb_layout == 1)
2525cabdff1aSopenharmony_ci        mb = s->macroblocks_base + ((s->mb_width + 1) * (mb_y + 1) + 1);
2526cabdff1aSopenharmony_ci    else
2527cabdff1aSopenharmony_ci        mb = s->macroblocks + (s->mb_height - mb_y - 1) * 2;
2528cabdff1aSopenharmony_ci
2529cabdff1aSopenharmony_ci    if (mb_y == 0)
2530cabdff1aSopenharmony_ci        prev_td = td;
2531cabdff1aSopenharmony_ci    else
2532cabdff1aSopenharmony_ci        prev_td = &s->thread_data[(jobnr + num_jobs - 1) % num_jobs];
2533cabdff1aSopenharmony_ci    if (mb_y == s->mb_height - 1)
2534cabdff1aSopenharmony_ci        next_td = td;
2535cabdff1aSopenharmony_ci    else
2536cabdff1aSopenharmony_ci        next_td = &s->thread_data[(jobnr + 1) % num_jobs];
2537cabdff1aSopenharmony_ci
2538cabdff1aSopenharmony_ci    for (mb_x = 0; mb_x < s->mb_width; mb_x++, mb++) {
2539cabdff1aSopenharmony_ci        VP8FilterStrength *f = &td->filter_strength[mb_x];
2540cabdff1aSopenharmony_ci        if (prev_td != td)
2541cabdff1aSopenharmony_ci            check_thread_pos(td, prev_td,
2542cabdff1aSopenharmony_ci                             (mb_x + 1) + (s->mb_width + 3), mb_y - 1);
2543cabdff1aSopenharmony_ci        if (next_td != td)
2544cabdff1aSopenharmony_ci            if (next_td != &s->thread_data[0])
2545cabdff1aSopenharmony_ci                check_thread_pos(td, next_td, mb_x + 1, mb_y + 1);
2546cabdff1aSopenharmony_ci
2547cabdff1aSopenharmony_ci        if (num_jobs == 1) {
2548cabdff1aSopenharmony_ci            if (s->filter.simple)
2549cabdff1aSopenharmony_ci                backup_mb_border(s->top_border[mb_x + 1], dst[0],
2550cabdff1aSopenharmony_ci                                 NULL, NULL, s->linesize, 0, 1);
2551cabdff1aSopenharmony_ci            else
2552cabdff1aSopenharmony_ci                backup_mb_border(s->top_border[mb_x + 1], dst[0],
2553cabdff1aSopenharmony_ci                                 dst[1], dst[2], s->linesize, s->uvlinesize, 0);
2554cabdff1aSopenharmony_ci        }
2555cabdff1aSopenharmony_ci
2556cabdff1aSopenharmony_ci        if (s->filter.simple)
2557cabdff1aSopenharmony_ci            filter_mb_simple(s, dst[0], f, mb_x, mb_y);
2558cabdff1aSopenharmony_ci        else
2559cabdff1aSopenharmony_ci            filter_mb(s, dst, f, mb_x, mb_y, is_vp7);
2560cabdff1aSopenharmony_ci        dst[0] += 16;
2561cabdff1aSopenharmony_ci        dst[1] += 8;
2562cabdff1aSopenharmony_ci        dst[2] += 8;
2563cabdff1aSopenharmony_ci
2564cabdff1aSopenharmony_ci        update_pos(td, mb_y, (s->mb_width + 3) + mb_x);
2565cabdff1aSopenharmony_ci    }
2566cabdff1aSopenharmony_ci}
2567cabdff1aSopenharmony_ci
2568cabdff1aSopenharmony_cistatic void vp7_filter_mb_row(AVCodecContext *avctx, void *tdata,
2569cabdff1aSopenharmony_ci                              int jobnr, int threadnr)
2570cabdff1aSopenharmony_ci{
2571cabdff1aSopenharmony_ci    filter_mb_row(avctx, tdata, jobnr, threadnr, 1);
2572cabdff1aSopenharmony_ci}
2573cabdff1aSopenharmony_ci
2574cabdff1aSopenharmony_cistatic void vp8_filter_mb_row(AVCodecContext *avctx, void *tdata,
2575cabdff1aSopenharmony_ci                              int jobnr, int threadnr)
2576cabdff1aSopenharmony_ci{
2577cabdff1aSopenharmony_ci    filter_mb_row(avctx, tdata, jobnr, threadnr, 0);
2578cabdff1aSopenharmony_ci}
2579cabdff1aSopenharmony_ci
2580cabdff1aSopenharmony_cistatic av_always_inline
2581cabdff1aSopenharmony_ciint vp78_decode_mb_row_sliced(AVCodecContext *avctx, void *tdata, int jobnr,
2582cabdff1aSopenharmony_ci                              int threadnr, int is_vp7)
2583cabdff1aSopenharmony_ci{
2584cabdff1aSopenharmony_ci    VP8Context *s = avctx->priv_data;
2585cabdff1aSopenharmony_ci    VP8ThreadData *td = &s->thread_data[jobnr];
2586cabdff1aSopenharmony_ci    VP8ThreadData *next_td = NULL, *prev_td = NULL;
2587cabdff1aSopenharmony_ci    VP8Frame *curframe = s->curframe;
2588cabdff1aSopenharmony_ci    int mb_y, num_jobs = s->num_jobs;
2589cabdff1aSopenharmony_ci    int ret;
2590cabdff1aSopenharmony_ci
2591cabdff1aSopenharmony_ci    td->thread_nr = threadnr;
2592cabdff1aSopenharmony_ci    td->mv_bounds.mv_min.y   = -MARGIN - 64 * threadnr;
2593cabdff1aSopenharmony_ci    td->mv_bounds.mv_max.y   = ((s->mb_height - 1) << 6) + MARGIN - 64 * threadnr;
2594cabdff1aSopenharmony_ci    for (mb_y = jobnr; mb_y < s->mb_height; mb_y += num_jobs) {
2595cabdff1aSopenharmony_ci        atomic_store(&td->thread_mb_pos, mb_y << 16);
2596cabdff1aSopenharmony_ci        ret = s->decode_mb_row_no_filter(avctx, tdata, jobnr, threadnr);
2597cabdff1aSopenharmony_ci        if (ret < 0) {
2598cabdff1aSopenharmony_ci            update_pos(td, s->mb_height, INT_MAX & 0xFFFF);
2599cabdff1aSopenharmony_ci            return ret;
2600cabdff1aSopenharmony_ci        }
2601cabdff1aSopenharmony_ci        if (s->deblock_filter)
2602cabdff1aSopenharmony_ci            s->filter_mb_row(avctx, tdata, jobnr, threadnr);
2603cabdff1aSopenharmony_ci        update_pos(td, mb_y, INT_MAX & 0xFFFF);
2604cabdff1aSopenharmony_ci
2605cabdff1aSopenharmony_ci        td->mv_bounds.mv_min.y -= 64 * num_jobs;
2606cabdff1aSopenharmony_ci        td->mv_bounds.mv_max.y -= 64 * num_jobs;
2607cabdff1aSopenharmony_ci
2608cabdff1aSopenharmony_ci        if (avctx->active_thread_type == FF_THREAD_FRAME)
2609cabdff1aSopenharmony_ci            ff_thread_report_progress(&curframe->tf, mb_y, 0);
2610cabdff1aSopenharmony_ci    }
2611cabdff1aSopenharmony_ci
2612cabdff1aSopenharmony_ci    return 0;
2613cabdff1aSopenharmony_ci}
2614cabdff1aSopenharmony_ci
2615cabdff1aSopenharmony_cistatic int vp7_decode_mb_row_sliced(AVCodecContext *avctx, void *tdata,
2616cabdff1aSopenharmony_ci                                    int jobnr, int threadnr)
2617cabdff1aSopenharmony_ci{
2618cabdff1aSopenharmony_ci    return vp78_decode_mb_row_sliced(avctx, tdata, jobnr, threadnr, IS_VP7);
2619cabdff1aSopenharmony_ci}
2620cabdff1aSopenharmony_ci
2621cabdff1aSopenharmony_cistatic int vp8_decode_mb_row_sliced(AVCodecContext *avctx, void *tdata,
2622cabdff1aSopenharmony_ci                                    int jobnr, int threadnr)
2623cabdff1aSopenharmony_ci{
2624cabdff1aSopenharmony_ci    return vp78_decode_mb_row_sliced(avctx, tdata, jobnr, threadnr, IS_VP8);
2625cabdff1aSopenharmony_ci}
2626cabdff1aSopenharmony_ci
2627cabdff1aSopenharmony_cistatic av_always_inline
2628cabdff1aSopenharmony_ciint vp78_decode_frame(AVCodecContext *avctx, AVFrame *rframe, int *got_frame,
2629cabdff1aSopenharmony_ci                      const AVPacket *avpkt, int is_vp7)
2630cabdff1aSopenharmony_ci{
2631cabdff1aSopenharmony_ci    VP8Context *s = avctx->priv_data;
2632cabdff1aSopenharmony_ci    int ret, i, referenced, num_jobs;
2633cabdff1aSopenharmony_ci    enum AVDiscard skip_thresh;
2634cabdff1aSopenharmony_ci    VP8Frame *av_uninit(curframe), *prev_frame;
2635cabdff1aSopenharmony_ci
2636cabdff1aSopenharmony_ci    if (is_vp7)
2637cabdff1aSopenharmony_ci        ret = vp7_decode_frame_header(s, avpkt->data, avpkt->size);
2638cabdff1aSopenharmony_ci    else
2639cabdff1aSopenharmony_ci        ret = vp8_decode_frame_header(s, avpkt->data, avpkt->size);
2640cabdff1aSopenharmony_ci
2641cabdff1aSopenharmony_ci    if (ret < 0)
2642cabdff1aSopenharmony_ci        goto err;
2643cabdff1aSopenharmony_ci
2644cabdff1aSopenharmony_ci    if (s->actually_webp) {
2645cabdff1aSopenharmony_ci        // avctx->pix_fmt already set in caller.
2646cabdff1aSopenharmony_ci    } else if (!is_vp7 && s->pix_fmt == AV_PIX_FMT_NONE) {
2647cabdff1aSopenharmony_ci        s->pix_fmt = get_pixel_format(s);
2648cabdff1aSopenharmony_ci        if (s->pix_fmt < 0) {
2649cabdff1aSopenharmony_ci            ret = AVERROR(EINVAL);
2650cabdff1aSopenharmony_ci            goto err;
2651cabdff1aSopenharmony_ci        }
2652cabdff1aSopenharmony_ci        avctx->pix_fmt = s->pix_fmt;
2653cabdff1aSopenharmony_ci    }
2654cabdff1aSopenharmony_ci
2655cabdff1aSopenharmony_ci    prev_frame = s->framep[VP56_FRAME_CURRENT];
2656cabdff1aSopenharmony_ci
2657cabdff1aSopenharmony_ci    referenced = s->update_last || s->update_golden == VP56_FRAME_CURRENT ||
2658cabdff1aSopenharmony_ci                 s->update_altref == VP56_FRAME_CURRENT;
2659cabdff1aSopenharmony_ci
2660cabdff1aSopenharmony_ci    skip_thresh = !referenced ? AVDISCARD_NONREF
2661cabdff1aSopenharmony_ci                              : !s->keyframe ? AVDISCARD_NONKEY
2662cabdff1aSopenharmony_ci                                             : AVDISCARD_ALL;
2663cabdff1aSopenharmony_ci
2664cabdff1aSopenharmony_ci    if (avctx->skip_frame >= skip_thresh) {
2665cabdff1aSopenharmony_ci        s->invisible = 1;
2666cabdff1aSopenharmony_ci        memcpy(&s->next_framep[0], &s->framep[0], sizeof(s->framep[0]) * 4);
2667cabdff1aSopenharmony_ci        goto skip_decode;
2668cabdff1aSopenharmony_ci    }
2669cabdff1aSopenharmony_ci    s->deblock_filter = s->filter.level && avctx->skip_loop_filter < skip_thresh;
2670cabdff1aSopenharmony_ci
2671cabdff1aSopenharmony_ci    // release no longer referenced frames
2672cabdff1aSopenharmony_ci    for (i = 0; i < 5; i++)
2673cabdff1aSopenharmony_ci        if (s->frames[i].tf.f->buf[0] &&
2674cabdff1aSopenharmony_ci            &s->frames[i] != prev_frame &&
2675cabdff1aSopenharmony_ci            &s->frames[i] != s->framep[VP56_FRAME_PREVIOUS] &&
2676cabdff1aSopenharmony_ci            &s->frames[i] != s->framep[VP56_FRAME_GOLDEN]   &&
2677cabdff1aSopenharmony_ci            &s->frames[i] != s->framep[VP56_FRAME_GOLDEN2])
2678cabdff1aSopenharmony_ci            vp8_release_frame(s, &s->frames[i]);
2679cabdff1aSopenharmony_ci
2680cabdff1aSopenharmony_ci    curframe = s->framep[VP56_FRAME_CURRENT] = vp8_find_free_buffer(s);
2681cabdff1aSopenharmony_ci
2682cabdff1aSopenharmony_ci    if (!s->colorspace)
2683cabdff1aSopenharmony_ci        avctx->colorspace = AVCOL_SPC_BT470BG;
2684cabdff1aSopenharmony_ci    if (s->fullrange)
2685cabdff1aSopenharmony_ci        avctx->color_range = AVCOL_RANGE_JPEG;
2686cabdff1aSopenharmony_ci    else
2687cabdff1aSopenharmony_ci        avctx->color_range = AVCOL_RANGE_MPEG;
2688cabdff1aSopenharmony_ci
2689cabdff1aSopenharmony_ci    /* Given that arithmetic probabilities are updated every frame, it's quite
2690cabdff1aSopenharmony_ci     * likely that the values we have on a random interframe are complete
2691cabdff1aSopenharmony_ci     * junk if we didn't start decode on a keyframe. So just don't display
2692cabdff1aSopenharmony_ci     * anything rather than junk. */
2693cabdff1aSopenharmony_ci    if (!s->keyframe && (!s->framep[VP56_FRAME_PREVIOUS] ||
2694cabdff1aSopenharmony_ci                         !s->framep[VP56_FRAME_GOLDEN]   ||
2695cabdff1aSopenharmony_ci                         !s->framep[VP56_FRAME_GOLDEN2])) {
2696cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_WARNING,
2697cabdff1aSopenharmony_ci               "Discarding interframe without a prior keyframe!\n");
2698cabdff1aSopenharmony_ci        ret = AVERROR_INVALIDDATA;
2699cabdff1aSopenharmony_ci        goto err;
2700cabdff1aSopenharmony_ci    }
2701cabdff1aSopenharmony_ci
2702cabdff1aSopenharmony_ci    curframe->tf.f->key_frame = s->keyframe;
2703cabdff1aSopenharmony_ci    curframe->tf.f->pict_type = s->keyframe ? AV_PICTURE_TYPE_I
2704cabdff1aSopenharmony_ci                                            : AV_PICTURE_TYPE_P;
2705cabdff1aSopenharmony_ci    if ((ret = vp8_alloc_frame(s, curframe, referenced)) < 0)
2706cabdff1aSopenharmony_ci        goto err;
2707cabdff1aSopenharmony_ci
2708cabdff1aSopenharmony_ci    // check if golden and altref are swapped
2709cabdff1aSopenharmony_ci    if (s->update_altref != VP56_FRAME_NONE)
2710cabdff1aSopenharmony_ci        s->next_framep[VP56_FRAME_GOLDEN2] = s->framep[s->update_altref];
2711cabdff1aSopenharmony_ci    else
2712cabdff1aSopenharmony_ci        s->next_framep[VP56_FRAME_GOLDEN2] = s->framep[VP56_FRAME_GOLDEN2];
2713cabdff1aSopenharmony_ci
2714cabdff1aSopenharmony_ci    if (s->update_golden != VP56_FRAME_NONE)
2715cabdff1aSopenharmony_ci        s->next_framep[VP56_FRAME_GOLDEN] = s->framep[s->update_golden];
2716cabdff1aSopenharmony_ci    else
2717cabdff1aSopenharmony_ci        s->next_framep[VP56_FRAME_GOLDEN] = s->framep[VP56_FRAME_GOLDEN];
2718cabdff1aSopenharmony_ci
2719cabdff1aSopenharmony_ci    if (s->update_last)
2720cabdff1aSopenharmony_ci        s->next_framep[VP56_FRAME_PREVIOUS] = curframe;
2721cabdff1aSopenharmony_ci    else
2722cabdff1aSopenharmony_ci        s->next_framep[VP56_FRAME_PREVIOUS] = s->framep[VP56_FRAME_PREVIOUS];
2723cabdff1aSopenharmony_ci
2724cabdff1aSopenharmony_ci    s->next_framep[VP56_FRAME_CURRENT] = curframe;
2725cabdff1aSopenharmony_ci
2726cabdff1aSopenharmony_ci    if (ffcodec(avctx->codec)->update_thread_context)
2727cabdff1aSopenharmony_ci        ff_thread_finish_setup(avctx);
2728cabdff1aSopenharmony_ci
2729cabdff1aSopenharmony_ci    if (avctx->hwaccel) {
2730cabdff1aSopenharmony_ci        ret = avctx->hwaccel->start_frame(avctx, avpkt->data, avpkt->size);
2731cabdff1aSopenharmony_ci        if (ret < 0)
2732cabdff1aSopenharmony_ci            goto err;
2733cabdff1aSopenharmony_ci
2734cabdff1aSopenharmony_ci        ret = avctx->hwaccel->decode_slice(avctx, avpkt->data, avpkt->size);
2735cabdff1aSopenharmony_ci        if (ret < 0)
2736cabdff1aSopenharmony_ci            goto err;
2737cabdff1aSopenharmony_ci
2738cabdff1aSopenharmony_ci        ret = avctx->hwaccel->end_frame(avctx);
2739cabdff1aSopenharmony_ci        if (ret < 0)
2740cabdff1aSopenharmony_ci            goto err;
2741cabdff1aSopenharmony_ci
2742cabdff1aSopenharmony_ci    } else {
2743cabdff1aSopenharmony_ci        s->linesize   = curframe->tf.f->linesize[0];
2744cabdff1aSopenharmony_ci        s->uvlinesize = curframe->tf.f->linesize[1];
2745cabdff1aSopenharmony_ci
2746cabdff1aSopenharmony_ci        memset(s->top_nnz, 0, s->mb_width * sizeof(*s->top_nnz));
2747cabdff1aSopenharmony_ci        /* Zero macroblock structures for top/top-left prediction
2748cabdff1aSopenharmony_ci         * from outside the frame. */
2749cabdff1aSopenharmony_ci        if (!s->mb_layout)
2750cabdff1aSopenharmony_ci            memset(s->macroblocks + s->mb_height * 2 - 1, 0,
2751cabdff1aSopenharmony_ci                   (s->mb_width + 1) * sizeof(*s->macroblocks));
2752cabdff1aSopenharmony_ci        if (!s->mb_layout && s->keyframe)
2753cabdff1aSopenharmony_ci            memset(s->intra4x4_pred_mode_top, DC_PRED, s->mb_width * 4);
2754cabdff1aSopenharmony_ci
2755cabdff1aSopenharmony_ci        memset(s->ref_count, 0, sizeof(s->ref_count));
2756cabdff1aSopenharmony_ci
2757cabdff1aSopenharmony_ci        if (s->mb_layout == 1) {
2758cabdff1aSopenharmony_ci            // Make sure the previous frame has read its segmentation map,
2759cabdff1aSopenharmony_ci            // if we re-use the same map.
2760cabdff1aSopenharmony_ci            if (prev_frame && s->segmentation.enabled &&
2761cabdff1aSopenharmony_ci                !s->segmentation.update_map)
2762cabdff1aSopenharmony_ci                ff_thread_await_progress(&prev_frame->tf, 1, 0);
2763cabdff1aSopenharmony_ci            if (is_vp7)
2764cabdff1aSopenharmony_ci                ret = vp7_decode_mv_mb_modes(avctx, curframe, prev_frame);
2765cabdff1aSopenharmony_ci            else
2766cabdff1aSopenharmony_ci                ret = vp8_decode_mv_mb_modes(avctx, curframe, prev_frame);
2767cabdff1aSopenharmony_ci            if (ret < 0)
2768cabdff1aSopenharmony_ci                goto err;
2769cabdff1aSopenharmony_ci        }
2770cabdff1aSopenharmony_ci
2771cabdff1aSopenharmony_ci        if (avctx->active_thread_type == FF_THREAD_FRAME)
2772cabdff1aSopenharmony_ci            num_jobs = 1;
2773cabdff1aSopenharmony_ci        else
2774cabdff1aSopenharmony_ci            num_jobs = FFMIN(s->num_coeff_partitions, avctx->thread_count);
2775cabdff1aSopenharmony_ci        s->num_jobs   = num_jobs;
2776cabdff1aSopenharmony_ci        s->curframe   = curframe;
2777cabdff1aSopenharmony_ci        s->prev_frame = prev_frame;
2778cabdff1aSopenharmony_ci        s->mv_bounds.mv_min.y   = -MARGIN;
2779cabdff1aSopenharmony_ci        s->mv_bounds.mv_max.y   = ((s->mb_height - 1) << 6) + MARGIN;
2780cabdff1aSopenharmony_ci        for (i = 0; i < MAX_THREADS; i++) {
2781cabdff1aSopenharmony_ci            VP8ThreadData *td = &s->thread_data[i];
2782cabdff1aSopenharmony_ci            atomic_init(&td->thread_mb_pos, 0);
2783cabdff1aSopenharmony_ci            atomic_init(&td->wait_mb_pos, INT_MAX);
2784cabdff1aSopenharmony_ci        }
2785cabdff1aSopenharmony_ci        if (is_vp7)
2786cabdff1aSopenharmony_ci            avctx->execute2(avctx, vp7_decode_mb_row_sliced, s->thread_data, NULL,
2787cabdff1aSopenharmony_ci                            num_jobs);
2788cabdff1aSopenharmony_ci        else
2789cabdff1aSopenharmony_ci            avctx->execute2(avctx, vp8_decode_mb_row_sliced, s->thread_data, NULL,
2790cabdff1aSopenharmony_ci                            num_jobs);
2791cabdff1aSopenharmony_ci    }
2792cabdff1aSopenharmony_ci
2793cabdff1aSopenharmony_ci    ff_thread_report_progress(&curframe->tf, INT_MAX, 0);
2794cabdff1aSopenharmony_ci    memcpy(&s->framep[0], &s->next_framep[0], sizeof(s->framep[0]) * 4);
2795cabdff1aSopenharmony_ci
2796cabdff1aSopenharmony_ciskip_decode:
2797cabdff1aSopenharmony_ci    // if future frames don't use the updated probabilities,
2798cabdff1aSopenharmony_ci    // reset them to the values we saved
2799cabdff1aSopenharmony_ci    if (!s->update_probabilities)
2800cabdff1aSopenharmony_ci        s->prob[0] = s->prob[1];
2801cabdff1aSopenharmony_ci
2802cabdff1aSopenharmony_ci    if (!s->invisible) {
2803cabdff1aSopenharmony_ci        if ((ret = av_frame_ref(rframe, curframe->tf.f)) < 0)
2804cabdff1aSopenharmony_ci            return ret;
2805cabdff1aSopenharmony_ci        *got_frame = 1;
2806cabdff1aSopenharmony_ci    }
2807cabdff1aSopenharmony_ci
2808cabdff1aSopenharmony_ci    return avpkt->size;
2809cabdff1aSopenharmony_cierr:
2810cabdff1aSopenharmony_ci    memcpy(&s->next_framep[0], &s->framep[0], sizeof(s->framep[0]) * 4);
2811cabdff1aSopenharmony_ci    return ret;
2812cabdff1aSopenharmony_ci}
2813cabdff1aSopenharmony_ci
2814cabdff1aSopenharmony_ciint ff_vp8_decode_frame(AVCodecContext *avctx, AVFrame *frame,
2815cabdff1aSopenharmony_ci                        int *got_frame, AVPacket *avpkt)
2816cabdff1aSopenharmony_ci{
2817cabdff1aSopenharmony_ci    return vp78_decode_frame(avctx, frame, got_frame, avpkt, IS_VP8);
2818cabdff1aSopenharmony_ci}
2819cabdff1aSopenharmony_ci
2820cabdff1aSopenharmony_ci#if CONFIG_VP7_DECODER
2821cabdff1aSopenharmony_cistatic int vp7_decode_frame(AVCodecContext *avctx, AVFrame *frame,
2822cabdff1aSopenharmony_ci                            int *got_frame, AVPacket *avpkt)
2823cabdff1aSopenharmony_ci{
2824cabdff1aSopenharmony_ci    return vp78_decode_frame(avctx, frame, got_frame, avpkt, IS_VP7);
2825cabdff1aSopenharmony_ci}
2826cabdff1aSopenharmony_ci#endif /* CONFIG_VP7_DECODER */
2827cabdff1aSopenharmony_ci
2828cabdff1aSopenharmony_ciav_cold int ff_vp8_decode_free(AVCodecContext *avctx)
2829cabdff1aSopenharmony_ci{
2830cabdff1aSopenharmony_ci    VP8Context *s = avctx->priv_data;
2831cabdff1aSopenharmony_ci    int i;
2832cabdff1aSopenharmony_ci
2833cabdff1aSopenharmony_ci    vp8_decode_flush_impl(avctx, 1);
2834cabdff1aSopenharmony_ci    for (i = 0; i < FF_ARRAY_ELEMS(s->frames); i++)
2835cabdff1aSopenharmony_ci        av_frame_free(&s->frames[i].tf.f);
2836cabdff1aSopenharmony_ci
2837cabdff1aSopenharmony_ci    return 0;
2838cabdff1aSopenharmony_ci}
2839cabdff1aSopenharmony_ci
2840cabdff1aSopenharmony_cistatic av_cold int vp8_init_frames(VP8Context *s)
2841cabdff1aSopenharmony_ci{
2842cabdff1aSopenharmony_ci    int i;
2843cabdff1aSopenharmony_ci    for (i = 0; i < FF_ARRAY_ELEMS(s->frames); i++) {
2844cabdff1aSopenharmony_ci        s->frames[i].tf.f = av_frame_alloc();
2845cabdff1aSopenharmony_ci        if (!s->frames[i].tf.f)
2846cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
2847cabdff1aSopenharmony_ci    }
2848cabdff1aSopenharmony_ci    return 0;
2849cabdff1aSopenharmony_ci}
2850cabdff1aSopenharmony_ci
2851cabdff1aSopenharmony_cistatic av_always_inline
2852cabdff1aSopenharmony_ciint vp78_decode_init(AVCodecContext *avctx, int is_vp7)
2853cabdff1aSopenharmony_ci{
2854cabdff1aSopenharmony_ci    VP8Context *s = avctx->priv_data;
2855cabdff1aSopenharmony_ci    int ret;
2856cabdff1aSopenharmony_ci
2857cabdff1aSopenharmony_ci    s->avctx = avctx;
2858cabdff1aSopenharmony_ci    s->vp7   = avctx->codec->id == AV_CODEC_ID_VP7;
2859cabdff1aSopenharmony_ci    s->pix_fmt = AV_PIX_FMT_NONE;
2860cabdff1aSopenharmony_ci    avctx->pix_fmt = AV_PIX_FMT_YUV420P;
2861cabdff1aSopenharmony_ci
2862cabdff1aSopenharmony_ci    ff_videodsp_init(&s->vdsp, 8);
2863cabdff1aSopenharmony_ci
2864cabdff1aSopenharmony_ci    ff_vp78dsp_init(&s->vp8dsp);
2865cabdff1aSopenharmony_ci    if (CONFIG_VP7_DECODER && is_vp7) {
2866cabdff1aSopenharmony_ci        ff_h264_pred_init(&s->hpc, AV_CODEC_ID_VP7, 8, 1);
2867cabdff1aSopenharmony_ci        ff_vp7dsp_init(&s->vp8dsp);
2868cabdff1aSopenharmony_ci        s->decode_mb_row_no_filter = vp7_decode_mb_row_no_filter;
2869cabdff1aSopenharmony_ci        s->filter_mb_row           = vp7_filter_mb_row;
2870cabdff1aSopenharmony_ci    } else if (CONFIG_VP8_DECODER && !is_vp7) {
2871cabdff1aSopenharmony_ci        ff_h264_pred_init(&s->hpc, AV_CODEC_ID_VP8, 8, 1);
2872cabdff1aSopenharmony_ci        ff_vp8dsp_init(&s->vp8dsp);
2873cabdff1aSopenharmony_ci        s->decode_mb_row_no_filter = vp8_decode_mb_row_no_filter;
2874cabdff1aSopenharmony_ci        s->filter_mb_row           = vp8_filter_mb_row;
2875cabdff1aSopenharmony_ci    }
2876cabdff1aSopenharmony_ci
2877cabdff1aSopenharmony_ci    /* does not change for VP8 */
2878cabdff1aSopenharmony_ci    memcpy(s->prob[0].scan, ff_zigzag_scan, sizeof(s->prob[0].scan));
2879cabdff1aSopenharmony_ci
2880cabdff1aSopenharmony_ci    if ((ret = vp8_init_frames(s)) < 0) {
2881cabdff1aSopenharmony_ci        ff_vp8_decode_free(avctx);
2882cabdff1aSopenharmony_ci        return ret;
2883cabdff1aSopenharmony_ci    }
2884cabdff1aSopenharmony_ci
2885cabdff1aSopenharmony_ci    return 0;
2886cabdff1aSopenharmony_ci}
2887cabdff1aSopenharmony_ci
2888cabdff1aSopenharmony_ci#if CONFIG_VP7_DECODER
2889cabdff1aSopenharmony_cistatic int vp7_decode_init(AVCodecContext *avctx)
2890cabdff1aSopenharmony_ci{
2891cabdff1aSopenharmony_ci    return vp78_decode_init(avctx, IS_VP7);
2892cabdff1aSopenharmony_ci}
2893cabdff1aSopenharmony_ci#endif /* CONFIG_VP7_DECODER */
2894cabdff1aSopenharmony_ci
2895cabdff1aSopenharmony_ciav_cold int ff_vp8_decode_init(AVCodecContext *avctx)
2896cabdff1aSopenharmony_ci{
2897cabdff1aSopenharmony_ci    return vp78_decode_init(avctx, IS_VP8);
2898cabdff1aSopenharmony_ci}
2899cabdff1aSopenharmony_ci
2900cabdff1aSopenharmony_ci#if CONFIG_VP8_DECODER
2901cabdff1aSopenharmony_ci#if HAVE_THREADS
2902cabdff1aSopenharmony_ci#define REBASE(pic) ((pic) ? (pic) - &s_src->frames[0] + &s->frames[0] : NULL)
2903cabdff1aSopenharmony_ci
2904cabdff1aSopenharmony_cistatic int vp8_decode_update_thread_context(AVCodecContext *dst,
2905cabdff1aSopenharmony_ci                                            const AVCodecContext *src)
2906cabdff1aSopenharmony_ci{
2907cabdff1aSopenharmony_ci    VP8Context *s = dst->priv_data, *s_src = src->priv_data;
2908cabdff1aSopenharmony_ci    int i;
2909cabdff1aSopenharmony_ci
2910cabdff1aSopenharmony_ci    if (s->macroblocks_base &&
2911cabdff1aSopenharmony_ci        (s_src->mb_width != s->mb_width || s_src->mb_height != s->mb_height)) {
2912cabdff1aSopenharmony_ci        free_buffers(s);
2913cabdff1aSopenharmony_ci        s->mb_width  = s_src->mb_width;
2914cabdff1aSopenharmony_ci        s->mb_height = s_src->mb_height;
2915cabdff1aSopenharmony_ci    }
2916cabdff1aSopenharmony_ci
2917cabdff1aSopenharmony_ci    s->pix_fmt      = s_src->pix_fmt;
2918cabdff1aSopenharmony_ci    s->prob[0]      = s_src->prob[!s_src->update_probabilities];
2919cabdff1aSopenharmony_ci    s->segmentation = s_src->segmentation;
2920cabdff1aSopenharmony_ci    s->lf_delta     = s_src->lf_delta;
2921cabdff1aSopenharmony_ci    memcpy(s->sign_bias, s_src->sign_bias, sizeof(s->sign_bias));
2922cabdff1aSopenharmony_ci
2923cabdff1aSopenharmony_ci    for (i = 0; i < FF_ARRAY_ELEMS(s_src->frames); i++) {
2924cabdff1aSopenharmony_ci        if (s_src->frames[i].tf.f->buf[0]) {
2925cabdff1aSopenharmony_ci            int ret = vp8_ref_frame(s, &s->frames[i], &s_src->frames[i]);
2926cabdff1aSopenharmony_ci            if (ret < 0)
2927cabdff1aSopenharmony_ci                return ret;
2928cabdff1aSopenharmony_ci        }
2929cabdff1aSopenharmony_ci    }
2930cabdff1aSopenharmony_ci
2931cabdff1aSopenharmony_ci    s->framep[0] = REBASE(s_src->next_framep[0]);
2932cabdff1aSopenharmony_ci    s->framep[1] = REBASE(s_src->next_framep[1]);
2933cabdff1aSopenharmony_ci    s->framep[2] = REBASE(s_src->next_framep[2]);
2934cabdff1aSopenharmony_ci    s->framep[3] = REBASE(s_src->next_framep[3]);
2935cabdff1aSopenharmony_ci
2936cabdff1aSopenharmony_ci    return 0;
2937cabdff1aSopenharmony_ci}
2938cabdff1aSopenharmony_ci#endif /* HAVE_THREADS */
2939cabdff1aSopenharmony_ci#endif /* CONFIG_VP8_DECODER */
2940cabdff1aSopenharmony_ci
2941cabdff1aSopenharmony_ci#if CONFIG_VP7_DECODER
2942cabdff1aSopenharmony_ciconst FFCodec ff_vp7_decoder = {
2943cabdff1aSopenharmony_ci    .p.name                = "vp7",
2944cabdff1aSopenharmony_ci    .p.long_name           = NULL_IF_CONFIG_SMALL("On2 VP7"),
2945cabdff1aSopenharmony_ci    .p.type                = AVMEDIA_TYPE_VIDEO,
2946cabdff1aSopenharmony_ci    .p.id                  = AV_CODEC_ID_VP7,
2947cabdff1aSopenharmony_ci    .priv_data_size        = sizeof(VP8Context),
2948cabdff1aSopenharmony_ci    .init                  = vp7_decode_init,
2949cabdff1aSopenharmony_ci    .close                 = ff_vp8_decode_free,
2950cabdff1aSopenharmony_ci    FF_CODEC_DECODE_CB(vp7_decode_frame),
2951cabdff1aSopenharmony_ci    .p.capabilities        = AV_CODEC_CAP_DR1,
2952cabdff1aSopenharmony_ci    .caps_internal         = FF_CODEC_CAP_INIT_THREADSAFE,
2953cabdff1aSopenharmony_ci    .flush                 = vp8_decode_flush,
2954cabdff1aSopenharmony_ci};
2955cabdff1aSopenharmony_ci#endif /* CONFIG_VP7_DECODER */
2956cabdff1aSopenharmony_ci
2957cabdff1aSopenharmony_ci#if CONFIG_VP8_DECODER
2958cabdff1aSopenharmony_ciconst FFCodec ff_vp8_decoder = {
2959cabdff1aSopenharmony_ci    .p.name                = "vp8",
2960cabdff1aSopenharmony_ci    .p.long_name           = NULL_IF_CONFIG_SMALL("On2 VP8"),
2961cabdff1aSopenharmony_ci    .p.type                = AVMEDIA_TYPE_VIDEO,
2962cabdff1aSopenharmony_ci    .p.id                  = AV_CODEC_ID_VP8,
2963cabdff1aSopenharmony_ci    .priv_data_size        = sizeof(VP8Context),
2964cabdff1aSopenharmony_ci    .init                  = ff_vp8_decode_init,
2965cabdff1aSopenharmony_ci    .close                 = ff_vp8_decode_free,
2966cabdff1aSopenharmony_ci    FF_CODEC_DECODE_CB(ff_vp8_decode_frame),
2967cabdff1aSopenharmony_ci    .p.capabilities        = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |
2968cabdff1aSopenharmony_ci                             AV_CODEC_CAP_SLICE_THREADS,
2969cabdff1aSopenharmony_ci    .caps_internal         = FF_CODEC_CAP_INIT_THREADSAFE |
2970cabdff1aSopenharmony_ci                             FF_CODEC_CAP_ALLOCATE_PROGRESS,
2971cabdff1aSopenharmony_ci    .flush                 = vp8_decode_flush,
2972cabdff1aSopenharmony_ci    .update_thread_context = ONLY_IF_THREADS_ENABLED(vp8_decode_update_thread_context),
2973cabdff1aSopenharmony_ci    .hw_configs            = (const AVCodecHWConfigInternal *const []) {
2974cabdff1aSopenharmony_ci#if CONFIG_VP8_VAAPI_HWACCEL
2975cabdff1aSopenharmony_ci                               HWACCEL_VAAPI(vp8),
2976cabdff1aSopenharmony_ci#endif
2977cabdff1aSopenharmony_ci#if CONFIG_VP8_NVDEC_HWACCEL
2978cabdff1aSopenharmony_ci                               HWACCEL_NVDEC(vp8),
2979cabdff1aSopenharmony_ci#endif
2980cabdff1aSopenharmony_ci                               NULL
2981cabdff1aSopenharmony_ci                           },
2982cabdff1aSopenharmony_ci};
2983cabdff1aSopenharmony_ci#endif /* CONFIG_VP7_DECODER */
2984