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 "progressframe.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 
37 static void find_ref_mvs(VP9TileData *td,
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_progress_frame_await(&s->s.frames[REF_FRAME_MVPAIR].tf, row >> 3);
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_ZERO32(&mv[0]);
298  AV_ZERO32(&mv[1]);
299  } else {
300  int hp;
301 
302  // FIXME cache this value and reuse for other subblocks
303  find_ref_mvs(td, &mv[0], b->ref[0], 0, mode == NEARMV,
304  mode == NEWMV ? -1 : sb);
305  // FIXME maybe move this code into find_ref_mvs()
306  if ((mode == NEWMV || sb == -1) &&
307  !(hp = s->s.h.highprecisionmvs &&
308  abs(mv[0].x) < 64 && abs(mv[0].y) < 64)) {
309  if (mv[0].y & 1) {
310  if (mv[0].y < 0)
311  mv[0].y++;
312  else
313  mv[0].y--;
314  }
315  if (mv[0].x & 1) {
316  if (mv[0].x < 0)
317  mv[0].x++;
318  else
319  mv[0].x--;
320  }
321  }
322  if (mode == NEWMV) {
324  s->prob.p.mv_joint);
325 
326  td->counts.mv_joint[j]++;
327  if (j >= MV_JOINT_V)
328  mv[0].y += read_mv_component(td, 0, hp);
329  if (j & 1)
330  mv[0].x += read_mv_component(td, 1, hp);
331  }
332 
333  if (b->comp) {
334  // FIXME cache this value and reuse for other subblocks
335  find_ref_mvs(td, &mv[1], b->ref[1], 1, mode == NEARMV,
336  mode == NEWMV ? -1 : sb);
337  if ((mode == NEWMV || sb == -1) &&
338  !(hp = s->s.h.highprecisionmvs &&
339  abs(mv[1].x) < 64 && abs(mv[1].y) < 64)) {
340  if (mv[1].y & 1) {
341  if (mv[1].y < 0)
342  mv[1].y++;
343  else
344  mv[1].y--;
345  }
346  if (mv[1].x & 1) {
347  if (mv[1].x < 0)
348  mv[1].x++;
349  else
350  mv[1].x--;
351  }
352  }
353  if (mode == NEWMV) {
355  s->prob.p.mv_joint);
356 
357  td->counts.mv_joint[j]++;
358  if (j >= MV_JOINT_V)
359  mv[1].y += read_mv_component(td, 0, hp);
360  if (j & 1)
361  mv[1].x += read_mv_component(td, 1, hp);
362  }
363  }
364  }
365 }
av_clip
#define av_clip
Definition: common.h:100
r
const char * r
Definition: vf_curves.c:127
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:81
INVALID_MV
#define INVALID_MV
VP9TileData::row
int row
Definition: vp9dec.h:171
mode
Definition: swscale.c:52
MVJoint
MVJoint
Definition: vp9dec.h:44
VP9TileData::x
int x
Definition: vp9dec.h:225
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
VP9TileData::b
VP9Block * b
Definition: vp9dec.h:174
NEARMV
@ NEARMV
Definition: vp9shared.h:44
VP9Block
Definition: vp9dec.h:84
bit
#define bit(string, value)
Definition: cbs_mpeg2.c:56
BS_8x16
@ BS_8x16
Definition: vp9shared.h:91
progressframe.h
ZEROMV
@ ZEROMV
Definition: vp9shared.h:45
VP9TileData::col
int col
Definition: vp9dec.h:171
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
VP9TileData::mv_joint
unsigned mv_joint[4]
Definition: vp9dec.h:190
VP9TileData::max_mv
struct VP9TileData::@274 max_mv
AV_ZERO32
#define AV_ZERO32(d)
Definition: intreadwrite.h:662
vp9data.h
ff_progress_frame_await
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_progress_frame_await() 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_progress_frame_report() has been called on them. This includes draw_edges(). Porting codecs to frame threading
RETURN_DIRECT_MV
#define RETURN_DIRECT_MV(mv)
BS_8x4
@ BS_8x4
Definition: vp9shared.h:93
VP9TileData::y
int y
Definition: vp9dec.h:225
if
if(ret)
Definition: filter_design.txt:179
VP9Context
Definition: vp9dec.h:96
REF_FRAME_MVPAIR
#define REF_FRAME_MVPAIR
Definition: vp9shared.h:169
VP9TileData::counts
struct VP9TileData::@273 counts
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
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:83
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:256
vpx_rac.h
BS_16x32
@ BS_16x32
Definition: vp9shared.h:88
av_always_inline
#define av_always_inline
Definition: attributes.h:49
VP9TileData::left_mv_ctx
VP9mv left_mv_ctx[16][2]
Definition: vp9dec.h:212
VP9TileData::c
VPXRangeCoder * c
Definition: vp9dec.h:170
AV_RN32A
#define AV_RN32A(p)
Definition: intreadwrite.h:522
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
VP9TileData::s
const VP9Context * s
Definition: vp9dec.h:168
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
ref
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:117
vp9dec.h
CUR_FRAME
#define CUR_FRAME
Definition: vp9shared.h:168
VP9TileData::row7
int row7
Definition: vp9dec.h:171
BS_32x16
@ BS_32x16
Definition: vp9shared.h:87
VP9TileData::mv_comp
struct VP9TileData::@273::@276 mv_comp[2]
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
VP9TileData::tile_col_start
unsigned tile_col_start
Definition: vp9dec.h:175
vpx_rac_get_prob
#define vpx_rac_get_prob
Definition: vpx_rac.h:82
src
#define src
Definition: vp8dsp.c:248
VP9TileData::min_mv
struct VP9TileData::@274 min_mv