Commit fa2ae822 authored by Michael Niedermayer's avatar Michael Niedermayer

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
parent 5e502c3f
......@@ -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];
......@@ -66,6 +70,8 @@ typedef struct SVQ1Context {
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
}
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment