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