diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2004-05-07 20:30:52 +0000 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2004-05-07 20:30:52 +0000 |
commit | fa2ae822063a8e41ef3c0713a6872899153c1027 (patch) | |
tree | a9794f81b2d6ef21d95f4ea9938aed211a7596a0 /libavcodec | |
parent | 5e502c3ff73ca0621408bd021c1c46ae2ff3ae40 (diff) | |
download | ffmpeg-fa2ae822063a8e41ef3c0713a6872899153c1027.tar.gz |
rate distorted intra only encoding
still grayscale, still no real ratecontrol ...
use -qscale x to set the quality
not optimized yet ...
Originally committed as revision 3115 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec')
-rw-r--r-- | libavcodec/svq1.c | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/libavcodec/svq1.c b/libavcodec/svq1.c index 1a03d29340..48b25ec476 100644 --- a/libavcodec/svq1.c +++ b/libavcodec/svq1.c @@ -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 } } } |