yading@10: /* yading@10: * Copyright (C) 2004 Michael Niedermayer yading@10: * yading@10: * This file is part of FFmpeg. yading@10: * yading@10: * FFmpeg is free software; you can redistribute it and/or yading@10: * modify it under the terms of the GNU Lesser General Public yading@10: * License as published by the Free Software Foundation; either yading@10: * version 2.1 of the License, or (at your option) any later version. yading@10: * yading@10: * FFmpeg is distributed in the hope that it will be useful, yading@10: * but WITHOUT ANY WARRANTY; without even the implied warranty of yading@10: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU yading@10: * Lesser General Public License for more details. yading@10: * yading@10: * You should have received a copy of the GNU Lesser General Public yading@10: * License along with FFmpeg; if not, write to the Free Software yading@10: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA yading@10: */ yading@10: yading@10: #include "libavutil/intmath.h" yading@10: #include "libavutil/log.h" yading@10: #include "libavutil/opt.h" yading@10: #include "avcodec.h" yading@10: #include "internal.h" yading@10: #include "dsputil.h" yading@10: #include "internal.h" yading@10: #include "snow_dwt.h" yading@10: #include "snow.h" yading@10: yading@10: #include "rangecoder.h" yading@10: #include "mathops.h" yading@10: yading@10: #include "mpegvideo.h" yading@10: #include "h263.h" yading@10: yading@10: #undef NDEBUG yading@10: #include yading@10: yading@10: #define QUANTIZE2 0 yading@10: yading@10: #if QUANTIZE2==1 yading@10: #define Q2_STEP 8 yading@10: yading@10: static void find_sse(SnowContext *s, Plane *p, int *score, int score_stride, IDWTELEM *r0, IDWTELEM *r1, int level, int orientation){ yading@10: SubBand *b= &p->band[level][orientation]; yading@10: int x, y; yading@10: int xo=0; yading@10: int yo=0; yading@10: int step= 1 << (s->spatial_decomposition_count - level); yading@10: yading@10: if(orientation&1) yading@10: xo= step>>1; yading@10: if(orientation&2) yading@10: yo= step>>1; yading@10: yading@10: //FIXME bias for nonzero ? yading@10: //FIXME optimize yading@10: memset(score, 0, sizeof(*score)*score_stride*((p->height + Q2_STEP-1)/Q2_STEP)); yading@10: for(y=0; yheight; y++){ yading@10: for(x=0; xwidth; x++){ yading@10: int sx= (x-xo + step/2) / step / Q2_STEP; yading@10: int sy= (y-yo + step/2) / step / Q2_STEP; yading@10: int v= r0[x + y*p->width] - r1[x + y*p->width]; yading@10: assert(sx>=0 && sy>=0 && sx < score_stride); yading@10: v= ((v+8)>>4)<<4; yading@10: score[sx + sy*score_stride] += v*v; yading@10: assert(score[sx + sy*score_stride] >= 0); yading@10: } yading@10: } yading@10: } yading@10: yading@10: static void dequantize_all(SnowContext *s, Plane *p, IDWTELEM *buffer, int width, int height){ yading@10: int level, orientation; yading@10: yading@10: for(level=0; levelspatial_decomposition_count; level++){ yading@10: for(orientation=level ? 1 : 0; orientation<4; orientation++){ yading@10: SubBand *b= &p->band[level][orientation]; yading@10: IDWTELEM *dst= buffer + (b->ibuf - s->spatial_idwt_buffer); yading@10: yading@10: dequantize(s, b, dst, b->stride); yading@10: } yading@10: } yading@10: } yading@10: yading@10: static void dwt_quantize(SnowContext *s, Plane *p, DWTELEM *buffer, int width, int height, int stride, int type){ yading@10: int level, orientation, ys, xs, x, y, pass; yading@10: IDWTELEM best_dequant[height * stride]; yading@10: IDWTELEM idwt2_buffer[height * stride]; yading@10: const int score_stride= (width + 10)/Q2_STEP; yading@10: int best_score[(width + 10)/Q2_STEP * (height + 10)/Q2_STEP]; //FIXME size yading@10: int score[(width + 10)/Q2_STEP * (height + 10)/Q2_STEP]; //FIXME size yading@10: int threshold= (s->m.lambda * s->m.lambda) >> 6; yading@10: yading@10: //FIXME pass the copy cleanly ? yading@10: yading@10: // memcpy(dwt_buffer, buffer, height * stride * sizeof(DWTELEM)); yading@10: ff_spatial_dwt(buffer, s->temp_dwt_buffer, width, height, stride, type, s->spatial_decomposition_count); yading@10: yading@10: for(level=0; levelspatial_decomposition_count; level++){ yading@10: for(orientation=level ? 1 : 0; orientation<4; orientation++){ yading@10: SubBand *b= &p->band[level][orientation]; yading@10: IDWTELEM *dst= best_dequant + (b->ibuf - s->spatial_idwt_buffer); yading@10: DWTELEM *src= buffer + (b-> buf - s->spatial_dwt_buffer); yading@10: assert(src == b->buf); // code does not depend on this but it is true currently yading@10: yading@10: quantize(s, b, dst, src, b->stride, s->qbias); yading@10: } yading@10: } yading@10: for(pass=0; pass<1; pass++){ yading@10: if(s->qbias == 0) //keyframe yading@10: continue; yading@10: for(level=0; levelspatial_decomposition_count; level++){ yading@10: for(orientation=level ? 1 : 0; orientation<4; orientation++){ yading@10: SubBand *b= &p->band[level][orientation]; yading@10: IDWTELEM *dst= idwt2_buffer + (b->ibuf - s->spatial_idwt_buffer); yading@10: IDWTELEM *best_dst= best_dequant + (b->ibuf - s->spatial_idwt_buffer); yading@10: yading@10: for(ys= 0; ystemp_idwt_buffer, width, height, stride, type, s->spatial_decomposition_count); yading@10: find_sse(s, p, best_score, score_stride, idwt2_buffer, s->spatial_idwt_buffer, level, orientation); yading@10: memcpy(idwt2_buffer, best_dequant, height * stride * sizeof(IDWTELEM)); yading@10: for(y=ys; yheight; y+= Q2_STEP){ yading@10: for(x=xs; xwidth; x+= Q2_STEP){ yading@10: if(dst[x + y*b->stride]<0) dst[x + y*b->stride]++; yading@10: if(dst[x + y*b->stride]>0) dst[x + y*b->stride]--; yading@10: //FIXME try more than just -- yading@10: } yading@10: } yading@10: dequantize_all(s, p, idwt2_buffer, width, height); yading@10: ff_spatial_idwt(idwt2_buffer, s->temp_idwt_buffer, width, height, stride, type, s->spatial_decomposition_count); yading@10: find_sse(s, p, score, score_stride, idwt2_buffer, s->spatial_idwt_buffer, level, orientation); yading@10: for(y=ys; yheight; y+= Q2_STEP){ yading@10: for(x=xs; xwidth; x+= Q2_STEP){ yading@10: int score_idx= x/Q2_STEP + (y/Q2_STEP)*score_stride; yading@10: if(score[score_idx] <= best_score[score_idx] + threshold){ yading@10: best_score[score_idx]= score[score_idx]; yading@10: if(best_dst[x + y*b->stride]<0) best_dst[x + y*b->stride]++; yading@10: if(best_dst[x + y*b->stride]>0) best_dst[x + y*b->stride]--; yading@10: //FIXME copy instead yading@10: } yading@10: } yading@10: } yading@10: } yading@10: } yading@10: } yading@10: } yading@10: } yading@10: memcpy(s->spatial_idwt_buffer, best_dequant, height * stride * sizeof(IDWTELEM)); //FIXME work with that directly instead of copy at the end yading@10: } yading@10: yading@10: #endif /* QUANTIZE2==1 */ yading@10: yading@10: static av_cold int encode_init(AVCodecContext *avctx) yading@10: { yading@10: SnowContext *s = avctx->priv_data; yading@10: int plane_index, ret; yading@10: yading@10: if(avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL){ yading@10: av_log(avctx, AV_LOG_ERROR, "This codec is under development, files encoded with it may not be decodable with future versions!!!\n" yading@10: "Use vstrict=-2 / -strict -2 to use it anyway.\n"); yading@10: return -1; yading@10: } yading@10: yading@10: if(avctx->prediction_method == DWT_97 yading@10: && (avctx->flags & CODEC_FLAG_QSCALE) yading@10: && avctx->global_quality == 0){ yading@10: av_log(avctx, AV_LOG_ERROR, "The 9/7 wavelet is incompatible with lossless mode.\n"); yading@10: return -1; yading@10: } yading@10: yading@10: s->spatial_decomposition_type= avctx->prediction_method; //FIXME add decorrelator type r transform_type yading@10: yading@10: s->mv_scale = (avctx->flags & CODEC_FLAG_QPEL) ? 2 : 4; yading@10: s->block_max_depth= (avctx->flags & CODEC_FLAG_4MV ) ? 1 : 0; yading@10: yading@10: for(plane_index=0; plane_index<3; plane_index++){ yading@10: s->plane[plane_index].diag_mc= 1; yading@10: s->plane[plane_index].htaps= 6; yading@10: s->plane[plane_index].hcoeff[0]= 40; yading@10: s->plane[plane_index].hcoeff[1]= -10; yading@10: s->plane[plane_index].hcoeff[2]= 2; yading@10: s->plane[plane_index].fast_mc= 1; yading@10: } yading@10: yading@10: if ((ret = ff_snow_common_init(avctx)) < 0) { yading@10: ff_snow_common_end(avctx->priv_data); yading@10: return ret; yading@10: } yading@10: ff_snow_alloc_blocks(s); yading@10: yading@10: s->version=0; yading@10: yading@10: s->m.avctx = avctx; yading@10: s->m.flags = avctx->flags; yading@10: s->m.bit_rate= avctx->bit_rate; yading@10: yading@10: s->m.me.temp = yading@10: s->m.me.scratchpad= av_mallocz((avctx->width+64)*2*16*2*sizeof(uint8_t)); yading@10: s->m.me.map = av_mallocz(ME_MAP_SIZE*sizeof(uint32_t)); yading@10: s->m.me.score_map = av_mallocz(ME_MAP_SIZE*sizeof(uint32_t)); yading@10: s->m.obmc_scratchpad= av_mallocz(MB_SIZE*MB_SIZE*12*sizeof(uint32_t)); yading@10: ff_h263_encode_init(&s->m); //mv_penalty yading@10: yading@10: s->max_ref_frames = FFMAX(FFMIN(avctx->refs, MAX_REF_FRAMES), 1); yading@10: yading@10: if(avctx->flags&CODEC_FLAG_PASS1){ yading@10: if(!avctx->stats_out) yading@10: avctx->stats_out = av_mallocz(256); yading@10: } yading@10: if((avctx->flags&CODEC_FLAG_PASS2) || !(avctx->flags&CODEC_FLAG_QSCALE)){ yading@10: if(ff_rate_control_init(&s->m) < 0) yading@10: return -1; yading@10: } yading@10: s->pass1_rc= !(avctx->flags & (CODEC_FLAG_QSCALE|CODEC_FLAG_PASS2)); yading@10: yading@10: avctx->coded_frame= &s->current_picture; yading@10: switch(avctx->pix_fmt){ yading@10: case AV_PIX_FMT_YUV444P: yading@10: // case AV_PIX_FMT_YUV422P: yading@10: case AV_PIX_FMT_YUV420P: yading@10: // case AV_PIX_FMT_GRAY8: yading@10: // case AV_PIX_FMT_YUV411P: yading@10: case AV_PIX_FMT_YUV410P: yading@10: s->colorspace_type= 0; yading@10: break; yading@10: /* case AV_PIX_FMT_RGB32: yading@10: s->colorspace= 1; yading@10: break;*/ yading@10: default: yading@10: av_log(avctx, AV_LOG_ERROR, "pixel format not supported\n"); yading@10: return -1; yading@10: } yading@10: avcodec_get_chroma_sub_sample(avctx->pix_fmt, &s->chroma_h_shift, &s->chroma_v_shift); yading@10: yading@10: ff_set_cmp(&s->dsp, s->dsp.me_cmp, s->avctx->me_cmp); yading@10: ff_set_cmp(&s->dsp, s->dsp.me_sub_cmp, s->avctx->me_sub_cmp); yading@10: yading@10: if ((ret = ff_get_buffer(s->avctx, &s->input_picture, AV_GET_BUFFER_FLAG_REF)) < 0) yading@10: return ret; yading@10: yading@10: if(s->avctx->me_method == ME_ITER){ yading@10: int i; yading@10: int size= s->b_width * s->b_height << 2*s->block_max_depth; yading@10: for(i=0; imax_ref_frames; i++){ yading@10: s->ref_mvs[i]= av_mallocz(size*sizeof(int16_t[2])); yading@10: s->ref_scores[i]= av_mallocz(size*sizeof(uint32_t)); yading@10: } yading@10: } yading@10: yading@10: return 0; yading@10: } yading@10: yading@10: //near copy & paste from dsputil, FIXME yading@10: static int pix_sum(uint8_t * pix, int line_size, int w, int h) yading@10: { yading@10: int s, i, j; yading@10: yading@10: s = 0; yading@10: for (i = 0; i < h; i++) { yading@10: for (j = 0; j < w; j++) { yading@10: s += pix[0]; yading@10: pix ++; yading@10: } yading@10: pix += line_size - w; yading@10: } yading@10: return s; yading@10: } yading@10: yading@10: //near copy & paste from dsputil, FIXME yading@10: static int pix_norm1(uint8_t * pix, int line_size, int w) yading@10: { yading@10: int s, i, j; yading@10: uint32_t *sq = ff_squareTbl + 256; yading@10: yading@10: s = 0; yading@10: for (i = 0; i < w; i++) { yading@10: for (j = 0; j < w; j ++) { yading@10: s += sq[pix[0]]; yading@10: pix ++; yading@10: } yading@10: pix += line_size - w; yading@10: } yading@10: return s; yading@10: } yading@10: yading@10: static inline int get_penalty_factor(int lambda, int lambda2, int type){ yading@10: switch(type&0xFF){ yading@10: default: yading@10: case FF_CMP_SAD: yading@10: return lambda>>FF_LAMBDA_SHIFT; yading@10: case FF_CMP_DCT: yading@10: return (3*lambda)>>(FF_LAMBDA_SHIFT+1); yading@10: case FF_CMP_W53: yading@10: return (4*lambda)>>(FF_LAMBDA_SHIFT); yading@10: case FF_CMP_W97: yading@10: return (2*lambda)>>(FF_LAMBDA_SHIFT); yading@10: case FF_CMP_SATD: yading@10: case FF_CMP_DCT264: yading@10: return (2*lambda)>>FF_LAMBDA_SHIFT; yading@10: case FF_CMP_RD: yading@10: case FF_CMP_PSNR: yading@10: case FF_CMP_SSE: yading@10: case FF_CMP_NSSE: yading@10: return lambda2>>FF_LAMBDA_SHIFT; yading@10: case FF_CMP_BIT: yading@10: return 1; yading@10: } yading@10: } yading@10: yading@10: //FIXME copy&paste yading@10: #define P_LEFT P[1] yading@10: #define P_TOP P[2] yading@10: #define P_TOPRIGHT P[3] yading@10: #define P_MEDIAN P[4] yading@10: #define P_MV1 P[9] yading@10: #define FLAG_QPEL 1 //must be 1 yading@10: yading@10: static int encode_q_branch(SnowContext *s, int level, int x, int y){ yading@10: uint8_t p_buffer[1024]; yading@10: uint8_t i_buffer[1024]; yading@10: uint8_t p_state[sizeof(s->block_state)]; yading@10: uint8_t i_state[sizeof(s->block_state)]; yading@10: RangeCoder pc, ic; yading@10: uint8_t *pbbak= s->c.bytestream; yading@10: uint8_t *pbbak_start= s->c.bytestream_start; yading@10: int score, score2, iscore, i_len, p_len, block_s, sum, base_bits; yading@10: const int w= s->b_width << s->block_max_depth; yading@10: const int h= s->b_height << s->block_max_depth; yading@10: const int rem_depth= s->block_max_depth - level; yading@10: const int index= (x + y*w) << rem_depth; yading@10: const int block_w= 1<<(LOG2_MB_SIZE - level); yading@10: int trx= (x+1)<block[index-1] : &null_block; yading@10: const BlockNode *top = y ? &s->block[index-w] : &null_block; yading@10: const BlockNode *right = trxblock[index+1] : &null_block; yading@10: const BlockNode *bottom= tryblock[index+w] : &null_block; yading@10: const BlockNode *tl = y && x ? &s->block[index-w-1] : left; yading@10: const BlockNode *tr = y && trxblock[index-w+(1<color[0]; yading@10: int pcb= left->color[1]; yading@10: int pcr= left->color[2]; yading@10: int pmx, pmy; yading@10: int mx=0, my=0; yading@10: int l,cr,cb; yading@10: const int stride= s->current_picture.linesize[0]; yading@10: const int uvstride= s->current_picture.linesize[1]; yading@10: uint8_t *current_data[3]= { s->input_picture.data[0] + (x + y* stride)*block_w, yading@10: s->input_picture.data[1] + ((x*block_w)>>s->chroma_h_shift) + ((y*uvstride*block_w)>>s->chroma_v_shift), yading@10: s->input_picture.data[2] + ((x*block_w)>>s->chroma_h_shift) + ((y*uvstride*block_w)>>s->chroma_v_shift)}; yading@10: int P[10][2]; yading@10: int16_t last_mv[3][2]; yading@10: int qpel= !!(s->avctx->flags & CODEC_FLAG_QPEL); //unused yading@10: const int shift= 1+qpel; yading@10: MotionEstContext *c= &s->m.me; yading@10: int ref_context= av_log2(2*left->ref) + av_log2(2*top->ref); yading@10: int mx_context= av_log2(2*FFABS(left->mx - top->mx)); yading@10: int my_context= av_log2(2*FFABS(left->my - top->my)); yading@10: int s_context= 2*left->level + 2*top->level + tl->level + tr->level; yading@10: int ref, best_ref, ref_score, ref_mx, ref_my; yading@10: yading@10: assert(sizeof(s->block_state) >= 256); yading@10: if(s->keyframe){ yading@10: set_blocks(s, level, x, y, pl, pcb, pcr, 0, 0, 0, BLOCK_INTRA); yading@10: return 0; yading@10: } yading@10: yading@10: // clip predictors / edge ? yading@10: yading@10: P_LEFT[0]= left->mx; yading@10: P_LEFT[1]= left->my; yading@10: P_TOP [0]= top->mx; yading@10: P_TOP [1]= top->my; yading@10: P_TOPRIGHT[0]= tr->mx; yading@10: P_TOPRIGHT[1]= tr->my; yading@10: yading@10: last_mv[0][0]= s->block[index].mx; yading@10: last_mv[0][1]= s->block[index].my; yading@10: last_mv[1][0]= right->mx; yading@10: last_mv[1][1]= right->my; yading@10: last_mv[2][0]= bottom->mx; yading@10: last_mv[2][1]= bottom->my; yading@10: yading@10: s->m.mb_stride=2; yading@10: s->m.mb_x= yading@10: s->m.mb_y= 0; yading@10: c->skip= 0; yading@10: yading@10: assert(c-> stride == stride); yading@10: assert(c->uvstride == uvstride); yading@10: yading@10: c->penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_cmp); yading@10: c->sub_penalty_factor= get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_sub_cmp); yading@10: c->mb_penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->mb_cmp); yading@10: c->current_mv_penalty= c->mv_penalty[s->m.f_code=1] + MAX_MV; yading@10: yading@10: c->xmin = - x*block_w - 16+3; yading@10: c->ymin = - y*block_w - 16+3; yading@10: c->xmax = - (x+1)*block_w + (w<<(LOG2_MB_SIZE - s->block_max_depth)) + 16-3; yading@10: c->ymax = - (y+1)*block_w + (h<<(LOG2_MB_SIZE - s->block_max_depth)) + 16-3; yading@10: yading@10: if(P_LEFT[0] > (c->xmax<xmax< (c->ymax<ymax< (c->xmax<xmax< (c->ymax<ymax<xmin<xmin< (c->xmax<xmax< (c->ymax<ymax<pred_x= P_LEFT[0]; yading@10: c->pred_y= P_LEFT[1]; yading@10: } else { yading@10: c->pred_x = P_MEDIAN[0]; yading@10: c->pred_y = P_MEDIAN[1]; yading@10: } yading@10: yading@10: score= INT_MAX; yading@10: best_ref= 0; yading@10: for(ref=0; refref_frames; ref++){ yading@10: init_ref(c, current_data, s->last_picture[ref].data, NULL, block_w*x, block_w*y, 0); yading@10: yading@10: ref_score= ff_epzs_motion_search(&s->m, &ref_mx, &ref_my, P, 0, /*ref_index*/ 0, last_mv, yading@10: (1<<16)>>shift, level-LOG2_MB_SIZE+4, block_w); yading@10: yading@10: assert(ref_mx >= c->xmin); yading@10: assert(ref_mx <= c->xmax); yading@10: assert(ref_my >= c->ymin); yading@10: assert(ref_my <= c->ymax); yading@10: yading@10: ref_score= c->sub_motion_search(&s->m, &ref_mx, &ref_my, ref_score, 0, 0, level-LOG2_MB_SIZE+4, block_w); yading@10: ref_score= ff_get_mb_score(&s->m, ref_mx, ref_my, 0, 0, level-LOG2_MB_SIZE+4, block_w, 0); yading@10: ref_score+= 2*av_log2(2*ref)*c->penalty_factor; yading@10: if(s->ref_mvs[ref]){ yading@10: s->ref_mvs[ref][index][0]= ref_mx; yading@10: s->ref_mvs[ref][index][1]= ref_my; yading@10: s->ref_scores[ref][index]= ref_score; yading@10: } yading@10: if(score > ref_score){ yading@10: score= ref_score; yading@10: best_ref= ref; yading@10: mx= ref_mx; yading@10: my= ref_my; yading@10: } yading@10: } yading@10: //FIXME if mb_cmp != SSE then intra cannot be compared currently and mb_penalty vs. lambda2 yading@10: yading@10: // subpel search yading@10: base_bits= get_rac_count(&s->c) - 8*(s->c.bytestream - s->c.bytestream_start); yading@10: pc= s->c; yading@10: pc.bytestream_start= yading@10: pc.bytestream= p_buffer; //FIXME end/start? and at the other stoo yading@10: memcpy(p_state, s->block_state, sizeof(s->block_state)); yading@10: yading@10: if(level!=s->block_max_depth) yading@10: put_rac(&pc, &p_state[4 + s_context], 1); yading@10: put_rac(&pc, &p_state[1 + left->type + top->type], 0); yading@10: if(s->ref_frames > 1) yading@10: put_symbol(&pc, &p_state[128 + 1024 + 32*ref_context], best_ref, 0); yading@10: pred_mv(s, &pmx, &pmy, best_ref, left, top, tr); yading@10: put_symbol(&pc, &p_state[128 + 32*(mx_context + 16*!!best_ref)], mx - pmx, 1); yading@10: put_symbol(&pc, &p_state[128 + 32*(my_context + 16*!!best_ref)], my - pmy, 1); yading@10: p_len= pc.bytestream - pc.bytestream_start; yading@10: score += (s->lambda2*(get_rac_count(&pc)-base_bits))>>FF_LAMBDA_SHIFT; yading@10: yading@10: block_s= block_w*block_w; yading@10: sum = pix_sum(current_data[0], stride, block_w, block_w); yading@10: l= (sum + block_s/2)/block_s; yading@10: iscore = pix_norm1(current_data[0], stride, block_w) - 2*l*sum + l*l*block_s; yading@10: yading@10: block_s= block_w*block_w>>(s->chroma_h_shift + s->chroma_v_shift); yading@10: sum = pix_sum(current_data[1], uvstride, block_w>>s->chroma_h_shift, block_w>>s->chroma_v_shift); yading@10: cb= (sum + block_s/2)/block_s; yading@10: // iscore += pix_norm1(¤t_mb[1][0], uvstride, block_w>>1) - 2*cb*sum + cb*cb*block_s; yading@10: sum = pix_sum(current_data[2], uvstride, block_w>>s->chroma_h_shift, block_w>>s->chroma_v_shift); yading@10: cr= (sum + block_s/2)/block_s; yading@10: // iscore += pix_norm1(¤t_mb[2][0], uvstride, block_w>>1) - 2*cr*sum + cr*cr*block_s; yading@10: yading@10: ic= s->c; yading@10: ic.bytestream_start= yading@10: ic.bytestream= i_buffer; //FIXME end/start? and at the other stoo yading@10: memcpy(i_state, s->block_state, sizeof(s->block_state)); yading@10: if(level!=s->block_max_depth) yading@10: put_rac(&ic, &i_state[4 + s_context], 1); yading@10: put_rac(&ic, &i_state[1 + left->type + top->type], 1); yading@10: put_symbol(&ic, &i_state[32], l-pl , 1); yading@10: put_symbol(&ic, &i_state[64], cb-pcb, 1); yading@10: put_symbol(&ic, &i_state[96], cr-pcr, 1); yading@10: i_len= ic.bytestream - ic.bytestream_start; yading@10: iscore += (s->lambda2*(get_rac_count(&ic)-base_bits))>>FF_LAMBDA_SHIFT; yading@10: yading@10: // assert(score==256*256*256*64-1); yading@10: assert(iscore < 255*255*256 + s->lambda2*10); yading@10: assert(iscore >= 0); yading@10: assert(l>=0 && l<=255); yading@10: assert(pl>=0 && pl<=255); yading@10: yading@10: if(level==0){ yading@10: int varc= iscore >> 8; yading@10: int vard= score >> 8; yading@10: if (vard <= 64 || vard < varc) yading@10: c->scene_change_score+= ff_sqrt(vard) - ff_sqrt(varc); yading@10: else yading@10: c->scene_change_score+= s->m.qscale; yading@10: } yading@10: yading@10: if(level!=s->block_max_depth){ yading@10: put_rac(&s->c, &s->block_state[4 + s_context], 0); yading@10: score2 = encode_q_branch(s, level+1, 2*x+0, 2*y+0); yading@10: score2+= encode_q_branch(s, level+1, 2*x+1, 2*y+0); yading@10: score2+= encode_q_branch(s, level+1, 2*x+0, 2*y+1); yading@10: score2+= encode_q_branch(s, level+1, 2*x+1, 2*y+1); yading@10: score2+= s->lambda2>>FF_LAMBDA_SHIFT; //FIXME exact split overhead yading@10: yading@10: if(score2 < score && score2 < iscore) yading@10: return score2; yading@10: } yading@10: yading@10: if(iscore < score){ yading@10: pred_mv(s, &pmx, &pmy, 0, left, top, tr); yading@10: memcpy(pbbak, i_buffer, i_len); yading@10: s->c= ic; yading@10: s->c.bytestream_start= pbbak_start; yading@10: s->c.bytestream= pbbak + i_len; yading@10: set_blocks(s, level, x, y, l, cb, cr, pmx, pmy, 0, BLOCK_INTRA); yading@10: memcpy(s->block_state, i_state, sizeof(s->block_state)); yading@10: return iscore; yading@10: }else{ yading@10: memcpy(pbbak, p_buffer, p_len); yading@10: s->c= pc; yading@10: s->c.bytestream_start= pbbak_start; yading@10: s->c.bytestream= pbbak + p_len; yading@10: set_blocks(s, level, x, y, pl, pcb, pcr, mx, my, best_ref, 0); yading@10: memcpy(s->block_state, p_state, sizeof(s->block_state)); yading@10: return score; yading@10: } yading@10: } yading@10: yading@10: static void encode_q_branch2(SnowContext *s, int level, int x, int y){ yading@10: const int w= s->b_width << s->block_max_depth; yading@10: const int rem_depth= s->block_max_depth - level; yading@10: const int index= (x + y*w) << rem_depth; yading@10: int trx= (x+1)<block[index]; yading@10: const BlockNode *left = x ? &s->block[index-1] : &null_block; yading@10: const BlockNode *top = y ? &s->block[index-w] : &null_block; yading@10: const BlockNode *tl = y && x ? &s->block[index-w-1] : left; yading@10: const BlockNode *tr = y && trxblock[index-w+(1<color[0]; yading@10: int pcb= left->color[1]; yading@10: int pcr= left->color[2]; yading@10: int pmx, pmy; yading@10: int ref_context= av_log2(2*left->ref) + av_log2(2*top->ref); yading@10: int mx_context= av_log2(2*FFABS(left->mx - top->mx)) + 16*!!b->ref; yading@10: int my_context= av_log2(2*FFABS(left->my - top->my)) + 16*!!b->ref; yading@10: int s_context= 2*left->level + 2*top->level + tl->level + tr->level; yading@10: yading@10: if(s->keyframe){ yading@10: set_blocks(s, level, x, y, pl, pcb, pcr, 0, 0, 0, BLOCK_INTRA); yading@10: return; yading@10: } yading@10: yading@10: if(level!=s->block_max_depth){ yading@10: if(same_block(b,b+1) && same_block(b,b+w) && same_block(b,b+w+1)){ yading@10: put_rac(&s->c, &s->block_state[4 + s_context], 1); yading@10: }else{ yading@10: put_rac(&s->c, &s->block_state[4 + s_context], 0); yading@10: encode_q_branch2(s, level+1, 2*x+0, 2*y+0); yading@10: encode_q_branch2(s, level+1, 2*x+1, 2*y+0); yading@10: encode_q_branch2(s, level+1, 2*x+0, 2*y+1); yading@10: encode_q_branch2(s, level+1, 2*x+1, 2*y+1); yading@10: return; yading@10: } yading@10: } yading@10: if(b->type & BLOCK_INTRA){ yading@10: pred_mv(s, &pmx, &pmy, 0, left, top, tr); yading@10: put_rac(&s->c, &s->block_state[1 + (left->type&1) + (top->type&1)], 1); yading@10: put_symbol(&s->c, &s->block_state[32], b->color[0]-pl , 1); yading@10: put_symbol(&s->c, &s->block_state[64], b->color[1]-pcb, 1); yading@10: put_symbol(&s->c, &s->block_state[96], b->color[2]-pcr, 1); yading@10: set_blocks(s, level, x, y, b->color[0], b->color[1], b->color[2], pmx, pmy, 0, BLOCK_INTRA); yading@10: }else{ yading@10: pred_mv(s, &pmx, &pmy, b->ref, left, top, tr); yading@10: put_rac(&s->c, &s->block_state[1 + (left->type&1) + (top->type&1)], 0); yading@10: if(s->ref_frames > 1) yading@10: put_symbol(&s->c, &s->block_state[128 + 1024 + 32*ref_context], b->ref, 0); yading@10: put_symbol(&s->c, &s->block_state[128 + 32*mx_context], b->mx - pmx, 1); yading@10: put_symbol(&s->c, &s->block_state[128 + 32*my_context], b->my - pmy, 1); yading@10: set_blocks(s, level, x, y, pl, pcb, pcr, b->mx, b->my, b->ref, 0); yading@10: } yading@10: } yading@10: yading@10: static int get_dc(SnowContext *s, int mb_x, int mb_y, int plane_index){ yading@10: int i, x2, y2; yading@10: Plane *p= &s->plane[plane_index]; yading@10: const int block_size = MB_SIZE >> s->block_max_depth; yading@10: const int block_w = plane_index ? block_size>>s->chroma_h_shift : block_size; yading@10: const int block_h = plane_index ? block_size>>s->chroma_v_shift : block_size; yading@10: const uint8_t *obmc = plane_index ? ff_obmc_tab[s->block_max_depth+s->chroma_h_shift] : ff_obmc_tab[s->block_max_depth]; yading@10: const int obmc_stride= plane_index ? (2*block_size)>>s->chroma_h_shift : 2*block_size; yading@10: const int ref_stride= s->current_picture.linesize[plane_index]; yading@10: uint8_t *src= s-> input_picture.data[plane_index]; yading@10: IDWTELEM *dst= (IDWTELEM*)s->m.obmc_scratchpad + plane_index*block_size*block_size*4; //FIXME change to unsigned yading@10: const int b_stride = s->b_width << s->block_max_depth; yading@10: const int w= p->width; yading@10: const int h= p->height; yading@10: int index= mb_x + mb_y*b_stride; yading@10: BlockNode *b= &s->block[index]; yading@10: BlockNode backup= *b; yading@10: int ab=0; yading@10: int aa=0; yading@10: yading@10: av_assert2(s->chroma_h_shift == s->chroma_v_shift); //obmc stuff above yading@10: yading@10: b->type|= BLOCK_INTRA; yading@10: b->color[plane_index]= 0; yading@10: memset(dst, 0, obmc_stride*obmc_stride*sizeof(IDWTELEM)); yading@10: yading@10: for(i=0; i<4; i++){ yading@10: int mb_x2= mb_x + (i &1) - 1; yading@10: int mb_y2= mb_y + (i>>1) - 1; yading@10: int x= block_w*mb_x2 + block_w/2; yading@10: int y= block_h*mb_y2 + block_h/2; yading@10: yading@10: add_yblock(s, 0, NULL, dst + (i&1)*block_w + (i>>1)*obmc_stride*block_h, NULL, obmc, yading@10: x, y, block_w, block_h, w, h, obmc_stride, ref_stride, obmc_stride, mb_x2, mb_y2, 0, 0, plane_index); yading@10: yading@10: for(y2= FFMAX(y, 0); y2h) obmc_v += obmc[index - block_h*obmc_stride]; yading@10: if(x+block_w>w) obmc_v += obmc[index - block_w]; yading@10: //FIXME precalculate this or simplify it somehow else yading@10: yading@10: d = -dst[index] + (1<<(FRAC_BITS-1)); yading@10: dst[index] = d; yading@10: ab += (src[x2 + y2*ref_stride] - (d>>FRAC_BITS)) * obmc_v; yading@10: aa += obmc_v * obmc_v; //FIXME precalculate this yading@10: } yading@10: } yading@10: } yading@10: *b= backup; yading@10: yading@10: return av_clip( ROUNDED_DIV(ab<b_width << s->block_max_depth; yading@10: const int b_height = s->b_height<< s->block_max_depth; yading@10: int index= x + y*b_stride; yading@10: const BlockNode *b = &s->block[index]; yading@10: const BlockNode *left = x ? &s->block[index-1] : &null_block; yading@10: const BlockNode *top = y ? &s->block[index-b_stride] : &null_block; yading@10: const BlockNode *tl = y && x ? &s->block[index-b_stride-1] : left; yading@10: const BlockNode *tr = y && x+wblock[index-b_stride+w] : tl; yading@10: int dmx, dmy; yading@10: // int mx_context= av_log2(2*FFABS(left->mx - top->mx)); yading@10: // int my_context= av_log2(2*FFABS(left->my - top->my)); yading@10: yading@10: if(x<0 || x>=b_stride || y>=b_height) yading@10: return 0; yading@10: /* yading@10: 1 0 0 yading@10: 01X 1-2 1 yading@10: 001XX 3-6 2-3 yading@10: 0001XXX 7-14 4-7 yading@10: 00001XXXX 15-30 8-15 yading@10: */ yading@10: //FIXME try accurate rate yading@10: //FIXME intra and inter predictors if surrounding blocks are not the same type yading@10: if(b->type & BLOCK_INTRA){ yading@10: return 3+2*( av_log2(2*FFABS(left->color[0] - b->color[0])) yading@10: + av_log2(2*FFABS(left->color[1] - b->color[1])) yading@10: + av_log2(2*FFABS(left->color[2] - b->color[2]))); yading@10: }else{ yading@10: pred_mv(s, &dmx, &dmy, b->ref, left, top, tr); yading@10: dmx-= b->mx; yading@10: dmy-= b->my; yading@10: return 2*(1 + av_log2(2*FFABS(dmx)) //FIXME kill the 2* can be merged in lambda yading@10: + av_log2(2*FFABS(dmy)) yading@10: + av_log2(2*b->ref)); yading@10: } yading@10: } yading@10: yading@10: static int get_block_rd(SnowContext *s, int mb_x, int mb_y, int plane_index, uint8_t (*obmc_edged)[MB_SIZE * 2]){ yading@10: Plane *p= &s->plane[plane_index]; yading@10: const int block_size = MB_SIZE >> s->block_max_depth; yading@10: const int block_w = plane_index ? block_size>>s->chroma_h_shift : block_size; yading@10: const int block_h = plane_index ? block_size>>s->chroma_v_shift : block_size; yading@10: const int obmc_stride= plane_index ? (2*block_size)>>s->chroma_h_shift : 2*block_size; yading@10: const int ref_stride= s->current_picture.linesize[plane_index]; yading@10: uint8_t *dst= s->current_picture.data[plane_index]; yading@10: uint8_t *src= s-> input_picture.data[plane_index]; yading@10: IDWTELEM *pred= (IDWTELEM*)s->m.obmc_scratchpad + plane_index*block_size*block_size*4; yading@10: uint8_t *cur = s->scratchbuf; yading@10: uint8_t *tmp = s->emu_edge_buffer; yading@10: const int b_stride = s->b_width << s->block_max_depth; yading@10: const int b_height = s->b_height<< s->block_max_depth; yading@10: const int w= p->width; yading@10: const int h= p->height; yading@10: int distortion; yading@10: int rate= 0; yading@10: const int penalty_factor= get_penalty_factor(s->lambda, s->lambda2, s->avctx->me_cmp); yading@10: int sx= block_w*mb_x - block_w/2; yading@10: int sy= block_h*mb_y - block_h/2; yading@10: int x0= FFMAX(0,-sx); yading@10: int y0= FFMAX(0,-sy); yading@10: int x1= FFMIN(block_w*2, w-sx); yading@10: int y1= FFMIN(block_h*2, h-sy); yading@10: int i,x,y; yading@10: yading@10: av_assert2(s->chroma_h_shift == s->chroma_v_shift); //obmc and square assumtions below chckinhg only block_w yading@10: yading@10: ff_snow_pred_block(s, cur, tmp, ref_stride, sx, sy, block_w*2, block_h*2, &s->block[mb_x + mb_y*b_stride], plane_index, w, h); yading@10: yading@10: for(y=y0; y= LOG2_OBMC_MAX yading@10: int v = (cur1[x] * obmc1[x]) << (FRAC_BITS - LOG2_OBMC_MAX); yading@10: #else yading@10: int v = (cur1[x] * obmc1[x] + (1<<(LOG2_OBMC_MAX - FRAC_BITS-1))) >> (LOG2_OBMC_MAX - FRAC_BITS); yading@10: #endif yading@10: v = (v + pred1[x]) >> FRAC_BITS; yading@10: if(v&(~255)) v= ~(v>>31); yading@10: dst1[x] = v; yading@10: } yading@10: } yading@10: yading@10: /* copy the regions where obmc[] = (uint8_t)256 */ yading@10: if(LOG2_OBMC_MAX == 8 yading@10: && (mb_x == 0 || mb_x == b_stride-1) yading@10: && (mb_y == 0 || mb_y == b_height-1)){ yading@10: if(mb_x == 0) yading@10: x1 = block_w; yading@10: else yading@10: x0 = block_w; yading@10: if(mb_y == 0) yading@10: y1 = block_h; yading@10: else yading@10: y0 = block_h; yading@10: for(y=y0; yavctx->me_cmp == FF_CMP_W97) yading@10: distortion = ff_w97_32_c(&s->m, src + sx + sy*ref_stride, dst + sx + sy*ref_stride, ref_stride, 32); yading@10: else if(s->avctx->me_cmp == FF_CMP_W53) yading@10: distortion = ff_w53_32_c(&s->m, src + sx + sy*ref_stride, dst + sx + sy*ref_stride, ref_stride, 32); yading@10: else{ yading@10: distortion = 0; yading@10: for(i=0; i<4; i++){ yading@10: int off = sx+16*(i&1) + (sy+16*(i>>1))*ref_stride; yading@10: distortion += s->dsp.me_cmp[0](&s->m, src + off, dst + off, ref_stride, 16); yading@10: } yading@10: } yading@10: }else{ yading@10: assert(block_w==8); yading@10: distortion = s->dsp.me_cmp[0](&s->m, src + sx + sy*ref_stride, dst + sx + sy*ref_stride, ref_stride, block_w*2); yading@10: } yading@10: yading@10: if(plane_index==0){ yading@10: for(i=0; i<4; i++){ yading@10: /* ..RRr yading@10: * .RXx. yading@10: * rxx.. yading@10: */ yading@10: rate += get_block_bits(s, mb_x + (i&1) - (i>>1), mb_y + (i>>1), 1); yading@10: } yading@10: if(mb_x == b_stride-2) yading@10: rate += get_block_bits(s, mb_x + 1, mb_y + 1, 1); yading@10: } yading@10: return distortion + rate*penalty_factor; yading@10: } yading@10: yading@10: static int get_4block_rd(SnowContext *s, int mb_x, int mb_y, int plane_index){ yading@10: int i, y2; yading@10: Plane *p= &s->plane[plane_index]; yading@10: const int block_size = MB_SIZE >> s->block_max_depth; yading@10: const int block_w = plane_index ? block_size>>s->chroma_h_shift : block_size; yading@10: const int block_h = plane_index ? block_size>>s->chroma_v_shift : block_size; yading@10: const uint8_t *obmc = plane_index ? ff_obmc_tab[s->block_max_depth+s->chroma_h_shift] : ff_obmc_tab[s->block_max_depth]; yading@10: const int obmc_stride= plane_index ? (2*block_size)>>s->chroma_h_shift : 2*block_size; yading@10: const int ref_stride= s->current_picture.linesize[plane_index]; yading@10: uint8_t *dst= s->current_picture.data[plane_index]; yading@10: uint8_t *src= s-> input_picture.data[plane_index]; yading@10: //FIXME zero_dst is const but add_yblock changes dst if add is 0 (this is never the case for dst=zero_dst yading@10: // const has only been removed from zero_dst to suppress a warning yading@10: static IDWTELEM zero_dst[4096]; //FIXME yading@10: const int b_stride = s->b_width << s->block_max_depth; yading@10: const int w= p->width; yading@10: const int h= p->height; yading@10: int distortion= 0; yading@10: int rate= 0; yading@10: const int penalty_factor= get_penalty_factor(s->lambda, s->lambda2, s->avctx->me_cmp); yading@10: yading@10: av_assert2(s->chroma_h_shift == s->chroma_v_shift); //obmc and square assumtions below yading@10: yading@10: for(i=0; i<9; i++){ yading@10: int mb_x2= mb_x + (i%3) - 1; yading@10: int mb_y2= mb_y + (i/3) - 1; yading@10: int x= block_w*mb_x2 + block_w/2; yading@10: int y= block_h*mb_y2 + block_h/2; yading@10: yading@10: add_yblock(s, 0, NULL, zero_dst, dst, obmc, yading@10: x, y, block_w, block_h, w, h, /*dst_stride*/0, ref_stride, obmc_stride, mb_x2, mb_y2, 1, 1, plane_index); yading@10: yading@10: //FIXME find a cleaner/simpler way to skip the outside stuff yading@10: for(y2= y; y2<0; y2++) yading@10: memcpy(dst + x + y2*ref_stride, src + x + y2*ref_stride, block_w); yading@10: for(y2= h; y2 w){ yading@10: for(y2= y; y2dsp.me_cmp[block_w==8](&s->m, src + x + y*ref_stride, dst + x + y*ref_stride, ref_stride, block_h); yading@10: } yading@10: yading@10: if(plane_index==0){ yading@10: BlockNode *b= &s->block[mb_x+mb_y*b_stride]; yading@10: int merged= same_block(b,b+1) && same_block(b,b+b_stride) && same_block(b,b+b_stride+1); yading@10: yading@10: /* ..RRRr yading@10: * .RXXx. yading@10: * .RXXx. yading@10: * rxxx. yading@10: */ yading@10: if(merged) yading@10: rate = get_block_bits(s, mb_x, mb_y, 2); yading@10: for(i=merged?4:0; i<9; i++){ yading@10: static const int dxy[9][2] = {{0,0},{1,0},{0,1},{1,1},{2,0},{2,1},{-1,2},{0,2},{1,2}}; yading@10: rate += get_block_bits(s, mb_x + dxy[i][0], mb_y + dxy[i][1], 1); yading@10: } yading@10: } yading@10: return distortion + rate*penalty_factor; yading@10: } yading@10: yading@10: static int encode_subband_c0run(SnowContext *s, SubBand *b, const IDWTELEM *src, const IDWTELEM *parent, int stride, int orientation){ yading@10: const int w= b->width; yading@10: const int h= b->height; yading@10: int x, y; yading@10: yading@10: if(1){ yading@10: int run=0; yading@10: int *runs = s->run_buffer; yading@10: int run_index=0; yading@10: int max_index; yading@10: yading@10: for(y=0; y 1){ yading@10: if(orientation==1) ll= src[y + (x-2)*stride]; yading@10: else ll= src[x - 2 + y*stride]; yading@10: }*/ yading@10: } yading@10: if(parent){ yading@10: int px= x>>1; yading@10: int py= y>>1; yading@10: if(pxparent->width && pyparent->height) yading@10: p= parent[px + py*2*stride]; yading@10: } yading@10: if(!(/*ll|*/l|lt|t|rt|p)){ yading@10: if(v){ yading@10: runs[run_index++]= run; yading@10: run=0; yading@10: }else{ yading@10: run++; yading@10: } yading@10: } yading@10: } yading@10: } yading@10: max_index= run_index; yading@10: runs[run_index++]= run; yading@10: run_index=0; yading@10: run= runs[run_index++]; yading@10: yading@10: put_symbol2(&s->c, b->state[30], max_index, 0); yading@10: if(run_index <= max_index) yading@10: put_symbol2(&s->c, b->state[1], run, 3); yading@10: yading@10: for(y=0; yc.bytestream_end - s->c.bytestream < w*40){ yading@10: av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); yading@10: return -1; yading@10: } yading@10: for(x=0; x 1){ yading@10: if(orientation==1) ll= src[y + (x-2)*stride]; yading@10: else ll= src[x - 2 + y*stride]; yading@10: }*/ yading@10: } yading@10: if(parent){ yading@10: int px= x>>1; yading@10: int py= y>>1; yading@10: if(pxparent->width && pyparent->height) yading@10: p= parent[px + py*2*stride]; yading@10: } yading@10: if(/*ll|*/l|lt|t|rt|p){ yading@10: int context= av_log2(/*FFABS(ll) + */3*FFABS(l) + FFABS(lt) + 2*FFABS(t) + FFABS(rt) + FFABS(p)); yading@10: yading@10: put_rac(&s->c, &b->state[0][context], !!v); yading@10: }else{ yading@10: if(!run){ yading@10: run= runs[run_index++]; yading@10: yading@10: if(run_index <= max_index) yading@10: put_symbol2(&s->c, b->state[1], run, 3); yading@10: assert(v); yading@10: }else{ yading@10: run--; yading@10: assert(!v); yading@10: } yading@10: } yading@10: if(v){ yading@10: int context= av_log2(/*FFABS(ll) + */3*FFABS(l) + FFABS(lt) + 2*FFABS(t) + FFABS(rt) + FFABS(p)); yading@10: int l2= 2*FFABS(l) + (l<0); yading@10: int t2= 2*FFABS(t) + (t<0); yading@10: yading@10: put_symbol2(&s->c, b->state[context + 2], FFABS(v)-1, context-4); yading@10: put_rac(&s->c, &b->state[0][16 + 1 + 3 + ff_quant3bA[l2&0xFF] + 3*ff_quant3bA[t2&0xFF]], v<0); yading@10: } yading@10: } yading@10: } yading@10: } yading@10: return 0; yading@10: } yading@10: yading@10: static int encode_subband(SnowContext *s, SubBand *b, const IDWTELEM *src, const IDWTELEM *parent, int stride, int orientation){ yading@10: // encode_subband_qtree(s, b, src, parent, stride, orientation); yading@10: // encode_subband_z0run(s, b, src, parent, stride, orientation); yading@10: return encode_subband_c0run(s, b, src, parent, stride, orientation); yading@10: // encode_subband_dzr(s, b, src, parent, stride, orientation); yading@10: } yading@10: yading@10: static av_always_inline int check_block(SnowContext *s, int mb_x, int mb_y, int p[3], int intra, uint8_t (*obmc_edged)[MB_SIZE * 2], int *best_rd){ yading@10: const int b_stride= s->b_width << s->block_max_depth; yading@10: BlockNode *block= &s->block[mb_x + mb_y * b_stride]; yading@10: BlockNode backup= *block; yading@10: unsigned value; yading@10: int rd, index; yading@10: yading@10: assert(mb_x>=0 && mb_y>=0); yading@10: assert(mb_xcolor[0] = p[0]; yading@10: block->color[1] = p[1]; yading@10: block->color[2] = p[2]; yading@10: block->type |= BLOCK_INTRA; yading@10: }else{ yading@10: index= (p[0] + 31*p[1]) & (ME_CACHE_SIZE-1); yading@10: value= s->me_cache_generation + (p[0]>>10) + (p[1]<<6) + (block->ref<<12); yading@10: if(s->me_cache[index] == value) yading@10: return 0; yading@10: s->me_cache[index]= value; yading@10: yading@10: block->mx= p[0]; yading@10: block->my= p[1]; yading@10: block->type &= ~BLOCK_INTRA; yading@10: } yading@10: yading@10: rd= get_block_rd(s, mb_x, mb_y, 0, obmc_edged); yading@10: yading@10: //FIXME chroma yading@10: if(rd < *best_rd){ yading@10: *best_rd= rd; yading@10: return 1; yading@10: }else{ yading@10: *block= backup; yading@10: return 0; yading@10: } yading@10: } yading@10: yading@10: /* special case for int[2] args we discard afterwards, yading@10: * fixes compilation problem with gcc 2.95 */ yading@10: static av_always_inline int check_block_inter(SnowContext *s, int mb_x, int mb_y, int p0, int p1, uint8_t (*obmc_edged)[MB_SIZE * 2], int *best_rd){ yading@10: int p[2] = {p0, p1}; yading@10: return check_block(s, mb_x, mb_y, p, 0, obmc_edged, best_rd); yading@10: } yading@10: yading@10: static av_always_inline int check_4block_inter(SnowContext *s, int mb_x, int mb_y, int p0, int p1, int ref, int *best_rd){ yading@10: const int b_stride= s->b_width << s->block_max_depth; yading@10: BlockNode *block= &s->block[mb_x + mb_y * b_stride]; yading@10: BlockNode backup[4]; yading@10: unsigned value; yading@10: int rd, index; yading@10: yading@10: /* We don't initialize backup[] during variable declaration, because yading@10: * that fails to compile on MSVC: "cannot convert from 'BlockNode' to yading@10: * 'int16_t'". */ yading@10: backup[0] = block[0]; yading@10: backup[1] = block[1]; yading@10: backup[2] = block[b_stride]; yading@10: backup[3] = block[b_stride + 1]; yading@10: yading@10: assert(mb_x>=0 && mb_y>=0); yading@10: assert(mb_xme_cache_generation + (p0>>10) + (p1<<6) + (block->ref<<12); yading@10: if(s->me_cache[index] == value) yading@10: return 0; yading@10: s->me_cache[index]= value; yading@10: yading@10: block->mx= p0; yading@10: block->my= p1; yading@10: block->ref= ref; yading@10: block->type &= ~BLOCK_INTRA; yading@10: block[1]= block[b_stride]= block[b_stride+1]= *block; yading@10: yading@10: rd= get_4block_rd(s, mb_x, mb_y, 0); yading@10: yading@10: //FIXME chroma yading@10: if(rd < *best_rd){ yading@10: *best_rd= rd; yading@10: return 1; yading@10: }else{ yading@10: block[0]= backup[0]; yading@10: block[1]= backup[1]; yading@10: block[b_stride]= backup[2]; yading@10: block[b_stride+1]= backup[3]; yading@10: return 0; yading@10: } yading@10: } yading@10: yading@10: static void iterative_me(SnowContext *s){ yading@10: int pass, mb_x, mb_y; yading@10: const int b_width = s->b_width << s->block_max_depth; yading@10: const int b_height= s->b_height << s->block_max_depth; yading@10: const int b_stride= b_width; yading@10: int color[3]; yading@10: yading@10: { yading@10: RangeCoder r = s->c; yading@10: uint8_t state[sizeof(s->block_state)]; yading@10: memcpy(state, s->block_state, sizeof(s->block_state)); yading@10: for(mb_y= 0; mb_yb_height; mb_y++) yading@10: for(mb_x= 0; mb_xb_width; mb_x++) yading@10: encode_q_branch(s, 0, mb_x, mb_y); yading@10: s->c = r; yading@10: memcpy(s->block_state, state, sizeof(s->block_state)); yading@10: } yading@10: yading@10: for(pass=0; pass<25; pass++){ yading@10: int change= 0; yading@10: yading@10: for(mb_y= 0; mb_yblock[index]; yading@10: BlockNode *tb = mb_y ? &s->block[index-b_stride ] : NULL; yading@10: BlockNode *lb = mb_x ? &s->block[index -1] : NULL; yading@10: BlockNode *rb = mb_x+1block[index +1] : NULL; yading@10: BlockNode *bb = mb_y+1block[index+b_stride ] : NULL; yading@10: BlockNode *tlb= mb_x && mb_y ? &s->block[index-b_stride-1] : NULL; yading@10: BlockNode *trb= mb_x+1block[index-b_stride+1] : NULL; yading@10: BlockNode *blb= mb_x && mb_y+1block[index+b_stride-1] : NULL; yading@10: BlockNode *brb= mb_x+1block[index+b_stride+1] : NULL; yading@10: const int b_w= (MB_SIZE >> s->block_max_depth); yading@10: uint8_t obmc_edged[MB_SIZE * 2][MB_SIZE * 2]; yading@10: yading@10: if(pass && (block->type & BLOCK_OPT)) yading@10: continue; yading@10: block->type |= BLOCK_OPT; yading@10: yading@10: backup= *block; yading@10: yading@10: if(!s->me_cache_generation) yading@10: memset(s->me_cache, 0, sizeof(s->me_cache)); yading@10: s->me_cache_generation += 1<<22; yading@10: yading@10: //FIXME precalculate yading@10: { yading@10: int x, y; yading@10: for (y = 0; y < b_w * 2; y++) yading@10: memcpy(obmc_edged[y], ff_obmc_tab[s->block_max_depth] + y * b_w * 2, b_w * 2); yading@10: if(mb_x==0) yading@10: for(y=0; y input_picture.data[0]; yading@10: uint8_t *dst= s->current_picture.data[0]; yading@10: const int stride= s->current_picture.linesize[0]; yading@10: const int block_w= MB_SIZE >> s->block_max_depth; yading@10: const int block_h= MB_SIZE >> s->block_max_depth; yading@10: const int sx= block_w*mb_x - block_w/2; yading@10: const int sy= block_h*mb_y - block_h/2; yading@10: const int w= s->plane[0].width; yading@10: const int h= s->plane[0].height; yading@10: int y; yading@10: yading@10: for(y=sy; y<0; y++) yading@10: memcpy(dst + sx + y*stride, src + sx + y*stride, block_w*2); yading@10: for(y=h; y w){ yading@10: for(y=sy; y 0 && (block->type&BLOCK_INTRA)){ yading@10: int color0[3]= {block->color[0], block->color[1], block->color[2]}; yading@10: check_block(s, mb_x, mb_y, color0, 1, obmc_edged, &best_rd); yading@10: }else yading@10: check_block_inter(s, mb_x, mb_y, block->mx, block->my, obmc_edged, &best_rd); yading@10: yading@10: ref_b= *block; yading@10: ref_rd= best_rd; yading@10: for(ref=0; ref < s->ref_frames; ref++){ yading@10: int16_t (*mvr)[2]= &s->ref_mvs[ref][index]; yading@10: if(s->ref_scores[ref][index] > s->ref_scores[ref_b.ref][index]*3/2) //FIXME tune threshold yading@10: continue; yading@10: block->ref= ref; yading@10: best_rd= INT_MAX; yading@10: yading@10: check_block_inter(s, mb_x, mb_y, mvr[0][0], mvr[0][1], obmc_edged, &best_rd); yading@10: check_block_inter(s, mb_x, mb_y, 0, 0, obmc_edged, &best_rd); yading@10: if(tb) yading@10: check_block_inter(s, mb_x, mb_y, mvr[-b_stride][0], mvr[-b_stride][1], obmc_edged, &best_rd); yading@10: if(lb) yading@10: check_block_inter(s, mb_x, mb_y, mvr[-1][0], mvr[-1][1], obmc_edged, &best_rd); yading@10: if(rb) yading@10: check_block_inter(s, mb_x, mb_y, mvr[1][0], mvr[1][1], obmc_edged, &best_rd); yading@10: if(bb) yading@10: check_block_inter(s, mb_x, mb_y, mvr[b_stride][0], mvr[b_stride][1], obmc_edged, &best_rd); yading@10: yading@10: /* fullpel ME */ yading@10: //FIXME avoid subpel interpolation / round to nearest integer yading@10: do{ yading@10: dia_change=0; yading@10: for(i=0; iavctx->dia_size, 1); i++){ yading@10: for(j=0; jmx+4*(i-j), block->my+(4*j), obmc_edged, &best_rd); yading@10: dia_change |= check_block_inter(s, mb_x, mb_y, block->mx-4*(i-j), block->my-(4*j), obmc_edged, &best_rd); yading@10: dia_change |= check_block_inter(s, mb_x, mb_y, block->mx+4*(i-j), block->my-(4*j), obmc_edged, &best_rd); yading@10: dia_change |= check_block_inter(s, mb_x, mb_y, block->mx-4*(i-j), block->my+(4*j), obmc_edged, &best_rd); yading@10: } yading@10: } yading@10: }while(dia_change); yading@10: /* subpel ME */ yading@10: do{ yading@10: static const int square[8][2]= {{+1, 0},{-1, 0},{ 0,+1},{ 0,-1},{+1,+1},{-1,-1},{+1,-1},{-1,+1},}; yading@10: dia_change=0; yading@10: for(i=0; i<8; i++) yading@10: dia_change |= check_block_inter(s, mb_x, mb_y, block->mx+square[i][0], block->my+square[i][1], obmc_edged, &best_rd); yading@10: }while(dia_change); yading@10: //FIXME or try the standard 2 pass qpel or similar yading@10: yading@10: mvr[0][0]= block->mx; yading@10: mvr[0][1]= block->my; yading@10: if(ref_rd > best_rd){ yading@10: ref_rd= best_rd; yading@10: ref_b= *block; yading@10: } yading@10: } yading@10: best_rd= ref_rd; yading@10: *block= ref_b; yading@10: check_block(s, mb_x, mb_y, color, 1, obmc_edged, &best_rd); yading@10: //FIXME RD style color selection yading@10: if(!same_block(block, &backup)){ yading@10: if(tb ) tb ->type &= ~BLOCK_OPT; yading@10: if(lb ) lb ->type &= ~BLOCK_OPT; yading@10: if(rb ) rb ->type &= ~BLOCK_OPT; yading@10: if(bb ) bb ->type &= ~BLOCK_OPT; yading@10: if(tlb) tlb->type &= ~BLOCK_OPT; yading@10: if(trb) trb->type &= ~BLOCK_OPT; yading@10: if(blb) blb->type &= ~BLOCK_OPT; yading@10: if(brb) brb->type &= ~BLOCK_OPT; yading@10: change ++; yading@10: } yading@10: } yading@10: } yading@10: av_log(s->avctx, AV_LOG_ERROR, "pass:%d changed:%d\n", pass, change); yading@10: if(!change) yading@10: break; yading@10: } yading@10: yading@10: if(s->block_max_depth == 1){ yading@10: int change= 0; yading@10: for(mb_y= 0; mb_yblock[index]; yading@10: b[1]= b[0]+1; yading@10: b[2]= b[0]+b_stride; yading@10: b[3]= b[2]+1; yading@10: if(same_block(b[0], b[1]) && yading@10: same_block(b[0], b[2]) && yading@10: same_block(b[0], b[3])) yading@10: continue; yading@10: yading@10: if(!s->me_cache_generation) yading@10: memset(s->me_cache, 0, sizeof(s->me_cache)); yading@10: s->me_cache_generation += 1<<22; yading@10: yading@10: init_rd= best_rd= get_4block_rd(s, mb_x, mb_y, 0); yading@10: yading@10: //FIXME more multiref search? yading@10: check_4block_inter(s, mb_x, mb_y, yading@10: (b[0]->mx + b[1]->mx + b[2]->mx + b[3]->mx + 2) >> 2, yading@10: (b[0]->my + b[1]->my + b[2]->my + b[3]->my + 2) >> 2, 0, &best_rd); yading@10: yading@10: for(i=0; i<4; i++) yading@10: if(!(b[i]->type&BLOCK_INTRA)) yading@10: check_4block_inter(s, mb_x, mb_y, b[i]->mx, b[i]->my, b[i]->ref, &best_rd); yading@10: yading@10: if(init_rd != best_rd) yading@10: change++; yading@10: } yading@10: } yading@10: av_log(s->avctx, AV_LOG_ERROR, "pass:4mv changed:%d\n", change*4); yading@10: } yading@10: } yading@10: yading@10: static void encode_blocks(SnowContext *s, int search){ yading@10: int x, y; yading@10: int w= s->b_width; yading@10: int h= s->b_height; yading@10: yading@10: if(s->avctx->me_method == ME_ITER && !s->keyframe && search) yading@10: iterative_me(s); yading@10: yading@10: for(y=0; yc.bytestream_end - s->c.bytestream < w*MB_SIZE*MB_SIZE*3){ //FIXME nicer limit yading@10: av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); yading@10: return; yading@10: } yading@10: for(x=0; xavctx->me_method == ME_ITER || !search) yading@10: encode_q_branch2(s, 0, x, y); yading@10: else yading@10: encode_q_branch (s, 0, x, y); yading@10: } yading@10: } yading@10: } yading@10: yading@10: static void quantize(SnowContext *s, SubBand *b, IDWTELEM *dst, DWTELEM *src, int stride, int bias){ yading@10: const int w= b->width; yading@10: const int h= b->height; yading@10: const int qlog= av_clip(s->qlog + b->qlog, 0, QROOT*16); yading@10: const int qmul= ff_qexp[qlog&(QROOT-1)]<<((qlog>>QSHIFT) + ENCODER_EXTRA_BITS); yading@10: int x,y, thres1, thres2; yading@10: yading@10: if(s->qlog == LOSSLESS_QLOG){ yading@10: for(y=0; y>3; yading@10: thres1= ((qmul - bias)>>QEXPSHIFT) - 1; yading@10: thres2= 2*thres1; yading@10: yading@10: if(!bias){ yading@10: for(y=0; y thres2){ yading@10: if(i>=0){ yading@10: i<<= QEXPSHIFT; yading@10: i/= qmul; //FIXME optimize yading@10: dst[x + y*stride]= i; yading@10: }else{ yading@10: i= -i; yading@10: i<<= QEXPSHIFT; yading@10: i/= qmul; //FIXME optimize yading@10: dst[x + y*stride]= -i; yading@10: } yading@10: }else yading@10: dst[x + y*stride]= 0; yading@10: } yading@10: } yading@10: }else{ yading@10: for(y=0; y thres2){ yading@10: if(i>=0){ yading@10: i<<= QEXPSHIFT; yading@10: i= (i + bias) / qmul; //FIXME optimize yading@10: dst[x + y*stride]= i; yading@10: }else{ yading@10: i= -i; yading@10: i<<= QEXPSHIFT; yading@10: i= (i + bias) / qmul; //FIXME optimize yading@10: dst[x + y*stride]= -i; yading@10: } yading@10: }else yading@10: dst[x + y*stride]= 0; yading@10: } yading@10: } yading@10: } yading@10: } yading@10: yading@10: static void dequantize(SnowContext *s, SubBand *b, IDWTELEM *src, int stride){ yading@10: const int w= b->width; yading@10: const int h= b->height; yading@10: const int qlog= av_clip(s->qlog + b->qlog, 0, QROOT*16); yading@10: const int qmul= ff_qexp[qlog&(QROOT-1)]<<(qlog>>QSHIFT); yading@10: const int qadd= (s->qbias*qmul)>>QBIAS_SHIFT; yading@10: int x,y; yading@10: yading@10: if(s->qlog == LOSSLESS_QLOG) return; yading@10: yading@10: for(y=0; y>(QEXPSHIFT)); //FIXME try different bias yading@10: }else if(i>0){ yading@10: src[x + y*stride]= (( i*qmul + qadd)>>(QEXPSHIFT)); yading@10: } yading@10: } yading@10: } yading@10: } yading@10: yading@10: static void decorrelate(SnowContext *s, SubBand *b, IDWTELEM *src, int stride, int inverse, int use_median){ yading@10: const int w= b->width; yading@10: const int h= b->height; yading@10: int x,y; yading@10: yading@10: for(y=h-1; y>=0; y--){ yading@10: for(x=w-1; x>=0; x--){ yading@10: int i= x + y*stride; yading@10: yading@10: if(x){ yading@10: if(use_median){ yading@10: if(y && x+1width; yading@10: const int h= b->height; yading@10: int x,y; yading@10: yading@10: for(y=0; yspatial_decomposition_count; level++){ yading@10: for(orientation=level ? 1:0; orientation<4; orientation++){ yading@10: if(orientation==2) continue; yading@10: put_symbol(&s->c, s->header_state, s->plane[plane_index].band[level][orientation].qlog, 1); yading@10: } yading@10: } yading@10: } yading@10: } yading@10: yading@10: static void encode_header(SnowContext *s){ yading@10: int plane_index, i; yading@10: uint8_t kstate[32]; yading@10: yading@10: memset(kstate, MID_STATE, sizeof(kstate)); yading@10: yading@10: put_rac(&s->c, kstate, s->keyframe); yading@10: if(s->keyframe || s->always_reset){ yading@10: ff_snow_reset_contexts(s); yading@10: s->last_spatial_decomposition_type= yading@10: s->last_qlog= yading@10: s->last_qbias= yading@10: s->last_mv_scale= yading@10: s->last_block_max_depth= 0; yading@10: for(plane_index=0; plane_index<2; plane_index++){ yading@10: Plane *p= &s->plane[plane_index]; yading@10: p->last_htaps=0; yading@10: p->last_diag_mc=0; yading@10: memset(p->last_hcoeff, 0, sizeof(p->last_hcoeff)); yading@10: } yading@10: } yading@10: if(s->keyframe){ yading@10: put_symbol(&s->c, s->header_state, s->version, 0); yading@10: put_rac(&s->c, s->header_state, s->always_reset); yading@10: put_symbol(&s->c, s->header_state, s->temporal_decomposition_type, 0); yading@10: put_symbol(&s->c, s->header_state, s->temporal_decomposition_count, 0); yading@10: put_symbol(&s->c, s->header_state, s->spatial_decomposition_count, 0); yading@10: put_symbol(&s->c, s->header_state, s->colorspace_type, 0); yading@10: put_symbol(&s->c, s->header_state, s->chroma_h_shift, 0); yading@10: put_symbol(&s->c, s->header_state, s->chroma_v_shift, 0); yading@10: put_rac(&s->c, s->header_state, s->spatial_scalability); yading@10: // put_rac(&s->c, s->header_state, s->rate_scalability); yading@10: put_symbol(&s->c, s->header_state, s->max_ref_frames-1, 0); yading@10: yading@10: encode_qlogs(s); yading@10: } yading@10: yading@10: if(!s->keyframe){ yading@10: int update_mc=0; yading@10: for(plane_index=0; plane_index<2; plane_index++){ yading@10: Plane *p= &s->plane[plane_index]; yading@10: update_mc |= p->last_htaps != p->htaps; yading@10: update_mc |= p->last_diag_mc != p->diag_mc; yading@10: update_mc |= !!memcmp(p->last_hcoeff, p->hcoeff, sizeof(p->hcoeff)); yading@10: } yading@10: put_rac(&s->c, s->header_state, update_mc); yading@10: if(update_mc){ yading@10: for(plane_index=0; plane_index<2; plane_index++){ yading@10: Plane *p= &s->plane[plane_index]; yading@10: put_rac(&s->c, s->header_state, p->diag_mc); yading@10: put_symbol(&s->c, s->header_state, p->htaps/2-1, 0); yading@10: for(i= p->htaps/2; i; i--) yading@10: put_symbol(&s->c, s->header_state, FFABS(p->hcoeff[i]), 0); yading@10: } yading@10: } yading@10: if(s->last_spatial_decomposition_count != s->spatial_decomposition_count){ yading@10: put_rac(&s->c, s->header_state, 1); yading@10: put_symbol(&s->c, s->header_state, s->spatial_decomposition_count, 0); yading@10: encode_qlogs(s); yading@10: }else yading@10: put_rac(&s->c, s->header_state, 0); yading@10: } yading@10: yading@10: put_symbol(&s->c, s->header_state, s->spatial_decomposition_type - s->last_spatial_decomposition_type, 1); yading@10: put_symbol(&s->c, s->header_state, s->qlog - s->last_qlog , 1); yading@10: put_symbol(&s->c, s->header_state, s->mv_scale - s->last_mv_scale, 1); yading@10: put_symbol(&s->c, s->header_state, s->qbias - s->last_qbias , 1); yading@10: put_symbol(&s->c, s->header_state, s->block_max_depth - s->last_block_max_depth, 1); yading@10: yading@10: } yading@10: yading@10: static void update_last_header_values(SnowContext *s){ yading@10: int plane_index; yading@10: yading@10: if(!s->keyframe){ yading@10: for(plane_index=0; plane_index<2; plane_index++){ yading@10: Plane *p= &s->plane[plane_index]; yading@10: p->last_diag_mc= p->diag_mc; yading@10: p->last_htaps = p->htaps; yading@10: memcpy(p->last_hcoeff, p->hcoeff, sizeof(p->hcoeff)); yading@10: } yading@10: } yading@10: yading@10: s->last_spatial_decomposition_type = s->spatial_decomposition_type; yading@10: s->last_qlog = s->qlog; yading@10: s->last_qbias = s->qbias; yading@10: s->last_mv_scale = s->mv_scale; yading@10: s->last_block_max_depth = s->block_max_depth; yading@10: s->last_spatial_decomposition_count = s->spatial_decomposition_count; yading@10: } yading@10: yading@10: static int qscale2qlog(int qscale){ yading@10: return rint(QROOT*log2(qscale / (float)FF_QP2LAMBDA)) yading@10: + 61*QROOT/8; ///< 64 > 60 yading@10: } yading@10: yading@10: static int ratecontrol_1pass(SnowContext *s, AVFrame *pict) yading@10: { yading@10: /* Estimate the frame's complexity as a sum of weighted dwt coefficients. yading@10: * FIXME we know exact mv bits at this point, yading@10: * but ratecontrol isn't set up to include them. */ yading@10: uint32_t coef_sum= 0; yading@10: int level, orientation, delta_qlog; yading@10: yading@10: for(level=0; levelspatial_decomposition_count; level++){ yading@10: for(orientation=level ? 1 : 0; orientation<4; orientation++){ yading@10: SubBand *b= &s->plane[0].band[level][orientation]; yading@10: IDWTELEM *buf= b->ibuf; yading@10: const int w= b->width; yading@10: const int h= b->height; yading@10: const int stride= b->stride; yading@10: const int qlog= av_clip(2*QROOT + b->qlog, 0, QROOT*16); yading@10: const int qmul= ff_qexp[qlog&(QROOT-1)]<<(qlog>>QSHIFT); yading@10: const int qdiv= (1<<16)/qmul; yading@10: int x, y; yading@10: //FIXME this is ugly yading@10: for(y=0; ybuf[x+y*stride]; yading@10: if(orientation==0) yading@10: decorrelate(s, b, buf, stride, 1, 0); yading@10: for(y=0; y> 16; yading@10: } yading@10: } yading@10: yading@10: /* ugly, ratecontrol just takes a sqrt again */ yading@10: coef_sum = (uint64_t)coef_sum * coef_sum >> 16; yading@10: assert(coef_sum < INT_MAX); yading@10: yading@10: if(pict->pict_type == AV_PICTURE_TYPE_I){ yading@10: s->m.current_picture.mb_var_sum= coef_sum; yading@10: s->m.current_picture.mc_mb_var_sum= 0; yading@10: }else{ yading@10: s->m.current_picture.mc_mb_var_sum= coef_sum; yading@10: s->m.current_picture.mb_var_sum= 0; yading@10: } yading@10: yading@10: pict->quality= ff_rate_estimate_qscale(&s->m, 1); yading@10: if (pict->quality < 0) yading@10: return INT_MIN; yading@10: s->lambda= pict->quality * 3/2; yading@10: delta_qlog= qscale2qlog(pict->quality) - s->qlog; yading@10: s->qlog+= delta_qlog; yading@10: return delta_qlog; yading@10: } yading@10: yading@10: static void calculate_visual_weight(SnowContext *s, Plane *p){ yading@10: int width = p->width; yading@10: int height= p->height; yading@10: int level, orientation, x, y; yading@10: yading@10: for(level=0; levelspatial_decomposition_count; level++){ yading@10: for(orientation=level ? 1 : 0; orientation<4; orientation++){ yading@10: SubBand *b= &p->band[level][orientation]; yading@10: IDWTELEM *ibuf= b->ibuf; yading@10: int64_t error=0; yading@10: yading@10: memset(s->spatial_idwt_buffer, 0, sizeof(*s->spatial_idwt_buffer)*width*height); yading@10: ibuf[b->width/2 + b->height/2*b->stride]= 256*16; yading@10: ff_spatial_idwt(s->spatial_idwt_buffer, s->temp_idwt_buffer, width, height, width, s->spatial_decomposition_type, s->spatial_decomposition_count); yading@10: for(y=0; yspatial_idwt_buffer[x + y*width]*16; yading@10: error += d*d; yading@10: } yading@10: } yading@10: yading@10: b->qlog= (int)(log(352256.0/sqrt(error)) / log(pow(2.0, 1.0/QROOT))+0.5); yading@10: } yading@10: } yading@10: } yading@10: yading@10: static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, yading@10: const AVFrame *pict, int *got_packet) yading@10: { yading@10: SnowContext *s = avctx->priv_data; yading@10: RangeCoder * const c= &s->c; yading@10: AVFrame *pic = &s->new_picture; yading@10: const int width= s->avctx->width; yading@10: const int height= s->avctx->height; yading@10: int level, orientation, plane_index, i, y, ret; yading@10: uint8_t rc_header_bak[sizeof(s->header_state)]; yading@10: uint8_t rc_block_bak[sizeof(s->block_state)]; yading@10: yading@10: if ((ret = ff_alloc_packet2(avctx, pkt, s->b_width*s->b_height*MB_SIZE*MB_SIZE*3 + FF_MIN_BUFFER_SIZE)) < 0) yading@10: return ret; yading@10: yading@10: ff_init_range_encoder(c, pkt->data, pkt->size); yading@10: ff_build_rac_states(c, 0.05*(1LL<<32), 256-8); yading@10: yading@10: for(i=0; i<3; i++){ yading@10: int hshift= i ? s->chroma_h_shift : 0; yading@10: int vshift= i ? s->chroma_v_shift : 0; yading@10: for(y=0; y<(height>>vshift); y++) yading@10: memcpy(&s->input_picture.data[i][y * s->input_picture.linesize[i]], yading@10: &pict->data[i][y * pict->linesize[i]], yading@10: width>>hshift); yading@10: s->dsp.draw_edges(s->input_picture.data[i], s->input_picture.linesize[i], yading@10: width >> hshift, height >> vshift, yading@10: EDGE_WIDTH >> hshift, EDGE_WIDTH >> vshift, yading@10: EDGE_TOP | EDGE_BOTTOM); yading@10: yading@10: } yading@10: emms_c(); yading@10: s->new_picture = *pict; yading@10: yading@10: s->m.picture_number= avctx->frame_number; yading@10: if(avctx->flags&CODEC_FLAG_PASS2){ yading@10: s->m.pict_type = pic->pict_type = s->m.rc_context.entry[avctx->frame_number].new_pict_type; yading@10: s->keyframe = pic->pict_type == AV_PICTURE_TYPE_I; yading@10: if(!(avctx->flags&CODEC_FLAG_QSCALE)) { yading@10: pic->quality = ff_rate_estimate_qscale(&s->m, 0); yading@10: if (pic->quality < 0) yading@10: return -1; yading@10: } yading@10: }else{ yading@10: s->keyframe= avctx->gop_size==0 || avctx->frame_number % avctx->gop_size == 0; yading@10: s->m.pict_type = pic->pict_type = s->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; yading@10: } yading@10: yading@10: if(s->pass1_rc && avctx->frame_number == 0) yading@10: pic->quality = 2*FF_QP2LAMBDA; yading@10: if (pic->quality) { yading@10: s->qlog = qscale2qlog(pic->quality); yading@10: s->lambda = pic->quality * 3/2; yading@10: } yading@10: if (s->qlog < 0 || (!pic->quality && (avctx->flags & CODEC_FLAG_QSCALE))) { yading@10: s->qlog= LOSSLESS_QLOG; yading@10: s->lambda = 0; yading@10: }//else keep previous frame's qlog until after motion estimation yading@10: yading@10: ff_snow_frame_start(s); yading@10: yading@10: s->m.current_picture_ptr= &s->m.current_picture; yading@10: s->m.last_picture.f.pts = s->m.current_picture.f.pts; yading@10: s->m.current_picture.f.pts = pict->pts; yading@10: if(pic->pict_type == AV_PICTURE_TYPE_P){ yading@10: int block_width = (width +15)>>4; yading@10: int block_height= (height+15)>>4; yading@10: int stride= s->current_picture.linesize[0]; yading@10: yading@10: assert(s->current_picture.data[0]); yading@10: assert(s->last_picture[0].data[0]); yading@10: yading@10: s->m.avctx= s->avctx; yading@10: s->m.current_picture.f.data[0] = s->current_picture.data[0]; yading@10: s->m. last_picture.f.data[0] = s->last_picture[0].data[0]; yading@10: s->m. new_picture.f.data[0] = s-> input_picture.data[0]; yading@10: s->m. last_picture_ptr= &s->m. last_picture; yading@10: s->m.linesize= yading@10: s->m. last_picture.f.linesize[0] = yading@10: s->m. new_picture.f.linesize[0] = yading@10: s->m.current_picture.f.linesize[0] = stride; yading@10: s->m.uvlinesize= s->current_picture.linesize[1]; yading@10: s->m.width = width; yading@10: s->m.height= height; yading@10: s->m.mb_width = block_width; yading@10: s->m.mb_height= block_height; yading@10: s->m.mb_stride= s->m.mb_width+1; yading@10: s->m.b8_stride= 2*s->m.mb_width+1; yading@10: s->m.f_code=1; yading@10: s->m.pict_type = pic->pict_type; yading@10: s->m.me_method= s->avctx->me_method; yading@10: s->m.me.scene_change_score=0; yading@10: s->m.flags= s->avctx->flags; yading@10: s->m.quarter_sample= (s->avctx->flags & CODEC_FLAG_QPEL)!=0; yading@10: s->m.out_format= FMT_H263; yading@10: s->m.unrestricted_mv= 1; yading@10: yading@10: s->m.lambda = s->lambda; yading@10: s->m.qscale= (s->m.lambda*139 + FF_LAMBDA_SCALE*64) >> (FF_LAMBDA_SHIFT + 7); yading@10: s->lambda2= s->m.lambda2= (s->m.lambda*s->m.lambda + FF_LAMBDA_SCALE/2) >> FF_LAMBDA_SHIFT; yading@10: yading@10: s->m.dsp= s->dsp; //move yading@10: s->m.hdsp = s->hdsp; yading@10: ff_init_me(&s->m); yading@10: s->hdsp = s->m.hdsp; yading@10: s->dsp= s->m.dsp; yading@10: } yading@10: yading@10: if(s->pass1_rc){ yading@10: memcpy(rc_header_bak, s->header_state, sizeof(s->header_state)); yading@10: memcpy(rc_block_bak, s->block_state, sizeof(s->block_state)); yading@10: } yading@10: yading@10: redo_frame: yading@10: yading@10: if (pic->pict_type == AV_PICTURE_TYPE_I) yading@10: s->spatial_decomposition_count= 5; yading@10: else yading@10: s->spatial_decomposition_count= 5; yading@10: yading@10: while( !(width >>(s->chroma_h_shift + s->spatial_decomposition_count)) yading@10: || !(height>>(s->chroma_v_shift + s->spatial_decomposition_count))) yading@10: s->spatial_decomposition_count--; yading@10: yading@10: s->m.pict_type = pic->pict_type; yading@10: s->qbias = pic->pict_type == AV_PICTURE_TYPE_P ? 2 : 0; yading@10: yading@10: ff_snow_common_init_after_header(avctx); yading@10: yading@10: if(s->last_spatial_decomposition_count != s->spatial_decomposition_count){ yading@10: for(plane_index=0; plane_index<3; plane_index++){ yading@10: calculate_visual_weight(s, &s->plane[plane_index]); yading@10: } yading@10: } yading@10: yading@10: encode_header(s); yading@10: s->m.misc_bits = 8*(s->c.bytestream - s->c.bytestream_start); yading@10: encode_blocks(s, 1); yading@10: s->m.mv_bits = 8*(s->c.bytestream - s->c.bytestream_start) - s->m.misc_bits; yading@10: yading@10: for(plane_index=0; plane_index<3; plane_index++){ yading@10: Plane *p= &s->plane[plane_index]; yading@10: int w= p->width; yading@10: int h= p->height; yading@10: int x, y; yading@10: // int bits= put_bits_count(&s->c.pb); yading@10: yading@10: if (!s->memc_only) { yading@10: //FIXME optimize yading@10: if(pict->data[plane_index]) //FIXME gray hack yading@10: for(y=0; yspatial_idwt_buffer[y*w + x]= pict->data[plane_index][y*pict->linesize[plane_index] + x]<spatial_idwt_buffer, plane_index, 0); yading@10: yading@10: if( plane_index==0 yading@10: && pic->pict_type == AV_PICTURE_TYPE_P yading@10: && !(avctx->flags&CODEC_FLAG_PASS2) yading@10: && s->m.me.scene_change_score > s->avctx->scenechange_threshold){ yading@10: ff_init_range_encoder(c, pkt->data, pkt->size); yading@10: ff_build_rac_states(c, 0.05*(1LL<<32), 256-8); yading@10: pic->pict_type= AV_PICTURE_TYPE_I; yading@10: s->keyframe=1; yading@10: s->current_picture.key_frame=1; yading@10: goto redo_frame; yading@10: } yading@10: yading@10: if(s->qlog == LOSSLESS_QLOG){ yading@10: for(y=0; yspatial_dwt_buffer[y*w + x]= (s->spatial_idwt_buffer[y*w + x] + (1<<(FRAC_BITS-1))-1)>>FRAC_BITS; yading@10: } yading@10: } yading@10: }else{ yading@10: for(y=0; yspatial_dwt_buffer[y*w + x]=s->spatial_idwt_buffer[y*w + x]<spatial_dwt_buffer, w, h, w, s->spatial_decomposition_type); yading@10: else*/ yading@10: ff_spatial_dwt(s->spatial_dwt_buffer, s->temp_dwt_buffer, w, h, w, s->spatial_decomposition_type, s->spatial_decomposition_count); yading@10: yading@10: if(s->pass1_rc && plane_index==0){ yading@10: int delta_qlog = ratecontrol_1pass(s, pic); yading@10: if (delta_qlog <= INT_MIN) yading@10: return -1; yading@10: if(delta_qlog){ yading@10: //reordering qlog in the bitstream would eliminate this reset yading@10: ff_init_range_encoder(c, pkt->data, pkt->size); yading@10: memcpy(s->header_state, rc_header_bak, sizeof(s->header_state)); yading@10: memcpy(s->block_state, rc_block_bak, sizeof(s->block_state)); yading@10: encode_header(s); yading@10: encode_blocks(s, 0); yading@10: } yading@10: } yading@10: yading@10: for(level=0; levelspatial_decomposition_count; level++){ yading@10: for(orientation=level ? 1 : 0; orientation<4; orientation++){ yading@10: SubBand *b= &p->band[level][orientation]; yading@10: yading@10: if(!QUANTIZE2) yading@10: quantize(s, b, b->ibuf, b->buf, b->stride, s->qbias); yading@10: if(orientation==0) yading@10: decorrelate(s, b, b->ibuf, b->stride, pic->pict_type == AV_PICTURE_TYPE_P, 0); yading@10: if (!s->no_bitstream) yading@10: encode_subband(s, b, b->ibuf, b->parent ? b->parent->ibuf : NULL, b->stride, orientation); yading@10: assert(b->parent==NULL || b->parent->stride == b->stride*2); yading@10: if(orientation==0) yading@10: correlate(s, b, b->ibuf, b->stride, 1, 0); yading@10: } yading@10: } yading@10: yading@10: for(level=0; levelspatial_decomposition_count; level++){ yading@10: for(orientation=level ? 1 : 0; orientation<4; orientation++){ yading@10: SubBand *b= &p->band[level][orientation]; yading@10: yading@10: dequantize(s, b, b->ibuf, b->stride); yading@10: } yading@10: } yading@10: yading@10: ff_spatial_idwt(s->spatial_idwt_buffer, s->temp_idwt_buffer, w, h, w, s->spatial_decomposition_type, s->spatial_decomposition_count); yading@10: if(s->qlog == LOSSLESS_QLOG){ yading@10: for(y=0; yspatial_idwt_buffer[y*w + x]<<=FRAC_BITS; yading@10: } yading@10: } yading@10: } yading@10: predict_plane(s, s->spatial_idwt_buffer, plane_index, 1); yading@10: }else{ yading@10: //ME/MC only yading@10: if(pic->pict_type == AV_PICTURE_TYPE_I){ yading@10: for(y=0; ycurrent_picture.data[plane_index][y*s->current_picture.linesize[plane_index] + x]= yading@10: pict->data[plane_index][y*pict->linesize[plane_index] + x]; yading@10: } yading@10: } yading@10: }else{ yading@10: memset(s->spatial_idwt_buffer, 0, sizeof(IDWTELEM)*w*h); yading@10: predict_plane(s, s->spatial_idwt_buffer, plane_index, 1); yading@10: } yading@10: } yading@10: if(s->avctx->flags&CODEC_FLAG_PSNR){ yading@10: int64_t error= 0; yading@10: yading@10: if(pict->data[plane_index]) //FIXME gray hack yading@10: for(y=0; ycurrent_picture.data[plane_index][y*s->current_picture.linesize[plane_index] + x] - pict->data[plane_index][y*pict->linesize[plane_index] + x]; yading@10: error += d*d; yading@10: } yading@10: } yading@10: s->avctx->error[plane_index] += error; yading@10: s->current_picture.error[plane_index] = error; yading@10: } yading@10: yading@10: } yading@10: yading@10: update_last_header_values(s); yading@10: yading@10: ff_snow_release_buffer(avctx); yading@10: yading@10: s->current_picture.coded_picture_number = avctx->frame_number; yading@10: s->current_picture.pict_type = pict->pict_type; yading@10: s->current_picture.quality = pict->quality; yading@10: s->m.frame_bits = 8*(s->c.bytestream - s->c.bytestream_start); yading@10: s->m.p_tex_bits = s->m.frame_bits - s->m.misc_bits - s->m.mv_bits; yading@10: s->m.current_picture.f.display_picture_number = yading@10: s->m.current_picture.f.coded_picture_number = avctx->frame_number; yading@10: s->m.current_picture.f.quality = pic->quality; yading@10: s->m.total_bits += 8*(s->c.bytestream - s->c.bytestream_start); yading@10: if(s->pass1_rc) yading@10: if (ff_rate_estimate_qscale(&s->m, 0) < 0) yading@10: return -1; yading@10: if(avctx->flags&CODEC_FLAG_PASS1) yading@10: ff_write_pass1_stats(&s->m); yading@10: s->m.last_pict_type = s->m.pict_type; yading@10: avctx->frame_bits = s->m.frame_bits; yading@10: avctx->mv_bits = s->m.mv_bits; yading@10: avctx->misc_bits = s->m.misc_bits; yading@10: avctx->p_tex_bits = s->m.p_tex_bits; yading@10: yading@10: emms_c(); yading@10: yading@10: pkt->size = ff_rac_terminate(c); yading@10: if (avctx->coded_frame->key_frame) yading@10: pkt->flags |= AV_PKT_FLAG_KEY; yading@10: *got_packet = 1; yading@10: yading@10: return 0; yading@10: } yading@10: yading@10: static av_cold int encode_end(AVCodecContext *avctx) yading@10: { yading@10: SnowContext *s = avctx->priv_data; yading@10: yading@10: ff_snow_common_end(s); yading@10: av_frame_unref(&s->input_picture); yading@10: av_free(avctx->stats_out); yading@10: yading@10: return 0; yading@10: } yading@10: yading@10: #define OFFSET(x) offsetof(SnowContext, x) yading@10: #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM yading@10: static const AVOption options[] = { yading@10: { "memc_only", "Only do ME/MC (I frames -> ref, P frame -> ME+MC).", OFFSET(memc_only), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, yading@10: { "no_bitstream", "Skip final bitstream writeout.", OFFSET(no_bitstream), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, yading@10: { NULL }, yading@10: }; yading@10: yading@10: static const AVClass snowenc_class = { yading@10: .class_name = "snow encoder", yading@10: .item_name = av_default_item_name, yading@10: .option = options, yading@10: .version = LIBAVUTIL_VERSION_INT, yading@10: }; yading@10: yading@10: AVCodec ff_snow_encoder = { yading@10: .name = "snow", yading@10: .type = AVMEDIA_TYPE_VIDEO, yading@10: .id = AV_CODEC_ID_SNOW, yading@10: .priv_data_size = sizeof(SnowContext), yading@10: .init = encode_init, yading@10: .encode2 = encode_frame, yading@10: .close = encode_end, yading@10: .pix_fmts = (const enum AVPixelFormat[]){ yading@10: AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV444P, yading@10: AV_PIX_FMT_NONE yading@10: }, yading@10: .long_name = NULL_IF_CONFIG_SMALL("Snow"), yading@10: .priv_class = &snowenc_class, yading@10: }; yading@10: yading@10: yading@10: #ifdef TEST yading@10: #undef malloc yading@10: #undef free yading@10: #undef printf yading@10: yading@10: #include "libavutil/lfg.h" yading@10: #include "libavutil/mathematics.h" yading@10: yading@10: int main(void){ yading@10: #define width 256 yading@10: #define height 256 yading@10: int buffer[2][width*height]; yading@10: SnowContext s; yading@10: int i; yading@10: AVLFG prng; yading@10: s.spatial_decomposition_count=6; yading@10: s.spatial_decomposition_type=1; yading@10: yading@10: s.temp_dwt_buffer = av_mallocz(width * sizeof(DWTELEM)); yading@10: s.temp_idwt_buffer = av_mallocz(width * sizeof(IDWTELEM)); yading@10: yading@10: av_lfg_init(&prng, 1); yading@10: yading@10: printf("testing 5/3 DWT\n"); yading@10: for(i=0; i20) printf("fsck: %6d %12d %7d\n",i, buffer[0][i], buffer[1][i]); yading@10: yading@10: { yading@10: int level, orientation, x, y; yading@10: int64_t errors[8][4]; yading@10: int64_t g=0; yading@10: yading@10: memset(errors, 0, sizeof(errors)); yading@10: s.spatial_decomposition_count=3; yading@10: s.spatial_decomposition_type=0; yading@10: for(level=0; level> (s.spatial_decomposition_count-level); yading@10: int h= height >> (s.spatial_decomposition_count-level); yading@10: int stride= width << (s.spatial_decomposition_count-level); yading@10: DWTELEM *buf= buffer[0]; yading@10: int64_t error=0; yading@10: yading@10: if(orientation&1) buf+=w; yading@10: if(orientation>1) buf+=stride>>1; yading@10: yading@10: memset(buffer[0], 0, sizeof(int)*width*height); yading@10: buf[w/2 + h/2*stride]= 256*256; yading@10: ff_spatial_idwt((IDWTELEM*)buffer[0], s.temp_idwt_buffer, width, height, width, s.spatial_decomposition_type, s.spatial_decomposition_count); yading@10: for(y=0; y> (s.spatial_decomposition_count-level); yading@10: //int h= height >> (s.spatial_decomposition_count-level); yading@10: int stride= width << (s.spatial_decomposition_count-level); yading@10: DWTELEM *buf= buffer[0]; yading@10: int64_t error=0; yading@10: yading@10: buf+=w; yading@10: buf+=stride>>1; yading@10: yading@10: memset(buffer[0], 0, sizeof(int)*width*height); yading@10: for(y=0; y