1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * VP9 compatible video decoder 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * Copyright (C) 2013 Ronald S. Bultje <rsbultje gmail com> 5cabdff1aSopenharmony_ci * Copyright (C) 2013 Clément Bœsch <u pkh me> 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * This file is part of FFmpeg. 8cabdff1aSopenharmony_ci * 9cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 10cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 11cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 12cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 13cabdff1aSopenharmony_ci * 14cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 15cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 16cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17cabdff1aSopenharmony_ci * Lesser General Public License for more details. 18cabdff1aSopenharmony_ci * 19cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 20cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 21cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 22cabdff1aSopenharmony_ci */ 23cabdff1aSopenharmony_ci 24cabdff1aSopenharmony_ci#include "threadframe.h" 25cabdff1aSopenharmony_ci#include "vp56.h" 26cabdff1aSopenharmony_ci#include "vp9.h" 27cabdff1aSopenharmony_ci#include "vp9data.h" 28cabdff1aSopenharmony_ci#include "vp9dec.h" 29cabdff1aSopenharmony_ci 30cabdff1aSopenharmony_cistatic av_always_inline void clamp_mv(VP56mv *dst, const VP56mv *src, 31cabdff1aSopenharmony_ci VP9TileData *td) 32cabdff1aSopenharmony_ci{ 33cabdff1aSopenharmony_ci dst->x = av_clip(src->x, td->min_mv.x, td->max_mv.x); 34cabdff1aSopenharmony_ci dst->y = av_clip(src->y, td->min_mv.y, td->max_mv.y); 35cabdff1aSopenharmony_ci} 36cabdff1aSopenharmony_ci 37cabdff1aSopenharmony_cistatic void find_ref_mvs(VP9TileData *td, 38cabdff1aSopenharmony_ci VP56mv *pmv, int ref, int z, int idx, int sb) 39cabdff1aSopenharmony_ci{ 40cabdff1aSopenharmony_ci static const int8_t mv_ref_blk_off[N_BS_SIZES][8][2] = { 41cabdff1aSopenharmony_ci [BS_64x64] = { { 3, -1 }, { -1, 3 }, { 4, -1 }, { -1, 4 }, 42cabdff1aSopenharmony_ci { -1, -1 }, { 0, -1 }, { -1, 0 }, { 6, -1 } }, 43cabdff1aSopenharmony_ci [BS_64x32] = { { 0, -1 }, { -1, 0 }, { 4, -1 }, { -1, 2 }, 44cabdff1aSopenharmony_ci { -1, -1 }, { 0, -3 }, { -3, 0 }, { 2, -1 } }, 45cabdff1aSopenharmony_ci [BS_32x64] = { { -1, 0 }, { 0, -1 }, { -1, 4 }, { 2, -1 }, 46cabdff1aSopenharmony_ci { -1, -1 }, { -3, 0 }, { 0, -3 }, { -1, 2 } }, 47cabdff1aSopenharmony_ci [BS_32x32] = { { 1, -1 }, { -1, 1 }, { 2, -1 }, { -1, 2 }, 48cabdff1aSopenharmony_ci { -1, -1 }, { 0, -3 }, { -3, 0 }, { -3, -3 } }, 49cabdff1aSopenharmony_ci [BS_32x16] = { { 0, -1 }, { -1, 0 }, { 2, -1 }, { -1, -1 }, 50cabdff1aSopenharmony_ci { -1, 1 }, { 0, -3 }, { -3, 0 }, { -3, -3 } }, 51cabdff1aSopenharmony_ci [BS_16x32] = { { -1, 0 }, { 0, -1 }, { -1, 2 }, { -1, -1 }, 52cabdff1aSopenharmony_ci { 1, -1 }, { -3, 0 }, { 0, -3 }, { -3, -3 } }, 53cabdff1aSopenharmony_ci [BS_16x16] = { { 0, -1 }, { -1, 0 }, { 1, -1 }, { -1, 1 }, 54cabdff1aSopenharmony_ci { -1, -1 }, { 0, -3 }, { -3, 0 }, { -3, -3 } }, 55cabdff1aSopenharmony_ci [BS_16x8] = { { 0, -1 }, { -1, 0 }, { 1, -1 }, { -1, -1 }, 56cabdff1aSopenharmony_ci { 0, -2 }, { -2, 0 }, { -2, -1 }, { -1, -2 } }, 57cabdff1aSopenharmony_ci [BS_8x16] = { { -1, 0 }, { 0, -1 }, { -1, 1 }, { -1, -1 }, 58cabdff1aSopenharmony_ci { -2, 0 }, { 0, -2 }, { -1, -2 }, { -2, -1 } }, 59cabdff1aSopenharmony_ci [BS_8x8] = { { 0, -1 }, { -1, 0 }, { -1, -1 }, { 0, -2 }, 60cabdff1aSopenharmony_ci { -2, 0 }, { -1, -2 }, { -2, -1 }, { -2, -2 } }, 61cabdff1aSopenharmony_ci [BS_8x4] = { { 0, -1 }, { -1, 0 }, { -1, -1 }, { 0, -2 }, 62cabdff1aSopenharmony_ci { -2, 0 }, { -1, -2 }, { -2, -1 }, { -2, -2 } }, 63cabdff1aSopenharmony_ci [BS_4x8] = { { 0, -1 }, { -1, 0 }, { -1, -1 }, { 0, -2 }, 64cabdff1aSopenharmony_ci { -2, 0 }, { -1, -2 }, { -2, -1 }, { -2, -2 } }, 65cabdff1aSopenharmony_ci [BS_4x4] = { { 0, -1 }, { -1, 0 }, { -1, -1 }, { 0, -2 }, 66cabdff1aSopenharmony_ci { -2, 0 }, { -1, -2 }, { -2, -1 }, { -2, -2 } }, 67cabdff1aSopenharmony_ci }; 68cabdff1aSopenharmony_ci VP9Context *s = td->s; 69cabdff1aSopenharmony_ci VP9Block *b = td->b; 70cabdff1aSopenharmony_ci int row = td->row, col = td->col, row7 = td->row7; 71cabdff1aSopenharmony_ci const int8_t (*p)[2] = mv_ref_blk_off[b->bs]; 72cabdff1aSopenharmony_ci#define INVALID_MV 0x80008000U 73cabdff1aSopenharmony_ci uint32_t mem = INVALID_MV, mem_sub8x8 = INVALID_MV; 74cabdff1aSopenharmony_ci int i; 75cabdff1aSopenharmony_ci 76cabdff1aSopenharmony_ci#define RETURN_DIRECT_MV(mv) \ 77cabdff1aSopenharmony_ci do { \ 78cabdff1aSopenharmony_ci uint32_t m = AV_RN32A(&mv); \ 79cabdff1aSopenharmony_ci if (!idx) { \ 80cabdff1aSopenharmony_ci AV_WN32A(pmv, m); \ 81cabdff1aSopenharmony_ci return; \ 82cabdff1aSopenharmony_ci } else if (mem == INVALID_MV) { \ 83cabdff1aSopenharmony_ci mem = m; \ 84cabdff1aSopenharmony_ci } else if (m != mem) { \ 85cabdff1aSopenharmony_ci AV_WN32A(pmv, m); \ 86cabdff1aSopenharmony_ci return; \ 87cabdff1aSopenharmony_ci } \ 88cabdff1aSopenharmony_ci } while (0) 89cabdff1aSopenharmony_ci 90cabdff1aSopenharmony_ci if (sb >= 0) { 91cabdff1aSopenharmony_ci if (sb == 2 || sb == 1) { 92cabdff1aSopenharmony_ci RETURN_DIRECT_MV(b->mv[0][z]); 93cabdff1aSopenharmony_ci } else if (sb == 3) { 94cabdff1aSopenharmony_ci RETURN_DIRECT_MV(b->mv[2][z]); 95cabdff1aSopenharmony_ci RETURN_DIRECT_MV(b->mv[1][z]); 96cabdff1aSopenharmony_ci RETURN_DIRECT_MV(b->mv[0][z]); 97cabdff1aSopenharmony_ci } 98cabdff1aSopenharmony_ci 99cabdff1aSopenharmony_ci#define RETURN_MV(mv) \ 100cabdff1aSopenharmony_ci do { \ 101cabdff1aSopenharmony_ci if (sb > 0) { \ 102cabdff1aSopenharmony_ci VP56mv tmp; \ 103cabdff1aSopenharmony_ci uint32_t m; \ 104cabdff1aSopenharmony_ci av_assert2(idx == 1); \ 105cabdff1aSopenharmony_ci av_assert2(mem != INVALID_MV); \ 106cabdff1aSopenharmony_ci if (mem_sub8x8 == INVALID_MV) { \ 107cabdff1aSopenharmony_ci clamp_mv(&tmp, &mv, td); \ 108cabdff1aSopenharmony_ci m = AV_RN32A(&tmp); \ 109cabdff1aSopenharmony_ci if (m != mem) { \ 110cabdff1aSopenharmony_ci AV_WN32A(pmv, m); \ 111cabdff1aSopenharmony_ci return; \ 112cabdff1aSopenharmony_ci } \ 113cabdff1aSopenharmony_ci mem_sub8x8 = AV_RN32A(&mv); \ 114cabdff1aSopenharmony_ci } else if (mem_sub8x8 != AV_RN32A(&mv)) { \ 115cabdff1aSopenharmony_ci clamp_mv(&tmp, &mv, td); \ 116cabdff1aSopenharmony_ci m = AV_RN32A(&tmp); \ 117cabdff1aSopenharmony_ci if (m != mem) { \ 118cabdff1aSopenharmony_ci AV_WN32A(pmv, m); \ 119cabdff1aSopenharmony_ci } else { \ 120cabdff1aSopenharmony_ci /* BUG I'm pretty sure this isn't the intention */ \ 121cabdff1aSopenharmony_ci AV_WN32A(pmv, 0); \ 122cabdff1aSopenharmony_ci } \ 123cabdff1aSopenharmony_ci return; \ 124cabdff1aSopenharmony_ci } \ 125cabdff1aSopenharmony_ci } else { \ 126cabdff1aSopenharmony_ci uint32_t m = AV_RN32A(&mv); \ 127cabdff1aSopenharmony_ci if (!idx) { \ 128cabdff1aSopenharmony_ci clamp_mv(pmv, &mv, td); \ 129cabdff1aSopenharmony_ci return; \ 130cabdff1aSopenharmony_ci } else if (mem == INVALID_MV) { \ 131cabdff1aSopenharmony_ci mem = m; \ 132cabdff1aSopenharmony_ci } else if (m != mem) { \ 133cabdff1aSopenharmony_ci clamp_mv(pmv, &mv, td); \ 134cabdff1aSopenharmony_ci return; \ 135cabdff1aSopenharmony_ci } \ 136cabdff1aSopenharmony_ci } \ 137cabdff1aSopenharmony_ci } while (0) 138cabdff1aSopenharmony_ci 139cabdff1aSopenharmony_ci if (row > 0) { 140cabdff1aSopenharmony_ci VP9mvrefPair *mv = &s->s.frames[CUR_FRAME].mv[(row - 1) * s->sb_cols * 8 + col]; 141cabdff1aSopenharmony_ci if (mv->ref[0] == ref) 142cabdff1aSopenharmony_ci RETURN_MV(s->above_mv_ctx[2 * col + (sb & 1)][0]); 143cabdff1aSopenharmony_ci else if (mv->ref[1] == ref) 144cabdff1aSopenharmony_ci RETURN_MV(s->above_mv_ctx[2 * col + (sb & 1)][1]); 145cabdff1aSopenharmony_ci } 146cabdff1aSopenharmony_ci if (col > td->tile_col_start) { 147cabdff1aSopenharmony_ci VP9mvrefPair *mv = &s->s.frames[CUR_FRAME].mv[row * s->sb_cols * 8 + col - 1]; 148cabdff1aSopenharmony_ci if (mv->ref[0] == ref) 149cabdff1aSopenharmony_ci RETURN_MV(td->left_mv_ctx[2 * row7 + (sb >> 1)][0]); 150cabdff1aSopenharmony_ci else if (mv->ref[1] == ref) 151cabdff1aSopenharmony_ci RETURN_MV(td->left_mv_ctx[2 * row7 + (sb >> 1)][1]); 152cabdff1aSopenharmony_ci } 153cabdff1aSopenharmony_ci i = 2; 154cabdff1aSopenharmony_ci } else { 155cabdff1aSopenharmony_ci i = 0; 156cabdff1aSopenharmony_ci } 157cabdff1aSopenharmony_ci 158cabdff1aSopenharmony_ci // previously coded MVs in this neighborhood, using same reference frame 159cabdff1aSopenharmony_ci for (; i < 8; i++) { 160cabdff1aSopenharmony_ci int c = p[i][0] + col, r = p[i][1] + row; 161cabdff1aSopenharmony_ci 162cabdff1aSopenharmony_ci if (c >= td->tile_col_start && c < s->cols && 163cabdff1aSopenharmony_ci r >= 0 && r < s->rows) { 164cabdff1aSopenharmony_ci VP9mvrefPair *mv = &s->s.frames[CUR_FRAME].mv[r * s->sb_cols * 8 + c]; 165cabdff1aSopenharmony_ci 166cabdff1aSopenharmony_ci if (mv->ref[0] == ref) 167cabdff1aSopenharmony_ci RETURN_MV(mv->mv[0]); 168cabdff1aSopenharmony_ci else if (mv->ref[1] == ref) 169cabdff1aSopenharmony_ci RETURN_MV(mv->mv[1]); 170cabdff1aSopenharmony_ci } 171cabdff1aSopenharmony_ci } 172cabdff1aSopenharmony_ci 173cabdff1aSopenharmony_ci // MV at this position in previous frame, using same reference frame 174cabdff1aSopenharmony_ci if (s->s.h.use_last_frame_mvs) { 175cabdff1aSopenharmony_ci VP9mvrefPair *mv = &s->s.frames[REF_FRAME_MVPAIR].mv[row * s->sb_cols * 8 + col]; 176cabdff1aSopenharmony_ci 177cabdff1aSopenharmony_ci if (!s->s.frames[REF_FRAME_MVPAIR].uses_2pass) 178cabdff1aSopenharmony_ci ff_thread_await_progress(&s->s.frames[REF_FRAME_MVPAIR].tf, row >> 3, 0); 179cabdff1aSopenharmony_ci if (mv->ref[0] == ref) 180cabdff1aSopenharmony_ci RETURN_MV(mv->mv[0]); 181cabdff1aSopenharmony_ci else if (mv->ref[1] == ref) 182cabdff1aSopenharmony_ci RETURN_MV(mv->mv[1]); 183cabdff1aSopenharmony_ci } 184cabdff1aSopenharmony_ci 185cabdff1aSopenharmony_ci#define RETURN_SCALE_MV(mv, scale) \ 186cabdff1aSopenharmony_ci do { \ 187cabdff1aSopenharmony_ci if (scale) { \ 188cabdff1aSopenharmony_ci VP56mv mv_temp = { -mv.x, -mv.y }; \ 189cabdff1aSopenharmony_ci RETURN_MV(mv_temp); \ 190cabdff1aSopenharmony_ci } else { \ 191cabdff1aSopenharmony_ci RETURN_MV(mv); \ 192cabdff1aSopenharmony_ci } \ 193cabdff1aSopenharmony_ci } while (0) 194cabdff1aSopenharmony_ci 195cabdff1aSopenharmony_ci // previously coded MVs in this neighborhood, using different reference frame 196cabdff1aSopenharmony_ci for (i = 0; i < 8; i++) { 197cabdff1aSopenharmony_ci int c = p[i][0] + col, r = p[i][1] + row; 198cabdff1aSopenharmony_ci 199cabdff1aSopenharmony_ci if (c >= td->tile_col_start && c < s->cols && r >= 0 && r < s->rows) { 200cabdff1aSopenharmony_ci VP9mvrefPair *mv = &s->s.frames[CUR_FRAME].mv[r * s->sb_cols * 8 + c]; 201cabdff1aSopenharmony_ci 202cabdff1aSopenharmony_ci if (mv->ref[0] != ref && mv->ref[0] >= 0) 203cabdff1aSopenharmony_ci RETURN_SCALE_MV(mv->mv[0], 204cabdff1aSopenharmony_ci s->s.h.signbias[mv->ref[0]] != s->s.h.signbias[ref]); 205cabdff1aSopenharmony_ci if (mv->ref[1] != ref && mv->ref[1] >= 0 && 206cabdff1aSopenharmony_ci // BUG - libvpx has this condition regardless of whether 207cabdff1aSopenharmony_ci // we used the first ref MV and pre-scaling 208cabdff1aSopenharmony_ci AV_RN32A(&mv->mv[0]) != AV_RN32A(&mv->mv[1])) { 209cabdff1aSopenharmony_ci RETURN_SCALE_MV(mv->mv[1], s->s.h.signbias[mv->ref[1]] != s->s.h.signbias[ref]); 210cabdff1aSopenharmony_ci } 211cabdff1aSopenharmony_ci } 212cabdff1aSopenharmony_ci } 213cabdff1aSopenharmony_ci 214cabdff1aSopenharmony_ci // MV at this position in previous frame, using different reference frame 215cabdff1aSopenharmony_ci if (s->s.h.use_last_frame_mvs) { 216cabdff1aSopenharmony_ci VP9mvrefPair *mv = &s->s.frames[REF_FRAME_MVPAIR].mv[row * s->sb_cols * 8 + col]; 217cabdff1aSopenharmony_ci 218cabdff1aSopenharmony_ci // no need to await_progress, because we already did that above 219cabdff1aSopenharmony_ci if (mv->ref[0] != ref && mv->ref[0] >= 0) 220cabdff1aSopenharmony_ci RETURN_SCALE_MV(mv->mv[0], s->s.h.signbias[mv->ref[0]] != s->s.h.signbias[ref]); 221cabdff1aSopenharmony_ci if (mv->ref[1] != ref && mv->ref[1] >= 0 && 222cabdff1aSopenharmony_ci // BUG - libvpx has this condition regardless of whether 223cabdff1aSopenharmony_ci // we used the first ref MV and pre-scaling 224cabdff1aSopenharmony_ci AV_RN32A(&mv->mv[0]) != AV_RN32A(&mv->mv[1])) { 225cabdff1aSopenharmony_ci RETURN_SCALE_MV(mv->mv[1], s->s.h.signbias[mv->ref[1]] != s->s.h.signbias[ref]); 226cabdff1aSopenharmony_ci } 227cabdff1aSopenharmony_ci } 228cabdff1aSopenharmony_ci 229cabdff1aSopenharmony_ci AV_ZERO32(pmv); 230cabdff1aSopenharmony_ci clamp_mv(pmv, pmv, td); 231cabdff1aSopenharmony_ci#undef INVALID_MV 232cabdff1aSopenharmony_ci#undef RETURN_MV 233cabdff1aSopenharmony_ci#undef RETURN_SCALE_MV 234cabdff1aSopenharmony_ci} 235cabdff1aSopenharmony_ci 236cabdff1aSopenharmony_cistatic av_always_inline int read_mv_component(VP9TileData *td, int idx, int hp) 237cabdff1aSopenharmony_ci{ 238cabdff1aSopenharmony_ci VP9Context *s = td->s; 239cabdff1aSopenharmony_ci int bit, sign = vp56_rac_get_prob(td->c, s->prob.p.mv_comp[idx].sign); 240cabdff1aSopenharmony_ci int n, c = vp8_rac_get_tree(td->c, ff_vp9_mv_class_tree, 241cabdff1aSopenharmony_ci s->prob.p.mv_comp[idx].classes); 242cabdff1aSopenharmony_ci 243cabdff1aSopenharmony_ci td->counts.mv_comp[idx].sign[sign]++; 244cabdff1aSopenharmony_ci td->counts.mv_comp[idx].classes[c]++; 245cabdff1aSopenharmony_ci if (c) { 246cabdff1aSopenharmony_ci int m; 247cabdff1aSopenharmony_ci 248cabdff1aSopenharmony_ci for (n = 0, m = 0; m < c; m++) { 249cabdff1aSopenharmony_ci bit = vp56_rac_get_prob(td->c, s->prob.p.mv_comp[idx].bits[m]); 250cabdff1aSopenharmony_ci n |= bit << m; 251cabdff1aSopenharmony_ci td->counts.mv_comp[idx].bits[m][bit]++; 252cabdff1aSopenharmony_ci } 253cabdff1aSopenharmony_ci n <<= 3; 254cabdff1aSopenharmony_ci bit = vp8_rac_get_tree(td->c, ff_vp9_mv_fp_tree, 255cabdff1aSopenharmony_ci s->prob.p.mv_comp[idx].fp); 256cabdff1aSopenharmony_ci n |= bit << 1; 257cabdff1aSopenharmony_ci td->counts.mv_comp[idx].fp[bit]++; 258cabdff1aSopenharmony_ci if (hp) { 259cabdff1aSopenharmony_ci bit = vp56_rac_get_prob(td->c, s->prob.p.mv_comp[idx].hp); 260cabdff1aSopenharmony_ci td->counts.mv_comp[idx].hp[bit]++; 261cabdff1aSopenharmony_ci n |= bit; 262cabdff1aSopenharmony_ci } else { 263cabdff1aSopenharmony_ci n |= 1; 264cabdff1aSopenharmony_ci // bug in libvpx - we count for bw entropy purposes even if the 265cabdff1aSopenharmony_ci // bit wasn't coded 266cabdff1aSopenharmony_ci td->counts.mv_comp[idx].hp[1]++; 267cabdff1aSopenharmony_ci } 268cabdff1aSopenharmony_ci n += 8 << c; 269cabdff1aSopenharmony_ci } else { 270cabdff1aSopenharmony_ci n = vp56_rac_get_prob(td->c, s->prob.p.mv_comp[idx].class0); 271cabdff1aSopenharmony_ci td->counts.mv_comp[idx].class0[n]++; 272cabdff1aSopenharmony_ci bit = vp8_rac_get_tree(td->c, ff_vp9_mv_fp_tree, 273cabdff1aSopenharmony_ci s->prob.p.mv_comp[idx].class0_fp[n]); 274cabdff1aSopenharmony_ci td->counts.mv_comp[idx].class0_fp[n][bit]++; 275cabdff1aSopenharmony_ci n = (n << 3) | (bit << 1); 276cabdff1aSopenharmony_ci if (hp) { 277cabdff1aSopenharmony_ci bit = vp56_rac_get_prob(td->c, s->prob.p.mv_comp[idx].class0_hp); 278cabdff1aSopenharmony_ci td->counts.mv_comp[idx].class0_hp[bit]++; 279cabdff1aSopenharmony_ci n |= bit; 280cabdff1aSopenharmony_ci } else { 281cabdff1aSopenharmony_ci n |= 1; 282cabdff1aSopenharmony_ci // bug in libvpx - we count for bw entropy purposes even if the 283cabdff1aSopenharmony_ci // bit wasn't coded 284cabdff1aSopenharmony_ci td->counts.mv_comp[idx].class0_hp[1]++; 285cabdff1aSopenharmony_ci } 286cabdff1aSopenharmony_ci } 287cabdff1aSopenharmony_ci 288cabdff1aSopenharmony_ci return sign ? -(n + 1) : (n + 1); 289cabdff1aSopenharmony_ci} 290cabdff1aSopenharmony_ci 291cabdff1aSopenharmony_civoid ff_vp9_fill_mv(VP9TileData *td, VP56mv *mv, int mode, int sb) 292cabdff1aSopenharmony_ci{ 293cabdff1aSopenharmony_ci VP9Context *s = td->s; 294cabdff1aSopenharmony_ci VP9Block *b = td->b; 295cabdff1aSopenharmony_ci 296cabdff1aSopenharmony_ci if (mode == ZEROMV) { 297cabdff1aSopenharmony_ci AV_ZERO64(mv); 298cabdff1aSopenharmony_ci } else { 299cabdff1aSopenharmony_ci int hp; 300cabdff1aSopenharmony_ci 301cabdff1aSopenharmony_ci // FIXME cache this value and reuse for other subblocks 302cabdff1aSopenharmony_ci find_ref_mvs(td, &mv[0], b->ref[0], 0, mode == NEARMV, 303cabdff1aSopenharmony_ci mode == NEWMV ? -1 : sb); 304cabdff1aSopenharmony_ci // FIXME maybe move this code into find_ref_mvs() 305cabdff1aSopenharmony_ci if ((mode == NEWMV || sb == -1) && 306cabdff1aSopenharmony_ci !(hp = s->s.h.highprecisionmvs && 307cabdff1aSopenharmony_ci abs(mv[0].x) < 64 && abs(mv[0].y) < 64)) { 308cabdff1aSopenharmony_ci if (mv[0].y & 1) { 309cabdff1aSopenharmony_ci if (mv[0].y < 0) 310cabdff1aSopenharmony_ci mv[0].y++; 311cabdff1aSopenharmony_ci else 312cabdff1aSopenharmony_ci mv[0].y--; 313cabdff1aSopenharmony_ci } 314cabdff1aSopenharmony_ci if (mv[0].x & 1) { 315cabdff1aSopenharmony_ci if (mv[0].x < 0) 316cabdff1aSopenharmony_ci mv[0].x++; 317cabdff1aSopenharmony_ci else 318cabdff1aSopenharmony_ci mv[0].x--; 319cabdff1aSopenharmony_ci } 320cabdff1aSopenharmony_ci } 321cabdff1aSopenharmony_ci if (mode == NEWMV) { 322cabdff1aSopenharmony_ci enum MVJoint j = vp8_rac_get_tree(td->c, ff_vp9_mv_joint_tree, 323cabdff1aSopenharmony_ci s->prob.p.mv_joint); 324cabdff1aSopenharmony_ci 325cabdff1aSopenharmony_ci td->counts.mv_joint[j]++; 326cabdff1aSopenharmony_ci if (j >= MV_JOINT_V) 327cabdff1aSopenharmony_ci mv[0].y += read_mv_component(td, 0, hp); 328cabdff1aSopenharmony_ci if (j & 1) 329cabdff1aSopenharmony_ci mv[0].x += read_mv_component(td, 1, hp); 330cabdff1aSopenharmony_ci } 331cabdff1aSopenharmony_ci 332cabdff1aSopenharmony_ci if (b->comp) { 333cabdff1aSopenharmony_ci // FIXME cache this value and reuse for other subblocks 334cabdff1aSopenharmony_ci find_ref_mvs(td, &mv[1], b->ref[1], 1, mode == NEARMV, 335cabdff1aSopenharmony_ci mode == NEWMV ? -1 : sb); 336cabdff1aSopenharmony_ci if ((mode == NEWMV || sb == -1) && 337cabdff1aSopenharmony_ci !(hp = s->s.h.highprecisionmvs && 338cabdff1aSopenharmony_ci abs(mv[1].x) < 64 && abs(mv[1].y) < 64)) { 339cabdff1aSopenharmony_ci if (mv[1].y & 1) { 340cabdff1aSopenharmony_ci if (mv[1].y < 0) 341cabdff1aSopenharmony_ci mv[1].y++; 342cabdff1aSopenharmony_ci else 343cabdff1aSopenharmony_ci mv[1].y--; 344cabdff1aSopenharmony_ci } 345cabdff1aSopenharmony_ci if (mv[1].x & 1) { 346cabdff1aSopenharmony_ci if (mv[1].x < 0) 347cabdff1aSopenharmony_ci mv[1].x++; 348cabdff1aSopenharmony_ci else 349cabdff1aSopenharmony_ci mv[1].x--; 350cabdff1aSopenharmony_ci } 351cabdff1aSopenharmony_ci } 352cabdff1aSopenharmony_ci if (mode == NEWMV) { 353cabdff1aSopenharmony_ci enum MVJoint j = vp8_rac_get_tree(td->c, ff_vp9_mv_joint_tree, 354cabdff1aSopenharmony_ci s->prob.p.mv_joint); 355cabdff1aSopenharmony_ci 356cabdff1aSopenharmony_ci td->counts.mv_joint[j]++; 357cabdff1aSopenharmony_ci if (j >= MV_JOINT_V) 358cabdff1aSopenharmony_ci mv[1].y += read_mv_component(td, 0, hp); 359cabdff1aSopenharmony_ci if (j & 1) 360cabdff1aSopenharmony_ci mv[1].x += read_mv_component(td, 1, hp); 361cabdff1aSopenharmony_ci } 362cabdff1aSopenharmony_ci } 363cabdff1aSopenharmony_ci } 364cabdff1aSopenharmony_ci} 365