/*
* 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
*/
#include "vp9.h"
#include "vp9dec.h"
static av_always_inline void adapt_prob(uint8_t *p, unsigned ct0, unsigned ct1,
int max_count, int update_factor)
{
unsigned ct = ct0 + ct1, p2, p1;
if (!ct)
return ;
update_factor = FASTDIV(update_factor * FFMIN(ct, max_count), max_count);
p1 = *p;
p2 = ((((int64_t) ct0) << 8 ) + (ct >> 1 )) / ct;
p2 = av_clip(p2, 1 , 255 );
// (p1 * (256 - update_factor) + p2 * update_factor + 128) >> 8
*p = p1 + (((p2 - p1) * update_factor + 128 ) >> 8 );
}
void ff_vp9_adapt_probs(VP9Context *s)
{
int i, j, k, l, m;
ProbContext *p = &s->prob_ctx[s->s.h.framectxid].p;
int uf = (s->s.h.keyframe || s->s.h.intraonly || !s->last_keyframe) ? 112 : 128 ;
// coefficients
for (i = 0 ; i < 4 ; i++)
for (j = 0 ; j < 2 ; j++)
for (k = 0 ; k < 2 ; k++)
for (l = 0 ; l < 6 ; l++)
for (m = 0 ; m < 6 ; m++) {
uint8_t *pp = s->prob_ctx[s->s.h.framectxid].coef[i][j][k][l][m];
unsigned *e = s->td[0 ].counts.eob[i][j][k][l][m];
unsigned *c = s->td[0 ].counts.coef[i][j][k][l][m];
if (l == 0 && m >= 3 ) // dc only has 3 pt
break ;
adapt_prob(&pp[0 ], e[0 ], e[1 ], 24 , uf);
adapt_prob(&pp[1 ], c[0 ], c[1 ] + c[2 ], 24 , uf);
adapt_prob(&pp[2 ], c[1 ], c[2 ], 24 , uf);
}
if (s->s.h.keyframe || s->s.h.intraonly) {
memcpy(p->skip, s->prob.p.skip, sizeof (p->skip));
memcpy(p->tx32p, s->prob.p.tx32p, sizeof (p->tx32p));
memcpy(p->tx16p, s->prob.p.tx16p, sizeof (p->tx16p));
memcpy(p->tx8p, s->prob.p.tx8p, sizeof (p->tx8p));
return ;
}
// skip flag
for (i = 0 ; i < 3 ; i++)
adapt_prob(&p->skip[i], s->td[0 ].counts.skip[i][0 ],
s->td[0 ].counts.skip[i][1 ], 20 , 128 );
// intra/inter flag
for (i = 0 ; i < 4 ; i++)
adapt_prob(&p->intra[i], s->td[0 ].counts.intra[i][0 ],
s->td[0 ].counts.intra[i][1 ], 20 , 128 );
// comppred flag
if (s->s.h.comppredmode == PRED_SWITCHABLE) {
for (i = 0 ; i < 5 ; i++)
adapt_prob(&p->comp[i], s->td[0 ].counts.comp[i][0 ],
s->td[0 ].counts.comp[i][1 ], 20 , 128 );
}
// reference frames
if (s->s.h.comppredmode != PRED_SINGLEREF) {
for (i = 0 ; i < 5 ; i++)
adapt_prob(&p->comp_ref[i], s->td[0 ].counts.comp_ref[i][0 ],
s->td[0 ].counts.comp_ref[i][1 ], 20 , 128 );
}
if (s->s.h.comppredmode != PRED_COMPREF) {
for (i = 0 ; i < 5 ; i++) {
uint8_t *pp = p->single_ref[i];
unsigned (*c)[2 ] = s->td[0 ].counts.single_ref[i];
adapt_prob(&pp[0 ], c[0 ][0 ], c[0 ][1 ], 20 , 128 );
adapt_prob(&pp[1 ], c[1 ][0 ], c[1 ][1 ], 20 , 128 );
}
}
// block partitioning
for (i = 0 ; i < 4 ; i++)
for (j = 0 ; j < 4 ; j++) {
uint8_t *pp = p->partition[i][j];
unsigned *c = s->td[0 ].counts.partition[i][j];
adapt_prob(&pp[0 ], c[0 ], c[1 ] + c[2 ] + c[3 ], 20 , 128 );
adapt_prob(&pp[1 ], c[1 ], c[2 ] + c[3 ], 20 , 128 );
adapt_prob(&pp[2 ], c[2 ], c[3 ], 20 , 128 );
}
// tx size
if (s->s.h.txfmmode == TX_SWITCHABLE) {
for (i = 0 ; i < 2 ; i++) {
unsigned *c16 = s->td[0 ].counts.tx16p[i], *c32 = s->td[0 ].counts.tx32p[i];
adapt_prob(&p->tx8p[i], s->td[0 ].counts.tx8p[i][0 ],
s->td[0 ].counts.tx8p[i][1 ], 20 , 128 );
adapt_prob(&p->tx16p[i][0 ], c16[0 ], c16[1 ] + c16[2 ], 20 , 128 );
adapt_prob(&p->tx16p[i][1 ], c16[1 ], c16[2 ], 20 , 128 );
adapt_prob(&p->tx32p[i][0 ], c32[0 ], c32[1 ] + c32[2 ] + c32[3 ], 20 , 128 );
adapt_prob(&p->tx32p[i][1 ], c32[1 ], c32[2 ] + c32[3 ], 20 , 128 );
adapt_prob(&p->tx32p[i][2 ], c32[2 ], c32[3 ], 20 , 128 );
}
}
// interpolation filter
if (s->s.h.filtermode == FILTER_SWITCHABLE) {
for (i = 0 ; i < 4 ; i++) {
uint8_t *pp = p->filter[i];
unsigned *c = s->td[0 ].counts.filter[i];
adapt_prob(&pp[0 ], c[0 ], c[1 ] + c[2 ], 20 , 128 );
adapt_prob(&pp[1 ], c[1 ], c[2 ], 20 , 128 );
}
}
// inter modes
for (i = 0 ; i < 7 ; i++) {
uint8_t *pp = p->mv_mode[i];
unsigned *c = s->td[0 ].counts.mv_mode[i];
adapt_prob(&pp[0 ], c[2 ], c[1 ] + c[0 ] + c[3 ], 20 , 128 );
adapt_prob(&pp[1 ], c[0 ], c[1 ] + c[3 ], 20 , 128 );
adapt_prob(&pp[2 ], c[1 ], c[3 ], 20 , 128 );
}
// mv joints
{
uint8_t *pp = p->mv_joint;
unsigned *c = s->td[0 ].counts.mv_joint;
adapt_prob(&pp[0 ], c[0 ], c[1 ] + c[2 ] + c[3 ], 20 , 128 );
adapt_prob(&pp[1 ], c[1 ], c[2 ] + c[3 ], 20 , 128 );
adapt_prob(&pp[2 ], c[2 ], c[3 ], 20 , 128 );
}
// mv components
for (i = 0 ; i < 2 ; i++) {
uint8_t *pp;
unsigned *c, (*c2)[2 ], sum;
adapt_prob(&p->mv_comp[i].sign, s->td[0 ].counts.mv_comp[i].sign[0 ],
s->td[0 ].counts.mv_comp[i].sign[1 ], 20 , 128 );
pp = p->mv_comp[i].classes;
c = s->td[0 ].counts.mv_comp[i].classes;
sum = c[1 ] + c[2 ] + c[3 ] + c[4 ] + c[5 ] +
c[6 ] + c[7 ] + c[8 ] + c[9 ] + c[10 ];
adapt_prob(&pp[0 ], c[0 ], sum, 20 , 128 );
sum -= c[1 ];
adapt_prob(&pp[1 ], c[1 ], sum, 20 , 128 );
sum -= c[2 ] + c[3 ];
adapt_prob(&pp[2 ], c[2 ] + c[3 ], sum, 20 , 128 );
adapt_prob(&pp[3 ], c[2 ], c[3 ], 20 , 128 );
sum -= c[4 ] + c[5 ];
adapt_prob(&pp[4 ], c[4 ] + c[5 ], sum, 20 , 128 );
adapt_prob(&pp[5 ], c[4 ], c[5 ], 20 , 128 );
sum -= c[6 ];
adapt_prob(&pp[6 ], c[6 ], sum, 20 , 128 );
adapt_prob(&pp[7 ], c[7 ] + c[8 ], c[9 ] + c[10 ], 20 , 128 );
adapt_prob(&pp[8 ], c[7 ], c[8 ], 20 , 128 );
adapt_prob(&pp[9 ], c[9 ], c[10 ], 20 , 128 );
adapt_prob(&p->mv_comp[i].class0, s->td[0 ].counts.mv_comp[i].class0[0 ],
s->td[0 ].counts.mv_comp[i].class0[1 ], 20 , 128 );
pp = p->mv_comp[i].bits;
c2 = s->td[0 ].counts.mv_comp[i].bits;
for (j = 0 ; j < 10 ; j++)
adapt_prob(&pp[j], c2[j][0 ], c2[j][1 ], 20 , 128 );
for (j = 0 ; j < 2 ; j++) {
pp = p->mv_comp[i].class0_fp[j];
c = s->td[0 ].counts.mv_comp[i].class0_fp[j];
adapt_prob(&pp[0 ], c[0 ], c[1 ] + c[2 ] + c[3 ], 20 , 128 );
adapt_prob(&pp[1 ], c[1 ], c[2 ] + c[3 ], 20 , 128 );
adapt_prob(&pp[2 ], c[2 ], c[3 ], 20 , 128 );
}
pp = p->mv_comp[i].fp;
c = s->td[0 ].counts.mv_comp[i].fp;
adapt_prob(&pp[0 ], c[0 ], c[1 ] + c[2 ] + c[3 ], 20 , 128 );
adapt_prob(&pp[1 ], c[1 ], c[2 ] + c[3 ], 20 , 128 );
adapt_prob(&pp[2 ], c[2 ], c[3 ], 20 , 128 );
if (s->s.h.highprecisionmvs) {
adapt_prob(&p->mv_comp[i].class0_hp,
s->td[0 ].counts.mv_comp[i].class0_hp[0 ],
s->td[0 ].counts.mv_comp[i].class0_hp[1 ], 20 , 128 );
adapt_prob(&p->mv_comp[i].hp, s->td[0 ].counts.mv_comp[i].hp[0 ],
s->td[0 ].counts.mv_comp[i].hp[1 ], 20 , 128 );
}
}
// y intra modes
for (i = 0 ; i < 4 ; i++) {
uint8_t *pp = p->y_mode[i];
unsigned *c = s->td[0 ].counts.y_mode[i], sum, s2;
sum = c[0 ] + c[1 ] + c[3 ] + c[4 ] + c[5 ] + c[6 ] + c[7 ] + c[8 ] + c[9 ];
adapt_prob(&pp[0 ], c[DC_PRED], sum, 20 , 128 );
sum -= c[TM_VP8_PRED];
adapt_prob(&pp[1 ], c[TM_VP8_PRED], sum, 20 , 128 );
sum -= c[VERT_PRED];
adapt_prob(&pp[2 ], c[VERT_PRED], sum, 20 , 128 );
s2 = c[HOR_PRED] + c[DIAG_DOWN_RIGHT_PRED] + c[VERT_RIGHT_PRED];
sum -= s2;
adapt_prob(&pp[3 ], s2, sum, 20 , 128 );
s2 -= c[HOR_PRED];
adapt_prob(&pp[4 ], c[HOR_PRED], s2, 20 , 128 );
adapt_prob(&pp[5 ], c[DIAG_DOWN_RIGHT_PRED], c[VERT_RIGHT_PRED],
20 , 128 );
sum -= c[DIAG_DOWN_LEFT_PRED];
adapt_prob(&pp[6 ], c[DIAG_DOWN_LEFT_PRED], sum, 20 , 128 );
sum -= c[VERT_LEFT_PRED];
adapt_prob(&pp[7 ], c[VERT_LEFT_PRED], sum, 20 , 128 );
adapt_prob(&pp[8 ], c[HOR_DOWN_PRED], c[HOR_UP_PRED], 20 , 128 );
}
// uv intra modes
for (i = 0 ; i < 10 ; i++) {
uint8_t *pp = p->uv_mode[i];
unsigned *c = s->td[0 ].counts.uv_mode[i], sum, s2;
sum = c[0 ] + c[1 ] + c[3 ] + c[4 ] + c[5 ] + c[6 ] + c[7 ] + c[8 ] + c[9 ];
adapt_prob(&pp[0 ], c[DC_PRED], sum, 20 , 128 );
sum -= c[TM_VP8_PRED];
adapt_prob(&pp[1 ], c[TM_VP8_PRED], sum, 20 , 128 );
sum -= c[VERT_PRED];
adapt_prob(&pp[2 ], c[VERT_PRED], sum, 20 , 128 );
s2 = c[HOR_PRED] + c[DIAG_DOWN_RIGHT_PRED] + c[VERT_RIGHT_PRED];
sum -= s2;
adapt_prob(&pp[3 ], s2, sum, 20 , 128 );
s2 -= c[HOR_PRED];
adapt_prob(&pp[4 ], c[HOR_PRED], s2, 20 , 128 );
adapt_prob(&pp[5 ], c[DIAG_DOWN_RIGHT_PRED], c[VERT_RIGHT_PRED],
20 , 128 );
sum -= c[DIAG_DOWN_LEFT_PRED];
adapt_prob(&pp[6 ], c[DIAG_DOWN_LEFT_PRED], sum, 20 , 128 );
sum -= c[VERT_LEFT_PRED];
adapt_prob(&pp[7 ], c[VERT_LEFT_PRED], sum, 20 , 128 );
adapt_prob(&pp[8 ], c[HOR_DOWN_PRED], c[HOR_UP_PRED], 20 , 128 );
}
}
Messung V0.5 in Prozent C=92 H=92 G=91
¤ Dauer der Verarbeitung: 0.9 Sekunden
(vorverarbeitet am 2026-06-06)
¤
*© Formatika GbR, Deutschland