Commit 8c36eaaa authored by Loren Merritt's avatar Loren Merritt

Snow multiple reference frames

(bitstream is not backwards compatible, even if refs aren't used)

Originally committed as revision 5417 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent 4e64bead
......@@ -369,6 +369,7 @@ static const uint8_t *obmc_tab[4]={
typedef struct BlockNode{
int16_t mx;
int16_t my;
uint8_t ref;
uint8_t color[3];
uint8_t type;
//#define TYPE_SPLIT 1
......@@ -382,6 +383,7 @@ static const BlockNode null_block= { //FIXME add border maybe
.color= {128,128,128},
.mx= 0,
.my= 0,
.ref= 0,
.type= 0,
.level= 0,
};
......@@ -424,7 +426,7 @@ typedef struct SnowContext{
AVFrame new_picture;
AVFrame input_picture; ///< new_picture with the internal linesizes
AVFrame current_picture;
AVFrame last_picture;
AVFrame last_picture[MAX_REF_FRAMES];
AVFrame mconly_picture;
// uint8_t q_context[16];
uint8_t header_state[32];
......@@ -436,6 +438,10 @@ typedef struct SnowContext{
int temporal_decomposition_type;
int spatial_decomposition_count;
int temporal_decomposition_count;
int max_ref_frames;
int ref_frames;
int16_t (*ref_mvs[MAX_REF_FRAMES])[2];
uint32_t *ref_scores[MAX_REF_FRAMES];
DWTELEM *spatial_dwt_buffer;
int colorspace_type;
int chroma_h_shift;
......@@ -1905,7 +1911,7 @@ static int pix_norm1(uint8_t * pix, int line_size, int 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 type){
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;
......@@ -1918,6 +1924,7 @@ static inline void set_blocks(SnowContext *s, int level, int x, int y, int l, in
block.color[2]= cr;
block.mx= mx;
block.my= my;
block.ref= ref;
block.type= type;
block.level= level;
......@@ -1989,13 +1996,15 @@ static int encode_q_branch(SnowContext *s, int level, int x, int y){
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*ABS(left->mx - top->mx));
int my_context= av_log2(2*ABS(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, pmx, pmy, BLOCK_INTRA);
set_blocks(s, level, x, y, pl, pcb, pcr, pmx, pmy, 0, BLOCK_INTRA);
return 0;
}
......@@ -2020,8 +2029,6 @@ static int encode_q_branch(SnowContext *s, int level, int x, int y){
s->m.mb_y= 0;
s->m.me.skip= 0;
init_ref(c, current_data, s->last_picture.data, NULL, block_w*x, block_w*y, 0);
assert(s->m.me. stride == stride);
assert(s->m.me.uvstride == uvstride);
......@@ -2054,16 +2061,34 @@ static int encode_q_branch(SnowContext *s, int level, int x, int y){
c->pred_y = P_MEDIAN[1];
}
score= ff_epzs_motion_search(&s->m, &mx, &my, P, 0, /*ref_index*/ 0, last_mv,
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(mx >= c->xmin);
assert(mx <= c->xmax);
assert(my >= c->ymin);
assert(my <= c->ymax);
assert(ref_mx >= c->xmin);
assert(ref_mx <= c->xmax);
assert(ref_my >= c->ymin);
assert(ref_my <= c->ymax);
score= s->m.me.sub_motion_search(&s->m, &mx, &my, score, 0, 0, level-LOG2_MB_SIZE+4, block_w);
score= ff_get_mb_score(&s->m, mx, my, 0, 0, level-LOG2_MB_SIZE+4, block_w, 0);
ref_score= s->m.me.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
......@@ -2075,8 +2100,10 @@ static int encode_q_branch(SnowContext *s, int level, int x, int y){
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);
put_symbol(&pc, &p_state[128 + 32*mx_context], mx - pmx, 1);
put_symbol(&pc, &p_state[128 + 32*my_context], my - pmy, 1);
if(s->ref_frames > 1)
put_symbol(&pc, &p_state[128 + 1024 + 32*ref_context], best_ref, 0);
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*(p_len*8
+ (pc.outstanding_count - s->c.outstanding_count)*8
......@@ -2144,7 +2171,7 @@ static int encode_q_branch(SnowContext *s, int level, int x, int y){
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, BLOCK_INTRA);
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{
......@@ -2152,7 +2179,7 @@ static int encode_q_branch(SnowContext *s, int level, int x, int y){
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, 0);
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;
}
......@@ -2162,7 +2189,7 @@ static 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->type ^ b->type)&BLOCK_INTRA));
return !((a->mx - b->mx) | (a->my - b->my) | (a->ref - b->ref) | ((a->type ^ b->type)&BLOCK_INTRA));
}
}
......@@ -2181,12 +2208,13 @@ static void encode_q_branch2(SnowContext *s, int level, int x, int y){
int pcr= left->color[2];
int pmx= mid_pred(left->mx, top->mx, tr->mx);
int pmy= mid_pred(left->my, top->my, tr->my);
int mx_context= av_log2(2*ABS(left->mx - top->mx));
int my_context= av_log2(2*ABS(left->my - top->my));
int ref_context= av_log2(2*left->ref) + av_log2(2*top->ref);
int mx_context= av_log2(2*ABS(left->mx - top->mx)) + 16*!!b->ref;
int my_context= av_log2(2*ABS(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, pmx, pmy, BLOCK_INTRA);
set_blocks(s, level, x, y, pl, pcb, pcr, pmx, pmy, 0, BLOCK_INTRA);
return;
}
......@@ -2207,12 +2235,14 @@ static void encode_q_branch2(SnowContext *s, int level, int x, int y){
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, BLOCK_INTRA);
set_blocks(s, level, x, y, b->color[0], b->color[1], b->color[2], pmx, pmy, 0, BLOCK_INTRA);
}else{
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, 0);
set_blocks(s, level, x, y, pl, pcb, pcr, b->mx, b->my, b->ref, 0);
}
}
......@@ -2228,7 +2258,7 @@ static void decode_q_branch(SnowContext *s, int level, int x, int y){
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, BLOCK_INTRA);
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;
}
......@@ -2239,6 +2269,8 @@ static void decode_q_branch(SnowContext *s, int level, int x, int y){
int cr= left->color[2];
int mx= mid_pred(left->mx, top->mx, tr->mx);
int my= mid_pred(left->my, top->my, tr->my);
int ref = 0;
int ref_context= av_log2(2*left->ref) + av_log2(2*top->ref);
int mx_context= av_log2(2*ABS(left->mx - top->mx)) + 0*av_log2(2*ABS(tr->mx - top->mx));
int my_context= av_log2(2*ABS(left->my - top->my)) + 0*av_log2(2*ABS(tr->my - top->my));
......@@ -2249,10 +2281,12 @@ static void decode_q_branch(SnowContext *s, int level, int x, int y){
cb+= get_symbol(&s->c, &s->block_state[64], 1);
cr+= get_symbol(&s->c, &s->block_state[96], 1);
}else{
mx+= get_symbol(&s->c, &s->block_state[128 + 32*mx_context], 1);
my+= get_symbol(&s->c, &s->block_state[128 + 32*my_context], 1);
if(s->ref_frames > 1)
ref= get_symbol(&s->c, &s->block_state[128 + 1024 + 32*ref_context], 0);
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, type);
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);
......@@ -2380,7 +2414,7 @@ mca( 8, 0,8)
mca( 0, 8,8)
mca( 8, 8,8)
static void pred_block(SnowContext *s, uint8_t *dst, uint8_t *src, uint8_t *tmp, int stride, int sx, int sy, int b_w, int b_h, BlockNode *block, int plane_index, int w, int h){
static void pred_block(SnowContext *s, uint8_t *dst, uint8_t *tmp, int stride, int sx, int sy, int b_w, int b_h, BlockNode *block, int plane_index, int w, int h){
if(block->type & BLOCK_INTRA){
int x, y;
const int color = block->color[plane_index];
......@@ -2420,6 +2454,7 @@ static void pred_block(SnowContext *s, uint8_t *dst, uint8_t *src, uint8_t *tmp,
}
}
}else{
uint8_t *src= s->last_picture[block->ref].data[plane_index];
const int scale= plane_index ? s->mv_scale : 2*s->mv_scale;
int mx= block->mx*scale;
int my= block->my*scale;
......@@ -2494,7 +2529,7 @@ void ff_snow_inner_add_yblock(uint8_t *obmc, const int obmc_stride, uint8_t * *
}
//FIXME name clenup (b_w, block_w, b_width stuff)
static always_inline void add_yblock_buffered(SnowContext *s, slice_buffer * sb, DWTELEM *old_dst, uint8_t *dst8, uint8_t *src, uint8_t *obmc, int src_x, int src_y, int b_w, int b_h, int w, int h, int dst_stride, int src_stride, int obmc_stride, int b_x, int b_y, int add, int plane_index){
static always_inline void add_yblock_buffered(SnowContext *s, slice_buffer * sb, DWTELEM *old_dst, uint8_t *dst8, uint8_t *obmc, int src_x, int src_y, int b_w, int b_h, int w, int h, int dst_stride, int src_stride, int obmc_stride, int b_x, int b_y, int add, int plane_index){
DWTELEM * dst = NULL;
const int b_width = s->b_width << s->block_max_depth;
const int b_height= s->b_height << s->block_max_depth;
......@@ -2549,14 +2584,14 @@ assert(src_stride > 2*MB_SIZE + 5);
ptmp= tmp + 3*tmp_step;
block[0]= ptmp;
ptmp+=tmp_step;
pred_block(s, block[0], src, tmp, src_stride, src_x, src_y, b_w, b_h, lt, plane_index, w, h);
pred_block(s, block[0], tmp, src_stride, src_x, src_y, b_w, b_h, lt, plane_index, w, h);
if(same_block(lt, rt)){
block[1]= block[0];
}else{
block[1]= ptmp;
ptmp+=tmp_step;
pred_block(s, block[1], src, tmp, src_stride, src_x, src_y, b_w, b_h, rt, plane_index, w, h);
pred_block(s, block[1], tmp, src_stride, src_x, src_y, b_w, b_h, rt, plane_index, w, h);
}
if(same_block(lt, lb)){
......@@ -2566,7 +2601,7 @@ assert(src_stride > 2*MB_SIZE + 5);
}else{
block[2]= ptmp;
ptmp+=tmp_step;
pred_block(s, block[2], src, tmp, src_stride, src_x, src_y, b_w, b_h, lb, plane_index, w, h);
pred_block(s, block[2], tmp, src_stride, src_x, src_y, b_w, b_h, lb, plane_index, w, h);
}
if(same_block(lt, rb) ){
......@@ -2577,7 +2612,7 @@ assert(src_stride > 2*MB_SIZE + 5);
block[3]= block[2];
}else{
block[3]= ptmp;
pred_block(s, block[3], src, tmp, src_stride, src_x, src_y, b_w, b_h, rb, plane_index, w, h);
pred_block(s, block[3], tmp, src_stride, src_x, src_y, b_w, b_h, rb, plane_index, w, h);
}
#if 0
for(y=0; y<b_h; y++){
......@@ -2624,7 +2659,7 @@ assert(src_stride > 2*MB_SIZE + 5);
}
//FIXME name clenup (b_w, block_w, b_width stuff)
static always_inline void add_yblock(SnowContext *s, DWTELEM *dst, uint8_t *dst8, uint8_t *src, uint8_t *obmc, int src_x, int src_y, int b_w, int b_h, int w, int h, int dst_stride, int src_stride, int obmc_stride, int b_x, int b_y, int add, int offset_dst, int plane_index){
static always_inline void add_yblock(SnowContext *s, DWTELEM *dst, uint8_t *dst8, uint8_t *obmc, int src_x, int src_y, int b_w, int b_h, int w, int h, int dst_stride, int src_stride, int obmc_stride, int b_x, int b_y, int add, int offset_dst, int plane_index){
const int b_width = s->b_width << s->block_max_depth;
const int b_height= s->b_height << s->block_max_depth;
const int b_stride= b_width;
......@@ -2683,14 +2718,14 @@ assert(src_stride > 2*MB_SIZE + 5);
ptmp= tmp + 3*tmp_step;
block[0]= ptmp;
ptmp+=tmp_step;
pred_block(s, block[0], src, tmp, src_stride, src_x, src_y, b_w, b_h, lt, plane_index, w, h);
pred_block(s, block[0], tmp, src_stride, src_x, src_y, b_w, b_h, lt, plane_index, w, h);
if(same_block(lt, rt)){
block[1]= block[0];
}else{
block[1]= ptmp;
ptmp+=tmp_step;
pred_block(s, block[1], src, tmp, src_stride, src_x, src_y, b_w, b_h, rt, plane_index, w, h);
pred_block(s, block[1], tmp, src_stride, src_x, src_y, b_w, b_h, rt, plane_index, w, h);
}
if(same_block(lt, lb)){
......@@ -2700,7 +2735,7 @@ assert(src_stride > 2*MB_SIZE + 5);
}else{
block[2]= ptmp;
ptmp+=tmp_step;
pred_block(s, block[2], src, tmp, src_stride, src_x, src_y, b_w, b_h, lb, plane_index, w, h);
pred_block(s, block[2], tmp, src_stride, src_x, src_y, b_w, b_h, lb, plane_index, w, h);
}
if(same_block(lt, rb) ){
......@@ -2711,7 +2746,7 @@ assert(src_stride > 2*MB_SIZE + 5);
block[3]= block[2];
}else{
block[3]= ptmp;
pred_block(s, block[3], src, tmp, src_stride, src_x, src_y, b_w, b_h, rb, plane_index, w, h);
pred_block(s, block[3], tmp, src_stride, src_x, src_y, b_w, b_h, rb, plane_index, w, h);
}
#if 0
for(y=0; y<b_h; y++){
......@@ -2787,7 +2822,6 @@ static always_inline void predict_slice_buffered(SnowContext *s, slice_buffer *
const uint8_t *obmc = plane_index ? obmc_tab[s->block_max_depth+1] : obmc_tab[s->block_max_depth];
int obmc_stride= plane_index ? block_size : 2*block_size;
int ref_stride= s->current_picture.linesize[plane_index];
uint8_t *ref = s->last_picture.data[plane_index];
uint8_t *dst8= s->current_picture.data[plane_index];
int w= p->width;
int h= p->height;
......@@ -2830,7 +2864,7 @@ static always_inline void predict_slice_buffered(SnowContext *s, slice_buffer *
for(mb_x=0; mb_x<=mb_w; mb_x++){
START_TIMER
add_yblock_buffered(s, sb, old_buffer, dst8, ref, obmc,
add_yblock_buffered(s, sb, old_buffer, dst8, obmc,
block_w*mb_x - block_w/2,
block_w*mb_y - block_w/2,
block_w, block_w,
......@@ -2855,7 +2889,6 @@ static always_inline void predict_slice(SnowContext *s, DWTELEM *buf, int plane_
const uint8_t *obmc = plane_index ? obmc_tab[s->block_max_depth+1] : obmc_tab[s->block_max_depth];
const int obmc_stride= plane_index ? block_size : 2*block_size;
int ref_stride= s->current_picture.linesize[plane_index];
uint8_t *ref = s->last_picture.data[plane_index];
uint8_t *dst8= s->current_picture.data[plane_index];
int w= p->width;
int h= p->height;
......@@ -2888,7 +2921,7 @@ static always_inline void predict_slice(SnowContext *s, DWTELEM *buf, int plane_
for(mb_x=0; mb_x<=mb_w; mb_x++){
START_TIMER
add_yblock(s, buf, dst8, ref, obmc,
add_yblock(s, buf, dst8, obmc,
block_w*mb_x - block_w/2,
block_w*mb_y - block_w/2,
block_w, block_w,
......@@ -2918,7 +2951,6 @@ static int get_dc(SnowContext *s, int mb_x, int mb_y, int plane_index){
const uint8_t *obmc = plane_index ? obmc_tab[s->block_max_depth+1] : obmc_tab[s->block_max_depth];
const int obmc_stride= plane_index ? block_size : 2*block_size;
const int ref_stride= s->current_picture.linesize[plane_index];
uint8_t *ref= s-> last_picture.data[plane_index];
uint8_t *src= s-> input_picture.data[plane_index];
DWTELEM *dst= (DWTELEM*)s->m.obmc_scratchpad + plane_index*block_size*block_size*4;
const int b_stride = s->b_width << s->block_max_depth;
......@@ -2940,7 +2972,7 @@ static int get_dc(SnowContext *s, int mb_x, int mb_y, int plane_index){
int x= block_w*mb_x2 + block_w/2;
int y= block_w*mb_y2 + block_w/2;
add_yblock(s, dst + ((i&1)+(i>>1)*obmc_stride)*block_w, NULL, ref, obmc,
add_yblock(s, dst + ((i&1)+(i>>1)*obmc_stride)*block_w, NULL, obmc,
x, y, block_w, block_w, w, h, obmc_stride, ref_stride, obmc_stride, mb_x2, mb_y2, 0, 0, plane_index);
for(y2= FFMAX(y, 0); y2<FFMIN(h, y+block_w); y2++){
......@@ -2997,8 +3029,9 @@ static inline int get_block_bits(SnowContext *s, int x, int y, int w){
+ av_log2(2*ABS(left->color[1] - b->color[1]))
+ av_log2(2*ABS(left->color[2] - b->color[2])));
}else
return 2*(1 + av_log2(2*ABS(dmx))
+ av_log2(2*ABS(dmy))); //FIXME kill the 2* can be merged in lambda
return 2*(1 + av_log2(2*ABS(dmx)) //FIXME kill the 2* can be merged in lambda
+ av_log2(2*ABS(dmy))
+ av_log2(2*b->ref));
}
static int get_block_rd(SnowContext *s, int mb_x, int mb_y, int plane_index, const uint8_t *obmc_edged){
......@@ -3008,7 +3041,6 @@ static int get_block_rd(SnowContext *s, int mb_x, int mb_y, int plane_index, con
const uint8_t *obmc = plane_index ? obmc_tab[s->block_max_depth+1] : obmc_tab[s->block_max_depth];
const int obmc_stride= plane_index ? block_size : 2*block_size;
const int ref_stride= s->current_picture.linesize[plane_index];
uint8_t *ref= s-> last_picture.data[plane_index];
uint8_t *dst= s->current_picture.data[plane_index];
uint8_t *src= s-> input_picture.data[plane_index];
DWTELEM *pred= (DWTELEM*)s->m.obmc_scratchpad + plane_index*block_size*block_size*4;
......@@ -3029,7 +3061,7 @@ static int get_block_rd(SnowContext *s, int mb_x, int mb_y, int plane_index, con
int y1= FFMIN(block_w*2, h-sy);
int i,x,y;
pred_block(s, cur, ref, tmp, ref_stride, sx, sy, block_w*2, block_w*2, &s->block[mb_x + mb_y*b_stride], plane_index, w, h);
pred_block(s, cur, tmp, ref_stride, sx, sy, block_w*2, block_w*2, &s->block[mb_x + mb_y*b_stride], plane_index, w, h);
for(y=y0; y<y1; y++){
const uint8_t *obmc1= obmc_edged + y*obmc_stride;
......@@ -3094,7 +3126,6 @@ static int get_4block_rd(SnowContext *s, int mb_x, int mb_y, int plane_index){
const uint8_t *obmc = plane_index ? obmc_tab[s->block_max_depth+1] : obmc_tab[s->block_max_depth];
const int obmc_stride= plane_index ? block_size : 2*block_size;
const int ref_stride= s->current_picture.linesize[plane_index];
uint8_t *ref= s-> last_picture.data[plane_index];
uint8_t *dst= s->current_picture.data[plane_index];
uint8_t *src= s-> input_picture.data[plane_index];
const static DWTELEM zero_dst[4096]; //FIXME
......@@ -3112,7 +3143,7 @@ static int get_4block_rd(SnowContext *s, int mb_x, int mb_y, int plane_index){
int x= block_w*mb_x2 + block_w/2;
int y= block_w*mb_y2 + block_w/2;
add_yblock(s, zero_dst, dst, ref, obmc,
add_yblock(s, zero_dst, dst, obmc,
x, y, block_w, block_w, w, h, /*dst_stride*/0, ref_stride, obmc_stride, mb_x2, mb_y2, 1, 1, plane_index);
//FIXME find a cleaner/simpler way to skip the outside stuff
......@@ -3168,7 +3199,7 @@ static always_inline int check_block(SnowContext *s, int mb_x, int mb_y, int p[3
block->type |= BLOCK_INTRA;
}else{
index= (p[0] + 31*p[1]) & (ME_CACHE_SIZE-1);
value= s->me_cache_generation + (p[0]>>10) + (p[1]<<6);
value= s->me_cache_generation + (p[0]>>10) + (p[1]<<6) + (block->ref<<12);
if(s->me_cache[index] == value)
return 0;
s->me_cache[index]= value;
......@@ -3196,7 +3227,7 @@ static always_inline int check_block_inter(SnowContext *s, int mb_x, int mb_y, i
return check_block(s, mb_x, mb_y, p, 0, obmc_edged, best_rd);
}
static always_inline int check_4block_inter(SnowContext *s, int mb_x, int mb_y, int p0, int p1, int *best_rd){
static always_inline int check_4block_inter(SnowContext *s, int mb_x, int mb_y, int p0, int p1, int ref, int *best_rd){
const int b_stride= s->b_width << s->block_max_depth;
BlockNode *block= &s->block[mb_x + mb_y * b_stride];
BlockNode backup[4]= {block[0], block[1], block[b_stride], block[b_stride+1]};
......@@ -3207,13 +3238,14 @@ static always_inline int check_4block_inter(SnowContext *s, int mb_x, int mb_y,
assert(((mb_x|mb_y)&1) == 0);
index= (p0 + 31*p1) & (ME_CACHE_SIZE-1);
value= s->me_cache_generation + (p0>>10) + (p1<<6);
value= s->me_cache_generation + (p0>>10) + (p1<<6) + (block->ref<<12);
if(s->me_cache[index] == value)
return 0;
s->me_cache[index]= value;
block->mx= p0;
block->my= p1;
block->ref= ref;
block->type &= ~BLOCK_INTRA;
block[1]= block[b_stride]= block[b_stride+1]= *block;
......@@ -3255,9 +3287,9 @@ static void iterative_me(SnowContext *s){
for(mb_y= 0; mb_y<b_height; mb_y++){
for(mb_x= 0; mb_x<b_width; mb_x++){
int dia_change, i, j;
int best_rd= INT_MAX;
BlockNode backup;
int dia_change, i, j, ref;
int best_rd= INT_MAX, ref_rd;
BlockNode backup, ref_b;
const int index= mb_x + mb_y * b_stride;
BlockNode *block= &s->block[index];
BlockNode *tb = mb_y ? &s->block[index-b_stride ] : &null_block;
......@@ -3343,11 +3375,25 @@ static void iterative_me(SnowContext *s){
}else
check_block_inter(s, mb_x, mb_y, block->mx, block->my, *obmc_edged, &best_rd);
ref_b= *block;
ref_rd= best_rd;
for(ref=0; ref < s->ref_frames; ref++){
int16_t (*mvr)[2]= &s->ref_mvs[ref][index];
if(s->ref_scores[ref][index] > s->ref_scores[ref_b.ref][index]*3/2) //FIXME tune threshold
continue;
block->ref= ref;
best_rd= INT_MAX;
check_block_inter(s, mb_x, mb_y, mvr[0][0], mvr[0][1], *obmc_edged, &best_rd);
check_block_inter(s, mb_x, mb_y, 0, 0, *obmc_edged, &best_rd);
check_block_inter(s, mb_x, mb_y, tb->mx, tb->my, *obmc_edged, &best_rd);
check_block_inter(s, mb_x, mb_y, lb->mx, lb->my, *obmc_edged, &best_rd);
check_block_inter(s, mb_x, mb_y, rb->mx, rb->my, *obmc_edged, &best_rd);
check_block_inter(s, mb_x, mb_y, bb->mx, bb->my, *obmc_edged, &best_rd);
if(tb!=&null_block)
check_block_inter(s, mb_x, mb_y, mvr[-b_stride][0], mvr[-b_stride][1], *obmc_edged, &best_rd);
if(lb!=&null_block)
check_block_inter(s, mb_x, mb_y, mvr[-1][0], mvr[-1][1], *obmc_edged, &best_rd);
if(rb!=&null_block)
check_block_inter(s, mb_x, mb_y, mvr[1][0], mvr[1][1], *obmc_edged, &best_rd);
if(bb!=&null_block)
check_block_inter(s, mb_x, mb_y, mvr[b_stride][0], mvr[b_stride][1], *obmc_edged, &best_rd);
/* fullpel ME */
//FIXME avoid subpel interpol / round to nearest integer
......@@ -3370,6 +3416,16 @@ static void iterative_me(SnowContext *s){
dia_change |= check_block_inter(s, mb_x, mb_y, block->mx+square[i][0], block->my+square[i][1], *obmc_edged, &best_rd);
}while(dia_change);
//FIXME or try the standard 2 pass qpel or similar
mvr[0][0]= block->mx;
mvr[0][1]= block->my;
if(ref_rd > best_rd){
ref_rd= best_rd;
ref_b= *block;
}
}
best_rd= ref_rd;
*block= ref_b;
#if 1
check_block(s, mb_x, mb_y, color, 1, *obmc_edged, &best_rd);
//FIXME RD style color selection
......@@ -3416,13 +3472,14 @@ static void iterative_me(SnowContext *s){
init_rd= best_rd= get_4block_rd(s, mb_x, mb_y, 0);
//FIXME more multiref search?
check_4block_inter(s, mb_x, mb_y,
(b[0]->mx + b[1]->mx + b[2]->mx + b[3]->mx + 2) >> 2,
(b[0]->my + b[1]->my + b[2]->my + b[3]->my + 2) >> 2, &best_rd);
(b[0]->my + b[1]->my + b[2]->my + b[3]->my + 2) >> 2, 0, &best_rd);
for(i=0; i<4; i++)
if(!(b[i]->type&BLOCK_INTRA))
check_4block_inter(s, mb_x, mb_y, b[i]->mx, b[i]->my, &best_rd);
check_4block_inter(s, mb_x, mb_y, b[i]->mx, b[i]->my, b[i]->ref, &best_rd);
if(init_rd != best_rd)
change++;
......@@ -3648,6 +3705,7 @@ static void encode_header(SnowContext *s){
put_symbol(&s->c, s->header_state, s->chroma_v_shift, 0);
put_rac(&s->c, s->header_state, s->spatial_scalability);
// put_rac(&s->c, s->header_state, s->rate_scalability);
put_symbol(&s->c, s->header_state, s->max_ref_frames-1, 0);
for(plane_index=0; plane_index<2; plane_index++){
for(level=0; level<s->spatial_decomposition_count; level++){
......@@ -3689,6 +3747,7 @@ static int decode_header(SnowContext *s){
s->chroma_v_shift= get_symbol(&s->c, s->header_state, 0);
s->spatial_scalability= get_rac(&s->c, s->header_state);
// s->rate_scalability= get_rac(&s->c, s->header_state);
s->max_ref_frames= get_symbol(&s->c, s->header_state, 0)+1;
for(plane_index=0; plane_index<3; plane_index++){
for(level=0; level<s->spatial_decomposition_count; level++){
......@@ -3951,6 +4010,8 @@ static int encode_init(AVCodecContext *avctx)
s->m.obmc_scratchpad= av_mallocz(MB_SIZE*MB_SIZE*12*sizeof(uint32_t));
h263_encode_init(&s->m); //mv_penalty
s->max_ref_frames = FFMAX(FFMIN(avctx->refs, MAX_REF_FRAMES), 1);
if(avctx->flags&CODEC_FLAG_PASS1){
if(!avctx->stats_out)
avctx->stats_out = av_mallocz(256);
......@@ -3992,6 +4053,15 @@ static int encode_init(AVCodecContext *avctx)
s->avctx->get_buffer(s->avctx, &s->input_picture);
if(s->avctx->me_method == ME_ITER){
int i;
int size= s->b_width * s->b_height << 2*s->block_max_depth;
for(i=0; i<s->max_ref_frames; i++){
s->ref_mvs[i]= av_mallocz(size*sizeof(int16_t[2]));
s->ref_scores[i]= av_mallocz(size*sizeof(uint32_t));
}
}
return 0;
}
......@@ -4006,16 +4076,29 @@ static int frame_start(SnowContext *s){
draw_edges(s->current_picture.data[2], s->current_picture.linesize[2], w>>1, h>>1, EDGE_WIDTH/2);
}
tmp= s->last_picture;
s->last_picture= s->current_picture;
tmp= s->last_picture[s->max_ref_frames-1];
memmove(s->last_picture+1, s->last_picture, (s->max_ref_frames-1)*sizeof(AVFrame));
s->last_picture[0]= s->current_picture;
s->current_picture= tmp;
if(s->keyframe){
s->ref_frames= 0;
}else{
int i;
for(i=0; i<s->max_ref_frames && s->last_picture[i].data[0]; i++)
if(i && s->last_picture[i-1].key_frame)
break;
s->ref_frames= i;
}
s->current_picture.reference= 1;
if(s->avctx->get_buffer(s->avctx, &s->current_picture) < 0){
av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n");
return -1;
}
s->current_picture.key_frame= s->keyframe;
return 0;
}
......@@ -4066,7 +4149,6 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size,
}//else keep previous frame's qlog until after motion est
frame_start(s);
s->current_picture.key_frame= s->keyframe;
s->m.current_picture_ptr= &s->m.current_picture;
if(pict->pict_type == P_TYPE){
......@@ -4075,11 +4157,11 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size,
int stride= s->current_picture.linesize[0];
assert(s->current_picture.data[0]);
assert(s->last_picture.data[0]);
assert(s->last_picture[0].data[0]);
s->m.avctx= s->avctx;
s->m.current_picture.data[0]= s->current_picture.data[0];
s->m. last_picture.data[0]= s-> last_picture.data[0];
s->m. last_picture.data[0]= s->last_picture[0].data[0];
s->m. new_picture.data[0]= s-> input_picture.data[0];
s->m. last_picture_ptr= &s->m. last_picture;
s->m.linesize=
......@@ -4145,6 +4227,7 @@ redo_frame:
ff_build_rac_states(c, 0.05*(1LL<<32), 256-8);
pict->pict_type= FF_I_TYPE;
s->keyframe=1;
s->current_picture.key_frame=1;
reset_contexts(s);
goto redo_frame;
}
......@@ -4211,8 +4294,8 @@ STOP_TIMER("pred-conv")}
}
}
if(s->last_picture.data[0])
avctx->release_buffer(avctx, &s->last_picture);
if(s->last_picture[s->max_ref_frames-1].data[0])
avctx->release_buffer(avctx, &s->last_picture[s->max_ref_frames-1]);
s->current_picture.coded_picture_number = avctx->frame_number;
s->current_picture.pict_type = pict->pict_type;
......@@ -4235,7 +4318,7 @@ STOP_TIMER("pred-conv")}
}
static void common_end(SnowContext *s){
int plane_index, level, orientation;
int plane_index, level, orientation, i;
av_freep(&s->spatial_dwt_buffer);
......@@ -4246,6 +4329,13 @@ static void common_end(SnowContext *s){
av_freep(&s->block);
for(i=0; i<MAX_REF_FRAMES; i++){
av_freep(&s->ref_mvs[i]);
av_freep(&s->ref_scores[i]);
if(s->last_picture[i].data[0])
s->avctx->release_buffer(s->avctx, &s->last_picture[i]);
}
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++){
......@@ -4419,8 +4509,8 @@ STOP_TIMER("idwt + predict_slices")}
emms_c();
if(s->last_picture.data[0])
avctx->release_buffer(avctx, &s->last_picture);
if(s->last_picture[s->max_ref_frames-1].data[0])
avctx->release_buffer(avctx, &s->last_picture[s->max_ref_frames-1]);
if(!(s->avctx->debug&2048))
*picture= s->current_picture;
......
......@@ -30,6 +30,7 @@
#define QROOT (1<<QSHIFT)
#define LOSSLESS_QLOG -128
#define FRAC_BITS 8
#define MAX_REF_FRAMES 8
#define LOG2_OBMC_MAX 8
#define OBMC_MAX (1<<(LOG2_OBMC_MAX))
......
......@@ -133,12 +133,12 @@ a7ef4746f27be309138c188e327d3ebe *./data/a-ffv1.avi
2653642 ./data/a-ffv1.avi
799d3db687f6cdd7a837ec156efc171f *./data/out.yuv
stddev: 0.00 PSNR:99.99 bytes:7602176
dfe6fae9971a40378ae1c1c66d15ec52 *./data/a-snow.avi
155226 ./data/a-snow.avi
bc8dc6fe1bae64430b16ec1e1e139509 *./data/out.yuv
stddev: 23.18 PSNR:20.82 bytes:7602176
11fd61ee7e67ef7a7b2a3df973691305 *./data/a-snow53.avi
3533710 ./data/a-snow53.avi
ee3a27ccd48345f071e1617b116c76b6 *./data/a-snow.avi
154958 ./data/a-snow.avi
5310705af239bc5a427a2fa2ffb9206d *./data/out.yuv
stddev: 23.18 PSNR:20.81 bytes:7602176
ef6b08e8e122c5d29aa7af9259098d3e *./data/a-snow53.avi
3533712 ./data/a-snow53.avi
799d3db687f6cdd7a837ec156efc171f *./data/out.yuv
stddev: 0.00 PSNR:99.99 bytes:7602176
85529d9838c5a8aef041445fa8ef3c85 *./data/a-dv.dv
......
......@@ -133,11 +133,11 @@ d0831a8339491fd680b650f05262e5d9 *./data/a-ffv1.avi
3524768 ./data/a-ffv1.avi
dde5895817ad9d219f79a52d0bdfb001 *./data/out.yuv
stddev: 0.00 PSNR:99.99 bytes:7602176
d65c40a7d53f828a6c16eaef637d466f *./data/a-snow.avi
68060 ./data/a-snow.avi
a7d48185f56d612b2f19b9e52640d102 *./data/out.yuv
stddev: 10.93 PSNR:27.34 bytes:7602176
3f20642bb789dfb75ae3e8c03f9b425c *./data/a-snow53.avi
64812de848ca5eec1931bce8299ed6a1 *./data/a-snow.avi
68024 ./data/a-snow.avi
146f2c37d861f542bfb635e05be160e9 *./data/out.yuv
stddev: 10.94 PSNR:27.34 bytes:7602176
1b4d88af4c8c1ac3fd092de0a69d5023 *./data/a-snow53.avi
2725570 ./data/a-snow53.avi
dde5895817ad9d219f79a52d0bdfb001 *./data/out.yuv
stddev: 0.00 PSNR:99.99 bytes:7602176
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment