blob: d9719fdca3afbae53a4d4f803e561414024fe893 [file] [log] [blame]
/*------------------------------------------------------------------------------
-- --
-- This software is confidential and proprietary and may be used --
-- only as expressly authorized by a licensing agreement from --
-- --
-- Hantro Products Oy. --
-- --
-- (C) COPYRIGHT 2006 HANTRO PRODUCTS OY --
-- ALL RIGHTS RESERVED --
-- --
-- The entire notice above must be reproduced --
-- on all copies and should not be removed. --
-- --
--------------------------------------------------------------------------------
*/
#include "vp8entropy.h"
#include <memory.h>
#include "enccommon.h"
#include "vp8entropytable.h"
#include "vp8macroblocktools.h"
/* Approximate bit cost of bin at given probability prob */
#define COST_BOOL(prob, bin)\
((bin) ? vp8_prob_cost[255 - (prob)] : vp8_prob_cost[prob])
enum {
MAX_BAND = 7,
MAX_CTX = 3,
};
static int32_t CostTree(tree const* tree, int32_t* prob);
static void UpdateEntropy(vp8Instance_s* inst);
void EncSwapEndianess(uint32_t* buf, uint32_t sizeBytes) {
#if (ENCH1_OUTPUT_SWAP_8 == 1)
uint32_t i = 0;
int32_t words = sizeBytes / 4;
ASSERT((sizeBytes % 8) == 0);
while (words > 0) {
uint32_t val = buf[i];
uint32_t tmp = 0;
tmp |= (val & 0xFF) << 24;
tmp |= (val & 0xFF00) << 8;
tmp |= (val & 0xFF0000) >> 8;
tmp |= (val & 0xFF000000) >> 24;
#if(ENCH1_OUTPUT_SWAP_32 == 1) /* need this for 64-bit HW */
{
uint32_t val2 = buf[i + 1];
uint32_t tmp2 = 0;
tmp2 |= (val2 & 0xFF) << 24;
tmp2 |= (val2 & 0xFF00) << 8;
tmp2 |= (val2 & 0xFF0000) >> 8;
tmp2 |= (val2 & 0xFF000000) >> 24;
buf[i] = tmp2;
words--;
i++;
}
#endif
buf[i] = tmp;
words--;
i++;
}
#endif
}
void InitEntropy(vp8Instance_s* inst) {
entropy* entropy = inst->entropy;
ASSERT(sizeof(defaultCoeffProb) == sizeof(entropy->coeffProb));
ASSERT(sizeof(defaultCoeffProb) == sizeof(coeffUpdateProb));
ASSERT(sizeof(defaultMvProb) == sizeof(mvUpdateProb));
ASSERT(sizeof(defaultMvProb) == sizeof(entropy->mvProb));
UpdateEntropy(inst);
/* Default propability */
entropy->lastProb = 255; /* Stetson-Harrison method TODO */
entropy->gfProb = 128; /* Stetson-Harrison method TODO */
memcpy(entropy->YmodeProb, YmodeProb, sizeof(YmodeProb));
memcpy(entropy->UVmodeProb, UVmodeProb, sizeof(UVmodeProb));
}
void WriteEntropyTables(vp8Instance_s* inst) {
entropy* entropy = inst->entropy;
uint8_t* table = (uint8_t*)inst->asic.cabacCtx.vir_addr;
int32_t i, j, k, l;
ASSERT(table);
/* Write probability tables to ASIC linear memory, reg + mem */
memset(table, 0, 56);
table[0] = entropy->skipFalseProb;
table[1] = entropy->intraProb;
table[2] = entropy->lastProb;
table[3] = entropy->gfProb;
table[4] = entropy->segmentProb[0];
table[5] = entropy->segmentProb[1];
table[6] = entropy->segmentProb[2];
table[8] = entropy->YmodeProb[0];
table[9] = entropy->YmodeProb[1];
table[10] = entropy->YmodeProb[2];
table[11] = entropy->YmodeProb[3];
table[12] = entropy->UVmodeProb[0];
table[13] = entropy->UVmodeProb[1];
table[14] = entropy->UVmodeProb[2];
/* MV probabilities x+y: short, sign, size 8-9 */
table[16] = entropy->mvProb[1][0];
table[17] = entropy->mvProb[0][0];
table[18] = entropy->mvProb[1][1];
table[19] = entropy->mvProb[0][1];
table[20] = entropy->mvProb[1][17];
table[21] = entropy->mvProb[1][18];
table[22] = entropy->mvProb[0][17];
table[23] = entropy->mvProb[0][18];
/* MV X size */
for (i = 0; i < 8; i++)
table[24 + i] = entropy->mvProb[1][9 + i];
/* MV Y size */
for (i = 0; i < 8; i++)
table[32 + i] = entropy->mvProb[0][9 + i];
/* MV X short tree */
for (i = 0; i < 7; i++)
table[40 + i] = entropy->mvProb[1][2 + i];
/* MV Y short tree */
for (i = 0; i < 7; i++)
table[48 + i] = entropy->mvProb[0][2 + i];
/* Update the ASIC table when needed. */
if (entropy->updateCoeffProbFlag) {
table += 56;
/* DCT coeff probabilities 0-2, two fields per line. */
for (i = 0; i < 4; i++)
for (j = 0; j < 8; j++)
for (k = 0; k < 3; k++) {
for (l = 0; l < 3; l++) {
*table++ = entropy->coeffProb[i][j][k][l];
}
*table++ = 0;
}
/* ASIC second probability table in ext mem.
* DCT coeff probabilities 4 5 6 7 8 9 10 3 on each line.
* coeff 3 was moved from first table to second so it is last. */
for (i = 0; i < 4; i++)
for (j = 0; j < 8; j++)
for (k = 0; k < 3; k++) {
for (l = 4; l < 11; l++) {
*table++ = entropy->coeffProb[i][j][k][l];
}
*table++ = entropy->coeffProb[i][j][k][3];
}
}
table = (uint8_t*)inst->asic.cabacCtx.vir_addr;
if (entropy->updateCoeffProbFlag)
EncSwapEndianess((uint32_t*)table, 56 + 8 * 48 + 8 * 96);
else
EncSwapEndianess((uint32_t*)table, 56);
}
void InitTreePenaltyTables(vp8Instance_s* container) {
mbs* mbs = &container->mbs; /* Macroblock related stuff */
int32_t tmp, i;
/* Calculate bit cost for each 16x16 mode, uses p-frame probs */
for (i = DC_PRED; i <= B_PRED; i++) {
tmp = CostTree(YmodeTree[i], (int32_t*)YmodeProb);
mbs->intra16ModeBitCost[i] = tmp;
}
/* Calculate bit cost for each 4x4 mode, uses p-frame probs */
for (i = B_DC_PRED; i <= B_HU_PRED; i++) {
tmp = CostTree(BmodeTree[i], (int32_t*)BmodeProb);
mbs->intra4ModeBitCost[i] = tmp;
}
}
int32_t CostTree(tree const* tree, int32_t* prob) {
int32_t value = tree->value;
int32_t number = tree->number;
int32_t const* index = tree->index;
int32_t bitCost = 0;
while (number--) {
bitCost += COST_BOOL(prob[*index++], (value >> number) & 1);
}
return bitCost;
}
int32_t CostMv(int32_t mvd, int32_t* mvProb) {
int32_t i, tmp, bitCost = 0;
/* Luma motion vectors are doubled, see 18.1 in "VP8 Data Format and
* Decoding Guide". */
ASSERT(!(mvd & 1));
tmp = ABS(mvd >> 1);
/* Short Tree */
if (tmp < 8) {
bitCost += COST_BOOL(mvProb[0], 0);
bitCost += CostTree(&mvTree[tmp], mvProb + 2);
if (!tmp) return bitCost;
/* Sign */
bitCost += COST_BOOL(mvProb[1], mvd < 0);
return bitCost;
}
/* Long Tree */
bitCost += COST_BOOL(mvProb[0], 1);
/* Bits 0, 1, 2 */
for (i = 0; i < 3; i++) {
bitCost += COST_BOOL(mvProb[9 + i], (tmp >> i) & 1);
}
/* Bits 9, 8, 7, 6, 5, 4 */
for (i = 9; i > 3; i--) {
bitCost += COST_BOOL(mvProb[9 + i], (tmp >> i) & 1);
}
/* Bit 3: if ABS(mvd) < 8, it is coded with short tree, so if here
* ABS(mvd) <= 15, bit 3 must be one (because here we code values
* 8,...,15) and is not explicitly coded. */
if (tmp > 15) {
bitCost += COST_BOOL(mvProb[9 + 3], (tmp >> 3) & 1);
}
/* Sign */
bitCost += COST_BOOL(mvProb[1], mvd < 0);
return bitCost;
}
void CoeffProb(vp8buffer* buffer, int32_t curr[4][8][3][11],
int32_t prev[4][8][3][11]) {
int32_t i, j, k, l;
int32_t prob, new, old;
for (i = 0; i < 4; i++) {
for (j = 0; j < 8; j++) {
for (k = 0; k < 3; k++) {
for (l = 0; l < 11; l++) {
prob = coeffUpdateProb[i][j][k][l];
old = prev[i][j][k][l];
new = curr[i][j][k][l];
if (new == old) {
VP8PutBool(buffer, prob, 0);
COMMENT("Coeff prob update");
} else {
VP8PutBool(buffer, prob, 1);
COMMENT("Coeff prob update");
VP8PutLit(buffer, new, 8);
COMMENT("New prob");
}
}
}
}
}
}
void MvProb(vp8buffer* buffer, int32_t curr[2][19], int32_t prev[2][19]) {
int32_t i, j;
int32_t prob, new, old;
for (i = 0; i < 2; i++) {
for (j = 0; j < 19; j++) {
prob = mvUpdateProb[i][j];
old = prev[i][j];
new = curr[i][j];
if (new == old) {
VP8PutBool(buffer, prob, 0);
COMMENT("MV prob update");
} else {
VP8PutBool(buffer, prob, 1);
COMMENT("MV prob update");
VP8PutLit(buffer, new >> 1, 7);
COMMENT("New prob");
}
}
}
}
/*------------------------------------------------------------------------------
update
determine if given probability is to be updated (savings larger than
cost of update)
------------------------------------------------------------------------------*/
uint32_t update(uint32_t updP, uint32_t left, uint32_t right, uint32_t oldP,
uint32_t newP, uint32_t fixed) {
int32_t u, s;
/* how much it costs to update a coeff */
u = (int32_t)fixed + ((vp8_prob_cost[255 - updP] - vp8_prob_cost[updP]) >> 8);
/* bit savings if updated */
s = ((int32_t)left * /* zero branch count */
/* diff cost for '0' bin */
(vp8_prob_cost[oldP] - vp8_prob_cost[newP]) +
(int32_t)right * /* one branch count */
/* diff cost for '1' bin */
(vp8_prob_cost[255 - oldP] - vp8_prob_cost[255 - newP])) >> 8;
return (s > u);
}
/*------------------------------------------------------------------------------
mvprob
compute new mv probability
------------------------------------------------------------------------------*/
uint32_t mvprob(uint32_t left, uint32_t right, uint32_t oldP) {
uint32_t p;
if (left + right) {
p = (left * 255) / (left + right);
p &= -2;
if (!p) p = 1;
} else
p = oldP;
return p;
}
/*------------------------------------------------------------------------------
UpdateEntropy
------------------------------------------------------------------------------*/
void UpdateEntropy(vp8Instance_s* inst) {
entropy* entropy = inst->entropy;
int32_t i, j, k, l, tmp, ii;
uint16_t* pCnt = (uint16_t*)inst->asic.probCount.vir_addr;
uint16_t* pTmp;
uint32_t p, left, right, oldP, updP;
uint32_t type;
uint32_t branchCnt[2];
const int32_t offset[] = {
-1, -1, -1, 0, 1, 2, -1, 3, 4, -1, 5, 6, -1, 7, 8, -1,
9, 10, -1, 11, 12, 13, 14, 15, -1, 16, 17, -1, 18, 19, -1, 20,
21, -1, 22, 23, -1, 24, 25, -1, 26, 27, 28, 29, 30, -1, 31, 32,
-1, 33, 34, -1, 35, 36, -1, 37, 38, -1, 39, 40, -1, 41, 42, 43,
44, 45, -1, 46, 47, -1, 48, 49, -1, 50, 51, -1, 52, 53, -1, 54,
55, -1, 56, 57, -1, -1, -1, 58, 59, 60, 61, 62, 63, 64, 65, 66,
67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130,
131, 132, 133, 134, 135, 136, 137, 138, -1, -1, -1, 139, 140, 141, 142, 143,
144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219 };
/* Update the HW prob table only when needed. */
entropy->updateCoeffProbFlag = 0;
/* Use default propabilities as reference when needed. */
if (!inst->sps.refreshEntropy || inst->picBuffer.cur_pic->i_frame) {
/* Only do the copying when something has changed. */
if (!entropy->defaultCoeffProbFlag) {
memcpy(entropy->coeffProb, defaultCoeffProb,
sizeof(defaultCoeffProb));
entropy->updateCoeffProbFlag = 1;
}
memcpy(entropy->mvProb, defaultMvProb, sizeof(defaultMvProb));
entropy->defaultCoeffProbFlag = 1;
}
/* store current probs */
memcpy(entropy->oldCoeffProb, entropy->coeffProb, sizeof(entropy->coeffProb));
if (inst->frameCnt == 0 || !inst->picBuffer.last_pic->i_frame)
memcpy(entropy->oldMvProb, entropy->mvProb, sizeof(entropy->mvProb));
/* init probs */
entropy->skipFalseProb = defaultSkipFalseProb[inst->rateControl.qpHdr];
/* Do not update on first frame, token/branch counters not valid yet. */
if (inst->frameCnt == 0) return;
/* Do not update probabilities for droppable frames. */
if (!inst->picBuffer.cur_pic->ipf && !inst->picBuffer.cur_pic->grf &&
!inst->picBuffer.cur_pic->arf) return;
/* If previous frame was lost the prob counters are not valid. */
if (inst->prevFrameLost) return;
#ifdef TRACE_PROBS
/* Trace HW output prob counters into file */
EncTraceProbs(pCnt, ASIC_VP8_PROB_COUNT_SIZE);
#endif
/* All four block types */
for (i = 0; i < 4; i++) {
/* All but last (==7) bands */
for (j = 0; j < MAX_BAND; j++)
/* All three neighbour contexts */
for (k = 0; k < MAX_CTX; k++) {
/* last token of current (type,band,ctx) */
tmp = i * MAX_BAND * MAX_CTX + j * MAX_CTX + k;
tmp += 2 * 4 * MAX_BAND * MAX_CTX;
ii = offset[tmp];
right = ii >= 0 ? pCnt[ii] : 0;
/* first two branch probabilities */
for (l = 2; l--;) {
oldP = entropy->coeffProb[i][j][k][l];
updP = coeffUpdateProb[i][j][k][l];
tmp -= 4 * MAX_BAND * MAX_CTX;
ii = offset[tmp];
left = ii >= 0 ? pCnt[ii] : 0;
/* probability of 0 for current branch */
if (left + right) {
p = ((left * 256) + ((left + right) >> 1)) / (left + right);
if (p > 255) p = 255;
} else
p = oldP;
if (update(updP, left, right, oldP, p, 8)) {
entropy->coeffProb[i][j][k][l] = p;
entropy->updateCoeffProbFlag = 1;
}
right += left;
}
}
}
/* If updating coeffProbs the defaults are no longer in use. */
if (entropy->updateCoeffProbFlag)
entropy->defaultCoeffProbFlag = 0;
/* skip prob */
pTmp = pCnt + ASIC_VP8_PROB_COUNT_MODE_OFFSET;
p = pTmp[0] * 256 / inst->mbPerFrame;
entropy->skipFalseProb = CLIP3(256 - (int32_t)p, 0, 255);
/* intra prob,, do not update if previous was I frame */
if (!inst->picBuffer.last_pic->i_frame) {
p = pTmp[1] * 255 / inst->mbPerFrame;
entropy->intraProb = CLIP3(p, 0, 255);
} else
entropy->intraProb = 63; /* TODO default value */
/* MV probs shouldn't be updated if previous or current frame is intra */
if (inst->picBuffer.last_pic->i_frame || inst->picBuffer.cur_pic->i_frame)
return;
/* mv probs */
pTmp = pCnt + ASIC_VP8_PROB_COUNT_MV_OFFSET;
for (i = 0; i < 2; i++) {
/* is short prob */
left = *pTmp++; /* short */
right = *pTmp++; /* long */
p = mvprob(left, right, entropy->oldMvProb[i][0]);
if (update(mvUpdateProb[i][0], left, right,
entropy->oldMvProb[i][0], p, 6))
entropy->mvProb[i][0] = p;
/* sign prob */
right += left; /* total mvs */
left = *pTmp++; /* num positive */
/* amount of negative vectors = total - positive - zero vectors */
right -= left - pTmp[0];
p = mvprob(left, right, entropy->oldMvProb[i][1]);
if (update(mvUpdateProb[i][1], left, right,
entropy->oldMvProb[i][1], p, 6))
entropy->mvProb[i][1] = p;
/* short mv probs, branches 2 and 3 (0/1 and 2/3) */
for (j = 0; j < 2; j++) {
left = *pTmp++;
right = *pTmp++;
p = mvprob(left, right, entropy->oldMvProb[i][4 + j]);
if (update(mvUpdateProb[i][4 + j], left, right,
entropy->oldMvProb[i][4 + j], p, 6))
entropy->mvProb[i][4 + j] = p;
branchCnt[j] = left + right;
}
/* short mv probs, branch 1 */
p = mvprob(branchCnt[0], branchCnt[1], entropy->oldMvProb[i][3]);
if (update(mvUpdateProb[i][3], branchCnt[0], branchCnt[1],
entropy->oldMvProb[i][3], p, 6))
entropy->mvProb[i][3] = p;
/* store total count for branch 0 computation */
type = branchCnt[0] + branchCnt[1];
/* short mv probs, branches 5 and 6 (4/5 and 6/7) */
for (j = 0; j < 2; j++) {
left = *pTmp++;
right = *pTmp++;
p = mvprob(left, right, entropy->oldMvProb[i][7 + j]);
if (update(mvUpdateProb[i][7 + j], left, right,
entropy->oldMvProb[i][7 + j], p, 6))
entropy->mvProb[i][7 + j] = p;
branchCnt[j] = left + right;
}
/* short mv probs, branch 4 */
p = mvprob(branchCnt[0], branchCnt[1], entropy->oldMvProb[i][6]);
if (update(mvUpdateProb[i][6], branchCnt[0], branchCnt[1],
entropy->oldMvProb[i][6], p, 6))
entropy->mvProb[i][6] = p;
/* short mv probs, branch 0 */
p = mvprob(type, branchCnt[0] + branchCnt[1], entropy->oldMvProb[i][2]);
if (update(mvUpdateProb[i][2], type, branchCnt[0] + branchCnt[1],
entropy->oldMvProb[i][2], p, 6))
entropy->mvProb[i][2] = p;
}
}