📄 snow.c
字号:
}
(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->buf == s->spatial_dwt_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;
DWTELEM * line = slice_buffer_get_line(sb, y * b->stride_line + b->buf_y_offset) + b->buf_x_offset;
memset(line, 0, b->width*sizeof(DWTELEM));
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<s->spatial_decomposition_count; 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;
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 cant 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;
sum = pix_sum(current_data[2], uvstride, block_w>>1);
cr= (sum + block_s/2)/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(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+= enco
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -