const int last = *cnt;
for (int n = 0; n < last; n++)
if (mvstack[n].mv.n == cand_mv.n) {
mvstack[n].weight += weight; return;
}
if (last < 8) {
mvstack[last].mv = cand_mv;
mvstack[last].weight = weight;
*cnt = last + 1;
}
}
}
static int scan_row(refmvs_candidate *const mvstack, int *const cnt, constunion refmvs_refpair ref, const mv gmv[2], const refmvs_block *b, const int bw4, const int w4, const int max_rows, const int step,
int *const have_newmv_match, int *const have_refmv_match)
{ const refmvs_block *cand_b = b; const enum BlockSize first_cand_bs = cand_b->bs; const uint8_t *const first_cand_b_dim = dav1d_block_dimensions[first_cand_bs];
int cand_bw4 = first_cand_b_dim[0];
int len = imax(step, imin(bw4, cand_bw4));
if (bw4 <= cand_bw4) { // FIXME weight can be higher for odd blocks (bx4 & 1), but then the // position of the first block has to be odd already, i.e. not just // for row_offset=-3/-5 // FIXME why can this not be cand_bw4? const int weight = bw4 == 1 ? 2 :
imax(2, imin(2 * max_rows, first_cand_b_dim[1]));
add_spatial_candidate(mvstack, cnt, len * weight, cand_b, ref, gmv,
have_newmv_match, have_refmv_match); return weight >> 1;
}
for (int x = 0;;) { // FIXME if we overhang above, we could fill a bitmask so we don't have // to repeat the add_spatial_candidate() for the next row, but just increase // the weight here
add_spatial_candidate(mvstack, cnt, len * 2, cand_b, ref, gmv,
have_newmv_match, have_refmv_match);
x += len;
if (x >= w4) return1;
cand_b = &b[x];
cand_bw4 = dav1d_block_dimensions[cand_b->bs][0];
assert(cand_bw4 < bw4);
len = imax(step, cand_bw4);
}
}
static int scan_col(refmvs_candidate *const mvstack, int *const cnt, constunion refmvs_refpair ref, const mv gmv[2], /*const*/ refmvs_block *const *b, const int bh4, const int h4, const int bx4, const int max_cols, const int step,
int *const have_newmv_match, int *const have_refmv_match)
{ const refmvs_block *cand_b = &b[0][bx4]; const enum BlockSize first_cand_bs = cand_b->bs; const uint8_t *const first_cand_b_dim = dav1d_block_dimensions[first_cand_bs];
int cand_bh4 = first_cand_b_dim[1];
int len = imax(step, imin(bh4, cand_bh4));
if (bh4 <= cand_bh4) { // FIXME weight can be higher for odd blocks (by4 & 1), but then the // position of the first block has to be odd already, i.e. not just // for col_offset=-3/-5 // FIXME why can this not be cand_bh4? const int weight = bh4 == 1 ? 2 :
imax(2, imin(2 * max_cols, first_cand_b_dim[0]));
add_spatial_candidate(mvstack, cnt, len * weight, cand_b, ref, gmv,
have_newmv_match, have_refmv_match); return weight >> 1;
}
for (int y = 0;;) { // FIXME if we overhang above, we could fill a bitmask so we don't have // to repeat the add_spatial_candidate() for the next row, but just increase // the weight here
add_spatial_candidate(mvstack, cnt, len * 2, cand_b, ref, gmv,
have_newmv_match, have_refmv_match);
y += len;
if (y >= h4) return1;
cand_b = &b[y][bx4];
cand_bh4 = dav1d_block_dimensions[cand_b->bs][1];
assert(cand_bh4 < bh4);
len = imax(step, cand_bh4);
}
}
staticvoid add_single_extended_candidate(refmvs_candidate mvstack[8], int *const cnt, const refmvs_block *const cand_b, const int sign, const uint8_t *const sign_bias)
{
for (int n = 0; n < 2; n++) { const int cand_ref = cand_b->ref.ref[n];
if (cand_ref <= 0) break; // we need to continue even if cand_ref == ref.ref[0], since // the candidate could have been added as a globalmv variant, // which changes the value // FIXME if scan_{row,col}() returned a mask for the nearest // edge, we could skip the appropriate ones here
int m; const int last = *cnt;
for (m = 0; m < last; m++)
if (cand_mv.n == mvstack[m].mv.mv[0].n) break;
if (m == last) {
mvstack[m].mv.mv[0] = cand_mv;
mvstack[m].weight = 2; // "minimal"
*cnt = last + 1;
}
}
}
// top/left (which, confusingly, is part of "secondary" references)
int have_dummy_newmv_match;
if ((n_rows | n_cols) != ~0U) {
add_spatial_candidate(mvstack, cnt, 4, &b_top[-1], ref, gmv,
&have_dummy_newmv_match, &have_row_mvs);
}
// "secondary" (non-direct neighbour) top & left edges // what is different about secondary is that everything is now in 8x8 resolution
for (int n = 2; n <= 3; n++) {
if ((unsigned) n > n_rows && (unsigned) n <= max_rows) {
n_rows += scan_row(mvstack, cnt, ref, gmv,
&rt->r[(((by4 & 31) - 2 * n + 1) | 1) + 5][bx4 | 1],
bw4, w4, 1 + max_rows - n, bw4 >= 16 ? 4 : 2,
&have_dummy_newmv_match, &have_row_mvs);
}
// sorting (nearest, then "secondary")
int len = nearest_cnt; while (len) {
int last = 0;
for (int n = 1; n < len; n++) {
if (mvstack[n - 1].weight < mvstack[n].weight) { #define EXCHANGE(a, b) do { refmvs_candidate tmp = a; a = b; b = tmp; } while (0)
EXCHANGE(mvstack[n - 1], mvstack[n]);
last = n;
}
}
len = last;
}
len = *cnt; while (len > nearest_cnt) {
int last = nearest_cnt;
for (int n = nearest_cnt + 1; n < len; n++) {
if (mvstack[n - 1].weight < mvstack[n].weight) {
EXCHANGE(mvstack[n - 1], mvstack[n]); #undef EXCHANGE
last = n;
}
}
len = last;
}
if (ref.ref[1] > 0) {
if (*cnt < 2) { const int sign0 = rf->sign_bias[ref.ref[0] - 1]; const int sign1 = rf->sign_bias[ref.ref[1] - 1]; const int sz4 = imin(w4, h4);
refmvs_candidate *const same = &mvstack[*cnt];
int same_count[4] = { 0 };
// non-self references in top
if (n_rows != ~0U) for (int x = 0; x < sz4;) { const refmvs_block *const cand_b = &b_top[x];
add_compound_extended_candidate(same, same_count, cand_b,
sign0, sign1, ref, rf->sign_bias);
x += dav1d_block_dimensions[cand_b->bs][0];
}
// non-self references in left
if (n_cols != ~0U) for (int y = 0; y < sz4;) { const refmvs_block *const cand_b = &b_left[y][bx4 - 1];
add_compound_extended_candidate(same, same_count, cand_b,
sign0, sign1, ref, rf->sign_bias);
y += dav1d_block_dimensions[cand_b->bs][1];
}
// merge together
for (int n = 0; n < 2; n++) {
int m = same_count[n];
if (m >= 2) continue;
const int l = diff_count[n];
if (l) {
same[m].mv.mv[n] = diff[0].mv.mv[n];
if (++m == 2) continue;
if (l == 2) {
same[1].mv.mv[n] = diff[1].mv.mv[n]; continue;
}
} do {
same[m].mv.mv[n] = tgmv[n];
} while (++m < 2);
}
// if the first extended was the same as the non-extended one, // then replace it with the second extended one
int n = *cnt;
if (n == 1 && mvstack[0].mv.n == same[0].mv.n)
mvstack[1].mv = mvstack[2].mv; do {
mvstack[n].weight = 2;
} while (++n < 2);
*cnt = 2;
}
// clamping const int left = -(bx4 + bw4 + 4) * 4 * 8; const int right = (rf->iw4 - bx4 + 4) * 4 * 8; const int top = -(by4 + bh4 + 4) * 4 * 8; const int bottom = (rf->ih4 - by4 + 4) * 4 * 8;
const int n_refmvs = *cnt;
int n = 0; do {
mvstack[n].mv.mv[0].x = iclip(mvstack[n].mv.mv[0].x, left, right);
mvstack[n].mv.mv[0].y = iclip(mvstack[n].mv.mv[0].y, top, bottom);
mvstack[n].mv.mv[1].x = iclip(mvstack[n].mv.mv[1].x, left, right);
mvstack[n].mv.mv[1].y = iclip(mvstack[n].mv.mv[1].y, top, bottom);
} while (++n < n_refmvs);
const int poc = frm_hdr->frame_offset;
for (int i = 0; i < 7; i++) { const int poc_diff = get_poc_diff(seq_hdr->order_hint_n_bits,
ref_poc[i], poc);
rf->sign_bias[i] = poc_diff > 0;
rf->mfmv_sign[i] = poc_diff < 0;
rf->pocdiff[i] = iclip(get_poc_diff(seq_hdr->order_hint_n_bits,
poc, ref_poc[i]), -31, 31);
}
// temporal MV setup
rf->n_mfmvs = 0;
rf->rp_ref = rp_ref;
if (frm_hdr->use_ref_frame_mvs && seq_hdr->order_hint_n_bits) {
int total = 2;
if (rp_ref[0] && ref_ref_poc[0][6] != ref_poc[3] /* alt-of-last != gold */) {
rf->mfmv_ref[rf->n_mfmvs++] = 0; // last
total = 3;
}
if (rp_ref[4] && get_poc_diff(seq_hdr->order_hint_n_bits, ref_poc[4],
frm_hdr->frame_offset) > 0)
{
rf->mfmv_ref[rf->n_mfmvs++] = 4; // bwd
}
if (rp_ref[5] && get_poc_diff(seq_hdr->order_hint_n_bits, ref_poc[5],
frm_hdr->frame_offset) > 0)
{
rf->mfmv_ref[rf->n_mfmvs++] = 5; // altref2
}
if (rf->n_mfmvs < total && rp_ref[6] &&
get_poc_diff(seq_hdr->order_hint_n_bits, ref_poc[6],
frm_hdr->frame_offset) > 0)
{
rf->mfmv_ref[rf->n_mfmvs++] = 6; // altref
}
if (rf->n_mfmvs < total && rp_ref[1])
rf->mfmv_ref[rf->n_mfmvs++] = 1; // last2
for (int n = 0; n < rf->n_mfmvs; n++) { const int rpoc = ref_poc[rf->mfmv_ref[n]]; const int diff1 = get_poc_diff(seq_hdr->order_hint_n_bits,
rpoc, frm_hdr->frame_offset);
if (abs(diff1) > 31) {
rf->mfmv_ref2cur[n] = INVALID_REF2CUR;
} else {
rf->mfmv_ref2cur[n] = rf->mfmv_ref[n] < 4 ? -diff1 : diff1;
for (int m = 0; m < 7; m++) { const int rrpoc = ref_ref_poc[rf->mfmv_ref[n]][m]; const int diff2 = get_poc_diff(seq_hdr->order_hint_n_bits,
rpoc, rrpoc); // unsigned comparison also catches the < 0 case
rf->mfmv_ref2ref[n][m] = (unsigned) diff2 > 31U ? 0 : diff2;
}
}
}
}
rf->use_ref_frame_mvs = rf->n_mfmvs > 0;
return0;
}
staticvoid splat_mv_c(refmvs_block **rr, const refmvs_block *const rmv, const int bx4, const int bw4, int bh4)
{ do {
refmvs_block *const r = *rr++ + bx4;
for (int x = 0; x < bw4; x++)
r[x] = *rmv;
} while (--bh4);
}
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.