changeset 2007:5be94affdb14 libavcodec

rate distorted intra only encoding still grayscale, still no real ratecontrol ... use -qscale x to set the quality not optimized yet ...
author michael
date Fri, 07 May 2004 20:30:52 +0000
parents 7d6edcadb1a1
children fc54b7be8448
files svq1.c
diffstat 1 files changed, 140 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/svq1.c	Fri May 07 14:57:05 2004 +0000
+++ b/svq1.c	Fri May 07 20:30:52 2004 +0000
@@ -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 @@
     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 @@
 }
 #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 @@
     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 @@
 
             /* 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 @@
                 if (!subvector_count)
                     break;
             }
+#endif
         }
     }
 }