Mercurial > libavcodec.hg
comparison snow.c @ 3051:c0fde3eb7784 libavcodec
obmc-aware 4mv
author | lorenm |
---|---|
date | Tue, 17 Jan 2006 08:27:39 +0000 |
parents | 0b546eab515d |
children | 2991dc513726 |
comparison
equal
deleted
inserted
replaced
3050:61e47d203191 | 3051:c0fde3eb7784 |
---|---|
3045 *b= backup; | 3045 *b= backup; |
3046 | 3046 |
3047 return clip(((ab<<6) + aa/2)/aa, 0, 255); //FIXME we shouldnt need cliping | 3047 return clip(((ab<<6) + aa/2)/aa, 0, 255); //FIXME we shouldnt need cliping |
3048 } | 3048 } |
3049 | 3049 |
3050 static inline int get_block_bits(SnowContext *s, int x, int y, int w){ | |
3051 const int b_stride = s->b_width << s->block_max_depth; | |
3052 const int b_height = s->b_height<< s->block_max_depth; | |
3053 int index= x + y*b_stride; | |
3054 BlockNode *b = &s->block[index]; | |
3055 BlockNode *left = x ? &s->block[index-1] : &null_block; | |
3056 BlockNode *top = y ? &s->block[index-b_stride] : &null_block; | |
3057 BlockNode *tl = y && x ? &s->block[index-b_stride-1] : left; | |
3058 BlockNode *tr = y && x+w<b_stride ? &s->block[index-b_stride+w] : tl; | |
3059 int dmx, dmy; | |
3060 // int mx_context= av_log2(2*ABS(left->mx - top->mx)); | |
3061 // int my_context= av_log2(2*ABS(left->my - top->my)); | |
3062 | |
3063 if(x<0 || x>=b_stride || y>=b_height) | |
3064 return 0; | |
3065 dmx= b->mx - mid_pred(left->mx, top->mx, tr->mx); | |
3066 dmy= b->my - mid_pred(left->my, top->my, tr->my); | |
3067 /* | |
3068 1 0 0 | |
3069 01X 1-2 1 | |
3070 001XX 3-6 2-3 | |
3071 0001XXX 7-14 4-7 | |
3072 00001XXXX 15-30 8-15 | |
3073 */ | |
3074 //FIXME try accurate rate | |
3075 //FIXME intra and inter predictors if surrounding blocks arent the same type | |
3076 if(b->type & BLOCK_INTRA){ | |
3077 return 3+2*( av_log2(2*ABS(left->color[0] - b->color[0])) | |
3078 + av_log2(2*ABS(left->color[1] - b->color[1])) | |
3079 + av_log2(2*ABS(left->color[2] - b->color[2]))); | |
3080 }else | |
3081 return 2*(1 + av_log2(2*ABS(dmx)) | |
3082 + av_log2(2*ABS(dmy))); //FIXME kill the 2* can be merged in lambda | |
3083 } | |
3084 | |
3050 static int get_block_rd(SnowContext *s, int mb_x, int mb_y, int plane_index, const uint8_t *obmc_edged){ | 3085 static int get_block_rd(SnowContext *s, int mb_x, int mb_y, int plane_index, const uint8_t *obmc_edged){ |
3051 Plane *p= &s->plane[plane_index]; | 3086 Plane *p= &s->plane[plane_index]; |
3052 const int block_size = MB_SIZE >> s->block_max_depth; | 3087 const int block_size = MB_SIZE >> s->block_max_depth; |
3053 const int block_w = plane_index ? block_size/2 : block_size; | 3088 const int block_w = plane_index ? block_size/2 : block_size; |
3054 const uint8_t *obmc = plane_index ? obmc_tab[s->block_max_depth+1] : obmc_tab[s->block_max_depth]; | 3089 const uint8_t *obmc = plane_index ? obmc_tab[s->block_max_depth+1] : obmc_tab[s->block_max_depth]; |
3106 for(i=0; i<4; i++){ | 3141 for(i=0; i<4; i++){ |
3107 /* ..RRr | 3142 /* ..RRr |
3108 * .RXx. | 3143 * .RXx. |
3109 * rxx.. | 3144 * rxx.. |
3110 */ | 3145 */ |
3111 int x= mb_x + (i&1) - (i>>1); | 3146 rate += get_block_bits(s, mb_x + (i&1) - (i>>1), mb_y + (i>>1), 1); |
3112 int y= mb_y + (i>>1); | 3147 } |
3113 int index= x + y*b_stride; | 3148 } |
3114 BlockNode *b = &s->block[index]; | 3149 return distortion + rate*penalty_factor; |
3115 BlockNode *left = x ? &s->block[index-1] : &null_block; | 3150 } |
3116 BlockNode *top = y ? &s->block[index-b_stride] : &null_block; | 3151 |
3117 BlockNode *tl = y && x ? &s->block[index-b_stride-1] : left; | 3152 static int get_4block_rd(SnowContext *s, int mb_x, int mb_y, int plane_index){ |
3118 BlockNode *tr = y && x+1<b_stride ? &s->block[index-b_stride+1] : tl; | 3153 int i, y2; |
3119 int dmx, dmy; | 3154 Plane *p= &s->plane[plane_index]; |
3120 // int mx_context= av_log2(2*ABS(left->mx - top->mx)); | 3155 const int block_size = MB_SIZE >> s->block_max_depth; |
3121 // int my_context= av_log2(2*ABS(left->my - top->my)); | 3156 const int block_w = plane_index ? block_size/2 : block_size; |
3122 | 3157 const uint8_t *obmc = plane_index ? obmc_tab[s->block_max_depth+1] : obmc_tab[s->block_max_depth]; |
3123 if(x<0 || x>=b_stride || y>=b_height) | 3158 const int obmc_stride= plane_index ? block_size : 2*block_size; |
3124 continue; | 3159 const int ref_stride= s->current_picture.linesize[plane_index]; |
3125 dmx= b->mx - mid_pred(left->mx, top->mx, tr->mx); | 3160 uint8_t *ref= s-> last_picture.data[plane_index]; |
3126 dmy= b->my - mid_pred(left->my, top->my, tr->my); | 3161 uint8_t *dst= s->current_picture.data[plane_index]; |
3127 /* | 3162 uint8_t *src= s-> input_picture.data[plane_index]; |
3128 1 0 0 | 3163 const static DWTELEM zero_dst[4096]; //FIXME |
3129 01X 1-2 1 | 3164 const int b_stride = s->b_width << s->block_max_depth; |
3130 001XX 3-6 2-3 | 3165 const int b_height = s->b_height<< s->block_max_depth; |
3131 0001XXX 7-14 4-7 | 3166 const int w= p->width; |
3132 00001XXXX 15-30 8-15 | 3167 const int h= p->height; |
3133 */ | 3168 int distortion= 0; |
3134 //FIXME try accurate rate | 3169 int rate= 0; |
3135 //FIXME intra and inter predictors if surrounding blocks arent the same type | 3170 const int penalty_factor= get_penalty_factor(s->lambda, s->lambda2, s->avctx->me_cmp); |
3136 if(b->type & BLOCK_INTRA){ | 3171 |
3137 rate += 3+2*( av_log2(2*ABS(left->color[0] - b->color[0])) | 3172 for(i=0; i<9; i++){ |
3138 + av_log2(2*ABS(left->color[1] - b->color[1])) | 3173 int mb_x2= mb_x + (i%3) - 1; |
3139 + av_log2(2*ABS(left->color[2] - b->color[2]))); | 3174 int mb_y2= mb_y + (i/3) - 1; |
3140 }else | 3175 int x= block_w*mb_x2 + block_w/2; |
3141 rate += 2*(1 + av_log2(2*ABS(dmx)) | 3176 int y= block_w*mb_y2 + block_w/2; |
3142 + av_log2(2*ABS(dmy))); //FIXME kill the 2* can be merged in lambda | 3177 |
3143 } | 3178 add_yblock(s, zero_dst, dst, ref, obmc, |
3144 } | 3179 x, y, block_w, block_w, w, h, /*dst_stride*/0, ref_stride, obmc_stride, mb_x2, mb_y2, 1, 1, plane_index); |
3145 | 3180 |
3181 //FIXME find a cleaner/simpler way to skip the outside stuff | |
3182 for(y2= y; y2<0; y2++) | |
3183 memcpy(dst + x + y2*ref_stride, src + x + y2*ref_stride, block_w); | |
3184 for(y2= h; y2<y+block_w; y2++) | |
3185 memcpy(dst + x + y2*ref_stride, src + x + y2*ref_stride, block_w); | |
3186 if(x<0){ | |
3187 for(y2= y; y2<y+block_w; y2++) | |
3188 memcpy(dst + x + y2*ref_stride, src + x + y2*ref_stride, -x); | |
3189 } | |
3190 if(x+block_w > w){ | |
3191 for(y2= y; y2<y+block_w; y2++) | |
3192 memcpy(dst + w + y2*ref_stride, src + w + y2*ref_stride, x+block_w - w); | |
3193 } | |
3194 | |
3195 assert(block_w== 8 || block_w==16); | |
3196 distortion += s->dsp.me_cmp[block_w==8](&s->m, src + x + y*ref_stride, dst + x + y*ref_stride, ref_stride, block_w); | |
3197 } | |
3198 | |
3199 if(plane_index==0){ | |
3200 BlockNode *b= &s->block[mb_x+mb_y*b_stride]; | |
3201 int merged= same_block(b,b+1) && same_block(b,b+b_stride) && same_block(b,b+b_stride+1); | |
3202 | |
3203 /* ..RRRr | |
3204 * .RXXx. | |
3205 * .RXXx. | |
3206 * rxxx. | |
3207 */ | |
3208 if(merged) | |
3209 rate = get_block_bits(s, mb_x, mb_y, 2); | |
3210 for(i=merged?4:0; i<9; i++){ | |
3211 static const int dxy[9][2] = {{0,0},{1,0},{0,1},{1,1},{2,0},{2,1},{-1,2},{0,2},{1,2}}; | |
3212 rate += get_block_bits(s, mb_x + dxy[i][0], mb_y + dxy[i][1], 1); | |
3213 } | |
3214 } | |
3146 return distortion + rate*penalty_factor; | 3215 return distortion + rate*penalty_factor; |
3147 } | 3216 } |
3148 | 3217 |
3149 static always_inline int check_block(SnowContext *s, int mb_x, int mb_y, int p[3], int intra, const uint8_t *obmc_edged, int *best_rd){ | 3218 static always_inline int check_block(SnowContext *s, int mb_x, int mb_y, int p[3], int intra, const uint8_t *obmc_edged, int *best_rd){ |
3150 const int b_stride= s->b_width << s->block_max_depth; | 3219 const int b_stride= s->b_width << s->block_max_depth; |
3186 | 3255 |
3187 /* special case for int[2] args we discard afterward, fixes compilation prob with gcc 2.95 */ | 3256 /* special case for int[2] args we discard afterward, fixes compilation prob with gcc 2.95 */ |
3188 static always_inline int check_block_inter(SnowContext *s, int mb_x, int mb_y, int p0, int p1, int intra, const uint8_t *obmc_edged, int *best_rd){ | 3257 static always_inline int check_block_inter(SnowContext *s, int mb_x, int mb_y, int p0, int p1, int intra, const uint8_t *obmc_edged, int *best_rd){ |
3189 int p[2] = {p0, p1}; | 3258 int p[2] = {p0, p1}; |
3190 return check_block(s, mb_x, mb_y, p, intra, obmc_edged, best_rd); | 3259 return check_block(s, mb_x, mb_y, p, intra, obmc_edged, best_rd); |
3260 } | |
3261 | |
3262 static always_inline int check_4block_inter(SnowContext *s, int mb_x, int mb_y, int p0, int p1, int *best_rd){ | |
3263 const int b_stride= s->b_width << s->block_max_depth; | |
3264 BlockNode *block= &s->block[mb_x + mb_y * b_stride]; | |
3265 BlockNode backup[4]= {block[0], block[1], block[b_stride], block[b_stride+1]}; | |
3266 int rd, index, value; | |
3267 | |
3268 assert(mb_x>=0 && mb_y>=0); | |
3269 assert(mb_x<b_stride); | |
3270 assert(((mb_x|mb_y)&1) == 0); | |
3271 | |
3272 index= (p0 + 31*p1) & (ME_CACHE_SIZE-1); | |
3273 value= s->me_cache_generation + (p0>>10) + (p1<<6); | |
3274 if(s->me_cache[index] == value) | |
3275 return 0; | |
3276 s->me_cache[index]= value; | |
3277 | |
3278 block->mx= p0; | |
3279 block->my= p1; | |
3280 block->type &= ~BLOCK_INTRA; | |
3281 block[1]= block[b_stride]= block[b_stride+1]= *block; | |
3282 | |
3283 rd= get_4block_rd(s, mb_x, mb_y, 0); | |
3284 | |
3285 //FIXME chroma | |
3286 if(rd < *best_rd){ | |
3287 *best_rd= rd; | |
3288 return 1; | |
3289 }else{ | |
3290 block[0]= backup[0]; | |
3291 block[1]= backup[1]; | |
3292 block[b_stride]= backup[2]; | |
3293 block[b_stride+1]= backup[3]; | |
3294 return 0; | |
3295 } | |
3191 } | 3296 } |
3192 | 3297 |
3193 static void iterative_me(SnowContext *s){ | 3298 static void iterative_me(SnowContext *s){ |
3194 int pass, mb_x, mb_y; | 3299 int pass, mb_x, mb_y; |
3195 const int b_width = s->b_width << s->block_max_depth; | 3300 const int b_width = s->b_width << s->block_max_depth; |
3331 } | 3436 } |
3332 av_log(NULL, AV_LOG_ERROR, "pass:%d changed:%d\n", pass, change); | 3437 av_log(NULL, AV_LOG_ERROR, "pass:%d changed:%d\n", pass, change); |
3333 if(!change) | 3438 if(!change) |
3334 break; | 3439 break; |
3335 } | 3440 } |
3441 | |
3442 if(s->block_max_depth == 1){ | |
3443 int change= 0; | |
3444 for(mb_y= 0; mb_y<b_height; mb_y+=2){ | |
3445 for(mb_x= 0; mb_x<b_width; mb_x+=2){ | |
3446 int dia_change, i, j; | |
3447 int best_rd, init_rd; | |
3448 const int index= mb_x + mb_y * b_stride; | |
3449 BlockNode *b[4]; | |
3450 | |
3451 b[0]= &s->block[index]; | |
3452 b[1]= b[0]+1; | |
3453 b[2]= b[0]+b_stride; | |
3454 b[3]= b[2]+1; | |
3455 if(same_block(b[0], b[1]) && | |
3456 same_block(b[0], b[2]) && | |
3457 same_block(b[0], b[3])) | |
3458 continue; | |
3459 | |
3460 if(!s->me_cache_generation) | |
3461 memset(s->me_cache, 0, sizeof(s->me_cache)); | |
3462 s->me_cache_generation += 1<<22; | |
3463 | |
3464 init_rd= best_rd= get_4block_rd(s, mb_x, mb_y, 0); | |
3465 | |
3466 check_4block_inter(s, mb_x, mb_y, | |
3467 (b[0]->mx + b[1]->mx + b[2]->mx + b[3]->mx + 2) >> 2, | |
3468 (b[0]->my + b[1]->my + b[2]->my + b[3]->my + 2) >> 2, &best_rd); | |
3469 | |
3470 for(i=0; i<4; i++) | |
3471 if(!(b[i]->type&BLOCK_INTRA)) | |
3472 check_4block_inter(s, mb_x, mb_y, b[i]->mx, b[i]->my, &best_rd); | |
3473 | |
3474 if(init_rd != best_rd) | |
3475 change++; | |
3476 } | |
3477 } | |
3478 av_log(NULL, AV_LOG_ERROR, "pass:4mv changed:%d\n", change*4); | |
3479 } | |
3336 } | 3480 } |
3337 | 3481 |
3338 static void quantize(SnowContext *s, SubBand *b, DWTELEM *src, int stride, int bias){ | 3482 static void quantize(SnowContext *s, SubBand *b, DWTELEM *src, int stride, int bias){ |
3339 const int level= b->level; | 3483 const int level= b->level; |
3340 const int w= b->width; | 3484 const int w= b->width; |