|
|
|
@@ -37,6 +37,7 @@ |
|
|
|
#include <stdlib.h> |
|
|
|
#include <string.h> |
|
|
|
#include <unistd.h> |
|
|
|
#include <limits.h> |
|
|
|
|
|
|
|
#include "common.h" |
|
|
|
#include "avcodec.h" |
|
|
|
@@ -44,6 +45,9 @@ |
|
|
|
#include "mpegvideo.h" |
|
|
|
#include "bswap.h" |
|
|
|
|
|
|
|
#undef NDEBUG |
|
|
|
#include <assert.h> |
|
|
|
|
|
|
|
static VLC svq1_block_type; |
|
|
|
static VLC svq1_motion_component; |
|
|
|
static VLC svq1_intra_multistage[6]; |
|
|
|
@@ -65,6 +69,8 @@ typedef struct SVQ1Context { |
|
|
|
AVFrame picture; |
|
|
|
PutBitContext pb; |
|
|
|
GetBitContext gb; |
|
|
|
|
|
|
|
PutBitContext reorder_pb[6]; //why ooh why this sick breadth first order, everything is slower and more complex |
|
|
|
|
|
|
|
int frame_width; |
|
|
|
int frame_height; |
|
|
|
@@ -1303,6 +1309,125 @@ av_log(s->avctx, AV_LOG_INFO, "\n"); |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
static int encode_block(SVQ1Context *s, uint8_t *src, int stride, int level, int threshold, int lambda){ |
|
|
|
int count, y, x, i, j, split, best_mean, best_score, best_count; |
|
|
|
int best_vector[6]; |
|
|
|
int block_sum[7]= {0, 0, 0, 0, 0, 0}; |
|
|
|
int w= 2<<((level+2)>>1); |
|
|
|
int h= 2<<((level+1)>>1); |
|
|
|
int size=w*h; |
|
|
|
int16_t block[7][256]; |
|
|
|
|
|
|
|
best_score=0; |
|
|
|
for(y=0; y<h; y++){ |
|
|
|
for(x=0; x<w; x++){ |
|
|
|
int v= src[x + y*stride]; |
|
|
|
block[0][x + w*y]= v; |
|
|
|
best_score += v*v; |
|
|
|
block_sum[0] += v; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
best_count=0; |
|
|
|
best_score -= ((block_sum[0]*block_sum[0])>>(level+3)); |
|
|
|
best_mean= (block_sum[0] + (size>>1)) >> (level+3); |
|
|
|
|
|
|
|
if(level<4){ |
|
|
|
for(count=1; count<7; count++){ |
|
|
|
int best_vector_score= INT_MAX; |
|
|
|
int best_vector_sum=-99, best_vector_mean=-99; |
|
|
|
const int stage= count-1; |
|
|
|
int8_t *vector; |
|
|
|
|
|
|
|
for(i=0; i<16; i++){ |
|
|
|
int sum=0; |
|
|
|
int sqr=0; |
|
|
|
int diff, mean, score; |
|
|
|
|
|
|
|
vector = svq1_intra_codebooks[level] + stage*size*16 + i*size; |
|
|
|
|
|
|
|
for(j=0; j<size; j++){ |
|
|
|
int v= vector[j]; |
|
|
|
sum += v; |
|
|
|
sqr += (v - block[stage][j])*(v - block[stage][j]); |
|
|
|
} |
|
|
|
diff= block_sum[stage] - sum; |
|
|
|
mean= (diff + (size>>1)) >> (level+3); |
|
|
|
assert(mean >-50 && mean<300); |
|
|
|
mean= clip(mean, 0, 255); |
|
|
|
score= sqr - ((diff*(int64_t)diff)>>(level+3)); //FIXME 64bit slooow |
|
|
|
if(score < best_vector_score){ |
|
|
|
best_vector_score= score; |
|
|
|
best_vector[stage]= i; |
|
|
|
best_vector_sum= sum; |
|
|
|
best_vector_mean= mean; |
|
|
|
} |
|
|
|
} |
|
|
|
assert(best_vector_mean != -99); |
|
|
|
vector= svq1_intra_codebooks[level] + stage*size*16 + best_vector[stage]*size; |
|
|
|
for(j=0; j<size; j++){ |
|
|
|
block[stage+1][j] = block[stage][j] - vector[j]; |
|
|
|
} |
|
|
|
block_sum[stage+1]= block_sum[stage] - best_vector_sum; |
|
|
|
best_vector_score += |
|
|
|
lambda*(+ 1 + 4*count |
|
|
|
+ svq1_intra_multistage_vlc[level][1+count][1] |
|
|
|
+ svq1_intra_mean_vlc[best_vector_mean][1]); |
|
|
|
|
|
|
|
if(best_vector_score < best_score){ |
|
|
|
best_score= best_vector_score; |
|
|
|
best_count= count; |
|
|
|
best_mean= best_vector_mean; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
split=0; |
|
|
|
if(best_score > threshold && level){ |
|
|
|
int score=0; |
|
|
|
int offset= (level&1) ? stride*h/2 : w/2; |
|
|
|
PutBitContext backup[6]; |
|
|
|
|
|
|
|
for(i=level-1; i>=0; i--){ |
|
|
|
backup[i]= s->reorder_pb[i]; |
|
|
|
} |
|
|
|
score += encode_block(s, src , stride, level-1, threshold>>1, lambda); |
|
|
|
score += encode_block(s, src + offset, stride, level-1, threshold>>1, lambda); |
|
|
|
score += lambda; |
|
|
|
|
|
|
|
if(score < best_score){ |
|
|
|
best_score= score; |
|
|
|
split=1; |
|
|
|
}else{ |
|
|
|
for(i=level-1; i>=0; i--){ |
|
|
|
s->reorder_pb[i]= backup[i]; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if (level > 0) |
|
|
|
put_bits(&s->reorder_pb[level], 1, split); |
|
|
|
|
|
|
|
if(!split){ |
|
|
|
assert(best_mean >= 0 && best_mean<256); |
|
|
|
assert(best_count >=0 && best_count<7); |
|
|
|
assert(level<4 || best_count==0); |
|
|
|
|
|
|
|
/* output the encoding */ |
|
|
|
put_bits(&s->reorder_pb[level], |
|
|
|
svq1_intra_multistage_vlc[level][1 + best_count][1], |
|
|
|
svq1_intra_multistage_vlc[level][1 + best_count][0]); |
|
|
|
put_bits(&s->reorder_pb[level], svq1_intra_mean_vlc[best_mean][1], |
|
|
|
svq1_intra_mean_vlc[best_mean][0]); |
|
|
|
|
|
|
|
for (i = 0; i < best_count; i++){ |
|
|
|
assert(best_vector[i]>=0 && best_vector[i]<16); |
|
|
|
put_bits(&s->reorder_pb[level], 4, best_vector[i]); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return best_score; |
|
|
|
} |
|
|
|
|
|
|
|
static void svq1_encode_plane(SVQ1Context *s, unsigned char *plane, |
|
|
|
int width, int height, int stride) |
|
|
|
{ |
|
|
|
@@ -1337,6 +1462,7 @@ av_log(s->avctx, AV_LOG_INFO, "********* frame #%d\n", frame++); |
|
|
|
for (y = 0; y < block_height; y++) { |
|
|
|
|
|
|
|
for (x = 0; x < block_width; x++) { |
|
|
|
uint8_t reorder_buffer[6][7*32]; |
|
|
|
|
|
|
|
#ifdef DEBUG_SVQ1 |
|
|
|
av_log(s->avctx, AV_LOG_INFO, "* level 5 vector @ %d, %d:\n", x * 16, y * 16); |
|
|
|
@@ -1344,6 +1470,19 @@ av_log(s->avctx, AV_LOG_INFO, "* level 5 vector @ %d, %d:\n", x * 16, y * 16); |
|
|
|
|
|
|
|
/* copy the block into the current work buffer */ |
|
|
|
left_edge = (y * 16 * stride) + (x * 16); |
|
|
|
|
|
|
|
for(i=0; i<6; i++){ |
|
|
|
init_put_bits(&s->reorder_pb[i], reorder_buffer[i], 7*32); |
|
|
|
} |
|
|
|
encode_block(s, &plane[left_edge], stride, 5, 256, (s->picture.quality*s->picture.quality) >> (2*FF_LAMBDA_SHIFT)); |
|
|
|
for(i=5; i>=0; i--){ |
|
|
|
int count= put_bits_count(&s->reorder_pb[i]); |
|
|
|
|
|
|
|
flush_put_bits(&s->reorder_pb[i]); |
|
|
|
ff_copy_bits(&s->pb, s->reorder_pb[i].buf, count); |
|
|
|
} |
|
|
|
|
|
|
|
#if 0 |
|
|
|
for (i = 0; i < 256; i += 16) { |
|
|
|
memcpy(&buffer0[i], &plane[left_edge], 16); |
|
|
|
left_edge += stride; |
|
|
|
@@ -1416,6 +1555,7 @@ av_log(s->avctx, AV_LOG_INFO, " split to level %d\n", level - 1); |
|
|
|
if (!subvector_count) |
|
|
|
break; |
|
|
|
} |
|
|
|
#endif |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|