aboutsummaryrefslogtreecommitdiffstats
path: root/libavcodec
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2004-05-07 20:30:52 +0000
committerMichael Niedermayer <michaelni@gmx.at>2004-05-07 20:30:52 +0000
commitfa2ae822063a8e41ef3c0713a6872899153c1027 (patch)
treea9794f81b2d6ef21d95f4ea9938aed211a7596a0 /libavcodec
parent5e502c3ff73ca0621408bd021c1c46ae2ff3ae40 (diff)
downloadffmpeg-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.c140
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
}
}
}