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 "internal.h"
25 #include "vp56.h"
26 #include "vp9.h"
27 #include "vp9data.h"
28 #include "vp9dec.h"
29 
30 static av_always_inline void clamp_mv(VP56mv *dst, const VP56mv *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  VP56mv *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  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  VP56mv 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  VP56mv 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  VP9Context *s = td->s;
239  int bit, sign = vp56_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 = vp56_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 = vp56_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 = vp56_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 = vp56_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, VP56mv *mv, int mode, int sb)
292 {
293  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 }
find_ref_mvs
static void find_ref_mvs(VP9TileData *td, VP56mv *pmv, int ref, int z, int idx, int sb)
Definition: vp9mvs.c:37
td
#define td
Definition: regdef.h:70
av_clip
#define av_clip
Definition: common.h:96
VP56mv::x
int16_t x
Definition: vp56.h:69
r
const char * r
Definition: vf_curves.c:116
BS_64x64
@ BS_64x64
Definition: vp9shared.h:78
BS_64x32
@ BS_64x32
Definition: vp9shared.h:79
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:79
INVALID_MV
#define INVALID_MV
internal.h
MVJoint
MVJoint
Definition: vp9dec.h:42
b
#define b
Definition: input.c:40
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)
BS_4x8
@ BS_4x8
Definition: vp9shared.h:89
NEARMV
@ NEARMV
Definition: vp9shared.h:43
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:82
bit
#define bit(string, value)
Definition: cbs_mpeg2.c:58
BS_8x16
@ BS_8x16
Definition: vp9shared.h:86
ZEROMV
@ ZEROMV
Definition: vp9shared.h:44
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:81
s
#define s(width, name)
Definition: cbs_vp9.c:257
AV_ZERO64
#define AV_ZERO64(d)
Definition: intreadwrite.h:633
AV_ZERO32
#define AV_ZERO32(d)
Definition: intreadwrite.h:629
vp9data.h
RETURN_DIRECT_MV
#define RETURN_DIRECT_MV(mv)
VP56mv::y
int16_t y
Definition: vp56.h:70
VP56mv
Definition: vp56.h:68
BS_8x4
@ BS_8x4
Definition: vp9shared.h:88
vp56.h
if
if(ret)
Definition: filter_design.txt:179
VP9Context
Definition: vp9dec.h:94
vp8_rac_get_tree
static av_always_inline int vp8_rac_get_tree(VP56RangeCoder *c, const int8_t(*tree)[2], const uint8_t *probs)
Definition: vp56.h:396
REF_FRAME_MVPAIR
#define REF_FRAME_MVPAIR
Definition: vp9shared.h:164
src
#define src
Definition: vp8dsp.c:255
BS_32x64
@ BS_32x64
Definition: vp9shared.h:80
abs
#define abs(x)
Definition: cuda_runtime.h:35
MV_JOINT_V
@ MV_JOINT_V
Definition: vp9dec.h:45
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
vp9.h
BS_8x8
@ BS_8x8
Definition: vp9shared.h:87
N_BS_SIZES
@ N_BS_SIZES
Definition: vp9shared.h:91
BS_4x4
@ BS_4x4
Definition: vp9shared.h:90
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:271
BS_16x32
@ BS_16x32
Definition: vp9shared.h:83
av_always_inline
#define av_always_inline
Definition: attributes.h:49
AV_RN32A
#define AV_RN32A(p)
Definition: intreadwrite.h:526
read_mv_component
static av_always_inline int read_mv_component(VP9TileData *td, int idx, int hp)
Definition: vp9mvs.c:236
VP9mvrefPair
Definition: vp9shared.h:54
clamp_mv
static av_always_inline void clamp_mv(VP56mv *dst, const VP56mv *src, VP9TileData *td)
Definition: vp9mvs.c:30
VP9TileData
Definition: vp9dec.h:165
NEWMV
@ NEWMV
Definition: vp9shared.h:45
BS_16x16
@ BS_16x16
Definition: vp9shared.h:84
ff_vp9_fill_mv
void ff_vp9_fill_mv(VP9TileData *td, VP56mv *mv, int mode, int sb)
Definition: vp9mvs.c:291
BS_16x8
@ BS_16x8
Definition: vp9shared.h:85
mode
mode
Definition: ebur128.h:83
ref
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:107
vp9dec.h
vp56_rac_get_prob
#define vp56_rac_get_prob
Definition: vp56.h:270
CUR_FRAME
#define CUR_FRAME
Definition: vp9shared.h:163
BS_32x16
@ BS_32x16
Definition: vp9shared.h:82
RETURN_MV
#define RETURN_MV(mv)