-static void ff_spatial_idwt_buffered_slice(DSPContext *dsp, DWTCompose *cs, slice_buffer * slice_buf, int width, int height, int stride_line, int type, int decomposition_count, int y){
- const int support = type==1 ? 3 : 5;
- int level;
- if(type==2) return;
-
- for(level=decomposition_count-1; level>=0; level--){
- while(cs[level].y <= FFMIN((y>>level)+support, height>>level)){
- switch(type){
- case DWT_97: spatial_compose97i_dy_buffered(dsp, cs+level, slice_buf, width>>level, height>>level, stride_line<<level);
- break;
- case DWT_53: spatial_compose53i_dy_buffered(cs+level, slice_buf, width>>level, height>>level, stride_line<<level);
- break;
- }
- }
- }
-}
-
-static void ff_spatial_idwt(IDWTELEM *buffer, int width, int height, int stride, int type, int decomposition_count){
- DWTCompose cs[MAX_DECOMPOSITIONS];
- int y;
- ff_spatial_idwt_init(cs, buffer, width, height, stride, type, decomposition_count);
- for(y=0; y<height; y+=4)
- ff_spatial_idwt_slice(cs, buffer, width, height, stride, type, decomposition_count, y);
-}
-
-static int encode_subband_c0run(SnowContext *s, SubBand *b, IDWTELEM *src, IDWTELEM *parent, int stride, int orientation){
- const int w= b->width;
- const int h= b->height;
- int x, y;
-
- if(1){
- int run=0;
- int runs[w*h];
- int run_index=0;
- int max_index;
-
- 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;
- 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(!(/*ll|*/l|lt|t|rt|p)){
- if(v){
- runs[run_index++]= run;
- run=0;
- }else{
- run++;
- }
- }
- }
- }
- max_index= run_index;
- runs[run_index++]= run;
- run_index=0;
- run= runs[run_index++];
-
- put_symbol2(&s->c, b->state[30], max_index, 0);
- if(run_index <= max_index)
- put_symbol2(&s->c, b->state[1], run, 3);
-
- for(y=0; y<h; y++){
- if(s->c.bytestream_end - s->c.bytestream < w*40){
- av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
- return -1;
- }
- for(x=0; x<w; x++){
- int v, p=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(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(/*ll|*/l|lt|t|rt|p){
- int context= av_log2(/*FFABS(ll) + */3*FFABS(l) + FFABS(lt) + 2*FFABS(t) + FFABS(rt) + FFABS(p));
-
- put_rac(&s->c, &b->state[0][context], !!v);
- }else{
- if(!run){
- run= runs[run_index++];
-
- if(run_index <= max_index)
- put_symbol2(&s->c, b->state[1], run, 3);
- assert(v);
- }else{
- run--;
- assert(!v);
- }
- }
- if(v){
- int context= av_log2(/*FFABS(ll) + */3*FFABS(l) + FFABS(lt) + 2*FFABS(t) + FFABS(rt) + FFABS(p));
- int l2= 2*FFABS(l) + (l<0);
- int t2= 2*FFABS(t) + (t<0);
-
- put_symbol2(&s->c, b->state[context + 2], FFABS(v)-1, context-4);
- put_rac(&s->c, &b->state[0][16 + 1 + 3 + quant3bA[l2&0xFF] + 3*quant3bA[t2&0xFF]], v<0);
- }
- }
- }
- }
- return 0;
-}
-
-static int encode_subband(SnowContext *s, SubBand *b, IDWTELEM *src, IDWTELEM *parent, int stride, int orientation){
-// encode_subband_qtree(s, b, src, parent, stride, orientation);
-// encode_subband_z0run(s, b, src, parent, stride, orientation);
- return encode_subband_c0run(s, b, src, parent, stride, orientation);
-// encode_subband_dzr(s, b, src, parent, stride, orientation);
-}
-
-static inline void unpack_coeffs(SnowContext *s, SubBand *b, SubBand * parent, int orientation){
- const int w= b->width;
- const int h= b->height;
- int x,y;
-
- if(1){
- int run, runs;
- x_and_coeff *xc= b->x_coeff;
- x_and_coeff *prev_xc= NULL;
- x_and_coeff *prev2_xc= xc;
- x_and_coeff *parent_xc= parent ? parent->x_coeff : NULL;
- x_and_coeff *prev_parent_xc= parent_xc;
-
- runs= get_symbol2(&s->c, b->state[30], 0);
- if(runs-- > 0) run= get_symbol2(&s->c, b->state[1], 3);
- else run= INT_MAX;
-
- for(y=0; y<h; y++){
- int v=0;
- int lt=0, t=0, rt=0;
-
- if(y && prev_xc->x == 0){
- rt= prev_xc->coeff;
- }
- for(x=0; x<w; x++){
- int p=0;
- const int l= v;
-
- lt= t; t= rt;
-
- if(y){
- if(prev_xc->x <= x)
- prev_xc++;
- if(prev_xc->x == x + 1)
- rt= prev_xc->coeff;
- else
- rt=0;
- }
- if(parent_xc){
- if(x>>1 > parent_xc->x){
- parent_xc++;
- }
- if(x>>1 == parent_xc->x){
- p= parent_xc->coeff;
- }
- }
- if(/*ll|*/l|lt|t|rt|p){
- int context= av_log2(/*FFABS(ll) + */3*(l>>1) + (lt>>1) + (t&~1) + (rt>>1) + (p>>1));
-
- v=get_rac(&s->c, &b->state[0][context]);
- if(v){
- v= 2*(get_symbol2(&s->c, b->state[context + 2], context-4) + 1);
- v+=get_rac(&s->c, &b->state[0][16 + 1 + 3 + quant3bA[l&0xFF] + 3*quant3bA[t&0xFF]]);
-
- xc->x=x;
- (xc++)->coeff= v;
- }
- }else{
- if(!run){
- if(runs-- > 0) run= get_symbol2(&s->c, b->state[1], 3);
- else run= INT_MAX;
- v= 2*(get_symbol2(&s->c, b->state[0 + 2], 0-4) + 1);
- v+=get_rac(&s->c, &b->state[0][16 + 1 + 3]);
-
- xc->x=x;
- (xc++)->coeff= v;
- }else{
- int max_run;
- run--;
- v=0;
-
- if(y) max_run= FFMIN(run, prev_xc->x - x - 2);
- else max_run= FFMIN(run, w-x-1);
- if(parent_xc)
- max_run= FFMIN(max_run, 2*parent_xc->x - x - 1);
- x+= max_run;
- run-= max_run;
- }
- }
- }
- (xc++)->x= w+1; //end marker
- prev_xc= prev2_xc;
- prev2_xc= xc;
-
- if(parent_xc){
- if(y&1){
- while(parent_xc->x != parent->width+1)
- parent_xc++;
- parent_xc++;
- prev_parent_xc= parent_xc;
- }else{
- parent_xc= prev_parent_xc;
- }
- }
- }
-
- (xc++)->x= w+1; //end marker
- }
-}
-
-static inline void decode_subband_slice_buffered(SnowContext *s, SubBand *b, slice_buffer * sb, int start_y, int h, int save_state[1]){
- const int w= b->width;
- int y;
- const int qlog= av_clip(s->qlog + b->qlog, 0, QROOT*16);
- int qmul= qexp[qlog&(QROOT-1)]<<(qlog>>QSHIFT);
- int qadd= (s->qbias*qmul)>>QBIAS_SHIFT;
- int new_index = 0;
-
- if(b->ibuf == s->spatial_idwt_buffer || s->qlog == LOSSLESS_QLOG){
- qadd= 0;
- qmul= 1<<QEXPSHIFT;
- }
-
- /* If we are on the second or later slice, restore our index. */
- if (start_y != 0)
- new_index = save_state[0];
-
-
- for(y=start_y; y<h; y++){
- int x = 0;
- int v;
- IDWTELEM * line = slice_buffer_get_line(sb, y * b->stride_line + b->buf_y_offset) + b->buf_x_offset;
- memset(line, 0, b->width*sizeof(IDWTELEM));
- v = b->x_coeff[new_index].coeff;
- x = b->x_coeff[new_index++].x;
- while(x < w){
- register int t= ( (v>>1)*qmul + qadd)>>QEXPSHIFT;
- register int u= -(v&1);
- line[x] = (t^u) - u;
-
- v = b->x_coeff[new_index].coeff;
- x = b->x_coeff[new_index++].x;
- }
- }
-
- /* Save our variables for the next slice. */
- save_state[0] = new_index;
-
- return;
-}
-
-static void reset_contexts(SnowContext *s){ //FIXME better initial contexts
- int plane_index, level, orientation;
-
- for(plane_index=0; plane_index<3; plane_index++){
- for(level=0; level<MAX_DECOMPOSITIONS; level++){
- for(orientation=level ? 1:0; orientation<4; orientation++){
- memset(s->plane[plane_index].band[level][orientation].state, MID_STATE, sizeof(s->plane[plane_index].band[level][orientation].state));
- }
- }
- }
- memset(s->header_state, MID_STATE, sizeof(s->header_state));
- memset(s->block_state, MID_STATE, sizeof(s->block_state));
-}
-
-static int alloc_blocks(SnowContext *s){
- int w= -((-s->avctx->width )>>LOG2_MB_SIZE);
- int h= -((-s->avctx->height)>>LOG2_MB_SIZE);
-
- s->b_width = w;
- s->b_height= h;
-
- av_free(s->block);
- s->block= av_mallocz(w * h * sizeof(BlockNode) << (s->block_max_depth*2));
- return 0;
-}
-
-static inline void copy_rac_state(RangeCoder *d, RangeCoder *s){
- uint8_t *bytestream= d->bytestream;
- uint8_t *bytestream_start= d->bytestream_start;
- *d= *s;
- d->bytestream= bytestream;
- d->bytestream_start= bytestream_start;
-}
-
-//near copy & paste from dsputil, FIXME
-static int pix_sum(uint8_t * pix, int line_size, int w)
-{
- int s, i, j;
-
- s = 0;
- for (i = 0; i < w; i++) {
- for (j = 0; j < w; j++) {
- s += pix[0];
- pix ++;
- }
- pix += line_size - w;
- }
- return s;
-}
-
-//near copy & paste from dsputil, FIXME
-static int pix_norm1(uint8_t * pix, int line_size, int w)
-{
- int s, i, j;
- uint32_t *sq = ff_squareTbl + 256;
-
- s = 0;
- for (i = 0; i < w; i++) {
- for (j = 0; j < w; j ++) {
- s += sq[pix[0]];
- pix ++;
- }
- pix += line_size - w;
- }
- return s;
-}
-
-static inline void set_blocks(SnowContext *s, int level, int x, int y, int l, int cb, int cr, int mx, int my, int ref, int type){
- const int w= s->b_width << s->block_max_depth;
- const int rem_depth= s->block_max_depth - level;
- const int index= (x + y*w) << rem_depth;
- const int block_w= 1<<rem_depth;
- BlockNode block;
- int i,j;
-
- block.color[0]= l;
- block.color[1]= cb;
- block.color[2]= cr;
- block.mx= mx;
- block.my= my;
- block.ref= ref;
- block.type= type;
- block.level= level;
-
- for(j=0; j<block_w; j++){
- for(i=0; i<block_w; i++){
- s->block[index + i + j*w]= block;
- }
- }
-}
-
-static inline void init_ref(MotionEstContext *c, uint8_t *src[3], uint8_t *ref[3], uint8_t *ref2[3], int x, int y, int ref_index){
- const int offset[3]= {
- y*c-> stride + x,
- ((y*c->uvstride + x)>>1),
- ((y*c->uvstride + x)>>1),
- };
- int i;
- for(i=0; i<3; i++){
- c->src[0][i]= src [i];
- c->ref[0][i]= ref [i] + offset[i];
- }
- assert(!ref_index);
-}
-
-static inline void pred_mv(SnowContext *s, int *mx, int *my, int ref,
- const BlockNode *left, const BlockNode *top, const BlockNode *tr){
- if(s->ref_frames == 1){
- *mx = mid_pred(left->mx, top->mx, tr->mx);
- *my = mid_pred(left->my, top->my, tr->my);
- }else{
- const int *scale = scale_mv_ref[ref];
- *mx = mid_pred((left->mx * scale[left->ref] + 128) >>8,
- (top ->mx * scale[top ->ref] + 128) >>8,
- (tr ->mx * scale[tr ->ref] + 128) >>8);
- *my = mid_pred((left->my * scale[left->ref] + 128) >>8,
- (top ->my * scale[top ->ref] + 128) >>8,
- (tr ->my * scale[tr ->ref] + 128) >>8);
- }
-}
-
-//FIXME copy&paste
-#define P_LEFT P[1]
-#define P_TOP P[2]
-#define P_TOPRIGHT P[3]
-#define P_MEDIAN P[4]
-#define P_MV1 P[9]
-#define FLAG_QPEL 1 //must be 1
-
-static int encode_q_branch(SnowContext *s, int level, int x, int y){
- uint8_t p_buffer[1024];
- uint8_t i_buffer[1024];
- uint8_t p_state[sizeof(s->block_state)];
- uint8_t i_state[sizeof(s->block_state)];
- RangeCoder pc, ic;
- uint8_t *pbbak= s->c.bytestream;
- uint8_t *pbbak_start= s->c.bytestream_start;
- int score, score2, iscore, i_len, p_len, block_s, sum, base_bits;
- const int w= s->b_width << s->block_max_depth;
- const int h= s->b_height << s->block_max_depth;
- const int rem_depth= s->block_max_depth - level;
- const int index= (x + y*w) << rem_depth;
- const int block_w= 1<<(LOG2_MB_SIZE - level);
- int trx= (x+1)<<rem_depth;
- int try= (y+1)<<rem_depth;
- const BlockNode *left = x ? &s->block[index-1] : &null_block;
- const BlockNode *top = y ? &s->block[index-w] : &null_block;
- const BlockNode *right = trx<w ? &s->block[index+1] : &null_block;
- const BlockNode *bottom= try<h ? &s->block[index+w] : &null_block;
- const BlockNode *tl = y && x ? &s->block[index-w-1] : left;
- const BlockNode *tr = y && trx<w && ((x&1)==0 || level==0) ? &s->block[index-w+(1<<rem_depth)] : tl; //FIXME use lt
- int pl = left->color[0];
- int pcb= left->color[1];
- int pcr= left->color[2];
- int pmx, pmy;
- int mx=0, my=0;
- int l,cr,cb;
- const int stride= s->current_picture.linesize[0];
- const int uvstride= s->current_picture.linesize[1];
- uint8_t *current_data[3]= { s->input_picture.data[0] + (x + y* stride)*block_w,
- s->input_picture.data[1] + (x + y*uvstride)*block_w/2,
- s->input_picture.data[2] + (x + y*uvstride)*block_w/2};
- int P[10][2];
- int16_t last_mv[3][2];
- int qpel= !!(s->avctx->flags & CODEC_FLAG_QPEL); //unused
- const int shift= 1+qpel;
- MotionEstContext *c= &s->m.me;
- int ref_context= av_log2(2*left->ref) + av_log2(2*top->ref);
- int mx_context= av_log2(2*FFABS(left->mx - top->mx));
- int my_context= av_log2(2*FFABS(left->my - top->my));
- int s_context= 2*left->level + 2*top->level + tl->level + tr->level;
- int ref, best_ref, ref_score, ref_mx, ref_my;
-
- assert(sizeof(s->block_state) >= 256);
- if(s->keyframe){
- set_blocks(s, level, x, y, pl, pcb, pcr, 0, 0, 0, BLOCK_INTRA);
- return 0;
- }
-
-// clip predictors / edge ?
-
- P_LEFT[0]= left->mx;
- P_LEFT[1]= left->my;
- P_TOP [0]= top->mx;
- P_TOP [1]= top->my;
- P_TOPRIGHT[0]= tr->mx;
- P_TOPRIGHT[1]= tr->my;
-
- last_mv[0][0]= s->block[index].mx;
- last_mv[0][1]= s->block[index].my;
- last_mv[1][0]= right->mx;
- last_mv[1][1]= right->my;
- last_mv[2][0]= bottom->mx;
- last_mv[2][1]= bottom->my;
-
- s->m.mb_stride=2;
- s->m.mb_x=
- s->m.mb_y= 0;
- c->skip= 0;
-
- assert(c-> stride == stride);
- assert(c->uvstride == uvstride);
-
- c->penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_cmp);
- c->sub_penalty_factor= get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_sub_cmp);
- c->mb_penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->mb_cmp);
- c->current_mv_penalty= c->mv_penalty[s->m.f_code=1] + MAX_MV;
-
- c->xmin = - x*block_w - 16+2;
- c->ymin = - y*block_w - 16+2;
- c->xmax = - (x+1)*block_w + (w<<(LOG2_MB_SIZE - s->block_max_depth)) + 16-2;
- c->ymax = - (y+1)*block_w + (h<<(LOG2_MB_SIZE - s->block_max_depth)) + 16-2;
-
- if(P_LEFT[0] > (c->xmax<<shift)) P_LEFT[0] = (c->xmax<<shift);
- if(P_LEFT[1] > (c->ymax<<shift)) P_LEFT[1] = (c->ymax<<shift);
- if(P_TOP[0] > (c->xmax<<shift)) P_TOP[0] = (c->xmax<<shift);
- if(P_TOP[1] > (c->ymax<<shift)) P_TOP[1] = (c->ymax<<shift);
- if(P_TOPRIGHT[0] < (c->xmin<<shift)) P_TOPRIGHT[0]= (c->xmin<<shift);
- if(P_TOPRIGHT[0] > (c->xmax<<shift)) P_TOPRIGHT[0]= (c->xmax<<shift); //due to pmx no clip
- if(P_TOPRIGHT[1] > (c->ymax<<shift)) P_TOPRIGHT[1]= (c->ymax<<shift);
-
- P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
- P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
-
- if (!y) {
- c->pred_x= P_LEFT[0];
- c->pred_y= P_LEFT[1];
- } else {
- c->pred_x = P_MEDIAN[0];
- c->pred_y = P_MEDIAN[1];
- }
-
- score= INT_MAX;
- best_ref= 0;
- for(ref=0; ref<s->ref_frames; ref++){
- init_ref(c, current_data, s->last_picture[ref].data, NULL, block_w*x, block_w*y, 0);
-
- ref_score= ff_epzs_motion_search(&s->m, &ref_mx, &ref_my, P, 0, /*ref_index*/ 0, last_mv,
- (1<<16)>>shift, level-LOG2_MB_SIZE+4, block_w);
-
- assert(ref_mx >= c->xmin);
- assert(ref_mx <= c->xmax);
- assert(ref_my >= c->ymin);
- assert(ref_my <= c->ymax);
-
- ref_score= c->sub_motion_search(&s->m, &ref_mx, &ref_my, ref_score, 0, 0, level-LOG2_MB_SIZE+4, block_w);
- ref_score= ff_get_mb_score(&s->m, ref_mx, ref_my, 0, 0, level-LOG2_MB_SIZE+4, block_w, 0);
- ref_score+= 2*av_log2(2*ref)*c->penalty_factor;
- if(s->ref_mvs[ref]){
- s->ref_mvs[ref][index][0]= ref_mx;
- s->ref_mvs[ref][index][1]= ref_my;
- s->ref_scores[ref][index]= ref_score;
- }
- if(score > ref_score){
- score= ref_score;
- best_ref= ref;
- mx= ref_mx;
- my= ref_my;
- }
- }
- //FIXME if mb_cmp != SSE then intra cannot be compared currently and mb_penalty vs. lambda2
-
- // subpel search
- base_bits= get_rac_count(&s->c) - 8*(s->c.bytestream - s->c.bytestream_start);
- pc= s->c;
- pc.bytestream_start=
- pc.bytestream= p_buffer; //FIXME end/start? and at the other stoo
- memcpy(p_state, s->block_state, sizeof(s->block_state));
-
- if(level!=s->block_max_depth)
- put_rac(&pc, &p_state[4 + s_context], 1);
- put_rac(&pc, &p_state[1 + left->type + top->type], 0);
- if(s->ref_frames > 1)
- put_symbol(&pc, &p_state[128 + 1024 + 32*ref_context], best_ref, 0);
- pred_mv(s, &pmx, &pmy, best_ref, left, top, tr);
- put_symbol(&pc, &p_state[128 + 32*(mx_context + 16*!!best_ref)], mx - pmx, 1);
- put_symbol(&pc, &p_state[128 + 32*(my_context + 16*!!best_ref)], my - pmy, 1);
- p_len= pc.bytestream - pc.bytestream_start;
- score += (s->lambda2*(get_rac_count(&pc)-base_bits))>>FF_LAMBDA_SHIFT;
-
- block_s= block_w*block_w;
- sum = pix_sum(current_data[0], stride, block_w);
- l= (sum + block_s/2)/block_s;
- iscore = pix_norm1(current_data[0], stride, block_w) - 2*l*sum + l*l*block_s;
-
- block_s= block_w*block_w>>2;
- sum = pix_sum(current_data[1], uvstride, block_w>>1);
- cb= (sum + block_s/2)/block_s;
-// iscore += pix_norm1(¤t_mb[1][0], uvstride, block_w>>1) - 2*cb*sum + cb*cb*block_s;
- sum = pix_sum(current_data[2], uvstride, block_w>>1);
- cr= (sum + block_s/2)/block_s;
-// iscore += pix_norm1(¤t_mb[2][0], uvstride, block_w>>1) - 2*cr*sum + cr*cr*block_s;
-
- ic= s->c;
- ic.bytestream_start=
- ic.bytestream= i_buffer; //FIXME end/start? and at the other stoo
- memcpy(i_state, s->block_state, sizeof(s->block_state));
- if(level!=s->block_max_depth)
- put_rac(&ic, &i_state[4 + s_context], 1);
- put_rac(&ic, &i_state[1 + left->type + top->type], 1);
- put_symbol(&ic, &i_state[32], l-pl , 1);
- put_symbol(&ic, &i_state[64], cb-pcb, 1);
- put_symbol(&ic, &i_state[96], cr-pcr, 1);
- i_len= ic.bytestream - ic.bytestream_start;
- iscore += (s->lambda2*(get_rac_count(&ic)-base_bits))>>FF_LAMBDA_SHIFT;
-
-// assert(score==256*256*256*64-1);
- assert(iscore < 255*255*256 + s->lambda2*10);
- assert(iscore >= 0);
- assert(l>=0 && l<=255);
- assert(pl>=0 && pl<=255);
-
- if(level==0){
- int varc= iscore >> 8;
- int vard= score >> 8;
- if (vard <= 64 || vard < varc)
- c->scene_change_score+= ff_sqrt(vard) - ff_sqrt(varc);
- else
- c->scene_change_score+= s->m.qscale;
- }
-
- if(level!=s->block_max_depth){
- put_rac(&s->c, &s->block_state[4 + s_context], 0);
- score2 = encode_q_branch(s, level+1, 2*x+0, 2*y+0);
- score2+= encode_q_branch(s, level+1, 2*x+1, 2*y+0);
- score2+= encode_q_branch(s, level+1, 2*x+0, 2*y+1);
- score2+= encode_q_branch(s, level+1, 2*x+1, 2*y+1);
- score2+= s->lambda2>>FF_LAMBDA_SHIFT; //FIXME exact split overhead
-
- if(score2 < score && score2 < iscore)
- return score2;
- }
-
- if(iscore < score){
- pred_mv(s, &pmx, &pmy, 0, left, top, tr);
- memcpy(pbbak, i_buffer, i_len);
- s->c= ic;
- s->c.bytestream_start= pbbak_start;
- s->c.bytestream= pbbak + i_len;
- set_blocks(s, level, x, y, l, cb, cr, pmx, pmy, 0, BLOCK_INTRA);
- memcpy(s->block_state, i_state, sizeof(s->block_state));
- return iscore;
- }else{
- memcpy(pbbak, p_buffer, p_len);
- s->c= pc;
- s->c.bytestream_start= pbbak_start;
- s->c.bytestream= pbbak + p_len;
- set_blocks(s, level, x, y, pl, pcb, pcr, mx, my, best_ref, 0);
- memcpy(s->block_state, p_state, sizeof(s->block_state));
- return score;
- }
-}
-
-static av_always_inline int same_block(BlockNode *a, BlockNode *b){
- if((a->type&BLOCK_INTRA) && (b->type&BLOCK_INTRA)){
- return !((a->color[0] - b->color[0]) | (a->color[1] - b->color[1]) | (a->color[2] - b->color[2]));
- }else{
- return !((a->mx - b->mx) | (a->my - b->my) | (a->ref - b->ref) | ((a->type ^ b->type)&BLOCK_INTRA));
- }
-}
-
-static void encode_q_branch2(SnowContext *s, int level, int x, int y){
- const int w= s->b_width << s->block_max_depth;
- const int rem_depth= s->block_max_depth - level;
- const int index= (x + y*w) << rem_depth;
- int trx= (x+1)<<rem_depth;
- BlockNode *b= &s->block[index];
- const BlockNode *left = x ? &s->block[index-1] : &null_block;
- const BlockNode *top = y ? &s->block[index-w] : &null_block;
- const BlockNode *tl = y && x ? &s->block[index-w-1] : left;
- const BlockNode *tr = y && trx<w && ((x&1)==0 || level==0) ? &s->block[index-w+(1<<rem_depth)] : tl; //FIXME use lt
- int pl = left->color[0];
- int pcb= left->color[1];
- int pcr= left->color[2];
- int pmx, pmy;
- int ref_context= av_log2(2*left->ref) + av_log2(2*top->ref);
- int mx_context= av_log2(2*FFABS(left->mx - top->mx)) + 16*!!b->ref;
- int my_context= av_log2(2*FFABS(left->my - top->my)) + 16*!!b->ref;
- int s_context= 2*left->level + 2*top->level + tl->level + tr->level;
-
- if(s->keyframe){
- set_blocks(s, level, x, y, pl, pcb, pcr, 0, 0, 0, BLOCK_INTRA);
- return;
- }
-
- if(level!=s->block_max_depth){
- if(same_block(b,b+1) && same_block(b,b+w) && same_block(b,b+w+1)){
- put_rac(&s->c, &s->block_state[4 + s_context], 1);
- }else{
- put_rac(&s->c, &s->block_state[4 + s_context], 0);
- encode_q_branch2(s, level+1, 2*x+0, 2*y+0);
- encode_q_branch2(s, level+1, 2*x+1, 2*y+0);
- encode_q_branch2(s, level+1, 2*x+0, 2*y+1);
- encode_q_branch2(s, level+1, 2*x+1, 2*y+1);
- return;
- }
- }
- if(b->type & BLOCK_INTRA){
- pred_mv(s, &pmx, &pmy, 0, left, top, tr);
- put_rac(&s->c, &s->block_state[1 + (left->type&1) + (top->type&1)], 1);
- put_symbol(&s->c, &s->block_state[32], b->color[0]-pl , 1);
- put_symbol(&s->c, &s->block_state[64], b->color[1]-pcb, 1);
- put_symbol(&s->c, &s->block_state[96], b->color[2]-pcr, 1);
- set_blocks(s, level, x, y, b->color[0], b->color[1], b->color[2], pmx, pmy, 0, BLOCK_INTRA);
- }else{
- pred_mv(s, &pmx, &pmy, b->ref, left, top, tr);
- put_rac(&s->c, &s->block_state[1 + (left->type&1) + (top->type&1)], 0);
- if(s->ref_frames > 1)
- put_symbol(&s->c, &s->block_state[128 + 1024 + 32*ref_context], b->ref, 0);
- put_symbol(&s->c, &s->block_state[128 + 32*mx_context], b->mx - pmx, 1);
- put_symbol(&s->c, &s->block_state[128 + 32*my_context], b->my - pmy, 1);
- set_blocks(s, level, x, y, pl, pcb, pcr, b->mx, b->my, b->ref, 0);
- }
-}
-
-static void decode_q_branch(SnowContext *s, int level, int x, int y){
- const int w= s->b_width << s->block_max_depth;
- const int rem_depth= s->block_max_depth - level;
- const int index= (x + y*w) << rem_depth;
- int trx= (x+1)<<rem_depth;
- const BlockNode *left = x ? &s->block[index-1] : &null_block;
- const BlockNode *top = y ? &s->block[index-w] : &null_block;
- const BlockNode *tl = y && x ? &s->block[index-w-1] : left;
- const BlockNode *tr = y && trx<w && ((x&1)==0 || level==0) ? &s->block[index-w+(1<<rem_depth)] : tl; //FIXME use lt
- int s_context= 2*left->level + 2*top->level + tl->level + tr->level;
-
- if(s->keyframe){
- set_blocks(s, level, x, y, null_block.color[0], null_block.color[1], null_block.color[2], null_block.mx, null_block.my, null_block.ref, BLOCK_INTRA);
- return;
- }
-
- if(level==s->block_max_depth || get_rac(&s->c, &s->block_state[4 + s_context])){
- int type, mx, my;
- int l = left->color[0];
- int cb= left->color[1];
- int cr= left->color[2];
- int ref = 0;
- int ref_context= av_log2(2*left->ref) + av_log2(2*top->ref);
- int mx_context= av_log2(2*FFABS(left->mx - top->mx)) + 0*av_log2(2*FFABS(tr->mx - top->mx));
- int my_context= av_log2(2*FFABS(left->my - top->my)) + 0*av_log2(2*FFABS(tr->my - top->my));
-
- type= get_rac(&s->c, &s->block_state[1 + left->type + top->type]) ? BLOCK_INTRA : 0;
-
- if(type){
- pred_mv(s, &mx, &my, 0, left, top, tr);
- l += get_symbol(&s->c, &s->block_state[32], 1);
- cb+= get_symbol(&s->c, &s->block_state[64], 1);
- cr+= get_symbol(&s->c, &s->block_state[96], 1);
- }else{
- if(s->ref_frames > 1)
- ref= get_symbol(&s->c, &s->block_state[128 + 1024 + 32*ref_context], 0);
- pred_mv(s, &mx, &my, ref, left, top, tr);
- mx+= get_symbol(&s->c, &s->block_state[128 + 32*(mx_context + 16*!!ref)], 1);
- my+= get_symbol(&s->c, &s->block_state[128 + 32*(my_context + 16*!!ref)], 1);
- }
- set_blocks(s, level, x, y, l, cb, cr, mx, my, ref, type);
- }else{
- decode_q_branch(s, level+1, 2*x+0, 2*y+0);
- decode_q_branch(s, level+1, 2*x+1, 2*y+0);
- decode_q_branch(s, level+1, 2*x+0, 2*y+1);
- decode_q_branch(s, level+1, 2*x+1, 2*y+1);
- }
-}
-
-static void encode_blocks(SnowContext *s, int search){
- int x, y;
- int w= s->b_width;
- int h= s->b_height;
-
- if(s->avctx->me_method == ME_ITER && !s->keyframe && search)
- iterative_me(s);
-
- for(y=0; y<h; y++){
- if(s->c.bytestream_end - s->c.bytestream < w*MB_SIZE*MB_SIZE*3){ //FIXME nicer limit
- av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
- return;
- }
- for(x=0; x<w; x++){
- if(s->avctx->me_method == ME_ITER || !search)
- encode_q_branch2(s, 0, x, y);
- else
- encode_q_branch (s, 0, x, y);
- }
- }
-}
-
-static void decode_blocks(SnowContext *s){
- int x, y;
- int w= s->b_width;
- int h= s->b_height;
-
- for(y=0; y<h; y++){
- for(x=0; x<w; x++){
- decode_q_branch(s, 0, x, y);
- }
- }
-}
-
-static void mc_block(Plane *p, uint8_t *dst, const uint8_t *src, uint8_t *tmp, int stride, int b_w, int b_h, int dx, int dy){
- static const uint8_t weight[64]={
- 8,7,6,5,4,3,2,1,
- 7,7,0,0,0,0,0,1,
- 6,0,6,0,0,0,2,0,
- 5,0,0,5,0,3,0,0,
- 4,0,0,0,4,0,0,0,
- 3,0,0,5,0,3,0,0,
- 2,0,6,0,0,0,2,0,
- 1,7,0,0,0,0,0,1,
- };
-
- static const uint8_t brane[256]={
- 0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x11,0x12,0x12,0x12,0x12,0x12,0x12,0x12,
- 0x04,0x05,0xcc,0xcc,0xcc,0xcc,0xcc,0x41,0x15,0x16,0xcc,0xcc,0xcc,0xcc,0xcc,0x52,
- 0x04,0xcc,0x05,0xcc,0xcc,0xcc,0x41,0xcc,0x15,0xcc,0x16,0xcc,0xcc,0xcc,0x52,0xcc,
- 0x04,0xcc,0xcc,0x05,0xcc,0x41,0xcc,0xcc,0x15,0xcc,0xcc,0x16,0xcc,0x52,0xcc,0xcc,
- 0x04,0xcc,0xcc,0xcc,0x41,0xcc,0xcc,0xcc,0x15,0xcc,0xcc,0xcc,0x16,0xcc,0xcc,0xcc,
- 0x04,0xcc,0xcc,0x41,0xcc,0x05,0xcc,0xcc,0x15,0xcc,0xcc,0x52,0xcc,0x16,0xcc,0xcc,
- 0x04,0xcc,0x41,0xcc,0xcc,0xcc,0x05,0xcc,0x15,0xcc,0x52,0xcc,0xcc,0xcc,0x16,0xcc,
- 0x04,0x41,0xcc,0xcc,0xcc,0xcc,0xcc,0x05,0x15,0x52,0xcc,0xcc,0xcc,0xcc,0xcc,0x16,
- 0x44,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x55,0x56,0x56,0x56,0x56,0x56,0x56,0x56,
- 0x48,0x49,0xcc,0xcc,0xcc,0xcc,0xcc,0x85,0x59,0x5A,0xcc,0xcc,0xcc,0xcc,0xcc,0x96,
- 0x48,0xcc,0x49,0xcc,0xcc,0xcc,0x85,0xcc,0x59,0xcc,0x5A,0xcc,0xcc,0xcc,0x96,0xcc,
- 0x48,0xcc,0xcc,0x49,0xcc,0x85,0xcc,0xcc,0x59,0xcc,0xcc,0x5A,0xcc,0x96,0xcc,0xcc,
- 0x48,0xcc,0xcc,0xcc,0x49,0xcc,0xcc,0xcc,0x59,0xcc,0xcc,0xcc,0x96,0xcc,0xcc,0xcc,
- 0x48,0xcc,0xcc,0x85,0xcc,0x49,0xcc,0xcc,0x59,0xcc,0xcc,0x96,0xcc,0x5A,0xcc,0xcc,
- 0x48,0xcc,0x85,0xcc,0xcc,0xcc,0x49,0xcc,0x59,0xcc,0x96,0xcc,0xcc,0xcc,0x5A,0xcc,
- 0x48,0x85,0xcc,0xcc,0xcc,0xcc,0xcc,0x49,0x59,0x96,0xcc,0xcc,0xcc,0xcc,0xcc,0x5A,
- };
-
- static const uint8_t needs[16]={
- 0,1,0,0,
- 2,4,2,0,
- 0,1,0,0,
- 15
- };
-
- int x, y, b, r, l;
- int16_t tmpIt [64*(32+HTAPS_MAX)];
- uint8_t tmp2t[3][stride*(32+HTAPS_MAX)];
- int16_t *tmpI= tmpIt;
- uint8_t *tmp2= tmp2t[0];
- const uint8_t *hpel[11];
- assert(dx<16 && dy<16);
- r= brane[dx + 16*dy]&15;
- l= brane[dx + 16*dy]>>4;
-
- b= needs[l] | needs[r];
- if(p && !p->diag_mc)
- b= 15;
-
- if(b&5){
- for(y=0; y < b_h+HTAPS_MAX-1; y++){
- for(x=0; x < b_w; x++){
- int a_1=src[x + HTAPS_MAX/2-4];
- int a0= src[x + HTAPS_MAX/2-3];
- int a1= src[x + HTAPS_MAX/2-2];
- int a2= src[x + HTAPS_MAX/2-1];
- int a3= src[x + HTAPS_MAX/2+0];
- int a4= src[x + HTAPS_MAX/2+1];
- int a5= src[x + HTAPS_MAX/2+2];
- int a6= src[x + HTAPS_MAX/2+3];
- int am=0;
- if(!p || p->fast_mc){
- am= 20*(a2+a3) - 5*(a1+a4) + (a0+a5);
- tmpI[x]= am;
- am= (am+16)>>5;
- }else{
- am= p->hcoeff[0]*(a2+a3) + p->hcoeff[1]*(a1+a4) + p->hcoeff[2]*(a0+a5) + p->hcoeff[3]*(a_1+a6);
- tmpI[x]= am;
- am= (am+32)>>6;
- }
-
- if(am&(~255)) am= ~(am>>31);
- tmp2[x]= am;
- }
- tmpI+= 64;
- tmp2+= stride;
- src += stride;
- }
- src -= stride*y;
- }
- src += HTAPS_MAX/2 - 1;
- tmp2= tmp2t[1];
-
- if(b&2){
- for(y=0; y < b_h; y++){
- for(x=0; x < b_w+1; x++){
- int a_1=src[x + (HTAPS_MAX/2-4)*stride];
- int a0= src[x + (HTAPS_MAX/2-3)*stride];
- int a1= src[x + (HTAPS_MAX/2-2)*stride];
- int a2= src[x + (HTAPS_MAX/2-1)*stride];
- int a3= src[x + (HTAPS_MAX/2+0)*stride];
- int a4= src[x + (HTAPS_MAX/2+1)*stride];
- int a5= src[x + (HTAPS_MAX/2+2)*stride];
- int a6= src[x + (HTAPS_MAX/2+3)*stride];
- int am=0;
- if(!p || p->fast_mc)
- am= (20*(a2+a3) - 5*(a1+a4) + (a0+a5) + 16)>>5;
- else
- am= (p->hcoeff[0]*(a2+a3) + p->hcoeff[1]*(a1+a4) + p->hcoeff[2]*(a0+a5) + p->hcoeff[3]*(a_1+a6) + 32)>>6;
-
- if(am&(~255)) am= ~(am>>31);
- tmp2[x]= am;
- }
- src += stride;
- tmp2+= stride;
- }
- src -= stride*y;
- }
- src += stride*(HTAPS_MAX/2 - 1);
- tmp2= tmp2t[2];
- tmpI= tmpIt;
- if(b&4){
- for(y=0; y < b_h; y++){
- for(x=0; x < b_w; x++){
- int a_1=tmpI[x + (HTAPS_MAX/2-4)*64];
- int a0= tmpI[x + (HTAPS_MAX/2-3)*64];
- int a1= tmpI[x + (HTAPS_MAX/2-2)*64];
- int a2= tmpI[x + (HTAPS_MAX/2-1)*64];
- int a3= tmpI[x + (HTAPS_MAX/2+0)*64];
- int a4= tmpI[x + (HTAPS_MAX/2+1)*64];
- int a5= tmpI[x + (HTAPS_MAX/2+2)*64];
- int a6= tmpI[x + (HTAPS_MAX/2+3)*64];
- int am=0;
- if(!p || p->fast_mc)
- am= (20*(a2+a3) - 5*(a1+a4) + (a0+a5) + 512)>>10;
- else
- am= (p->hcoeff[0]*(a2+a3) + p->hcoeff[1]*(a1+a4) + p->hcoeff[2]*(a0+a5) + p->hcoeff[3]*(a_1+a6) + 2048)>>12;
- if(am&(~255)) am= ~(am>>31);
- tmp2[x]= am;
- }
- tmpI+= 64;
- tmp2+= stride;
- }
- }
-
- hpel[ 0]= src;
- hpel[ 1]= tmp2t[0] + stride*(HTAPS_MAX/2-1);
- hpel[ 2]= src + 1;
-
- hpel[ 4]= tmp2t[1];
- hpel[ 5]= tmp2t[2];
- hpel[ 6]= tmp2t[1] + 1;
-
- hpel[ 8]= src + stride;
- hpel[ 9]= hpel[1] + stride;
- hpel[10]= hpel[8] + 1;
-
- if(b==15){
- const uint8_t *src1= hpel[dx/8 + dy/8*4 ];
- const uint8_t *src2= hpel[dx/8 + dy/8*4+1];
- const uint8_t *src3= hpel[dx/8 + dy/8*4+4];
- const uint8_t *src4= hpel[dx/8 + dy/8*4+5];
- dx&=7;
- dy&=7;
- for(y=0; y < b_h; y++){
- for(x=0; x < b_w; x++){
- dst[x]= ((8-dx)*(8-dy)*src1[x] + dx*(8-dy)*src2[x]+
- (8-dx)* dy *src3[x] + dx* dy *src4[x]+32)>>6;
- }
- src1+=stride;
- src2+=stride;
- src3+=stride;
- src4+=stride;
- dst +=stride;
- }
- }else{
- const uint8_t *src1= hpel[l];
- const uint8_t *src2= hpel[r];
- int a= weight[((dx&7) + (8*(dy&7)))];
- int b= 8-a;
- for(y=0; y < b_h; y++){
- for(x=0; x < b_w; x++){
- dst[x]= (a*src1[x] + b*src2[x] + 4)>>3;
- }
- src1+=stride;
- src2+=stride;
- dst +=stride;
- }
- }
-}
-
-#define mca(dx,dy,b_w)\
-static void mc_block_hpel ## dx ## dy ## b_w(uint8_t *dst, const uint8_t *src, int stride, int h){\
- uint8_t tmp[stride*(b_w+HTAPS_MAX-1)];\
- assert(h==b_w);\
- mc_block(NULL, dst, src-(HTAPS_MAX/2-1)-(HTAPS_MAX/2-1)*stride, tmp, stride, b_w, b_w, dx, dy);\