Skip to content

Commit c02d54c

Browse files
committed
Calculate block scores taking previous block's histogram into account
- move histogram-building code into its own function - add histogram[i] and prev_histogram[i] together when calculating the sum - store the prev_histogram for vx,vy after writing every block - increase score_tab maximum index by 2 So far this approach seems to adversely affect compression.
1 parent ab82af4 commit c02d54c

File tree

1 file changed

+35
-15
lines changed

1 file changed

+35
-15
lines changed

libavcodec/zmbvenc.c

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -55,20 +55,18 @@ typedef struct ZmbvEncContext {
5555
int keyint, curfrm;
5656
z_stream zstream;
5757

58-
int score_tab[ZMBV_BLOCK * ZMBV_BLOCK + 1];
58+
int score_tab[2 * ZMBV_BLOCK * ZMBV_BLOCK + 1];
5959
} ZmbvEncContext;
6060

61-
62-
/** Block comparing function
63-
* XXX should be optimized and moved to DSPContext
61+
/** Block histogram generating function
62+
* XORs all the bytes in all the blocks and counts the occurence of each
63+
* resulting value
6464
*/
65-
static inline int block_cmp(ZmbvEncContext *c, uint8_t *src, int stride,
65+
static inline void block_histogram(ZmbvEncContext *c, uint8_t *src, int stride,
6666
uint8_t *src2, int stride2, int bw, int bh,
67-
int *xored)
68-
{
69-
int sum = 0;
67+
int *xored, uint16_t *histogram) {
7068
int i, j;
71-
uint16_t histogram[256] = {0};
69+
memset(histogram, 0, 256*sizeof(histogram[0]));
7270

7371
/* Build frequency histogram of byte values for src[] ^ src2[] */
7472
for(j = 0; j < bh; j++){
@@ -83,12 +81,27 @@ static inline int block_cmp(ZmbvEncContext *c, uint8_t *src, int stride,
8381
/* If not all the xored values were 0, then the blocks are different */
8482
*xored = (histogram[0] < bw * bh);
8583

84+
}
85+
86+
/** Block comparing function
87+
* XXX should be optimized and moved to DSPContext
88+
*/
89+
static inline int block_cmp(ZmbvEncContext *c, uint8_t *src, int stride,
90+
uint8_t *src2, int stride2, int bw, int bh,
91+
int *xored, uint16_t * const prev_histogram)
92+
{
93+
int i;
94+
unsigned int sum = 0;
95+
uint16_t histogram[256] = {0};
96+
97+
block_histogram(c, src, stride, src2, stride2, bw, bh, xored, histogram);
98+
8699
/* Exit early if blocks are equal */
87100
if (!*xored) return 0;
88101

89102
/* Sum the entropy of all values */
90103
for(i = 0; i < 256; i++)
91-
sum += c->score_tab[histogram[i]];
104+
sum += c->score_tab[histogram[i] + prev_histogram[i]];
92105

93106
return sum;
94107
}
@@ -97,24 +110,26 @@ static inline int block_cmp(ZmbvEncContext *c, uint8_t *src, int stride,
97110
* TODO make better ME decisions
98111
*/
99112
static int zmbv_me(ZmbvEncContext *c, uint8_t *src, int sstride, uint8_t *prev,
100-
int pstride, int x, int y, int *mx, int *my, int *xored)
113+
int pstride, int x, int y, int *mx, int *my, int *xored, uint16_t * const prev_histogram)
101114
{
102115
int dx, dy, txored, tv, bv, bw, bh;
103116
int mx0, my0;
104117

105118
mx0 = *mx;
106119
my0 = *my;
120+
121+
*mx = *my = 0;
107122
bw = FFMIN(ZMBV_BLOCK, c->avctx->width - x);
108123
bh = FFMIN(ZMBV_BLOCK, c->avctx->height - y);
109124

110125
/* Try (0,0) */
111-
bv = block_cmp(c, src, sstride, prev, pstride, bw, bh, xored);
126+
bv = block_cmp(c, src, sstride, prev, pstride, bw, bh, xored, prev_histogram);
112127
*mx = *my = 0;
113128
if(!bv) return 0;
114129

115130
/* Try previous block's MV (if not 0,0) */
116131
if (mx0 || my0){
117-
tv = block_cmp(c, src, sstride, prev + mx0 + my0 * pstride, pstride, bw, bh, &txored);
132+
tv = block_cmp(c, src, sstride, prev + mx0 + my0 * pstride, pstride, bw, bh, &txored, prev_histogram);
118133
if(tv < bv){
119134
bv = tv;
120135
*mx = mx0;
@@ -129,7 +144,7 @@ static int zmbv_me(ZmbvEncContext *c, uint8_t *src, int sstride, uint8_t *prev,
129144
for(dx = -c->lrange; dx <= c->urange; dx++){
130145
if(!dx && !dy) continue; // we already tested this block
131146
if(dx == mx0 && dy == my0) continue; // this one too
132-
tv = block_cmp(c, src, sstride, prev + dx + dy * pstride, pstride, bw, bh, &txored);
147+
tv = block_cmp(c, src, sstride, prev + dx + dy * pstride, pstride, bw, bh, &txored, prev_histogram);
133148
if(tv < bv){
134149
bv = tv;
135150
*mx = dx;
@@ -154,6 +169,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
154169
int work_size = 0, pkt_size;
155170
int bw, bh;
156171
int i, j, ret;
172+
uint16_t prev_histogram[256] = {0};
157173

158174
keyframe = !c->curfrm;
159175
c->curfrm++;
@@ -209,13 +225,15 @@ FF_ENABLE_DEPRECATION_WARNINGS
209225
/* for now just XOR'ing */
210226
for(y = 0; y < avctx->height; y += ZMBV_BLOCK) {
211227
bh2 = FFMIN(avctx->height - y, ZMBV_BLOCK);
228+
/* Don't use the prev histogram from the end of the last row */
229+
memset(prev_histogram, 0, sizeof(prev_histogram));
212230
for(x = 0; x < avctx->width; x += ZMBV_BLOCK, mv += 2) {
213231
bw2 = FFMIN(avctx->width - x, ZMBV_BLOCK);
214232

215233
tsrc = src + x;
216234
tprev = prev + x;
217235

218-
zmbv_me(c, tsrc, p->linesize[0], tprev, c->pstride, x, y, &mx, &my, &xored);
236+
zmbv_me(c, tsrc, p->linesize[0], tprev, c->pstride, x, y, &mx, &my, &xored, prev_histogram);
219237
mv[0] = (mx << 1) | !!xored;
220238
mv[1] = my << 1;
221239
tprev += mx + my * c->pstride;
@@ -227,6 +245,8 @@ FF_ENABLE_DEPRECATION_WARNINGS
227245
tprev += c->pstride;
228246
}
229247
}
248+
/* Store the previous histogram to use with the next block */
249+
block_histogram(c, src, p->linesize[0], prev + mx + my * c->pstride, c->pstride, bw, bh, &xored, prev_histogram);
230250
}
231251
src += p->linesize[0] * ZMBV_BLOCK;
232252
prev += c->pstride * ZMBV_BLOCK;

0 commit comments

Comments
 (0)