@@ -55,20 +55,18 @@ typedef struct ZmbvEncContext {
55
55
int keyint , curfrm ;
56
56
z_stream zstream ;
57
57
58
- int score_tab [ZMBV_BLOCK * ZMBV_BLOCK + 1 ];
58
+ int score_tab [2 * ZMBV_BLOCK * ZMBV_BLOCK + 1 ];
59
59
} ZmbvEncContext ;
60
60
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
64
64
*/
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 ,
66
66
uint8_t * src2 , int stride2 , int bw , int bh ,
67
- int * xored )
68
- {
69
- int sum = 0 ;
67
+ int * xored , uint16_t * histogram ) {
70
68
int i , j ;
71
- uint16_t histogram [ 256 ] = { 0 } ;
69
+ memset ( histogram , 0 , 256 * sizeof ( histogram [ 0 ])) ;
72
70
73
71
/* Build frequency histogram of byte values for src[] ^ src2[] */
74
72
for (j = 0 ; j < bh ; j ++ ){
@@ -83,12 +81,27 @@ static inline int block_cmp(ZmbvEncContext *c, uint8_t *src, int stride,
83
81
/* If not all the xored values were 0, then the blocks are different */
84
82
* xored = (histogram [0 ] < bw * bh );
85
83
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
+
86
99
/* Exit early if blocks are equal */
87
100
if (!* xored ) return 0 ;
88
101
89
102
/* Sum the entropy of all values */
90
103
for (i = 0 ; i < 256 ; i ++ )
91
- sum += c -> score_tab [histogram [i ]];
104
+ sum += c -> score_tab [histogram [i ] + prev_histogram [ i ] ];
92
105
93
106
return sum ;
94
107
}
@@ -97,24 +110,26 @@ static inline int block_cmp(ZmbvEncContext *c, uint8_t *src, int stride,
97
110
* TODO make better ME decisions
98
111
*/
99
112
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 )
101
114
{
102
115
int dx , dy , txored , tv , bv , bw , bh ;
103
116
int mx0 , my0 ;
104
117
105
118
mx0 = * mx ;
106
119
my0 = * my ;
120
+
121
+ * mx = * my = 0 ;
107
122
bw = FFMIN (ZMBV_BLOCK , c -> avctx -> width - x );
108
123
bh = FFMIN (ZMBV_BLOCK , c -> avctx -> height - y );
109
124
110
125
/* 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 );
112
127
* mx = * my = 0 ;
113
128
if (!bv ) return 0 ;
114
129
115
130
/* Try previous block's MV (if not 0,0) */
116
131
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 );
118
133
if (tv < bv ){
119
134
bv = tv ;
120
135
* mx = mx0 ;
@@ -129,7 +144,7 @@ static int zmbv_me(ZmbvEncContext *c, uint8_t *src, int sstride, uint8_t *prev,
129
144
for (dx = - c -> lrange ; dx <= c -> urange ; dx ++ ){
130
145
if (!dx && !dy ) continue ; // we already tested this block
131
146
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 );
133
148
if (tv < bv ){
134
149
bv = tv ;
135
150
* mx = dx ;
@@ -154,6 +169,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
154
169
int work_size = 0 , pkt_size ;
155
170
int bw , bh ;
156
171
int i , j , ret ;
172
+ uint16_t prev_histogram [256 ] = {0 };
157
173
158
174
keyframe = !c -> curfrm ;
159
175
c -> curfrm ++ ;
@@ -209,13 +225,15 @@ FF_ENABLE_DEPRECATION_WARNINGS
209
225
/* for now just XOR'ing */
210
226
for (y = 0 ; y < avctx -> height ; y += ZMBV_BLOCK ) {
211
227
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 ));
212
230
for (x = 0 ; x < avctx -> width ; x += ZMBV_BLOCK , mv += 2 ) {
213
231
bw2 = FFMIN (avctx -> width - x , ZMBV_BLOCK );
214
232
215
233
tsrc = src + x ;
216
234
tprev = prev + x ;
217
235
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 );
219
237
mv [0 ] = (mx << 1 ) | !!xored ;
220
238
mv [1 ] = my << 1 ;
221
239
tprev += mx + my * c -> pstride ;
@@ -227,6 +245,8 @@ FF_ENABLE_DEPRECATION_WARNINGS
227
245
tprev += c -> pstride ;
228
246
}
229
247
}
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 );
230
250
}
231
251
src += p -> linesize [0 ] * ZMBV_BLOCK ;
232
252
prev += c -> pstride * ZMBV_BLOCK ;
0 commit comments