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, ©, 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