mirror of https://git.ffmpeg.org/ffmpeg.git
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
This commit is contained in:
parent
5e502c3ff7
commit
fa2ae82206
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue