Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- From 0d90ea4ec79409199d6d8b82ac02043dce919ad5 Mon Sep 17 00:00:00 2001
- From: Stanislav Dolganov <dolganov@qst.hk>
- Date: Thu, 18 Aug 2016 14:07:35 +0300
- Subject: [PATCH 1/4] factoring obmc out of snow
- ---
- libavcodec/Makefile | 8 +-
- libavcodec/obmc.c | 61 ++
- libavcodec/obmc.h | 45 ++
- libavcodec/obme.c | 1135 +++++++++++++++++++++++++++++++++++++
- libavcodec/obme.h | 58 ++
- libavcodec/obmemc.c | 651 +++++++++++++++++++++
- libavcodec/obmemc.h | 522 +++++++++++++++++
- libavcodec/obmemc_data.h | 132 +++++
- libavcodec/snow.c | 571 +------------------
- libavcodec/snow.h | 356 +-----------
- libavcodec/snowdata.h | 132 -----
- libavcodec/snowdec.c | 234 +++-----
- libavcodec/snowenc.c | 1409 ++++++++--------------------------------------
- 13 files changed, 2939 insertions(+), 2375 deletions(-)
- create mode 100644 libavcodec/obmc.c
- create mode 100644 libavcodec/obmc.h
- create mode 100644 libavcodec/obme.c
- create mode 100644 libavcodec/obme.h
- create mode 100644 libavcodec/obmemc.c
- create mode 100644 libavcodec/obmemc.h
- create mode 100644 libavcodec/obmemc_data.h
- delete mode 100644 libavcodec/snowdata.h
- diff --git a/libavcodec/Makefile b/libavcodec/Makefile
- index b375720..dbbf9a1 100644
- --- a/libavcodec/Makefile
- +++ b/libavcodec/Makefile
- @@ -511,9 +511,11 @@ OBJS-$(CONFIG_SMACKAUD_DECODER) += smacker.o
- OBJS-$(CONFIG_SMACKER_DECODER) += smacker.o
- OBJS-$(CONFIG_SMC_DECODER) += smc.o
- OBJS-$(CONFIG_SMVJPEG_DECODER) += smvjpegdec.o
- -OBJS-$(CONFIG_SNOW_DECODER) += snowdec.o snow.o snow_dwt.o
- -OBJS-$(CONFIG_SNOW_ENCODER) += snowenc.o snow.o snow_dwt.o \
- - h263.o ituh263enc.o
- +OBJS-$(CONFIG_SNOW_DECODER) += snowdec.o snow.o snow_dwt.o\
- + obmemc.o obmc.o
- +OBJS-$(CONFIG_SNOW_ENCODER) += snowenc.o snow.o snow_dwt.o\
- + h263.o ituh263enc.o\
- + obmemc.o obme.o
- OBJS-$(CONFIG_SOL_DPCM_DECODER) += dpcm.o
- OBJS-$(CONFIG_SONIC_DECODER) += sonic.o
- OBJS-$(CONFIG_SONIC_ENCODER) += sonic.o
- diff --git a/libavcodec/obmc.c b/libavcodec/obmc.c
- new file mode 100644
- index 0000000..fccad24
- --- /dev/null
- +++ b/libavcodec/obmc.c
- @@ -0,0 +1,61 @@
- +/*
- + * Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at>
- + *
- + * This file is part of FFmpeg.
- + *
- + * FFmpeg is free software; you can redistribute it and/or
- + * modify it under the terms of the GNU Lesser General Public
- + * License as published by the Free Software Foundation; either
- + * version 2.1 of the License, or (at your option) any later version.
- + *
- + * FFmpeg is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- + * Lesser General Public License for more details.
- + *
- + * You should have received a copy of the GNU Lesser General Public
- + * License along with FFmpeg; if not, write to the Free Software
- + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- + */
- +
- + #include "obmc.h"
- +
- +int ff_obmc_decode_init(OBMCContext *f) {
- + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(f->avctx->pix_fmt);
- + if (!desc)
- + return AVERROR_INVALIDDATA;
- + int i;
- + f->nb_planes = 0;
- + for (i = 0; i < desc->nb_components; i++)
- + f->nb_planes = FFMAX(f->nb_planes, desc->comp[i].plane + 1);
- +
- + avcodec_get_chroma_sub_sample(f->avctx->pix_fmt, &f->chroma_h_shift, &f->chroma_v_shift);
- +
- + return 0;
- +}
- +
- +int ff_obmc_predecode_frame(OBMCContext *f) {
- + int plane_index, ret;
- + for(plane_index=0; plane_index < f->nb_planes; plane_index++){
- + PlaneObmc *pc= &f->plane[plane_index];
- + pc->fast_mc= pc->diag_mc && pc->htaps==6 && pc->hcoeff[0]==40
- + && pc->hcoeff[1]==-10
- + && pc->hcoeff[2]==2;
- + }
- +
- + if ((ret = ff_obmc_alloc_blocks(f)) < 0)
- + return ret;
- +
- + if ((ret = ff_obmc_frame_start(f)) < 0)
- + return ret;
- +
- + f->current_picture->pict_type = f->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
- +
- + av_assert0(!f->avmv);
- + if (f->avctx->flags2 & AV_CODEC_FLAG2_EXPORT_MVS) {
- + f->avmv = av_malloc_array(f->b_width * f->b_height, sizeof(AVMotionVector) << (f->block_max_depth*2));
- + }
- + f->avmv_index = 0;
- +
- + return 0;
- +}
- diff --git a/libavcodec/obmc.h b/libavcodec/obmc.h
- new file mode 100644
- index 0000000..1e218b1
- --- /dev/null
- +++ b/libavcodec/obmc.h
- @@ -0,0 +1,45 @@
- +/*
- + * Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at>
- + *
- + * This file is part of FFmpeg.
- + *
- + * FFmpeg is free software; you can redistribute it and/or
- + * modify it under the terms of the GNU Lesser General Public
- + * License as published by the Free Software Foundation; either
- + * version 2.1 of the License, or (at your option) any later version.
- + *
- + * FFmpeg is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- + * Lesser General Public License for more details.
- + *
- + * You should have received a copy of the GNU Lesser General Public
- + * License along with FFmpeg; if not, write to the Free Software
- + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- + */
- +
- + /**
- + * @file obmc.h
- + * @brief Overlapped block motion compensation functions
- + */
- +
- +#ifndef AVCODEC_OBMC_H
- +#define AVCODEC_OBMC_H
- +
- +#include "obmemc.h"
- +
- + /**
- + * Inits OBMC context parameters needed for decoding process
- + *
- + * @param[in,out] f OBMC context to init
- + */
- +int ff_obmc_decode_init(OBMCContext *f);
- +
- + /**
- + * Prepares OBMC context for block decoding for each frame
- + *
- + * @param[in,out] f OBMC context to prepare
- + */
- +int ff_obmc_predecode_frame(OBMCContext *f);
- +
- +#endif /* AVCODEC_OBMC_H */
- diff --git a/libavcodec/obme.c b/libavcodec/obme.c
- new file mode 100644
- index 0000000..f442b26
- --- /dev/null
- +++ b/libavcodec/obme.c
- @@ -0,0 +1,1135 @@
- +/*
- + * Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at>
- + *
- + * This file is part of FFmpeg.
- + *
- + * FFmpeg is free software; you can redistribute it and/or
- + * modify it under the terms of the GNU Lesser General Public
- + * License as published by the Free Software Foundation; either
- + * version 2.1 of the License, or (at your option) any later version.
- + *
- + * FFmpeg is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- + * Lesser General Public License for more details.
- + *
- + * You should have received a copy of the GNU Lesser General Public
- + * License along with FFmpeg; if not, write to the Free Software
- + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- + */
- +
- +#include "obme.h"
- +#include "h263.h"
- +
- +int ff_obmc_encode_init(OBMCContext *s, AVCodecContext *avctx)
- +{
- + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt);
- + if (!desc)
- + return AVERROR_INVALIDDATA;
- + int plane_index, ret;
- + int i;
- +
- + #if FF_API_MOTION_EST
- + FF_DISABLE_DEPRECATION_WARNINGS
- + if (avctx->me_method == ME_ITER)
- + s->motion_est = FF_ME_ITER;
- + FF_ENABLE_DEPRECATION_WARNINGS
- + #endif
- +
- + s->mv_scale = (avctx->flags & AV_CODEC_FLAG_QPEL) ? 2 : 4;
- + s->block_max_depth= (avctx->flags & AV_CODEC_FLAG_4MV ) ? 1 : 0;
- +
- + avcodec_get_chroma_sub_sample(avctx->pix_fmt, &s->chroma_h_shift, &s->chroma_v_shift);
- +
- + for(plane_index=0; plane_index<3; plane_index++){
- + s->plane[plane_index].diag_mc= 1;
- + s->plane[plane_index].htaps= 6;
- + s->plane[plane_index].hcoeff[0]= 40;
- + s->plane[plane_index].hcoeff[1]= -10;
- + s->plane[plane_index].hcoeff[2]= 2;
- + s->plane[plane_index].fast_mc= 1;
- + }
- +
- + ff_mpegvideoencdsp_init(&s->mpvencdsp, avctx);
- +
- + if ((ret = ff_obmc_alloc_blocks(s)) < 0)
- + return ret;
- +
- + s->m.avctx = avctx;
- + s->m.bit_rate= avctx->bit_rate;
- +
- + s->m.me.temp =
- + s->m.me.scratchpad= av_mallocz_array((avctx->width+64), 2*16*2*sizeof(uint8_t));
- + s->m.me.map = av_mallocz(ME_MAP_SIZE*sizeof(uint32_t));
- + s->m.me.score_map = av_mallocz(ME_MAP_SIZE*sizeof(uint32_t));
- + s->m.sc.obmc_scratchpad= av_mallocz(MB_SIZE*MB_SIZE*12*sizeof(uint32_t));
- + if (!s->m.me.scratchpad || !s->m.me.map || !s->m.me.score_map || !s->m.sc.obmc_scratchpad)
- + return AVERROR(ENOMEM);
- +
- + ff_h263_encode_init(&s->m); //mv_penalty
- +
- + s->max_ref_frames = av_clip(avctx->refs, 1, MAX_REF_FRAMES);
- +
- + s->nb_planes = 0;
- + for (i = 0; i < desc->nb_components; i++)
- + s->nb_planes = FFMAX(s->nb_planes, desc->comp[i].plane + 1);
- +
- + ff_set_cmp(&s->mecc, s->mecc.me_cmp, s->avctx->me_cmp);
- + ff_set_cmp(&s->mecc, s->mecc.me_sub_cmp, s->avctx->me_sub_cmp);
- +
- + s->input_picture = av_frame_alloc();
- + if (!s->input_picture)
- + return AVERROR(ENOMEM);
- +
- + if ((ret = ff_obmc_get_buffer(s, s->input_picture)) < 0)
- + return ret;
- +
- + if(s->motion_est == FF_ME_ITER){
- + 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_array(size, sizeof(int16_t[2]));
- + s->ref_scores[i]= av_mallocz_array(size, sizeof(uint32_t));
- + if (!s->ref_mvs[i] || !s->ref_scores[i])
- + return AVERROR(ENOMEM);
- + }
- + }
- +
- + return 0;
- +}
- +
- +//near copy & paste from dsputil, FIXME
- +static int pix_sum(uint8_t * pix, int line_size, int w, int h)
- +{
- + int s, i, j;
- +
- + s = 0;
- + for (i = 0; i < h; i++) {
- + for (j = 0; j < w; j++) {
- + s += pix[0];
- + pix ++;
- + }
- + pix += line_size - w;
- + }
- + return s;
- +}
- +
- +//near copy & paste from dsputil, FIXME
- +static int pix_norm1(uint8_t * pix, int line_size, int w)
- +{
- + int s, i, j;
- + uint32_t *sq = ff_square_tab + 256;
- +
- + s = 0;
- + for (i = 0; i < w; i++) {
- + for (j = 0; j < w; j ++) {
- + s += sq[pix[0]];
- + pix ++;
- + }
- + pix += line_size - w;
- + }
- + return s;
- +}
- +
- +static inline int get_penalty_factor(int lambda, int lambda2, int type){
- + switch(type&0xFF){
- + default:
- + case FF_CMP_SAD:
- + return lambda>>FF_LAMBDA_SHIFT;
- + case FF_CMP_DCT:
- + return (3*lambda)>>(FF_LAMBDA_SHIFT+1);
- + case FF_CMP_W53:
- + return (4*lambda)>>(FF_LAMBDA_SHIFT);
- + case FF_CMP_W97:
- + return (2*lambda)>>(FF_LAMBDA_SHIFT);
- + case FF_CMP_SATD:
- + case FF_CMP_DCT264:
- + return (2*lambda)>>FF_LAMBDA_SHIFT;
- + case FF_CMP_RD:
- + case FF_CMP_PSNR:
- + case FF_CMP_SSE:
- + case FF_CMP_NSSE:
- + return lambda2>>FF_LAMBDA_SHIFT;
- + case FF_CMP_BIT:
- + return 1;
- + }
- +}
- +
- +//FIXME copy&paste
- +#define P_LEFT P[1]
- +#define P_TOP P[2]
- +#define P_TOPRIGHT P[3]
- +#define P_MEDIAN P[4]
- +#define P_MV1 P[9]
- +#define FLAG_QPEL 1 //must be 1
- +
- +static int encode_q_branch(OBMCContext *s, int level, int x, int y)
- +{
- + ObmcCoderContext *const rc = &s->obmc_coder;
- + ObmcCoderContext pc, ic;
- + int score, score2, iscore, block_s, sum;;
- + const int w= s->b_width << s->block_max_depth;
- + const int h= s->b_height << s->block_max_depth;
- + const int rem_depth= s->block_max_depth - level;
- + const int index= (x + y*w) << rem_depth;
- + const int block_w= 1<<(LOG2_MB_SIZE - level);
- + int trx= (x+1)<<rem_depth;
- + int try= (y+1)<<rem_depth;
- + const BlockNode *left = x ? &s->block[index-1] : &null_block;
- + const BlockNode *top = y ? &s->block[index-w] : &null_block;
- + const BlockNode *right = trx<w ? &s->block[index+1] : &null_block;
- + const BlockNode *bottom= try<h ? &s->block[index+w] : &null_block;
- + const BlockNode *tl = y && x ? &s->block[index-w-1] : left;
- + const BlockNode *tr = y && trx<w && ((x&1)==0 || level==0) ? &s->block[index-w+(1<<rem_depth)] : tl; //FIXME use lt
- + int pl = left->color[0];
- + int pcb= left->color[1];
- + int pcr= left->color[2];
- + int pmx, pmy;
- + int mx=0, my=0;
- + int l,cr,cb;
- + const int stride= s->current_picture->linesize[0];
- + const int uvstride= s->current_picture->linesize[1];
- + uint8_t *current_data[3]= { s->input_picture->data[0] + (x + y* stride)*block_w,
- + s->input_picture->data[1] + ((x*block_w)>>s->chroma_h_shift) + ((y*uvstride*block_w)>>s->chroma_v_shift),
- + s->input_picture->data[2] + ((x*block_w)>>s->chroma_h_shift) + ((y*uvstride*block_w)>>s->chroma_v_shift)};
- + int P[10][2];
- + int16_t last_mv[3][2];
- + int qpel= !!(s->avctx->flags & AV_CODEC_FLAG_QPEL); //unused
- + const int shift= 1+qpel;
- + MotionEstContext *c= &s->m.me;
- + int ref_context= av_log2(2*left->ref) + av_log2(2*top->ref);
- + int mx_context= av_log2(2*FFABS(left->mx - top->mx));
- + int my_context= av_log2(2*FFABS(left->my - top->my));
- + int s_context= 2*left->level + 2*top->level + tl->level + tr->level;
- + int ref, best_ref, ref_score, ref_mx, ref_my;
- +
- + if(s->keyframe){
- + set_blocks(s, level, x, y, pl, pcb, pcr, 0, 0, 0, BLOCK_INTRA);
- + return 0;
- + }
- +
- +// clip predictors / edge ?
- +
- + P_LEFT[0]= left->mx;
- + P_LEFT[1]= left->my;
- + P_TOP [0]= top->mx;
- + P_TOP [1]= top->my;
- + P_TOPRIGHT[0]= tr->mx;
- + P_TOPRIGHT[1]= tr->my;
- +
- + last_mv[0][0]= s->block[index].mx;
- + last_mv[0][1]= s->block[index].my;
- + last_mv[1][0]= right->mx;
- + last_mv[1][1]= right->my;
- + last_mv[2][0]= bottom->mx;
- + last_mv[2][1]= bottom->my;
- +
- + s->m.mb_stride=2;
- + s->m.mb_x=
- + s->m.mb_y= 0;
- + c->skip= 0;
- +
- + av_assert1(c-> stride == stride);
- + av_assert1(c->uvstride == uvstride);
- +
- + c->penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_cmp);
- + c->sub_penalty_factor= get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_sub_cmp);
- + c->mb_penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->mb_cmp);
- + c->current_mv_penalty= c->mv_penalty[s->m.f_code=1] + MAX_DMV;
- +
- + c->xmin = - x*block_w - 16+3;
- + c->ymin = - y*block_w - 16+3;
- + c->xmax = - (x+1)*block_w + (w<<(LOG2_MB_SIZE - s->block_max_depth)) + 16-3;
- + c->ymax = - (y+1)*block_w + (h<<(LOG2_MB_SIZE - s->block_max_depth)) + 16-3;
- +
- + if(P_LEFT[0] > (c->xmax<<shift)) P_LEFT[0] = (c->xmax<<shift);
- + if(P_LEFT[1] > (c->ymax<<shift)) P_LEFT[1] = (c->ymax<<shift);
- + if(P_TOP[0] > (c->xmax<<shift)) P_TOP[0] = (c->xmax<<shift);
- + if(P_TOP[1] > (c->ymax<<shift)) P_TOP[1] = (c->ymax<<shift);
- + if(P_TOPRIGHT[0] < (c->xmin<<shift)) P_TOPRIGHT[0]= (c->xmin<<shift);
- + if(P_TOPRIGHT[0] > (c->xmax<<shift)) P_TOPRIGHT[0]= (c->xmax<<shift); //due to pmx no clip
- + if(P_TOPRIGHT[1] > (c->ymax<<shift)) P_TOPRIGHT[1]= (c->ymax<<shift);
- +
- + P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
- + P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
- +
- + if (!y) {
- + c->pred_x= P_LEFT[0];
- + c->pred_y= P_LEFT[1];
- + } else {
- + c->pred_x = P_MEDIAN[0];
- + c->pred_y = P_MEDIAN[1];
- + }
- +
- + score= INT_MAX;
- + best_ref= 0;
- + for(ref=0; ref<s->ref_frames; ref++){
- + init_ref(c, current_data, s->last_pictures[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);
- +
- + av_assert2(ref_mx >= c->xmin);
- + av_assert2(ref_mx <= c->xmax);
- + av_assert2(ref_my >= c->ymin);
- + av_assert2(ref_my <= c->ymax);
- +
- + ref_score= c->sub_motion_search(&s->m, &ref_mx, &ref_my, ref_score, 0, 0, level-LOG2_MB_SIZE+4, block_w);
- + ref_score= ff_get_mb_score(&s->m, ref_mx, ref_my, 0, 0, level-LOG2_MB_SIZE+4, block_w, 0);
- + ref_score+= 2*av_log2(2*ref)*c->penalty_factor;
- + if(s->ref_mvs[ref]){
- + s->ref_mvs[ref][index][0]= ref_mx;
- + s->ref_mvs[ref][index][1]= ref_my;
- + s->ref_scores[ref][index]= ref_score;
- + }
- + if(score > ref_score){
- + score= ref_score;
- + best_ref= ref;
- + mx= ref_mx;
- + my= ref_my;
- + }
- + }
- + //FIXME if mb_cmp != SSE then intra cannot be compared currently and mb_penalty vs. lambda2
- +
- + // subpel search
- + rc->init_frame_coder(s->avctx, &pc);
- +
- + if(level!=s->block_max_depth)
- + pc.put_level_break(&pc, 4 + s_context, 1);
- + pc.put_block_type(&pc, 1 + left->type + top->type, 0);
- + if(s->ref_frames > 1)
- + pc.put_best_ref(&pc, 128 + 1024 + 32*ref_context, best_ref);
- + pred_mv(s, &pmx, &pmy, best_ref, left, top, tr);
- + pc.put_block_mv(&pc,
- + 128 + 32*(mx_context + 16*!!best_ref), 128 + 32*(my_context + 16*!!best_ref),
- + mx - pmx, my - pmy
- + );
- + score += (s->lambda2*pc.get_bits(&pc))>>FF_LAMBDA_SHIFT;
- +
- + block_s= block_w*block_w;
- + sum = pix_sum(current_data[0], stride, block_w, block_w);
- + l= (sum + block_s/2)/block_s;
- + iscore = pix_norm1(current_data[0], stride, block_w) - 2*l*sum + l*l*block_s;
- +
- + if (s->nb_planes > 2) {
- + block_s= block_w*block_w>>(s->chroma_h_shift + s->chroma_v_shift);
- + sum = pix_sum(current_data[1], uvstride, block_w>>s->chroma_h_shift, block_w>>s->chroma_v_shift);
- + cb= (sum + block_s/2)/block_s;
- + // iscore += pix_norm1(¤t_mb[1][0], uvstride, block_w>>1) - 2*cb*sum + cb*cb*block_s;
- + sum = pix_sum(current_data[2], uvstride, block_w>>s->chroma_h_shift, block_w>>s->chroma_v_shift);
- + cr= (sum + block_s/2)/block_s;
- + // iscore += pix_norm1(¤t_mb[2][0], uvstride, block_w>>1) - 2*cr*sum + cr*cr*block_s;
- + }else
- + cb = cr = 0;
- +
- + rc->init_frame_coder(s->avctx, &ic);
- +
- + if(level!=s->block_max_depth)
- + ic.put_level_break(&ic, 4 + s_context, 1);
- + ic.put_block_type(&ic, 1 + left->type + top->type, 1);
- + ic.put_block_color(&ic, 32, 64, 96, l-pl, cb-pcb, cr-pcr);
- + iscore += (s->lambda2*ic.get_bits(&ic))>>FF_LAMBDA_SHIFT;
- +
- + av_assert1(iscore < 255*255*256 + s->lambda2*10);
- + av_assert1(iscore >= 0);
- + av_assert1(l>=0 && l<=255);
- + av_assert1(pl>=0 && pl<=255);
- +
- + if(level==0){
- + int varc= iscore >> 8;
- + int vard= score >> 8;
- + if (vard <= 64 || vard < varc)
- + c->scene_change_score+= ff_sqrt(vard) - ff_sqrt(varc);
- + else
- + c->scene_change_score+= s->m.qscale;
- + }
- +
- + if(level!=s->block_max_depth){
- + rc->put_level_break(rc, 4 + s_context, 0);
- + score2 = encode_q_branch(s, level+1, 2*x+0, 2*y+0);
- + score2+= encode_q_branch(s, level+1, 2*x+1, 2*y+0);
- + score2+= encode_q_branch(s, level+1, 2*x+0, 2*y+1);
- + score2+= encode_q_branch(s, level+1, 2*x+1, 2*y+1);
- + score2+= s->lambda2>>FF_LAMBDA_SHIFT; //FIXME exact split overhead
- +
- + if(score2 < score && score2 < iscore) {
- + rc->free(&ic); rc->free(&pc);
- + return score2;
- + }
- + }
- +
- + if(iscore < score){
- + pred_mv(s, &pmx, &pmy, 0, left, top, tr);
- + rc->copy_coder(&ic);
- + set_blocks(s, level, x, y, l, cb, cr, pmx, pmy, 0, BLOCK_INTRA);
- + rc->free(&ic); rc->free(&pc);
- + return iscore;
- + }else{
- + rc->copy_coder(&pc);
- + set_blocks(s, level, x, y, pl, pcb, pcr, mx, my, best_ref, 0);
- + rc->free(&ic); rc->free(&pc);
- + return score;
- + }
- +}
- +
- +static void encode_q_branch2(OBMCContext *s, int level, int x, int y)
- +{
- + ObmcCoderContext *const rc = &s->obmc_coder;
- + const int w= s->b_width << s->block_max_depth;
- + const int rem_depth= s->block_max_depth - level;
- + const int index= (x + y*w) << rem_depth;
- + int trx= (x+1)<<rem_depth;
- + BlockNode *b= &s->block[index];
- + const BlockNode *left = x ? &s->block[index-1] : &null_block;
- + const BlockNode *top = y ? &s->block[index-w] : &null_block;
- + const BlockNode *tl = y && x ? &s->block[index-w-1] : left;
- + const BlockNode *tr = y && trx<w && ((x&1)==0 || level==0) ? &s->block[index-w+(1<<rem_depth)] : tl; //FIXME use lt
- + int pl = left->color[0];
- + int pcb= left->color[1];
- + int pcr= left->color[2];
- + int pmx, pmy;
- + int ref_context= av_log2(2*left->ref) + av_log2(2*top->ref);
- + int mx_context= av_log2(2*FFABS(left->mx - top->mx)) + 16*!!b->ref;
- + int my_context= av_log2(2*FFABS(left->my - top->my)) + 16*!!b->ref;
- + int s_context= 2*left->level + 2*top->level + tl->level + tr->level;
- +
- + if(s->keyframe){
- + set_blocks(s, level, x, y, pl, pcb, pcr, 0, 0, 0, BLOCK_INTRA);
- + return;
- + }
- +
- + if(level!=s->block_max_depth){
- + if(same_block(b,b+1) && same_block(b,b+w) && same_block(b,b+w+1)){
- + rc->put_level_break(rc, 4 + s_context, 1);
- + }else{
- + rc->put_level_break(rc, 4 + s_context, 0);
- + encode_q_branch2(s, level+1, 2*x+0, 2*y+0);
- + encode_q_branch2(s, level+1, 2*x+1, 2*y+0);
- + encode_q_branch2(s, level+1, 2*x+0, 2*y+1);
- + encode_q_branch2(s, level+1, 2*x+1, 2*y+1);
- + return;
- + }
- + }
- + if(b->type & BLOCK_INTRA){
- + pred_mv(s, &pmx, &pmy, 0, left, top, tr);
- + rc->put_block_type(rc, 1 + (left->type&1) + (top->type&1), 1);
- + rc->put_block_color(
- + rc,
- + 32, 64, 96,
- + b->color[0]-pl, b->color[1]-pcb, b->color[2]-pcr
- + );
- + set_blocks(s, level, x, y, b->color[0], b->color[1], b->color[2], pmx, pmy, 0, BLOCK_INTRA);
- + }else{
- + pred_mv(s, &pmx, &pmy, b->ref, left, top, tr);
- + rc->put_block_type(rc, 1 + (left->type&1) + (top->type&1), 0);
- + if(s->ref_frames > 1)
- + rc->put_best_ref(rc, 128 + 1024 + 32*ref_context, b->ref);
- + rc->put_block_mv(rc,
- + 128 + 32*mx_context, 128 + 32*my_context,
- + b->mx - pmx, b->my - pmy
- + );
- + set_blocks(s, level, x, y, pl, pcb, pcr, b->mx, b->my, b->ref, 0);
- + }
- +}
- +
- +static int get_dc(OBMCContext *s, int mb_x, int mb_y, int plane_index){
- + int i, x2, y2;
- + PlaneObmc *p= &s->plane[plane_index];
- + const int block_size = MB_SIZE >> s->block_max_depth;
- + const int block_w = plane_index ? block_size>>s->chroma_h_shift : block_size;
- + const int block_h = plane_index ? block_size>>s->chroma_v_shift : block_size;
- + const uint8_t *obmc = plane_index ? ff_obmc_tab[s->block_max_depth+s->chroma_h_shift] : ff_obmc_tab[s->block_max_depth];
- + const int obmc_stride= plane_index ? (2*block_size)>>s->chroma_h_shift : 2*block_size;
- + const int ref_stride= s->current_picture->linesize[plane_index];
- + uint8_t *src= s-> input_picture->data[plane_index];
- + IDWTELEM *dst= (IDWTELEM*)s->m.sc.obmc_scratchpad + plane_index*block_size*block_size*4; //FIXME change to unsigned
- + const int b_stride = s->b_width << s->block_max_depth;
- + const int w= p->width;
- + const int h= p->height;
- + int index= mb_x + mb_y*b_stride;
- + BlockNode *b= &s->block[index];
- + BlockNode backup= *b;
- + int ab=0;
- + int aa=0;
- +
- + av_assert2(s->chroma_h_shift == s->chroma_v_shift); //obmc stuff above
- +
- + b->type|= BLOCK_INTRA;
- + b->color[plane_index]= 0;
- + memset(dst, 0, obmc_stride*obmc_stride*sizeof(IDWTELEM));
- +
- + for(i=0; i<4; i++){
- + int mb_x2= mb_x + (i &1) - 1;
- + int mb_y2= mb_y + (i>>1) - 1;
- + int x= block_w*mb_x2 + block_w/2;
- + int y= block_h*mb_y2 + block_h/2;
- +
- + add_yblock(s, 0, NULL, dst + (i&1)*block_w + (i>>1)*obmc_stride*block_h, NULL, obmc,
- + x, y, block_w, block_h, 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_h); y2++){
- + for(x2= FFMAX(x, 0); x2<FFMIN(w, x+block_w); x2++){
- + int index= x2-(block_w*mb_x - block_w/2) + (y2-(block_h*mb_y - block_h/2))*obmc_stride;
- + int obmc_v= obmc[index];
- + int d;
- + if(y<0) obmc_v += obmc[index + block_h*obmc_stride];
- + if(x<0) obmc_v += obmc[index + block_w];
- + if(y+block_h>h) obmc_v += obmc[index - block_h*obmc_stride];
- + if(x+block_w>w) obmc_v += obmc[index - block_w];
- + //FIXME precalculate this or simplify it somehow else
- +
- + d = -dst[index] + (1<<(FRAC_BITS-1));
- + dst[index] = d;
- + ab += (src[x2 + y2*ref_stride] - (d>>FRAC_BITS)) * obmc_v;
- + aa += obmc_v * obmc_v; //FIXME precalculate this
- + }
- + }
- + }
- + *b= backup;
- +
- + return av_clip_uint8( ROUNDED_DIV(ab<<LOG2_OBMC_MAX, aa) ); //FIXME we should not need clipping
- +}
- +
- +static inline int get_block_bits(OBMCContext *s, int x, int y, int w){
- + const int b_stride = s->b_width << s->block_max_depth;
- + const int b_height = s->b_height<< s->block_max_depth;
- + int index= x + y*b_stride;
- + const BlockNode *b = &s->block[index];
- + const BlockNode *left = x ? &s->block[index-1] : &null_block;
- + const BlockNode *top = y ? &s->block[index-b_stride] : &null_block;
- + const BlockNode *tl = y && x ? &s->block[index-b_stride-1] : left;
- + const BlockNode *tr = y && x+w<b_stride ? &s->block[index-b_stride+w] : tl;
- + int dmx, dmy;
- +// int mx_context= av_log2(2*FFABS(left->mx - top->mx));
- +// int my_context= av_log2(2*FFABS(left->my - top->my));
- +
- + if(x<0 || x>=b_stride || y>=b_height)
- + return 0;
- +/*
- +1 0 0
- +01X 1-2 1
- +001XX 3-6 2-3
- +0001XXX 7-14 4-7
- +00001XXXX 15-30 8-15
- +*/
- +//FIXME try accurate rate
- +//FIXME intra and inter predictors if surrounding blocks are not the same type
- + if(b->type & BLOCK_INTRA){
- + return 3+2*( av_log2(2*FFABS(left->color[0] - b->color[0]))
- + + av_log2(2*FFABS(left->color[1] - b->color[1]))
- + + av_log2(2*FFABS(left->color[2] - b->color[2])));
- + }else{
- + pred_mv(s, &dmx, &dmy, b->ref, left, top, tr);
- + dmx-= b->mx;
- + dmy-= b->my;
- + return 2*(1 + av_log2(2*FFABS(dmx)) //FIXME kill the 2* can be merged in lambda
- + + av_log2(2*FFABS(dmy))
- + + av_log2(2*b->ref));
- + }
- +}
- +
- +static int get_block_rd(OBMCContext *s, int mb_x, int mb_y, int plane_index, uint8_t (*obmc_edged)[MB_SIZE * 2]){
- + PlaneObmc *p= &s->plane[plane_index];
- + const int block_size = MB_SIZE >> s->block_max_depth;
- + const int block_w = plane_index ? block_size>>s->chroma_h_shift : block_size;
- + const int block_h = plane_index ? block_size>>s->chroma_v_shift : block_size;
- + const int obmc_stride= plane_index ? (2*block_size)>>s->chroma_h_shift : 2*block_size;
- + const int ref_stride= s->current_picture->linesize[plane_index];
- + uint8_t *dst= s->current_picture->data[plane_index];
- + uint8_t *src= s-> input_picture->data[plane_index];
- + IDWTELEM *pred= (IDWTELEM*)s->m.sc.obmc_scratchpad + plane_index*block_size*block_size*4;
- + uint8_t *cur = s->scratchbuf;
- + uint8_t *tmp = s->emu_edge_buffer;
- + const int b_stride = s->b_width << s->block_max_depth;
- + const int b_height = s->b_height<< s->block_max_depth;
- + const int w= p->width;
- + const int h= p->height;
- + int distortion;
- + int rate= 0;
- + const int penalty_factor= get_penalty_factor(s->lambda, s->lambda2, s->avctx->me_cmp);
- + int sx= block_w*mb_x - block_w/2;
- + int sy= block_h*mb_y - block_h/2;
- + int x0= FFMAX(0,-sx);
- + int y0= FFMAX(0,-sy);
- + int x1= FFMIN(block_w*2, w-sx);
- + int y1= FFMIN(block_h*2, h-sy);
- + int i,x,y;
- +
- + av_assert2(s->chroma_h_shift == s->chroma_v_shift); //obmc and square assumtions below chckinhg only block_w
- +
- + ff_obmc_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);
- +
- + for(y=y0; y<y1; y++){
- + const uint8_t *obmc1= obmc_edged[y];
- + const IDWTELEM *pred1 = pred + y*obmc_stride;
- + uint8_t *cur1 = cur + y*ref_stride;
- + uint8_t *dst1 = dst + sx + (sy+y)*ref_stride;
- + for(x=x0; x<x1; x++){
- +#if FRAC_BITS >= LOG2_OBMC_MAX
- + int v = (cur1[x] * obmc1[x]) << (FRAC_BITS - LOG2_OBMC_MAX);
- +#else
- + int v = (cur1[x] * obmc1[x] + (1<<(LOG2_OBMC_MAX - FRAC_BITS-1))) >> (LOG2_OBMC_MAX - FRAC_BITS);
- +#endif
- + v = (v + pred1[x]) >> FRAC_BITS;
- + if(v&(~255)) v= ~(v>>31);
- + dst1[x] = v;
- + }
- + }
- +
- + /* copy the regions where obmc[] = (uint8_t)256 */
- + if(LOG2_OBMC_MAX == 8
- + && (mb_x == 0 || mb_x == b_stride-1)
- + && (mb_y == 0 || mb_y == b_height-1)){
- + if(mb_x == 0)
- + x1 = block_w;
- + else
- + x0 = block_w;
- + if(mb_y == 0)
- + y1 = block_h;
- + else
- + y0 = block_h;
- + for(y=y0; y<y1; y++)
- + memcpy(dst + sx+x0 + (sy+y)*ref_stride, cur + x0 + y*ref_stride, x1-x0);
- + }
- +
- + if(block_w==16){
- + /* FIXME rearrange dsputil to fit 32x32 cmp functions */
- + /* FIXME check alignment of the cmp wavelet vs the encoding wavelet */
- + /* FIXME cmps overlap but do not cover the wavelet's whole support.
- + * So improving the score of one block is not strictly guaranteed
- + * to improve the score of the whole frame, thus iterative motion
- + * estimation does not always converge. */
- + if(s->avctx->me_cmp == FF_CMP_W97)
- + distortion = ff_w97_32_c(&s->m, src + sx + sy*ref_stride, dst + sx + sy*ref_stride, ref_stride, 32);
- + else if(s->avctx->me_cmp == FF_CMP_W53)
- + distortion = ff_w53_32_c(&s->m, src + sx + sy*ref_stride, dst + sx + sy*ref_stride, ref_stride, 32);
- + else{
- + distortion = 0;
- + for(i=0; i<4; i++){
- + int off = sx+16*(i&1) + (sy+16*(i>>1))*ref_stride;
- + distortion += s->mecc.me_cmp[0](&s->m, src + off, dst + off, ref_stride, 16);
- + }
- + }
- + }else{
- + av_assert2(block_w==8);
- + distortion = s->mecc.me_cmp[0](&s->m, src + sx + sy*ref_stride, dst + sx + sy*ref_stride, ref_stride, block_w*2);
- + }
- +
- + if(plane_index==0){
- + for(i=0; i<4; i++){
- +/* ..RRr
- + * .RXx.
- + * rxx..
- + */
- + rate += get_block_bits(s, mb_x + (i&1) - (i>>1), mb_y + (i>>1), 1);
- + }
- + if(mb_x == b_stride-2)
- + rate += get_block_bits(s, mb_x + 1, mb_y + 1, 1);
- + }
- + return distortion + rate*penalty_factor;
- +}
- +
- +static int get_4block_rd(OBMCContext *s, int mb_x, int mb_y, int plane_index){
- + int i, y2;
- + PlaneObmc *p= &s->plane[plane_index];
- + const int block_size = MB_SIZE >> s->block_max_depth;
- + const int block_w = plane_index ? block_size>>s->chroma_h_shift : block_size;
- + const int block_h = plane_index ? block_size>>s->chroma_v_shift : block_size;
- + const uint8_t *obmc = plane_index ? ff_obmc_tab[s->block_max_depth+s->chroma_h_shift] : ff_obmc_tab[s->block_max_depth];
- + const int obmc_stride= plane_index ? (2*block_size)>>s->chroma_h_shift : 2*block_size;
- + const int ref_stride= s->current_picture->linesize[plane_index];
- + uint8_t *dst= s->current_picture->data[plane_index];
- + uint8_t *src= s-> input_picture->data[plane_index];
- + //FIXME zero_dst is const but add_yblock changes dst if add is 0 (this is never the case for dst=zero_dst
- + // const has only been removed from zero_dst to suppress a warning
- + static IDWTELEM zero_dst[4096]; //FIXME
- + const int b_stride = s->b_width << s->block_max_depth;
- + const int w= p->width;
- + const int h= p->height;
- + int distortion= 0;
- + int rate= 0;
- + const int penalty_factor= get_penalty_factor(s->lambda, s->lambda2, s->avctx->me_cmp);
- +
- + av_assert2(s->chroma_h_shift == s->chroma_v_shift); //obmc and square assumtions below
- +
- + for(i=0; i<9; i++){
- + int mb_x2= mb_x + (i%3) - 1;
- + int mb_y2= mb_y + (i/3) - 1;
- + int x= block_w*mb_x2 + block_w/2;
- + int y= block_h*mb_y2 + block_h/2;
- +
- + add_yblock(s, 0, NULL, zero_dst, dst, obmc,
- + x, y, block_w, block_h, 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
- + for(y2= y; y2<0; y2++)
- + memcpy(dst + x + y2*ref_stride, src + x + y2*ref_stride, block_w);
- + for(y2= h; y2<y+block_h; y2++)
- + memcpy(dst + x + y2*ref_stride, src + x + y2*ref_stride, block_w);
- + if(x<0){
- + for(y2= y; y2<y+block_h; y2++)
- + memcpy(dst + x + y2*ref_stride, src + x + y2*ref_stride, -x);
- + }
- + if(x+block_w > w){
- + for(y2= y; y2<y+block_h; y2++)
- + memcpy(dst + w + y2*ref_stride, src + w + y2*ref_stride, x+block_w - w);
- + }
- +
- + av_assert1(block_w== 8 || block_w==16);
- + distortion += s->mecc.me_cmp[block_w==8](&s->m, src + x + y*ref_stride, dst + x + y*ref_stride, ref_stride, block_h);
- + }
- +
- + if(plane_index==0){
- + BlockNode *b= &s->block[mb_x+mb_y*b_stride];
- + int merged= same_block(b,b+1) && same_block(b,b+b_stride) && same_block(b,b+b_stride+1);
- +
- +/* ..RRRr
- + * .RXXx.
- + * .RXXx.
- + * rxxx.
- + */
- + if(merged)
- + rate = get_block_bits(s, mb_x, mb_y, 2);
- + for(i=merged?4:0; i<9; i++){
- + static const int dxy[9][2] = {{0,0},{1,0},{0,1},{1,1},{2,0},{2,1},{-1,2},{0,2},{1,2}};
- + rate += get_block_bits(s, mb_x + dxy[i][0], mb_y + dxy[i][1], 1);
- + }
- + }
- + return distortion + rate*penalty_factor;
- +}
- +
- +static av_always_inline int check_block(OBMCContext *s, int mb_x, int mb_y, int p[3], int intra, uint8_t (*obmc_edged)[MB_SIZE * 2], 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= *block;
- + unsigned value;
- + int rd, index;
- +
- + av_assert2(mb_x>=0 && mb_y>=0);
- + av_assert2(mb_x<b_stride);
- +
- + if(intra){
- + block->color[0] = p[0];
- + block->color[1] = p[1];
- + block->color[2] = p[2];
- + 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) + (block->ref<<12);
- + if(s->me_cache[index] == value)
- + return 0;
- + s->me_cache[index]= value;
- +
- + block->mx= p[0];
- + block->my= p[1];
- + block->type &= ~BLOCK_INTRA;
- + }
- +
- + rd= get_block_rd(s, mb_x, mb_y, 0, obmc_edged) + s->intra_penalty * !!intra;
- +
- +//FIXME chroma
- + if(rd < *best_rd){
- + *best_rd= rd;
- + return 1;
- + }else{
- + *block= backup;
- + return 0;
- + }
- +}
- +
- +/* special case for int[2] args we discard afterwards,
- + * fixes compilation problem with gcc 2.95 */
- +static av_always_inline int check_block_inter(OBMCContext *s, int mb_x, int mb_y, int p0, int p1, uint8_t (*obmc_edged)[MB_SIZE * 2], int *best_rd){
- + int p[2] = {p0, p1};
- + return check_block(s, mb_x, mb_y, p, 0, obmc_edged, best_rd);
- +}
- +
- +static av_always_inline int check_4block_inter(OBMCContext *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];
- + unsigned value;
- + int rd, index;
- +
- + /* We don't initialize backup[] during variable declaration, because
- + * that fails to compile on MSVC: "cannot convert from 'BlockNode' to
- + * 'int16_t'". */
- + backup[0] = block[0];
- + backup[1] = block[1];
- + backup[2] = block[b_stride];
- + backup[3] = block[b_stride + 1];
- +
- + av_assert2(mb_x>=0 && mb_y>=0);
- + av_assert2(mb_x<b_stride);
- + av_assert2(((mb_x|mb_y)&1) == 0);
- +
- + index= (p0 + 31*p1) & (ME_CACHE_SIZE-1);
- + 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;
- +
- + rd= get_4block_rd(s, mb_x, mb_y, 0);
- +
- +//FIXME chroma
- + if(rd < *best_rd){
- + *best_rd= rd;
- + return 1;
- + }else{
- + block[0]= backup[0];
- + block[1]= backup[1];
- + block[b_stride]= backup[2];
- + block[b_stride+1]= backup[3];
- + return 0;
- + }
- +}
- +
- +static void iterative_me(OBMCContext *s){
- + int pass, mb_x, mb_y;
- + 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;
- + int color[3];
- +
- + {
- + ObmcCoderContext r;
- + s->obmc_coder.init_frame_coder(s->avctx, &r);
- + for(mb_y= 0; mb_y<s->b_height; mb_y++)
- + for(mb_x= 0; mb_x<s->b_width; mb_x++)
- + encode_q_branch(s, 0, mb_x, mb_y);
- + s->obmc_coder.reset_coder(&r);
- + s->obmc_coder.free(&r);
- + }
- +
- + for(pass=0; pass<25; pass++){
- + int change= 0;
- +
- + 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, 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;
- + BlockNode *lb = mb_x ? &s->block[index -1] : NULL;
- + BlockNode *rb = mb_x+1<b_width ? &s->block[index +1] : NULL;
- + BlockNode *bb = mb_y+1<b_height ? &s->block[index+b_stride ] : NULL;
- + BlockNode *tlb= mb_x && mb_y ? &s->block[index-b_stride-1] : NULL;
- + BlockNode *trb= mb_x+1<b_width && mb_y ? &s->block[index-b_stride+1] : NULL;
- + BlockNode *blb= mb_x && mb_y+1<b_height ? &s->block[index+b_stride-1] : NULL;
- + BlockNode *brb= mb_x+1<b_width && mb_y+1<b_height ? &s->block[index+b_stride+1] : NULL;
- + const int b_w= (MB_SIZE >> s->block_max_depth);
- + uint8_t obmc_edged[MB_SIZE * 2][MB_SIZE * 2];
- +
- + if(pass && (block->type & BLOCK_OPT))
- + continue;
- + block->type |= BLOCK_OPT;
- +
- + backup= *block;
- +
- + if(!s->me_cache_generation)
- + memset(s->me_cache, 0, sizeof(s->me_cache));
- + s->me_cache_generation += 1<<22;
- +
- + //FIXME precalculate
- + {
- + int x, y;
- + for (y = 0; y < b_w * 2; y++)
- + memcpy(obmc_edged[y], ff_obmc_tab[s->block_max_depth] + y * b_w * 2, b_w * 2);
- + if(mb_x==0)
- + for(y=0; y<b_w*2; y++)
- + memset(obmc_edged[y], obmc_edged[y][0] + obmc_edged[y][b_w-1], b_w);
- + if(mb_x==b_stride-1)
- + for(y=0; y<b_w*2; y++)
- + memset(obmc_edged[y]+b_w, obmc_edged[y][b_w] + obmc_edged[y][b_w*2-1], b_w);
- + if(mb_y==0){
- + for(x=0; x<b_w*2; x++)
- + obmc_edged[0][x] += obmc_edged[b_w-1][x];
- + for(y=1; y<b_w; y++)
- + memcpy(obmc_edged[y], obmc_edged[0], b_w*2);
- + }
- + if(mb_y==b_height-1){
- + for(x=0; x<b_w*2; x++)
- + obmc_edged[b_w*2-1][x] += obmc_edged[b_w][x];
- + for(y=b_w; y<b_w*2-1; y++)
- + memcpy(obmc_edged[y], obmc_edged[b_w*2-1], b_w*2);
- + }
- + }
- +
- + //skip stuff outside the picture
- + if(mb_x==0 || mb_y==0 || mb_x==b_width-1 || mb_y==b_height-1){
- + uint8_t *src= s-> input_picture->data[0];
- + uint8_t *dst= s->current_picture->data[0];
- + const int stride= s->current_picture->linesize[0];
- + const int block_w= MB_SIZE >> s->block_max_depth;
- + const int block_h= MB_SIZE >> s->block_max_depth;
- + const int sx= block_w*mb_x - block_w/2;
- + const int sy= block_h*mb_y - block_h/2;
- + const int w= s->plane[0].width;
- + const int h= s->plane[0].height;
- + int y;
- +
- + for(y=sy; y<0; y++)
- + memcpy(dst + sx + y*stride, src + sx + y*stride, block_w*2);
- + for(y=h; y<sy+block_h*2; y++)
- + memcpy(dst + sx + y*stride, src + sx + y*stride, block_w*2);
- + if(sx<0){
- + for(y=sy; y<sy+block_h*2; y++)
- + memcpy(dst + sx + y*stride, src + sx + y*stride, -sx);
- + }
- + if(sx+block_w*2 > w){
- + for(y=sy; y<sy+block_h*2; y++)
- + memcpy(dst + w + y*stride, src + w + y*stride, sx+block_w*2 - w);
- + }
- + }
- +
- + // intra(black) = neighbors' contribution to the current block
- + for(i=0; i < s->nb_planes; i++)
- + color[i]= get_dc(s, mb_x, mb_y, i);
- +
- + // get previous score (cannot be cached due to OBMC)
- + if(pass > 0 && (block->type&BLOCK_INTRA)){
- + int color0[3]= {block->color[0], block->color[1], block->color[2]};
- + check_block(s, mb_x, mb_y, color0, 1, obmc_edged, &best_rd);
- + }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);
- + if(tb)
- + check_block_inter(s, mb_x, mb_y, mvr[-b_stride][0], mvr[-b_stride][1], obmc_edged, &best_rd);
- + if(lb)
- + check_block_inter(s, mb_x, mb_y, mvr[-1][0], mvr[-1][1], obmc_edged, &best_rd);
- + if(rb)
- + check_block_inter(s, mb_x, mb_y, mvr[1][0], mvr[1][1], obmc_edged, &best_rd);
- + if(bb)
- + 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 interpolation / round to nearest integer
- + do{
- + int newx = block->mx;
- + int newy = block->my;
- + int dia_size = s->iterative_dia_size ? s->iterative_dia_size : FFMAX(s->avctx->dia_size, 1);
- + dia_change=0;
- + for(i=0; i < dia_size; i++){
- + for(j=0; j<i; j++){
- + dia_change |= check_block_inter(s, mb_x, mb_y, newx+4*(i-j), newy+(4*j), obmc_edged, &best_rd);
- + dia_change |= check_block_inter(s, mb_x, mb_y, newx-4*(i-j), newy-(4*j), obmc_edged, &best_rd);
- + dia_change |= check_block_inter(s, mb_x, mb_y, newx-(4*j), newy+4*(i-j), obmc_edged, &best_rd);
- + dia_change |= check_block_inter(s, mb_x, mb_y, newx+(4*j), newy-4*(i-j), obmc_edged, &best_rd);
- + }
- + }
- + }while(dia_change);
- + /* subpel ME */
- + do{
- + static const int square[8][2]= {{+1, 0},{-1, 0},{ 0,+1},{ 0,-1},{+1,+1},{-1,-1},{+1,-1},{-1,+1},};
- + dia_change=0;
- + for(i=0; i<8; i++)
- + 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;
- + check_block(s, mb_x, mb_y, color, 1, obmc_edged, &best_rd);
- + //FIXME RD style color selection
- + if(!same_block(block, &backup)){
- + if(tb ) tb ->type &= ~BLOCK_OPT;
- + if(lb ) lb ->type &= ~BLOCK_OPT;
- + if(rb ) rb ->type &= ~BLOCK_OPT;
- + if(bb ) bb ->type &= ~BLOCK_OPT;
- + if(tlb) tlb->type &= ~BLOCK_OPT;
- + if(trb) trb->type &= ~BLOCK_OPT;
- + if(blb) blb->type &= ~BLOCK_OPT;
- + if(brb) brb->type &= ~BLOCK_OPT;
- + change ++;
- + }
- + }
- + }
- + av_log(s->avctx, AV_LOG_DEBUG, "pass:%d changed:%d\n", pass, change);
- + if(!change)
- + break;
- + }
- +
- + if(s->block_max_depth == 1){
- + int change= 0;
- + for(mb_y= 0; mb_y<b_height; mb_y+=2){
- + for(mb_x= 0; mb_x<b_width; mb_x+=2){
- + int i;
- + int best_rd, init_rd;
- + const int index= mb_x + mb_y * b_stride;
- + BlockNode *b[4];
- +
- + b[0]= &s->block[index];
- + b[1]= b[0]+1;
- + b[2]= b[0]+b_stride;
- + b[3]= b[2]+1;
- + if(same_block(b[0], b[1]) &&
- + same_block(b[0], b[2]) &&
- + same_block(b[0], b[3]))
- + continue;
- +
- + if(!s->me_cache_generation)
- + memset(s->me_cache, 0, sizeof(s->me_cache));
- + s->me_cache_generation += 1<<22;
- +
- + 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, 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, b[i]->ref, &best_rd);
- +
- + if(init_rd != best_rd)
- + change++;
- + }
- + }
- + av_log(s->avctx, AV_LOG_DEBUG, "pass:4mv changed:%d\n", change*4);
- + }
- +}
- +
- +static void encode_blocks(OBMCContext *s, int search){
- + int x, y;
- + int w= s->b_width;
- + int h= s->b_height;
- + ObmcCoderContext *const c = &s->obmc_coder;
- +
- + if(s->motion_est == FF_ME_ITER && !s->keyframe && search)
- + iterative_me(s);
- +
- + for(y=0; y<h; y++){
- + if(c->available_bytes(c) < w*MB_SIZE*MB_SIZE*3){ //FIXME nicer limit
- + av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
- + return;
- + }
- + for(x=0; x<w; x++){
- + if(s->motion_est == FF_ME_ITER || !search)
- + encode_q_branch2(s, 0, x, y);
- + else
- + encode_q_branch (s, 0, x, y);
- + }
- + }
- +}
- +
- +int ff_obmc_pre_encode_frame(OBMCContext *s, AVCodecContext *avctx, const AVFrame *pict)
- +{
- + const int width= s->avctx->width;
- + const int height= s->avctx->height;
- +
- + int ret;
- + if (s->current_picture->data[0]
- + #if FF_API_EMU_EDGE
- + && !(s->avctx->flags&CODEC_FLAG_EMU_EDGE)
- + #endif
- + ) {
- + int w = s->avctx->width;
- + int h = s->avctx->height;
- +
- + s->mpvencdsp.draw_edges(s->current_picture->data[0],
- + s->current_picture->linesize[0], w , h ,
- + EDGE_WIDTH , EDGE_WIDTH , EDGE_TOP | EDGE_BOTTOM);
- + if (s->current_picture->data[2]) {
- + s->mpvencdsp.draw_edges(s->current_picture->data[1],
- + s->current_picture->linesize[1], w>>s->chroma_h_shift, h>>s->chroma_v_shift,
- + EDGE_WIDTH>>s->chroma_h_shift, EDGE_WIDTH>>s->chroma_v_shift, EDGE_TOP | EDGE_BOTTOM);
- + s->mpvencdsp.draw_edges(s->current_picture->data[2],
- + s->current_picture->linesize[2], w>>s->chroma_h_shift, h>>s->chroma_v_shift,
- + EDGE_WIDTH>>s->chroma_h_shift, EDGE_WIDTH>>s->chroma_v_shift, EDGE_TOP | EDGE_BOTTOM);
- + }
- + }
- +
- + if ((ret = ff_obmc_frame_start(s)) < 0)
- + return ret;
- +
- +#if FF_API_CODED_FRAME
- +FF_DISABLE_DEPRECATION_WARNINGS
- + av_frame_unref(avctx->coded_frame);
- + ret = av_frame_ref(avctx->coded_frame, s->current_picture);
- + if (ret < 0)
- + return ret;
- +FF_ENABLE_DEPRECATION_WARNINGS
- +#endif
- +
- + s->m.current_picture_ptr= &s->m.current_picture;
- + s->m.current_picture.f = s->current_picture;
- + s->m.current_picture.f->pts = pict->pts;
- + if(s->m.pict_type == AV_PICTURE_TYPE_P){
- + int block_width = (width +15)>>4;
- + int block_height= (height+15)>>4;
- + int stride= s->current_picture->linesize[0];
- +
- + av_assert0(s->current_picture->data[0]);
- + av_assert0(s->last_pictures[0]->data[0]);
- +
- + s->m.avctx= s->avctx;
- + s->m.last_picture.f = s->last_pictures[0];
- + s->m.new_picture.f = s->input_picture;
- + s->m.last_picture_ptr= &s->m.last_picture;
- + s->m.linesize = stride;
- + s->m.uvlinesize= s->current_picture->linesize[1];
- + s->m.width = width;
- + s->m.height= height;
- + s->m.mb_width = block_width;
- + s->m.mb_height= block_height;
- + s->m.mb_stride= s->m.mb_width+1;
- + s->m.b8_stride= 2*s->m.mb_width+1;
- + s->m.f_code=1;
- + /* s->m.pict_type = pic->pict_type; // DELETED */
- +#if FF_API_MOTION_EST
- +FF_DISABLE_DEPRECATION_WARNINGS
- + s->m.me_method= s->avctx->me_method;
- +FF_ENABLE_DEPRECATION_WARNINGS
- +#endif
- + s->m.motion_est= s->motion_est;
- + s->m.me.scene_change_score=0;
- + s->m.me.dia_size = avctx->dia_size;
- + s->m.quarter_sample= (s->avctx->flags & AV_CODEC_FLAG_QPEL)!=0;
- + s->m.out_format= FMT_H263;
- + s->m.unrestricted_mv= 1;
- +
- + s->m.lambda = s->lambda;
- + s->m.qscale= (s->m.lambda*139 + FF_LAMBDA_SCALE*64) >> (FF_LAMBDA_SHIFT + 7);
- + s->lambda2= s->m.lambda2= (s->m.lambda*s->m.lambda + FF_LAMBDA_SCALE/2) >> FF_LAMBDA_SHIFT;
- +
- + s->m.mecc= s->mecc; //move
- + s->m.qdsp= s->qdsp; //move
- + s->m.hdsp = s->hdsp;
- + ff_init_me(&s->m);
- + s->hdsp = s->m.hdsp;
- + s->mecc= s->m.mecc;
- + }
- +
- + return 0;
- +}
- +
- +void ff_obmc_encode_blocks(OBMCContext *s, int search)
- +{
- + encode_blocks(s, search);
- +}
- diff --git a/libavcodec/obme.h b/libavcodec/obme.h
- new file mode 100644
- index 0000000..08b4760
- --- /dev/null
- +++ b/libavcodec/obme.h
- @@ -0,0 +1,58 @@
- +/*
- + * Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at>
- + *
- + * This file is part of FFmpeg.
- + *
- + * FFmpeg is free software; you can redistribute it and/or
- + * modify it under the terms of the GNU Lesser General Public
- + * License as published by the Free Software Foundation; either
- + * version 2.1 of the License, or (at your option) any later version.
- + *
- + * FFmpeg is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- + * Lesser General Public License for more details.
- + *
- + * You should have received a copy of the GNU Lesser General Public
- + * License along with FFmpeg; if not, write to the Free Software
- + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- + */
- +
- + /**
- + * @file obme.h
- + * @brief Overlapped block motion estimation functions
- + */
- +
- +#ifndef AVCODEC_OBME_H
- +#define AVCODEC_OBME_H
- +
- +#include "obmemc.h"
- +
- +#define FF_ME_ITER 50
- +
- + /**
- + * Inits OBMC context parameters needed for encoding process
- + *
- + * @param[in,out] s OBMC context to init
- + * @param[in] avctx Codec context to retrieve some initial values
- + */
- +int ff_obmc_encode_init(OBMCContext *s, AVCodecContext *avctx);
- +
- + /**
- + * Prepares OBMC context for block encoding for each frame
- + *
- + * @param[in,out] f OBMC context to prepare
- + * @param[in] avctx Codec context to retrieve some required values
- + * @param[in] pict Frame to encode
- + */
- +int ff_obmc_pre_encode_frame(OBMCContext *f, AVCodecContext *avctx, const AVFrame *pict);
- +
- + /**
- + * Starts encoding blocks
- + *
- + * @param[in,out] s OBMC context
- + * @param[in] search Defines if reference blocks should be searched for
- + */
- +void ff_obmc_encode_blocks(OBMCContext *s, int search);
- +
- +#endif /* AVCODEC_OBME_H */
- diff --git a/libavcodec/obmemc.c b/libavcodec/obmemc.c
- new file mode 100644
- index 0000000..314b1b3
- --- /dev/null
- +++ b/libavcodec/obmemc.c
- @@ -0,0 +1,651 @@
- +/*
- + * Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at>
- + *
- + * This file is part of FFmpeg.
- + *
- + * FFmpeg is free software; you can redistribute it and/or
- + * modify it under the terms of the GNU Lesser General Public
- + * License as published by the Free Software Foundation; either
- + * version 2.1 of the License, or (at your option) any later version.
- + *
- + * FFmpeg is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- + * Lesser General Public License for more details.
- + *
- + * You should have received a copy of the GNU Lesser General Public
- + * License along with FFmpeg; if not, write to the Free Software
- + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- + */
- +
- +#include "obmemc.h"
- +#include "obmemc_data.h"
- +
- +int ff_obmc_get_buffer(OBMCContext *s, AVFrame *frame)
- +{
- + int ret, i;
- + int edges_needed = av_codec_is_encoder(s->avctx->codec);
- +
- + frame->width = s->avctx->width ;
- + frame->height = s->avctx->height;
- + if (edges_needed) {
- + frame->width += 2 * EDGE_WIDTH;
- + frame->height += 2 * EDGE_WIDTH;
- + }
- + if ((ret = ff_get_buffer(s->avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0)
- + return ret;
- + if (edges_needed) {
- + for (i = 0; frame->data[i]; i++) {
- + int offset = (EDGE_WIDTH >> (i ? s->chroma_v_shift : 0)) *
- + frame->linesize[i] +
- + (EDGE_WIDTH >> (i ? s->chroma_h_shift : 0));
- + frame->data[i] += offset;
- + }
- + frame->width = s->avctx->width;
- + frame->height = s->avctx->height;
- + }
- +
- + return 0;
- +}
- +
- +int ff_obmc_alloc_blocks(OBMCContext *s)
- +{
- + int w= AV_CEIL_RSHIFT(s->avctx->width, LOG2_MB_SIZE);
- + int h= AV_CEIL_RSHIFT(s->avctx->height, LOG2_MB_SIZE);
- +
- + s->b_width = w;
- + s->b_height= h;
- +
- + av_free(s->block);
- + s->block= av_mallocz_array(w * h, sizeof(BlockNode) << (s->block_max_depth*2));
- + if (!s->block)
- + return AVERROR(ENOMEM);
- +
- + return 0;
- +}
- +
- +static av_cold void init_qexp(void)
- +{
- + int i;
- + double v=128;
- +
- + for(i=0; i<QROOT; i++)
- + {
- + ff_qexp[i]= lrintf(v);
- + v *= pow(2, 1.0 / QROOT);
- + }
- +}
- +
- +static void mc_block(PlaneObmc *p, uint8_t *dst, const uint8_t *src, int stride, int b_w, int b_h, int dx, int dy){
- + static const uint8_t weight[64]={
- + 8,7,6,5,4,3,2,1,
- + 7,7,0,0,0,0,0,1,
- + 6,0,6,0,0,0,2,0,
- + 5,0,0,5,0,3,0,0,
- + 4,0,0,0,4,0,0,0,
- + 3,0,0,5,0,3,0,0,
- + 2,0,6,0,0,0,2,0,
- + 1,7,0,0,0,0,0,1,
- + };
- +
- + static const uint8_t brane[256]={
- + 0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x11,0x12,0x12,0x12,0x12,0x12,0x12,0x12,
- + 0x04,0x05,0xcc,0xcc,0xcc,0xcc,0xcc,0x41,0x15,0x16,0xcc,0xcc,0xcc,0xcc,0xcc,0x52,
- + 0x04,0xcc,0x05,0xcc,0xcc,0xcc,0x41,0xcc,0x15,0xcc,0x16,0xcc,0xcc,0xcc,0x52,0xcc,
- + 0x04,0xcc,0xcc,0x05,0xcc,0x41,0xcc,0xcc,0x15,0xcc,0xcc,0x16,0xcc,0x52,0xcc,0xcc,
- + 0x04,0xcc,0xcc,0xcc,0x41,0xcc,0xcc,0xcc,0x15,0xcc,0xcc,0xcc,0x16,0xcc,0xcc,0xcc,
- + 0x04,0xcc,0xcc,0x41,0xcc,0x05,0xcc,0xcc,0x15,0xcc,0xcc,0x52,0xcc,0x16,0xcc,0xcc,
- + 0x04,0xcc,0x41,0xcc,0xcc,0xcc,0x05,0xcc,0x15,0xcc,0x52,0xcc,0xcc,0xcc,0x16,0xcc,
- + 0x04,0x41,0xcc,0xcc,0xcc,0xcc,0xcc,0x05,0x15,0x52,0xcc,0xcc,0xcc,0xcc,0xcc,0x16,
- + 0x44,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x55,0x56,0x56,0x56,0x56,0x56,0x56,0x56,
- + 0x48,0x49,0xcc,0xcc,0xcc,0xcc,0xcc,0x85,0x59,0x5A,0xcc,0xcc,0xcc,0xcc,0xcc,0x96,
- + 0x48,0xcc,0x49,0xcc,0xcc,0xcc,0x85,0xcc,0x59,0xcc,0x5A,0xcc,0xcc,0xcc,0x96,0xcc,
- + 0x48,0xcc,0xcc,0x49,0xcc,0x85,0xcc,0xcc,0x59,0xcc,0xcc,0x5A,0xcc,0x96,0xcc,0xcc,
- + 0x48,0xcc,0xcc,0xcc,0x49,0xcc,0xcc,0xcc,0x59,0xcc,0xcc,0xcc,0x96,0xcc,0xcc,0xcc,
- + 0x48,0xcc,0xcc,0x85,0xcc,0x49,0xcc,0xcc,0x59,0xcc,0xcc,0x96,0xcc,0x5A,0xcc,0xcc,
- + 0x48,0xcc,0x85,0xcc,0xcc,0xcc,0x49,0xcc,0x59,0xcc,0x96,0xcc,0xcc,0xcc,0x5A,0xcc,
- + 0x48,0x85,0xcc,0xcc,0xcc,0xcc,0xcc,0x49,0x59,0x96,0xcc,0xcc,0xcc,0xcc,0xcc,0x5A,
- + };
- +
- + static const uint8_t needs[16]={
- + 0,1,0,0,
- + 2,4,2,0,
- + 0,1,0,0,
- + 15
- + };
- +
- + int x, y, b, r, l;
- + int16_t tmpIt [64*(32+HTAPS_MAX)];
- + uint8_t tmp2t[3][64*(32+HTAPS_MAX)];
- + int16_t *tmpI= tmpIt;
- + uint8_t *tmp2= tmp2t[0];
- + const uint8_t *hpel[11];
- + av_assert2(dx<16 && dy<16);
- + r= brane[dx + 16*dy]&15;
- + l= brane[dx + 16*dy]>>4;
- +
- + b= needs[l] | needs[r];
- + if(p && !p->diag_mc)
- + b= 15;
- +
- + if(b&5){
- + for(y=0; y < b_h+HTAPS_MAX-1; y++){
- + for(x=0; x < b_w; x++){
- + int a_1=src[x + HTAPS_MAX/2-4];
- + int a0= src[x + HTAPS_MAX/2-3];
- + int a1= src[x + HTAPS_MAX/2-2];
- + int a2= src[x + HTAPS_MAX/2-1];
- + int a3= src[x + HTAPS_MAX/2+0];
- + int a4= src[x + HTAPS_MAX/2+1];
- + int a5= src[x + HTAPS_MAX/2+2];
- + int a6= src[x + HTAPS_MAX/2+3];
- + int am=0;
- + if(!p || p->fast_mc){
- + am= 20*(a2+a3) - 5*(a1+a4) + (a0+a5);
- + tmpI[x]= am;
- + am= (am+16)>>5;
- + }else{
- + am= p->hcoeff[0]*(a2+a3) + p->hcoeff[1]*(a1+a4) + p->hcoeff[2]*(a0+a5) + p->hcoeff[3]*(a_1+a6);
- + tmpI[x]= am;
- + am= (am+32)>>6;
- + }
- +
- + if(am&(~255)) am= ~(am>>31);
- + tmp2[x]= am;
- + }
- + tmpI+= 64;
- + tmp2+= 64;
- + src += stride;
- + }
- + src -= stride*y;
- + }
- + src += HTAPS_MAX/2 - 1;
- + tmp2= tmp2t[1];
- +
- + if(b&2){
- + for(y=0; y < b_h; y++){
- + for(x=0; x < b_w+1; x++){
- + int a_1=src[x + (HTAPS_MAX/2-4)*stride];
- + int a0= src[x + (HTAPS_MAX/2-3)*stride];
- + int a1= src[x + (HTAPS_MAX/2-2)*stride];
- + int a2= src[x + (HTAPS_MAX/2-1)*stride];
- + int a3= src[x + (HTAPS_MAX/2+0)*stride];
- + int a4= src[x + (HTAPS_MAX/2+1)*stride];
- + int a5= src[x + (HTAPS_MAX/2+2)*stride];
- + int a6= src[x + (HTAPS_MAX/2+3)*stride];
- + int am=0;
- + if(!p || p->fast_mc)
- + am= (20*(a2+a3) - 5*(a1+a4) + (a0+a5) + 16)>>5;
- + else
- + am= (p->hcoeff[0]*(a2+a3) + p->hcoeff[1]*(a1+a4) + p->hcoeff[2]*(a0+a5) + p->hcoeff[3]*(a_1+a6) + 32)>>6;
- +
- + if(am&(~255)) am= ~(am>>31);
- + tmp2[x]= am;
- + }
- + src += stride;
- + tmp2+= 64;
- + }
- + src -= stride*y;
- + }
- + src += stride*(HTAPS_MAX/2 - 1);
- + tmp2= tmp2t[2];
- + tmpI= tmpIt;
- + if(b&4){
- + for(y=0; y < b_h; y++){
- + for(x=0; x < b_w; x++){
- + int a_1=tmpI[x + (HTAPS_MAX/2-4)*64];
- + int a0= tmpI[x + (HTAPS_MAX/2-3)*64];
- + int a1= tmpI[x + (HTAPS_MAX/2-2)*64];
- + int a2= tmpI[x + (HTAPS_MAX/2-1)*64];
- + int a3= tmpI[x + (HTAPS_MAX/2+0)*64];
- + int a4= tmpI[x + (HTAPS_MAX/2+1)*64];
- + int a5= tmpI[x + (HTAPS_MAX/2+2)*64];
- + int a6= tmpI[x + (HTAPS_MAX/2+3)*64];
- + int am=0;
- + if(!p || p->fast_mc)
- + am= (20*(a2+a3) - 5*(a1+a4) + (a0+a5) + 512)>>10;
- + else
- + am= (p->hcoeff[0]*(a2+a3) + p->hcoeff[1]*(a1+a4) + p->hcoeff[2]*(a0+a5) + p->hcoeff[3]*(a_1+a6) + 2048)>>12;
- + if(am&(~255)) am= ~(am>>31);
- + tmp2[x]= am;
- + }
- + tmpI+= 64;
- + tmp2+= 64;
- + }
- + }
- +
- + hpel[ 0]= src;
- + hpel[ 1]= tmp2t[0] + 64*(HTAPS_MAX/2-1);
- + hpel[ 2]= src + 1;
- +
- + hpel[ 4]= tmp2t[1];
- + hpel[ 5]= tmp2t[2];
- + hpel[ 6]= tmp2t[1] + 1;
- +
- + hpel[ 8]= src + stride;
- + hpel[ 9]= hpel[1] + 64;
- + hpel[10]= hpel[8] + 1;
- +
- +#define MC_STRIDE(x) (needs[x] ? 64 : stride)
- +
- + if(b==15){
- + int dxy = dx / 8 + dy / 8 * 4;
- + const uint8_t *src1 = hpel[dxy ];
- + const uint8_t *src2 = hpel[dxy + 1];
- + const uint8_t *src3 = hpel[dxy + 4];
- + const uint8_t *src4 = hpel[dxy + 5];
- + int stride1 = MC_STRIDE(dxy);
- + int stride2 = MC_STRIDE(dxy + 1);
- + int stride3 = MC_STRIDE(dxy + 4);
- + int stride4 = MC_STRIDE(dxy + 5);
- + dx&=7;
- + dy&=7;
- + for(y=0; y < b_h; y++){
- + for(x=0; x < b_w; x++){
- + dst[x]= ((8-dx)*(8-dy)*src1[x] + dx*(8-dy)*src2[x]+
- + (8-dx)* dy *src3[x] + dx* dy *src4[x]+32)>>6;
- + }
- + src1+=stride1;
- + src2+=stride2;
- + src3+=stride3;
- + src4+=stride4;
- + dst +=stride;
- + }
- + }else{
- + const uint8_t *src1= hpel[l];
- + const uint8_t *src2= hpel[r];
- + int stride1 = MC_STRIDE(l);
- + int stride2 = MC_STRIDE(r);
- + int a= weight[((dx&7) + (8*(dy&7)))];
- + int b= 8-a;
- + for(y=0; y < b_h; y++){
- + for(x=0; x < b_w; x++){
- + dst[x]= (a*src1[x] + b*src2[x] + 4)>>3;
- + }
- + src1+=stride1;
- + src2+=stride2;
- + dst +=stride;
- + }
- + }
- +}
- +
- +void ff_obmc_pred_block(OBMCContext *s, uint8_t *dst, uint8_t *tmp, ptrdiff_t stride,
- + int sx, int sy, int b_w, int b_h, const BlockNode *block,
- + int plane_index, int w, int h)
- +{
- + if(block->type & BLOCK_INTRA){
- + int x, y;
- + const unsigned color = block->color[plane_index];
- + const unsigned color4 = color*0x01010101;
- + if(b_w==32){
- + for(y=0; y < b_h; y++){
- + *(uint32_t*)&dst[0 + y*stride]= color4;
- + *(uint32_t*)&dst[4 + y*stride]= color4;
- + *(uint32_t*)&dst[8 + y*stride]= color4;
- + *(uint32_t*)&dst[12+ y*stride]= color4;
- + *(uint32_t*)&dst[16+ y*stride]= color4;
- + *(uint32_t*)&dst[20+ y*stride]= color4;
- + *(uint32_t*)&dst[24+ y*stride]= color4;
- + *(uint32_t*)&dst[28+ y*stride]= color4;
- + }
- + }else if(b_w==16){
- + for(y=0; y < b_h; y++){
- + *(uint32_t*)&dst[0 + y*stride]= color4;
- + *(uint32_t*)&dst[4 + y*stride]= color4;
- + *(uint32_t*)&dst[8 + y*stride]= color4;
- + *(uint32_t*)&dst[12+ y*stride]= color4;
- + }
- + }else if(b_w==8){
- + for(y=0; y < b_h; y++){
- + *(uint32_t*)&dst[0 + y*stride]= color4;
- + *(uint32_t*)&dst[4 + y*stride]= color4;
- + }
- + }else if(b_w==4){
- + for(y=0; y < b_h; y++){
- + *(uint32_t*)&dst[0 + y*stride]= color4;
- + }
- + }else{
- + for(y=0; y < b_h; y++){
- + for(x=0; x < b_w; x++){
- + dst[x + y*stride]= color;
- + }
- + }
- + }
- + }else{
- + uint8_t *src= s->last_pictures[block->ref]->data[plane_index];
- + const int scale= plane_index ? (2*s->mv_scale)>>s->chroma_h_shift : 2*s->mv_scale;
- + int mx= block->mx*scale;
- + int my= block->my*scale;
- + const int dx= mx&15;
- + const int dy= my&15;
- + const int tab_index= 3 - (b_w>>2) + (b_w>>4);
- + sx += (mx>>4) - (HTAPS_MAX/2-1);
- + sy += (my>>4) - (HTAPS_MAX/2-1);
- + src += sx + sy*stride;
- + if( (unsigned)sx >= FFMAX(w - b_w - (HTAPS_MAX-2), 0)
- + || (unsigned)sy >= FFMAX(h - b_h - (HTAPS_MAX-2), 0)){
- + s->vdsp.emulated_edge_mc(tmp + MB_SIZE, src,
- + stride, stride,
- + b_w+HTAPS_MAX-1, b_h+HTAPS_MAX-1,
- + sx, sy, w, h);
- + src= tmp + MB_SIZE;
- + }
- +
- + av_assert2(s->chroma_h_shift == s->chroma_v_shift); // only one mv_scale
- +
- + av_assert2((tab_index>=0 && tab_index<4) || b_w==32);
- + if( (dx&3) || (dy&3)
- + || !(b_w == b_h || 2*b_w == b_h || b_w == 2*b_h)
- + || (b_w&(b_w-1))
- + || b_w == 1
- + || b_h == 1
- + || !s->plane[plane_index].fast_mc )
- + mc_block(&s->plane[plane_index], dst, src, stride, b_w, b_h, dx, dy);
- + else if(b_w==32){
- + int y;
- + for(y=0; y<b_h; y+=16){
- + s->h264qpel.put_h264_qpel_pixels_tab[0][dy+(dx>>2)](dst + y*stride, src + 3 + (y+3)*stride,stride);
- + s->h264qpel.put_h264_qpel_pixels_tab[0][dy+(dx>>2)](dst + 16 + y*stride, src + 19 + (y+3)*stride,stride);
- + }
- + }else if(b_w==b_h)
- + s->h264qpel.put_h264_qpel_pixels_tab[tab_index ][dy+(dx>>2)](dst,src + 3 + 3*stride,stride);
- + else if(b_w==2*b_h){
- + s->h264qpel.put_h264_qpel_pixels_tab[tab_index+1][dy+(dx>>2)](dst ,src + 3 + 3*stride,stride);
- + s->h264qpel.put_h264_qpel_pixels_tab[tab_index+1][dy+(dx>>2)](dst+b_h,src + 3 + b_h + 3*stride,stride);
- + }else{
- + av_assert2(2*b_w==b_h);
- + s->h264qpel.put_h264_qpel_pixels_tab[tab_index ][dy+(dx>>2)](dst ,src + 3 + 3*stride ,stride);
- + s->h264qpel.put_h264_qpel_pixels_tab[tab_index ][dy+(dx>>2)](dst+b_w*stride,src + 3 + 3*stride+b_w*stride,stride);
- + }
- + }
- +}
- +
- +#define mca(dx,dy,b_w)\
- +static void mc_block_hpel ## dx ## dy ## b_w(uint8_t *dst, const uint8_t *src, ptrdiff_t stride, int h){\
- + av_assert2(h==b_w);\
- + mc_block(NULL, dst, src-(HTAPS_MAX/2-1)-(HTAPS_MAX/2-1)*stride, stride, b_w, b_w, dx, dy);\
- +}
- +
- +mca( 0, 0,16)
- +mca( 8, 0,16)
- +mca( 0, 8,16)
- +mca( 8, 8,16)
- +mca( 0, 0,8)
- +mca( 8, 0,8)
- +mca( 0, 8,8)
- +mca( 8, 8,8)
- +
- +av_cold int ff_obmc_common_init(OBMCContext *s, AVCodecContext *avctx)
- +{
- + s->avctx = avctx;
- +
- + s->obmc_coder.priv_data = NULL;
- + s->obmc_coder.avctx = NULL;
- +
- + int width, height, i, j;
- +
- + width = avctx->width;
- + height = avctx->height;
- +
- + ff_me_cmp_init(&s->mecc, avctx);
- + ff_hpeldsp_init(&s->hdsp, avctx->flags);
- + ff_videodsp_init(&s->vdsp, 8);
- + ff_dwt_init(&s->dwt);
- + ff_h264qpel_init(&s->h264qpel, 8);
- +
- + s->max_ref_frames = 1; //just make sure it's not an invalid value in case of no initial keyframe
- +
- +#define mcf(dx,dy)\
- + s->qdsp.put_qpel_pixels_tab [0][dy+dx/4]=\
- + s->qdsp.put_no_rnd_qpel_pixels_tab[0][dy+dx/4]=\
- + s->h264qpel.put_h264_qpel_pixels_tab[0][dy+dx/4];\
- + s->qdsp.put_qpel_pixels_tab [1][dy+dx/4]=\
- + s->qdsp.put_no_rnd_qpel_pixels_tab[1][dy+dx/4]=\
- + s->h264qpel.put_h264_qpel_pixels_tab[1][dy+dx/4];
- +
- + mcf( 0, 0)
- + mcf( 4, 0)
- + mcf( 8, 0)
- + mcf(12, 0)
- + mcf( 0, 4)
- + mcf( 4, 4)
- + mcf( 8, 4)
- + mcf(12, 4)
- + mcf( 0, 8)
- + mcf( 4, 8)
- + mcf( 8, 8)
- + mcf(12, 8)
- + mcf( 0,12)
- + mcf( 4,12)
- + mcf( 8,12)
- + mcf(12,12)
- +
- +#define mcfh(dx,dy)\
- + s->hdsp.put_pixels_tab [0][dy/4+dx/8]=\
- + s->hdsp.put_no_rnd_pixels_tab[0][dy/4+dx/8]=\
- + mc_block_hpel ## dx ## dy ## 16;\
- + s->hdsp.put_pixels_tab [1][dy/4+dx/8]=\
- + s->hdsp.put_no_rnd_pixels_tab[1][dy/4+dx/8]=\
- + mc_block_hpel ## dx ## dy ## 8;
- +
- + mcfh(0, 0)
- + mcfh(8, 0)
- + mcfh(0, 8)
- + mcfh(8, 8)
- +
- + init_qexp();
- +
- + FF_ALLOCZ_ARRAY_OR_GOTO(avctx, s->spatial_idwt_buffer, width, height * sizeof(IDWTELEM), fail);
- +
- + for(i=0; i<MAX_REF_FRAMES; i++) {
- + for(j=0; j<MAX_REF_FRAMES; j++)
- + ff_scale_mv_ref[i][j] = 256*(i+1)/(j+1);
- + s->last_pictures[i] = av_frame_alloc();
- + if (!s->last_pictures[i])
- + goto fail;
- + }
- +
- + s->mconly_picture = av_frame_alloc();
- + s->current_picture = av_frame_alloc();
- + if (!s->mconly_picture || !s->current_picture)
- + goto fail;
- +
- + return 0;
- +fail:
- + return AVERROR(ENOMEM);
- +}
- +
- +int ff_obmc_common_init_after_header(OBMCContext *s)
- +{
- + int plane_index;
- + int ret, emu_buf_size;
- +
- + if(!s->scratchbuf) {
- + if ((ret = ff_get_buffer(s->avctx, s->mconly_picture, AV_GET_BUFFER_FLAG_REF)) < 0)
- + return ret;
- + FF_ALLOCZ_ARRAY_OR_GOTO(s->avctx, s->scratchbuf, FFMAX(s->mconly_picture->linesize[0], 2*s->avctx->width+256), 7*MB_SIZE, fail);
- + emu_buf_size = FFMAX(s->mconly_picture->linesize[0], 2*s->avctx->width+256) * (2 * MB_SIZE + HTAPS_MAX - 1);
- + FF_ALLOC_OR_GOTO(s->avctx, s->emu_edge_buffer, emu_buf_size, fail);
- + }
- +
- + if(s->mconly_picture->format != s->avctx->pix_fmt) {
- + av_log(s->avctx, AV_LOG_ERROR, "pixel format changed\n");
- + return AVERROR_INVALIDDATA;
- + }
- +
- + for(plane_index=0; plane_index < s->nb_planes; plane_index++){
- + int w= s->avctx->width;
- + int h= s->avctx->height;
- +
- + if(plane_index){
- + w = AV_CEIL_RSHIFT(w, s->chroma_h_shift);
- + h = AV_CEIL_RSHIFT(h, s->chroma_v_shift);
- + }
- + s->plane[plane_index].width = w;
- + s->plane[plane_index].height= h;
- + }
- +
- + return 0;
- +fail:
- + return AVERROR(ENOMEM);
- +}
- +
- +static int halfpel_interpol(OBMCContext *s, uint8_t *halfpel[4][4], AVFrame *frame)
- +{
- + int p,x,y;
- +
- + for(p=0; p < s->nb_planes; p++){
- + int is_chroma= !!p;
- + int w= is_chroma ? AV_CEIL_RSHIFT(s->avctx->width, s->chroma_h_shift) : s->avctx->width;
- + int h= is_chroma ? AV_CEIL_RSHIFT(s->avctx->height, s->chroma_v_shift) : s->avctx->height;
- + int ls= frame->linesize[p];
- + uint8_t *src= frame->data[p];
- +
- + halfpel[1][p] = av_malloc_array(ls, (h + 2 * EDGE_WIDTH));
- + halfpel[2][p] = av_malloc_array(ls, (h + 2 * EDGE_WIDTH));
- + halfpel[3][p] = av_malloc_array(ls, (h + 2 * EDGE_WIDTH));
- + if (!halfpel[1][p] || !halfpel[2][p] || !halfpel[3][p]) {
- + av_freep(&halfpel[1][p]);
- + av_freep(&halfpel[2][p]);
- + av_freep(&halfpel[3][p]);
- + return AVERROR(ENOMEM);
- + }
- + halfpel[1][p] += EDGE_WIDTH * (1 + ls);
- + halfpel[2][p] += EDGE_WIDTH * (1 + ls);
- + halfpel[3][p] += EDGE_WIDTH * (1 + ls);
- +
- + halfpel[0][p]= src;
- + for(y=0; y<h; y++){
- + for(x=0; x<w; x++){
- + int i= y*ls + x;
- +
- + halfpel[1][p][i]= (
- + 20*(src[i] + src[i+1<h*w?i+1:i-1]) -
- + 5*(src[i-1<0?i+1:i-1] + src[i+2<h*w?i+2:i-2]) +
- + (src[i-2<0?i+2:i-2] + src[i+3<h*w?i+3:i-3]) + 16
- + )>>5;
- + }
- + }
- + for(y=0; y<h; y++){
- + for(x=0; x<w; x++){
- + int i= y*ls + x;
- +
- + halfpel[2][p][i]= (
- + 20*(src[i] + src[i+ls<h*w?i+ls:i-ls]) -
- + 5*(src[i-ls<0?i+ls:i-ls] + src[i+2*ls<h*w?i+2*ls:i-2*ls]) +
- + (src[i-2*ls<0?i+2*ls:i-2*ls] + src[i+3*ls<h*w?i+3*ls:i-3*ls]) + 16
- + )>>5;
- + }
- + }
- + src= halfpel[1][p];
- + for(y=0; y<h; y++){
- + for(x=0; x<w; x++){
- + int i= y*ls + x;
- +
- + halfpel[3][p][i]= (
- + 20*(src[i] + src[i+ls<h*w?i+ls:i-ls]) -
- + 5*(src[i-ls<0?i+ls:i-ls] + src[i+2*ls<h*w?i+2*ls:i-2*ls]) +
- + (src[i-2*ls<0?i+2*ls:i-2*ls] + src[i+3*ls<h*w?i+3*ls:i-3*ls]) + 16
- + )>>5;
- + }
- + }
- +
- +//FIXME border!
- + }
- + return 0;
- +}
- +
- +void ff_obmc_release_buffer(OBMCContext *s)
- +{
- + int i;
- +
- + if(s->last_pictures[s->max_ref_frames-1]->data[0]){
- + av_frame_unref(s->last_pictures[s->max_ref_frames-1]);
- + for(i=0; i<9; i++)
- + if(s->halfpel_plane[s->max_ref_frames-1][1+i/3][i%3]) {
- + av_free(s->halfpel_plane[s->max_ref_frames-1][1+i/3][i%3] - EDGE_WIDTH*(1+s->current_picture->linesize[i%3]));
- + s->halfpel_plane[s->max_ref_frames-1][1+i/3][i%3] = NULL;
- + }
- + }
- +}
- +
- +int ff_obmc_frame_start(OBMCContext *s)
- +{
- + AVFrame *tmp;
- + int i, ret;
- +
- + int USE_HALFPEL_PLANE = 0;
- +
- + switch(s->avctx->codec_id) {
- + case AV_CODEC_ID_FFV1:
- + USE_HALFPEL_PLANE = 1;
- + break;
- + default:
- + break;
- + }
- +
- + ff_obmc_release_buffer(s);
- +
- + tmp= s->last_pictures[s->max_ref_frames-1];
- + for(i=s->max_ref_frames-1; i>0; i--)
- + s->last_pictures[i] = s->last_pictures[i-1];
- + memmove(s->halfpel_plane+1, s->halfpel_plane, (s->max_ref_frames-1)*sizeof(void*)*4*4);
- + if(USE_HALFPEL_PLANE && s->current_picture->data[0]) {
- + if((ret = halfpel_interpol(s, s->halfpel_plane[0], s->current_picture)) < 0)
- + return ret;
- + }
- + s->last_pictures[0] = s->current_picture;
- + s->current_picture = tmp;
- + av_frame_copy_props(s->current_picture, s->last_pictures[0]);
- +
- + if (s->keyframe) {
- + s->ref_frames= 0;
- + } else {
- + int i;
- + for(i=0; i<s->max_ref_frames && s->last_pictures[i]->data[0]; i++)
- + if(i && s->last_pictures[i-1]->key_frame)
- + break;
- + s->ref_frames= i;
- + if(s->ref_frames==0){
- + av_log(s->avctx,AV_LOG_ERROR, "No reference frames\n");
- + return AVERROR_INVALIDDATA;
- + }
- + }
- + if ((ret = ff_obmc_get_buffer(s, s->current_picture)) < 0)
- + return ret;
- +
- + s->current_picture->key_frame= s->keyframe;
- +
- + return 0;
- +}
- +
- +av_cold int ff_obmc_close(OBMCContext *s)
- +{
- + int i;
- +
- + av_freep(&s->spatial_idwt_buffer);
- +
- + s->m.me.temp= NULL;
- + av_freep(&s->m.me.scratchpad);
- + av_freep(&s->m.me.map);
- + av_freep(&s->m.me.score_map);
- + av_freep(&s->m.sc.obmc_scratchpad);
- +
- + av_freep(&s->block);
- + av_freep(&s->scratchbuf);
- + av_freep(&s->emu_edge_buffer);
- +
- + for(i=0; i<MAX_REF_FRAMES; i++){
- + av_freep(&s->ref_mvs[i]);
- + av_freep(&s->ref_scores[i]);
- + if(s->last_pictures[i] && s->last_pictures[i]->data[0]) {
- + av_assert0(s->last_pictures[i]->data[0] != s->current_picture->data[0]);
- + }
- + av_frame_free(&s->last_pictures[i]);
- + }
- +
- + av_frame_free(&s->mconly_picture);
- + av_frame_free(&s->current_picture);
- +
- + return 0;
- +}
- diff --git a/libavcodec/obmemc.h b/libavcodec/obmemc.h
- new file mode 100644
- index 0000000..00e079c
- --- /dev/null
- +++ b/libavcodec/obmemc.h
- @@ -0,0 +1,522 @@
- +/*
- + * Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at>
- + * Copyright (C) 2006 Robert Edele <yartrebo@earthlink.net>
- + *
- + * This file is part of FFmpeg.
- + *
- + * FFmpeg is free software; you can redistribute it and/or
- + * modify it under the terms of the GNU Lesser General Public
- + * License as published by the Free Software Foundation; either
- + * version 2.1 of the License, or (at your option) any later version.
- + *
- + * FFmpeg is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- + * Lesser General Public License for more details.
- + *
- + * You should have received a copy of the GNU Lesser General Public
- + * License along with FFmpeg; if not, write to the Free Software
- + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- + */
- +
- + /**
- + * @file obmemc.h
- + * @brief Overlapped block motion estimation and compensation
- + */
- +
- +#ifndef AVCODEC_OBMEMC_H
- +#define AVCODEC_OBMEMC_H
- +
- +#include "libavutil/imgutils.h"
- +#include "libavutil/pixdesc.h"
- +#include "libavutil/motion_vector.h"
- +
- +#include "rangecoder.h"
- +
- +#include "hpeldsp.h"
- +#include "me_cmp.h"
- +#include "qpeldsp.h"
- +#include "snow_dwt.h"
- +
- +#include "mpegvideo.h"
- +#include "h264qpel.h"
- +
- +#define MAX_PLANES 4
- +#define QSHIFT 5
- +#define QROOT (1<<QSHIFT)
- +#define LOSSLESS_QLOG -128
- +#define FRAC_BITS 4
- +#define MAX_REF_FRAMES 8
- +
- +#define LOG2_OBMC_MAX 8
- +#define OBMC_MAX (1<<(LOG2_OBMC_MAX))
- +typedef struct BlockNode{
- + int16_t mx; ///< Motion vector component X, see mv_scale
- + int16_t my; ///< Motion vector component Y, see mv_scale
- + uint8_t ref; ///< Reference frame index
- + uint8_t color[3]; ///< Color for intra
- + uint8_t type; ///< Bitfield of BLOCK_*
- +//#define TYPE_SPLIT 1
- +#define BLOCK_INTRA 1 ///< Intra block, inter otherwise
- +#define BLOCK_OPT 2 ///< Block needs no checks in this round of iterative motion estiation
- +//#define TYPE_NOCOLOR 4
- + uint8_t level; //FIXME merge into type?
- +}BlockNode;
- +
- +static const BlockNode null_block= { //FIXME add border maybe
- + .color= {128,128,128},
- + .mx= 0,
- + .my= 0,
- + .ref= 0,
- + .type= 0,
- + .level= 0,
- +};
- +
- +#define LOG2_MB_SIZE 4
- +#define MB_SIZE (1<<LOG2_MB_SIZE)
- +#define ENCODER_EXTRA_BITS 4
- +#define HTAPS_MAX 8
- +
- +typedef struct PlaneObmc{
- + int width;
- + int height;
- +
- + int htaps;
- + int8_t hcoeff[HTAPS_MAX/2];
- + int diag_mc;
- + int fast_mc;
- +
- + int last_htaps;
- + int8_t last_hcoeff[HTAPS_MAX/2];
- + int last_diag_mc;
- +} PlaneObmc;
- +
- +/**
- + * @struct ObmcCoderContext
- + * @file obmemc.h
- + * @brief struct that stores callbacks to interact with the bitstream encoder
- + */
- +typedef struct ObmcCoderContext {
- + void *priv_data;
- + AVCodecContext *avctx;
- +
- + int (*get_bits) (struct ObmcCoderContext *);
- + int (*available_bytes) (struct ObmcCoderContext *);
- +
- + // UTILS
- + void (*init_frame_coder) (AVCodecContext *, struct ObmcCoderContext *);
- + void (*copy_coder) (struct ObmcCoderContext *);
- + void (*reset_coder) (struct ObmcCoderContext *);
- + void (*free) (struct ObmcCoderContext *);
- +
- + // ENCODER
- + void (*put_level_break) (struct ObmcCoderContext *, int, int);
- + void (*put_block_type) (struct ObmcCoderContext *, int, int);
- + void (*put_best_ref) (struct ObmcCoderContext *, int, int);
- + void (*put_block_mv) (struct ObmcCoderContext *, int, int, int, int);
- + void (*put_block_color) (struct ObmcCoderContext *, int, int, int, int, int, int);
- +
- +} ObmcCoderContext;
- +
- +typedef struct OBMCContext {
- + AVCodecContext *avctx;
- + int keyframe;
- + int chroma_h_shift, chroma_v_shift;
- +
- + ObmcCoderContext obmc_coder;
- +
- + /* ME/MC part */
- + MECmpContext mecc;
- + HpelDSPContext hdsp;
- + QpelDSPContext qdsp;
- + VideoDSPContext vdsp;
- + H264QpelContext h264qpel;
- + MpegvideoEncDSPContext mpvencdsp;
- + SnowDWTContext dwt;
- +
- + AVFrame *input_picture; ///< new_picture with the internal linesizes
- + AVFrame *current_picture;
- + AVFrame *last_pictures[MAX_REF_FRAMES];
- + uint8_t *halfpel_plane[MAX_REF_FRAMES][4][4];
- + AVFrame *mconly_picture;
- +
- + MpegEncContext m; // needed for motion estimation, should not be used for anything else, the idea is to eventually make the motion estimation independent of MpegEncContext, so this will be removed then (FIXME/XXX)
- +
- + uint8_t *scratchbuf;
- + uint8_t *emu_edge_buffer;
- +
- + AVMotionVector *avmv;
- + int avmv_index;
- +
- + int motion_est;
- + int intra_penalty;
- + int lambda;
- + int lambda2;
- + int max_ref_frames;
- + int ref_frames;
- +
- + BlockNode *block;
- + int b_width;
- + int b_height;
- + int block_max_depth;
- + int last_block_max_depth;
- +
- + uint32_t *ref_scores[MAX_REF_FRAMES];
- + int16_t (*ref_mvs[MAX_REF_FRAMES])[2];
- +
- +#define ME_CACHE_SIZE 1024
- + unsigned me_cache[ME_CACHE_SIZE];
- + unsigned me_cache_generation;
- + int mv_scale;
- + int last_mv_scale;
- + int iterative_dia_size;
- +
- + IDWTELEM *spatial_idwt_buffer;
- +
- + PlaneObmc plane[MAX_PLANES];
- +
- + int nb_planes;
- +} OBMCContext;
- +
- +/* Tables */
- +extern const uint8_t * const ff_obmc_tab[4];
- +extern uint8_t ff_qexp[QROOT];
- +extern int ff_scale_mv_ref[MAX_REF_FRAMES][MAX_REF_FRAMES];
- +
- +int ff_obmc_get_buffer(OBMCContext *s, AVFrame *frame);
- +void ff_obmc_release_buffer(OBMCContext *s);
- +int ff_obmc_common_init_after_header(OBMCContext *s);
- +int ff_obmc_frame_start(OBMCContext *f);
- +int ff_obmc_alloc_blocks(OBMCContext *s);
- +int ff_obmc_common_init(OBMCContext *s, AVCodecContext *avctx);
- +int ff_obmc_close(OBMCContext *s);
- +void ff_obmc_pred_block(OBMCContext *s, uint8_t *dst, uint8_t *tmp, ptrdiff_t stride,
- + int sx, int sy, int b_w, int b_h, const BlockNode *block,
- + int plane_index, int w, int h);
- +
- +static inline void pred_mv(OBMCContext *s, int *mx, int *my, int ref,
- + const BlockNode *left, const BlockNode *top, const BlockNode *tr){
- + if(s->ref_frames == 1){
- + *mx = mid_pred(left->mx, top->mx, tr->mx);
- + *my = mid_pred(left->my, top->my, tr->my);
- + }else{
- + const int *scale = ff_scale_mv_ref[ref];
- + *mx = mid_pred((left->mx * scale[left->ref] + 128) >>8,
- + (top ->mx * scale[top ->ref] + 128) >>8,
- + (tr ->mx * scale[tr ->ref] + 128) >>8);
- + *my = mid_pred((left->my * scale[left->ref] + 128) >>8,
- + (top ->my * scale[top ->ref] + 128) >>8,
- + (tr ->my * scale[tr ->ref] + 128) >>8);
- + }
- +}
- +
- +static av_always_inline int same_block(BlockNode *a, BlockNode *b){
- + if((a->type&BLOCK_INTRA) && (b->type&BLOCK_INTRA)){
- + return !((a->color[0] - b->color[0]) | (a->color[1] - b->color[1]) | (a->color[2] - b->color[2]));
- + }else{
- + return !((a->mx - b->mx) | (a->my - b->my) | (a->ref - b->ref) | ((a->type ^ b->type)&BLOCK_INTRA));
- + }
- +}
- +
- +static av_always_inline void add_yblock(OBMCContext *s, int sliced, slice_buffer *sb, IDWTELEM *dst, uint8_t *dst8, const 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;
- + BlockNode *lt= &s->block[b_x + b_y*b_stride];
- + BlockNode *rt= lt+1;
- + BlockNode *lb= lt+b_stride;
- + BlockNode *rb= lb+1;
- + uint8_t *block[4];
- + // When src_stride is large enough, it is possible to interleave the blocks.
- + // Otherwise the blocks are written sequentially in the tmp buffer.
- + int tmp_step= src_stride >= 7*MB_SIZE ? MB_SIZE : MB_SIZE*src_stride;
- + uint8_t *tmp = s->scratchbuf;
- + uint8_t *ptmp;
- + int x,y;
- +
- + if(b_x<0){
- + lt= rt;
- + lb= rb;
- + }else if(b_x + 1 >= b_width){
- + rt= lt;
- + rb= lb;
- + }
- + if(b_y<0){
- + lt= lb;
- + rt= rb;
- + }else if(b_y + 1 >= b_height){
- + lb= lt;
- + rb= rt;
- + }
- +
- + if(src_x<0){ //FIXME merge with prev & always round internal width up to *16
- + obmc -= src_x;
- + b_w += src_x;
- + if(!sliced && !offset_dst)
- + dst -= src_x;
- + src_x=0;
- + }
- + if(src_x + b_w > w){
- + b_w = w - src_x;
- + }
- + if(src_y<0){
- + obmc -= src_y*obmc_stride;
- + b_h += src_y;
- + if(!sliced && !offset_dst)
- + dst -= src_y*dst_stride;
- + src_y=0;
- + }
- + if(src_y + b_h> h){
- + b_h = h - src_y;
- + }
- +
- + if(b_w<=0 || b_h<=0) return;
- +
- + if(!sliced && offset_dst)
- + dst += src_x + src_y*dst_stride;
- + dst8+= src_x + src_y*src_stride;
- +// src += src_x + src_y*src_stride;
- +
- + ptmp= tmp + 3*tmp_step;
- + block[0]= ptmp;
- + ptmp+=tmp_step;
- + ff_obmc_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;
- + ff_obmc_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)){
- + block[2]= block[0];
- + }else if(same_block(rt, lb)){
- + block[2]= block[1];
- + }else{
- + block[2]= ptmp;
- + ptmp+=tmp_step;
- + ff_obmc_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) ){
- + block[3]= block[0];
- + }else if(same_block(rt, rb)){
- + block[3]= block[1];
- + }else if(same_block(lb, rb)){
- + block[3]= block[2];
- + }else{
- + block[3]= ptmp;
- + ff_obmc_pred_block(s, block[3], tmp, src_stride, src_x, src_y, b_w, b_h, rb, plane_index, w, h);
- + }
- + if(sliced){
- + s->dwt.inner_add_yblock(obmc, obmc_stride, block, b_w, b_h, src_x,src_y, src_stride, sb, add, dst8);
- + }else{
- + for(y=0; y<b_h; y++){
- + //FIXME ugly misuse of obmc_stride
- + const uint8_t *obmc1= obmc + y*obmc_stride;
- + const uint8_t *obmc2= obmc1+ (obmc_stride>>1);
- + const uint8_t *obmc3= obmc1+ obmc_stride*(obmc_stride>>1);
- + const uint8_t *obmc4= obmc3+ (obmc_stride>>1);
- + for(x=0; x<b_w; x++){
- + int v= obmc1[x] * block[3][x + y*src_stride]
- + +obmc2[x] * block[2][x + y*src_stride]
- + +obmc3[x] * block[1][x + y*src_stride]
- + +obmc4[x] * block[0][x + y*src_stride];
- +
- + v <<= 8 - LOG2_OBMC_MAX;
- + if(FRAC_BITS != 8) {
- + v >>= 8 - FRAC_BITS;
- + }
- + if(add) {
- + v += dst[x + y*dst_stride];
- + v = (v + (1<<(FRAC_BITS-1))) >> FRAC_BITS;
- + if(v&(~255)) v= ~(v>>31);
- + dst8[x + y*src_stride] = v;
- + } else {
- + dst[x + y*dst_stride] -= v;
- + }
- + }
- + }
- + }
- +}
- +
- +static av_always_inline void predict_slice(OBMCContext *s, IDWTELEM *buf, int plane_index, int add, int mb_y){
- + PlaneObmc *p= &s->plane[plane_index];
- + const int mb_w= s->b_width << s->block_max_depth;
- + const int mb_h= s->b_height << s->block_max_depth;
- + int x, y, mb_x;
- + int block_size = MB_SIZE >> s->block_max_depth;
- + int block_w = plane_index ? block_size>>s->chroma_h_shift : block_size;
- + int block_h = plane_index ? block_size>>s->chroma_v_shift : block_size;
- + const uint8_t *obmc = plane_index ? ff_obmc_tab[s->block_max_depth+s->chroma_h_shift] : ff_obmc_tab[s->block_max_depth];
- + const int obmc_stride= plane_index ? (2*block_size)>>s->chroma_h_shift : 2*block_size;
- + int ref_stride= s->current_picture->linesize[plane_index];
- + uint8_t *dst8= s->current_picture->data[plane_index];
- + int w= p->width;
- + int h= p->height;
- + av_assert2(s->chroma_h_shift == s->chroma_v_shift); // obmc params assume squares
- + if(s->keyframe || (s->avctx->debug&512)){
- + if(mb_y==mb_h)
- + return;
- +
- + if(add){
- + for(y=block_h*mb_y; y<FFMIN(h,block_h*(mb_y+1)); y++){
- + for(x=0; x<w; x++){
- + int v= buf[x + y*w] + (128<<FRAC_BITS) + (1<<(FRAC_BITS-1));
- + v >>= FRAC_BITS;
- + if(v&(~255)) v= ~(v>>31);
- + dst8[x + y*ref_stride]= v;
- + }
- + }
- + }else{
- + for(y=block_h*mb_y; y<FFMIN(h,block_h*(mb_y+1)); y++){
- + for(x=0; x<w; x++){
- + buf[x + y*w]-= 128<<FRAC_BITS;
- + }
- + }
- + }
- +
- + return;
- + }
- +
- + for(mb_x=0; mb_x<=mb_w; mb_x++){
- + add_yblock(s, 0, NULL, buf, dst8, obmc,
- + block_w*mb_x - block_w/2,
- + block_h*mb_y - block_h/2,
- + block_w, block_h,
- + w, h,
- + w, ref_stride, obmc_stride,
- + mb_x - 1, mb_y - 1,
- + add, 1, plane_index);
- + }
- +}
- +
- +static av_always_inline void predict_slice_buffered(OBMCContext *s, slice_buffer * sb, IDWTELEM * old_buffer, int plane_index, int add, int mb_y){
- + PlaneObmc *p= &s->plane[plane_index];
- + const int mb_w= s->b_width << s->block_max_depth;
- + const int mb_h= s->b_height << s->block_max_depth;
- + int x, y, mb_x;
- + int block_size = MB_SIZE >> s->block_max_depth;
- + int block_w = plane_index ? block_size>>s->chroma_h_shift : block_size;
- + int block_h = plane_index ? block_size>>s->chroma_v_shift : block_size;
- + const uint8_t *obmc = plane_index ? ff_obmc_tab[s->block_max_depth+s->chroma_h_shift] : ff_obmc_tab[s->block_max_depth];
- + int obmc_stride= plane_index ? (2*block_size)>>s->chroma_h_shift : 2*block_size;
- + int ref_stride= s->current_picture->linesize[plane_index];
- + uint8_t *dst8= s->current_picture->data[plane_index];
- + int w= p->width;
- + int h= p->height;
- +
- + if(s->keyframe || (s->avctx->debug&512)){
- + if(mb_y==mb_h)
- + return;
- +
- + if(add){
- + for(y=block_h*mb_y; y<FFMIN(h,block_h*(mb_y+1)); y++){
- + IDWTELEM * line = sb->line[y];
- + for(x=0; x<w; x++){
- + int v= line[x] + (128<<FRAC_BITS) + (1<<(FRAC_BITS-1));
- + v >>= FRAC_BITS;
- + if(v&(~255)) v= ~(v>>31);
- + dst8[x + y*ref_stride]= v;
- + }
- + }
- + }else{
- + for(y=block_h*mb_y; y<FFMIN(h,block_h*(mb_y+1)); y++){
- + IDWTELEM * line = sb->line[y];
- + for(x=0; x<w; x++){
- + line[x] -= 128 << FRAC_BITS;
- + }
- + }
- + }
- +
- + return;
- + }
- +
- + for(mb_x=0; mb_x<=mb_w; mb_x++){
- + add_yblock(s, 1, sb, old_buffer, dst8, obmc,
- + block_w*mb_x - block_w/2,
- + block_h*mb_y - block_h/2,
- + block_w, block_h,
- + w, h,
- + w, ref_stride, obmc_stride,
- + mb_x - 1, mb_y - 1,
- + add, 0, plane_index);
- + }
- +
- + if(s->avmv && mb_y < mb_h && plane_index == 0)
- + for(mb_x=0; mb_x<mb_w; mb_x++){
- + AVMotionVector *avmv = s->avmv + s->avmv_index;
- + const int b_width = s->b_width << s->block_max_depth;
- + const int b_stride= b_width;
- + BlockNode *bn= &s->block[mb_x + mb_y*b_stride];
- +
- + if (bn->type)
- + continue;
- +
- + s->avmv_index++;
- +
- + avmv->w = block_w;
- + avmv->h = block_h;
- + avmv->dst_x = block_w*mb_x - block_w/2;
- + avmv->dst_y = block_h*mb_y - block_h/2;
- + avmv->motion_scale = 8;
- + avmv->motion_x = bn->mx * s->mv_scale;
- + avmv->motion_y = bn->my * s->mv_scale;
- + avmv->src_x = avmv->dst_x + avmv->motion_x / 8;
- + avmv->src_y = avmv->dst_y + avmv->motion_y / 8;
- + avmv->source= -1 - bn->ref;
- + avmv->flags = 0;
- + }
- +}
- +
- +static av_always_inline void predict_plane(OBMCContext *s, IDWTELEM *buf, int plane_index, int add){
- + const int mb_h= s->b_height << s->block_max_depth;
- + int mb_y;
- + for(mb_y=0; mb_y<=mb_h; mb_y++)
- + predict_slice(s, buf, plane_index, add, mb_y);
- +}
- +
- +static inline void set_blocks(OBMCContext *s, int level, int x, int y, int l, int cb, int cr, int mx, int my, int ref, int type)
- +{
- + const int w= s->b_width << s->block_max_depth;
- + const int rem_depth= s->block_max_depth - level;
- + const int index= (x + y*w) << rem_depth;
- + const int block_w= 1<<rem_depth;
- + const int block_h= 1<<rem_depth; //FIXME "w!=h"
- + BlockNode block;
- + int i,j;
- +
- + block.color[0]= l;
- + block.color[1]= cb;
- + block.color[2]= cr;
- + block.mx= mx;
- + block.my= my;
- + block.ref= ref;
- + block.type= type;
- + block.level= level;
- +
- + for(j=0; j<block_h; j++){
- + for(i=0; i<block_w; i++){
- + s->block[index + i + j*w]= block;
- + }
- + }
- +}
- +
- +static inline void init_ref(MotionEstContext *c, uint8_t *src[3], uint8_t *ref[3], uint8_t *ref2[3], int x, int y, int ref_index){
- + OBMCContext *s = c->avctx->priv_data;
- + const int offset[3]= {
- + y*c-> stride + x,
- + ((y*c->uvstride + x)>>s->chroma_h_shift),
- + ((y*c->uvstride + x)>>s->chroma_h_shift),
- + };
- + int i;
- + for(i=0; i<3; i++){
- + c->src[0][i]= src [i];
- + c->ref[0][i]= ref [i] + offset[i];
- + }
- + av_assert2(!ref_index);
- +}
- +
- +#endif /* AVCODEC_OBMEMC_H */
- diff --git a/libavcodec/obmemc_data.h b/libavcodec/obmemc_data.h
- new file mode 100644
- index 0000000..a32c27e
- --- /dev/null
- +++ b/libavcodec/obmemc_data.h
- @@ -0,0 +1,132 @@
- +/*
- + * Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at>
- + * Copyright (C) 2006 Robert Edele <yartrebo@earthlink.net>
- + *
- + * This file is part of FFmpeg.
- + *
- + * FFmpeg is free software; you can redistribute it and/or
- + * modify it under the terms of the GNU Lesser General Public
- + * License as published by the Free Software Foundation; either
- + * version 2.1 of the License, or (at your option) any later version.
- + *
- + * FFmpeg is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- + * Lesser General Public License for more details.
- + *
- + * You should have received a copy of the GNU Lesser General Public
- + * License along with FFmpeg; if not, write to the Free Software
- + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- + */
- +
- +#ifndef AVCODEC_OBMEMC_DATA_H
- +#define AVCODEC_OBMEMC_DATA_H
- +
- +#include "obmemc.h"
- +
- +static const uint8_t obmc32[1024]={
- + 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0,
- + 0, 4, 4, 4, 8, 8, 8, 12, 12, 16, 16, 16, 20, 20, 20, 24, 24, 20, 20, 20, 16, 16, 16, 12, 12, 8, 8, 8, 4, 4, 4, 0,
- + 0, 4, 8, 8, 12, 12, 16, 20, 20, 24, 28, 28, 32, 32, 36, 40, 40, 36, 32, 32, 28, 28, 24, 20, 20, 16, 12, 12, 8, 8, 4, 0,
- + 0, 4, 8, 12, 16, 20, 24, 28, 28, 32, 36, 40, 44, 48, 52, 56, 56, 52, 48, 44, 40, 36, 32, 28, 28, 24, 20, 16, 12, 8, 4, 0,
- + 4, 8, 12, 16, 20, 24, 28, 32, 40, 44, 48, 52, 56, 60, 64, 68, 68, 64, 60, 56, 52, 48, 44, 40, 32, 28, 24, 20, 16, 12, 8, 4,
- + 4, 8, 12, 20, 24, 32, 36, 40, 48, 52, 56, 64, 68, 76, 80, 84, 84, 80, 76, 68, 64, 56, 52, 48, 40, 36, 32, 24, 20, 12, 8, 4,
- + 4, 8, 16, 24, 28, 36, 44, 48, 56, 60, 68, 76, 80, 88, 96,100,100, 96, 88, 80, 76, 68, 60, 56, 48, 44, 36, 28, 24, 16, 8, 4,
- + 4, 12, 20, 28, 32, 40, 48, 56, 64, 72, 80, 88, 92,100,108,116,116,108,100, 92, 88, 80, 72, 64, 56, 48, 40, 32, 28, 20, 12, 4,
- + 4, 12, 20, 28, 40, 48, 56, 64, 72, 80, 88, 96,108,116,124,132,132,124,116,108, 96, 88, 80, 72, 64, 56, 48, 40, 28, 20, 12, 4,
- + 4, 16, 24, 32, 44, 52, 60, 72, 80, 92,100,108,120,128,136,148,148,136,128,120,108,100, 92, 80, 72, 60, 52, 44, 32, 24, 16, 4,
- + 4, 16, 28, 36, 48, 56, 68, 80, 88,100,112,120,132,140,152,164,164,152,140,132,120,112,100, 88, 80, 68, 56, 48, 36, 28, 16, 4,
- + 4, 16, 28, 40, 52, 64, 76, 88, 96,108,120,132,144,156,168,180,180,168,156,144,132,120,108, 96, 88, 76, 64, 52, 40, 28, 16, 4,
- + 8, 20, 32, 44, 56, 68, 80, 92,108,120,132,144,156,168,180,192,192,180,168,156,144,132,120,108, 92, 80, 68, 56, 44, 32, 20, 8,
- + 8, 20, 32, 48, 60, 76, 88,100,116,128,140,156,168,184,196,208,208,196,184,168,156,140,128,116,100, 88, 76, 60, 48, 32, 20, 8,
- + 8, 20, 36, 52, 64, 80, 96,108,124,136,152,168,180,196,212,224,224,212,196,180,168,152,136,124,108, 96, 80, 64, 52, 36, 20, 8,
- + 8, 24, 40, 56, 68, 84,100,116,132,148,164,180,192,208,224,240,240,224,208,192,180,164,148,132,116,100, 84, 68, 56, 40, 24, 8,
- + 8, 24, 40, 56, 68, 84,100,116,132,148,164,180,192,208,224,240,240,224,208,192,180,164,148,132,116,100, 84, 68, 56, 40, 24, 8,
- + 8, 20, 36, 52, 64, 80, 96,108,124,136,152,168,180,196,212,224,224,212,196,180,168,152,136,124,108, 96, 80, 64, 52, 36, 20, 8,
- + 8, 20, 32, 48, 60, 76, 88,100,116,128,140,156,168,184,196,208,208,196,184,168,156,140,128,116,100, 88, 76, 60, 48, 32, 20, 8,
- + 8, 20, 32, 44, 56, 68, 80, 92,108,120,132,144,156,168,180,192,192,180,168,156,144,132,120,108, 92, 80, 68, 56, 44, 32, 20, 8,
- + 4, 16, 28, 40, 52, 64, 76, 88, 96,108,120,132,144,156,168,180,180,168,156,144,132,120,108, 96, 88, 76, 64, 52, 40, 28, 16, 4,
- + 4, 16, 28, 36, 48, 56, 68, 80, 88,100,112,120,132,140,152,164,164,152,140,132,120,112,100, 88, 80, 68, 56, 48, 36, 28, 16, 4,
- + 4, 16, 24, 32, 44, 52, 60, 72, 80, 92,100,108,120,128,136,148,148,136,128,120,108,100, 92, 80, 72, 60, 52, 44, 32, 24, 16, 4,
- + 4, 12, 20, 28, 40, 48, 56, 64, 72, 80, 88, 96,108,116,124,132,132,124,116,108, 96, 88, 80, 72, 64, 56, 48, 40, 28, 20, 12, 4,
- + 4, 12, 20, 28, 32, 40, 48, 56, 64, 72, 80, 88, 92,100,108,116,116,108,100, 92, 88, 80, 72, 64, 56, 48, 40, 32, 28, 20, 12, 4,
- + 4, 8, 16, 24, 28, 36, 44, 48, 56, 60, 68, 76, 80, 88, 96,100,100, 96, 88, 80, 76, 68, 60, 56, 48, 44, 36, 28, 24, 16, 8, 4,
- + 4, 8, 12, 20, 24, 32, 36, 40, 48, 52, 56, 64, 68, 76, 80, 84, 84, 80, 76, 68, 64, 56, 52, 48, 40, 36, 32, 24, 20, 12, 8, 4,
- + 4, 8, 12, 16, 20, 24, 28, 32, 40, 44, 48, 52, 56, 60, 64, 68, 68, 64, 60, 56, 52, 48, 44, 40, 32, 28, 24, 20, 16, 12, 8, 4,
- + 0, 4, 8, 12, 16, 20, 24, 28, 28, 32, 36, 40, 44, 48, 52, 56, 56, 52, 48, 44, 40, 36, 32, 28, 28, 24, 20, 16, 12, 8, 4, 0,
- + 0, 4, 8, 8, 12, 12, 16, 20, 20, 24, 28, 28, 32, 32, 36, 40, 40, 36, 32, 32, 28, 28, 24, 20, 20, 16, 12, 12, 8, 8, 4, 0,
- + 0, 4, 4, 4, 8, 8, 8, 12, 12, 16, 16, 16, 20, 20, 20, 24, 24, 20, 20, 20, 16, 16, 16, 12, 12, 8, 8, 8, 4, 4, 4, 0,
- + 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0,
- + //error:0.000020
- +};
- +static const uint8_t obmc16[256]={
- + 0, 4, 4, 8, 8, 12, 12, 16, 16, 12, 12, 8, 8, 4, 4, 0,
- + 4, 8, 16, 20, 28, 32, 40, 44, 44, 40, 32, 28, 20, 16, 8, 4,
- + 4, 16, 24, 36, 44, 56, 64, 76, 76, 64, 56, 44, 36, 24, 16, 4,
- + 8, 20, 36, 48, 64, 76, 92,104,104, 92, 76, 64, 48, 36, 20, 8,
- + 8, 28, 44, 64, 80,100,116,136,136,116,100, 80, 64, 44, 28, 8,
- + 12, 32, 56, 76,100,120,144,164,164,144,120,100, 76, 56, 32, 12,
- + 12, 40, 64, 92,116,144,168,196,196,168,144,116, 92, 64, 40, 12,
- + 16, 44, 76,104,136,164,196,224,224,196,164,136,104, 76, 44, 16,
- + 16, 44, 76,104,136,164,196,224,224,196,164,136,104, 76, 44, 16,
- + 12, 40, 64, 92,116,144,168,196,196,168,144,116, 92, 64, 40, 12,
- + 12, 32, 56, 76,100,120,144,164,164,144,120,100, 76, 56, 32, 12,
- + 8, 28, 44, 64, 80,100,116,136,136,116,100, 80, 64, 44, 28, 8,
- + 8, 20, 36, 48, 64, 76, 92,104,104, 92, 76, 64, 48, 36, 20, 8,
- + 4, 16, 24, 36, 44, 56, 64, 76, 76, 64, 56, 44, 36, 24, 16, 4,
- + 4, 8, 16, 20, 28, 32, 40, 44, 44, 40, 32, 28, 20, 16, 8, 4,
- + 0, 4, 4, 8, 8, 12, 12, 16, 16, 12, 12, 8, 8, 4, 4, 0,
- +//error:0.000015
- +};
- +
- +//linear *64
- +static const uint8_t obmc8[64]={
- + 4, 12, 20, 28, 28, 20, 12, 4,
- + 12, 36, 60, 84, 84, 60, 36, 12,
- + 20, 60,100,140,140,100, 60, 20,
- + 28, 84,140,196,196,140, 84, 28,
- + 28, 84,140,196,196,140, 84, 28,
- + 20, 60,100,140,140,100, 60, 20,
- + 12, 36, 60, 84, 84, 60, 36, 12,
- + 4, 12, 20, 28, 28, 20, 12, 4,
- +//error:0.000000
- +};
- +
- +//linear *64
- +static const uint8_t obmc4[16]={
- + 16, 48, 48, 16,
- + 48,144,144, 48,
- + 48,144,144, 48,
- + 16, 48, 48, 16,
- +//error:0.000000
- +};
- +
- +const int8_t ff_quant3bA[256]={
- + 0, 0, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
- + 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
- + 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
- + 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
- + 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
- + 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
- + 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
- + 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
- + 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
- + 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
- + 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
- + 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
- + 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
- + 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
- + 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
- + 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
- +};
- +
- +const uint8_t * const ff_obmc_tab[4]= {
- + obmc32, obmc16, obmc8, obmc4
- +};
- +
- +/* runtime generated tables */
- +uint8_t ff_qexp[QROOT];
- +int ff_scale_mv_ref[MAX_REF_FRAMES][MAX_REF_FRAMES];
- +
- +
- +#endif /* AVCODEC_OBMEMC_DATA_H */
- diff --git a/libavcodec/snow.c b/libavcodec/snow.c
- index a3e6afc..7b210ea 100644
- --- a/libavcodec/snow.c
- +++ b/libavcodec/snow.c
- @@ -26,7 +26,6 @@
- #include "snow_dwt.h"
- #include "internal.h"
- #include "snow.h"
- -#include "snowdata.h"
- #include "rangecoder.h"
- #include "mathops.h"
- @@ -66,40 +65,16 @@ void ff_snow_inner_add_yblock(const uint8_t *obmc, const int obmc_stride, uint8_
- }
- }
- -int ff_snow_get_buffer(SnowContext *s, AVFrame *frame)
- -{
- - int ret, i;
- - int edges_needed = av_codec_is_encoder(s->avctx->codec);
- -
- - frame->width = s->avctx->width ;
- - frame->height = s->avctx->height;
- - if (edges_needed) {
- - frame->width += 2 * EDGE_WIDTH;
- - frame->height += 2 * EDGE_WIDTH;
- - }
- - if ((ret = ff_get_buffer(s->avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0)
- - return ret;
- - if (edges_needed) {
- - for (i = 0; frame->data[i]; i++) {
- - int offset = (EDGE_WIDTH >> (i ? s->chroma_v_shift : 0)) *
- - frame->linesize[i] +
- - (EDGE_WIDTH >> (i ? s->chroma_h_shift : 0));
- - frame->data[i] += offset;
- - }
- - frame->width = s->avctx->width;
- - frame->height = s->avctx->height;
- - }
- -
- - return 0;
- -}
- -
- void ff_snow_reset_contexts(SnowContext *s){ //FIXME better initial contexts
- int plane_index, level, orientation;
- for(plane_index=0; plane_index<3; plane_index++){
- for(level=0; level<MAX_DECOMPOSITIONS; level++){
- for(orientation=level ? 1:0; orientation<4; orientation++){
- - memset(s->plane[plane_index].band[level][orientation].state, MID_STATE, sizeof(s->plane[plane_index].band[level][orientation].state));
- + memset(
- + s->plane[plane_index].band[level][orientation].state,
- + MID_STATE,
- + sizeof(s->plane[plane_index].band[level][orientation].state));
- }
- }
- }
- @@ -107,404 +82,25 @@ void ff_snow_reset_contexts(SnowContext *s){ //FIXME better initial contexts
- memset(s->block_state, MID_STATE, sizeof(s->block_state));
- }
- -int ff_snow_alloc_blocks(SnowContext *s){
- - int w= AV_CEIL_RSHIFT(s->avctx->width, LOG2_MB_SIZE);
- - int h= AV_CEIL_RSHIFT(s->avctx->height, LOG2_MB_SIZE);
- -
- - s->b_width = w;
- - s->b_height= h;
- -
- - av_free(s->block);
- - s->block= av_mallocz_array(w * h, sizeof(BlockNode) << (s->block_max_depth*2));
- - if (!s->block)
- - return AVERROR(ENOMEM);
- -
- - return 0;
- -}
- -
- -static av_cold void init_qexp(void){
- - int i;
- - double v=128;
- -
- - for(i=0; i<QROOT; i++){
- - ff_qexp[i]= lrintf(v);
- - v *= pow(2, 1.0 / QROOT);
- - }
- -}
- -static void mc_block(Plane *p, uint8_t *dst, const uint8_t *src, int stride, int b_w, int b_h, int dx, int dy){
- - static const uint8_t weight[64]={
- - 8,7,6,5,4,3,2,1,
- - 7,7,0,0,0,0,0,1,
- - 6,0,6,0,0,0,2,0,
- - 5,0,0,5,0,3,0,0,
- - 4,0,0,0,4,0,0,0,
- - 3,0,0,5,0,3,0,0,
- - 2,0,6,0,0,0,2,0,
- - 1,7,0,0,0,0,0,1,
- - };
- -
- - static const uint8_t brane[256]={
- - 0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x11,0x12,0x12,0x12,0x12,0x12,0x12,0x12,
- - 0x04,0x05,0xcc,0xcc,0xcc,0xcc,0xcc,0x41,0x15,0x16,0xcc,0xcc,0xcc,0xcc,0xcc,0x52,
- - 0x04,0xcc,0x05,0xcc,0xcc,0xcc,0x41,0xcc,0x15,0xcc,0x16,0xcc,0xcc,0xcc,0x52,0xcc,
- - 0x04,0xcc,0xcc,0x05,0xcc,0x41,0xcc,0xcc,0x15,0xcc,0xcc,0x16,0xcc,0x52,0xcc,0xcc,
- - 0x04,0xcc,0xcc,0xcc,0x41,0xcc,0xcc,0xcc,0x15,0xcc,0xcc,0xcc,0x16,0xcc,0xcc,0xcc,
- - 0x04,0xcc,0xcc,0x41,0xcc,0x05,0xcc,0xcc,0x15,0xcc,0xcc,0x52,0xcc,0x16,0xcc,0xcc,
- - 0x04,0xcc,0x41,0xcc,0xcc,0xcc,0x05,0xcc,0x15,0xcc,0x52,0xcc,0xcc,0xcc,0x16,0xcc,
- - 0x04,0x41,0xcc,0xcc,0xcc,0xcc,0xcc,0x05,0x15,0x52,0xcc,0xcc,0xcc,0xcc,0xcc,0x16,
- - 0x44,0x45,0x45,0x45,0x45,0x45,0x45,0x45,0x55,0x56,0x56,0x56,0x56,0x56,0x56,0x56,
- - 0x48,0x49,0xcc,0xcc,0xcc,0xcc,0xcc,0x85,0x59,0x5A,0xcc,0xcc,0xcc,0xcc,0xcc,0x96,
- - 0x48,0xcc,0x49,0xcc,0xcc,0xcc,0x85,0xcc,0x59,0xcc,0x5A,0xcc,0xcc,0xcc,0x96,0xcc,
- - 0x48,0xcc,0xcc,0x49,0xcc,0x85,0xcc,0xcc,0x59,0xcc,0xcc,0x5A,0xcc,0x96,0xcc,0xcc,
- - 0x48,0xcc,0xcc,0xcc,0x49,0xcc,0xcc,0xcc,0x59,0xcc,0xcc,0xcc,0x96,0xcc,0xcc,0xcc,
- - 0x48,0xcc,0xcc,0x85,0xcc,0x49,0xcc,0xcc,0x59,0xcc,0xcc,0x96,0xcc,0x5A,0xcc,0xcc,
- - 0x48,0xcc,0x85,0xcc,0xcc,0xcc,0x49,0xcc,0x59,0xcc,0x96,0xcc,0xcc,0xcc,0x5A,0xcc,
- - 0x48,0x85,0xcc,0xcc,0xcc,0xcc,0xcc,0x49,0x59,0x96,0xcc,0xcc,0xcc,0xcc,0xcc,0x5A,
- - };
- -
- - static const uint8_t needs[16]={
- - 0,1,0,0,
- - 2,4,2,0,
- - 0,1,0,0,
- - 15
- - };
- -
- - int x, y, b, r, l;
- - int16_t tmpIt [64*(32+HTAPS_MAX)];
- - uint8_t tmp2t[3][64*(32+HTAPS_MAX)];
- - int16_t *tmpI= tmpIt;
- - uint8_t *tmp2= tmp2t[0];
- - const uint8_t *hpel[11];
- - av_assert2(dx<16 && dy<16);
- - r= brane[dx + 16*dy]&15;
- - l= brane[dx + 16*dy]>>4;
- -
- - b= needs[l] | needs[r];
- - if(p && !p->diag_mc)
- - b= 15;
- -
- - if(b&5){
- - for(y=0; y < b_h+HTAPS_MAX-1; y++){
- - for(x=0; x < b_w; x++){
- - int a_1=src[x + HTAPS_MAX/2-4];
- - int a0= src[x + HTAPS_MAX/2-3];
- - int a1= src[x + HTAPS_MAX/2-2];
- - int a2= src[x + HTAPS_MAX/2-1];
- - int a3= src[x + HTAPS_MAX/2+0];
- - int a4= src[x + HTAPS_MAX/2+1];
- - int a5= src[x + HTAPS_MAX/2+2];
- - int a6= src[x + HTAPS_MAX/2+3];
- - int am=0;
- - if(!p || p->fast_mc){
- - am= 20*(a2+a3) - 5*(a1+a4) + (a0+a5);
- - tmpI[x]= am;
- - am= (am+16)>>5;
- - }else{
- - am= p->hcoeff[0]*(a2+a3) + p->hcoeff[1]*(a1+a4) + p->hcoeff[2]*(a0+a5) + p->hcoeff[3]*(a_1+a6);
- - tmpI[x]= am;
- - am= (am+32)>>6;
- - }
- -
- - if(am&(~255)) am= ~(am>>31);
- - tmp2[x]= am;
- - }
- - tmpI+= 64;
- - tmp2+= 64;
- - src += stride;
- - }
- - src -= stride*y;
- - }
- - src += HTAPS_MAX/2 - 1;
- - tmp2= tmp2t[1];
- -
- - if(b&2){
- - for(y=0; y < b_h; y++){
- - for(x=0; x < b_w+1; x++){
- - int a_1=src[x + (HTAPS_MAX/2-4)*stride];
- - int a0= src[x + (HTAPS_MAX/2-3)*stride];
- - int a1= src[x + (HTAPS_MAX/2-2)*stride];
- - int a2= src[x + (HTAPS_MAX/2-1)*stride];
- - int a3= src[x + (HTAPS_MAX/2+0)*stride];
- - int a4= src[x + (HTAPS_MAX/2+1)*stride];
- - int a5= src[x + (HTAPS_MAX/2+2)*stride];
- - int a6= src[x + (HTAPS_MAX/2+3)*stride];
- - int am=0;
- - if(!p || p->fast_mc)
- - am= (20*(a2+a3) - 5*(a1+a4) + (a0+a5) + 16)>>5;
- - else
- - am= (p->hcoeff[0]*(a2+a3) + p->hcoeff[1]*(a1+a4) + p->hcoeff[2]*(a0+a5) + p->hcoeff[3]*(a_1+a6) + 32)>>6;
- -
- - if(am&(~255)) am= ~(am>>31);
- - tmp2[x]= am;
- - }
- - src += stride;
- - tmp2+= 64;
- - }
- - src -= stride*y;
- - }
- - src += stride*(HTAPS_MAX/2 - 1);
- - tmp2= tmp2t[2];
- - tmpI= tmpIt;
- - if(b&4){
- - for(y=0; y < b_h; y++){
- - for(x=0; x < b_w; x++){
- - int a_1=tmpI[x + (HTAPS_MAX/2-4)*64];
- - int a0= tmpI[x + (HTAPS_MAX/2-3)*64];
- - int a1= tmpI[x + (HTAPS_MAX/2-2)*64];
- - int a2= tmpI[x + (HTAPS_MAX/2-1)*64];
- - int a3= tmpI[x + (HTAPS_MAX/2+0)*64];
- - int a4= tmpI[x + (HTAPS_MAX/2+1)*64];
- - int a5= tmpI[x + (HTAPS_MAX/2+2)*64];
- - int a6= tmpI[x + (HTAPS_MAX/2+3)*64];
- - int am=0;
- - if(!p || p->fast_mc)
- - am= (20*(a2+a3) - 5*(a1+a4) + (a0+a5) + 512)>>10;
- - else
- - am= (p->hcoeff[0]*(a2+a3) + p->hcoeff[1]*(a1+a4) + p->hcoeff[2]*(a0+a5) + p->hcoeff[3]*(a_1+a6) + 2048)>>12;
- - if(am&(~255)) am= ~(am>>31);
- - tmp2[x]= am;
- - }
- - tmpI+= 64;
- - tmp2+= 64;
- - }
- - }
- -
- - hpel[ 0]= src;
- - hpel[ 1]= tmp2t[0] + 64*(HTAPS_MAX/2-1);
- - hpel[ 2]= src + 1;
- -
- - hpel[ 4]= tmp2t[1];
- - hpel[ 5]= tmp2t[2];
- - hpel[ 6]= tmp2t[1] + 1;
- -
- - hpel[ 8]= src + stride;
- - hpel[ 9]= hpel[1] + 64;
- - hpel[10]= hpel[8] + 1;
- -
- -#define MC_STRIDE(x) (needs[x] ? 64 : stride)
- -
- - if(b==15){
- - int dxy = dx / 8 + dy / 8 * 4;
- - const uint8_t *src1 = hpel[dxy ];
- - const uint8_t *src2 = hpel[dxy + 1];
- - const uint8_t *src3 = hpel[dxy + 4];
- - const uint8_t *src4 = hpel[dxy + 5];
- - int stride1 = MC_STRIDE(dxy);
- - int stride2 = MC_STRIDE(dxy + 1);
- - int stride3 = MC_STRIDE(dxy + 4);
- - int stride4 = MC_STRIDE(dxy + 5);
- - dx&=7;
- - dy&=7;
- - for(y=0; y < b_h; y++){
- - for(x=0; x < b_w; x++){
- - dst[x]= ((8-dx)*(8-dy)*src1[x] + dx*(8-dy)*src2[x]+
- - (8-dx)* dy *src3[x] + dx* dy *src4[x]+32)>>6;
- - }
- - src1+=stride1;
- - src2+=stride2;
- - src3+=stride3;
- - src4+=stride4;
- - dst +=stride;
- - }
- - }else{
- - const uint8_t *src1= hpel[l];
- - const uint8_t *src2= hpel[r];
- - int stride1 = MC_STRIDE(l);
- - int stride2 = MC_STRIDE(r);
- - int a= weight[((dx&7) + (8*(dy&7)))];
- - int b= 8-a;
- - for(y=0; y < b_h; y++){
- - for(x=0; x < b_w; x++){
- - dst[x]= (a*src1[x] + b*src2[x] + 4)>>3;
- - }
- - src1+=stride1;
- - src2+=stride2;
- - dst +=stride;
- - }
- - }
- -}
- -
- -void ff_snow_pred_block(SnowContext *s, uint8_t *dst, uint8_t *tmp, ptrdiff_t stride, int sx, int sy, int b_w, int b_h, const BlockNode *block, int plane_index, int w, int h){
- - if(block->type & BLOCK_INTRA){
- - int x, y;
- - const unsigned color = block->color[plane_index];
- - const unsigned color4 = color*0x01010101;
- - if(b_w==32){
- - for(y=0; y < b_h; y++){
- - *(uint32_t*)&dst[0 + y*stride]= color4;
- - *(uint32_t*)&dst[4 + y*stride]= color4;
- - *(uint32_t*)&dst[8 + y*stride]= color4;
- - *(uint32_t*)&dst[12+ y*stride]= color4;
- - *(uint32_t*)&dst[16+ y*stride]= color4;
- - *(uint32_t*)&dst[20+ y*stride]= color4;
- - *(uint32_t*)&dst[24+ y*stride]= color4;
- - *(uint32_t*)&dst[28+ y*stride]= color4;
- - }
- - }else if(b_w==16){
- - for(y=0; y < b_h; y++){
- - *(uint32_t*)&dst[0 + y*stride]= color4;
- - *(uint32_t*)&dst[4 + y*stride]= color4;
- - *(uint32_t*)&dst[8 + y*stride]= color4;
- - *(uint32_t*)&dst[12+ y*stride]= color4;
- - }
- - }else if(b_w==8){
- - for(y=0; y < b_h; y++){
- - *(uint32_t*)&dst[0 + y*stride]= color4;
- - *(uint32_t*)&dst[4 + y*stride]= color4;
- - }
- - }else if(b_w==4){
- - for(y=0; y < b_h; y++){
- - *(uint32_t*)&dst[0 + y*stride]= color4;
- - }
- - }else{
- - for(y=0; y < b_h; y++){
- - for(x=0; x < b_w; x++){
- - dst[x + y*stride]= color;
- - }
- - }
- - }
- - }else{
- - uint8_t *src= s->last_picture[block->ref]->data[plane_index];
- - const int scale= plane_index ? (2*s->mv_scale)>>s->chroma_h_shift : 2*s->mv_scale;
- - int mx= block->mx*scale;
- - int my= block->my*scale;
- - const int dx= mx&15;
- - const int dy= my&15;
- - const int tab_index= 3 - (b_w>>2) + (b_w>>4);
- - sx += (mx>>4) - (HTAPS_MAX/2-1);
- - sy += (my>>4) - (HTAPS_MAX/2-1);
- - src += sx + sy*stride;
- - if( (unsigned)sx >= FFMAX(w - b_w - (HTAPS_MAX-2), 0)
- - || (unsigned)sy >= FFMAX(h - b_h - (HTAPS_MAX-2), 0)){
- - s->vdsp.emulated_edge_mc(tmp + MB_SIZE, src,
- - stride, stride,
- - b_w+HTAPS_MAX-1, b_h+HTAPS_MAX-1,
- - sx, sy, w, h);
- - src= tmp + MB_SIZE;
- - }
- -
- - av_assert2(s->chroma_h_shift == s->chroma_v_shift); // only one mv_scale
- -
- - av_assert2((tab_index>=0 && tab_index<4) || b_w==32);
- - if( (dx&3) || (dy&3)
- - || !(b_w == b_h || 2*b_w == b_h || b_w == 2*b_h)
- - || (b_w&(b_w-1))
- - || b_w == 1
- - || b_h == 1
- - || !s->plane[plane_index].fast_mc )
- - mc_block(&s->plane[plane_index], dst, src, stride, b_w, b_h, dx, dy);
- - else if(b_w==32){
- - int y;
- - for(y=0; y<b_h; y+=16){
- - s->h264qpel.put_h264_qpel_pixels_tab[0][dy+(dx>>2)](dst + y*stride, src + 3 + (y+3)*stride,stride);
- - s->h264qpel.put_h264_qpel_pixels_tab[0][dy+(dx>>2)](dst + 16 + y*stride, src + 19 + (y+3)*stride,stride);
- - }
- - }else if(b_w==b_h)
- - s->h264qpel.put_h264_qpel_pixels_tab[tab_index ][dy+(dx>>2)](dst,src + 3 + 3*stride,stride);
- - else if(b_w==2*b_h){
- - s->h264qpel.put_h264_qpel_pixels_tab[tab_index+1][dy+(dx>>2)](dst ,src + 3 + 3*stride,stride);
- - s->h264qpel.put_h264_qpel_pixels_tab[tab_index+1][dy+(dx>>2)](dst+b_h,src + 3 + b_h + 3*stride,stride);
- - }else{
- - av_assert2(2*b_w==b_h);
- - s->h264qpel.put_h264_qpel_pixels_tab[tab_index ][dy+(dx>>2)](dst ,src + 3 + 3*stride ,stride);
- - s->h264qpel.put_h264_qpel_pixels_tab[tab_index ][dy+(dx>>2)](dst+b_w*stride,src + 3 + 3*stride+b_w*stride,stride);
- - }
- - }
- -}
- -
- -#define mca(dx,dy,b_w)\
- -static void mc_block_hpel ## dx ## dy ## b_w(uint8_t *dst, const uint8_t *src, ptrdiff_t stride, int h){\
- - av_assert2(h==b_w);\
- - mc_block(NULL, dst, src-(HTAPS_MAX/2-1)-(HTAPS_MAX/2-1)*stride, stride, b_w, b_w, dx, dy);\
- -}
- -
- -mca( 0, 0,16)
- -mca( 8, 0,16)
- -mca( 0, 8,16)
- -mca( 8, 8,16)
- -mca( 0, 0,8)
- -mca( 8, 0,8)
- -mca( 0, 8,8)
- -mca( 8, 8,8)
- -
- av_cold int ff_snow_common_init(AVCodecContext *avctx){
- SnowContext *s = avctx->priv_data;
- - int width, height;
- - int i, j;
- + int width, height, ret;
- s->avctx= avctx;
- - s->max_ref_frames=1; //just make sure it's not an invalid value in case of no initial keyframe
- s->spatial_decomposition_count = 1;
- - ff_me_cmp_init(&s->mecc, avctx);
- - ff_hpeldsp_init(&s->hdsp, avctx->flags);
- - ff_videodsp_init(&s->vdsp, 8);
- - ff_dwt_init(&s->dwt);
- - ff_h264qpel_init(&s->h264qpel, 8);
- -
- -#define mcf(dx,dy)\
- - s->qdsp.put_qpel_pixels_tab [0][dy+dx/4]=\
- - s->qdsp.put_no_rnd_qpel_pixels_tab[0][dy+dx/4]=\
- - s->h264qpel.put_h264_qpel_pixels_tab[0][dy+dx/4];\
- - s->qdsp.put_qpel_pixels_tab [1][dy+dx/4]=\
- - s->qdsp.put_no_rnd_qpel_pixels_tab[1][dy+dx/4]=\
- - s->h264qpel.put_h264_qpel_pixels_tab[1][dy+dx/4];
- -
- - mcf( 0, 0)
- - mcf( 4, 0)
- - mcf( 8, 0)
- - mcf(12, 0)
- - mcf( 0, 4)
- - mcf( 4, 4)
- - mcf( 8, 4)
- - mcf(12, 4)
- - mcf( 0, 8)
- - mcf( 4, 8)
- - mcf( 8, 8)
- - mcf(12, 8)
- - mcf( 0,12)
- - mcf( 4,12)
- - mcf( 8,12)
- - mcf(12,12)
- -
- -#define mcfh(dx,dy)\
- - s->hdsp.put_pixels_tab [0][dy/4+dx/8]=\
- - s->hdsp.put_no_rnd_pixels_tab[0][dy/4+dx/8]=\
- - mc_block_hpel ## dx ## dy ## 16;\
- - s->hdsp.put_pixels_tab [1][dy/4+dx/8]=\
- - s->hdsp.put_no_rnd_pixels_tab[1][dy/4+dx/8]=\
- - mc_block_hpel ## dx ## dy ## 8;
- -
- - mcfh(0, 0)
- - mcfh(8, 0)
- - mcfh(0, 8)
- - mcfh(8, 8)
- -
- - init_qexp();
- -
- // dec += FFMAX(s->chroma_h_shift, s->chroma_v_shift);
- width= s->avctx->width;
- height= s->avctx->height;
- - FF_ALLOCZ_ARRAY_OR_GOTO(avctx, s->spatial_idwt_buffer, width, height * sizeof(IDWTELEM), fail);
- FF_ALLOCZ_ARRAY_OR_GOTO(avctx, s->spatial_dwt_buffer, width, height * sizeof(DWTELEM), fail); //FIXME this does not belong here
- FF_ALLOCZ_ARRAY_OR_GOTO(avctx, s->temp_dwt_buffer, width, sizeof(DWTELEM), fail);
- FF_ALLOCZ_ARRAY_OR_GOTO(avctx, s->temp_idwt_buffer, width, sizeof(IDWTELEM), fail);
- FF_ALLOC_ARRAY_OR_GOTO(avctx, s->run_buffer, ((width + 1) >> 1), ((height + 1) >> 1) * sizeof(*s->run_buffer), fail);
- - for(i=0; i<MAX_REF_FRAMES; i++) {
- - for(j=0; j<MAX_REF_FRAMES; j++)
- - ff_scale_mv_ref[i][j] = 256*(i+1)/(j+1);
- - s->last_picture[i] = av_frame_alloc();
- - if (!s->last_picture[i])
- - goto fail;
- - }
- -
- - s->mconly_picture = av_frame_alloc();
- - s->current_picture = av_frame_alloc();
- - if (!s->mconly_picture || !s->current_picture)
- - goto fail;
- + if ((ret = ff_obmc_common_init(&s->obmc, avctx)) < 0)
- + return ret;
- return 0;
- fail:
- @@ -513,22 +109,10 @@ fail:
- int ff_snow_common_init_after_header(AVCodecContext *avctx) {
- SnowContext *s = avctx->priv_data;
- - int plane_index, level, orientation;
- - int ret, emu_buf_size;
- -
- - if(!s->scratchbuf) {
- - if ((ret = ff_get_buffer(s->avctx, s->mconly_picture,
- - AV_GET_BUFFER_FLAG_REF)) < 0)
- - return ret;
- - FF_ALLOCZ_ARRAY_OR_GOTO(avctx, s->scratchbuf, FFMAX(s->mconly_picture->linesize[0], 2*avctx->width+256), 7*MB_SIZE, fail);
- - emu_buf_size = FFMAX(s->mconly_picture->linesize[0], 2*avctx->width+256) * (2 * MB_SIZE + HTAPS_MAX - 1);
- - FF_ALLOC_OR_GOTO(avctx, s->emu_edge_buffer, emu_buf_size, fail);
- - }
- + int plane_index, level, orientation, ret;
- - if(s->mconly_picture->format != avctx->pix_fmt) {
- - av_log(avctx, AV_LOG_ERROR, "pixel format changed\n");
- - return AVERROR_INVALIDDATA;
- - }
- + if ((ret = ff_obmc_common_init_after_header(&s->obmc)) < 0)
- + return ret;
- for(plane_index=0; plane_index < s->nb_planes; plane_index++){
- int w= s->avctx->width;
- @@ -563,7 +147,7 @@ int ff_snow_common_init_after_header(AVCodecContext *avctx) {
- b->buf += b->stride>>1;
- b->buf_y_offset = b->stride_line >> 1;
- }
- - b->ibuf= s->spatial_idwt_buffer + (b->buf - s->spatial_dwt_buffer);
- + b->ibuf= s->obmc.spatial_idwt_buffer + (b->buf - s->spatial_dwt_buffer);
- if(level)
- b->parent= &s->plane[plane_index].band[level-1][orientation];
- @@ -583,142 +167,15 @@ fail:
- return AVERROR(ENOMEM);
- }
- -#define USE_HALFPEL_PLANE 0
- -
- -static int halfpel_interpol(SnowContext *s, uint8_t *halfpel[4][4], AVFrame *frame){
- - int p,x,y;
- -
- - for(p=0; p < s->nb_planes; p++){
- - int is_chroma= !!p;
- - int w= is_chroma ? AV_CEIL_RSHIFT(s->avctx->width, s->chroma_h_shift) : s->avctx->width;
- - int h= is_chroma ? AV_CEIL_RSHIFT(s->avctx->height, s->chroma_v_shift) : s->avctx->height;
- - int ls= frame->linesize[p];
- - uint8_t *src= frame->data[p];
- -
- - halfpel[1][p] = av_malloc_array(ls, (h + 2 * EDGE_WIDTH));
- - halfpel[2][p] = av_malloc_array(ls, (h + 2 * EDGE_WIDTH));
- - halfpel[3][p] = av_malloc_array(ls, (h + 2 * EDGE_WIDTH));
- - if (!halfpel[1][p] || !halfpel[2][p] || !halfpel[3][p]) {
- - av_freep(&halfpel[1][p]);
- - av_freep(&halfpel[2][p]);
- - av_freep(&halfpel[3][p]);
- - return AVERROR(ENOMEM);
- - }
- - halfpel[1][p] += EDGE_WIDTH * (1 + ls);
- - halfpel[2][p] += EDGE_WIDTH * (1 + ls);
- - halfpel[3][p] += EDGE_WIDTH * (1 + ls);
- -
- - halfpel[0][p]= src;
- - for(y=0; y<h; y++){
- - for(x=0; x<w; x++){
- - int i= y*ls + x;
- -
- - halfpel[1][p][i]= (20*(src[i] + src[i+1]) - 5*(src[i-1] + src[i+2]) + (src[i-2] + src[i+3]) + 16 )>>5;
- - }
- - }
- - for(y=0; y<h; y++){
- - for(x=0; x<w; x++){
- - int i= y*ls + x;
- -
- - halfpel[2][p][i]= (20*(src[i] + src[i+ls]) - 5*(src[i-ls] + src[i+2*ls]) + (src[i-2*ls] + src[i+3*ls]) + 16 )>>5;
- - }
- - }
- - src= halfpel[1][p];
- - for(y=0; y<h; y++){
- - for(x=0; x<w; x++){
- - int i= y*ls + x;
- -
- - halfpel[3][p][i]= (20*(src[i] + src[i+ls]) - 5*(src[i-ls] + src[i+2*ls]) + (src[i-2*ls] + src[i+3*ls]) + 16 )>>5;
- - }
- - }
- -
- -//FIXME border!
- - }
- - return 0;
- -}
- -
- -void ff_snow_release_buffer(AVCodecContext *avctx)
- -{
- - SnowContext *s = avctx->priv_data;
- - int i;
- -
- - if(s->last_picture[s->max_ref_frames-1]->data[0]){
- - av_frame_unref(s->last_picture[s->max_ref_frames-1]);
- - for(i=0; i<9; i++)
- - if(s->halfpel_plane[s->max_ref_frames-1][1+i/3][i%3]) {
- - av_free(s->halfpel_plane[s->max_ref_frames-1][1+i/3][i%3] - EDGE_WIDTH*(1+s->current_picture->linesize[i%3]));
- - s->halfpel_plane[s->max_ref_frames-1][1+i/3][i%3] = NULL;
- - }
- - }
- -}
- -
- -int ff_snow_frame_start(SnowContext *s){
- - AVFrame *tmp;
- - int i, ret;
- -
- - ff_snow_release_buffer(s->avctx);
- -
- - tmp= s->last_picture[s->max_ref_frames-1];
- - for(i=s->max_ref_frames-1; i>0; i--)
- - s->last_picture[i] = s->last_picture[i-1];
- - memmove(s->halfpel_plane+1, s->halfpel_plane, (s->max_ref_frames-1)*sizeof(void*)*4*4);
- - if(USE_HALFPEL_PLANE && s->current_picture->data[0]) {
- - if((ret = halfpel_interpol(s, s->halfpel_plane[0], s->current_picture)) < 0)
- - return ret;
- - }
- - 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;
- - if(s->ref_frames==0){
- - av_log(s->avctx,AV_LOG_ERROR, "No reference frames\n");
- - return AVERROR_INVALIDDATA;
- - }
- - }
- - if ((ret = ff_snow_get_buffer(s, s->current_picture)) < 0)
- - return ret;
- -
- - s->current_picture->key_frame= s->keyframe;
- -
- - return 0;
- -}
- -
- av_cold void ff_snow_common_end(SnowContext *s)
- {
- - int plane_index, level, orientation, i;
- + int plane_index, level, orientation;
- av_freep(&s->spatial_dwt_buffer);
- av_freep(&s->temp_dwt_buffer);
- - av_freep(&s->spatial_idwt_buffer);
- av_freep(&s->temp_idwt_buffer);
- av_freep(&s->run_buffer);
- - s->m.me.temp= NULL;
- - av_freep(&s->m.me.scratchpad);
- - av_freep(&s->m.me.map);
- - av_freep(&s->m.me.score_map);
- - av_freep(&s->m.sc.obmc_scratchpad);
- -
- - av_freep(&s->block);
- - av_freep(&s->scratchbuf);
- - av_freep(&s->emu_edge_buffer);
- -
- - 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] && s->last_picture[i]->data[0]) {
- - av_assert0(s->last_picture[i]->data[0] != s->current_picture->data[0]);
- - }
- - av_frame_free(&s->last_picture[i]);
- - }
- -
- for(plane_index=0; plane_index < MAX_PLANES; plane_index++){
- for(level=MAX_DECOMPOSITIONS-1; level>=0; level--){
- for(orientation=level ? 1 : 0; orientation<4; orientation++){
- @@ -728,6 +185,6 @@ av_cold void ff_snow_common_end(SnowContext *s)
- }
- }
- }
- - av_frame_free(&s->mconly_picture);
- - av_frame_free(&s->current_picture);
- +
- + ff_obmc_close(&s->obmc);
- }
- diff --git a/libavcodec/snow.h b/libavcodec/snow.h
- index 59c710b..712ed7d 100644
- --- a/libavcodec/snow.h
- +++ b/libavcodec/snow.h
- @@ -32,48 +32,11 @@
- #include "rangecoder.h"
- #include "mathops.h"
- -#define FF_MPV_OFFSET(x) (offsetof(MpegEncContext, x) + offsetof(SnowContext, m))
- -#include "mpegvideo.h"
- -#include "h264qpel.h"
- +#define FF_MPV_OFFSET(x) (offsetof(MpegEncContext, x) + offsetof(SnowContext, obmc.m))
- +#include "obmemc.h"
- #define MID_STATE 128
- -#define MAX_PLANES 4
- -#define QSHIFT 5
- -#define QROOT (1<<QSHIFT)
- -#define LOSSLESS_QLOG -128
- -#define FRAC_BITS 4
- -#define MAX_REF_FRAMES 8
- -
- -#define LOG2_OBMC_MAX 8
- -#define OBMC_MAX (1<<(LOG2_OBMC_MAX))
- -typedef struct BlockNode{
- - int16_t mx; ///< Motion vector component X, see mv_scale
- - int16_t my; ///< Motion vector component Y, see mv_scale
- - uint8_t ref; ///< Reference frame index
- - uint8_t color[3]; ///< Color for intra
- - uint8_t type; ///< Bitfield of BLOCK_*
- -//#define TYPE_SPLIT 1
- -#define BLOCK_INTRA 1 ///< Intra block, inter otherwise
- -#define BLOCK_OPT 2 ///< Block needs no checks in this round of iterative motion estiation
- -//#define TYPE_NOCOLOR 4
- - uint8_t level; //FIXME merge into type?
- -}BlockNode;
- -
- -static const BlockNode null_block= { //FIXME add border maybe
- - .color= {128,128,128},
- - .mx= 0,
- - .my= 0,
- - .ref= 0,
- - .type= 0,
- - .level= 0,
- -};
- -
- -#define LOG2_MB_SIZE 4
- -#define MB_SIZE (1<<LOG2_MB_SIZE)
- -#define ENCODER_EXTRA_BITS 4
- -#define HTAPS_MAX 8
- -
- typedef struct x_and_coeff{
- int16_t x;
- uint16_t coeff;
- @@ -99,33 +62,12 @@ typedef struct Plane{
- int width;
- int height;
- SubBand band[MAX_DECOMPOSITIONS][4];
- -
- - int htaps;
- - int8_t hcoeff[HTAPS_MAX/2];
- - int diag_mc;
- - int fast_mc;
- -
- - int last_htaps;
- - int8_t last_hcoeff[HTAPS_MAX/2];
- - int last_diag_mc;
- -}Plane;
- +} Plane;
- typedef struct SnowContext{
- AVClass *class;
- AVCodecContext *avctx;
- RangeCoder c;
- - MECmpContext mecc;
- - HpelDSPContext hdsp;
- - QpelDSPContext qdsp;
- - VideoDSPContext vdsp;
- - H264QpelContext h264qpel;
- - MpegvideoEncDSPContext mpvencdsp;
- - SnowDWTContext dwt;
- - AVFrame *input_picture; ///< new_picture with the internal linesizes
- - AVFrame *current_picture;
- - AVFrame *last_picture[MAX_REF_FRAMES];
- - uint8_t *halfpel_plane[MAX_REF_FRAMES][4][4];
- - AVFrame *mconly_picture;
- // uint8_t q_context[16];
- uint8_t header_state[32];
- uint8_t block_state[128 + 32*128];
- @@ -138,13 +80,8 @@ typedef struct SnowContext{
- int spatial_decomposition_count;
- int last_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;
- DWTELEM *temp_dwt_buffer;
- - IDWTELEM *spatial_idwt_buffer;
- IDWTELEM *temp_idwt_buffer;
- int *run_buffer;
- int colorspace_type;
- @@ -153,49 +90,24 @@ typedef struct SnowContext{
- int spatial_scalability;
- int qlog;
- int last_qlog;
- - int lambda;
- - int lambda2;
- int pass1_rc;
- - int mv_scale;
- - int last_mv_scale;
- int qbias;
- int last_qbias;
- #define QBIAS_SHIFT 3
- - int b_width;
- - int b_height;
- - int block_max_depth;
- - int last_block_max_depth;
- int nb_planes;
- Plane plane[MAX_PLANES];
- - BlockNode *block;
- -#define ME_CACHE_SIZE 1024
- - unsigned me_cache[ME_CACHE_SIZE];
- - unsigned me_cache_generation;
- slice_buffer sb;
- int memc_only;
- int no_bitstream;
- - int intra_penalty;
- - int motion_est;
- - int iterative_dia_size;
- int scenechange_threshold;
- - MpegEncContext m; // needed for motion estimation, should not be used for anything else, the idea is to eventually make the motion estimation independent of MpegEncContext, so this will be removed then (FIXME/XXX)
- -
- - uint8_t *scratchbuf;
- - uint8_t *emu_edge_buffer;
- -
- - AVMotionVector *avmv;
- - int avmv_index;
- uint64_t encoding_error[AV_NUM_DATA_POINTERS];
- + OBMCContext obmc;
- +
- int pred;
- }SnowContext;
- -/* Tables */
- -extern const uint8_t * const ff_obmc_tab[4];
- -extern uint8_t ff_qexp[QROOT];
- -extern int ff_scale_mv_ref[MAX_REF_FRAMES][MAX_REF_FRAMES];
- -
- /* C bits used by mmx/sse2/altivec */
- static av_always_inline void snow_interleave_line_header(int * i, int width, IDWTELEM * low, IDWTELEM * high){
- @@ -239,265 +151,7 @@ static av_always_inline void snow_horizontal_compose_liftS_lead_out(int i, IDWTE
- int ff_snow_common_init(AVCodecContext *avctx);
- int ff_snow_common_init_after_header(AVCodecContext *avctx);
- void ff_snow_common_end(SnowContext *s);
- -void ff_snow_release_buffer(AVCodecContext *avctx);
- void ff_snow_reset_contexts(SnowContext *s);
- -int ff_snow_alloc_blocks(SnowContext *s);
- -int ff_snow_frame_start(SnowContext *s);
- -void ff_snow_pred_block(SnowContext *s, uint8_t *dst, uint8_t *tmp, ptrdiff_t stride,
- - int sx, int sy, int b_w, int b_h, const BlockNode *block,
- - int plane_index, int w, int h);
- -int ff_snow_get_buffer(SnowContext *s, AVFrame *frame);
- -/* common inline functions */
- -//XXX doublecheck all of them should stay inlined
- -
- -static inline void pred_mv(SnowContext *s, int *mx, int *my, int ref,
- - const BlockNode *left, const BlockNode *top, const BlockNode *tr){
- - if(s->ref_frames == 1){
- - *mx = mid_pred(left->mx, top->mx, tr->mx);
- - *my = mid_pred(left->my, top->my, tr->my);
- - }else{
- - const int *scale = ff_scale_mv_ref[ref];
- - *mx = mid_pred((left->mx * scale[left->ref] + 128) >>8,
- - (top ->mx * scale[top ->ref] + 128) >>8,
- - (tr ->mx * scale[tr ->ref] + 128) >>8);
- - *my = mid_pred((left->my * scale[left->ref] + 128) >>8,
- - (top ->my * scale[top ->ref] + 128) >>8,
- - (tr ->my * scale[tr ->ref] + 128) >>8);
- - }
- -}
- -
- -static av_always_inline int same_block(BlockNode *a, BlockNode *b){
- - if((a->type&BLOCK_INTRA) && (b->type&BLOCK_INTRA)){
- - return !((a->color[0] - b->color[0]) | (a->color[1] - b->color[1]) | (a->color[2] - b->color[2]));
- - }else{
- - return !((a->mx - b->mx) | (a->my - b->my) | (a->ref - b->ref) | ((a->type ^ b->type)&BLOCK_INTRA));
- - }
- -}
- -
- -//FIXME name cleanup (b_w, block_w, b_width stuff)
- -//XXX should we really inline it?
- -static av_always_inline void add_yblock(SnowContext *s, int sliced, slice_buffer *sb, IDWTELEM *dst, uint8_t *dst8, const 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;
- - BlockNode *lt= &s->block[b_x + b_y*b_stride];
- - BlockNode *rt= lt+1;
- - BlockNode *lb= lt+b_stride;
- - BlockNode *rb= lb+1;
- - uint8_t *block[4];
- - // When src_stride is large enough, it is possible to interleave the blocks.
- - // Otherwise the blocks are written sequentially in the tmp buffer.
- - int tmp_step= src_stride >= 7*MB_SIZE ? MB_SIZE : MB_SIZE*src_stride;
- - uint8_t *tmp = s->scratchbuf;
- - uint8_t *ptmp;
- - int x,y;
- -
- - if(b_x<0){
- - lt= rt;
- - lb= rb;
- - }else if(b_x + 1 >= b_width){
- - rt= lt;
- - rb= lb;
- - }
- - if(b_y<0){
- - lt= lb;
- - rt= rb;
- - }else if(b_y + 1 >= b_height){
- - lb= lt;
- - rb= rt;
- - }
- -
- - if(src_x<0){ //FIXME merge with prev & always round internal width up to *16
- - obmc -= src_x;
- - b_w += src_x;
- - if(!sliced && !offset_dst)
- - dst -= src_x;
- - src_x=0;
- - }
- - if(src_x + b_w > w){
- - b_w = w - src_x;
- - }
- - if(src_y<0){
- - obmc -= src_y*obmc_stride;
- - b_h += src_y;
- - if(!sliced && !offset_dst)
- - dst -= src_y*dst_stride;
- - src_y=0;
- - }
- - if(src_y + b_h> h){
- - b_h = h - src_y;
- - }
- -
- - if(b_w<=0 || b_h<=0) return;
- -
- - if(!sliced && offset_dst)
- - dst += src_x + src_y*dst_stride;
- - dst8+= src_x + src_y*src_stride;
- -// src += src_x + src_y*src_stride;
- -
- - ptmp= tmp + 3*tmp_step;
- - block[0]= ptmp;
- - ptmp+=tmp_step;
- - ff_snow_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;
- - ff_snow_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)){
- - block[2]= block[0];
- - }else if(same_block(rt, lb)){
- - block[2]= block[1];
- - }else{
- - block[2]= ptmp;
- - ptmp+=tmp_step;
- - ff_snow_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) ){
- - block[3]= block[0];
- - }else if(same_block(rt, rb)){
- - block[3]= block[1];
- - }else if(same_block(lb, rb)){
- - block[3]= block[2];
- - }else{
- - block[3]= ptmp;
- - ff_snow_pred_block(s, block[3], tmp, src_stride, src_x, src_y, b_w, b_h, rb, plane_index, w, h);
- - }
- - if(sliced){
- - s->dwt.inner_add_yblock(obmc, obmc_stride, block, b_w, b_h, src_x,src_y, src_stride, sb, add, dst8);
- - }else{
- - for(y=0; y<b_h; y++){
- - //FIXME ugly misuse of obmc_stride
- - const uint8_t *obmc1= obmc + y*obmc_stride;
- - const uint8_t *obmc2= obmc1+ (obmc_stride>>1);
- - const uint8_t *obmc3= obmc1+ obmc_stride*(obmc_stride>>1);
- - const uint8_t *obmc4= obmc3+ (obmc_stride>>1);
- - for(x=0; x<b_w; x++){
- - int v= obmc1[x] * block[3][x + y*src_stride]
- - +obmc2[x] * block[2][x + y*src_stride]
- - +obmc3[x] * block[1][x + y*src_stride]
- - +obmc4[x] * block[0][x + y*src_stride];
- -
- - v <<= 8 - LOG2_OBMC_MAX;
- - if(FRAC_BITS != 8){
- - v >>= 8 - FRAC_BITS;
- - }
- - if(add){
- - v += dst[x + y*dst_stride];
- - v = (v + (1<<(FRAC_BITS-1))) >> FRAC_BITS;
- - if(v&(~255)) v= ~(v>>31);
- - dst8[x + y*src_stride] = v;
- - }else{
- - dst[x + y*dst_stride] -= v;
- - }
- - }
- - }
- - }
- -}
- -
- -static av_always_inline void predict_slice(SnowContext *s, IDWTELEM *buf, int plane_index, int add, int mb_y){
- - Plane *p= &s->plane[plane_index];
- - const int mb_w= s->b_width << s->block_max_depth;
- - const int mb_h= s->b_height << s->block_max_depth;
- - int x, y, mb_x;
- - int block_size = MB_SIZE >> s->block_max_depth;
- - int block_w = plane_index ? block_size>>s->chroma_h_shift : block_size;
- - int block_h = plane_index ? block_size>>s->chroma_v_shift : block_size;
- - const uint8_t *obmc = plane_index ? ff_obmc_tab[s->block_max_depth+s->chroma_h_shift] : ff_obmc_tab[s->block_max_depth];
- - const int obmc_stride= plane_index ? (2*block_size)>>s->chroma_h_shift : 2*block_size;
- - int ref_stride= s->current_picture->linesize[plane_index];
- - uint8_t *dst8= s->current_picture->data[plane_index];
- - int w= p->width;
- - int h= p->height;
- - av_assert2(s->chroma_h_shift == s->chroma_v_shift); // obmc params assume squares
- - if(s->keyframe || (s->avctx->debug&512)){
- - if(mb_y==mb_h)
- - return;
- -
- - if(add){
- - for(y=block_h*mb_y; y<FFMIN(h,block_h*(mb_y+1)); y++){
- - for(x=0; x<w; x++){
- - int v= buf[x + y*w] + (128<<FRAC_BITS) + (1<<(FRAC_BITS-1));
- - v >>= FRAC_BITS;
- - if(v&(~255)) v= ~(v>>31);
- - dst8[x + y*ref_stride]= v;
- - }
- - }
- - }else{
- - for(y=block_h*mb_y; y<FFMIN(h,block_h*(mb_y+1)); y++){
- - for(x=0; x<w; x++){
- - buf[x + y*w]-= 128<<FRAC_BITS;
- - }
- - }
- - }
- -
- - return;
- - }
- -
- - for(mb_x=0; mb_x<=mb_w; mb_x++){
- - add_yblock(s, 0, NULL, buf, dst8, obmc,
- - block_w*mb_x - block_w/2,
- - block_h*mb_y - block_h/2,
- - block_w, block_h,
- - w, h,
- - w, ref_stride, obmc_stride,
- - mb_x - 1, mb_y - 1,
- - add, 1, plane_index);
- - }
- -}
- -
- -static av_always_inline void predict_plane(SnowContext *s, IDWTELEM *buf, int plane_index, int add){
- - const int mb_h= s->b_height << s->block_max_depth;
- - int mb_y;
- - for(mb_y=0; mb_y<=mb_h; mb_y++)
- - predict_slice(s, buf, plane_index, add, mb_y);
- -}
- -
- -static inline void set_blocks(SnowContext *s, int level, int x, int y, int l, int cb, int cr, int mx, int my, int ref, int type){
- - const int w= s->b_width << s->block_max_depth;
- - const int rem_depth= s->block_max_depth - level;
- - const int index= (x + y*w) << rem_depth;
- - const int block_w= 1<<rem_depth;
- - const int block_h= 1<<rem_depth; //FIXME "w!=h"
- - BlockNode block;
- - int i,j;
- -
- - block.color[0]= l;
- - block.color[1]= cb;
- - block.color[2]= cr;
- - block.mx= mx;
- - block.my= my;
- - block.ref= ref;
- - block.type= type;
- - block.level= level;
- -
- - for(j=0; j<block_h; j++){
- - for(i=0; i<block_w; i++){
- - s->block[index + i + j*w]= block;
- - }
- - }
- -}
- -
- -static inline void init_ref(MotionEstContext *c, uint8_t *src[3], uint8_t *ref[3], uint8_t *ref2[3], int x, int y, int ref_index){
- - SnowContext *s = c->avctx->priv_data;
- - const int offset[3]= {
- - y*c-> stride + x,
- - ((y*c->uvstride + x)>>s->chroma_h_shift),
- - ((y*c->uvstride + x)>>s->chroma_h_shift),
- - };
- - int i;
- - for(i=0; i<3; i++){
- - c->src[0][i]= src [i];
- - c->ref[0][i]= ref [i] + offset[i];
- - }
- - av_assert2(!ref_index);
- -}
- -
- /* bitstream functions */
- diff --git a/libavcodec/snowdata.h b/libavcodec/snowdata.h
- deleted file mode 100644
- index 490fdf8..0000000
- --- a/libavcodec/snowdata.h
- +++ /dev/null
- @@ -1,132 +0,0 @@
- -/*
- - * Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at>
- - * Copyright (C) 2006 Robert Edele <yartrebo@earthlink.net>
- - *
- - * This file is part of FFmpeg.
- - *
- - * FFmpeg is free software; you can redistribute it and/or
- - * modify it under the terms of the GNU Lesser General Public
- - * License as published by the Free Software Foundation; either
- - * version 2.1 of the License, or (at your option) any later version.
- - *
- - * FFmpeg is distributed in the hope that it will be useful,
- - * but WITHOUT ANY WARRANTY; without even the implied warranty of
- - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- - * Lesser General Public License for more details.
- - *
- - * You should have received a copy of the GNU Lesser General Public
- - * License along with FFmpeg; if not, write to the Free Software
- - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- - */
- -
- -#ifndef AVCODEC_SNOWDATA_H
- -#define AVCODEC_SNOWDATA_H
- -
- -#include "snow.h"
- -
- -static const uint8_t obmc32[1024]={
- - 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0,
- - 0, 4, 4, 4, 8, 8, 8, 12, 12, 16, 16, 16, 20, 20, 20, 24, 24, 20, 20, 20, 16, 16, 16, 12, 12, 8, 8, 8, 4, 4, 4, 0,
- - 0, 4, 8, 8, 12, 12, 16, 20, 20, 24, 28, 28, 32, 32, 36, 40, 40, 36, 32, 32, 28, 28, 24, 20, 20, 16, 12, 12, 8, 8, 4, 0,
- - 0, 4, 8, 12, 16, 20, 24, 28, 28, 32, 36, 40, 44, 48, 52, 56, 56, 52, 48, 44, 40, 36, 32, 28, 28, 24, 20, 16, 12, 8, 4, 0,
- - 4, 8, 12, 16, 20, 24, 28, 32, 40, 44, 48, 52, 56, 60, 64, 68, 68, 64, 60, 56, 52, 48, 44, 40, 32, 28, 24, 20, 16, 12, 8, 4,
- - 4, 8, 12, 20, 24, 32, 36, 40, 48, 52, 56, 64, 68, 76, 80, 84, 84, 80, 76, 68, 64, 56, 52, 48, 40, 36, 32, 24, 20, 12, 8, 4,
- - 4, 8, 16, 24, 28, 36, 44, 48, 56, 60, 68, 76, 80, 88, 96,100,100, 96, 88, 80, 76, 68, 60, 56, 48, 44, 36, 28, 24, 16, 8, 4,
- - 4, 12, 20, 28, 32, 40, 48, 56, 64, 72, 80, 88, 92,100,108,116,116,108,100, 92, 88, 80, 72, 64, 56, 48, 40, 32, 28, 20, 12, 4,
- - 4, 12, 20, 28, 40, 48, 56, 64, 72, 80, 88, 96,108,116,124,132,132,124,116,108, 96, 88, 80, 72, 64, 56, 48, 40, 28, 20, 12, 4,
- - 4, 16, 24, 32, 44, 52, 60, 72, 80, 92,100,108,120,128,136,148,148,136,128,120,108,100, 92, 80, 72, 60, 52, 44, 32, 24, 16, 4,
- - 4, 16, 28, 36, 48, 56, 68, 80, 88,100,112,120,132,140,152,164,164,152,140,132,120,112,100, 88, 80, 68, 56, 48, 36, 28, 16, 4,
- - 4, 16, 28, 40, 52, 64, 76, 88, 96,108,120,132,144,156,168,180,180,168,156,144,132,120,108, 96, 88, 76, 64, 52, 40, 28, 16, 4,
- - 8, 20, 32, 44, 56, 68, 80, 92,108,120,132,144,156,168,180,192,192,180,168,156,144,132,120,108, 92, 80, 68, 56, 44, 32, 20, 8,
- - 8, 20, 32, 48, 60, 76, 88,100,116,128,140,156,168,184,196,208,208,196,184,168,156,140,128,116,100, 88, 76, 60, 48, 32, 20, 8,
- - 8, 20, 36, 52, 64, 80, 96,108,124,136,152,168,180,196,212,224,224,212,196,180,168,152,136,124,108, 96, 80, 64, 52, 36, 20, 8,
- - 8, 24, 40, 56, 68, 84,100,116,132,148,164,180,192,208,224,240,240,224,208,192,180,164,148,132,116,100, 84, 68, 56, 40, 24, 8,
- - 8, 24, 40, 56, 68, 84,100,116,132,148,164,180,192,208,224,240,240,224,208,192,180,164,148,132,116,100, 84, 68, 56, 40, 24, 8,
- - 8, 20, 36, 52, 64, 80, 96,108,124,136,152,168,180,196,212,224,224,212,196,180,168,152,136,124,108, 96, 80, 64, 52, 36, 20, 8,
- - 8, 20, 32, 48, 60, 76, 88,100,116,128,140,156,168,184,196,208,208,196,184,168,156,140,128,116,100, 88, 76, 60, 48, 32, 20, 8,
- - 8, 20, 32, 44, 56, 68, 80, 92,108,120,132,144,156,168,180,192,192,180,168,156,144,132,120,108, 92, 80, 68, 56, 44, 32, 20, 8,
- - 4, 16, 28, 40, 52, 64, 76, 88, 96,108,120,132,144,156,168,180,180,168,156,144,132,120,108, 96, 88, 76, 64, 52, 40, 28, 16, 4,
- - 4, 16, 28, 36, 48, 56, 68, 80, 88,100,112,120,132,140,152,164,164,152,140,132,120,112,100, 88, 80, 68, 56, 48, 36, 28, 16, 4,
- - 4, 16, 24, 32, 44, 52, 60, 72, 80, 92,100,108,120,128,136,148,148,136,128,120,108,100, 92, 80, 72, 60, 52, 44, 32, 24, 16, 4,
- - 4, 12, 20, 28, 40, 48, 56, 64, 72, 80, 88, 96,108,116,124,132,132,124,116,108, 96, 88, 80, 72, 64, 56, 48, 40, 28, 20, 12, 4,
- - 4, 12, 20, 28, 32, 40, 48, 56, 64, 72, 80, 88, 92,100,108,116,116,108,100, 92, 88, 80, 72, 64, 56, 48, 40, 32, 28, 20, 12, 4,
- - 4, 8, 16, 24, 28, 36, 44, 48, 56, 60, 68, 76, 80, 88, 96,100,100, 96, 88, 80, 76, 68, 60, 56, 48, 44, 36, 28, 24, 16, 8, 4,
- - 4, 8, 12, 20, 24, 32, 36, 40, 48, 52, 56, 64, 68, 76, 80, 84, 84, 80, 76, 68, 64, 56, 52, 48, 40, 36, 32, 24, 20, 12, 8, 4,
- - 4, 8, 12, 16, 20, 24, 28, 32, 40, 44, 48, 52, 56, 60, 64, 68, 68, 64, 60, 56, 52, 48, 44, 40, 32, 28, 24, 20, 16, 12, 8, 4,
- - 0, 4, 8, 12, 16, 20, 24, 28, 28, 32, 36, 40, 44, 48, 52, 56, 56, 52, 48, 44, 40, 36, 32, 28, 28, 24, 20, 16, 12, 8, 4, 0,
- - 0, 4, 8, 8, 12, 12, 16, 20, 20, 24, 28, 28, 32, 32, 36, 40, 40, 36, 32, 32, 28, 28, 24, 20, 20, 16, 12, 12, 8, 8, 4, 0,
- - 0, 4, 4, 4, 8, 8, 8, 12, 12, 16, 16, 16, 20, 20, 20, 24, 24, 20, 20, 20, 16, 16, 16, 12, 12, 8, 8, 8, 4, 4, 4, 0,
- - 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0,
- - //error:0.000020
- -};
- -static const uint8_t obmc16[256]={
- - 0, 4, 4, 8, 8, 12, 12, 16, 16, 12, 12, 8, 8, 4, 4, 0,
- - 4, 8, 16, 20, 28, 32, 40, 44, 44, 40, 32, 28, 20, 16, 8, 4,
- - 4, 16, 24, 36, 44, 56, 64, 76, 76, 64, 56, 44, 36, 24, 16, 4,
- - 8, 20, 36, 48, 64, 76, 92,104,104, 92, 76, 64, 48, 36, 20, 8,
- - 8, 28, 44, 64, 80,100,116,136,136,116,100, 80, 64, 44, 28, 8,
- - 12, 32, 56, 76,100,120,144,164,164,144,120,100, 76, 56, 32, 12,
- - 12, 40, 64, 92,116,144,168,196,196,168,144,116, 92, 64, 40, 12,
- - 16, 44, 76,104,136,164,196,224,224,196,164,136,104, 76, 44, 16,
- - 16, 44, 76,104,136,164,196,224,224,196,164,136,104, 76, 44, 16,
- - 12, 40, 64, 92,116,144,168,196,196,168,144,116, 92, 64, 40, 12,
- - 12, 32, 56, 76,100,120,144,164,164,144,120,100, 76, 56, 32, 12,
- - 8, 28, 44, 64, 80,100,116,136,136,116,100, 80, 64, 44, 28, 8,
- - 8, 20, 36, 48, 64, 76, 92,104,104, 92, 76, 64, 48, 36, 20, 8,
- - 4, 16, 24, 36, 44, 56, 64, 76, 76, 64, 56, 44, 36, 24, 16, 4,
- - 4, 8, 16, 20, 28, 32, 40, 44, 44, 40, 32, 28, 20, 16, 8, 4,
- - 0, 4, 4, 8, 8, 12, 12, 16, 16, 12, 12, 8, 8, 4, 4, 0,
- -//error:0.000015
- -};
- -
- -//linear *64
- -static const uint8_t obmc8[64]={
- - 4, 12, 20, 28, 28, 20, 12, 4,
- - 12, 36, 60, 84, 84, 60, 36, 12,
- - 20, 60,100,140,140,100, 60, 20,
- - 28, 84,140,196,196,140, 84, 28,
- - 28, 84,140,196,196,140, 84, 28,
- - 20, 60,100,140,140,100, 60, 20,
- - 12, 36, 60, 84, 84, 60, 36, 12,
- - 4, 12, 20, 28, 28, 20, 12, 4,
- -//error:0.000000
- -};
- -
- -//linear *64
- -static const uint8_t obmc4[16]={
- - 16, 48, 48, 16,
- - 48,144,144, 48,
- - 48,144,144, 48,
- - 16, 48, 48, 16,
- -//error:0.000000
- -};
- -
- -const int8_t ff_quant3bA[256]={
- - 0, 0, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
- - 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
- - 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
- - 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
- - 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
- - 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
- - 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
- - 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
- - 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
- - 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
- - 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
- - 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
- - 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
- - 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
- - 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
- - 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
- -};
- -
- -const uint8_t * const ff_obmc_tab[4]= {
- - obmc32, obmc16, obmc8, obmc4
- -};
- -
- -/* runtime generated tables */
- -uint8_t ff_qexp[QROOT];
- -int ff_scale_mv_ref[MAX_REF_FRAMES][MAX_REF_FRAMES];
- -
- -
- -#endif /* AVCODEC_SNOW_H */
- diff --git a/libavcodec/snowdec.c b/libavcodec/snowdec.c
- index 042aecb..b224470 100644
- --- a/libavcodec/snowdec.c
- +++ b/libavcodec/snowdec.c
- @@ -29,90 +29,7 @@
- #include "rangecoder.h"
- #include "mathops.h"
- -#include "mpegvideo.h"
- -#include "h263.h"
- -
- -static av_always_inline void predict_slice_buffered(SnowContext *s, slice_buffer * sb, IDWTELEM * old_buffer, int plane_index, int add, int mb_y){
- - Plane *p= &s->plane[plane_index];
- - const int mb_w= s->b_width << s->block_max_depth;
- - const int mb_h= s->b_height << s->block_max_depth;
- - int x, y, mb_x;
- - int block_size = MB_SIZE >> s->block_max_depth;
- - int block_w = plane_index ? block_size>>s->chroma_h_shift : block_size;
- - int block_h = plane_index ? block_size>>s->chroma_v_shift : block_size;
- - const uint8_t *obmc = plane_index ? ff_obmc_tab[s->block_max_depth+s->chroma_h_shift] : ff_obmc_tab[s->block_max_depth];
- - int obmc_stride= plane_index ? (2*block_size)>>s->chroma_h_shift : 2*block_size;
- - int ref_stride= s->current_picture->linesize[plane_index];
- - uint8_t *dst8= s->current_picture->data[plane_index];
- - int w= p->width;
- - int h= p->height;
- -
- - if(s->keyframe || (s->avctx->debug&512)){
- - if(mb_y==mb_h)
- - return;
- -
- - if(add){
- - for(y=block_h*mb_y; y<FFMIN(h,block_h*(mb_y+1)); y++){
- -// DWTELEM * line = slice_buffer_get_line(sb, y);
- - IDWTELEM * line = sb->line[y];
- - for(x=0; x<w; x++){
- -// int v= buf[x + y*w] + (128<<FRAC_BITS) + (1<<(FRAC_BITS-1));
- - int v= line[x] + (128<<FRAC_BITS) + (1<<(FRAC_BITS-1));
- - v >>= FRAC_BITS;
- - if(v&(~255)) v= ~(v>>31);
- - dst8[x + y*ref_stride]= v;
- - }
- - }
- - }else{
- - for(y=block_h*mb_y; y<FFMIN(h,block_h*(mb_y+1)); y++){
- -// DWTELEM * line = slice_buffer_get_line(sb, y);
- - IDWTELEM * line = sb->line[y];
- - for(x=0; x<w; x++){
- - line[x] -= 128 << FRAC_BITS;
- -// buf[x + y*w]-= 128<<FRAC_BITS;
- - }
- - }
- - }
- -
- - return;
- - }
- -
- - for(mb_x=0; mb_x<=mb_w; mb_x++){
- - add_yblock(s, 1, sb, old_buffer, dst8, obmc,
- - block_w*mb_x - block_w/2,
- - block_h*mb_y - block_h/2,
- - block_w, block_h,
- - w, h,
- - w, ref_stride, obmc_stride,
- - mb_x - 1, mb_y - 1,
- - add, 0, plane_index);
- - }
- -
- - if(s->avmv && mb_y < mb_h && plane_index == 0)
- - for(mb_x=0; mb_x<mb_w; mb_x++){
- - AVMotionVector *avmv = s->avmv + s->avmv_index;
- - const int b_width = s->b_width << s->block_max_depth;
- - const int b_stride= b_width;
- - BlockNode *bn= &s->block[mb_x + mb_y*b_stride];
- -
- - if (bn->type)
- - continue;
- -
- - s->avmv_index++;
- -
- - avmv->w = block_w;
- - avmv->h = block_h;
- - avmv->dst_x = block_w*mb_x - block_w/2;
- - avmv->dst_y = block_h*mb_y - block_h/2;
- - avmv->motion_scale = 8;
- - avmv->motion_x = bn->mx * s->mv_scale;
- - avmv->motion_y = bn->my * s->mv_scale;
- - avmv->src_x = avmv->dst_x + avmv->motion_x / 8;
- - avmv->src_y = avmv->dst_y + avmv->motion_y / 8;
- - avmv->source= -1 - bn->ref;
- - avmv->flags = 0;
- - }
- -}
- +#include "obmc.h"
- static inline void decode_subband_slice_buffered(SnowContext *s, SubBand *b, slice_buffer * sb, int start_y, int h, int save_state[1]){
- const int w= b->width;
- @@ -122,7 +39,7 @@ static inline void decode_subband_slice_buffered(SnowContext *s, SubBand *b, sli
- int qadd= (s->qbias*qmul)>>QBIAS_SHIFT;
- int new_index = 0;
- - if(b->ibuf == s->spatial_idwt_buffer || s->qlog == LOSSLESS_QLOG){
- + if(b->ibuf == s->obmc.spatial_idwt_buffer || s->qlog == LOSSLESS_QLOG){
- qadd= 0;
- qmul= 1<<QEXPSHIFT;
- }
- @@ -156,23 +73,25 @@ static inline void decode_subband_slice_buffered(SnowContext *s, SubBand *b, sli
- }
- static int decode_q_branch(SnowContext *s, int level, int x, int y){
- - const int w= s->b_width << s->block_max_depth;
- - const int rem_depth= s->block_max_depth - level;
- + RangeCoder *const c = &s->c;
- + OBMCContext *oc = &s->obmc;
- + const int w= oc->b_width << oc->block_max_depth;
- + const int rem_depth= oc->block_max_depth - level;
- const int index= (x + y*w) << rem_depth;
- int trx= (x+1)<<rem_depth;
- - const BlockNode *left = x ? &s->block[index-1] : &null_block;
- - const BlockNode *top = y ? &s->block[index-w] : &null_block;
- - const BlockNode *tl = y && x ? &s->block[index-w-1] : left;
- - const BlockNode *tr = y && trx<w && ((x&1)==0 || level==0) ? &s->block[index-w+(1<<rem_depth)] : tl; //FIXME use lt
- + const BlockNode *left = x ? &oc->block[index-1] : &null_block;
- + const BlockNode *top = y ? &oc->block[index-w] : &null_block;
- + const BlockNode *tl = y && x ? &oc->block[index-w-1] : left;
- + const BlockNode *tr = y && trx<w && ((x&1)==0 || level==0) ? &oc->block[index-w+(1<<rem_depth)] : tl; //FIXME use lt
- int s_context= 2*left->level + 2*top->level + tl->level + tr->level;
- int res;
- - if(s->keyframe){
- - set_blocks(s, level, x, y, null_block.color[0], null_block.color[1], null_block.color[2], null_block.mx, null_block.my, null_block.ref, BLOCK_INTRA);
- + if(oc->keyframe){
- + set_blocks(oc, 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 0;
- }
- - if(level==s->block_max_depth || get_rac(&s->c, &s->block_state[4 + s_context])){
- + if(level==oc->block_max_depth || get_rac(c, &s->block_state[4 + s_context])){
- int type, mx, my;
- int l = left->color[0];
- int cb= left->color[1];
- @@ -182,27 +101,27 @@ static int decode_q_branch(SnowContext *s, int level, int x, int y){
- int mx_context= av_log2(2*FFABS(left->mx - top->mx)) + 0*av_log2(2*FFABS(tr->mx - top->mx));
- int my_context= av_log2(2*FFABS(left->my - top->my)) + 0*av_log2(2*FFABS(tr->my - top->my));
- - type= get_rac(&s->c, &s->block_state[1 + left->type + top->type]) ? BLOCK_INTRA : 0;
- + type= get_rac(c, &s->block_state[1 + left->type + top->type]) ? BLOCK_INTRA : 0;
- if(type){
- - pred_mv(s, &mx, &my, 0, left, top, tr);
- - l += get_symbol(&s->c, &s->block_state[32], 1);
- - if (s->nb_planes > 2) {
- - cb+= get_symbol(&s->c, &s->block_state[64], 1);
- - cr+= get_symbol(&s->c, &s->block_state[96], 1);
- + pred_mv(oc, &mx, &my, 0, left, top, tr);
- + l += get_symbol(c, &s->block_state[32], 1);
- + if (s->obmc.nb_planes > 2) {
- + cb += get_symbol(c, &s->block_state[64], 1);
- + cr += get_symbol(c, &s->block_state[96], 1);
- }
- }else{
- - if(s->ref_frames > 1)
- - ref= get_symbol(&s->c, &s->block_state[128 + 1024 + 32*ref_context], 0);
- - if (ref >= s->ref_frames) {
- + if(oc->ref_frames > 1)
- + ref = get_symbol(c, &s->block_state[128 + 1024 + 32*ref_context], 0);
- + if (ref >= oc->ref_frames) {
- av_log(s->avctx, AV_LOG_ERROR, "Invalid ref\n");
- return AVERROR_INVALIDDATA;
- }
- - pred_mv(s, &mx, &my, ref, left, top, tr);
- - mx+= get_symbol(&s->c, &s->block_state[128 + 32*(mx_context + 16*!!ref)], 1);
- - my+= get_symbol(&s->c, &s->block_state[128 + 32*(my_context + 16*!!ref)], 1);
- + pred_mv(oc, &mx, &my, ref, left, top, tr);
- + mx += get_symbol(c, &s->block_state[128 + 32*(mx_context + 16*!!ref)], 1);
- + my += get_symbol(c, &s->block_state[128 + 32*(my_context + 16*!!ref)], 1);
- }
- - set_blocks(s, level, x, y, l, cb, cr, mx, my, ref, type);
- + set_blocks(oc, level, x, y, l, cb, cr, mx, my, ref, type);
- }else{
- if ((res = decode_q_branch(s, level+1, 2*x+0, 2*y+0)) < 0 ||
- (res = decode_q_branch(s, level+1, 2*x+1, 2*y+0)) < 0 ||
- @@ -291,19 +210,20 @@ static void decode_qlogs(SnowContext *s){
- dst= tmp;
- static int decode_header(SnowContext *s){
- - int plane_index, tmp;
- + int plane_index, tmp, ret;
- uint8_t kstate[32];
- memset(kstate, MID_STATE, sizeof(kstate));
- s->keyframe= get_rac(&s->c, kstate);
- + s->obmc.keyframe = s->keyframe;
- if(s->keyframe || s->always_reset){
- ff_snow_reset_contexts(s);
- s->spatial_decomposition_type=
- s->qlog=
- s->qbias=
- - s->mv_scale=
- - s->block_max_depth= 0;
- + s->obmc.mv_scale=
- + s->obmc.block_max_depth= 0;
- }
- if(s->keyframe){
- GET_S(s->version, tmp <= 0U)
- @@ -342,8 +262,8 @@ static int decode_header(SnowContext *s){
- s->spatial_scalability= get_rac(&s->c, s->header_state);
- // s->rate_scalability= get_rac(&s->c, s->header_state);
- - GET_S(s->max_ref_frames, tmp < (unsigned)MAX_REF_FRAMES)
- - s->max_ref_frames++;
- + GET_S(s->obmc.max_ref_frames, tmp < (unsigned)MAX_REF_FRAMES)
- + s->obmc.max_ref_frames++;
- decode_qlogs(s);
- }
- @@ -352,7 +272,7 @@ static int decode_header(SnowContext *s){
- if(get_rac(&s->c, s->header_state)){
- for(plane_index=0; plane_index<FFMIN(s->nb_planes, 2); plane_index++){
- int htaps, i, sum=0;
- - Plane *p= &s->plane[plane_index];
- + PlaneObmc *p= &s->obmc.plane[plane_index];
- p->diag_mc= get_rac(&s->c, s->header_state);
- htaps= get_symbol(&s->c, s->header_state, 0)*2 + 2;
- if((unsigned)htaps > HTAPS_MAX || htaps==0)
- @@ -364,9 +284,9 @@ static int decode_header(SnowContext *s){
- }
- p->hcoeff[0]= 32-sum;
- }
- - s->plane[2].diag_mc= s->plane[1].diag_mc;
- - s->plane[2].htaps = s->plane[1].htaps;
- - memcpy(s->plane[2].hcoeff, s->plane[1].hcoeff, sizeof(s->plane[1].hcoeff));
- + s->obmc.plane[2].diag_mc= s->obmc.plane[1].diag_mc;
- + s->obmc.plane[2].htaps = s->obmc.plane[1].htaps;
- + memcpy(s->obmc.plane[2].hcoeff, s->obmc.plane[1].hcoeff, sizeof(s->obmc.plane[1].hcoeff));
- }
- if(get_rac(&s->c, s->header_state)){
- GET_S(s->spatial_decomposition_count, 0 < tmp && tmp <= MAX_DECOMPOSITIONS)
- @@ -386,16 +306,19 @@ static int decode_header(SnowContext *s){
- }
- - s->qlog += get_symbol(&s->c, s->header_state, 1);
- - s->mv_scale += get_symbol(&s->c, s->header_state, 1);
- - s->qbias += get_symbol(&s->c, s->header_state, 1);
- - s->block_max_depth+= get_symbol(&s->c, s->header_state, 1);
- - if(s->block_max_depth > 1 || s->block_max_depth < 0){
- - av_log(s->avctx, AV_LOG_ERROR, "block_max_depth= %d is too large\n", s->block_max_depth);
- - s->block_max_depth= 0;
- + s->qlog += get_symbol(&s->c, s->header_state, 1);
- + s->obmc.mv_scale += get_symbol(&s->c, s->header_state, 1);
- + s->qbias += get_symbol(&s->c, s->header_state, 1);
- + s->obmc.block_max_depth += get_symbol(&s->c, s->header_state, 1);
- + if(s->obmc.block_max_depth > 1 || s->obmc.block_max_depth < 0){
- + av_log(s->avctx, AV_LOG_ERROR, "block_max_depth= %d is too large\n", s->obmc.block_max_depth);
- + s->obmc.block_max_depth= 0;
- return AVERROR_INVALIDDATA;
- }
- + if ((ret = ff_obmc_decode_init(&s->obmc)) < 0)
- + return ret;
- +
- return 0;
- }
- @@ -412,8 +335,8 @@ static av_cold int decode_init(AVCodecContext *avctx)
- static int decode_blocks(SnowContext *s){
- int x, y;
- - int w= s->b_width;
- - int h= s->b_height;
- + int w= s->obmc.b_width;
- + int h= s->obmc.b_height;
- int res;
- for(y=0; y<h; y++){
- @@ -440,7 +363,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
- ff_init_range_decoder(c, buf, buf_size);
- ff_build_rac_states(c, 0.05*(1LL<<32), 256-8);
- - s->current_picture->pict_type= AV_PICTURE_TYPE_I; //FIXME I vs. P
- + s->obmc.current_picture->pict_type= AV_PICTURE_TYPE_I; //FIXME I vs. P
- if ((res = decode_header(s)) < 0)
- return res;
- if ((res=ff_snow_common_init_after_header(avctx)) < 0)
- @@ -448,42 +371,25 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
- // realloc slice buffer for the case that spatial_decomposition_count changed
- ff_slice_buffer_destroy(&s->sb);
- - if ((res = ff_slice_buffer_init(&s->sb, s->plane[0].height,
- - (MB_SIZE >> s->block_max_depth) +
- + if ((res = ff_slice_buffer_init(&s->sb, s->obmc.plane[0].height,
- + (MB_SIZE >> s->obmc.block_max_depth) +
- s->spatial_decomposition_count * 11 + 1,
- - s->plane[0].width,
- - s->spatial_idwt_buffer)) < 0)
- - return res;
- -
- - for(plane_index=0; plane_index < s->nb_planes; plane_index++){
- - Plane *p= &s->plane[plane_index];
- - p->fast_mc= p->diag_mc && p->htaps==6 && p->hcoeff[0]==40
- - && p->hcoeff[1]==-10
- - && p->hcoeff[2]==2;
- - }
- -
- - ff_snow_alloc_blocks(s);
- -
- - if((res = ff_snow_frame_start(s)) < 0)
- + s->obmc.plane[0].width,
- + s->obmc.spatial_idwt_buffer)) < 0)
- return res;
- - s->current_picture->pict_type = s->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
- -
- //keyframe flag duplication mess FIXME
- if(avctx->debug&FF_DEBUG_PICT_INFO)
- av_log(avctx, AV_LOG_ERROR,
- "keyframe:%d qlog:%d qbias: %d mvscale: %d "
- "decomposition_type:%d decomposition_count:%d\n",
- - s->keyframe, s->qlog, s->qbias, s->mv_scale,
- + s->keyframe, s->qlog, s->qbias, s->obmc.mv_scale,
- s->spatial_decomposition_type,
- s->spatial_decomposition_count
- );
- - av_assert0(!s->avmv);
- - if (s->avctx->flags2 & AV_CODEC_FLAG2_EXPORT_MVS) {
- - s->avmv = av_malloc_array(s->b_width * s->b_height, sizeof(AVMotionVector) << (s->block_max_depth*2));
- - }
- - s->avmv_index = 0;
- + if ((res = ff_obmc_predecode_frame(&s->obmc)) < 0)
- + return res;
- if ((res = decode_blocks(s)) < 0)
- return res;
- @@ -497,12 +403,12 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
- if(s->avctx->debug&2048){
- memset(s->spatial_dwt_buffer, 0, sizeof(DWTELEM)*w*h);
- - predict_plane(s, s->spatial_idwt_buffer, plane_index, 1);
- + predict_plane(&s->obmc, s->obmc.spatial_idwt_buffer, plane_index, 1);
- for(y=0; y<h; y++){
- for(x=0; x<w; x++){
- - int v= s->current_picture->data[plane_index][y*s->current_picture->linesize[plane_index] + x];
- - s->mconly_picture->data[plane_index][y*s->mconly_picture->linesize[plane_index] + x]= v;
- + int v= s->obmc.current_picture->data[plane_index][y*s->obmc.current_picture->linesize[plane_index] + x];
- + s->obmc.mconly_picture->data[plane_index][y*s->obmc.mconly_picture->linesize[plane_index] + x]= v;
- }
- }
- }
- @@ -517,8 +423,8 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
- }
- {
- - const int mb_h= s->b_height << s->block_max_depth;
- - const int block_size = MB_SIZE >> s->block_max_depth;
- + const int mb_h= s->obmc.b_height << s->obmc.block_max_depth;
- + const int block_size = MB_SIZE >> s->obmc.block_max_depth;
- const int block_h = plane_index ? block_size>>s->chroma_v_shift : block_size;
- int mb_y;
- DWTCompose cs[MAX_DECOMPOSITIONS];
- @@ -570,7 +476,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
- }
- for(; yd<slice_h; yd+=4){
- - ff_spatial_idwt_buffered_slice(&s->dwt, cs, &s->sb, s->temp_idwt_buffer, w, h, 1, s->spatial_decomposition_type, s->spatial_decomposition_count, yd);
- + ff_spatial_idwt_buffered_slice(&s->obmc.dwt, cs, &s->sb, s->temp_idwt_buffer, w, h, 1, s->spatial_decomposition_type, s->spatial_decomposition_count, yd);
- }
- if(s->qlog == LOSSLESS_QLOG){
- @@ -582,7 +488,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
- }
- }
- - predict_slice_buffered(s, &s->sb, s->spatial_idwt_buffer, plane_index, 1, mb_y);
- + predict_slice_buffered(&s->obmc, &s->sb, s->obmc.spatial_idwt_buffer, plane_index, 1, mb_y);
- y = FFMIN(p->height, slice_starty);
- end_y = FFMIN(p->height, slice_h);
- @@ -597,22 +503,22 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
- emms_c();
- - ff_snow_release_buffer(avctx);
- + ff_obmc_release_buffer(&s->obmc);
- if(!(s->avctx->debug&2048))
- - res = av_frame_ref(picture, s->current_picture);
- + res = av_frame_ref(picture, s->obmc.current_picture);
- else
- - res = av_frame_ref(picture, s->mconly_picture);
- - if (res >= 0 && s->avmv_index) {
- + res = av_frame_ref(picture, s->obmc.mconly_picture);
- + if (res >= 0 && s->obmc.avmv_index) {
- AVFrameSideData *sd;
- - sd = av_frame_new_side_data(picture, AV_FRAME_DATA_MOTION_VECTORS, s->avmv_index * sizeof(AVMotionVector));
- + sd = av_frame_new_side_data(picture, AV_FRAME_DATA_MOTION_VECTORS, s->obmc.avmv_index * sizeof(AVMotionVector));
- if (!sd)
- return AVERROR(ENOMEM);
- - memcpy(sd->data, s->avmv, s->avmv_index * sizeof(AVMotionVector));
- + memcpy(sd->data, s->obmc.avmv, s->obmc.avmv_index * sizeof(AVMotionVector));
- }
- - av_freep(&s->avmv);
- + av_freep(&s->obmc.avmv);
- if (res < 0)
- return res;
- diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c
- index 00aef57..40bc84b 100644
- --- a/libavcodec/snowenc.c
- +++ b/libavcodec/snowenc.c
- @@ -30,16 +30,164 @@
- #include "rangecoder.h"
- #include "mathops.h"
- -#include "mpegvideo.h"
- -#include "h263.h"
- +#include "obme.h"
- #define FF_ME_ITER 50
- +typedef struct RangeEncoderContext {
- + RangeCoder c;
- + uint8_t buffer[1024];
- + uint8_t state[128 + 32*128];
- + uint8_t *pbbak;
- + uint8_t *pbbak_start;
- + int base_bits;
- +} RangeEncoderContext;
- +
- +static void put_encoder_rac(ObmcCoderContext *c, int ctx, int v)
- +{
- + SnowContext *s = (SnowContext *)c->avctx->priv_data;
- + RangeCoder *rc = &s->c;
- + uint8_t *state = s->block_state;
- + if (c->priv_data) {
- + RangeEncoderContext *coder = (RangeEncoderContext *)c->priv_data;
- + rc = &coder->c; state = coder->state;
- + }
- + put_rac(rc, &state[ctx], v);
- +}
- +
- +static void put_encoder_symbol(ObmcCoderContext *c, int ctx, int v, int sign)
- +{
- + SnowContext *s = (SnowContext *)c->avctx->priv_data;
- + RangeCoder *rc = &s->c;
- + uint8_t *state = s->block_state;
- + if (c->priv_data) {
- + RangeEncoderContext *coder = (RangeEncoderContext *)c->priv_data;
- + rc = &coder->c; state = coder->state;
- + }
- + put_symbol(rc, &state[ctx], v, sign);
- +}
- +
- +static void ff_snow_init_encode_callbacks(ObmcCoderContext *, AVCodecContext *);
- +
- +static void init_frame_encoder(AVCodecContext *avctx, ObmcCoderContext *c)
- +{
- + SnowContext *f = (SnowContext *)avctx->priv_data;
- + RangeEncoderContext *coder = av_mallocz(sizeof(RangeEncoderContext));
- + c->priv_data = coder;
- +
- + coder->pbbak = f->c.bytestream;
- + coder->pbbak_start = f->c.bytestream_start;
- + coder->base_bits = get_rac_count(&f->c) - 8*(f->c.bytestream - f->c.bytestream_start);
- + coder->c = f->c;
- + coder->c.bytestream_start = coder->c.bytestream= coder->buffer; //FIXME end/start? and at the other stoo
- + memcpy(coder->state, f->block_state, sizeof(f->block_state));
- +
- + ff_snow_init_encode_callbacks(c, avctx);
- +}
- +
- +static void free_coder (ObmcCoderContext *c)
- +{
- + av_freep(&c->priv_data);
- +}
- +
- +static void copy_coder (struct ObmcCoderContext *c)
- +{
- + SnowContext *f = (SnowContext *)c->avctx->priv_data;
- + RangeEncoderContext *coder = (RangeEncoderContext *)c->priv_data;
- +
- + int len = coder->c.bytestream - coder->c.bytestream_start;
- +
- + memcpy(coder->pbbak, coder->buffer, len);
- + f->c = coder->c;
- + f->c.bytestream_start= coder->pbbak_start;
- + f->c.bytestream= coder->pbbak + len;
- + memcpy(f->block_state, coder->state, sizeof(f->block_state));
- +}
- +
- +static void reset_coder (struct ObmcCoderContext *c)
- +{
- + SnowContext *f = (SnowContext *)c->avctx->priv_data;
- + RangeEncoderContext *coder = (RangeEncoderContext *)c->priv_data;
- +
- + f->c = coder->c;
- + f->c.bytestream_start= coder->pbbak_start;
- + f->c.bytestream= coder->pbbak;
- + memcpy(f->block_state, coder->state, sizeof(f->block_state));
- +}
- +
- +static void put_level_break(ObmcCoderContext *c, int ctx, int v)
- +{
- + put_encoder_rac(c, ctx, v);
- +}
- +
- +static void put_block_type (struct ObmcCoderContext *c, int ctx, int type)
- +{
- + put_encoder_rac(c, ctx, type);
- +}
- +
- +static void put_best_ref (struct ObmcCoderContext *c, int ctx, int best_ref)
- +{
- + put_encoder_symbol(c, ctx, best_ref, 0);
- +}
- +
- +static void put_block_mv (struct ObmcCoderContext *c, int ctx_mx, int ctx_my, int mx, int my)
- +{
- + put_encoder_symbol(c, ctx_mx, mx, 1);
- + put_encoder_symbol(c, ctx_my, my, 1);
- +}
- +
- +static void put_block_color (struct ObmcCoderContext *c, int ctx_l, int ctx_cb, int ctx_cr, int l, int cb, int cr)
- +{
- + SnowContext *s = (SnowContext *)c->avctx->priv_data;
- + put_encoder_symbol(c, ctx_l, l, 1);
- + if (s->obmc.nb_planes > 2) {
- + put_encoder_symbol(c, ctx_cb, cb, 1);
- + put_encoder_symbol(c, ctx_cr, cr, 1);
- + }
- +}
- +
- +static int get_coder_bits(ObmcCoderContext *c)
- +{
- + RangeEncoderContext *coder = (RangeEncoderContext *)c->priv_data;
- + return get_rac_count(&coder->c) - coder->base_bits;
- +}
- +
- +static int get_coder_available_bytes(ObmcCoderContext *c)
- +{
- + SnowContext *s = (SnowContext *)c->avctx->priv_data;
- + RangeCoder *rc = &s->c;
- + if (c->priv_data) {
- + RangeEncoderContext *coder = (RangeEncoderContext *)c->priv_data;
- + rc = &coder->c;
- + }
- + return rc->bytestream_end - rc->bytestream;
- +}
- +
- +static void ff_snow_init_encode_callbacks(ObmcCoderContext *c, AVCodecContext *avctx)
- +{
- + SnowContext *s = (SnowContext *)c->avctx->priv_data;
- + av_assert0(sizeof(s->block_state) >= 256);
- +
- + c->avctx = avctx;
- + c->put_level_break = put_level_break;
- + c->put_block_type = put_block_type;
- + c->put_block_color = put_block_color;
- + c->put_best_ref = put_best_ref;
- + c->put_block_mv = put_block_mv;
- +
- + c->init_frame_coder = init_frame_encoder;
- + c->reset_coder = reset_coder;
- + c->copy_coder = copy_coder;
- + c->free = free_coder;
- +
- + c->get_bits = get_coder_bits;
- + c->available_bytes = get_coder_available_bytes;
- +}
- +
- static av_cold int encode_init(AVCodecContext *avctx)
- {
- SnowContext *s = avctx->priv_data;
- - int plane_index, ret;
- - int i;
- + int ret;
- #if FF_API_PRIVATE_OPT
- FF_DISABLE_DEPRECATION_WARNINGS
- @@ -54,51 +202,15 @@ FF_ENABLE_DEPRECATION_WARNINGS
- av_log(avctx, AV_LOG_ERROR, "The 9/7 wavelet is incompatible with lossless mode.\n");
- return -1;
- }
- -#if FF_API_MOTION_EST
- -FF_DISABLE_DEPRECATION_WARNINGS
- - if (avctx->me_method == ME_ITER)
- - s->motion_est = FF_ME_ITER;
- -FF_ENABLE_DEPRECATION_WARNINGS
- -#endif
- s->spatial_decomposition_type= s->pred; //FIXME add decorrelator type r transform_type
- - s->mv_scale = (avctx->flags & AV_CODEC_FLAG_QPEL) ? 2 : 4;
- - s->block_max_depth= (avctx->flags & AV_CODEC_FLAG_4MV ) ? 1 : 0;
- -
- - for(plane_index=0; plane_index<3; plane_index++){
- - s->plane[plane_index].diag_mc= 1;
- - s->plane[plane_index].htaps= 6;
- - s->plane[plane_index].hcoeff[0]= 40;
- - s->plane[plane_index].hcoeff[1]= -10;
- - s->plane[plane_index].hcoeff[2]= 2;
- - s->plane[plane_index].fast_mc= 1;
- - }
- -
- if ((ret = ff_snow_common_init(avctx)) < 0) {
- return ret;
- }
- - ff_mpegvideoencdsp_init(&s->mpvencdsp, avctx);
- -
- - ff_snow_alloc_blocks(s);
- s->version=0;
- - s->m.avctx = avctx;
- - s->m.bit_rate= avctx->bit_rate;
- -
- - s->m.me.temp =
- - s->m.me.scratchpad= av_mallocz_array((avctx->width+64), 2*16*2*sizeof(uint8_t));
- - s->m.me.map = av_mallocz(ME_MAP_SIZE*sizeof(uint32_t));
- - s->m.me.score_map = av_mallocz(ME_MAP_SIZE*sizeof(uint32_t));
- - s->m.sc.obmc_scratchpad= av_mallocz(MB_SIZE*MB_SIZE*12*sizeof(uint32_t));
- - if (!s->m.me.scratchpad || !s->m.me.map || !s->m.me.score_map || !s->m.sc.obmc_scratchpad)
- - return AVERROR(ENOMEM);
- -
- - ff_h263_encode_init(&s->m); //mv_penalty
- -
- - s->max_ref_frames = av_clip(avctx->refs, 1, MAX_REF_FRAMES);
- -
- if(avctx->flags&AV_CODEC_FLAG_PASS1){
- if(!avctx->stats_out)
- avctx->stats_out = av_mallocz(256);
- @@ -106,11 +218,6 @@ FF_ENABLE_DEPRECATION_WARNINGS
- if (!avctx->stats_out)
- return AVERROR(ENOMEM);
- }
- - if((avctx->flags&AV_CODEC_FLAG_PASS2) || !(avctx->flags&CODEC_FLAG_QSCALE)){
- - if(ff_rate_control_init(&s->m) < 0)
- - return -1;
- - }
- - s->pass1_rc= !(avctx->flags & (AV_CODEC_FLAG_QSCALE|CODEC_FLAG_PASS2));
- switch(avctx->pix_fmt){
- case AV_PIX_FMT_YUV444P:
- @@ -134,644 +241,18 @@ FF_ENABLE_DEPRECATION_WARNINGS
- }
- avcodec_get_chroma_sub_sample(avctx->pix_fmt, &s->chroma_h_shift, &s->chroma_v_shift);
- - ff_set_cmp(&s->mecc, s->mecc.me_cmp, s->avctx->me_cmp);
- - ff_set_cmp(&s->mecc, s->mecc.me_sub_cmp, s->avctx->me_sub_cmp);
- + ff_obmc_encode_init(&s->obmc, avctx);
- + ff_snow_init_encode_callbacks(&s->obmc.obmc_coder, avctx);
- - s->input_picture = av_frame_alloc();
- - if (!s->input_picture)
- - return AVERROR(ENOMEM);
- -
- - if ((ret = ff_snow_get_buffer(s, s->input_picture)) < 0)
- - return ret;
- -
- - if(s->motion_est == FF_ME_ITER){
- - 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_array(size, sizeof(int16_t[2]));
- - s->ref_scores[i]= av_mallocz_array(size, sizeof(uint32_t));
- - if (!s->ref_mvs[i] || !s->ref_scores[i])
- - return AVERROR(ENOMEM);
- - }
- + if((avctx->flags&AV_CODEC_FLAG_PASS2) || !(avctx->flags&CODEC_FLAG_QSCALE)){
- + if(ff_rate_control_init(&s->obmc.m) < 0)
- + return -1;
- }
- + s->pass1_rc= !(avctx->flags & (AV_CODEC_FLAG_QSCALE|CODEC_FLAG_PASS2));
- return 0;
- }
- -//near copy & paste from dsputil, FIXME
- -static int pix_sum(uint8_t * pix, int line_size, int w, int h)
- -{
- - int s, i, j;
- -
- - s = 0;
- - for (i = 0; i < h; i++) {
- - for (j = 0; j < w; j++) {
- - s += pix[0];
- - pix ++;
- - }
- - pix += line_size - w;
- - }
- - return s;
- -}
- -
- -//near copy & paste from dsputil, FIXME
- -static int pix_norm1(uint8_t * pix, int line_size, int w)
- -{
- - int s, i, j;
- - uint32_t *sq = ff_square_tab + 256;
- -
- - s = 0;
- - for (i = 0; i < w; i++) {
- - for (j = 0; j < w; j ++) {
- - s += sq[pix[0]];
- - pix ++;
- - }
- - pix += line_size - w;
- - }
- - return s;
- -}
- -
- -static inline int get_penalty_factor(int lambda, int lambda2, int type){
- - switch(type&0xFF){
- - default:
- - case FF_CMP_SAD:
- - return lambda>>FF_LAMBDA_SHIFT;
- - case FF_CMP_DCT:
- - return (3*lambda)>>(FF_LAMBDA_SHIFT+1);
- - case FF_CMP_W53:
- - return (4*lambda)>>(FF_LAMBDA_SHIFT);
- - case FF_CMP_W97:
- - return (2*lambda)>>(FF_LAMBDA_SHIFT);
- - case FF_CMP_SATD:
- - case FF_CMP_DCT264:
- - return (2*lambda)>>FF_LAMBDA_SHIFT;
- - case FF_CMP_RD:
- - case FF_CMP_PSNR:
- - case FF_CMP_SSE:
- - case FF_CMP_NSSE:
- - return lambda2>>FF_LAMBDA_SHIFT;
- - case FF_CMP_BIT:
- - return 1;
- - }
- -}
- -
- -//FIXME copy&paste
- -#define P_LEFT P[1]
- -#define P_TOP P[2]
- -#define P_TOPRIGHT P[3]
- -#define P_MEDIAN P[4]
- -#define P_MV1 P[9]
- -#define FLAG_QPEL 1 //must be 1
- -
- -static int encode_q_branch(SnowContext *s, int level, int x, int y){
- - uint8_t p_buffer[1024];
- - uint8_t i_buffer[1024];
- - uint8_t p_state[sizeof(s->block_state)];
- - uint8_t i_state[sizeof(s->block_state)];
- - RangeCoder pc, ic;
- - uint8_t *pbbak= s->c.bytestream;
- - uint8_t *pbbak_start= s->c.bytestream_start;
- - int score, score2, iscore, i_len, p_len, block_s, sum, base_bits;
- - const int w= s->b_width << s->block_max_depth;
- - const int h= s->b_height << s->block_max_depth;
- - const int rem_depth= s->block_max_depth - level;
- - const int index= (x + y*w) << rem_depth;
- - const int block_w= 1<<(LOG2_MB_SIZE - level);
- - int trx= (x+1)<<rem_depth;
- - int try= (y+1)<<rem_depth;
- - const BlockNode *left = x ? &s->block[index-1] : &null_block;
- - const BlockNode *top = y ? &s->block[index-w] : &null_block;
- - const BlockNode *right = trx<w ? &s->block[index+1] : &null_block;
- - const BlockNode *bottom= try<h ? &s->block[index+w] : &null_block;
- - const BlockNode *tl = y && x ? &s->block[index-w-1] : left;
- - const BlockNode *tr = y && trx<w && ((x&1)==0 || level==0) ? &s->block[index-w+(1<<rem_depth)] : tl; //FIXME use lt
- - int pl = left->color[0];
- - int pcb= left->color[1];
- - int pcr= left->color[2];
- - int pmx, pmy;
- - int mx=0, my=0;
- - int l,cr,cb;
- - const int stride= s->current_picture->linesize[0];
- - const int uvstride= s->current_picture->linesize[1];
- - uint8_t *current_data[3]= { s->input_picture->data[0] + (x + y* stride)*block_w,
- - s->input_picture->data[1] + ((x*block_w)>>s->chroma_h_shift) + ((y*uvstride*block_w)>>s->chroma_v_shift),
- - s->input_picture->data[2] + ((x*block_w)>>s->chroma_h_shift) + ((y*uvstride*block_w)>>s->chroma_v_shift)};
- - int P[10][2];
- - int16_t last_mv[3][2];
- - int qpel= !!(s->avctx->flags & AV_CODEC_FLAG_QPEL); //unused
- - const int shift= 1+qpel;
- - MotionEstContext *c= &s->m.me;
- - int ref_context= av_log2(2*left->ref) + av_log2(2*top->ref);
- - int mx_context= av_log2(2*FFABS(left->mx - top->mx));
- - int my_context= av_log2(2*FFABS(left->my - top->my));
- - int s_context= 2*left->level + 2*top->level + tl->level + tr->level;
- - int ref, best_ref, ref_score, ref_mx, ref_my;
- -
- - av_assert0(sizeof(s->block_state) >= 256);
- - if(s->keyframe){
- - set_blocks(s, level, x, y, pl, pcb, pcr, 0, 0, 0, BLOCK_INTRA);
- - return 0;
- - }
- -
- -// clip predictors / edge ?
- -
- - P_LEFT[0]= left->mx;
- - P_LEFT[1]= left->my;
- - P_TOP [0]= top->mx;
- - P_TOP [1]= top->my;
- - P_TOPRIGHT[0]= tr->mx;
- - P_TOPRIGHT[1]= tr->my;
- -
- - last_mv[0][0]= s->block[index].mx;
- - last_mv[0][1]= s->block[index].my;
- - last_mv[1][0]= right->mx;
- - last_mv[1][1]= right->my;
- - last_mv[2][0]= bottom->mx;
- - last_mv[2][1]= bottom->my;
- -
- - s->m.mb_stride=2;
- - s->m.mb_x=
- - s->m.mb_y= 0;
- - c->skip= 0;
- -
- - av_assert1(c-> stride == stride);
- - av_assert1(c->uvstride == uvstride);
- -
- - c->penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_cmp);
- - c->sub_penalty_factor= get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_sub_cmp);
- - c->mb_penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->mb_cmp);
- - c->current_mv_penalty= c->mv_penalty[s->m.f_code=1] + MAX_DMV;
- -
- - c->xmin = - x*block_w - 16+3;
- - c->ymin = - y*block_w - 16+3;
- - c->xmax = - (x+1)*block_w + (w<<(LOG2_MB_SIZE - s->block_max_depth)) + 16-3;
- - c->ymax = - (y+1)*block_w + (h<<(LOG2_MB_SIZE - s->block_max_depth)) + 16-3;
- -
- - if(P_LEFT[0] > (c->xmax<<shift)) P_LEFT[0] = (c->xmax<<shift);
- - if(P_LEFT[1] > (c->ymax<<shift)) P_LEFT[1] = (c->ymax<<shift);
- - if(P_TOP[0] > (c->xmax<<shift)) P_TOP[0] = (c->xmax<<shift);
- - if(P_TOP[1] > (c->ymax<<shift)) P_TOP[1] = (c->ymax<<shift);
- - if(P_TOPRIGHT[0] < (c->xmin<<shift)) P_TOPRIGHT[0]= (c->xmin<<shift);
- - if(P_TOPRIGHT[0] > (c->xmax<<shift)) P_TOPRIGHT[0]= (c->xmax<<shift); //due to pmx no clip
- - if(P_TOPRIGHT[1] > (c->ymax<<shift)) P_TOPRIGHT[1]= (c->ymax<<shift);
- -
- - P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
- - P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
- -
- - if (!y) {
- - c->pred_x= P_LEFT[0];
- - c->pred_y= P_LEFT[1];
- - } else {
- - c->pred_x = P_MEDIAN[0];
- - c->pred_y = P_MEDIAN[1];
- - }
- -
- - score= INT_MAX;
- - best_ref= 0;
- - for(ref=0; ref<s->ref_frames; ref++){
- - init_ref(c, current_data, s->last_picture[ref]->data, NULL, block_w*x, block_w*y, 0);
- -
- - ref_score= ff_epzs_motion_search(&s->m, &ref_mx, &ref_my, P, 0, /*ref_index*/ 0, last_mv,
- - (1<<16)>>shift, level-LOG2_MB_SIZE+4, block_w);
- -
- - av_assert2(ref_mx >= c->xmin);
- - av_assert2(ref_mx <= c->xmax);
- - av_assert2(ref_my >= c->ymin);
- - av_assert2(ref_my <= c->ymax);
- -
- - ref_score= c->sub_motion_search(&s->m, &ref_mx, &ref_my, ref_score, 0, 0, level-LOG2_MB_SIZE+4, block_w);
- - ref_score= ff_get_mb_score(&s->m, ref_mx, ref_my, 0, 0, level-LOG2_MB_SIZE+4, block_w, 0);
- - ref_score+= 2*av_log2(2*ref)*c->penalty_factor;
- - if(s->ref_mvs[ref]){
- - s->ref_mvs[ref][index][0]= ref_mx;
- - s->ref_mvs[ref][index][1]= ref_my;
- - s->ref_scores[ref][index]= ref_score;
- - }
- - if(score > ref_score){
- - score= ref_score;
- - best_ref= ref;
- - mx= ref_mx;
- - my= ref_my;
- - }
- - }
- - //FIXME if mb_cmp != SSE then intra cannot be compared currently and mb_penalty vs. lambda2
- -
- - // subpel search
- - base_bits= get_rac_count(&s->c) - 8*(s->c.bytestream - s->c.bytestream_start);
- - pc= s->c;
- - pc.bytestream_start=
- - pc.bytestream= p_buffer; //FIXME end/start? and at the other stoo
- - memcpy(p_state, s->block_state, sizeof(s->block_state));
- -
- - if(level!=s->block_max_depth)
- - put_rac(&pc, &p_state[4 + s_context], 1);
- - put_rac(&pc, &p_state[1 + left->type + top->type], 0);
- - if(s->ref_frames > 1)
- - put_symbol(&pc, &p_state[128 + 1024 + 32*ref_context], best_ref, 0);
- - pred_mv(s, &pmx, &pmy, best_ref, left, top, tr);
- - put_symbol(&pc, &p_state[128 + 32*(mx_context + 16*!!best_ref)], mx - pmx, 1);
- - put_symbol(&pc, &p_state[128 + 32*(my_context + 16*!!best_ref)], my - pmy, 1);
- - p_len= pc.bytestream - pc.bytestream_start;
- - score += (s->lambda2*(get_rac_count(&pc)-base_bits))>>FF_LAMBDA_SHIFT;
- -
- - block_s= block_w*block_w;
- - sum = pix_sum(current_data[0], stride, block_w, block_w);
- - l= (sum + block_s/2)/block_s;
- - iscore = pix_norm1(current_data[0], stride, block_w) - 2*l*sum + l*l*block_s;
- -
- - if (s->nb_planes > 2) {
- - block_s= block_w*block_w>>(s->chroma_h_shift + s->chroma_v_shift);
- - sum = pix_sum(current_data[1], uvstride, block_w>>s->chroma_h_shift, block_w>>s->chroma_v_shift);
- - cb= (sum + block_s/2)/block_s;
- - // iscore += pix_norm1(¤t_mb[1][0], uvstride, block_w>>1) - 2*cb*sum + cb*cb*block_s;
- - sum = pix_sum(current_data[2], uvstride, block_w>>s->chroma_h_shift, block_w>>s->chroma_v_shift);
- - cr= (sum + block_s/2)/block_s;
- - // iscore += pix_norm1(¤t_mb[2][0], uvstride, block_w>>1) - 2*cr*sum + cr*cr*block_s;
- - }else
- - cb = cr = 0;
- -
- - ic= s->c;
- - ic.bytestream_start=
- - ic.bytestream= i_buffer; //FIXME end/start? and at the other stoo
- - memcpy(i_state, s->block_state, sizeof(s->block_state));
- - if(level!=s->block_max_depth)
- - put_rac(&ic, &i_state[4 + s_context], 1);
- - put_rac(&ic, &i_state[1 + left->type + top->type], 1);
- - put_symbol(&ic, &i_state[32], l-pl , 1);
- - if (s->nb_planes > 2) {
- - put_symbol(&ic, &i_state[64], cb-pcb, 1);
- - put_symbol(&ic, &i_state[96], cr-pcr, 1);
- - }
- - i_len= ic.bytestream - ic.bytestream_start;
- - iscore += (s->lambda2*(get_rac_count(&ic)-base_bits))>>FF_LAMBDA_SHIFT;
- -
- - av_assert1(iscore < 255*255*256 + s->lambda2*10);
- - av_assert1(iscore >= 0);
- - av_assert1(l>=0 && l<=255);
- - av_assert1(pl>=0 && pl<=255);
- -
- - if(level==0){
- - int varc= iscore >> 8;
- - int vard= score >> 8;
- - if (vard <= 64 || vard < varc)
- - c->scene_change_score+= ff_sqrt(vard) - ff_sqrt(varc);
- - else
- - c->scene_change_score+= s->m.qscale;
- - }
- -
- - if(level!=s->block_max_depth){
- - put_rac(&s->c, &s->block_state[4 + s_context], 0);
- - score2 = encode_q_branch(s, level+1, 2*x+0, 2*y+0);
- - score2+= encode_q_branch(s, level+1, 2*x+1, 2*y+0);
- - score2+= encode_q_branch(s, level+1, 2*x+0, 2*y+1);
- - score2+= encode_q_branch(s, level+1, 2*x+1, 2*y+1);
- - score2+= s->lambda2>>FF_LAMBDA_SHIFT; //FIXME exact split overhead
- -
- - if(score2 < score && score2 < iscore)
- - return score2;
- - }
- -
- - if(iscore < score){
- - pred_mv(s, &pmx, &pmy, 0, left, top, tr);
- - memcpy(pbbak, i_buffer, i_len);
- - s->c= ic;
- - s->c.bytestream_start= pbbak_start;
- - s->c.bytestream= pbbak + i_len;
- - set_blocks(s, level, x, y, l, cb, cr, pmx, pmy, 0, BLOCK_INTRA);
- - memcpy(s->block_state, i_state, sizeof(s->block_state));
- - return iscore;
- - }else{
- - memcpy(pbbak, p_buffer, p_len);
- - s->c= pc;
- - s->c.bytestream_start= pbbak_start;
- - s->c.bytestream= pbbak + p_len;
- - set_blocks(s, level, x, y, pl, pcb, pcr, mx, my, best_ref, 0);
- - memcpy(s->block_state, p_state, sizeof(s->block_state));
- - return score;
- - }
- -}
- -
- -static void encode_q_branch2(SnowContext *s, int level, int x, int y){
- - const int w= s->b_width << s->block_max_depth;
- - const int rem_depth= s->block_max_depth - level;
- - const int index= (x + y*w) << rem_depth;
- - int trx= (x+1)<<rem_depth;
- - BlockNode *b= &s->block[index];
- - const BlockNode *left = x ? &s->block[index-1] : &null_block;
- - const BlockNode *top = y ? &s->block[index-w] : &null_block;
- - const BlockNode *tl = y && x ? &s->block[index-w-1] : left;
- - const BlockNode *tr = y && trx<w && ((x&1)==0 || level==0) ? &s->block[index-w+(1<<rem_depth)] : tl; //FIXME use lt
- - int pl = left->color[0];
- - int pcb= left->color[1];
- - int pcr= left->color[2];
- - int pmx, pmy;
- - int ref_context= av_log2(2*left->ref) + av_log2(2*top->ref);
- - int mx_context= av_log2(2*FFABS(left->mx - top->mx)) + 16*!!b->ref;
- - int my_context= av_log2(2*FFABS(left->my - top->my)) + 16*!!b->ref;
- - int s_context= 2*left->level + 2*top->level + tl->level + tr->level;
- -
- - if(s->keyframe){
- - set_blocks(s, level, x, y, pl, pcb, pcr, 0, 0, 0, BLOCK_INTRA);
- - return;
- - }
- -
- - if(level!=s->block_max_depth){
- - if(same_block(b,b+1) && same_block(b,b+w) && same_block(b,b+w+1)){
- - put_rac(&s->c, &s->block_state[4 + s_context], 1);
- - }else{
- - put_rac(&s->c, &s->block_state[4 + s_context], 0);
- - encode_q_branch2(s, level+1, 2*x+0, 2*y+0);
- - encode_q_branch2(s, level+1, 2*x+1, 2*y+0);
- - encode_q_branch2(s, level+1, 2*x+0, 2*y+1);
- - encode_q_branch2(s, level+1, 2*x+1, 2*y+1);
- - return;
- - }
- - }
- - if(b->type & BLOCK_INTRA){
- - pred_mv(s, &pmx, &pmy, 0, left, top, tr);
- - put_rac(&s->c, &s->block_state[1 + (left->type&1) + (top->type&1)], 1);
- - put_symbol(&s->c, &s->block_state[32], b->color[0]-pl , 1);
- - if (s->nb_planes > 2) {
- - put_symbol(&s->c, &s->block_state[64], b->color[1]-pcb, 1);
- - put_symbol(&s->c, &s->block_state[96], b->color[2]-pcr, 1);
- - }
- - set_blocks(s, level, x, y, b->color[0], b->color[1], b->color[2], pmx, pmy, 0, BLOCK_INTRA);
- - }else{
- - pred_mv(s, &pmx, &pmy, b->ref, left, top, tr);
- - put_rac(&s->c, &s->block_state[1 + (left->type&1) + (top->type&1)], 0);
- - if(s->ref_frames > 1)
- - put_symbol(&s->c, &s->block_state[128 + 1024 + 32*ref_context], b->ref, 0);
- - put_symbol(&s->c, &s->block_state[128 + 32*mx_context], b->mx - pmx, 1);
- - put_symbol(&s->c, &s->block_state[128 + 32*my_context], b->my - pmy, 1);
- - set_blocks(s, level, x, y, pl, pcb, pcr, b->mx, b->my, b->ref, 0);
- - }
- -}
- -
- -static int get_dc(SnowContext *s, int mb_x, int mb_y, int plane_index){
- - int i, x2, y2;
- - Plane *p= &s->plane[plane_index];
- - const int block_size = MB_SIZE >> s->block_max_depth;
- - const int block_w = plane_index ? block_size>>s->chroma_h_shift : block_size;
- - const int block_h = plane_index ? block_size>>s->chroma_v_shift : block_size;
- - const uint8_t *obmc = plane_index ? ff_obmc_tab[s->block_max_depth+s->chroma_h_shift] : ff_obmc_tab[s->block_max_depth];
- - const int obmc_stride= plane_index ? (2*block_size)>>s->chroma_h_shift : 2*block_size;
- - const int ref_stride= s->current_picture->linesize[plane_index];
- - uint8_t *src= s-> input_picture->data[plane_index];
- - IDWTELEM *dst= (IDWTELEM*)s->m.sc.obmc_scratchpad + plane_index*block_size*block_size*4; //FIXME change to unsigned
- - const int b_stride = s->b_width << s->block_max_depth;
- - const int w= p->width;
- - const int h= p->height;
- - int index= mb_x + mb_y*b_stride;
- - BlockNode *b= &s->block[index];
- - BlockNode backup= *b;
- - int ab=0;
- - int aa=0;
- -
- - av_assert2(s->chroma_h_shift == s->chroma_v_shift); //obmc stuff above
- -
- - b->type|= BLOCK_INTRA;
- - b->color[plane_index]= 0;
- - memset(dst, 0, obmc_stride*obmc_stride*sizeof(IDWTELEM));
- -
- - for(i=0; i<4; i++){
- - int mb_x2= mb_x + (i &1) - 1;
- - int mb_y2= mb_y + (i>>1) - 1;
- - int x= block_w*mb_x2 + block_w/2;
- - int y= block_h*mb_y2 + block_h/2;
- -
- - add_yblock(s, 0, NULL, dst + (i&1)*block_w + (i>>1)*obmc_stride*block_h, NULL, obmc,
- - x, y, block_w, block_h, 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_h); y2++){
- - for(x2= FFMAX(x, 0); x2<FFMIN(w, x+block_w); x2++){
- - int index= x2-(block_w*mb_x - block_w/2) + (y2-(block_h*mb_y - block_h/2))*obmc_stride;
- - int obmc_v= obmc[index];
- - int d;
- - if(y<0) obmc_v += obmc[index + block_h*obmc_stride];
- - if(x<0) obmc_v += obmc[index + block_w];
- - if(y+block_h>h) obmc_v += obmc[index - block_h*obmc_stride];
- - if(x+block_w>w) obmc_v += obmc[index - block_w];
- - //FIXME precalculate this or simplify it somehow else
- -
- - d = -dst[index] + (1<<(FRAC_BITS-1));
- - dst[index] = d;
- - ab += (src[x2 + y2*ref_stride] - (d>>FRAC_BITS)) * obmc_v;
- - aa += obmc_v * obmc_v; //FIXME precalculate this
- - }
- - }
- - }
- - *b= backup;
- -
- - return av_clip_uint8( ROUNDED_DIV(ab<<LOG2_OBMC_MAX, aa) ); //FIXME we should not need clipping
- -}
- -
- -static inline int get_block_bits(SnowContext *s, int x, int y, int w){
- - const int b_stride = s->b_width << s->block_max_depth;
- - const int b_height = s->b_height<< s->block_max_depth;
- - int index= x + y*b_stride;
- - const BlockNode *b = &s->block[index];
- - const BlockNode *left = x ? &s->block[index-1] : &null_block;
- - const BlockNode *top = y ? &s->block[index-b_stride] : &null_block;
- - const BlockNode *tl = y && x ? &s->block[index-b_stride-1] : left;
- - const BlockNode *tr = y && x+w<b_stride ? &s->block[index-b_stride+w] : tl;
- - int dmx, dmy;
- -// int mx_context= av_log2(2*FFABS(left->mx - top->mx));
- -// int my_context= av_log2(2*FFABS(left->my - top->my));
- -
- - if(x<0 || x>=b_stride || y>=b_height)
- - return 0;
- -/*
- -1 0 0
- -01X 1-2 1
- -001XX 3-6 2-3
- -0001XXX 7-14 4-7
- -00001XXXX 15-30 8-15
- -*/
- -//FIXME try accurate rate
- -//FIXME intra and inter predictors if surrounding blocks are not the same type
- - if(b->type & BLOCK_INTRA){
- - return 3+2*( av_log2(2*FFABS(left->color[0] - b->color[0]))
- - + av_log2(2*FFABS(left->color[1] - b->color[1]))
- - + av_log2(2*FFABS(left->color[2] - b->color[2])));
- - }else{
- - pred_mv(s, &dmx, &dmy, b->ref, left, top, tr);
- - dmx-= b->mx;
- - dmy-= b->my;
- - return 2*(1 + av_log2(2*FFABS(dmx)) //FIXME kill the 2* can be merged in lambda
- - + av_log2(2*FFABS(dmy))
- - + av_log2(2*b->ref));
- - }
- -}
- -
- -static int get_block_rd(SnowContext *s, int mb_x, int mb_y, int plane_index, uint8_t (*obmc_edged)[MB_SIZE * 2]){
- - Plane *p= &s->plane[plane_index];
- - const int block_size = MB_SIZE >> s->block_max_depth;
- - const int block_w = plane_index ? block_size>>s->chroma_h_shift : block_size;
- - const int block_h = plane_index ? block_size>>s->chroma_v_shift : block_size;
- - const int obmc_stride= plane_index ? (2*block_size)>>s->chroma_h_shift : 2*block_size;
- - const int ref_stride= s->current_picture->linesize[plane_index];
- - uint8_t *dst= s->current_picture->data[plane_index];
- - uint8_t *src= s-> input_picture->data[plane_index];
- - IDWTELEM *pred= (IDWTELEM*)s->m.sc.obmc_scratchpad + plane_index*block_size*block_size*4;
- - uint8_t *cur = s->scratchbuf;
- - uint8_t *tmp = s->emu_edge_buffer;
- - const int b_stride = s->b_width << s->block_max_depth;
- - const int b_height = s->b_height<< s->block_max_depth;
- - const int w= p->width;
- - const int h= p->height;
- - int distortion;
- - int rate= 0;
- - const int penalty_factor= get_penalty_factor(s->lambda, s->lambda2, s->avctx->me_cmp);
- - int sx= block_w*mb_x - block_w/2;
- - int sy= block_h*mb_y - block_h/2;
- - int x0= FFMAX(0,-sx);
- - int y0= FFMAX(0,-sy);
- - int x1= FFMIN(block_w*2, w-sx);
- - int y1= FFMIN(block_h*2, h-sy);
- - int i,x,y;
- -
- - av_assert2(s->chroma_h_shift == s->chroma_v_shift); //obmc and square assumtions below chckinhg only block_w
- -
- - 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);
- -
- - for(y=y0; y<y1; y++){
- - const uint8_t *obmc1= obmc_edged[y];
- - const IDWTELEM *pred1 = pred + y*obmc_stride;
- - uint8_t *cur1 = cur + y*ref_stride;
- - uint8_t *dst1 = dst + sx + (sy+y)*ref_stride;
- - for(x=x0; x<x1; x++){
- -#if FRAC_BITS >= LOG2_OBMC_MAX
- - int v = (cur1[x] * obmc1[x]) << (FRAC_BITS - LOG2_OBMC_MAX);
- -#else
- - int v = (cur1[x] * obmc1[x] + (1<<(LOG2_OBMC_MAX - FRAC_BITS-1))) >> (LOG2_OBMC_MAX - FRAC_BITS);
- -#endif
- - v = (v + pred1[x]) >> FRAC_BITS;
- - if(v&(~255)) v= ~(v>>31);
- - dst1[x] = v;
- - }
- - }
- -
- - /* copy the regions where obmc[] = (uint8_t)256 */
- - if(LOG2_OBMC_MAX == 8
- - && (mb_x == 0 || mb_x == b_stride-1)
- - && (mb_y == 0 || mb_y == b_height-1)){
- - if(mb_x == 0)
- - x1 = block_w;
- - else
- - x0 = block_w;
- - if(mb_y == 0)
- - y1 = block_h;
- - else
- - y0 = block_h;
- - for(y=y0; y<y1; y++)
- - memcpy(dst + sx+x0 + (sy+y)*ref_stride, cur + x0 + y*ref_stride, x1-x0);
- - }
- -
- - if(block_w==16){
- - /* FIXME rearrange dsputil to fit 32x32 cmp functions */
- - /* FIXME check alignment of the cmp wavelet vs the encoding wavelet */
- - /* FIXME cmps overlap but do not cover the wavelet's whole support.
- - * So improving the score of one block is not strictly guaranteed
- - * to improve the score of the whole frame, thus iterative motion
- - * estimation does not always converge. */
- - if(s->avctx->me_cmp == FF_CMP_W97)
- - distortion = ff_w97_32_c(&s->m, src + sx + sy*ref_stride, dst + sx + sy*ref_stride, ref_stride, 32);
- - else if(s->avctx->me_cmp == FF_CMP_W53)
- - distortion = ff_w53_32_c(&s->m, src + sx + sy*ref_stride, dst + sx + sy*ref_stride, ref_stride, 32);
- - else{
- - distortion = 0;
- - for(i=0; i<4; i++){
- - int off = sx+16*(i&1) + (sy+16*(i>>1))*ref_stride;
- - distortion += s->mecc.me_cmp[0](&s->m, src + off, dst + off, ref_stride, 16);
- - }
- - }
- - }else{
- - av_assert2(block_w==8);
- - distortion = s->mecc.me_cmp[0](&s->m, src + sx + sy*ref_stride, dst + sx + sy*ref_stride, ref_stride, block_w*2);
- - }
- -
- - if(plane_index==0){
- - for(i=0; i<4; i++){
- -/* ..RRr
- - * .RXx.
- - * rxx..
- - */
- - rate += get_block_bits(s, mb_x + (i&1) - (i>>1), mb_y + (i>>1), 1);
- - }
- - if(mb_x == b_stride-2)
- - rate += get_block_bits(s, mb_x + 1, mb_y + 1, 1);
- - }
- - return distortion + rate*penalty_factor;
- -}
- -
- -static int get_4block_rd(SnowContext *s, int mb_x, int mb_y, int plane_index){
- - int i, y2;
- - Plane *p= &s->plane[plane_index];
- - const int block_size = MB_SIZE >> s->block_max_depth;
- - const int block_w = plane_index ? block_size>>s->chroma_h_shift : block_size;
- - const int block_h = plane_index ? block_size>>s->chroma_v_shift : block_size;
- - const uint8_t *obmc = plane_index ? ff_obmc_tab[s->block_max_depth+s->chroma_h_shift] : ff_obmc_tab[s->block_max_depth];
- - const int obmc_stride= plane_index ? (2*block_size)>>s->chroma_h_shift : 2*block_size;
- - const int ref_stride= s->current_picture->linesize[plane_index];
- - uint8_t *dst= s->current_picture->data[plane_index];
- - uint8_t *src= s-> input_picture->data[plane_index];
- - //FIXME zero_dst is const but add_yblock changes dst if add is 0 (this is never the case for dst=zero_dst
- - // const has only been removed from zero_dst to suppress a warning
- - static IDWTELEM zero_dst[4096]; //FIXME
- - const int b_stride = s->b_width << s->block_max_depth;
- - const int w= p->width;
- - const int h= p->height;
- - int distortion= 0;
- - int rate= 0;
- - const int penalty_factor= get_penalty_factor(s->lambda, s->lambda2, s->avctx->me_cmp);
- -
- - av_assert2(s->chroma_h_shift == s->chroma_v_shift); //obmc and square assumtions below
- -
- - for(i=0; i<9; i++){
- - int mb_x2= mb_x + (i%3) - 1;
- - int mb_y2= mb_y + (i/3) - 1;
- - int x= block_w*mb_x2 + block_w/2;
- - int y= block_h*mb_y2 + block_h/2;
- -
- - add_yblock(s, 0, NULL, zero_dst, dst, obmc,
- - x, y, block_w, block_h, 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
- - for(y2= y; y2<0; y2++)
- - memcpy(dst + x + y2*ref_stride, src + x + y2*ref_stride, block_w);
- - for(y2= h; y2<y+block_h; y2++)
- - memcpy(dst + x + y2*ref_stride, src + x + y2*ref_stride, block_w);
- - if(x<0){
- - for(y2= y; y2<y+block_h; y2++)
- - memcpy(dst + x + y2*ref_stride, src + x + y2*ref_stride, -x);
- - }
- - if(x+block_w > w){
- - for(y2= y; y2<y+block_h; y2++)
- - memcpy(dst + w + y2*ref_stride, src + w + y2*ref_stride, x+block_w - w);
- - }
- -
- - av_assert1(block_w== 8 || block_w==16);
- - distortion += s->mecc.me_cmp[block_w==8](&s->m, src + x + y*ref_stride, dst + x + y*ref_stride, ref_stride, block_h);
- - }
- -
- - if(plane_index==0){
- - BlockNode *b= &s->block[mb_x+mb_y*b_stride];
- - int merged= same_block(b,b+1) && same_block(b,b+b_stride) && same_block(b,b+b_stride+1);
- -
- -/* ..RRRr
- - * .RXXx.
- - * .RXXx.
- - * rxxx.
- - */
- - if(merged)
- - rate = get_block_bits(s, mb_x, mb_y, 2);
- - for(i=merged?4:0; i<9; i++){
- - static const int dxy[9][2] = {{0,0},{1,0},{0,1},{1,1},{2,0},{2,1},{-1,2},{0,2},{1,2}};
- - rate += get_block_bits(s, mb_x + dxy[i][0], mb_y + dxy[i][1], 1);
- - }
- - }
- - return distortion + rate*penalty_factor;
- -}
- -
- static int encode_subband_c0run(SnowContext *s, SubBand *b, const IDWTELEM *src, const IDWTELEM *parent, int stride, int orientation){
- const int w= b->width;
- const int h= b->height;
- @@ -899,347 +380,6 @@ static int encode_subband(SnowContext *s, SubBand *b, const IDWTELEM *src, const
- // encode_subband_dzr(s, b, src, parent, stride, orientation);
- }
- -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){
- - const int b_stride= s->b_width << s->block_max_depth;
- - BlockNode *block= &s->block[mb_x + mb_y * b_stride];
- - BlockNode backup= *block;
- - unsigned value;
- - int rd, index;
- -
- - av_assert2(mb_x>=0 && mb_y>=0);
- - av_assert2(mb_x<b_stride);
- -
- - if(intra){
- - block->color[0] = p[0];
- - block->color[1] = p[1];
- - block->color[2] = p[2];
- - 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) + (block->ref<<12);
- - if(s->me_cache[index] == value)
- - return 0;
- - s->me_cache[index]= value;
- -
- - block->mx= p[0];
- - block->my= p[1];
- - block->type &= ~BLOCK_INTRA;
- - }
- -
- - rd= get_block_rd(s, mb_x, mb_y, 0, obmc_edged) + s->intra_penalty * !!intra;
- -
- -//FIXME chroma
- - if(rd < *best_rd){
- - *best_rd= rd;
- - return 1;
- - }else{
- - *block= backup;
- - return 0;
- - }
- -}
- -
- -/* special case for int[2] args we discard afterwards,
- - * fixes compilation problem with gcc 2.95 */
- -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){
- - int p[2] = {p0, p1};
- - return check_block(s, mb_x, mb_y, p, 0, obmc_edged, best_rd);
- -}
- -
- -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){
- - const int b_stride= s->b_width << s->block_max_depth;
- - BlockNode *block= &s->block[mb_x + mb_y * b_stride];
- - BlockNode backup[4];
- - unsigned value;
- - int rd, index;
- -
- - /* We don't initialize backup[] during variable declaration, because
- - * that fails to compile on MSVC: "cannot convert from 'BlockNode' to
- - * 'int16_t'". */
- - backup[0] = block[0];
- - backup[1] = block[1];
- - backup[2] = block[b_stride];
- - backup[3] = block[b_stride + 1];
- -
- - av_assert2(mb_x>=0 && mb_y>=0);
- - av_assert2(mb_x<b_stride);
- - av_assert2(((mb_x|mb_y)&1) == 0);
- -
- - index= (p0 + 31*p1) & (ME_CACHE_SIZE-1);
- - 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;
- -
- - rd= get_4block_rd(s, mb_x, mb_y, 0);
- -
- -//FIXME chroma
- - if(rd < *best_rd){
- - *best_rd= rd;
- - return 1;
- - }else{
- - block[0]= backup[0];
- - block[1]= backup[1];
- - block[b_stride]= backup[2];
- - block[b_stride+1]= backup[3];
- - return 0;
- - }
- -}
- -
- -static void iterative_me(SnowContext *s){
- - int pass, mb_x, mb_y;
- - 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;
- - int color[3];
- -
- - {
- - RangeCoder r = s->c;
- - uint8_t state[sizeof(s->block_state)];
- - memcpy(state, s->block_state, sizeof(s->block_state));
- - for(mb_y= 0; mb_y<s->b_height; mb_y++)
- - for(mb_x= 0; mb_x<s->b_width; mb_x++)
- - encode_q_branch(s, 0, mb_x, mb_y);
- - s->c = r;
- - memcpy(s->block_state, state, sizeof(s->block_state));
- - }
- -
- - for(pass=0; pass<25; pass++){
- - int change= 0;
- -
- - 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, 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;
- - BlockNode *lb = mb_x ? &s->block[index -1] : NULL;
- - BlockNode *rb = mb_x+1<b_width ? &s->block[index +1] : NULL;
- - BlockNode *bb = mb_y+1<b_height ? &s->block[index+b_stride ] : NULL;
- - BlockNode *tlb= mb_x && mb_y ? &s->block[index-b_stride-1] : NULL;
- - BlockNode *trb= mb_x+1<b_width && mb_y ? &s->block[index-b_stride+1] : NULL;
- - BlockNode *blb= mb_x && mb_y+1<b_height ? &s->block[index+b_stride-1] : NULL;
- - BlockNode *brb= mb_x+1<b_width && mb_y+1<b_height ? &s->block[index+b_stride+1] : NULL;
- - const int b_w= (MB_SIZE >> s->block_max_depth);
- - uint8_t obmc_edged[MB_SIZE * 2][MB_SIZE * 2];
- -
- - if(pass && (block->type & BLOCK_OPT))
- - continue;
- - block->type |= BLOCK_OPT;
- -
- - backup= *block;
- -
- - if(!s->me_cache_generation)
- - memset(s->me_cache, 0, sizeof(s->me_cache));
- - s->me_cache_generation += 1<<22;
- -
- - //FIXME precalculate
- - {
- - int x, y;
- - for (y = 0; y < b_w * 2; y++)
- - memcpy(obmc_edged[y], ff_obmc_tab[s->block_max_depth] + y * b_w * 2, b_w * 2);
- - if(mb_x==0)
- - for(y=0; y<b_w*2; y++)
- - memset(obmc_edged[y], obmc_edged[y][0] + obmc_edged[y][b_w-1], b_w);
- - if(mb_x==b_stride-1)
- - for(y=0; y<b_w*2; y++)
- - memset(obmc_edged[y]+b_w, obmc_edged[y][b_w] + obmc_edged[y][b_w*2-1], b_w);
- - if(mb_y==0){
- - for(x=0; x<b_w*2; x++)
- - obmc_edged[0][x] += obmc_edged[b_w-1][x];
- - for(y=1; y<b_w; y++)
- - memcpy(obmc_edged[y], obmc_edged[0], b_w*2);
- - }
- - if(mb_y==b_height-1){
- - for(x=0; x<b_w*2; x++)
- - obmc_edged[b_w*2-1][x] += obmc_edged[b_w][x];
- - for(y=b_w; y<b_w*2-1; y++)
- - memcpy(obmc_edged[y], obmc_edged[b_w*2-1], b_w*2);
- - }
- - }
- -
- - //skip stuff outside the picture
- - if(mb_x==0 || mb_y==0 || mb_x==b_width-1 || mb_y==b_height-1){
- - uint8_t *src= s-> input_picture->data[0];
- - uint8_t *dst= s->current_picture->data[0];
- - const int stride= s->current_picture->linesize[0];
- - const int block_w= MB_SIZE >> s->block_max_depth;
- - const int block_h= MB_SIZE >> s->block_max_depth;
- - const int sx= block_w*mb_x - block_w/2;
- - const int sy= block_h*mb_y - block_h/2;
- - const int w= s->plane[0].width;
- - const int h= s->plane[0].height;
- - int y;
- -
- - for(y=sy; y<0; y++)
- - memcpy(dst + sx + y*stride, src + sx + y*stride, block_w*2);
- - for(y=h; y<sy+block_h*2; y++)
- - memcpy(dst + sx + y*stride, src + sx + y*stride, block_w*2);
- - if(sx<0){
- - for(y=sy; y<sy+block_h*2; y++)
- - memcpy(dst + sx + y*stride, src + sx + y*stride, -sx);
- - }
- - if(sx+block_w*2 > w){
- - for(y=sy; y<sy+block_h*2; y++)
- - memcpy(dst + w + y*stride, src + w + y*stride, sx+block_w*2 - w);
- - }
- - }
- -
- - // intra(black) = neighbors' contribution to the current block
- - for(i=0; i < s->nb_planes; i++)
- - color[i]= get_dc(s, mb_x, mb_y, i);
- -
- - // get previous score (cannot be cached due to OBMC)
- - if(pass > 0 && (block->type&BLOCK_INTRA)){
- - int color0[3]= {block->color[0], block->color[1], block->color[2]};
- - check_block(s, mb_x, mb_y, color0, 1, obmc_edged, &best_rd);
- - }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);
- - if(tb)
- - check_block_inter(s, mb_x, mb_y, mvr[-b_stride][0], mvr[-b_stride][1], obmc_edged, &best_rd);
- - if(lb)
- - check_block_inter(s, mb_x, mb_y, mvr[-1][0], mvr[-1][1], obmc_edged, &best_rd);
- - if(rb)
- - check_block_inter(s, mb_x, mb_y, mvr[1][0], mvr[1][1], obmc_edged, &best_rd);
- - if(bb)
- - 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 interpolation / round to nearest integer
- - do{
- - int newx = block->mx;
- - int newy = block->my;
- - int dia_size = s->iterative_dia_size ? s->iterative_dia_size : FFMAX(s->avctx->dia_size, 1);
- - dia_change=0;
- - for(i=0; i < dia_size; i++){
- - for(j=0; j<i; j++){
- - dia_change |= check_block_inter(s, mb_x, mb_y, newx+4*(i-j), newy+(4*j), obmc_edged, &best_rd);
- - dia_change |= check_block_inter(s, mb_x, mb_y, newx-4*(i-j), newy-(4*j), obmc_edged, &best_rd);
- - dia_change |= check_block_inter(s, mb_x, mb_y, newx-(4*j), newy+4*(i-j), obmc_edged, &best_rd);
- - dia_change |= check_block_inter(s, mb_x, mb_y, newx+(4*j), newy-4*(i-j), obmc_edged, &best_rd);
- - }
- - }
- - }while(dia_change);
- - /* subpel ME */
- - do{
- - static const int square[8][2]= {{+1, 0},{-1, 0},{ 0,+1},{ 0,-1},{+1,+1},{-1,-1},{+1,-1},{-1,+1},};
- - dia_change=0;
- - for(i=0; i<8; i++)
- - 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;
- - check_block(s, mb_x, mb_y, color, 1, obmc_edged, &best_rd);
- - //FIXME RD style color selection
- - if(!same_block(block, &backup)){
- - if(tb ) tb ->type &= ~BLOCK_OPT;
- - if(lb ) lb ->type &= ~BLOCK_OPT;
- - if(rb ) rb ->type &= ~BLOCK_OPT;
- - if(bb ) bb ->type &= ~BLOCK_OPT;
- - if(tlb) tlb->type &= ~BLOCK_OPT;
- - if(trb) trb->type &= ~BLOCK_OPT;
- - if(blb) blb->type &= ~BLOCK_OPT;
- - if(brb) brb->type &= ~BLOCK_OPT;
- - change ++;
- - }
- - }
- - }
- - av_log(s->avctx, AV_LOG_DEBUG, "pass:%d changed:%d\n", pass, change);
- - if(!change)
- - break;
- - }
- -
- - if(s->block_max_depth == 1){
- - int change= 0;
- - for(mb_y= 0; mb_y<b_height; mb_y+=2){
- - for(mb_x= 0; mb_x<b_width; mb_x+=2){
- - int i;
- - int best_rd, init_rd;
- - const int index= mb_x + mb_y * b_stride;
- - BlockNode *b[4];
- -
- - b[0]= &s->block[index];
- - b[1]= b[0]+1;
- - b[2]= b[0]+b_stride;
- - b[3]= b[2]+1;
- - if(same_block(b[0], b[1]) &&
- - same_block(b[0], b[2]) &&
- - same_block(b[0], b[3]))
- - continue;
- -
- - if(!s->me_cache_generation)
- - memset(s->me_cache, 0, sizeof(s->me_cache));
- - s->me_cache_generation += 1<<22;
- -
- - 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, 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, b[i]->ref, &best_rd);
- -
- - if(init_rd != best_rd)
- - change++;
- - }
- - }
- - av_log(s->avctx, AV_LOG_ERROR, "pass:4mv changed:%d\n", change*4);
- - }
- -}
- -
- -static void encode_blocks(SnowContext *s, int search){
- - int x, y;
- - int w= s->b_width;
- - int h= s->b_height;
- -
- - if(s->motion_est == FF_ME_ITER && !s->keyframe && search)
- - iterative_me(s);
- -
- - for(y=0; y<h; y++){
- - if(s->c.bytestream_end - s->c.bytestream < w*MB_SIZE*MB_SIZE*3){ //FIXME nicer limit
- - av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
- - return;
- - }
- - for(x=0; x<w; x++){
- - if(s->motion_est == FF_ME_ITER || !search)
- - encode_q_branch2(s, 0, x, y);
- - else
- - encode_q_branch (s, 0, x, y);
- - }
- - }
- -}
- -
- static void quantize(SnowContext *s, SubBand *b, IDWTELEM *dst, DWTELEM *src, int stride, int bias){
- const int w= b->width;
- const int h= b->height;
- @@ -1396,10 +536,10 @@ static void encode_header(SnowContext *s){
- s->last_spatial_decomposition_type=
- s->last_qlog=
- s->last_qbias=
- - s->last_mv_scale=
- - s->last_block_max_depth= 0;
- + s->obmc.last_mv_scale=
- + s->obmc.last_block_max_depth= 0;
- for(plane_index=0; plane_index<2; plane_index++){
- - Plane *p= &s->plane[plane_index];
- + PlaneObmc *p= &s->obmc.plane[plane_index];
- p->last_htaps=0;
- p->last_diag_mc=0;
- memset(p->last_hcoeff, 0, sizeof(p->last_hcoeff));
- @@ -1418,7 +558,7 @@ static void encode_header(SnowContext *s){
- }
- 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);
- + put_symbol(&s->c, s->header_state, s->obmc.max_ref_frames-1, 0);
- encode_qlogs(s);
- }
- @@ -1426,7 +566,7 @@ static void encode_header(SnowContext *s){
- if(!s->keyframe){
- int update_mc=0;
- for(plane_index=0; plane_index<FFMIN(s->nb_planes, 2); plane_index++){
- - Plane *p= &s->plane[plane_index];
- + PlaneObmc *p= &s->obmc.plane[plane_index];
- update_mc |= p->last_htaps != p->htaps;
- update_mc |= p->last_diag_mc != p->diag_mc;
- update_mc |= !!memcmp(p->last_hcoeff, p->hcoeff, sizeof(p->hcoeff));
- @@ -1434,7 +574,7 @@ static void encode_header(SnowContext *s){
- put_rac(&s->c, s->header_state, update_mc);
- if(update_mc){
- for(plane_index=0; plane_index<FFMIN(s->nb_planes, 2); plane_index++){
- - Plane *p= &s->plane[plane_index];
- + PlaneObmc *p= &s->obmc.plane[plane_index];
- put_rac(&s->c, s->header_state, p->diag_mc);
- put_symbol(&s->c, s->header_state, p->htaps/2-1, 0);
- for(i= p->htaps/2; i; i--)
- @@ -1450,10 +590,10 @@ static void encode_header(SnowContext *s){
- }
- put_symbol(&s->c, s->header_state, s->spatial_decomposition_type - s->last_spatial_decomposition_type, 1);
- - put_symbol(&s->c, s->header_state, s->qlog - s->last_qlog , 1);
- - put_symbol(&s->c, s->header_state, s->mv_scale - s->last_mv_scale, 1);
- - put_symbol(&s->c, s->header_state, s->qbias - s->last_qbias , 1);
- - put_symbol(&s->c, s->header_state, s->block_max_depth - s->last_block_max_depth, 1);
- + put_symbol(&s->c, s->header_state, s->qlog - s->last_qlog , 1);
- + put_symbol(&s->c, s->header_state, s->obmc.mv_scale - s->obmc.last_mv_scale, 1);
- + put_symbol(&s->c, s->header_state, s->qbias - s->last_qbias , 1);
- + put_symbol(&s->c, s->header_state, s->obmc.block_max_depth - s->obmc.last_block_max_depth, 1);
- }
- @@ -1462,7 +602,7 @@ static void update_last_header_values(SnowContext *s){
- if(!s->keyframe){
- for(plane_index=0; plane_index<2; plane_index++){
- - Plane *p= &s->plane[plane_index];
- + PlaneObmc *p= &s->obmc.plane[plane_index];
- p->last_diag_mc= p->diag_mc;
- p->last_htaps = p->htaps;
- memcpy(p->last_hcoeff, p->hcoeff, sizeof(p->hcoeff));
- @@ -1472,8 +612,8 @@ static void update_last_header_values(SnowContext *s){
- s->last_spatial_decomposition_type = s->spatial_decomposition_type;
- s->last_qlog = s->qlog;
- s->last_qbias = s->qbias;
- - s->last_mv_scale = s->mv_scale;
- - s->last_block_max_depth = s->block_max_depth;
- + s->obmc.last_mv_scale = s->obmc.mv_scale;
- + s->obmc.last_block_max_depth = s->obmc.block_max_depth;
- s->last_spatial_decomposition_count = s->spatial_decomposition_count;
- }
- @@ -1518,17 +658,17 @@ static int ratecontrol_1pass(SnowContext *s, AVFrame *pict)
- coef_sum = (uint64_t)coef_sum * coef_sum >> 16;
- if(pict->pict_type == AV_PICTURE_TYPE_I){
- - s->m.current_picture.mb_var_sum= coef_sum;
- - s->m.current_picture.mc_mb_var_sum= 0;
- + s->obmc.m.current_picture.mb_var_sum= coef_sum;
- + s->obmc.m.current_picture.mc_mb_var_sum= 0;
- }else{
- - s->m.current_picture.mc_mb_var_sum= coef_sum;
- - s->m.current_picture.mb_var_sum= 0;
- + s->obmc.m.current_picture.mc_mb_var_sum= coef_sum;
- + s->obmc.m.current_picture.mb_var_sum= 0;
- }
- - pict->quality= ff_rate_estimate_qscale(&s->m, 1);
- + pict->quality= ff_rate_estimate_qscale(&s->obmc.m, 1);
- if (pict->quality < 0)
- return INT_MIN;
- - s->lambda= pict->quality * 3/2;
- + s->obmc.lambda= pict->quality * 3/2;
- delta_qlog= qscale2qlog(pict->quality) - s->qlog;
- s->qlog+= delta_qlog;
- return delta_qlog;
- @@ -1545,12 +685,12 @@ static void calculate_visual_weight(SnowContext *s, Plane *p){
- IDWTELEM *ibuf= b->ibuf;
- int64_t error=0;
- - memset(s->spatial_idwt_buffer, 0, sizeof(*s->spatial_idwt_buffer)*width*height);
- + memset(s->obmc.spatial_idwt_buffer, 0, sizeof(*s->obmc.spatial_idwt_buffer)*width*height);
- ibuf[b->width/2 + b->height/2*b->stride]= 256*16;
- - ff_spatial_idwt(s->spatial_idwt_buffer, s->temp_idwt_buffer, width, height, width, s->spatial_decomposition_type, s->spatial_decomposition_count);
- + ff_spatial_idwt(s->obmc.spatial_idwt_buffer, s->temp_idwt_buffer, width, height, width, s->spatial_decomposition_type, s->spatial_decomposition_count);
- for(y=0; y<height; y++){
- for(x=0; x<width; x++){
- - int64_t d= s->spatial_idwt_buffer[x + y*width]*16;
- + int64_t d= s->obmc.spatial_idwt_buffer[x + y*width]*16;
- error += d*d;
- }
- }
- @@ -1572,7 +712,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
- uint8_t rc_header_bak[sizeof(s->header_state)];
- uint8_t rc_block_bak[sizeof(s->block_state)];
- - if ((ret = ff_alloc_packet2(avctx, pkt, s->b_width*s->b_height*MB_SIZE*MB_SIZE*3 + AV_INPUT_BUFFER_MIN_SIZE, 0)) < 0)
- + if ((ret = ff_alloc_packet2(avctx, pkt, s->obmc.b_width*s->obmc.b_height*MB_SIZE*MB_SIZE*3 + AV_INPUT_BUFFER_MIN_SIZE, 0)) < 0)
- return ret;
- ff_init_range_encoder(c, pkt->data, pkt->size);
- @@ -1582,124 +722,55 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
- int hshift= i ? s->chroma_h_shift : 0;
- int vshift= i ? s->chroma_v_shift : 0;
- for(y=0; y<AV_CEIL_RSHIFT(height, vshift); y++)
- - memcpy(&s->input_picture->data[i][y * s->input_picture->linesize[i]],
- + memcpy(&s->obmc.input_picture->data[i][y * s->obmc.input_picture->linesize[i]],
- &pict->data[i][y * pict->linesize[i]],
- AV_CEIL_RSHIFT(width, hshift));
- - s->mpvencdsp.draw_edges(s->input_picture->data[i], s->input_picture->linesize[i],
- + s->obmc.mpvencdsp.draw_edges(s->obmc.input_picture->data[i], s->obmc.input_picture->linesize[i],
- AV_CEIL_RSHIFT(width, hshift), AV_CEIL_RSHIFT(height, vshift),
- EDGE_WIDTH >> hshift, EDGE_WIDTH >> vshift,
- EDGE_TOP | EDGE_BOTTOM);
- }
- emms_c();
- - pic = s->input_picture;
- + pic = s->obmc.input_picture;
- pic->pict_type = pict->pict_type;
- pic->quality = pict->quality;
- - s->m.picture_number= avctx->frame_number;
- + s->obmc.m.picture_number= avctx->frame_number;
- if(avctx->flags&AV_CODEC_FLAG_PASS2){
- - s->m.pict_type = pic->pict_type = s->m.rc_context.entry[avctx->frame_number].new_pict_type;
- + s->obmc.m.pict_type = pic->pict_type = s->obmc.m.rc_context.entry[avctx->frame_number].new_pict_type;
- s->keyframe = pic->pict_type == AV_PICTURE_TYPE_I;
- + s->obmc.keyframe = s->keyframe;
- if(!(avctx->flags&AV_CODEC_FLAG_QSCALE)) {
- - pic->quality = ff_rate_estimate_qscale(&s->m, 0);
- + pic->quality = ff_rate_estimate_qscale(&s->obmc.m, 0);
- if (pic->quality < 0)
- return -1;
- }
- }else{
- s->keyframe= avctx->gop_size==0 || avctx->frame_number % avctx->gop_size == 0;
- - s->m.pict_type = pic->pict_type = s->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
- + s->obmc.m.pict_type = pic->pict_type = s->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
- + s->obmc.keyframe = s->keyframe;
- }
- if(s->pass1_rc && avctx->frame_number == 0)
- pic->quality = 2*FF_QP2LAMBDA;
- if (pic->quality) {
- s->qlog = qscale2qlog(pic->quality);
- - s->lambda = pic->quality * 3/2;
- + s->obmc.lambda = pic->quality * 3/2;
- }
- if (s->qlog < 0 || (!pic->quality && (avctx->flags & AV_CODEC_FLAG_QSCALE))) {
- s->qlog= LOSSLESS_QLOG;
- - s->lambda = 0;
- + s->obmc.lambda = 0;
- }//else keep previous frame's qlog until after motion estimation
- - if (s->current_picture->data[0]
- -#if FF_API_EMU_EDGE
- - && !(s->avctx->flags&CODEC_FLAG_EMU_EDGE)
- -#endif
- - ) {
- - int w = s->avctx->width;
- - int h = s->avctx->height;
- -
- - s->mpvencdsp.draw_edges(s->current_picture->data[0],
- - s->current_picture->linesize[0], w , h ,
- - EDGE_WIDTH , EDGE_WIDTH , EDGE_TOP | EDGE_BOTTOM);
- - if (s->current_picture->data[2]) {
- - s->mpvencdsp.draw_edges(s->current_picture->data[1],
- - s->current_picture->linesize[1], w>>s->chroma_h_shift, h>>s->chroma_v_shift,
- - EDGE_WIDTH>>s->chroma_h_shift, EDGE_WIDTH>>s->chroma_v_shift, EDGE_TOP | EDGE_BOTTOM);
- - s->mpvencdsp.draw_edges(s->current_picture->data[2],
- - s->current_picture->linesize[2], w>>s->chroma_h_shift, h>>s->chroma_v_shift,
- - EDGE_WIDTH>>s->chroma_h_shift, EDGE_WIDTH>>s->chroma_v_shift, EDGE_TOP | EDGE_BOTTOM);
- - }
- - }
- -
- - ff_snow_frame_start(s);
- - av_frame_unref(avctx->coded_frame);
- - ret = av_frame_ref(avctx->coded_frame, s->current_picture);
- - if (ret < 0)
- - return ret;
- -
- - s->m.current_picture_ptr= &s->m.current_picture;
- - s->m.current_picture.f = s->current_picture;
- - s->m.current_picture.f->pts = pict->pts;
- - if(pic->pict_type == AV_PICTURE_TYPE_P){
- - int block_width = (width +15)>>4;
- - int block_height= (height+15)>>4;
- - int stride= s->current_picture->linesize[0];
- -
- - av_assert0(s->current_picture->data[0]);
- - av_assert0(s->last_picture[0]->data[0]);
- -
- - s->m.avctx= s->avctx;
- - s->m. last_picture.f = s->last_picture[0];
- - s->m. new_picture.f = s->input_picture;
- - s->m. last_picture_ptr= &s->m. last_picture;
- - s->m.linesize = stride;
- - s->m.uvlinesize= s->current_picture->linesize[1];
- - s->m.width = width;
- - s->m.height= height;
- - s->m.mb_width = block_width;
- - s->m.mb_height= block_height;
- - s->m.mb_stride= s->m.mb_width+1;
- - s->m.b8_stride= 2*s->m.mb_width+1;
- - s->m.f_code=1;
- - s->m.pict_type = pic->pict_type;
- -#if FF_API_MOTION_EST
- - s->m.me_method= s->avctx->me_method;
- -#endif
- - s->m.motion_est= s->motion_est;
- - s->m.me.scene_change_score=0;
- - s->m.me.dia_size = avctx->dia_size;
- - s->m.quarter_sample= (s->avctx->flags & AV_CODEC_FLAG_QPEL)!=0;
- - s->m.out_format= FMT_H263;
- - s->m.unrestricted_mv= 1;
- -
- - s->m.lambda = s->lambda;
- - s->m.qscale= (s->m.lambda*139 + FF_LAMBDA_SCALE*64) >> (FF_LAMBDA_SHIFT + 7);
- - s->lambda2= s->m.lambda2= (s->m.lambda*s->m.lambda + FF_LAMBDA_SCALE/2) >> FF_LAMBDA_SHIFT;
- -
- - s->m.mecc= s->mecc; //move
- - s->m.qdsp= s->qdsp; //move
- - s->m.hdsp = s->hdsp;
- - ff_init_me(&s->m);
- - s->hdsp = s->m.hdsp;
- - s->mecc= s->m.mecc;
- - }
- -
- if(s->pass1_rc){
- memcpy(rc_header_bak, s->header_state, sizeof(s->header_state));
- memcpy(rc_block_bak, s->block_state, sizeof(s->block_state));
- }
- + if ((ret = ff_obmc_pre_encode_frame(&s->obmc, avctx, pict)) < 0)
- + return ret;
- +
- redo_frame:
- s->spatial_decomposition_count= 5;
- @@ -1713,7 +784,7 @@ redo_frame:
- return AVERROR(EINVAL);
- }
- - s->m.pict_type = pic->pict_type;
- + s->obmc.m.pict_type = pic->pict_type;
- s->qbias = pic->pict_type == AV_PICTURE_TYPE_P ? 2 : 0;
- ff_snow_common_init_after_header(avctx);
- @@ -1725,9 +796,9 @@ redo_frame:
- }
- encode_header(s);
- - s->m.misc_bits = 8*(s->c.bytestream - s->c.bytestream_start);
- - encode_blocks(s, 1);
- - s->m.mv_bits = 8*(s->c.bytestream - s->c.bytestream_start) - s->m.misc_bits;
- + s->obmc.m.misc_bits = 8*(s->c.bytestream - s->c.bytestream_start);
- + ff_obmc_encode_blocks(&s->obmc, 1);
- + s->obmc.m.mv_bits = 8*(s->c.bytestream - s->c.bytestream_start) - s->obmc.m.misc_bits;
- for(plane_index=0; plane_index < s->nb_planes; plane_index++){
- Plane *p= &s->plane[plane_index];
- @@ -1741,10 +812,10 @@ redo_frame:
- if(pict->data[plane_index]) //FIXME gray hack
- for(y=0; y<h; y++){
- for(x=0; x<w; x++){
- - s->spatial_idwt_buffer[y*w + x]= pict->data[plane_index][y*pict->linesize[plane_index] + x]<<FRAC_BITS;
- + s->obmc.spatial_idwt_buffer[y*w + x]= pict->data[plane_index][y*pict->linesize[plane_index] + x]<<FRAC_BITS;
- }
- }
- - predict_plane(s, s->spatial_idwt_buffer, plane_index, 0);
- + predict_plane(&s->obmc, s->obmc.spatial_idwt_buffer, plane_index, 0);
- #if FF_API_PRIVATE_OPT
- FF_DISABLE_DEPRECATION_WARNINGS
- @@ -1756,25 +827,26 @@ FF_ENABLE_DEPRECATION_WARNINGS
- if( plane_index==0
- && pic->pict_type == AV_PICTURE_TYPE_P
- && !(avctx->flags&AV_CODEC_FLAG_PASS2)
- - && s->m.me.scene_change_score > s->scenechange_threshold){
- + && s->obmc.m.me.scene_change_score > s->scenechange_threshold){
- ff_init_range_encoder(c, pkt->data, pkt->size);
- ff_build_rac_states(c, (1LL<<32)/20, 256-8);
- pic->pict_type= AV_PICTURE_TYPE_I;
- s->keyframe=1;
- - s->current_picture->key_frame=1;
- + s->obmc.keyframe = 1;
- + s->obmc.current_picture->key_frame=1;
- goto redo_frame;
- }
- if(s->qlog == LOSSLESS_QLOG){
- for(y=0; y<h; y++){
- for(x=0; x<w; x++){
- - s->spatial_dwt_buffer[y*w + x]= (s->spatial_idwt_buffer[y*w + x] + (1<<(FRAC_BITS-1))-1)>>FRAC_BITS;
- + s->spatial_dwt_buffer[y*w + x]= (s->obmc.spatial_idwt_buffer[y*w + x] + (1<<(FRAC_BITS-1))-1)>>FRAC_BITS;
- }
- }
- }else{
- for(y=0; y<h; y++){
- for(x=0; x<w; x++){
- - s->spatial_dwt_buffer[y*w + x]=s->spatial_idwt_buffer[y*w + x]<<ENCODER_EXTRA_BITS;
- + s->spatial_dwt_buffer[y*w + x]=s->obmc.spatial_idwt_buffer[y*w + x]<<ENCODER_EXTRA_BITS;
- }
- }
- }
- @@ -1791,7 +863,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
- memcpy(s->header_state, rc_header_bak, sizeof(s->header_state));
- memcpy(s->block_state, rc_block_bak, sizeof(s->block_state));
- encode_header(s);
- - encode_blocks(s, 0);
- + ff_obmc_encode_blocks(&s->obmc, 0);
- }
- }
- @@ -1818,27 +890,27 @@ FF_ENABLE_DEPRECATION_WARNINGS
- }
- }
- - ff_spatial_idwt(s->spatial_idwt_buffer, s->temp_idwt_buffer, w, h, w, s->spatial_decomposition_type, s->spatial_decomposition_count);
- + ff_spatial_idwt(s->obmc.spatial_idwt_buffer, s->temp_idwt_buffer, w, h, w, s->spatial_decomposition_type, s->spatial_decomposition_count);
- if(s->qlog == LOSSLESS_QLOG){
- for(y=0; y<h; y++){
- for(x=0; x<w; x++){
- - s->spatial_idwt_buffer[y*w + x]<<=FRAC_BITS;
- + s->obmc.spatial_idwt_buffer[y*w + x]<<=FRAC_BITS;
- }
- }
- }
- - predict_plane(s, s->spatial_idwt_buffer, plane_index, 1);
- + predict_plane(&s->obmc, s->obmc.spatial_idwt_buffer, plane_index, 1);
- }else{
- //ME/MC only
- if(pic->pict_type == AV_PICTURE_TYPE_I){
- for(y=0; y<h; y++){
- for(x=0; x<w; x++){
- - s->current_picture->data[plane_index][y*s->current_picture->linesize[plane_index] + x]=
- + s->obmc.current_picture->data[plane_index][y*s->obmc.current_picture->linesize[plane_index] + x]=
- pict->data[plane_index][y*pict->linesize[plane_index] + x];
- }
- }
- }else{
- - memset(s->spatial_idwt_buffer, 0, sizeof(IDWTELEM)*w*h);
- - predict_plane(s, s->spatial_idwt_buffer, plane_index, 1);
- + memset(s->obmc.spatial_idwt_buffer, 0, sizeof(IDWTELEM)*w*h);
- + predict_plane(&s->obmc, s->obmc.spatial_idwt_buffer, plane_index, 1);
- }
- }
- if(s->avctx->flags&AV_CODEC_FLAG_PSNR){
- @@ -1847,7 +919,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
- if(pict->data[plane_index]) //FIXME gray hack
- for(y=0; y<h; y++){
- for(x=0; x<w; x++){
- - int d= s->current_picture->data[plane_index][y*s->current_picture->linesize[plane_index] + x] - pict->data[plane_index][y*pict->linesize[plane_index] + x];
- + int d= s->obmc.current_picture->data[plane_index][y*s->obmc.current_picture->linesize[plane_index] + x] - pict->data[plane_index][y*pict->linesize[plane_index] + x];
- error += d*d;
- }
- }
- @@ -1859,43 +931,43 @@ FF_ENABLE_DEPRECATION_WARNINGS
- update_last_header_values(s);
- - ff_snow_release_buffer(avctx);
- -
- - s->current_picture->coded_picture_number = avctx->frame_number;
- - s->current_picture->pict_type = pic->pict_type;
- - s->current_picture->quality = pic->quality;
- - s->m.frame_bits = 8*(s->c.bytestream - s->c.bytestream_start);
- - s->m.p_tex_bits = s->m.frame_bits - s->m.misc_bits - s->m.mv_bits;
- - s->m.current_picture.f->display_picture_number =
- - s->m.current_picture.f->coded_picture_number = avctx->frame_number;
- - s->m.current_picture.f->quality = pic->quality;
- - s->m.total_bits += 8*(s->c.bytestream - s->c.bytestream_start);
- + ff_obmc_release_buffer(&s->obmc);
- +
- + s->obmc.current_picture->coded_picture_number = avctx->frame_number;
- + s->obmc.current_picture->pict_type = pic->pict_type;
- + s->obmc.current_picture->quality = pic->quality;
- + s->obmc.m.frame_bits = 8*(s->c.bytestream - s->c.bytestream_start);
- + s->obmc.m.p_tex_bits = s->obmc.m.frame_bits - s->obmc.m.misc_bits - s->obmc.m.mv_bits;
- + s->obmc.m.current_picture.f->display_picture_number =
- + s->obmc.m.current_picture.f->coded_picture_number = avctx->frame_number;
- + s->obmc.m.current_picture.f->quality = pic->quality;
- + s->obmc.m.total_bits += 8*(s->c.bytestream - s->c.bytestream_start);
- if(s->pass1_rc)
- - if (ff_rate_estimate_qscale(&s->m, 0) < 0)
- + if (ff_rate_estimate_qscale(&s->obmc.m, 0) < 0)
- return -1;
- if(avctx->flags&AV_CODEC_FLAG_PASS1)
- - ff_write_pass1_stats(&s->m);
- - s->m.last_pict_type = s->m.pict_type;
- - avctx->frame_bits = s->m.frame_bits;
- - avctx->mv_bits = s->m.mv_bits;
- - avctx->misc_bits = s->m.misc_bits;
- - avctx->p_tex_bits = s->m.p_tex_bits;
- + ff_write_pass1_stats(&s->obmc.m);
- + s->obmc.m.last_pict_type = s->obmc.m.pict_type;
- + avctx->frame_bits = s->obmc.m.frame_bits;
- + avctx->mv_bits = s->obmc.m.mv_bits;
- + avctx->misc_bits = s->obmc.m.misc_bits;
- + avctx->p_tex_bits = s->obmc.m.p_tex_bits;
- emms_c();
- - ff_side_data_set_encoder_stats(pkt, s->current_picture->quality,
- + ff_side_data_set_encoder_stats(pkt, s->obmc.current_picture->quality,
- s->encoding_error,
- (s->avctx->flags&AV_CODEC_FLAG_PSNR) ? 4 : 0,
- - s->current_picture->pict_type);
- + s->obmc.current_picture->pict_type);
- #if FF_API_ERROR_FRAME
- FF_DISABLE_DEPRECATION_WARNINGS
- - memcpy(s->current_picture->error, s->encoding_error, sizeof(s->encoding_error));
- + memcpy(s->obmc.current_picture->error, s->encoding_error, sizeof(s->encoding_error));
- FF_ENABLE_DEPRECATION_WARNINGS
- #endif
- pkt->size = ff_rac_terminate(c);
- - if (s->current_picture->key_frame)
- + if (s->obmc.current_picture->key_frame)
- pkt->flags |= AV_PKT_FLAG_KEY;
- *got_packet = 1;
- @@ -1907,22 +979,23 @@ static av_cold int encode_end(AVCodecContext *avctx)
- SnowContext *s = avctx->priv_data;
- ff_snow_common_end(s);
- - ff_rate_control_uninit(&s->m);
- - av_frame_free(&s->input_picture);
- + ff_rate_control_uninit(&s->obmc.m);
- + av_frame_free(&s->obmc.input_picture);
- av_freep(&avctx->stats_out);
- return 0;
- }
- #define OFFSET(x) offsetof(SnowContext, x)
- +#define OFFSET_OBMC(x) offsetof(SnowContext, obmc) + offsetof(OBMCContext, x)
- #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
- static const AVOption options[] = {
- FF_MPV_COMMON_OPTS
- { "iter", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_ME_ITER }, 0, 0, FF_MPV_OPT_FLAGS, "motion_est" },
- { "memc_only", "Only do ME/MC (I frames -> ref, P frame -> ME+MC).", OFFSET(memc_only), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
- { "no_bitstream", "Skip final bitstream writeout.", OFFSET(no_bitstream), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
- - { "intra_penalty", "Penalty for intra blocks in block decission", OFFSET(intra_penalty), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },
- - { "iterative_dia_size", "Dia size for the iterative ME", OFFSET(iterative_dia_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },
- + { "intra_penalty", "Penalty for intra blocks in block decission", OFFSET_OBMC(intra_penalty), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },
- + { "iterative_dia_size", "Dia size for the iterative ME", OFFSET_OBMC(iterative_dia_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },
- { "sc_threshold", "Scene change threshold", OFFSET(scenechange_threshold), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, VE },
- { "pred", "Spatial decomposition type", OFFSET(pred), AV_OPT_TYPE_INT, { .i64 = 0 }, DWT_97, DWT_53, VE, "pred" },
- { "dwt97", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, VE, "pred" },
- --
- 2.7.4 (Apple Git-66)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement