/* * VP9 compatible video decoder * * Copyright (C) 2013 Ronald S. Bultje <rsbultje gmail com> * Copyright (C) 2013 Clément Bœsch <u pkh me> * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
// MV at this position in previous frame, using same reference frame if (s->s.h.use_last_frame_mvs) {
VP9mvrefPair *mv = &s->s.frames[REF_FRAME_MVPAIR].mv[row * s->sb_cols * 8 + col];
if (!s->s.frames[REF_FRAME_MVPAIR].uses_2pass)
ff_progress_frame_await(&s->s.frames[REF_FRAME_MVPAIR].tf, row >> 3); if (mv->ref[0] == ref)
RETURN_MV(mv->mv[0]); elseif (mv->ref[1] == ref)
RETURN_MV(mv->mv[1]);
}
// previously coded MVs in this neighborhood, using different reference frame for (i = 0; i < 8; i++) { int c = p[i][0] + col, r = p[i][1] + row;
if (c >= td->tile_col_start && c < s->cols && r >= 0 && r < s->rows) {
VP9mvrefPair *mv = &s->s.frames[CUR_FRAME].mv[r * s->sb_cols * 8 + c];
if (mv->ref[0] != ref && mv->ref[0] >= 0)
RETURN_SCALE_MV(mv->mv[0],
s->s.h.signbias[mv->ref[0]] != s->s.h.signbias[ref]); if (mv->ref[1] != ref && mv->ref[1] >= 0 && // BUG - libvpx has this condition regardless of whether // we used the first ref MV and pre-scaling
AV_RN32A(&mv->mv[0]) != AV_RN32A(&mv->mv[1])) {
RETURN_SCALE_MV(mv->mv[1], s->s.h.signbias[mv->ref[1]] != s->s.h.signbias[ref]);
}
}
}
// MV at this position in previous frame, using different reference frame if (s->s.h.use_last_frame_mvs) {
VP9mvrefPair *mv = &s->s.frames[REF_FRAME_MVPAIR].mv[row * s->sb_cols * 8 + col];
// no need to await_progress, because we already did that above if (mv->ref[0] != ref && mv->ref[0] >= 0)
RETURN_SCALE_MV(mv->mv[0], s->s.h.signbias[mv->ref[0]] != s->s.h.signbias[ref]); if (mv->ref[1] != ref && mv->ref[1] >= 0 && // BUG - libvpx has this condition regardless of whether // we used the first ref MV and pre-scaling
AV_RN32A(&mv->mv[0]) != AV_RN32A(&mv->mv[1])) {
RETURN_SCALE_MV(mv->mv[1], s->s.h.signbias[mv->ref[1]] != s->s.h.signbias[ref]);
}
}
static av_always_inline int read_mv_component(VP9TileData *td, int idx, int hp)
{ const VP9Context *s = td->s; int bit, sign = vpx_rac_get_prob(td->c, s->prob.p.mv_comp[idx].sign); int n, c = vp89_rac_get_tree(td->c, ff_vp9_mv_class_tree,
s->prob.p.mv_comp[idx].classes);
td->counts.mv_comp[idx].sign[sign]++;
td->counts.mv_comp[idx].classes[c]++; if (c) { int m;
for (n = 0, m = 0; m < c; m++) {
bit = vpx_rac_get_prob(td->c, s->prob.p.mv_comp[idx].bits[m]);
n |= bit << m;
td->counts.mv_comp[idx].bits[m][bit]++;
}
n <<= 3;
bit = vp89_rac_get_tree(td->c, ff_vp9_mv_fp_tree,
s->prob.p.mv_comp[idx].fp);
n |= bit << 1;
td->counts.mv_comp[idx].fp[bit]++; if (hp) {
bit = vpx_rac_get_prob(td->c, s->prob.p.mv_comp[idx].hp);
td->counts.mv_comp[idx].hp[bit]++;
n |= bit;
} else {
n |= 1; // bug in libvpx - we count for bw entropy purposes even if the // bit wasn't coded
td->counts.mv_comp[idx].hp[1]++;
}
n += 8 << c;
} else {
n = vpx_rac_get_prob(td->c, s->prob.p.mv_comp[idx].class0);
td->counts.mv_comp[idx].class0[n]++;
bit = vp89_rac_get_tree(td->c, ff_vp9_mv_fp_tree,
s->prob.p.mv_comp[idx].class0_fp[n]);
td->counts.mv_comp[idx].class0_fp[n][bit]++;
n = (n << 3) | (bit << 1); if (hp) {
bit = vpx_rac_get_prob(td->c, s->prob.p.mv_comp[idx].class0_hp);
td->counts.mv_comp[idx].class0_hp[bit]++;
n |= bit;
} else {
n |= 1; // bug in libvpx - we count for bw entropy purposes even if the // bit wasn't coded
td->counts.mv_comp[idx].class0_hp[1]++;
}
}
return sign ? -(n + 1) : (n + 1);
}
void ff_vp9_fill_mv(VP9TileData *td, VP9mv *mv, int mode, int sb)
{ const VP9Context *s = td->s;
VP9Block *b = td->b;
if (mode == ZEROMV) {
AV_ZERO32(&mv[0]);
AV_ZERO32(&mv[1]);
} else { int hp;
// FIXME cache this value and reuse for other subblocks
find_ref_mvs(td, &mv[0], b->ref[0], 0, mode == NEARMV,
mode == NEWMV ? -1 : sb); // FIXME maybe move this code into find_ref_mvs() if ((mode == NEWMV || sb == -1) &&
!(hp = s->s.h.highprecisionmvs &&
abs(mv[0].x) < 64 && abs(mv[0].y) < 64)) { if (mv[0].y & 1) { if (mv[0].y < 0)
mv[0].y++; else
mv[0].y--;
} if (mv[0].x & 1) { if (mv[0].x < 0)
mv[0].x++; else
mv[0].x--;
}
} if (mode == NEWMV) { enum MVJoint j = vp89_rac_get_tree(td->c, ff_vp9_mv_joint_tree,
s->prob.p.mv_joint);
td->counts.mv_joint[j]++; if (j >= MV_JOINT_V)
mv[0].y += read_mv_component(td, 0, hp); if (j & 1)
mv[0].x += read_mv_component(td, 1, hp);
}
if (b->comp) { // FIXME cache this value and reuse for other subblocks
find_ref_mvs(td, &mv[1], b->ref[1], 1, mode == NEARMV,
mode == NEWMV ? -1 : sb); if ((mode == NEWMV || sb == -1) &&
!(hp = s->s.h.highprecisionmvs &&
abs(mv[1].x) < 64 && abs(mv[1].y) < 64)) { if (mv[1].y & 1) { if (mv[1].y < 0)
mv[1].y++; else
mv[1].y--;
} if (mv[1].x & 1) { if (mv[1].x < 0)
mv[1].x++; else
mv[1].x--;
}
} if (mode == NEWMV) { enum MVJoint j = vp89_rac_get_tree(td->c, ff_vp9_mv_joint_tree,
s->prob.p.mv_joint);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.