summaryrefslogtreecommitdiff
path: root/libavcodec/snow.c
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2004-08-02 01:03:52 +0000
committerMichael Niedermayer <michaelni@gmx.at>2004-08-02 01:03:52 +0000
commit4f4e963383d238c928281b6600e852ddface7f6e (patch)
treefe2372f7f6b961d6e89cfe24f732cceec259b849 /libavcodec/snow.c
parent24689bcee6aa8b81e0dfd25fad2ec456935dc266 (diff)
various subband encoders (all either worse or complicated so they are commented out)
different 0-context encoding, 1.2% lower bitrate (foreman@352x288 qscale=8) no significant change at qscale=1 Originally committed as revision 3366 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec/snow.c')
-rw-r--r--libavcodec/snow.c1036
1 files changed, 1028 insertions, 8 deletions
diff --git a/libavcodec/snow.c b/libavcodec/snow.c
index bf454b9103..c843997425 100644
--- a/libavcodec/snow.c
+++ b/libavcodec/snow.c
@@ -326,6 +326,12 @@ static const uint8_t obmc16[256]={
};
#endif
+typedef struct QTree{
+ int treedim[MAX_DECOMPOSITIONS][2];
+ uint8_t *tree[MAX_DECOMPOSITIONS];
+ int max_level;
+ int stride;
+}QTree;
typedef struct SubBand{
int level;
@@ -334,6 +340,7 @@ typedef struct SubBand{
int height;
int qlog; ///< log(qscale)/log[2^(1/6)]
DWTELEM *buf;
+ QTree tree;
struct SubBand *parent;
uint8_t state[/*7*2*/ 7 + 512][32];
}SubBand;
@@ -493,6 +500,44 @@ static inline int get_symbol(CABACContext *c, uint8_t *state, int is_signed){
}
}
+static inline void put_symbol2(CABACContext *c, uint8_t *state, int v, int log2){
+ int i;
+ int e= av_log2(v<<1);
+
+ assert(v>=0);
+ if(v==0) assert(e==0);
+
+ while(e > log2){
+ put_cabac(c, state+log2, 1);
+ v -= 1<<log2;
+ assert(v>=0);
+ e= av_log2(v<<1);
+ log2++;
+ }
+ put_cabac(c, state+log2, 0);
+
+ for(i=log2-1; i>=0; i--){
+ put_cabac(c, state+31-i, (v>>i)&1);
+ }
+ assert(!((v>>i)&1));
+}
+
+static inline int get_symbol2(CABACContext *c, uint8_t *state, int log2){
+ int i;
+ int v=0;
+
+ while(get_cabac(c, state+log2)){
+ v+= 1<<log2;
+ log2++;
+ }
+
+ for(i=log2-1; i>=0; i--){
+ v+= get_cabac(c, state+31-i)<<i;
+ }
+
+ return v;
+}
+
static always_inline void lift(DWTELEM *dst, DWTELEM *src, DWTELEM *ref, int dst_step, int src_step, int ref_step, int width, int mul, int add, int shift, int highpass, int inverse){
const int mirror_left= !highpass;
const int mirror_right= (width&1) ^ highpass;
@@ -1272,13 +1317,614 @@ static int sig_cmp(const void *a, const void *b){
else return da[0] - db[0];
}
+static int alloc_qtree(QTree *t, int w, int h){
+ int lev, x, y, tree_h;
+ int w2= w;
+ int h2= h;
+
+ t->stride=0;
+ t->max_level= av_log2(2*FFMAX(w,h)-1);
+
+ for(lev=t->max_level; lev>=0; lev--){
+ if(lev!=t->max_level)
+ t->stride += w2;
+ t->treedim[lev][0]= w2;
+ t->treedim[lev][1]= h2;
+av_log(NULL, AV_LOG_DEBUG, "alloc %p %d %d %d\n", t, w2, h2, t->max_level);
+ w2= (w2+1)>>1;
+ h2= (h2+1)>>1;
+ }
+ t->stride= FFMAX(t->stride, w);
+ tree_h= h + t->treedim[t->max_level-1][1];
+
+ t->tree[t->max_level]= av_mallocz(t->stride * tree_h);
+ t->tree[t->max_level-1]= t->tree[t->max_level] + h*t->stride;
+
+ for(lev=t->max_level-2; lev>=0; lev--){
+ t->tree[lev]= t->tree[lev+1] + t->treedim[lev+1][0];
+ }
+ return 0;
+}
+
+static void free_qtree(QTree *t){
+ if(t && t->tree);
+ av_freep(&t->tree[t->max_level]);
+}
+
+static void init_quandtree(QTree *t, DWTELEM *src, int w, int h, int stride){
+ const int max_level= t->max_level;
+ const int tree_stride= t->stride;
+ uint8_t **tree= t->tree;
+ int lev, x, y, tree_h, w2, h2;
+
+//av_log(NULL, AV_LOG_DEBUG, "init %p %d %d %d %d %d\n", t, w, h, t->max_level, t->treedim[max_level][0], t->treedim[max_level][1]);
+ assert(w==t->treedim[max_level][0]);
+ assert(h==t->treedim[max_level][1]);
+
+ for(y=0; y<h; y++){
+ for(x=0; x<w; x++){
+ tree[max_level][x + y*tree_stride]= clip(ABS(src[x + y*stride]), 0, 16);
+ }
+ }
+
+ for(lev=max_level-1; lev>=0; lev--){
+ w2= t->treedim[lev+1][0]>>1;
+ h2= t->treedim[lev+1][1]>>1;
+ for(y=0; y<h2; y++){
+ for(x=0; x<w2; x++){
+ tree[lev][x + y*tree_stride]=clip( (tree[lev+1][2*x + 2*y *tree_stride])
+ + (tree[lev+1][2*x + 1 + 2*y *tree_stride])
+ + (tree[lev+1][2*x + (2*y+1)*tree_stride])
+ + (tree[lev+1][2*x + 1 + (2*y+1)*tree_stride])+3, 0, 64)/4;
+ }
+ }
+ if(w2 != t->treedim[lev][0]){
+ for(y=0; y<h2; y++){
+ tree[lev][w2 + y*tree_stride]=clip( (tree[lev+1][2*w2 + 2*y *tree_stride])
+ +(tree[lev+1][2*w2 + (2*y+1)*tree_stride])+3, 0, 64)/4;
+ }
+ }
+ if(h2 != t->treedim[lev][1]){
+ for(x=0; x<w2; x++){
+ tree[lev][x + h2*tree_stride]=clip( (tree[lev+1][2*x + 2*h2*tree_stride])
+ +(tree[lev+1][2*x + 1 + 2*h2*tree_stride])+3, 0, 64)/4;
+ }
+ }
+ if(w2 != t->treedim[lev][0] && h2 != t->treedim[lev][1]){
+ tree[lev][w2 + h2*tree_stride]= tree[lev+1][2*w2 + 2*h2*tree_stride];
+ }
+ }
+}
+
+int white_leaf, gray_leaf;
+
+static void encode_branch(SnowContext *s, SubBand *b, DWTELEM *src, DWTELEM *parent, int stride, int lev, int x, int y, int first){
+ const int max_level= b->tree.max_level;
+ const int pmax_level= b->parent ? b->parent->tree.max_level : 0;
+ const int tree_stride= b->tree.stride;
+ const int ptree_stride= b->parent ? b->parent->tree.stride : 0;
+ int (*treedim)[2]= b->tree.treedim;
+ int (*ptreedim)[2]= b->parent ? b->parent->tree.treedim : NULL;
+ uint8_t **tree= b->tree.tree;
+ uint8_t **ptree= b->parent ? b->parent->tree.tree : NULL;
+// int w2=w, h2=h;
+
+ int l=0, t=0, lt=0, p=0;
+ int v= tree[lev][x + y*tree_stride];
+ int context, sig;
+ if(!first && !tree[lev-1][x/2 + y/2*tree_stride])
+ return;
-static void encode_subband(SnowContext *s, SubBand *b, DWTELEM *src, DWTELEM *parent, int stride, int orientation){
+ if(x) l= tree[lev][x - 1 + y*tree_stride];
+ if(y){
+ t= tree[lev][x + (y-1)*tree_stride];
+ if(x) lt= tree[lev][x - 1 + (y-1)*tree_stride];
+ }
+ if(lev < max_level && parent && x<ptreedim[lev][0] && y<ptreedim[lev][1])
+ p= ptree[lev - max_level + pmax_level + 1][x + y*ptree_stride];
+
+ if(lev != max_level)
+ context= lev + 32*av_log2(2*(3*(l) + 2*(t) + (lt) + 2*(p)));
+ else{
+ int p=0, l=0, lt=0, t=0, rt=0;
+
+ if(y){
+ t= src[x + (y-1)*stride];
+ if(x)
+ lt= src[x - 1 + (y-1)*stride];
+ }
+ if(x)
+ l= src[x - 1 + y*stride];
+
+
+ if(parent){
+ int px= x>>1;
+ int py= y>>1;
+ if(px<b->parent->width && py<b->parent->height){
+ p= parent[px + py*2*stride];
+ }
+ }
+ context= lev + 32*av_log2(2*(3*ABS(l) + 2*ABS(t) + ABS(lt) + ABS(p)));
+ }
+
+ if( (x&1) && l) sig=1;
+ else if((y&1) && t) sig=1;
+ else if((x&1) && (y&1) && lt) sig=1;
+ else sig=0;
+
+ if(!first){
+ if(sig) context+= 8+16;
+ else context+= 8*(x&1) + 16*(y&1);
+ }
+
+ if(l||t||lt||(x&1)==0||(y&1)==0||first){
+ put_cabac(&s->c, &b->state[98][context], !!v);
+ }else
+ assert(v);
+
+ if(v){
+ if(lev==max_level){
+ int p=0;
+ int /*ll=0, */l=0, lt=0, t=0;
+ int v= src[x + y*stride];
+
+ if(y){
+ t= src[x + (y-1)*stride];
+ if(x){
+ lt= src[x - 1 + (y-1)*stride];
+ }
+ }
+ if(x){
+ l= src[x - 1 + y*stride];
+ }
+
+ if(parent){
+ int px= x>>1;
+ int py= y>>1;
+ if(px<b->parent->width && py<b->parent->height){
+ p= parent[px + py*2*stride];
+ }
+ }
+ {
+ int context= av_log2(/*ABS(ll) + */3*ABS(l) + ABS(lt) + 2*ABS(t) + ABS(p)
+ /*+ 3*(!!r) + 2*(!!d)*/);
+
+ put_symbol(&s->c, b->state[context + 2], ABS(v)-1, 0);
+ put_cabac(&s->c, &b->state[0][16 + 1 + 3 + quant3b[l&0xFF] + 3*quant3b[t&0xFF]], v<0);
+ assert(tree[max_level][x + y*tree_stride]);
+ assert(tree[max_level-1][x/2 + y/2*tree_stride]);
+ }
+ gray_leaf++;
+ }else{
+ int r= 2*x+1 < treedim[lev+1][0];
+ int d= 2*y+1 < treedim[lev+1][1];
+ encode_branch (s, b, src, parent, stride, lev+1, 2*x , 2*y , 0);
+ if(r) encode_branch(s, b, src, parent, stride, lev+1, 2*x+1, 2*y , 0);
+ if(d) encode_branch(s, b, src, parent, stride, lev+1, 2*x , 2*y+1, 0);
+ if(r&&d)encode_branch(s, b, src, parent, stride, lev+1, 2*x+1, 2*y+1, 0);
+ }
+ }
+}
+
+static void encode_subband_qtree(SnowContext *s, SubBand *b, DWTELEM *src, DWTELEM *parent, int stride, int orientation){
const int level= b->level;
const int w= b->width;
const int h= b->height;
- int x, y;
+ int x, y, i;
+
+ init_quandtree(&b->tree, src, b->width, b->height, stride);
+
+ if(parent){
+ init_quandtree(&b->parent->tree, parent, b->parent->width, b->parent->height, 2*stride);
+ }
+
+ for(i=0; i<b->tree.max_level; i++){
+ int count=0;
+ for(y=0; y<b->tree.treedim[i][1]; y++){
+ for(x=0; x<b->tree.treedim[i][0]; x++){
+ if(b->tree.tree[i][x + y*b->tree.stride])
+ count++;
+ }
+ }
+ if(2*count < b->tree.treedim[i][1]*b->tree.treedim[i][0])
+ break;
+ }
+ //FIXME try recursive scan
+ for(y=0; y<b->tree.treedim[i][1]; y++){
+ for(x=0; x<b->tree.treedim[i][0]; x++){
+ encode_branch(s, b, src, parent, stride, i, x, y, 1);
+ }
+ }
+// encode_branch(s, b, src, parent, stride, 0, 0, 0, 1);
+// av_log(NULL, AV_LOG_DEBUG, "%d %d\n", gray_leaf, white_leaf);
+#if 0
+ for(lev=0; lev<=max_level; lev++){
+ w2= treedim[lev][0];
+ h2= treedim[lev][1];
+ for(y=0; y<h2; y++){
+ for(x=0; x<w2; x++){
+ int l= 0, t=0, rt=0, lt=0, p=0;
+ int v= tree[lev][x + y*tree_stride];
+ int context, sig;
+ if(lev && !tree[lev-1][x/2 + y/2*tree_stride])
+ continue;
+
+ if(x) l= tree[lev][x - 1 + y*tree_stride];
+ if(y){
+ t= tree[lev][x + (y-1)*tree_stride];
+ if(x) lt= tree[lev][x - 1 + (y-1)*tree_stride];
+ if(x+1<w2) rt= tree[lev][x + 1 + (y-1)*tree_stride];
+ }
+ if(lev < max_level && parent && x<ptreedim[lev][0] && y<ptreedim[lev][1])
+ p= ptree[lev][x + y*ptree_stride];
+
+ context= lev + 32*av_log2(2*(3*l + 2*t + lt + rt + 8*p));
+
+ if( (x&1) && l) sig=1;
+ else if((y&1) && t) sig=1;
+ else if((x&1) && (y&1) && lt) sig=1;
+ else sig=0;
+
+ if(sig) context+= 8+16;
+ else context+= 8*(x&1) + 16*(y&1);
+
+ if(l||t||lt||(x&1)==0||(y&1)==0)
+ put_cabac(&s->c, &b->state[98][context], !!v);
+ else
+ assert(v);
+ if(v && lev==max_level){
+ int p=0;
+ int /*ll=0, */l=0, lt=0, t=0, rt=0;
+ int v= src[x + y*stride];
+
+ if(y){
+ t= src[x + (y-1)*stride];
+ if(x){
+ lt= src[x - 1 + (y-1)*stride];
+ }
+ if(x + 1 < w){
+ rt= src[x + 1 + (y-1)*stride];
+ }
+ }
+ if(x){
+ l= src[x - 1 + y*stride];
+ /*if(x > 1){
+ if(orientation==1) ll= src[y + (x-2)*stride];
+ else ll= src[x - 2 + y*stride];
+ }*/
+ }
+
+ if(parent){
+ int px= x>>1;
+ int py= y>>1;
+ if(px<b->parent->width && py<b->parent->height){
+ p= parent[px + py*2*stride];
+ }
+ }
+ if(v){
+ int context= av_log2(/*ABS(ll) + */3*ABS(l) + ABS(lt) + 2*ABS(t) + ABS(p)
+ /*+ 3*(!!r) + 2*(!!d)*/);
+
+ put_symbol(&s->c, b->state[context + 2], ABS(v)-1, 0);
+ put_cabac(&s->c, &b->state[0][16 + 1 + 3 + quant3b[l&0xFF] + 3*quant3b[t&0xFF]], v<0);
+ assert(tree[max_level][x + y*tree_stride]);
+ assert(tree[max_level-1][x/2 + y/2*tree_stride]);
+ }else
+ assert(0);
+ }
+ }
+ }
+ }
+#endif
+}
+
+static int deint(unsigned int a){
+ a &= 0x55555555; //0 1 2 3 4 5 6 7 8 9 A B C D E F
+ a += a & 0x11111111; // 01 23 45 67 89 AB CD EF
+ a += 3*(a & 0x0F0F0F0F);// 0123 4567 89AB CDEF
+ a += 15*(a & 0x00FF00FF);// 01234567 89ABCDEF
+ a +=255*(a & 0x0000FFFF);// 0123456789ABCDEF
+ return a>>15;
+}
+
+static void encode_subband_z0run(SnowContext *s, SubBand *b, DWTELEM *src, DWTELEM *parent, int stride, int orientation){
+ const int level= b->level;
+ const int w= b->width;
+ const int h= b->height;
+ int x, y, pos;
+
+ if(1){
+ int run=0;
+ int runs[w*h];
+ int run_index=0;
+ int count=0;
+
+ for(pos=0; ; pos++){
+ int x= deint(pos );
+ int y= deint(pos>>1);
+ int v, p=0, pr=0, pd=0;
+ int /*ll=0, */l=0, lt=0, t=0/*, rt=0*/;
+
+ if(x>=w || y>=h){
+ if(x>=w && y>=h)
+ break;
+ continue;
+ }
+ count++;
+
+ v= src[x + y*stride];
+
+ if(y){
+ t= src[x + (y-1)*stride];
+ if(x){
+ lt= src[x - 1 + (y-1)*stride];
+ }
+ if(x + 1 < w){
+ /*rt= src[x + 1 + (y-1)*stride]*/;
+ }
+ }
+ if(x){
+ l= src[x - 1 + y*stride];
+ /*if(x > 1){
+ if(orientation==1) ll= src[y + (x-2)*stride];
+ else ll= src[x - 2 + y*stride];
+ }*/
+ }
+ if(parent){
+ int px= x>>1;
+ int py= y>>1;
+ if(px<b->parent->width && py<b->parent->height){
+ p= parent[px + py*2*stride];
+ /*if(px+1<b->parent->width)
+ pr= parent[px + 1 + py*2*stride];
+ if(py+1<b->parent->height)
+ pd= parent[px + (py+1)*2*stride];*/
+ }
+ }
+ if(!(/*ll|*/l|lt|t|/*rt|*/p)){
+ if(v){
+ runs[run_index++]= run;
+ run=0;
+ }else{
+ run++;
+ }
+ }
+ }
+ assert(count==w*h);
+ runs[run_index++]= run;
+ run_index=0;
+ run= runs[run_index++];
+
+ put_symbol(&s->c, b->state[1], run, 0);
+
+ for(pos=0; ; pos++){
+ int x= deint(pos );
+ int y= deint(pos>>1);
+ int v, p=0, pr=0, pd=0;
+ int /*ll=0, */l=0, lt=0, t=0/*, rt=0*/;
+
+ if(x>=w || y>=h){
+ if(x>=w && y>=h)
+ break;
+ continue;
+ }
+ v= src[x + y*stride];
+
+ if(y){
+ t= src[x + (y-1)*stride];
+ if(x){
+ lt= src[x - 1 + (y-1)*stride];
+ }
+ if(x + 1 < w){
+// rt= src[x + 1 + (y-1)*stride];
+ }
+ }
+ if(x){
+ l= src[x - 1 + y*stride];
+ /*if(x > 1){
+ if(orientation==1) ll= src[y + (x-2)*stride];
+ else ll= src[x - 2 + y*stride];
+ }*/
+ }
+
+ if(parent){
+ int px= x>>1;
+ int py= y>>1;
+ if(px<b->parent->width && py<b->parent->height){
+ p= parent[px + py*2*stride];
+/* if(px+1<b->parent->width)
+ pr= parent[px + 1 + py*2*stride];
+ if(py+1<b->parent->height)
+ pd= parent[px + (py+1)*2*stride];*/
+ }
+ }
+ if(/*ll|*/l|lt|t|/*rt|*/p){
+ int context= av_log2(/*ABS(ll) + */2*(3*ABS(l) + ABS(lt) + 2*ABS(t) + /*ABS(rt) +*/ ABS(p)));
+
+ put_cabac(&s->c, &b->state[0][context], !!v);
+ }else{
+ if(!run){
+ run= runs[run_index++];
+ put_symbol(&s->c, b->state[1], run, 0);
+ assert(v);
+ }else{
+ run--;
+ assert(!v);
+ }
+ }
+ if(v){
+ int context= av_log2(/*ABS(ll) + */3*ABS(l) + ABS(lt) + 2*ABS(t) + /*ABS(rt) +*/ ABS(p));
+
+ put_symbol(&s->c, b->state[context + 2], ABS(v)-1, 0);
+ put_cabac(&s->c, &b->state[0][16 + 1 + 3 + quant3b[l&0xFF] + 3*quant3b[t&0xFF]], v<0);
+ }
+ }
+ }
+}
+
+static void encode_subband_bp(SnowContext *s, SubBand *b, DWTELEM *src, DWTELEM *parent, int stride, int orientation){
+ const int level= b->level;
+ const int w= b->width;
+ const int h= b->height;
+ int x, y;
+
+#if 0
+ int plane;
+ for(plane=24; plane>=0; plane--){
+ int run=0;
+ int runs[w*h];
+ int run_index=0;
+
+ for(y=0; y<h; y++){
+ for(x=0; x<w; x++){
+ int v, lv, p=0;
+ int d=0, r=0, rd=0, ld=0;
+ int /*ll=0, */l=0, lt=0, t=0, rt=0;
+ v= src[x + y*stride];
+
+ if(y){
+ t= src[x + (y-1)*stride];
+ if(x){
+ lt= src[x - 1 + (y-1)*stride];
+ }
+ if(x + 1 < w){
+ rt= src[x + 1 + (y-1)*stride];
+ }
+ }
+ if(x){
+ l= src[x - 1 + y*stride];
+ /*if(x > 1){
+ if(orientation==1) ll= src[y + (x-2)*stride];
+ else ll= src[x - 2 + y*stride];
+ }*/
+ }
+ if(y+1<h){
+ d= src[x + (y+1)*stride];
+ if(x) ld= src[x - 1 + (y+1)*stride];
+ if(x + 1 < w) rd= src[x + 1 + (y+1)*stride];
+ }
+ if(x + 1 < w)
+ r= src[x + 1 + y*stride];
+ if(parent){
+ int px= x>>1;
+ int py= y>>1;
+ if(px<b->parent->width && py<b->parent->height)
+ p= parent[px + py*2*stride];
+ }
+#define HIDE(c, plane) c= c>=0 ? c&((-1)<<(plane)) : -((-c)&((-1)<<(plane)));
+ lv=v;
+ HIDE( v, plane)
+ HIDE(lv, plane+1)
+ HIDE( p, plane)
+ HIDE( l, plane)
+ HIDE(lt, plane)
+ HIDE( t, plane)
+ HIDE(rt, plane)
+ HIDE( r, plane+1)
+ HIDE(rd, plane+1)
+ HIDE( d, plane+1)
+ HIDE(ld, plane+1)
+ if(!(/*ll|*/l|lt|t|rt|r|rd|ld|d|p|lv)){
+ if(v){
+ runs[run_index++]= run;
+ run=0;
+ }else{
+ run++;
+ }
+ }
+ }
+ }
+ runs[run_index++]= run;
+ run_index=0;
+ run= runs[run_index++];
+
+ put_symbol(&s->c, b->state[1], run, 0);
+
+ for(y=0; y<h; y++){
+ for(x=0; x<w; x++){
+ int v, p=0, lv;
+ int /*ll=0, */l=0, lt=0, t=0, rt=0;
+ int d=0, r=0, rd=0, ld=0;
+ v= src[x + y*stride];
+
+ if(y){
+ t= src[x + (y-1)*stride];
+ if(x){
+ lt= src[x - 1 + (y-1)*stride];
+ }
+ if(x + 1 < w){
+ rt= src[x + 1 + (y-1)*stride];
+ }
+ }
+ if(x){
+ l= src[x - 1 + y*stride];
+ /*if(x > 1){
+ if(orientation==1) ll= src[y + (x-2)*stride];
+ else ll= src[x - 2 + y*stride];
+ }*/
+ }
+ if(y+1<h){
+ d= src[x + (y+1)*stride];
+ if(x) ld= src[x - 1 + (y+1)*stride];
+ if(x + 1 < w) rd= src[x + 1 + (y+1)*stride];
+ }
+ if(x + 1 < w)
+ r= src[x + 1 + y*stride];
+
+ if(parent){
+ int px= x>>1;
+ int py= y>>1;
+ if(px<b->parent->width && py<b->parent->height)
+ p= parent[px + py*2*stride];
+ }
+ lv=v;
+ HIDE( v, plane)
+ HIDE(lv, plane+1)
+ HIDE( p, plane)
+ HIDE( l, plane)
+ HIDE(lt, plane)
+ HIDE( t, plane)
+ HIDE(rt, plane)
+ HIDE( r, plane+1)
+ HIDE(rd, plane+1)
+ HIDE( d, plane+1)
+ HIDE(ld, plane+1)
+ if(/*ll|*/l|lt|t|rt|r|rd|ld|d|p|lv){
+ int context= av_log2(/*ABS(ll) + */3*ABS(l) + ABS(lt) + 2*ABS(t) + ABS(rt) + ABS(p)
+ +3*ABS(r) + ABS(rd) + 2*ABS(d) + ABS(ld));
+
+ if(lv) put_cabac(&s->c, &b->state[99][context + 8*(av_log2(ABS(lv))-plane)], !!(v-lv));
+ else put_cabac(&s->c, &b->state[ 0][context], !!v);
+ }else{
+ assert(!lv);
+ if(!run){
+ run= runs[run_index++];
+ put_symbol(&s->c, b->state[1], run, 0);
+ assert(v);
+ }else{
+ run--;
+ assert(!v);
+ }
+ }
+ if(v && !lv){
+ int context= clip(quant3b[l&0xFF] + quant3b[r&0xFF], -1,1)
+ + 3*clip(quant3b[t&0xFF] + quant3b[d&0xFF], -1,1);
+ put_cabac(&s->c, &b->state[0][16 + 1 + 3 + context], v<0);
+ }
+ }
+ }
+ }
+ return;
+#endif
+}
+
+static void encode_subband_X(SnowContext *s, SubBand *b, DWTELEM *src, DWTELEM *parent, int stride, int orientation){
+ const int level= b->level;
+ const int w= b->width;
+ const int h= b->height;
+ int x, y;
+
#if 0
if(orientation==3 && parent && 0){
int16_t candidate[w*h][2];
@@ -1400,6 +2046,14 @@ static void encode_subband(SnowContext *s, SubBand *b, DWTELEM *src, DWTELEM *pa
}
}
#endif
+}
+
+static void encode_subband_c0run(SnowContext *s, SubBand *b, DWTELEM *src, DWTELEM *parent, int stride, int orientation){
+ const int level= b->level;
+ const int w= b->width;
+ const int h= b->height;
+ int x, y;
+
if(1){
int run=0;
int runs[w*h];
@@ -1447,7 +2101,7 @@ static void encode_subband(SnowContext *s, SubBand *b, DWTELEM *src, DWTELEM *pa
run_index=0;
run= runs[run_index++];
- put_symbol(&s->c, b->state[1], run, 0);
+ put_symbol2(&s->c, b->state[1], run, 3);
for(y=0; y<h; y++){
for(x=0; x<w; x++){
@@ -1484,7 +2138,8 @@ static void encode_subband(SnowContext *s, SubBand *b, DWTELEM *src, DWTELEM *pa
}else{
if(!run){
run= runs[run_index++];
- put_symbol(&s->c, b->state[1], run, 0);
+
+ put_symbol2(&s->c, b->state[1], run, 3);
assert(v);
}else{
run--;
@@ -1499,10 +2154,191 @@ static void encode_subband(SnowContext *s, SubBand *b, DWTELEM *src, DWTELEM *pa
}
}
}
- return;
}
}
+static void encode_subband_dzr(SnowContext *s, SubBand *b, DWTELEM *src, DWTELEM *parent, int stride, int orientation){
+ const int level= b->level;
+ const int w= b->width;
+ const int h= b->height;
+ int x, y;
+
+ if(1){
+ int run[16]={0};
+ int runs[16][w*h]; //FIXME do something about the size
+ int run_index[16]={0};
+ int positions[2][w];
+ int distances[2][w];
+ int dist_count=0;
+ int i;
+
+ for(y=0; y<h; y++){
+ int * pos = positions[ y&1];
+ int *last_pos = positions[(y&1)^1];
+ int * dist= distances[ y&1];
+ int *last_dist= distances[(y&1)^1];
+ int dist_index=0;
+ int last_dist_index=0;
+
+ for(x=0; x<w; x++){
+ int p=0, l=0, lt=0, t=0, rt=0;
+ int v= src[x + y*stride];
+
+ if(y){
+ t= src[x + (y-1)*stride];
+ if(x){
+ lt= src[x - 1 + (y-1)*stride];
+ }
+ if(x + 1 < w){
+ rt= src[x + 1 + (y-1)*stride];
+ }
+ }
+ if(x){
+ l= src[x - 1 + y*stride];
+ }
+ if(parent){
+ int px= x>>1;
+ int py= y>>1;
+ if(px<b->parent->width && py<b->parent->height)
+ p= parent[px + py*2*stride];
+ }
+ if(last_dist_index < dist_count && last_pos[last_dist_index] == x){
+ if(dist_index==0 || x - pos[dist_index-1] > dist[dist_index-1] - last_dist[last_dist_index]){
+ pos[dist_index]= x;
+ dist[dist_index++]= last_dist[last_dist_index];
+ }
+ last_dist_index++;
+ }
+
+ if(!(l|lt|t|rt|p)){
+ int cur_dist=w>>1;
+ int run_class;
+
+ if(last_dist_index < dist_count)
+ cur_dist= last_pos[last_dist_index] - x + y - last_dist[last_dist_index];
+ if(dist_index)
+ cur_dist= FFMIN(cur_dist, x - pos[dist_index-1] + y - dist[dist_index-1]);
+ assert(cur_dist>=2);
+ run_class= av_log2(cur_dist+62);
+
+ if(v){
+ runs[run_class][run_index[run_class]++]= run[run_class];
+ run[run_class]=0;
+ }else{
+ run[run_class]++;
+ }
+ }
+ if(v){
+ while(dist_index && x - pos[dist_index-1] <= y - dist[dist_index-1])
+ dist_index--;
+ pos[dist_index]= x;
+ dist[dist_index++]= y;
+ }
+ }
+ dist_count= dist_index;
+ }
+ for(i=0; i<12; i++){
+ runs[i][run_index[i]++]= run[i];
+ run_index[i]=0;
+ run[i]=0;
+ }
+
+ dist_count=0;
+
+ for(y=0; y<h; y++){
+ int * pos = positions[ y&1];
+ int *last_pos = positions[(y&1)^1];
+ int * dist= distances[ y&1];
+ int *last_dist= distances[(y&1)^1];
+ int dist_index=0;
+ int last_dist_index=0;
+
+ for(x=0; x<w; x++){
+ int p=0, l=0, lt=0, t=0, rt=0;
+ int v= src[x + y*stride];
+
+ if(y){
+ t= src[x + (y-1)*stride];
+ if(x){
+ lt= src[x - 1 + (y-1)*stride];
+ }
+ if(x + 1 < w){
+ rt= src[x + 1 + (y-1)*stride];
+ }
+ }
+ if(x){
+ l= src[x - 1 + y*stride];
+ }
+ if(parent){
+ int px= x>>1;
+ int py= y>>1;
+ if(px<b->parent->width && py<b->parent->height)
+ p= parent[px + py*2*stride];
+ }
+ if(last_dist_index < dist_count && last_pos[last_dist_index] == x){
+ if(dist_index==0 || x - pos[dist_index-1] > dist[dist_index-1] - last_dist[last_dist_index]){
+ pos[dist_index]= x;
+ dist[dist_index++]= last_dist[last_dist_index];
+ }
+ last_dist_index++;
+ }
+ if(l|lt|t|rt|p){
+ int context= av_log2(/*ABS(ll) + */3*ABS(l) + ABS(lt) + 2*ABS(t) + ABS(rt) + ABS(p));
+
+ put_cabac(&s->c, &b->state[0][context], !!v);
+ }else{
+ int cur_dist=w>>1;
+ int run_class;
+
+ if(last_dist_index < dist_count)
+ cur_dist= last_pos[last_dist_index] - x + y - last_dist[last_dist_index];
+ if(dist_index)
+ cur_dist= FFMIN(cur_dist, x - pos[dist_index-1] + y - dist[dist_index-1]);
+ assert(cur_dist>=2);
+ assert(!dist_index || (pos[dist_index-1] >= 0 && pos[dist_index-1] <w));
+ assert(last_dist_index >= dist_count || (last_pos[last_dist_index] >= 0 && last_pos[last_dist_index] <w));
+ assert(!dist_index || dist[dist_index-1] <= y);
+ assert(last_dist_index >= dist_count || last_dist[last_dist_index] < y);
+ assert(cur_dist <= y + FFMAX(x, w-x-1));
+ run_class= av_log2(cur_dist+62);
+
+ if(!run_index[run_class]){
+ run[run_class]= runs[run_class][run_index[run_class]++];
+ put_symbol(&s->c, b->state[run_class+1], run[run_class], 0);
+ }
+ if(!run[run_class]){
+ run[run_class]= runs[run_class][run_index[run_class]++];
+ put_symbol(&s->c, b->state[run_class+1], run[run_class], 0);
+ assert(v);
+ }else{
+ run[run_class]--;
+ assert(!v);
+ }
+ }
+ if(v){
+ int context= av_log2(/*ABS(ll) + */3*ABS(l) + ABS(lt) + 2*ABS(t) + ABS(rt) + ABS(p));
+
+ put_symbol(&s->c, b->state[context + 16], ABS(v)-1, 0);
+ put_cabac(&s->c, &b->state[0][16 + 1 + 3 + quant3b[l&0xFF] + 3*quant3b[t&0xFF]], v<0);
+
+ while(dist_index && x - pos[dist_index-1] <= y - dist[dist_index-1])
+ dist_index--;
+ pos[dist_index]= x;
+ dist[dist_index++]= y;
+ }
+ }
+ dist_count= dist_index;
+ }
+ }
+}
+
+static void encode_subband(SnowContext *s, SubBand *b, DWTELEM *src, DWTELEM *parent, int stride, int orientation){
+// encode_subband_qtree(s, b, src, parent, stride, orientation);
+// encode_subband_z0run(s, b, src, parent, stride, orientation);
+ encode_subband_c0run(s, b, src, parent, stride, orientation);
+// encode_subband_dzr(s, b, src, parent, stride, orientation);
+}
+
static inline void decode_subband(SnowContext *s, SubBand *b, DWTELEM *src, DWTELEM *parent, int stride, int orientation){
const int level= b->level;
const int w= b->width;
@@ -1510,14 +2346,181 @@ static inline void decode_subband(SnowContext *s, SubBand *b, DWTELEM *src, DWTE
int x,y;
START_TIMER
-
+#if 0
+ for(y=0; y<b->height; y++)
+ memset(&src[y*stride], 0, b->width*sizeof(DWTELEM));
+
+ int plane;
+ for(plane=24; plane>=0; plane--){
+ int run;
+
+ run= get_symbol(&s->c, b->state[1], 0);
+
+#define HIDE(c, plane) c= c>=0 ? c&((-1)<<(plane)) : -((-c)&((-1)<<(plane)));
+
+ for(y=0; y<h; y++){
+ for(x=0; x<w; x++){
+ int v, p=0, lv;
+ int /*ll=0, */l=0, lt=0, t=0, rt=0;
+ int d=0, r=0, rd=0, ld=0;
+ lv= src[x + y*stride];
+
+ if(y){
+ t= src[x + (y-1)*stride];
+ if(x){
+ lt= src[x - 1 + (y-1)*stride];
+ }
+ if(x + 1 < w){
+ rt= src[x + 1 + (y-1)*stride];
+ }
+ }
+ if(x){
+ l= src[x - 1 + y*stride];
+ /*if(x > 1){
+ if(orientation==1) ll= src[y + (x-2)*stride];
+ else ll= src[x - 2 + y*stride];
+ }*/
+ }
+ if(y+1<h){
+ d= src[x + (y+1)*stride];
+ if(x) ld= src[x - 1 + (y+1)*stride];
+ if(x + 1 < w) rd= src[x + 1 + (y+1)*stride];
+ }
+ if(x + 1 < w)
+ r= src[x + 1 + y*stride];
+
+ if(parent){
+ int px= x>>1;
+ int py= y>>1;
+ if(px<b->parent->width && py<b->parent->height)
+ p= parent[px + py*2*stride];
+ }
+ HIDE( p, plane)
+ if(/*ll|*/l|lt|t|rt|r|rd|ld|d|p|lv){
+ int context= av_log2(/*ABS(ll) + */3*ABS(l) + ABS(lt) + 2*ABS(t) + ABS(rt) + ABS(p)
+ +3*ABS(r) + ABS(rd) + 2*ABS(d) + ABS(ld));
+
+ if(lv){
+ assert(context + 8*av_log2(ABS(lv)) < 512 - 100);
+ if(get_cabac(&s->c, &b->state[99][context + 8*(av_log2(ABS(lv))-plane)])){
+ if(lv<0) v= lv - (1<<plane);
+ else v= lv + (1<<plane);
+ }else
+ v=lv;
+ }else{
+ v= get_cabac(&s->c, &b->state[ 0][context]) << plane;
+ }
+ }else{
+ assert(!lv);
+ if(!run){
+ run= get_symbol(&s->c, b->state[1], 0);
+ v= 1<<plane;
+ }else{
+ run--;
+ v=0;
+ }
+ }
+ if(v && !lv){
+ int context= clip(quant3b[l&0xFF] + quant3b[r&0xFF], -1,1)
+ + 3*clip(quant3b[t&0xFF] + quant3b[d&0xFF], -1,1);
+ if(get_cabac(&s->c, &b->state[0][16 + 1 + 3 + context]))
+ v= -v;
+ }
+ src[x + y*stride]= v;
+ }
+ }
+ }
+ return;
+#endif
+#if 0
+ int tree[10][w*h]; //FIXME space waste ...
+ int treedim[10][2];
+ int lev;
+ const int max_level= av_log2(2*FFMAX(w,h)-1);
+ int w2=w, h2=h;
+ memset(tree, 0, sizeof(tree));
+
+// assert(w%2==0 && h%2==0);
+
+ for(lev=max_level; lev>=0; lev--){
+ treedim[lev][0]= w2;
+ treedim[lev][1]= h2;
+ w2= (w2+1)>>1;
+ h2= (h2+1)>>1;
+ }
+
+ for(lev=0; lev<=max_level; lev++){
+ w2= treedim[lev][0];
+ h2= treedim[lev][1];
+ for(y=0; y<h2; y++){
+ for(x=0; x<w2; x++){
+ int l= 0, t=0;
+ int context;
+ if(lev && !tree[lev-1][x/2 + y/2*w])
+ continue;
+
+ if(x) l= tree[lev][x - 1 + y*w];
+ if(y) t= tree[lev][x + (y-1)*w];
+
+ context= lev + 8*(!!l) + 16*(!!t);
+ tree[lev][x + y*w]= get_cabac(&s->c, &b->state[98][context]);
+ }
+ }
+ }
+ if(1){
+ for(y=0; y<b->height; y++)
+ memset(&src[y*stride], 0, b->width*sizeof(DWTELEM));
+
+ for(y=0; y<h; y++){
+ for(x=0; x<w; x++){
+ int v, p=0;
+ int /*ll=0, */l=0, lt=0, t=0, rt=0;
+
+ if(y){
+ t= src[x + (y-1)*stride];
+ if(x){
+ lt= src[x - 1 + (y-1)*stride];
+ }
+ if(x + 1 < w){
+ rt= src[x + 1 + (y-1)*stride];
+ }
+ }
+ if(x){
+ l= src[x - 1 + y*stride];
+ /*if(x > 1){
+ if(orientation==1) ll= src[y + (x-2)*stride];
+ else ll= src[x - 2 + y*stride];
+ }*/
+ }
+ if(parent){
+ int px= x>>1;
+ int py= y>>1;
+ if(px<b->parent->width && py<b->parent->height)
+ p= parent[px + py*2*stride];
+ }
+ if(tree[max_level][x + y*w]){
+ int context= av_log2(/*ABS(ll) + */3*ABS(l) + ABS(lt) + 2*ABS(t) + ABS(rt) + ABS(p));
+ v= get_symbol(&s->c, b->state[context + 2], 0) + 1;
+ if(get_cabac(&s->c, &b->state[0][16 + 1 + 3 + quant3b[l&0xFF] + 3*quant3b[t&0xFF]]))
+ v= -v;
+ src[x + y*stride]= v;
+ }
+ }
+ }
+ if(level+1 == s->spatial_decomposition_count){
+ STOP_TIMER("decode_subband")
+ }
+
+ return;
+ }
+#endif
if(1){
int run;
for(y=0; y<b->height; y++)
memset(&src[y*stride], 0, b->width*sizeof(DWTELEM));
- run= get_symbol(&s->c, b->state[1], 0);
+ run= get_symbol2(&s->c, b->state[1], 3);
for(y=0; y<h; y++){
for(x=0; x<w; x++){
int v, p=0;
@@ -1551,7 +2554,7 @@ static inline void decode_subband(SnowContext *s, SubBand *b, DWTELEM *src, DWTE
v=get_cabac(&s->c, &b->state[0][context]);
}else{
if(!run){
- run= get_symbol(&s->c, b->state[1], 0);
+ run= get_symbol2(&s->c, b->state[1], 3);
//FIXME optimize this here
//FIXME try to store a more naive run
v=1;
@@ -2089,6 +3092,8 @@ av_log(NULL, AV_LOG_DEBUG, "%d %d\n", w, h);
if(orientation&1) b->buf += (w+1)>>1;
if(orientation>1) b->buf += b->stride>>1;
+// alloc_qtree(&b->tree, b->width, b->height);
+
if(level)
b->parent= &s->plane[plane_index].band[level-1][orientation];
}
@@ -2104,6 +3109,9 @@ av_log(NULL, AV_LOG_DEBUG, "%d %d\n", w, h);
s->mb_band .buf= av_mallocz(s->mb_band .stride * s->mb_band .height*sizeof(DWTELEM));
s->mv_band[0].buf= av_mallocz(s->mv_band[0].stride * s->mv_band[0].height*sizeof(DWTELEM));
s->mv_band[1].buf= av_mallocz(s->mv_band[1].stride * s->mv_band[1].height*sizeof(DWTELEM));
+/* alloc_qtree(&s->mb_band .tree, s->mb_band .width, s->mb_band .height); //FIXME free these 3
+ alloc_qtree(&s->mv_band[0].tree, s->mv_band[0].width, s->mv_band[0].height);
+ alloc_qtree(&s->mv_band[1].tree, s->mv_band[0].width, s->mv_band[1].height);*/
reset_contexts(s);
/*
@@ -2534,6 +3542,8 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size,
}
static void common_end(SnowContext *s){
+ int plane_index, level, orientation;
+
av_freep(&s->spatial_dwt_buffer);
av_freep(&s->mb_band.buf);
av_freep(&s->mv_band[0].buf);
@@ -2547,6 +3557,16 @@ static void common_end(SnowContext *s){
av_freep(&s->dummy);
av_freep(&s->motion_val8);
av_freep(&s->motion_val16);
+/*
+ for(plane_index=0; plane_index<3; plane_index++){
+ for(level=s->spatial_decomposition_count-1; level>=0; level--){
+ for(orientation=level ? 1 : 0; orientation<4; orientation++){
+ SubBand *b= &s->plane[plane_index].band[level][orientation];
+
+ free_qtree(&b->tree);
+ }
+ }
+ }*/
}
static int encode_end(AVCodecContext *avctx)