1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at>
3cabdff1aSopenharmony_ci *
4cabdff1aSopenharmony_ci * This file is part of FFmpeg.
5cabdff1aSopenharmony_ci *
6cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
7cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
8cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
9cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
10cabdff1aSopenharmony_ci *
11cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
12cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
13cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14cabdff1aSopenharmony_ci * Lesser General Public License for more details.
15cabdff1aSopenharmony_ci *
16cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
17cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
18cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19cabdff1aSopenharmony_ci */
20cabdff1aSopenharmony_ci
21cabdff1aSopenharmony_ci#include "libavutil/intmath.h"
22cabdff1aSopenharmony_ci#include "libavutil/libm.h"
23cabdff1aSopenharmony_ci#include "libavutil/log.h"
24cabdff1aSopenharmony_ci#include "libavutil/opt.h"
25cabdff1aSopenharmony_ci#include "libavutil/pixdesc.h"
26cabdff1aSopenharmony_ci#include "avcodec.h"
27cabdff1aSopenharmony_ci#include "codec_internal.h"
28cabdff1aSopenharmony_ci#include "encode.h"
29cabdff1aSopenharmony_ci#include "packet_internal.h"
30cabdff1aSopenharmony_ci#include "snow_dwt.h"
31cabdff1aSopenharmony_ci#include "snow.h"
32cabdff1aSopenharmony_ci
33cabdff1aSopenharmony_ci#include "rangecoder.h"
34cabdff1aSopenharmony_ci#include "mathops.h"
35cabdff1aSopenharmony_ci
36cabdff1aSopenharmony_ci#include "mpegvideo.h"
37cabdff1aSopenharmony_ci#include "h263enc.h"
38cabdff1aSopenharmony_ci
39cabdff1aSopenharmony_cistatic av_cold int encode_init(AVCodecContext *avctx)
40cabdff1aSopenharmony_ci{
41cabdff1aSopenharmony_ci    SnowContext *s = avctx->priv_data;
42cabdff1aSopenharmony_ci    int plane_index, ret;
43cabdff1aSopenharmony_ci    int i;
44cabdff1aSopenharmony_ci
45cabdff1aSopenharmony_ci    if(s->pred == DWT_97
46cabdff1aSopenharmony_ci       && (avctx->flags & AV_CODEC_FLAG_QSCALE)
47cabdff1aSopenharmony_ci       && avctx->global_quality == 0){
48cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "The 9/7 wavelet is incompatible with lossless mode.\n");
49cabdff1aSopenharmony_ci        return AVERROR(EINVAL);
50cabdff1aSopenharmony_ci    }
51cabdff1aSopenharmony_ci
52cabdff1aSopenharmony_ci    s->spatial_decomposition_type= s->pred; //FIXME add decorrelator type r transform_type
53cabdff1aSopenharmony_ci
54cabdff1aSopenharmony_ci    s->mv_scale       = (avctx->flags & AV_CODEC_FLAG_QPEL) ? 2 : 4;
55cabdff1aSopenharmony_ci    s->block_max_depth= (avctx->flags & AV_CODEC_FLAG_4MV ) ? 1 : 0;
56cabdff1aSopenharmony_ci
57cabdff1aSopenharmony_ci    for(plane_index=0; plane_index<3; plane_index++){
58cabdff1aSopenharmony_ci        s->plane[plane_index].diag_mc= 1;
59cabdff1aSopenharmony_ci        s->plane[plane_index].htaps= 6;
60cabdff1aSopenharmony_ci        s->plane[plane_index].hcoeff[0]=  40;
61cabdff1aSopenharmony_ci        s->plane[plane_index].hcoeff[1]= -10;
62cabdff1aSopenharmony_ci        s->plane[plane_index].hcoeff[2]=   2;
63cabdff1aSopenharmony_ci        s->plane[plane_index].fast_mc= 1;
64cabdff1aSopenharmony_ci    }
65cabdff1aSopenharmony_ci
66cabdff1aSopenharmony_ci    if ((ret = ff_snow_common_init(avctx)) < 0) {
67cabdff1aSopenharmony_ci        return ret;
68cabdff1aSopenharmony_ci    }
69cabdff1aSopenharmony_ci    ff_mpegvideoencdsp_init(&s->mpvencdsp, avctx);
70cabdff1aSopenharmony_ci
71cabdff1aSopenharmony_ci    ff_snow_alloc_blocks(s);
72cabdff1aSopenharmony_ci
73cabdff1aSopenharmony_ci    s->version=0;
74cabdff1aSopenharmony_ci
75cabdff1aSopenharmony_ci    s->m.avctx   = avctx;
76cabdff1aSopenharmony_ci    s->m.bit_rate= avctx->bit_rate;
77cabdff1aSopenharmony_ci    s->m.lmin    = avctx->mb_lmin;
78cabdff1aSopenharmony_ci    s->m.lmax    = avctx->mb_lmax;
79cabdff1aSopenharmony_ci    s->m.mb_num  = (avctx->width * avctx->height + 255) / 256; // For ratecontrol
80cabdff1aSopenharmony_ci
81cabdff1aSopenharmony_ci    s->m.me.temp      =
82cabdff1aSopenharmony_ci    s->m.me.scratchpad = av_calloc(avctx->width + 64, 2*16*2*sizeof(uint8_t));
83cabdff1aSopenharmony_ci    s->m.me.map       = av_mallocz(ME_MAP_SIZE*sizeof(uint32_t));
84cabdff1aSopenharmony_ci    s->m.me.score_map = av_mallocz(ME_MAP_SIZE*sizeof(uint32_t));
85cabdff1aSopenharmony_ci    s->m.sc.obmc_scratchpad= av_mallocz(MB_SIZE*MB_SIZE*12*sizeof(uint32_t));
86cabdff1aSopenharmony_ci    if (!s->m.me.scratchpad || !s->m.me.map || !s->m.me.score_map || !s->m.sc.obmc_scratchpad)
87cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
88cabdff1aSopenharmony_ci
89cabdff1aSopenharmony_ci    ff_h263_encode_init(&s->m); //mv_penalty
90cabdff1aSopenharmony_ci
91cabdff1aSopenharmony_ci    s->max_ref_frames = av_clip(avctx->refs, 1, MAX_REF_FRAMES);
92cabdff1aSopenharmony_ci
93cabdff1aSopenharmony_ci    if(avctx->flags&AV_CODEC_FLAG_PASS1){
94cabdff1aSopenharmony_ci        if(!avctx->stats_out)
95cabdff1aSopenharmony_ci            avctx->stats_out = av_mallocz(256);
96cabdff1aSopenharmony_ci
97cabdff1aSopenharmony_ci        if (!avctx->stats_out)
98cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
99cabdff1aSopenharmony_ci    }
100cabdff1aSopenharmony_ci    if((avctx->flags&AV_CODEC_FLAG_PASS2) || !(avctx->flags&AV_CODEC_FLAG_QSCALE)){
101cabdff1aSopenharmony_ci        ret = ff_rate_control_init(&s->m);
102cabdff1aSopenharmony_ci        if(ret < 0)
103cabdff1aSopenharmony_ci            return ret;
104cabdff1aSopenharmony_ci    }
105cabdff1aSopenharmony_ci    s->pass1_rc= !(avctx->flags & (AV_CODEC_FLAG_QSCALE|AV_CODEC_FLAG_PASS2));
106cabdff1aSopenharmony_ci
107cabdff1aSopenharmony_ci    switch(avctx->pix_fmt){
108cabdff1aSopenharmony_ci    case AV_PIX_FMT_YUV444P:
109cabdff1aSopenharmony_ci//    case AV_PIX_FMT_YUV422P:
110cabdff1aSopenharmony_ci    case AV_PIX_FMT_YUV420P:
111cabdff1aSopenharmony_ci//    case AV_PIX_FMT_YUV411P:
112cabdff1aSopenharmony_ci    case AV_PIX_FMT_YUV410P:
113cabdff1aSopenharmony_ci        s->nb_planes = 3;
114cabdff1aSopenharmony_ci        s->colorspace_type= 0;
115cabdff1aSopenharmony_ci        break;
116cabdff1aSopenharmony_ci    case AV_PIX_FMT_GRAY8:
117cabdff1aSopenharmony_ci        s->nb_planes = 1;
118cabdff1aSopenharmony_ci        s->colorspace_type = 1;
119cabdff1aSopenharmony_ci        break;
120cabdff1aSopenharmony_ci/*    case AV_PIX_FMT_RGB32:
121cabdff1aSopenharmony_ci        s->colorspace= 1;
122cabdff1aSopenharmony_ci        break;*/
123cabdff1aSopenharmony_ci    }
124cabdff1aSopenharmony_ci
125cabdff1aSopenharmony_ci    ret = av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt, &s->chroma_h_shift,
126cabdff1aSopenharmony_ci                                           &s->chroma_v_shift);
127cabdff1aSopenharmony_ci    if (ret)
128cabdff1aSopenharmony_ci        return ret;
129cabdff1aSopenharmony_ci
130cabdff1aSopenharmony_ci    ret  = ff_set_cmp(&s->mecc, s->mecc.me_cmp, s->avctx->me_cmp);
131cabdff1aSopenharmony_ci    ret |= ff_set_cmp(&s->mecc, s->mecc.me_sub_cmp, s->avctx->me_sub_cmp);
132cabdff1aSopenharmony_ci    if (ret < 0)
133cabdff1aSopenharmony_ci        return AVERROR(EINVAL);
134cabdff1aSopenharmony_ci
135cabdff1aSopenharmony_ci    s->input_picture = av_frame_alloc();
136cabdff1aSopenharmony_ci    if (!s->input_picture)
137cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
138cabdff1aSopenharmony_ci
139cabdff1aSopenharmony_ci    if ((ret = ff_snow_get_buffer(s, s->input_picture)) < 0)
140cabdff1aSopenharmony_ci        return ret;
141cabdff1aSopenharmony_ci
142cabdff1aSopenharmony_ci    if(s->motion_est == FF_ME_ITER){
143cabdff1aSopenharmony_ci        int size= s->b_width * s->b_height << 2*s->block_max_depth;
144cabdff1aSopenharmony_ci        for(i=0; i<s->max_ref_frames; i++){
145cabdff1aSopenharmony_ci            s->ref_mvs[i]    = av_calloc(size, sizeof(*s->ref_mvs[i]));
146cabdff1aSopenharmony_ci            s->ref_scores[i] = av_calloc(size, sizeof(*s->ref_scores[i]));
147cabdff1aSopenharmony_ci            if (!s->ref_mvs[i] || !s->ref_scores[i])
148cabdff1aSopenharmony_ci                return AVERROR(ENOMEM);
149cabdff1aSopenharmony_ci        }
150cabdff1aSopenharmony_ci    }
151cabdff1aSopenharmony_ci
152cabdff1aSopenharmony_ci    return 0;
153cabdff1aSopenharmony_ci}
154cabdff1aSopenharmony_ci
155cabdff1aSopenharmony_ci//near copy & paste from dsputil, FIXME
156cabdff1aSopenharmony_cistatic int pix_sum(uint8_t * pix, int line_size, int w, int h)
157cabdff1aSopenharmony_ci{
158cabdff1aSopenharmony_ci    int s, i, j;
159cabdff1aSopenharmony_ci
160cabdff1aSopenharmony_ci    s = 0;
161cabdff1aSopenharmony_ci    for (i = 0; i < h; i++) {
162cabdff1aSopenharmony_ci        for (j = 0; j < w; j++) {
163cabdff1aSopenharmony_ci            s += pix[0];
164cabdff1aSopenharmony_ci            pix ++;
165cabdff1aSopenharmony_ci        }
166cabdff1aSopenharmony_ci        pix += line_size - w;
167cabdff1aSopenharmony_ci    }
168cabdff1aSopenharmony_ci    return s;
169cabdff1aSopenharmony_ci}
170cabdff1aSopenharmony_ci
171cabdff1aSopenharmony_ci//near copy & paste from dsputil, FIXME
172cabdff1aSopenharmony_cistatic int pix_norm1(uint8_t * pix, int line_size, int w)
173cabdff1aSopenharmony_ci{
174cabdff1aSopenharmony_ci    int s, i, j;
175cabdff1aSopenharmony_ci    const uint32_t *sq = ff_square_tab + 256;
176cabdff1aSopenharmony_ci
177cabdff1aSopenharmony_ci    s = 0;
178cabdff1aSopenharmony_ci    for (i = 0; i < w; i++) {
179cabdff1aSopenharmony_ci        for (j = 0; j < w; j ++) {
180cabdff1aSopenharmony_ci            s += sq[pix[0]];
181cabdff1aSopenharmony_ci            pix ++;
182cabdff1aSopenharmony_ci        }
183cabdff1aSopenharmony_ci        pix += line_size - w;
184cabdff1aSopenharmony_ci    }
185cabdff1aSopenharmony_ci    return s;
186cabdff1aSopenharmony_ci}
187cabdff1aSopenharmony_ci
188cabdff1aSopenharmony_cistatic inline int get_penalty_factor(int lambda, int lambda2, int type){
189cabdff1aSopenharmony_ci    switch(type&0xFF){
190cabdff1aSopenharmony_ci    default:
191cabdff1aSopenharmony_ci    case FF_CMP_SAD:
192cabdff1aSopenharmony_ci        return lambda>>FF_LAMBDA_SHIFT;
193cabdff1aSopenharmony_ci    case FF_CMP_DCT:
194cabdff1aSopenharmony_ci        return (3*lambda)>>(FF_LAMBDA_SHIFT+1);
195cabdff1aSopenharmony_ci    case FF_CMP_W53:
196cabdff1aSopenharmony_ci        return (4*lambda)>>(FF_LAMBDA_SHIFT);
197cabdff1aSopenharmony_ci    case FF_CMP_W97:
198cabdff1aSopenharmony_ci        return (2*lambda)>>(FF_LAMBDA_SHIFT);
199cabdff1aSopenharmony_ci    case FF_CMP_SATD:
200cabdff1aSopenharmony_ci    case FF_CMP_DCT264:
201cabdff1aSopenharmony_ci        return (2*lambda)>>FF_LAMBDA_SHIFT;
202cabdff1aSopenharmony_ci    case FF_CMP_RD:
203cabdff1aSopenharmony_ci    case FF_CMP_PSNR:
204cabdff1aSopenharmony_ci    case FF_CMP_SSE:
205cabdff1aSopenharmony_ci    case FF_CMP_NSSE:
206cabdff1aSopenharmony_ci        return lambda2>>FF_LAMBDA_SHIFT;
207cabdff1aSopenharmony_ci    case FF_CMP_BIT:
208cabdff1aSopenharmony_ci        return 1;
209cabdff1aSopenharmony_ci    }
210cabdff1aSopenharmony_ci}
211cabdff1aSopenharmony_ci
212cabdff1aSopenharmony_ci//FIXME copy&paste
213cabdff1aSopenharmony_ci#define P_LEFT P[1]
214cabdff1aSopenharmony_ci#define P_TOP P[2]
215cabdff1aSopenharmony_ci#define P_TOPRIGHT P[3]
216cabdff1aSopenharmony_ci#define P_MEDIAN P[4]
217cabdff1aSopenharmony_ci#define P_MV1 P[9]
218cabdff1aSopenharmony_ci#define FLAG_QPEL   1 //must be 1
219cabdff1aSopenharmony_ci
220cabdff1aSopenharmony_cistatic int encode_q_branch(SnowContext *s, int level, int x, int y){
221cabdff1aSopenharmony_ci    uint8_t p_buffer[1024];
222cabdff1aSopenharmony_ci    uint8_t i_buffer[1024];
223cabdff1aSopenharmony_ci    uint8_t p_state[sizeof(s->block_state)];
224cabdff1aSopenharmony_ci    uint8_t i_state[sizeof(s->block_state)];
225cabdff1aSopenharmony_ci    RangeCoder pc, ic;
226cabdff1aSopenharmony_ci    uint8_t *pbbak= s->c.bytestream;
227cabdff1aSopenharmony_ci    uint8_t *pbbak_start= s->c.bytestream_start;
228cabdff1aSopenharmony_ci    int score, score2, iscore, i_len, p_len, block_s, sum, base_bits;
229cabdff1aSopenharmony_ci    const int w= s->b_width  << s->block_max_depth;
230cabdff1aSopenharmony_ci    const int h= s->b_height << s->block_max_depth;
231cabdff1aSopenharmony_ci    const int rem_depth= s->block_max_depth - level;
232cabdff1aSopenharmony_ci    const int index= (x + y*w) << rem_depth;
233cabdff1aSopenharmony_ci    const int block_w= 1<<(LOG2_MB_SIZE - level);
234cabdff1aSopenharmony_ci    int trx= (x+1)<<rem_depth;
235cabdff1aSopenharmony_ci    int try= (y+1)<<rem_depth;
236cabdff1aSopenharmony_ci    const BlockNode *left  = x ? &s->block[index-1] : &null_block;
237cabdff1aSopenharmony_ci    const BlockNode *top   = y ? &s->block[index-w] : &null_block;
238cabdff1aSopenharmony_ci    const BlockNode *right = trx<w ? &s->block[index+1] : &null_block;
239cabdff1aSopenharmony_ci    const BlockNode *bottom= try<h ? &s->block[index+w] : &null_block;
240cabdff1aSopenharmony_ci    const BlockNode *tl    = y && x ? &s->block[index-w-1] : left;
241cabdff1aSopenharmony_ci    const BlockNode *tr    = y && trx<w && ((x&1)==0 || level==0) ? &s->block[index-w+(1<<rem_depth)] : tl; //FIXME use lt
242cabdff1aSopenharmony_ci    int pl = left->color[0];
243cabdff1aSopenharmony_ci    int pcb= left->color[1];
244cabdff1aSopenharmony_ci    int pcr= left->color[2];
245cabdff1aSopenharmony_ci    int pmx, pmy;
246cabdff1aSopenharmony_ci    int mx=0, my=0;
247cabdff1aSopenharmony_ci    int l,cr,cb;
248cabdff1aSopenharmony_ci    const int stride= s->current_picture->linesize[0];
249cabdff1aSopenharmony_ci    const int uvstride= s->current_picture->linesize[1];
250cabdff1aSopenharmony_ci    uint8_t *current_data[3]= { s->input_picture->data[0] + (x + y*  stride)*block_w,
251cabdff1aSopenharmony_ci                                s->input_picture->data[1] + ((x*block_w)>>s->chroma_h_shift) + ((y*uvstride*block_w)>>s->chroma_v_shift),
252cabdff1aSopenharmony_ci                                s->input_picture->data[2] + ((x*block_w)>>s->chroma_h_shift) + ((y*uvstride*block_w)>>s->chroma_v_shift)};
253cabdff1aSopenharmony_ci    int P[10][2];
254cabdff1aSopenharmony_ci    int16_t last_mv[3][2];
255cabdff1aSopenharmony_ci    int qpel= !!(s->avctx->flags & AV_CODEC_FLAG_QPEL); //unused
256cabdff1aSopenharmony_ci    const int shift= 1+qpel;
257cabdff1aSopenharmony_ci    MotionEstContext *c= &s->m.me;
258cabdff1aSopenharmony_ci    int ref_context= av_log2(2*left->ref) + av_log2(2*top->ref);
259cabdff1aSopenharmony_ci    int mx_context= av_log2(2*FFABS(left->mx - top->mx));
260cabdff1aSopenharmony_ci    int my_context= av_log2(2*FFABS(left->my - top->my));
261cabdff1aSopenharmony_ci    int s_context= 2*left->level + 2*top->level + tl->level + tr->level;
262cabdff1aSopenharmony_ci    int ref, best_ref, ref_score, ref_mx, ref_my;
263cabdff1aSopenharmony_ci    int range = MAX_MV >> (1 + qpel);
264cabdff1aSopenharmony_ci
265cabdff1aSopenharmony_ci    av_assert0(sizeof(s->block_state) >= 256);
266cabdff1aSopenharmony_ci    if(s->keyframe){
267cabdff1aSopenharmony_ci        set_blocks(s, level, x, y, pl, pcb, pcr, 0, 0, 0, BLOCK_INTRA);
268cabdff1aSopenharmony_ci        return 0;
269cabdff1aSopenharmony_ci    }
270cabdff1aSopenharmony_ci
271cabdff1aSopenharmony_ci//    clip predictors / edge ?
272cabdff1aSopenharmony_ci
273cabdff1aSopenharmony_ci    P_LEFT[0]= left->mx;
274cabdff1aSopenharmony_ci    P_LEFT[1]= left->my;
275cabdff1aSopenharmony_ci    P_TOP [0]= top->mx;
276cabdff1aSopenharmony_ci    P_TOP [1]= top->my;
277cabdff1aSopenharmony_ci    P_TOPRIGHT[0]= tr->mx;
278cabdff1aSopenharmony_ci    P_TOPRIGHT[1]= tr->my;
279cabdff1aSopenharmony_ci
280cabdff1aSopenharmony_ci    last_mv[0][0]= s->block[index].mx;
281cabdff1aSopenharmony_ci    last_mv[0][1]= s->block[index].my;
282cabdff1aSopenharmony_ci    last_mv[1][0]= right->mx;
283cabdff1aSopenharmony_ci    last_mv[1][1]= right->my;
284cabdff1aSopenharmony_ci    last_mv[2][0]= bottom->mx;
285cabdff1aSopenharmony_ci    last_mv[2][1]= bottom->my;
286cabdff1aSopenharmony_ci
287cabdff1aSopenharmony_ci    s->m.mb_stride=2;
288cabdff1aSopenharmony_ci    s->m.mb_x=
289cabdff1aSopenharmony_ci    s->m.mb_y= 0;
290cabdff1aSopenharmony_ci    c->skip= 0;
291cabdff1aSopenharmony_ci
292cabdff1aSopenharmony_ci    av_assert1(c->  stride ==   stride);
293cabdff1aSopenharmony_ci    av_assert1(c->uvstride == uvstride);
294cabdff1aSopenharmony_ci
295cabdff1aSopenharmony_ci    c->penalty_factor    = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_cmp);
296cabdff1aSopenharmony_ci    c->sub_penalty_factor= get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_sub_cmp);
297cabdff1aSopenharmony_ci    c->mb_penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->mb_cmp);
298cabdff1aSopenharmony_ci    c->current_mv_penalty= c->mv_penalty[s->m.f_code=1] + MAX_DMV;
299cabdff1aSopenharmony_ci
300cabdff1aSopenharmony_ci    c->xmin = - x*block_w - 16+3;
301cabdff1aSopenharmony_ci    c->ymin = - y*block_w - 16+3;
302cabdff1aSopenharmony_ci    c->xmax = - (x+1)*block_w + (w<<(LOG2_MB_SIZE - s->block_max_depth)) + 16-3;
303cabdff1aSopenharmony_ci    c->ymax = - (y+1)*block_w + (h<<(LOG2_MB_SIZE - s->block_max_depth)) + 16-3;
304cabdff1aSopenharmony_ci
305cabdff1aSopenharmony_ci    c->xmin = FFMAX(c->xmin, -range);
306cabdff1aSopenharmony_ci    c->xmax = FFMIN(c->xmax, range);
307cabdff1aSopenharmony_ci    c->ymin = FFMAX(c->ymin, -range);
308cabdff1aSopenharmony_ci    c->ymax = FFMIN(c->ymax, range);
309cabdff1aSopenharmony_ci
310cabdff1aSopenharmony_ci    if(P_LEFT[0]     > (c->xmax<<shift)) P_LEFT[0]    = (c->xmax<<shift);
311cabdff1aSopenharmony_ci    if(P_LEFT[1]     > (c->ymax<<shift)) P_LEFT[1]    = (c->ymax<<shift);
312cabdff1aSopenharmony_ci    if(P_TOP[0]      > (c->xmax<<shift)) P_TOP[0]     = (c->xmax<<shift);
313cabdff1aSopenharmony_ci    if(P_TOP[1]      > (c->ymax<<shift)) P_TOP[1]     = (c->ymax<<shift);
314cabdff1aSopenharmony_ci    if(P_TOPRIGHT[0] < (c->xmin * (1<<shift))) P_TOPRIGHT[0]= (c->xmin * (1<<shift));
315cabdff1aSopenharmony_ci    if(P_TOPRIGHT[0] > (c->xmax<<shift)) P_TOPRIGHT[0]= (c->xmax<<shift); //due to pmx no clip
316cabdff1aSopenharmony_ci    if(P_TOPRIGHT[1] > (c->ymax<<shift)) P_TOPRIGHT[1]= (c->ymax<<shift);
317cabdff1aSopenharmony_ci
318cabdff1aSopenharmony_ci    P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
319cabdff1aSopenharmony_ci    P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
320cabdff1aSopenharmony_ci
321cabdff1aSopenharmony_ci    if (!y) {
322cabdff1aSopenharmony_ci        c->pred_x= P_LEFT[0];
323cabdff1aSopenharmony_ci        c->pred_y= P_LEFT[1];
324cabdff1aSopenharmony_ci    } else {
325cabdff1aSopenharmony_ci        c->pred_x = P_MEDIAN[0];
326cabdff1aSopenharmony_ci        c->pred_y = P_MEDIAN[1];
327cabdff1aSopenharmony_ci    }
328cabdff1aSopenharmony_ci
329cabdff1aSopenharmony_ci    score= INT_MAX;
330cabdff1aSopenharmony_ci    best_ref= 0;
331cabdff1aSopenharmony_ci    for(ref=0; ref<s->ref_frames; ref++){
332cabdff1aSopenharmony_ci        init_ref(c, current_data, s->last_picture[ref]->data, NULL, block_w*x, block_w*y, 0);
333cabdff1aSopenharmony_ci
334cabdff1aSopenharmony_ci        ref_score= ff_epzs_motion_search(&s->m, &ref_mx, &ref_my, P, 0, /*ref_index*/ 0, last_mv,
335cabdff1aSopenharmony_ci                                         (1<<16)>>shift, level-LOG2_MB_SIZE+4, block_w);
336cabdff1aSopenharmony_ci
337cabdff1aSopenharmony_ci        av_assert2(ref_mx >= c->xmin);
338cabdff1aSopenharmony_ci        av_assert2(ref_mx <= c->xmax);
339cabdff1aSopenharmony_ci        av_assert2(ref_my >= c->ymin);
340cabdff1aSopenharmony_ci        av_assert2(ref_my <= c->ymax);
341cabdff1aSopenharmony_ci
342cabdff1aSopenharmony_ci        ref_score= c->sub_motion_search(&s->m, &ref_mx, &ref_my, ref_score, 0, 0, level-LOG2_MB_SIZE+4, block_w);
343cabdff1aSopenharmony_ci        ref_score= ff_get_mb_score(&s->m, ref_mx, ref_my, 0, 0, level-LOG2_MB_SIZE+4, block_w, 0);
344cabdff1aSopenharmony_ci        ref_score+= 2*av_log2(2*ref)*c->penalty_factor;
345cabdff1aSopenharmony_ci        if(s->ref_mvs[ref]){
346cabdff1aSopenharmony_ci            s->ref_mvs[ref][index][0]= ref_mx;
347cabdff1aSopenharmony_ci            s->ref_mvs[ref][index][1]= ref_my;
348cabdff1aSopenharmony_ci            s->ref_scores[ref][index]= ref_score;
349cabdff1aSopenharmony_ci        }
350cabdff1aSopenharmony_ci        if(score > ref_score){
351cabdff1aSopenharmony_ci            score= ref_score;
352cabdff1aSopenharmony_ci            best_ref= ref;
353cabdff1aSopenharmony_ci            mx= ref_mx;
354cabdff1aSopenharmony_ci            my= ref_my;
355cabdff1aSopenharmony_ci        }
356cabdff1aSopenharmony_ci    }
357cabdff1aSopenharmony_ci    //FIXME if mb_cmp != SSE then intra cannot be compared currently and mb_penalty vs. lambda2
358cabdff1aSopenharmony_ci
359cabdff1aSopenharmony_ci  //  subpel search
360cabdff1aSopenharmony_ci    base_bits= get_rac_count(&s->c) - 8*(s->c.bytestream - s->c.bytestream_start);
361cabdff1aSopenharmony_ci    pc= s->c;
362cabdff1aSopenharmony_ci    pc.bytestream_start=
363cabdff1aSopenharmony_ci    pc.bytestream= p_buffer; //FIXME end/start? and at the other stoo
364cabdff1aSopenharmony_ci    memcpy(p_state, s->block_state, sizeof(s->block_state));
365cabdff1aSopenharmony_ci
366cabdff1aSopenharmony_ci    if(level!=s->block_max_depth)
367cabdff1aSopenharmony_ci        put_rac(&pc, &p_state[4 + s_context], 1);
368cabdff1aSopenharmony_ci    put_rac(&pc, &p_state[1 + left->type + top->type], 0);
369cabdff1aSopenharmony_ci    if(s->ref_frames > 1)
370cabdff1aSopenharmony_ci        put_symbol(&pc, &p_state[128 + 1024 + 32*ref_context], best_ref, 0);
371cabdff1aSopenharmony_ci    pred_mv(s, &pmx, &pmy, best_ref, left, top, tr);
372cabdff1aSopenharmony_ci    put_symbol(&pc, &p_state[128 + 32*(mx_context + 16*!!best_ref)], mx - pmx, 1);
373cabdff1aSopenharmony_ci    put_symbol(&pc, &p_state[128 + 32*(my_context + 16*!!best_ref)], my - pmy, 1);
374cabdff1aSopenharmony_ci    p_len= pc.bytestream - pc.bytestream_start;
375cabdff1aSopenharmony_ci    score += (s->lambda2*(get_rac_count(&pc)-base_bits))>>FF_LAMBDA_SHIFT;
376cabdff1aSopenharmony_ci
377cabdff1aSopenharmony_ci    block_s= block_w*block_w;
378cabdff1aSopenharmony_ci    sum = pix_sum(current_data[0], stride, block_w, block_w);
379cabdff1aSopenharmony_ci    l= (sum + block_s/2)/block_s;
380cabdff1aSopenharmony_ci    iscore = pix_norm1(current_data[0], stride, block_w) - 2*l*sum + l*l*block_s;
381cabdff1aSopenharmony_ci
382cabdff1aSopenharmony_ci    if (s->nb_planes > 2) {
383cabdff1aSopenharmony_ci        block_s= block_w*block_w>>(s->chroma_h_shift + s->chroma_v_shift);
384cabdff1aSopenharmony_ci        sum = pix_sum(current_data[1], uvstride, block_w>>s->chroma_h_shift, block_w>>s->chroma_v_shift);
385cabdff1aSopenharmony_ci        cb= (sum + block_s/2)/block_s;
386cabdff1aSopenharmony_ci    //    iscore += pix_norm1(&current_mb[1][0], uvstride, block_w>>1) - 2*cb*sum + cb*cb*block_s;
387cabdff1aSopenharmony_ci        sum = pix_sum(current_data[2], uvstride, block_w>>s->chroma_h_shift, block_w>>s->chroma_v_shift);
388cabdff1aSopenharmony_ci        cr= (sum + block_s/2)/block_s;
389cabdff1aSopenharmony_ci    //    iscore += pix_norm1(&current_mb[2][0], uvstride, block_w>>1) - 2*cr*sum + cr*cr*block_s;
390cabdff1aSopenharmony_ci    }else
391cabdff1aSopenharmony_ci        cb = cr = 0;
392cabdff1aSopenharmony_ci
393cabdff1aSopenharmony_ci    ic= s->c;
394cabdff1aSopenharmony_ci    ic.bytestream_start=
395cabdff1aSopenharmony_ci    ic.bytestream= i_buffer; //FIXME end/start? and at the other stoo
396cabdff1aSopenharmony_ci    memcpy(i_state, s->block_state, sizeof(s->block_state));
397cabdff1aSopenharmony_ci    if(level!=s->block_max_depth)
398cabdff1aSopenharmony_ci        put_rac(&ic, &i_state[4 + s_context], 1);
399cabdff1aSopenharmony_ci    put_rac(&ic, &i_state[1 + left->type + top->type], 1);
400cabdff1aSopenharmony_ci    put_symbol(&ic, &i_state[32],  l-pl , 1);
401cabdff1aSopenharmony_ci    if (s->nb_planes > 2) {
402cabdff1aSopenharmony_ci        put_symbol(&ic, &i_state[64], cb-pcb, 1);
403cabdff1aSopenharmony_ci        put_symbol(&ic, &i_state[96], cr-pcr, 1);
404cabdff1aSopenharmony_ci    }
405cabdff1aSopenharmony_ci    i_len= ic.bytestream - ic.bytestream_start;
406cabdff1aSopenharmony_ci    iscore += (s->lambda2*(get_rac_count(&ic)-base_bits))>>FF_LAMBDA_SHIFT;
407cabdff1aSopenharmony_ci
408cabdff1aSopenharmony_ci    av_assert1(iscore < 255*255*256 + s->lambda2*10);
409cabdff1aSopenharmony_ci    av_assert1(iscore >= 0);
410cabdff1aSopenharmony_ci    av_assert1(l>=0 && l<=255);
411cabdff1aSopenharmony_ci    av_assert1(pl>=0 && pl<=255);
412cabdff1aSopenharmony_ci
413cabdff1aSopenharmony_ci    if(level==0){
414cabdff1aSopenharmony_ci        int varc= iscore >> 8;
415cabdff1aSopenharmony_ci        int vard= score >> 8;
416cabdff1aSopenharmony_ci        if (vard <= 64 || vard < varc)
417cabdff1aSopenharmony_ci            c->scene_change_score+= ff_sqrt(vard) - ff_sqrt(varc);
418cabdff1aSopenharmony_ci        else
419cabdff1aSopenharmony_ci            c->scene_change_score+= s->m.qscale;
420cabdff1aSopenharmony_ci    }
421cabdff1aSopenharmony_ci
422cabdff1aSopenharmony_ci    if(level!=s->block_max_depth){
423cabdff1aSopenharmony_ci        put_rac(&s->c, &s->block_state[4 + s_context], 0);
424cabdff1aSopenharmony_ci        score2 = encode_q_branch(s, level+1, 2*x+0, 2*y+0);
425cabdff1aSopenharmony_ci        score2+= encode_q_branch(s, level+1, 2*x+1, 2*y+0);
426cabdff1aSopenharmony_ci        score2+= encode_q_branch(s, level+1, 2*x+0, 2*y+1);
427cabdff1aSopenharmony_ci        score2+= encode_q_branch(s, level+1, 2*x+1, 2*y+1);
428cabdff1aSopenharmony_ci        score2+= s->lambda2>>FF_LAMBDA_SHIFT; //FIXME exact split overhead
429cabdff1aSopenharmony_ci
430cabdff1aSopenharmony_ci        if(score2 < score && score2 < iscore)
431cabdff1aSopenharmony_ci            return score2;
432cabdff1aSopenharmony_ci    }
433cabdff1aSopenharmony_ci
434cabdff1aSopenharmony_ci    if(iscore < score){
435cabdff1aSopenharmony_ci        pred_mv(s, &pmx, &pmy, 0, left, top, tr);
436cabdff1aSopenharmony_ci        memcpy(pbbak, i_buffer, i_len);
437cabdff1aSopenharmony_ci        s->c= ic;
438cabdff1aSopenharmony_ci        s->c.bytestream_start= pbbak_start;
439cabdff1aSopenharmony_ci        s->c.bytestream= pbbak + i_len;
440cabdff1aSopenharmony_ci        set_blocks(s, level, x, y, l, cb, cr, pmx, pmy, 0, BLOCK_INTRA);
441cabdff1aSopenharmony_ci        memcpy(s->block_state, i_state, sizeof(s->block_state));
442cabdff1aSopenharmony_ci        return iscore;
443cabdff1aSopenharmony_ci    }else{
444cabdff1aSopenharmony_ci        memcpy(pbbak, p_buffer, p_len);
445cabdff1aSopenharmony_ci        s->c= pc;
446cabdff1aSopenharmony_ci        s->c.bytestream_start= pbbak_start;
447cabdff1aSopenharmony_ci        s->c.bytestream= pbbak + p_len;
448cabdff1aSopenharmony_ci        set_blocks(s, level, x, y, pl, pcb, pcr, mx, my, best_ref, 0);
449cabdff1aSopenharmony_ci        memcpy(s->block_state, p_state, sizeof(s->block_state));
450cabdff1aSopenharmony_ci        return score;
451cabdff1aSopenharmony_ci    }
452cabdff1aSopenharmony_ci}
453cabdff1aSopenharmony_ci
454cabdff1aSopenharmony_cistatic void encode_q_branch2(SnowContext *s, int level, int x, int y){
455cabdff1aSopenharmony_ci    const int w= s->b_width  << s->block_max_depth;
456cabdff1aSopenharmony_ci    const int rem_depth= s->block_max_depth - level;
457cabdff1aSopenharmony_ci    const int index= (x + y*w) << rem_depth;
458cabdff1aSopenharmony_ci    int trx= (x+1)<<rem_depth;
459cabdff1aSopenharmony_ci    BlockNode *b= &s->block[index];
460cabdff1aSopenharmony_ci    const BlockNode *left  = x ? &s->block[index-1] : &null_block;
461cabdff1aSopenharmony_ci    const BlockNode *top   = y ? &s->block[index-w] : &null_block;
462cabdff1aSopenharmony_ci    const BlockNode *tl    = y && x ? &s->block[index-w-1] : left;
463cabdff1aSopenharmony_ci    const BlockNode *tr    = y && trx<w && ((x&1)==0 || level==0) ? &s->block[index-w+(1<<rem_depth)] : tl; //FIXME use lt
464cabdff1aSopenharmony_ci    int pl = left->color[0];
465cabdff1aSopenharmony_ci    int pcb= left->color[1];
466cabdff1aSopenharmony_ci    int pcr= left->color[2];
467cabdff1aSopenharmony_ci    int pmx, pmy;
468cabdff1aSopenharmony_ci    int ref_context= av_log2(2*left->ref) + av_log2(2*top->ref);
469cabdff1aSopenharmony_ci    int mx_context= av_log2(2*FFABS(left->mx - top->mx)) + 16*!!b->ref;
470cabdff1aSopenharmony_ci    int my_context= av_log2(2*FFABS(left->my - top->my)) + 16*!!b->ref;
471cabdff1aSopenharmony_ci    int s_context= 2*left->level + 2*top->level + tl->level + tr->level;
472cabdff1aSopenharmony_ci
473cabdff1aSopenharmony_ci    if(s->keyframe){
474cabdff1aSopenharmony_ci        set_blocks(s, level, x, y, pl, pcb, pcr, 0, 0, 0, BLOCK_INTRA);
475cabdff1aSopenharmony_ci        return;
476cabdff1aSopenharmony_ci    }
477cabdff1aSopenharmony_ci
478cabdff1aSopenharmony_ci    if(level!=s->block_max_depth){
479cabdff1aSopenharmony_ci        if(same_block(b,b+1) && same_block(b,b+w) && same_block(b,b+w+1)){
480cabdff1aSopenharmony_ci            put_rac(&s->c, &s->block_state[4 + s_context], 1);
481cabdff1aSopenharmony_ci        }else{
482cabdff1aSopenharmony_ci            put_rac(&s->c, &s->block_state[4 + s_context], 0);
483cabdff1aSopenharmony_ci            encode_q_branch2(s, level+1, 2*x+0, 2*y+0);
484cabdff1aSopenharmony_ci            encode_q_branch2(s, level+1, 2*x+1, 2*y+0);
485cabdff1aSopenharmony_ci            encode_q_branch2(s, level+1, 2*x+0, 2*y+1);
486cabdff1aSopenharmony_ci            encode_q_branch2(s, level+1, 2*x+1, 2*y+1);
487cabdff1aSopenharmony_ci            return;
488cabdff1aSopenharmony_ci        }
489cabdff1aSopenharmony_ci    }
490cabdff1aSopenharmony_ci    if(b->type & BLOCK_INTRA){
491cabdff1aSopenharmony_ci        pred_mv(s, &pmx, &pmy, 0, left, top, tr);
492cabdff1aSopenharmony_ci        put_rac(&s->c, &s->block_state[1 + (left->type&1) + (top->type&1)], 1);
493cabdff1aSopenharmony_ci        put_symbol(&s->c, &s->block_state[32], b->color[0]-pl , 1);
494cabdff1aSopenharmony_ci        if (s->nb_planes > 2) {
495cabdff1aSopenharmony_ci            put_symbol(&s->c, &s->block_state[64], b->color[1]-pcb, 1);
496cabdff1aSopenharmony_ci            put_symbol(&s->c, &s->block_state[96], b->color[2]-pcr, 1);
497cabdff1aSopenharmony_ci        }
498cabdff1aSopenharmony_ci        set_blocks(s, level, x, y, b->color[0], b->color[1], b->color[2], pmx, pmy, 0, BLOCK_INTRA);
499cabdff1aSopenharmony_ci    }else{
500cabdff1aSopenharmony_ci        pred_mv(s, &pmx, &pmy, b->ref, left, top, tr);
501cabdff1aSopenharmony_ci        put_rac(&s->c, &s->block_state[1 + (left->type&1) + (top->type&1)], 0);
502cabdff1aSopenharmony_ci        if(s->ref_frames > 1)
503cabdff1aSopenharmony_ci            put_symbol(&s->c, &s->block_state[128 + 1024 + 32*ref_context], b->ref, 0);
504cabdff1aSopenharmony_ci        put_symbol(&s->c, &s->block_state[128 + 32*mx_context], b->mx - pmx, 1);
505cabdff1aSopenharmony_ci        put_symbol(&s->c, &s->block_state[128 + 32*my_context], b->my - pmy, 1);
506cabdff1aSopenharmony_ci        set_blocks(s, level, x, y, pl, pcb, pcr, b->mx, b->my, b->ref, 0);
507cabdff1aSopenharmony_ci    }
508cabdff1aSopenharmony_ci}
509cabdff1aSopenharmony_ci
510cabdff1aSopenharmony_cistatic int get_dc(SnowContext *s, int mb_x, int mb_y, int plane_index){
511cabdff1aSopenharmony_ci    int i, x2, y2;
512cabdff1aSopenharmony_ci    Plane *p= &s->plane[plane_index];
513cabdff1aSopenharmony_ci    const int block_size = MB_SIZE >> s->block_max_depth;
514cabdff1aSopenharmony_ci    const int block_w    = plane_index ? block_size>>s->chroma_h_shift : block_size;
515cabdff1aSopenharmony_ci    const int block_h    = plane_index ? block_size>>s->chroma_v_shift : block_size;
516cabdff1aSopenharmony_ci    const uint8_t *obmc  = plane_index ? ff_obmc_tab[s->block_max_depth+s->chroma_h_shift] : ff_obmc_tab[s->block_max_depth];
517cabdff1aSopenharmony_ci    const int obmc_stride= plane_index ? (2*block_size)>>s->chroma_h_shift : 2*block_size;
518cabdff1aSopenharmony_ci    const int ref_stride= s->current_picture->linesize[plane_index];
519cabdff1aSopenharmony_ci    uint8_t *src= s-> input_picture->data[plane_index];
520cabdff1aSopenharmony_ci    IDWTELEM *dst= (IDWTELEM*)s->m.sc.obmc_scratchpad + plane_index*block_size*block_size*4; //FIXME change to unsigned
521cabdff1aSopenharmony_ci    const int b_stride = s->b_width << s->block_max_depth;
522cabdff1aSopenharmony_ci    const int w= p->width;
523cabdff1aSopenharmony_ci    const int h= p->height;
524cabdff1aSopenharmony_ci    int index= mb_x + mb_y*b_stride;
525cabdff1aSopenharmony_ci    BlockNode *b= &s->block[index];
526cabdff1aSopenharmony_ci    BlockNode backup= *b;
527cabdff1aSopenharmony_ci    int ab=0;
528cabdff1aSopenharmony_ci    int aa=0;
529cabdff1aSopenharmony_ci
530cabdff1aSopenharmony_ci    av_assert2(s->chroma_h_shift == s->chroma_v_shift); //obmc stuff above
531cabdff1aSopenharmony_ci
532cabdff1aSopenharmony_ci    b->type|= BLOCK_INTRA;
533cabdff1aSopenharmony_ci    b->color[plane_index]= 0;
534cabdff1aSopenharmony_ci    memset(dst, 0, obmc_stride*obmc_stride*sizeof(IDWTELEM));
535cabdff1aSopenharmony_ci
536cabdff1aSopenharmony_ci    for(i=0; i<4; i++){
537cabdff1aSopenharmony_ci        int mb_x2= mb_x + (i &1) - 1;
538cabdff1aSopenharmony_ci        int mb_y2= mb_y + (i>>1) - 1;
539cabdff1aSopenharmony_ci        int x= block_w*mb_x2 + block_w/2;
540cabdff1aSopenharmony_ci        int y= block_h*mb_y2 + block_h/2;
541cabdff1aSopenharmony_ci
542cabdff1aSopenharmony_ci        add_yblock(s, 0, NULL, dst + (i&1)*block_w + (i>>1)*obmc_stride*block_h, NULL, obmc,
543cabdff1aSopenharmony_ci                    x, y, block_w, block_h, w, h, obmc_stride, ref_stride, obmc_stride, mb_x2, mb_y2, 0, 0, plane_index);
544cabdff1aSopenharmony_ci
545cabdff1aSopenharmony_ci        for(y2= FFMAX(y, 0); y2<FFMIN(h, y+block_h); y2++){
546cabdff1aSopenharmony_ci            for(x2= FFMAX(x, 0); x2<FFMIN(w, x+block_w); x2++){
547cabdff1aSopenharmony_ci                int index= x2-(block_w*mb_x - block_w/2) + (y2-(block_h*mb_y - block_h/2))*obmc_stride;
548cabdff1aSopenharmony_ci                int obmc_v= obmc[index];
549cabdff1aSopenharmony_ci                int d;
550cabdff1aSopenharmony_ci                if(y<0) obmc_v += obmc[index + block_h*obmc_stride];
551cabdff1aSopenharmony_ci                if(x<0) obmc_v += obmc[index + block_w];
552cabdff1aSopenharmony_ci                if(y+block_h>h) obmc_v += obmc[index - block_h*obmc_stride];
553cabdff1aSopenharmony_ci                if(x+block_w>w) obmc_v += obmc[index - block_w];
554cabdff1aSopenharmony_ci                //FIXME precalculate this or simplify it somehow else
555cabdff1aSopenharmony_ci
556cabdff1aSopenharmony_ci                d = -dst[index] + (1<<(FRAC_BITS-1));
557cabdff1aSopenharmony_ci                dst[index] = d;
558cabdff1aSopenharmony_ci                ab += (src[x2 + y2*ref_stride] - (d>>FRAC_BITS)) * obmc_v;
559cabdff1aSopenharmony_ci                aa += obmc_v * obmc_v; //FIXME precalculate this
560cabdff1aSopenharmony_ci            }
561cabdff1aSopenharmony_ci        }
562cabdff1aSopenharmony_ci    }
563cabdff1aSopenharmony_ci    *b= backup;
564cabdff1aSopenharmony_ci
565cabdff1aSopenharmony_ci    return av_clip_uint8( ROUNDED_DIV(ab<<LOG2_OBMC_MAX, aa) ); //FIXME we should not need clipping
566cabdff1aSopenharmony_ci}
567cabdff1aSopenharmony_ci
568cabdff1aSopenharmony_cistatic inline int get_block_bits(SnowContext *s, int x, int y, int w){
569cabdff1aSopenharmony_ci    const int b_stride = s->b_width << s->block_max_depth;
570cabdff1aSopenharmony_ci    const int b_height = s->b_height<< s->block_max_depth;
571cabdff1aSopenharmony_ci    int index= x + y*b_stride;
572cabdff1aSopenharmony_ci    const BlockNode *b     = &s->block[index];
573cabdff1aSopenharmony_ci    const BlockNode *left  = x ? &s->block[index-1] : &null_block;
574cabdff1aSopenharmony_ci    const BlockNode *top   = y ? &s->block[index-b_stride] : &null_block;
575cabdff1aSopenharmony_ci    const BlockNode *tl    = y && x ? &s->block[index-b_stride-1] : left;
576cabdff1aSopenharmony_ci    const BlockNode *tr    = y && x+w<b_stride ? &s->block[index-b_stride+w] : tl;
577cabdff1aSopenharmony_ci    int dmx, dmy;
578cabdff1aSopenharmony_ci//  int mx_context= av_log2(2*FFABS(left->mx - top->mx));
579cabdff1aSopenharmony_ci//  int my_context= av_log2(2*FFABS(left->my - top->my));
580cabdff1aSopenharmony_ci
581cabdff1aSopenharmony_ci    if(x<0 || x>=b_stride || y>=b_height)
582cabdff1aSopenharmony_ci        return 0;
583cabdff1aSopenharmony_ci/*
584cabdff1aSopenharmony_ci1            0      0
585cabdff1aSopenharmony_ci01X          1-2    1
586cabdff1aSopenharmony_ci001XX        3-6    2-3
587cabdff1aSopenharmony_ci0001XXX      7-14   4-7
588cabdff1aSopenharmony_ci00001XXXX   15-30   8-15
589cabdff1aSopenharmony_ci*/
590cabdff1aSopenharmony_ci//FIXME try accurate rate
591cabdff1aSopenharmony_ci//FIXME intra and inter predictors if surrounding blocks are not the same type
592cabdff1aSopenharmony_ci    if(b->type & BLOCK_INTRA){
593cabdff1aSopenharmony_ci        return 3+2*( av_log2(2*FFABS(left->color[0] - b->color[0]))
594cabdff1aSopenharmony_ci                   + av_log2(2*FFABS(left->color[1] - b->color[1]))
595cabdff1aSopenharmony_ci                   + av_log2(2*FFABS(left->color[2] - b->color[2])));
596cabdff1aSopenharmony_ci    }else{
597cabdff1aSopenharmony_ci        pred_mv(s, &dmx, &dmy, b->ref, left, top, tr);
598cabdff1aSopenharmony_ci        dmx-= b->mx;
599cabdff1aSopenharmony_ci        dmy-= b->my;
600cabdff1aSopenharmony_ci        return 2*(1 + av_log2(2*FFABS(dmx)) //FIXME kill the 2* can be merged in lambda
601cabdff1aSopenharmony_ci                    + av_log2(2*FFABS(dmy))
602cabdff1aSopenharmony_ci                    + av_log2(2*b->ref));
603cabdff1aSopenharmony_ci    }
604cabdff1aSopenharmony_ci}
605cabdff1aSopenharmony_ci
606cabdff1aSopenharmony_cistatic int get_block_rd(SnowContext *s, int mb_x, int mb_y, int plane_index, uint8_t (*obmc_edged)[MB_SIZE * 2]){
607cabdff1aSopenharmony_ci    Plane *p= &s->plane[plane_index];
608cabdff1aSopenharmony_ci    const int block_size = MB_SIZE >> s->block_max_depth;
609cabdff1aSopenharmony_ci    const int block_w    = plane_index ? block_size>>s->chroma_h_shift : block_size;
610cabdff1aSopenharmony_ci    const int block_h    = plane_index ? block_size>>s->chroma_v_shift : block_size;
611cabdff1aSopenharmony_ci    const int obmc_stride= plane_index ? (2*block_size)>>s->chroma_h_shift : 2*block_size;
612cabdff1aSopenharmony_ci    const int ref_stride= s->current_picture->linesize[plane_index];
613cabdff1aSopenharmony_ci    uint8_t *dst= s->current_picture->data[plane_index];
614cabdff1aSopenharmony_ci    uint8_t *src= s->  input_picture->data[plane_index];
615cabdff1aSopenharmony_ci    IDWTELEM *pred= (IDWTELEM*)s->m.sc.obmc_scratchpad + plane_index*block_size*block_size*4;
616cabdff1aSopenharmony_ci    uint8_t *cur = s->scratchbuf;
617cabdff1aSopenharmony_ci    uint8_t *tmp = s->emu_edge_buffer;
618cabdff1aSopenharmony_ci    const int b_stride = s->b_width << s->block_max_depth;
619cabdff1aSopenharmony_ci    const int b_height = s->b_height<< s->block_max_depth;
620cabdff1aSopenharmony_ci    const int w= p->width;
621cabdff1aSopenharmony_ci    const int h= p->height;
622cabdff1aSopenharmony_ci    int distortion;
623cabdff1aSopenharmony_ci    int rate= 0;
624cabdff1aSopenharmony_ci    const int penalty_factor= get_penalty_factor(s->lambda, s->lambda2, s->avctx->me_cmp);
625cabdff1aSopenharmony_ci    int sx= block_w*mb_x - block_w/2;
626cabdff1aSopenharmony_ci    int sy= block_h*mb_y - block_h/2;
627cabdff1aSopenharmony_ci    int x0= FFMAX(0,-sx);
628cabdff1aSopenharmony_ci    int y0= FFMAX(0,-sy);
629cabdff1aSopenharmony_ci    int x1= FFMIN(block_w*2, w-sx);
630cabdff1aSopenharmony_ci    int y1= FFMIN(block_h*2, h-sy);
631cabdff1aSopenharmony_ci    int i,x,y;
632cabdff1aSopenharmony_ci
633cabdff1aSopenharmony_ci    av_assert2(s->chroma_h_shift == s->chroma_v_shift); //obmc and square assumtions below chckinhg only block_w
634cabdff1aSopenharmony_ci
635cabdff1aSopenharmony_ci    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);
636cabdff1aSopenharmony_ci
637cabdff1aSopenharmony_ci    for(y=y0; y<y1; y++){
638cabdff1aSopenharmony_ci        const uint8_t *obmc1= obmc_edged[y];
639cabdff1aSopenharmony_ci        const IDWTELEM *pred1 = pred + y*obmc_stride;
640cabdff1aSopenharmony_ci        uint8_t *cur1 = cur + y*ref_stride;
641cabdff1aSopenharmony_ci        uint8_t *dst1 = dst + sx + (sy+y)*ref_stride;
642cabdff1aSopenharmony_ci        for(x=x0; x<x1; x++){
643cabdff1aSopenharmony_ci#if FRAC_BITS >= LOG2_OBMC_MAX
644cabdff1aSopenharmony_ci            int v = (cur1[x] * obmc1[x]) << (FRAC_BITS - LOG2_OBMC_MAX);
645cabdff1aSopenharmony_ci#else
646cabdff1aSopenharmony_ci            int v = (cur1[x] * obmc1[x] + (1<<(LOG2_OBMC_MAX - FRAC_BITS-1))) >> (LOG2_OBMC_MAX - FRAC_BITS);
647cabdff1aSopenharmony_ci#endif
648cabdff1aSopenharmony_ci            v = (v + pred1[x]) >> FRAC_BITS;
649cabdff1aSopenharmony_ci            if(v&(~255)) v= ~(v>>31);
650cabdff1aSopenharmony_ci            dst1[x] = v;
651cabdff1aSopenharmony_ci        }
652cabdff1aSopenharmony_ci    }
653cabdff1aSopenharmony_ci
654cabdff1aSopenharmony_ci    /* copy the regions where obmc[] = (uint8_t)256 */
655cabdff1aSopenharmony_ci    if(LOG2_OBMC_MAX == 8
656cabdff1aSopenharmony_ci        && (mb_x == 0 || mb_x == b_stride-1)
657cabdff1aSopenharmony_ci        && (mb_y == 0 || mb_y == b_height-1)){
658cabdff1aSopenharmony_ci        if(mb_x == 0)
659cabdff1aSopenharmony_ci            x1 = block_w;
660cabdff1aSopenharmony_ci        else
661cabdff1aSopenharmony_ci            x0 = block_w;
662cabdff1aSopenharmony_ci        if(mb_y == 0)
663cabdff1aSopenharmony_ci            y1 = block_h;
664cabdff1aSopenharmony_ci        else
665cabdff1aSopenharmony_ci            y0 = block_h;
666cabdff1aSopenharmony_ci        for(y=y0; y<y1; y++)
667cabdff1aSopenharmony_ci            memcpy(dst + sx+x0 + (sy+y)*ref_stride, cur + x0 + y*ref_stride, x1-x0);
668cabdff1aSopenharmony_ci    }
669cabdff1aSopenharmony_ci
670cabdff1aSopenharmony_ci    if(block_w==16){
671cabdff1aSopenharmony_ci        /* FIXME rearrange dsputil to fit 32x32 cmp functions */
672cabdff1aSopenharmony_ci        /* FIXME check alignment of the cmp wavelet vs the encoding wavelet */
673cabdff1aSopenharmony_ci        /* FIXME cmps overlap but do not cover the wavelet's whole support.
674cabdff1aSopenharmony_ci         * So improving the score of one block is not strictly guaranteed
675cabdff1aSopenharmony_ci         * to improve the score of the whole frame, thus iterative motion
676cabdff1aSopenharmony_ci         * estimation does not always converge. */
677cabdff1aSopenharmony_ci        if(s->avctx->me_cmp == FF_CMP_W97)
678cabdff1aSopenharmony_ci            distortion = ff_w97_32_c(&s->m, src + sx + sy*ref_stride, dst + sx + sy*ref_stride, ref_stride, 32);
679cabdff1aSopenharmony_ci        else if(s->avctx->me_cmp == FF_CMP_W53)
680cabdff1aSopenharmony_ci            distortion = ff_w53_32_c(&s->m, src + sx + sy*ref_stride, dst + sx + sy*ref_stride, ref_stride, 32);
681cabdff1aSopenharmony_ci        else{
682cabdff1aSopenharmony_ci            distortion = 0;
683cabdff1aSopenharmony_ci            for(i=0; i<4; i++){
684cabdff1aSopenharmony_ci                int off = sx+16*(i&1) + (sy+16*(i>>1))*ref_stride;
685cabdff1aSopenharmony_ci                distortion += s->mecc.me_cmp[0](&s->m, src + off, dst + off, ref_stride, 16);
686cabdff1aSopenharmony_ci            }
687cabdff1aSopenharmony_ci        }
688cabdff1aSopenharmony_ci    }else{
689cabdff1aSopenharmony_ci        av_assert2(block_w==8);
690cabdff1aSopenharmony_ci        distortion = s->mecc.me_cmp[0](&s->m, src + sx + sy*ref_stride, dst + sx + sy*ref_stride, ref_stride, block_w*2);
691cabdff1aSopenharmony_ci    }
692cabdff1aSopenharmony_ci
693cabdff1aSopenharmony_ci    if(plane_index==0){
694cabdff1aSopenharmony_ci        for(i=0; i<4; i++){
695cabdff1aSopenharmony_ci/* ..RRr
696cabdff1aSopenharmony_ci * .RXx.
697cabdff1aSopenharmony_ci * rxx..
698cabdff1aSopenharmony_ci */
699cabdff1aSopenharmony_ci            rate += get_block_bits(s, mb_x + (i&1) - (i>>1), mb_y + (i>>1), 1);
700cabdff1aSopenharmony_ci        }
701cabdff1aSopenharmony_ci        if(mb_x == b_stride-2)
702cabdff1aSopenharmony_ci            rate += get_block_bits(s, mb_x + 1, mb_y + 1, 1);
703cabdff1aSopenharmony_ci    }
704cabdff1aSopenharmony_ci    return distortion + rate*penalty_factor;
705cabdff1aSopenharmony_ci}
706cabdff1aSopenharmony_ci
707cabdff1aSopenharmony_cistatic int get_4block_rd(SnowContext *s, int mb_x, int mb_y, int plane_index){
708cabdff1aSopenharmony_ci    int i, y2;
709cabdff1aSopenharmony_ci    Plane *p= &s->plane[plane_index];
710cabdff1aSopenharmony_ci    const int block_size = MB_SIZE >> s->block_max_depth;
711cabdff1aSopenharmony_ci    const int block_w    = plane_index ? block_size>>s->chroma_h_shift : block_size;
712cabdff1aSopenharmony_ci    const int block_h    = plane_index ? block_size>>s->chroma_v_shift : block_size;
713cabdff1aSopenharmony_ci    const uint8_t *obmc  = plane_index ? ff_obmc_tab[s->block_max_depth+s->chroma_h_shift] : ff_obmc_tab[s->block_max_depth];
714cabdff1aSopenharmony_ci    const int obmc_stride= plane_index ? (2*block_size)>>s->chroma_h_shift : 2*block_size;
715cabdff1aSopenharmony_ci    const int ref_stride= s->current_picture->linesize[plane_index];
716cabdff1aSopenharmony_ci    uint8_t *dst= s->current_picture->data[plane_index];
717cabdff1aSopenharmony_ci    uint8_t *src= s-> input_picture->data[plane_index];
718cabdff1aSopenharmony_ci    //FIXME zero_dst is const but add_yblock changes dst if add is 0 (this is never the case for dst=zero_dst
719cabdff1aSopenharmony_ci    // const has only been removed from zero_dst to suppress a warning
720cabdff1aSopenharmony_ci    static IDWTELEM zero_dst[4096]; //FIXME
721cabdff1aSopenharmony_ci    const int b_stride = s->b_width << s->block_max_depth;
722cabdff1aSopenharmony_ci    const int w= p->width;
723cabdff1aSopenharmony_ci    const int h= p->height;
724cabdff1aSopenharmony_ci    int distortion= 0;
725cabdff1aSopenharmony_ci    int rate= 0;
726cabdff1aSopenharmony_ci    const int penalty_factor= get_penalty_factor(s->lambda, s->lambda2, s->avctx->me_cmp);
727cabdff1aSopenharmony_ci
728cabdff1aSopenharmony_ci    av_assert2(s->chroma_h_shift == s->chroma_v_shift); //obmc and square assumtions below
729cabdff1aSopenharmony_ci
730cabdff1aSopenharmony_ci    for(i=0; i<9; i++){
731cabdff1aSopenharmony_ci        int mb_x2= mb_x + (i%3) - 1;
732cabdff1aSopenharmony_ci        int mb_y2= mb_y + (i/3) - 1;
733cabdff1aSopenharmony_ci        int x= block_w*mb_x2 + block_w/2;
734cabdff1aSopenharmony_ci        int y= block_h*mb_y2 + block_h/2;
735cabdff1aSopenharmony_ci
736cabdff1aSopenharmony_ci        add_yblock(s, 0, NULL, zero_dst, dst, obmc,
737cabdff1aSopenharmony_ci                   x, y, block_w, block_h, w, h, /*dst_stride*/0, ref_stride, obmc_stride, mb_x2, mb_y2, 1, 1, plane_index);
738cabdff1aSopenharmony_ci
739cabdff1aSopenharmony_ci        //FIXME find a cleaner/simpler way to skip the outside stuff
740cabdff1aSopenharmony_ci        for(y2= y; y2<0; y2++)
741cabdff1aSopenharmony_ci            memcpy(dst + x + y2*ref_stride, src + x + y2*ref_stride, block_w);
742cabdff1aSopenharmony_ci        for(y2= h; y2<y+block_h; y2++)
743cabdff1aSopenharmony_ci            memcpy(dst + x + y2*ref_stride, src + x + y2*ref_stride, block_w);
744cabdff1aSopenharmony_ci        if(x<0){
745cabdff1aSopenharmony_ci            for(y2= y; y2<y+block_h; y2++)
746cabdff1aSopenharmony_ci                memcpy(dst + x + y2*ref_stride, src + x + y2*ref_stride, -x);
747cabdff1aSopenharmony_ci        }
748cabdff1aSopenharmony_ci        if(x+block_w > w){
749cabdff1aSopenharmony_ci            for(y2= y; y2<y+block_h; y2++)
750cabdff1aSopenharmony_ci                memcpy(dst + w + y2*ref_stride, src + w + y2*ref_stride, x+block_w - w);
751cabdff1aSopenharmony_ci        }
752cabdff1aSopenharmony_ci
753cabdff1aSopenharmony_ci        av_assert1(block_w== 8 || block_w==16);
754cabdff1aSopenharmony_ci        distortion += s->mecc.me_cmp[block_w==8](&s->m, src + x + y*ref_stride, dst + x + y*ref_stride, ref_stride, block_h);
755cabdff1aSopenharmony_ci    }
756cabdff1aSopenharmony_ci
757cabdff1aSopenharmony_ci    if(plane_index==0){
758cabdff1aSopenharmony_ci        BlockNode *b= &s->block[mb_x+mb_y*b_stride];
759cabdff1aSopenharmony_ci        int merged= same_block(b,b+1) && same_block(b,b+b_stride) && same_block(b,b+b_stride+1);
760cabdff1aSopenharmony_ci
761cabdff1aSopenharmony_ci/* ..RRRr
762cabdff1aSopenharmony_ci * .RXXx.
763cabdff1aSopenharmony_ci * .RXXx.
764cabdff1aSopenharmony_ci * rxxx.
765cabdff1aSopenharmony_ci */
766cabdff1aSopenharmony_ci        if(merged)
767cabdff1aSopenharmony_ci            rate = get_block_bits(s, mb_x, mb_y, 2);
768cabdff1aSopenharmony_ci        for(i=merged?4:0; i<9; i++){
769cabdff1aSopenharmony_ci            static const int dxy[9][2] = {{0,0},{1,0},{0,1},{1,1},{2,0},{2,1},{-1,2},{0,2},{1,2}};
770cabdff1aSopenharmony_ci            rate += get_block_bits(s, mb_x + dxy[i][0], mb_y + dxy[i][1], 1);
771cabdff1aSopenharmony_ci        }
772cabdff1aSopenharmony_ci    }
773cabdff1aSopenharmony_ci    return distortion + rate*penalty_factor;
774cabdff1aSopenharmony_ci}
775cabdff1aSopenharmony_ci
776cabdff1aSopenharmony_cistatic int encode_subband_c0run(SnowContext *s, SubBand *b, const IDWTELEM *src, const IDWTELEM *parent, int stride, int orientation){
777cabdff1aSopenharmony_ci    const int w= b->width;
778cabdff1aSopenharmony_ci    const int h= b->height;
779cabdff1aSopenharmony_ci    int x, y;
780cabdff1aSopenharmony_ci
781cabdff1aSopenharmony_ci    if(1){
782cabdff1aSopenharmony_ci        int run=0;
783cabdff1aSopenharmony_ci        int *runs = s->run_buffer;
784cabdff1aSopenharmony_ci        int run_index=0;
785cabdff1aSopenharmony_ci        int max_index;
786cabdff1aSopenharmony_ci
787cabdff1aSopenharmony_ci        for(y=0; y<h; y++){
788cabdff1aSopenharmony_ci            for(x=0; x<w; x++){
789cabdff1aSopenharmony_ci                int v, p=0;
790cabdff1aSopenharmony_ci                int /*ll=0, */l=0, lt=0, t=0, rt=0;
791cabdff1aSopenharmony_ci                v= src[x + y*stride];
792cabdff1aSopenharmony_ci
793cabdff1aSopenharmony_ci                if(y){
794cabdff1aSopenharmony_ci                    t= src[x + (y-1)*stride];
795cabdff1aSopenharmony_ci                    if(x){
796cabdff1aSopenharmony_ci                        lt= src[x - 1 + (y-1)*stride];
797cabdff1aSopenharmony_ci                    }
798cabdff1aSopenharmony_ci                    if(x + 1 < w){
799cabdff1aSopenharmony_ci                        rt= src[x + 1 + (y-1)*stride];
800cabdff1aSopenharmony_ci                    }
801cabdff1aSopenharmony_ci                }
802cabdff1aSopenharmony_ci                if(x){
803cabdff1aSopenharmony_ci                    l= src[x - 1 + y*stride];
804cabdff1aSopenharmony_ci                    /*if(x > 1){
805cabdff1aSopenharmony_ci                        if(orientation==1) ll= src[y + (x-2)*stride];
806cabdff1aSopenharmony_ci                        else               ll= src[x - 2 + y*stride];
807cabdff1aSopenharmony_ci                    }*/
808cabdff1aSopenharmony_ci                }
809cabdff1aSopenharmony_ci                if(parent){
810cabdff1aSopenharmony_ci                    int px= x>>1;
811cabdff1aSopenharmony_ci                    int py= y>>1;
812cabdff1aSopenharmony_ci                    if(px<b->parent->width && py<b->parent->height)
813cabdff1aSopenharmony_ci                        p= parent[px + py*2*stride];
814cabdff1aSopenharmony_ci                }
815cabdff1aSopenharmony_ci                if(!(/*ll|*/l|lt|t|rt|p)){
816cabdff1aSopenharmony_ci                    if(v){
817cabdff1aSopenharmony_ci                        runs[run_index++]= run;
818cabdff1aSopenharmony_ci                        run=0;
819cabdff1aSopenharmony_ci                    }else{
820cabdff1aSopenharmony_ci                        run++;
821cabdff1aSopenharmony_ci                    }
822cabdff1aSopenharmony_ci                }
823cabdff1aSopenharmony_ci            }
824cabdff1aSopenharmony_ci        }
825cabdff1aSopenharmony_ci        max_index= run_index;
826cabdff1aSopenharmony_ci        runs[run_index++]= run;
827cabdff1aSopenharmony_ci        run_index=0;
828cabdff1aSopenharmony_ci        run= runs[run_index++];
829cabdff1aSopenharmony_ci
830cabdff1aSopenharmony_ci        put_symbol2(&s->c, b->state[30], max_index, 0);
831cabdff1aSopenharmony_ci        if(run_index <= max_index)
832cabdff1aSopenharmony_ci            put_symbol2(&s->c, b->state[1], run, 3);
833cabdff1aSopenharmony_ci
834cabdff1aSopenharmony_ci        for(y=0; y<h; y++){
835cabdff1aSopenharmony_ci            if(s->c.bytestream_end - s->c.bytestream < w*40){
836cabdff1aSopenharmony_ci                av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
837cabdff1aSopenharmony_ci                return AVERROR(ENOMEM);
838cabdff1aSopenharmony_ci            }
839cabdff1aSopenharmony_ci            for(x=0; x<w; x++){
840cabdff1aSopenharmony_ci                int v, p=0;
841cabdff1aSopenharmony_ci                int /*ll=0, */l=0, lt=0, t=0, rt=0;
842cabdff1aSopenharmony_ci                v= src[x + y*stride];
843cabdff1aSopenharmony_ci
844cabdff1aSopenharmony_ci                if(y){
845cabdff1aSopenharmony_ci                    t= src[x + (y-1)*stride];
846cabdff1aSopenharmony_ci                    if(x){
847cabdff1aSopenharmony_ci                        lt= src[x - 1 + (y-1)*stride];
848cabdff1aSopenharmony_ci                    }
849cabdff1aSopenharmony_ci                    if(x + 1 < w){
850cabdff1aSopenharmony_ci                        rt= src[x + 1 + (y-1)*stride];
851cabdff1aSopenharmony_ci                    }
852cabdff1aSopenharmony_ci                }
853cabdff1aSopenharmony_ci                if(x){
854cabdff1aSopenharmony_ci                    l= src[x - 1 + y*stride];
855cabdff1aSopenharmony_ci                    /*if(x > 1){
856cabdff1aSopenharmony_ci                        if(orientation==1) ll= src[y + (x-2)*stride];
857cabdff1aSopenharmony_ci                        else               ll= src[x - 2 + y*stride];
858cabdff1aSopenharmony_ci                    }*/
859cabdff1aSopenharmony_ci                }
860cabdff1aSopenharmony_ci                if(parent){
861cabdff1aSopenharmony_ci                    int px= x>>1;
862cabdff1aSopenharmony_ci                    int py= y>>1;
863cabdff1aSopenharmony_ci                    if(px<b->parent->width && py<b->parent->height)
864cabdff1aSopenharmony_ci                        p= parent[px + py*2*stride];
865cabdff1aSopenharmony_ci                }
866cabdff1aSopenharmony_ci                if(/*ll|*/l|lt|t|rt|p){
867cabdff1aSopenharmony_ci                    int context= av_log2(/*FFABS(ll) + */3*FFABS(l) + FFABS(lt) + 2*FFABS(t) + FFABS(rt) + FFABS(p));
868cabdff1aSopenharmony_ci
869cabdff1aSopenharmony_ci                    put_rac(&s->c, &b->state[0][context], !!v);
870cabdff1aSopenharmony_ci                }else{
871cabdff1aSopenharmony_ci                    if(!run){
872cabdff1aSopenharmony_ci                        run= runs[run_index++];
873cabdff1aSopenharmony_ci
874cabdff1aSopenharmony_ci                        if(run_index <= max_index)
875cabdff1aSopenharmony_ci                            put_symbol2(&s->c, b->state[1], run, 3);
876cabdff1aSopenharmony_ci                        av_assert2(v);
877cabdff1aSopenharmony_ci                    }else{
878cabdff1aSopenharmony_ci                        run--;
879cabdff1aSopenharmony_ci                        av_assert2(!v);
880cabdff1aSopenharmony_ci                    }
881cabdff1aSopenharmony_ci                }
882cabdff1aSopenharmony_ci                if(v){
883cabdff1aSopenharmony_ci                    int context= av_log2(/*FFABS(ll) + */3*FFABS(l) + FFABS(lt) + 2*FFABS(t) + FFABS(rt) + FFABS(p));
884cabdff1aSopenharmony_ci                    int l2= 2*FFABS(l) + (l<0);
885cabdff1aSopenharmony_ci                    int t2= 2*FFABS(t) + (t<0);
886cabdff1aSopenharmony_ci
887cabdff1aSopenharmony_ci                    put_symbol2(&s->c, b->state[context + 2], FFABS(v)-1, context-4);
888cabdff1aSopenharmony_ci                    put_rac(&s->c, &b->state[0][16 + 1 + 3 + ff_quant3bA[l2&0xFF] + 3*ff_quant3bA[t2&0xFF]], v<0);
889cabdff1aSopenharmony_ci                }
890cabdff1aSopenharmony_ci            }
891cabdff1aSopenharmony_ci        }
892cabdff1aSopenharmony_ci    }
893cabdff1aSopenharmony_ci    return 0;
894cabdff1aSopenharmony_ci}
895cabdff1aSopenharmony_ci
896cabdff1aSopenharmony_cistatic int encode_subband(SnowContext *s, SubBand *b, const IDWTELEM *src, const IDWTELEM *parent, int stride, int orientation){
897cabdff1aSopenharmony_ci//    encode_subband_qtree(s, b, src, parent, stride, orientation);
898cabdff1aSopenharmony_ci//    encode_subband_z0run(s, b, src, parent, stride, orientation);
899cabdff1aSopenharmony_ci    return encode_subband_c0run(s, b, src, parent, stride, orientation);
900cabdff1aSopenharmony_ci//    encode_subband_dzr(s, b, src, parent, stride, orientation);
901cabdff1aSopenharmony_ci}
902cabdff1aSopenharmony_ci
903cabdff1aSopenharmony_cistatic 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){
904cabdff1aSopenharmony_ci    const int b_stride= s->b_width << s->block_max_depth;
905cabdff1aSopenharmony_ci    BlockNode *block= &s->block[mb_x + mb_y * b_stride];
906cabdff1aSopenharmony_ci    BlockNode backup= *block;
907cabdff1aSopenharmony_ci    unsigned value;
908cabdff1aSopenharmony_ci    int rd, index;
909cabdff1aSopenharmony_ci
910cabdff1aSopenharmony_ci    av_assert2(mb_x>=0 && mb_y>=0);
911cabdff1aSopenharmony_ci    av_assert2(mb_x<b_stride);
912cabdff1aSopenharmony_ci
913cabdff1aSopenharmony_ci    if(intra){
914cabdff1aSopenharmony_ci        block->color[0] = p[0];
915cabdff1aSopenharmony_ci        block->color[1] = p[1];
916cabdff1aSopenharmony_ci        block->color[2] = p[2];
917cabdff1aSopenharmony_ci        block->type |= BLOCK_INTRA;
918cabdff1aSopenharmony_ci    }else{
919cabdff1aSopenharmony_ci        index= (p[0] + 31*p[1]) & (ME_CACHE_SIZE-1);
920cabdff1aSopenharmony_ci        value= s->me_cache_generation + (p[0]>>10) + (p[1]<<6) + (block->ref<<12);
921cabdff1aSopenharmony_ci        if(s->me_cache[index] == value)
922cabdff1aSopenharmony_ci            return 0;
923cabdff1aSopenharmony_ci        s->me_cache[index]= value;
924cabdff1aSopenharmony_ci
925cabdff1aSopenharmony_ci        block->mx= p[0];
926cabdff1aSopenharmony_ci        block->my= p[1];
927cabdff1aSopenharmony_ci        block->type &= ~BLOCK_INTRA;
928cabdff1aSopenharmony_ci    }
929cabdff1aSopenharmony_ci
930cabdff1aSopenharmony_ci    rd= get_block_rd(s, mb_x, mb_y, 0, obmc_edged) + s->intra_penalty * !!intra;
931cabdff1aSopenharmony_ci
932cabdff1aSopenharmony_ci//FIXME chroma
933cabdff1aSopenharmony_ci    if(rd < *best_rd){
934cabdff1aSopenharmony_ci        *best_rd= rd;
935cabdff1aSopenharmony_ci        return 1;
936cabdff1aSopenharmony_ci    }else{
937cabdff1aSopenharmony_ci        *block= backup;
938cabdff1aSopenharmony_ci        return 0;
939cabdff1aSopenharmony_ci    }
940cabdff1aSopenharmony_ci}
941cabdff1aSopenharmony_ci
942cabdff1aSopenharmony_ci/* special case for int[2] args we discard afterwards,
943cabdff1aSopenharmony_ci * fixes compilation problem with gcc 2.95 */
944cabdff1aSopenharmony_cistatic 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){
945cabdff1aSopenharmony_ci    int p[2] = {p0, p1};
946cabdff1aSopenharmony_ci    return check_block(s, mb_x, mb_y, p, 0, obmc_edged, best_rd);
947cabdff1aSopenharmony_ci}
948cabdff1aSopenharmony_ci
949cabdff1aSopenharmony_cistatic av_always_inline int check_4block_inter(SnowContext *s, int mb_x, int mb_y, int p0, int p1, int ref, int *best_rd){
950cabdff1aSopenharmony_ci    const int b_stride= s->b_width << s->block_max_depth;
951cabdff1aSopenharmony_ci    BlockNode *block= &s->block[mb_x + mb_y * b_stride];
952cabdff1aSopenharmony_ci    BlockNode backup[4];
953cabdff1aSopenharmony_ci    unsigned value;
954cabdff1aSopenharmony_ci    int rd, index;
955cabdff1aSopenharmony_ci
956cabdff1aSopenharmony_ci    /* We don't initialize backup[] during variable declaration, because
957cabdff1aSopenharmony_ci     * that fails to compile on MSVC: "cannot convert from 'BlockNode' to
958cabdff1aSopenharmony_ci     * 'int16_t'". */
959cabdff1aSopenharmony_ci    backup[0] = block[0];
960cabdff1aSopenharmony_ci    backup[1] = block[1];
961cabdff1aSopenharmony_ci    backup[2] = block[b_stride];
962cabdff1aSopenharmony_ci    backup[3] = block[b_stride + 1];
963cabdff1aSopenharmony_ci
964cabdff1aSopenharmony_ci    av_assert2(mb_x>=0 && mb_y>=0);
965cabdff1aSopenharmony_ci    av_assert2(mb_x<b_stride);
966cabdff1aSopenharmony_ci    av_assert2(((mb_x|mb_y)&1) == 0);
967cabdff1aSopenharmony_ci
968cabdff1aSopenharmony_ci    index= (p0 + 31*p1) & (ME_CACHE_SIZE-1);
969cabdff1aSopenharmony_ci    value= s->me_cache_generation + (p0>>10) + (p1<<6) + (block->ref<<12);
970cabdff1aSopenharmony_ci    if(s->me_cache[index] == value)
971cabdff1aSopenharmony_ci        return 0;
972cabdff1aSopenharmony_ci    s->me_cache[index]= value;
973cabdff1aSopenharmony_ci
974cabdff1aSopenharmony_ci    block->mx= p0;
975cabdff1aSopenharmony_ci    block->my= p1;
976cabdff1aSopenharmony_ci    block->ref= ref;
977cabdff1aSopenharmony_ci    block->type &= ~BLOCK_INTRA;
978cabdff1aSopenharmony_ci    block[1]= block[b_stride]= block[b_stride+1]= *block;
979cabdff1aSopenharmony_ci
980cabdff1aSopenharmony_ci    rd= get_4block_rd(s, mb_x, mb_y, 0);
981cabdff1aSopenharmony_ci
982cabdff1aSopenharmony_ci//FIXME chroma
983cabdff1aSopenharmony_ci    if(rd < *best_rd){
984cabdff1aSopenharmony_ci        *best_rd= rd;
985cabdff1aSopenharmony_ci        return 1;
986cabdff1aSopenharmony_ci    }else{
987cabdff1aSopenharmony_ci        block[0]= backup[0];
988cabdff1aSopenharmony_ci        block[1]= backup[1];
989cabdff1aSopenharmony_ci        block[b_stride]= backup[2];
990cabdff1aSopenharmony_ci        block[b_stride+1]= backup[3];
991cabdff1aSopenharmony_ci        return 0;
992cabdff1aSopenharmony_ci    }
993cabdff1aSopenharmony_ci}
994cabdff1aSopenharmony_ci
995cabdff1aSopenharmony_cistatic void iterative_me(SnowContext *s){
996cabdff1aSopenharmony_ci    int pass, mb_x, mb_y;
997cabdff1aSopenharmony_ci    const int b_width = s->b_width  << s->block_max_depth;
998cabdff1aSopenharmony_ci    const int b_height= s->b_height << s->block_max_depth;
999cabdff1aSopenharmony_ci    const int b_stride= b_width;
1000cabdff1aSopenharmony_ci    int color[3];
1001cabdff1aSopenharmony_ci
1002cabdff1aSopenharmony_ci    {
1003cabdff1aSopenharmony_ci        RangeCoder r = s->c;
1004cabdff1aSopenharmony_ci        uint8_t state[sizeof(s->block_state)];
1005cabdff1aSopenharmony_ci        memcpy(state, s->block_state, sizeof(s->block_state));
1006cabdff1aSopenharmony_ci        for(mb_y= 0; mb_y<s->b_height; mb_y++)
1007cabdff1aSopenharmony_ci            for(mb_x= 0; mb_x<s->b_width; mb_x++)
1008cabdff1aSopenharmony_ci                encode_q_branch(s, 0, mb_x, mb_y);
1009cabdff1aSopenharmony_ci        s->c = r;
1010cabdff1aSopenharmony_ci        memcpy(s->block_state, state, sizeof(s->block_state));
1011cabdff1aSopenharmony_ci    }
1012cabdff1aSopenharmony_ci
1013cabdff1aSopenharmony_ci    for(pass=0; pass<25; pass++){
1014cabdff1aSopenharmony_ci        int change= 0;
1015cabdff1aSopenharmony_ci
1016cabdff1aSopenharmony_ci        for(mb_y= 0; mb_y<b_height; mb_y++){
1017cabdff1aSopenharmony_ci            for(mb_x= 0; mb_x<b_width; mb_x++){
1018cabdff1aSopenharmony_ci                int dia_change, i, j, ref;
1019cabdff1aSopenharmony_ci                int best_rd= INT_MAX, ref_rd;
1020cabdff1aSopenharmony_ci                BlockNode backup, ref_b;
1021cabdff1aSopenharmony_ci                const int index= mb_x + mb_y * b_stride;
1022cabdff1aSopenharmony_ci                BlockNode *block= &s->block[index];
1023cabdff1aSopenharmony_ci                BlockNode *tb =                   mb_y            ? &s->block[index-b_stride  ] : NULL;
1024cabdff1aSopenharmony_ci                BlockNode *lb = mb_x                              ? &s->block[index         -1] : NULL;
1025cabdff1aSopenharmony_ci                BlockNode *rb = mb_x+1<b_width                    ? &s->block[index         +1] : NULL;
1026cabdff1aSopenharmony_ci                BlockNode *bb =                   mb_y+1<b_height ? &s->block[index+b_stride  ] : NULL;
1027cabdff1aSopenharmony_ci                BlockNode *tlb= mb_x           && mb_y            ? &s->block[index-b_stride-1] : NULL;
1028cabdff1aSopenharmony_ci                BlockNode *trb= mb_x+1<b_width && mb_y            ? &s->block[index-b_stride+1] : NULL;
1029cabdff1aSopenharmony_ci                BlockNode *blb= mb_x           && mb_y+1<b_height ? &s->block[index+b_stride-1] : NULL;
1030cabdff1aSopenharmony_ci                BlockNode *brb= mb_x+1<b_width && mb_y+1<b_height ? &s->block[index+b_stride+1] : NULL;
1031cabdff1aSopenharmony_ci                const int b_w= (MB_SIZE >> s->block_max_depth);
1032cabdff1aSopenharmony_ci                uint8_t obmc_edged[MB_SIZE * 2][MB_SIZE * 2];
1033cabdff1aSopenharmony_ci
1034cabdff1aSopenharmony_ci                if(pass && (block->type & BLOCK_OPT))
1035cabdff1aSopenharmony_ci                    continue;
1036cabdff1aSopenharmony_ci                block->type |= BLOCK_OPT;
1037cabdff1aSopenharmony_ci
1038cabdff1aSopenharmony_ci                backup= *block;
1039cabdff1aSopenharmony_ci
1040cabdff1aSopenharmony_ci                if(!s->me_cache_generation)
1041cabdff1aSopenharmony_ci                    memset(s->me_cache, 0, sizeof(s->me_cache));
1042cabdff1aSopenharmony_ci                s->me_cache_generation += 1<<22;
1043cabdff1aSopenharmony_ci
1044cabdff1aSopenharmony_ci                //FIXME precalculate
1045cabdff1aSopenharmony_ci                {
1046cabdff1aSopenharmony_ci                    int x, y;
1047cabdff1aSopenharmony_ci                    for (y = 0; y < b_w * 2; y++)
1048cabdff1aSopenharmony_ci                        memcpy(obmc_edged[y], ff_obmc_tab[s->block_max_depth] + y * b_w * 2, b_w * 2);
1049cabdff1aSopenharmony_ci                    if(mb_x==0)
1050cabdff1aSopenharmony_ci                        for(y=0; y<b_w*2; y++)
1051cabdff1aSopenharmony_ci                            memset(obmc_edged[y], obmc_edged[y][0] + obmc_edged[y][b_w-1], b_w);
1052cabdff1aSopenharmony_ci                    if(mb_x==b_stride-1)
1053cabdff1aSopenharmony_ci                        for(y=0; y<b_w*2; y++)
1054cabdff1aSopenharmony_ci                            memset(obmc_edged[y]+b_w, obmc_edged[y][b_w] + obmc_edged[y][b_w*2-1], b_w);
1055cabdff1aSopenharmony_ci                    if(mb_y==0){
1056cabdff1aSopenharmony_ci                        for(x=0; x<b_w*2; x++)
1057cabdff1aSopenharmony_ci                            obmc_edged[0][x] += obmc_edged[b_w-1][x];
1058cabdff1aSopenharmony_ci                        for(y=1; y<b_w; y++)
1059cabdff1aSopenharmony_ci                            memcpy(obmc_edged[y], obmc_edged[0], b_w*2);
1060cabdff1aSopenharmony_ci                    }
1061cabdff1aSopenharmony_ci                    if(mb_y==b_height-1){
1062cabdff1aSopenharmony_ci                        for(x=0; x<b_w*2; x++)
1063cabdff1aSopenharmony_ci                            obmc_edged[b_w*2-1][x] += obmc_edged[b_w][x];
1064cabdff1aSopenharmony_ci                        for(y=b_w; y<b_w*2-1; y++)
1065cabdff1aSopenharmony_ci                            memcpy(obmc_edged[y], obmc_edged[b_w*2-1], b_w*2);
1066cabdff1aSopenharmony_ci                    }
1067cabdff1aSopenharmony_ci                }
1068cabdff1aSopenharmony_ci
1069cabdff1aSopenharmony_ci                //skip stuff outside the picture
1070cabdff1aSopenharmony_ci                if(mb_x==0 || mb_y==0 || mb_x==b_width-1 || mb_y==b_height-1){
1071cabdff1aSopenharmony_ci                    uint8_t *src= s->  input_picture->data[0];
1072cabdff1aSopenharmony_ci                    uint8_t *dst= s->current_picture->data[0];
1073cabdff1aSopenharmony_ci                    const int stride= s->current_picture->linesize[0];
1074cabdff1aSopenharmony_ci                    const int block_w= MB_SIZE >> s->block_max_depth;
1075cabdff1aSopenharmony_ci                    const int block_h= MB_SIZE >> s->block_max_depth;
1076cabdff1aSopenharmony_ci                    const int sx= block_w*mb_x - block_w/2;
1077cabdff1aSopenharmony_ci                    const int sy= block_h*mb_y - block_h/2;
1078cabdff1aSopenharmony_ci                    const int w= s->plane[0].width;
1079cabdff1aSopenharmony_ci                    const int h= s->plane[0].height;
1080cabdff1aSopenharmony_ci                    int y;
1081cabdff1aSopenharmony_ci
1082cabdff1aSopenharmony_ci                    for(y=sy; y<0; y++)
1083cabdff1aSopenharmony_ci                        memcpy(dst + sx + y*stride, src + sx + y*stride, block_w*2);
1084cabdff1aSopenharmony_ci                    for(y=h; y<sy+block_h*2; y++)
1085cabdff1aSopenharmony_ci                        memcpy(dst + sx + y*stride, src + sx + y*stride, block_w*2);
1086cabdff1aSopenharmony_ci                    if(sx<0){
1087cabdff1aSopenharmony_ci                        for(y=sy; y<sy+block_h*2; y++)
1088cabdff1aSopenharmony_ci                            memcpy(dst + sx + y*stride, src + sx + y*stride, -sx);
1089cabdff1aSopenharmony_ci                    }
1090cabdff1aSopenharmony_ci                    if(sx+block_w*2 > w){
1091cabdff1aSopenharmony_ci                        for(y=sy; y<sy+block_h*2; y++)
1092cabdff1aSopenharmony_ci                            memcpy(dst + w + y*stride, src + w + y*stride, sx+block_w*2 - w);
1093cabdff1aSopenharmony_ci                    }
1094cabdff1aSopenharmony_ci                }
1095cabdff1aSopenharmony_ci
1096cabdff1aSopenharmony_ci                // intra(black) = neighbors' contribution to the current block
1097cabdff1aSopenharmony_ci                for(i=0; i < s->nb_planes; i++)
1098cabdff1aSopenharmony_ci                    color[i]= get_dc(s, mb_x, mb_y, i);
1099cabdff1aSopenharmony_ci
1100cabdff1aSopenharmony_ci                // get previous score (cannot be cached due to OBMC)
1101cabdff1aSopenharmony_ci                if(pass > 0 && (block->type&BLOCK_INTRA)){
1102cabdff1aSopenharmony_ci                    int color0[3]= {block->color[0], block->color[1], block->color[2]};
1103cabdff1aSopenharmony_ci                    check_block(s, mb_x, mb_y, color0, 1, obmc_edged, &best_rd);
1104cabdff1aSopenharmony_ci                }else
1105cabdff1aSopenharmony_ci                    check_block_inter(s, mb_x, mb_y, block->mx, block->my, obmc_edged, &best_rd);
1106cabdff1aSopenharmony_ci
1107cabdff1aSopenharmony_ci                ref_b= *block;
1108cabdff1aSopenharmony_ci                ref_rd= best_rd;
1109cabdff1aSopenharmony_ci                for(ref=0; ref < s->ref_frames; ref++){
1110cabdff1aSopenharmony_ci                    int16_t (*mvr)[2]= &s->ref_mvs[ref][index];
1111cabdff1aSopenharmony_ci                    if(s->ref_scores[ref][index] > s->ref_scores[ref_b.ref][index]*3/2) //FIXME tune threshold
1112cabdff1aSopenharmony_ci                        continue;
1113cabdff1aSopenharmony_ci                    block->ref= ref;
1114cabdff1aSopenharmony_ci                    best_rd= INT_MAX;
1115cabdff1aSopenharmony_ci
1116cabdff1aSopenharmony_ci                    check_block_inter(s, mb_x, mb_y, mvr[0][0], mvr[0][1], obmc_edged, &best_rd);
1117cabdff1aSopenharmony_ci                    check_block_inter(s, mb_x, mb_y, 0, 0, obmc_edged, &best_rd);
1118cabdff1aSopenharmony_ci                    if(tb)
1119cabdff1aSopenharmony_ci                        check_block_inter(s, mb_x, mb_y, mvr[-b_stride][0], mvr[-b_stride][1], obmc_edged, &best_rd);
1120cabdff1aSopenharmony_ci                    if(lb)
1121cabdff1aSopenharmony_ci                        check_block_inter(s, mb_x, mb_y, mvr[-1][0], mvr[-1][1], obmc_edged, &best_rd);
1122cabdff1aSopenharmony_ci                    if(rb)
1123cabdff1aSopenharmony_ci                        check_block_inter(s, mb_x, mb_y, mvr[1][0], mvr[1][1], obmc_edged, &best_rd);
1124cabdff1aSopenharmony_ci                    if(bb)
1125cabdff1aSopenharmony_ci                        check_block_inter(s, mb_x, mb_y, mvr[b_stride][0], mvr[b_stride][1], obmc_edged, &best_rd);
1126cabdff1aSopenharmony_ci
1127cabdff1aSopenharmony_ci                    /* fullpel ME */
1128cabdff1aSopenharmony_ci                    //FIXME avoid subpel interpolation / round to nearest integer
1129cabdff1aSopenharmony_ci                    do{
1130cabdff1aSopenharmony_ci                        int newx = block->mx;
1131cabdff1aSopenharmony_ci                        int newy = block->my;
1132cabdff1aSopenharmony_ci                        int dia_size = s->iterative_dia_size ? s->iterative_dia_size : FFMAX(s->avctx->dia_size, 1);
1133cabdff1aSopenharmony_ci                        dia_change=0;
1134cabdff1aSopenharmony_ci                        for(i=0; i < dia_size; i++){
1135cabdff1aSopenharmony_ci                            for(j=0; j<i; j++){
1136cabdff1aSopenharmony_ci                                dia_change |= check_block_inter(s, mb_x, mb_y, newx+4*(i-j), newy+(4*j), obmc_edged, &best_rd);
1137cabdff1aSopenharmony_ci                                dia_change |= check_block_inter(s, mb_x, mb_y, newx-4*(i-j), newy-(4*j), obmc_edged, &best_rd);
1138cabdff1aSopenharmony_ci                                dia_change |= check_block_inter(s, mb_x, mb_y, newx-(4*j), newy+4*(i-j), obmc_edged, &best_rd);
1139cabdff1aSopenharmony_ci                                dia_change |= check_block_inter(s, mb_x, mb_y, newx+(4*j), newy-4*(i-j), obmc_edged, &best_rd);
1140cabdff1aSopenharmony_ci                            }
1141cabdff1aSopenharmony_ci                        }
1142cabdff1aSopenharmony_ci                    }while(dia_change);
1143cabdff1aSopenharmony_ci                    /* subpel ME */
1144cabdff1aSopenharmony_ci                    do{
1145cabdff1aSopenharmony_ci                        static const int square[8][2]= {{+1, 0},{-1, 0},{ 0,+1},{ 0,-1},{+1,+1},{-1,-1},{+1,-1},{-1,+1},};
1146cabdff1aSopenharmony_ci                        dia_change=0;
1147cabdff1aSopenharmony_ci                        for(i=0; i<8; i++)
1148cabdff1aSopenharmony_ci                            dia_change |= check_block_inter(s, mb_x, mb_y, block->mx+square[i][0], block->my+square[i][1], obmc_edged, &best_rd);
1149cabdff1aSopenharmony_ci                    }while(dia_change);
1150cabdff1aSopenharmony_ci                    //FIXME or try the standard 2 pass qpel or similar
1151cabdff1aSopenharmony_ci
1152cabdff1aSopenharmony_ci                    mvr[0][0]= block->mx;
1153cabdff1aSopenharmony_ci                    mvr[0][1]= block->my;
1154cabdff1aSopenharmony_ci                    if(ref_rd > best_rd){
1155cabdff1aSopenharmony_ci                        ref_rd= best_rd;
1156cabdff1aSopenharmony_ci                        ref_b= *block;
1157cabdff1aSopenharmony_ci                    }
1158cabdff1aSopenharmony_ci                }
1159cabdff1aSopenharmony_ci                best_rd= ref_rd;
1160cabdff1aSopenharmony_ci                *block= ref_b;
1161cabdff1aSopenharmony_ci                check_block(s, mb_x, mb_y, color, 1, obmc_edged, &best_rd);
1162cabdff1aSopenharmony_ci                //FIXME RD style color selection
1163cabdff1aSopenharmony_ci                if(!same_block(block, &backup)){
1164cabdff1aSopenharmony_ci                    if(tb ) tb ->type &= ~BLOCK_OPT;
1165cabdff1aSopenharmony_ci                    if(lb ) lb ->type &= ~BLOCK_OPT;
1166cabdff1aSopenharmony_ci                    if(rb ) rb ->type &= ~BLOCK_OPT;
1167cabdff1aSopenharmony_ci                    if(bb ) bb ->type &= ~BLOCK_OPT;
1168cabdff1aSopenharmony_ci                    if(tlb) tlb->type &= ~BLOCK_OPT;
1169cabdff1aSopenharmony_ci                    if(trb) trb->type &= ~BLOCK_OPT;
1170cabdff1aSopenharmony_ci                    if(blb) blb->type &= ~BLOCK_OPT;
1171cabdff1aSopenharmony_ci                    if(brb) brb->type &= ~BLOCK_OPT;
1172cabdff1aSopenharmony_ci                    change ++;
1173cabdff1aSopenharmony_ci                }
1174cabdff1aSopenharmony_ci            }
1175cabdff1aSopenharmony_ci        }
1176cabdff1aSopenharmony_ci        av_log(s->avctx, AV_LOG_DEBUG, "pass:%d changed:%d\n", pass, change);
1177cabdff1aSopenharmony_ci        if(!change)
1178cabdff1aSopenharmony_ci            break;
1179cabdff1aSopenharmony_ci    }
1180cabdff1aSopenharmony_ci
1181cabdff1aSopenharmony_ci    if(s->block_max_depth == 1){
1182cabdff1aSopenharmony_ci        int change= 0;
1183cabdff1aSopenharmony_ci        for(mb_y= 0; mb_y<b_height; mb_y+=2){
1184cabdff1aSopenharmony_ci            for(mb_x= 0; mb_x<b_width; mb_x+=2){
1185cabdff1aSopenharmony_ci                int i;
1186cabdff1aSopenharmony_ci                int best_rd, init_rd;
1187cabdff1aSopenharmony_ci                const int index= mb_x + mb_y * b_stride;
1188cabdff1aSopenharmony_ci                BlockNode *b[4];
1189cabdff1aSopenharmony_ci
1190cabdff1aSopenharmony_ci                b[0]= &s->block[index];
1191cabdff1aSopenharmony_ci                b[1]= b[0]+1;
1192cabdff1aSopenharmony_ci                b[2]= b[0]+b_stride;
1193cabdff1aSopenharmony_ci                b[3]= b[2]+1;
1194cabdff1aSopenharmony_ci                if(same_block(b[0], b[1]) &&
1195cabdff1aSopenharmony_ci                   same_block(b[0], b[2]) &&
1196cabdff1aSopenharmony_ci                   same_block(b[0], b[3]))
1197cabdff1aSopenharmony_ci                    continue;
1198cabdff1aSopenharmony_ci
1199cabdff1aSopenharmony_ci                if(!s->me_cache_generation)
1200cabdff1aSopenharmony_ci                    memset(s->me_cache, 0, sizeof(s->me_cache));
1201cabdff1aSopenharmony_ci                s->me_cache_generation += 1<<22;
1202cabdff1aSopenharmony_ci
1203cabdff1aSopenharmony_ci                init_rd= best_rd= get_4block_rd(s, mb_x, mb_y, 0);
1204cabdff1aSopenharmony_ci
1205cabdff1aSopenharmony_ci                //FIXME more multiref search?
1206cabdff1aSopenharmony_ci                check_4block_inter(s, mb_x, mb_y,
1207cabdff1aSopenharmony_ci                                   (b[0]->mx + b[1]->mx + b[2]->mx + b[3]->mx + 2) >> 2,
1208cabdff1aSopenharmony_ci                                   (b[0]->my + b[1]->my + b[2]->my + b[3]->my + 2) >> 2, 0, &best_rd);
1209cabdff1aSopenharmony_ci
1210cabdff1aSopenharmony_ci                for(i=0; i<4; i++)
1211cabdff1aSopenharmony_ci                    if(!(b[i]->type&BLOCK_INTRA))
1212cabdff1aSopenharmony_ci                        check_4block_inter(s, mb_x, mb_y, b[i]->mx, b[i]->my, b[i]->ref, &best_rd);
1213cabdff1aSopenharmony_ci
1214cabdff1aSopenharmony_ci                if(init_rd != best_rd)
1215cabdff1aSopenharmony_ci                    change++;
1216cabdff1aSopenharmony_ci            }
1217cabdff1aSopenharmony_ci        }
1218cabdff1aSopenharmony_ci        av_log(s->avctx, AV_LOG_ERROR, "pass:4mv changed:%d\n", change*4);
1219cabdff1aSopenharmony_ci    }
1220cabdff1aSopenharmony_ci}
1221cabdff1aSopenharmony_ci
1222cabdff1aSopenharmony_cistatic void encode_blocks(SnowContext *s, int search){
1223cabdff1aSopenharmony_ci    int x, y;
1224cabdff1aSopenharmony_ci    int w= s->b_width;
1225cabdff1aSopenharmony_ci    int h= s->b_height;
1226cabdff1aSopenharmony_ci
1227cabdff1aSopenharmony_ci    if(s->motion_est == FF_ME_ITER && !s->keyframe && search)
1228cabdff1aSopenharmony_ci        iterative_me(s);
1229cabdff1aSopenharmony_ci
1230cabdff1aSopenharmony_ci    for(y=0; y<h; y++){
1231cabdff1aSopenharmony_ci        if(s->c.bytestream_end - s->c.bytestream < w*MB_SIZE*MB_SIZE*3){ //FIXME nicer limit
1232cabdff1aSopenharmony_ci            av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
1233cabdff1aSopenharmony_ci            return;
1234cabdff1aSopenharmony_ci        }
1235cabdff1aSopenharmony_ci        for(x=0; x<w; x++){
1236cabdff1aSopenharmony_ci            if(s->motion_est == FF_ME_ITER || !search)
1237cabdff1aSopenharmony_ci                encode_q_branch2(s, 0, x, y);
1238cabdff1aSopenharmony_ci            else
1239cabdff1aSopenharmony_ci                encode_q_branch (s, 0, x, y);
1240cabdff1aSopenharmony_ci        }
1241cabdff1aSopenharmony_ci    }
1242cabdff1aSopenharmony_ci}
1243cabdff1aSopenharmony_ci
1244cabdff1aSopenharmony_cistatic void quantize(SnowContext *s, SubBand *b, IDWTELEM *dst, DWTELEM *src, int stride, int bias){
1245cabdff1aSopenharmony_ci    const int w= b->width;
1246cabdff1aSopenharmony_ci    const int h= b->height;
1247cabdff1aSopenharmony_ci    const int qlog= av_clip(s->qlog + b->qlog, 0, QROOT*16);
1248cabdff1aSopenharmony_ci    const int qmul= ff_qexp[qlog&(QROOT-1)]<<((qlog>>QSHIFT) + ENCODER_EXTRA_BITS);
1249cabdff1aSopenharmony_ci    int x,y, thres1, thres2;
1250cabdff1aSopenharmony_ci
1251cabdff1aSopenharmony_ci    if(s->qlog == LOSSLESS_QLOG){
1252cabdff1aSopenharmony_ci        for(y=0; y<h; y++)
1253cabdff1aSopenharmony_ci            for(x=0; x<w; x++)
1254cabdff1aSopenharmony_ci                dst[x + y*stride]= src[x + y*stride];
1255cabdff1aSopenharmony_ci        return;
1256cabdff1aSopenharmony_ci    }
1257cabdff1aSopenharmony_ci
1258cabdff1aSopenharmony_ci    bias= bias ? 0 : (3*qmul)>>3;
1259cabdff1aSopenharmony_ci    thres1= ((qmul - bias)>>QEXPSHIFT) - 1;
1260cabdff1aSopenharmony_ci    thres2= 2*thres1;
1261cabdff1aSopenharmony_ci
1262cabdff1aSopenharmony_ci    if(!bias){
1263cabdff1aSopenharmony_ci        for(y=0; y<h; y++){
1264cabdff1aSopenharmony_ci            for(x=0; x<w; x++){
1265cabdff1aSopenharmony_ci                int i= src[x + y*stride];
1266cabdff1aSopenharmony_ci
1267cabdff1aSopenharmony_ci                if((unsigned)(i+thres1) > thres2){
1268cabdff1aSopenharmony_ci                    if(i>=0){
1269cabdff1aSopenharmony_ci                        i<<= QEXPSHIFT;
1270cabdff1aSopenharmony_ci                        i/= qmul; //FIXME optimize
1271cabdff1aSopenharmony_ci                        dst[x + y*stride]=  i;
1272cabdff1aSopenharmony_ci                    }else{
1273cabdff1aSopenharmony_ci                        i= -i;
1274cabdff1aSopenharmony_ci                        i<<= QEXPSHIFT;
1275cabdff1aSopenharmony_ci                        i/= qmul; //FIXME optimize
1276cabdff1aSopenharmony_ci                        dst[x + y*stride]= -i;
1277cabdff1aSopenharmony_ci                    }
1278cabdff1aSopenharmony_ci                }else
1279cabdff1aSopenharmony_ci                    dst[x + y*stride]= 0;
1280cabdff1aSopenharmony_ci            }
1281cabdff1aSopenharmony_ci        }
1282cabdff1aSopenharmony_ci    }else{
1283cabdff1aSopenharmony_ci        for(y=0; y<h; y++){
1284cabdff1aSopenharmony_ci            for(x=0; x<w; x++){
1285cabdff1aSopenharmony_ci                int i= src[x + y*stride];
1286cabdff1aSopenharmony_ci
1287cabdff1aSopenharmony_ci                if((unsigned)(i+thres1) > thres2){
1288cabdff1aSopenharmony_ci                    if(i>=0){
1289cabdff1aSopenharmony_ci                        i<<= QEXPSHIFT;
1290cabdff1aSopenharmony_ci                        i= (i + bias) / qmul; //FIXME optimize
1291cabdff1aSopenharmony_ci                        dst[x + y*stride]=  i;
1292cabdff1aSopenharmony_ci                    }else{
1293cabdff1aSopenharmony_ci                        i= -i;
1294cabdff1aSopenharmony_ci                        i<<= QEXPSHIFT;
1295cabdff1aSopenharmony_ci                        i= (i + bias) / qmul; //FIXME optimize
1296cabdff1aSopenharmony_ci                        dst[x + y*stride]= -i;
1297cabdff1aSopenharmony_ci                    }
1298cabdff1aSopenharmony_ci                }else
1299cabdff1aSopenharmony_ci                    dst[x + y*stride]= 0;
1300cabdff1aSopenharmony_ci            }
1301cabdff1aSopenharmony_ci        }
1302cabdff1aSopenharmony_ci    }
1303cabdff1aSopenharmony_ci}
1304cabdff1aSopenharmony_ci
1305cabdff1aSopenharmony_cistatic void dequantize(SnowContext *s, SubBand *b, IDWTELEM *src, int stride){
1306cabdff1aSopenharmony_ci    const int w= b->width;
1307cabdff1aSopenharmony_ci    const int h= b->height;
1308cabdff1aSopenharmony_ci    const int qlog= av_clip(s->qlog + b->qlog, 0, QROOT*16);
1309cabdff1aSopenharmony_ci    const int qmul= ff_qexp[qlog&(QROOT-1)]<<(qlog>>QSHIFT);
1310cabdff1aSopenharmony_ci    const int qadd= (s->qbias*qmul)>>QBIAS_SHIFT;
1311cabdff1aSopenharmony_ci    int x,y;
1312cabdff1aSopenharmony_ci
1313cabdff1aSopenharmony_ci    if(s->qlog == LOSSLESS_QLOG) return;
1314cabdff1aSopenharmony_ci
1315cabdff1aSopenharmony_ci    for(y=0; y<h; y++){
1316cabdff1aSopenharmony_ci        for(x=0; x<w; x++){
1317cabdff1aSopenharmony_ci            int i= src[x + y*stride];
1318cabdff1aSopenharmony_ci            if(i<0){
1319cabdff1aSopenharmony_ci                src[x + y*stride]= -((-i*qmul + qadd)>>(QEXPSHIFT)); //FIXME try different bias
1320cabdff1aSopenharmony_ci            }else if(i>0){
1321cabdff1aSopenharmony_ci                src[x + y*stride]=  (( i*qmul + qadd)>>(QEXPSHIFT));
1322cabdff1aSopenharmony_ci            }
1323cabdff1aSopenharmony_ci        }
1324cabdff1aSopenharmony_ci    }
1325cabdff1aSopenharmony_ci}
1326cabdff1aSopenharmony_ci
1327cabdff1aSopenharmony_cistatic void decorrelate(SnowContext *s, SubBand *b, IDWTELEM *src, int stride, int inverse, int use_median){
1328cabdff1aSopenharmony_ci    const int w= b->width;
1329cabdff1aSopenharmony_ci    const int h= b->height;
1330cabdff1aSopenharmony_ci    int x,y;
1331cabdff1aSopenharmony_ci
1332cabdff1aSopenharmony_ci    for(y=h-1; y>=0; y--){
1333cabdff1aSopenharmony_ci        for(x=w-1; x>=0; x--){
1334cabdff1aSopenharmony_ci            int i= x + y*stride;
1335cabdff1aSopenharmony_ci
1336cabdff1aSopenharmony_ci            if(x){
1337cabdff1aSopenharmony_ci                if(use_median){
1338cabdff1aSopenharmony_ci                    if(y && x+1<w) src[i] -= mid_pred(src[i - 1], src[i - stride], src[i - stride + 1]);
1339cabdff1aSopenharmony_ci                    else  src[i] -= src[i - 1];
1340cabdff1aSopenharmony_ci                }else{
1341cabdff1aSopenharmony_ci                    if(y) src[i] -= mid_pred(src[i - 1], src[i - stride], src[i - 1] + src[i - stride] - src[i - 1 - stride]);
1342cabdff1aSopenharmony_ci                    else  src[i] -= src[i - 1];
1343cabdff1aSopenharmony_ci                }
1344cabdff1aSopenharmony_ci            }else{
1345cabdff1aSopenharmony_ci                if(y) src[i] -= src[i - stride];
1346cabdff1aSopenharmony_ci            }
1347cabdff1aSopenharmony_ci        }
1348cabdff1aSopenharmony_ci    }
1349cabdff1aSopenharmony_ci}
1350cabdff1aSopenharmony_ci
1351cabdff1aSopenharmony_cistatic void correlate(SnowContext *s, SubBand *b, IDWTELEM *src, int stride, int inverse, int use_median){
1352cabdff1aSopenharmony_ci    const int w= b->width;
1353cabdff1aSopenharmony_ci    const int h= b->height;
1354cabdff1aSopenharmony_ci    int x,y;
1355cabdff1aSopenharmony_ci
1356cabdff1aSopenharmony_ci    for(y=0; y<h; y++){
1357cabdff1aSopenharmony_ci        for(x=0; x<w; x++){
1358cabdff1aSopenharmony_ci            int i= x + y*stride;
1359cabdff1aSopenharmony_ci
1360cabdff1aSopenharmony_ci            if(x){
1361cabdff1aSopenharmony_ci                if(use_median){
1362cabdff1aSopenharmony_ci                    if(y && x+1<w) src[i] += mid_pred(src[i - 1], src[i - stride], src[i - stride + 1]);
1363cabdff1aSopenharmony_ci                    else  src[i] += src[i - 1];
1364cabdff1aSopenharmony_ci                }else{
1365cabdff1aSopenharmony_ci                    if(y) src[i] += mid_pred(src[i - 1], src[i - stride], src[i - 1] + src[i - stride] - src[i - 1 - stride]);
1366cabdff1aSopenharmony_ci                    else  src[i] += src[i - 1];
1367cabdff1aSopenharmony_ci                }
1368cabdff1aSopenharmony_ci            }else{
1369cabdff1aSopenharmony_ci                if(y) src[i] += src[i - stride];
1370cabdff1aSopenharmony_ci            }
1371cabdff1aSopenharmony_ci        }
1372cabdff1aSopenharmony_ci    }
1373cabdff1aSopenharmony_ci}
1374cabdff1aSopenharmony_ci
1375cabdff1aSopenharmony_cistatic void encode_qlogs(SnowContext *s){
1376cabdff1aSopenharmony_ci    int plane_index, level, orientation;
1377cabdff1aSopenharmony_ci
1378cabdff1aSopenharmony_ci    for(plane_index=0; plane_index<FFMIN(s->nb_planes, 2); plane_index++){
1379cabdff1aSopenharmony_ci        for(level=0; level<s->spatial_decomposition_count; level++){
1380cabdff1aSopenharmony_ci            for(orientation=level ? 1:0; orientation<4; orientation++){
1381cabdff1aSopenharmony_ci                if(orientation==2) continue;
1382cabdff1aSopenharmony_ci                put_symbol(&s->c, s->header_state, s->plane[plane_index].band[level][orientation].qlog, 1);
1383cabdff1aSopenharmony_ci            }
1384cabdff1aSopenharmony_ci        }
1385cabdff1aSopenharmony_ci    }
1386cabdff1aSopenharmony_ci}
1387cabdff1aSopenharmony_ci
1388cabdff1aSopenharmony_cistatic void encode_header(SnowContext *s){
1389cabdff1aSopenharmony_ci    int plane_index, i;
1390cabdff1aSopenharmony_ci    uint8_t kstate[32];
1391cabdff1aSopenharmony_ci
1392cabdff1aSopenharmony_ci    memset(kstate, MID_STATE, sizeof(kstate));
1393cabdff1aSopenharmony_ci
1394cabdff1aSopenharmony_ci    put_rac(&s->c, kstate, s->keyframe);
1395cabdff1aSopenharmony_ci    if(s->keyframe || s->always_reset){
1396cabdff1aSopenharmony_ci        ff_snow_reset_contexts(s);
1397cabdff1aSopenharmony_ci        s->last_spatial_decomposition_type=
1398cabdff1aSopenharmony_ci        s->last_qlog=
1399cabdff1aSopenharmony_ci        s->last_qbias=
1400cabdff1aSopenharmony_ci        s->last_mv_scale=
1401cabdff1aSopenharmony_ci        s->last_block_max_depth= 0;
1402cabdff1aSopenharmony_ci        for(plane_index=0; plane_index<2; plane_index++){
1403cabdff1aSopenharmony_ci            Plane *p= &s->plane[plane_index];
1404cabdff1aSopenharmony_ci            p->last_htaps=0;
1405cabdff1aSopenharmony_ci            p->last_diag_mc=0;
1406cabdff1aSopenharmony_ci            memset(p->last_hcoeff, 0, sizeof(p->last_hcoeff));
1407cabdff1aSopenharmony_ci        }
1408cabdff1aSopenharmony_ci    }
1409cabdff1aSopenharmony_ci    if(s->keyframe){
1410cabdff1aSopenharmony_ci        put_symbol(&s->c, s->header_state, s->version, 0);
1411cabdff1aSopenharmony_ci        put_rac(&s->c, s->header_state, s->always_reset);
1412cabdff1aSopenharmony_ci        put_symbol(&s->c, s->header_state, s->temporal_decomposition_type, 0);
1413cabdff1aSopenharmony_ci        put_symbol(&s->c, s->header_state, s->temporal_decomposition_count, 0);
1414cabdff1aSopenharmony_ci        put_symbol(&s->c, s->header_state, s->spatial_decomposition_count, 0);
1415cabdff1aSopenharmony_ci        put_symbol(&s->c, s->header_state, s->colorspace_type, 0);
1416cabdff1aSopenharmony_ci        if (s->nb_planes > 2) {
1417cabdff1aSopenharmony_ci            put_symbol(&s->c, s->header_state, s->chroma_h_shift, 0);
1418cabdff1aSopenharmony_ci            put_symbol(&s->c, s->header_state, s->chroma_v_shift, 0);
1419cabdff1aSopenharmony_ci        }
1420cabdff1aSopenharmony_ci        put_rac(&s->c, s->header_state, s->spatial_scalability);
1421cabdff1aSopenharmony_ci//        put_rac(&s->c, s->header_state, s->rate_scalability);
1422cabdff1aSopenharmony_ci        put_symbol(&s->c, s->header_state, s->max_ref_frames-1, 0);
1423cabdff1aSopenharmony_ci
1424cabdff1aSopenharmony_ci        encode_qlogs(s);
1425cabdff1aSopenharmony_ci    }
1426cabdff1aSopenharmony_ci
1427cabdff1aSopenharmony_ci    if(!s->keyframe){
1428cabdff1aSopenharmony_ci        int update_mc=0;
1429cabdff1aSopenharmony_ci        for(plane_index=0; plane_index<FFMIN(s->nb_planes, 2); plane_index++){
1430cabdff1aSopenharmony_ci            Plane *p= &s->plane[plane_index];
1431cabdff1aSopenharmony_ci            update_mc |= p->last_htaps   != p->htaps;
1432cabdff1aSopenharmony_ci            update_mc |= p->last_diag_mc != p->diag_mc;
1433cabdff1aSopenharmony_ci            update_mc |= !!memcmp(p->last_hcoeff, p->hcoeff, sizeof(p->hcoeff));
1434cabdff1aSopenharmony_ci        }
1435cabdff1aSopenharmony_ci        put_rac(&s->c, s->header_state, update_mc);
1436cabdff1aSopenharmony_ci        if(update_mc){
1437cabdff1aSopenharmony_ci            for(plane_index=0; plane_index<FFMIN(s->nb_planes, 2); plane_index++){
1438cabdff1aSopenharmony_ci                Plane *p= &s->plane[plane_index];
1439cabdff1aSopenharmony_ci                put_rac(&s->c, s->header_state, p->diag_mc);
1440cabdff1aSopenharmony_ci                put_symbol(&s->c, s->header_state, p->htaps/2-1, 0);
1441cabdff1aSopenharmony_ci                for(i= p->htaps/2; i; i--)
1442cabdff1aSopenharmony_ci                    put_symbol(&s->c, s->header_state, FFABS(p->hcoeff[i]), 0);
1443cabdff1aSopenharmony_ci            }
1444cabdff1aSopenharmony_ci        }
1445cabdff1aSopenharmony_ci        if(s->last_spatial_decomposition_count != s->spatial_decomposition_count){
1446cabdff1aSopenharmony_ci            put_rac(&s->c, s->header_state, 1);
1447cabdff1aSopenharmony_ci            put_symbol(&s->c, s->header_state, s->spatial_decomposition_count, 0);
1448cabdff1aSopenharmony_ci            encode_qlogs(s);
1449cabdff1aSopenharmony_ci        }else
1450cabdff1aSopenharmony_ci            put_rac(&s->c, s->header_state, 0);
1451cabdff1aSopenharmony_ci    }
1452cabdff1aSopenharmony_ci
1453cabdff1aSopenharmony_ci    put_symbol(&s->c, s->header_state, s->spatial_decomposition_type - s->last_spatial_decomposition_type, 1);
1454cabdff1aSopenharmony_ci    put_symbol(&s->c, s->header_state, s->qlog            - s->last_qlog    , 1);
1455cabdff1aSopenharmony_ci    put_symbol(&s->c, s->header_state, s->mv_scale        - s->last_mv_scale, 1);
1456cabdff1aSopenharmony_ci    put_symbol(&s->c, s->header_state, s->qbias           - s->last_qbias   , 1);
1457cabdff1aSopenharmony_ci    put_symbol(&s->c, s->header_state, s->block_max_depth - s->last_block_max_depth, 1);
1458cabdff1aSopenharmony_ci
1459cabdff1aSopenharmony_ci}
1460cabdff1aSopenharmony_ci
1461cabdff1aSopenharmony_cistatic void update_last_header_values(SnowContext *s){
1462cabdff1aSopenharmony_ci    int plane_index;
1463cabdff1aSopenharmony_ci
1464cabdff1aSopenharmony_ci    if(!s->keyframe){
1465cabdff1aSopenharmony_ci        for(plane_index=0; plane_index<2; plane_index++){
1466cabdff1aSopenharmony_ci            Plane *p= &s->plane[plane_index];
1467cabdff1aSopenharmony_ci            p->last_diag_mc= p->diag_mc;
1468cabdff1aSopenharmony_ci            p->last_htaps  = p->htaps;
1469cabdff1aSopenharmony_ci            memcpy(p->last_hcoeff, p->hcoeff, sizeof(p->hcoeff));
1470cabdff1aSopenharmony_ci        }
1471cabdff1aSopenharmony_ci    }
1472cabdff1aSopenharmony_ci
1473cabdff1aSopenharmony_ci    s->last_spatial_decomposition_type  = s->spatial_decomposition_type;
1474cabdff1aSopenharmony_ci    s->last_qlog                        = s->qlog;
1475cabdff1aSopenharmony_ci    s->last_qbias                       = s->qbias;
1476cabdff1aSopenharmony_ci    s->last_mv_scale                    = s->mv_scale;
1477cabdff1aSopenharmony_ci    s->last_block_max_depth             = s->block_max_depth;
1478cabdff1aSopenharmony_ci    s->last_spatial_decomposition_count = s->spatial_decomposition_count;
1479cabdff1aSopenharmony_ci}
1480cabdff1aSopenharmony_ci
1481cabdff1aSopenharmony_cistatic int qscale2qlog(int qscale){
1482cabdff1aSopenharmony_ci    return lrint(QROOT*log2(qscale / (float)FF_QP2LAMBDA))
1483cabdff1aSopenharmony_ci           + 61*QROOT/8; ///< 64 > 60
1484cabdff1aSopenharmony_ci}
1485cabdff1aSopenharmony_ci
1486cabdff1aSopenharmony_cistatic int ratecontrol_1pass(SnowContext *s, AVFrame *pict)
1487cabdff1aSopenharmony_ci{
1488cabdff1aSopenharmony_ci    /* Estimate the frame's complexity as a sum of weighted dwt coefficients.
1489cabdff1aSopenharmony_ci     * FIXME we know exact mv bits at this point,
1490cabdff1aSopenharmony_ci     * but ratecontrol isn't set up to include them. */
1491cabdff1aSopenharmony_ci    uint32_t coef_sum= 0;
1492cabdff1aSopenharmony_ci    int level, orientation, delta_qlog;
1493cabdff1aSopenharmony_ci
1494cabdff1aSopenharmony_ci    for(level=0; level<s->spatial_decomposition_count; level++){
1495cabdff1aSopenharmony_ci        for(orientation=level ? 1 : 0; orientation<4; orientation++){
1496cabdff1aSopenharmony_ci            SubBand *b= &s->plane[0].band[level][orientation];
1497cabdff1aSopenharmony_ci            IDWTELEM *buf= b->ibuf;
1498cabdff1aSopenharmony_ci            const int w= b->width;
1499cabdff1aSopenharmony_ci            const int h= b->height;
1500cabdff1aSopenharmony_ci            const int stride= b->stride;
1501cabdff1aSopenharmony_ci            const int qlog= av_clip(2*QROOT + b->qlog, 0, QROOT*16);
1502cabdff1aSopenharmony_ci            const int qmul= ff_qexp[qlog&(QROOT-1)]<<(qlog>>QSHIFT);
1503cabdff1aSopenharmony_ci            const int qdiv= (1<<16)/qmul;
1504cabdff1aSopenharmony_ci            int x, y;
1505cabdff1aSopenharmony_ci            //FIXME this is ugly
1506cabdff1aSopenharmony_ci            for(y=0; y<h; y++)
1507cabdff1aSopenharmony_ci                for(x=0; x<w; x++)
1508cabdff1aSopenharmony_ci                    buf[x+y*stride]= b->buf[x+y*stride];
1509cabdff1aSopenharmony_ci            if(orientation==0)
1510cabdff1aSopenharmony_ci                decorrelate(s, b, buf, stride, 1, 0);
1511cabdff1aSopenharmony_ci            for(y=0; y<h; y++)
1512cabdff1aSopenharmony_ci                for(x=0; x<w; x++)
1513cabdff1aSopenharmony_ci                    coef_sum+= abs(buf[x+y*stride]) * qdiv >> 16;
1514cabdff1aSopenharmony_ci        }
1515cabdff1aSopenharmony_ci    }
1516cabdff1aSopenharmony_ci
1517cabdff1aSopenharmony_ci    /* ugly, ratecontrol just takes a sqrt again */
1518cabdff1aSopenharmony_ci    av_assert0(coef_sum < INT_MAX);
1519cabdff1aSopenharmony_ci    coef_sum = (uint64_t)coef_sum * coef_sum >> 16;
1520cabdff1aSopenharmony_ci
1521cabdff1aSopenharmony_ci    if(pict->pict_type == AV_PICTURE_TYPE_I){
1522cabdff1aSopenharmony_ci        s->m.current_picture.mb_var_sum= coef_sum;
1523cabdff1aSopenharmony_ci        s->m.current_picture.mc_mb_var_sum= 0;
1524cabdff1aSopenharmony_ci    }else{
1525cabdff1aSopenharmony_ci        s->m.current_picture.mc_mb_var_sum= coef_sum;
1526cabdff1aSopenharmony_ci        s->m.current_picture.mb_var_sum= 0;
1527cabdff1aSopenharmony_ci    }
1528cabdff1aSopenharmony_ci
1529cabdff1aSopenharmony_ci    pict->quality= ff_rate_estimate_qscale(&s->m, 1);
1530cabdff1aSopenharmony_ci    if (pict->quality < 0)
1531cabdff1aSopenharmony_ci        return INT_MIN;
1532cabdff1aSopenharmony_ci    s->lambda= pict->quality * 3/2;
1533cabdff1aSopenharmony_ci    delta_qlog= qscale2qlog(pict->quality) - s->qlog;
1534cabdff1aSopenharmony_ci    s->qlog+= delta_qlog;
1535cabdff1aSopenharmony_ci    return delta_qlog;
1536cabdff1aSopenharmony_ci}
1537cabdff1aSopenharmony_ci
1538cabdff1aSopenharmony_cistatic void calculate_visual_weight(SnowContext *s, Plane *p){
1539cabdff1aSopenharmony_ci    int width = p->width;
1540cabdff1aSopenharmony_ci    int height= p->height;
1541cabdff1aSopenharmony_ci    int level, orientation, x, y;
1542cabdff1aSopenharmony_ci
1543cabdff1aSopenharmony_ci    for(level=0; level<s->spatial_decomposition_count; level++){
1544cabdff1aSopenharmony_ci        int64_t error=0;
1545cabdff1aSopenharmony_ci        for(orientation=level ? 1 : 0; orientation<4; orientation++){
1546cabdff1aSopenharmony_ci            SubBand *b= &p->band[level][orientation];
1547cabdff1aSopenharmony_ci            IDWTELEM *ibuf= b->ibuf;
1548cabdff1aSopenharmony_ci
1549cabdff1aSopenharmony_ci            memset(s->spatial_idwt_buffer, 0, sizeof(*s->spatial_idwt_buffer)*width*height);
1550cabdff1aSopenharmony_ci            ibuf[b->width/2 + b->height/2*b->stride]= 256*16;
1551cabdff1aSopenharmony_ci            ff_spatial_idwt(s->spatial_idwt_buffer, s->temp_idwt_buffer, width, height, width, s->spatial_decomposition_type, s->spatial_decomposition_count);
1552cabdff1aSopenharmony_ci            for(y=0; y<height; y++){
1553cabdff1aSopenharmony_ci                for(x=0; x<width; x++){
1554cabdff1aSopenharmony_ci                    int64_t d= s->spatial_idwt_buffer[x + y*width]*16;
1555cabdff1aSopenharmony_ci                    error += d*d;
1556cabdff1aSopenharmony_ci                }
1557cabdff1aSopenharmony_ci            }
1558cabdff1aSopenharmony_ci            if (orientation == 2)
1559cabdff1aSopenharmony_ci                error /= 2;
1560cabdff1aSopenharmony_ci            b->qlog= (int)(QROOT * log2(352256.0/sqrt(error)) + 0.5);
1561cabdff1aSopenharmony_ci            if (orientation != 1)
1562cabdff1aSopenharmony_ci                error = 0;
1563cabdff1aSopenharmony_ci        }
1564cabdff1aSopenharmony_ci        p->band[level][1].qlog = p->band[level][2].qlog;
1565cabdff1aSopenharmony_ci    }
1566cabdff1aSopenharmony_ci}
1567cabdff1aSopenharmony_ci
1568cabdff1aSopenharmony_cistatic int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
1569cabdff1aSopenharmony_ci                        const AVFrame *pict, int *got_packet)
1570cabdff1aSopenharmony_ci{
1571cabdff1aSopenharmony_ci    SnowContext *s = avctx->priv_data;
1572cabdff1aSopenharmony_ci    RangeCoder * const c= &s->c;
1573cabdff1aSopenharmony_ci    AVFrame *pic;
1574cabdff1aSopenharmony_ci    const int width= s->avctx->width;
1575cabdff1aSopenharmony_ci    const int height= s->avctx->height;
1576cabdff1aSopenharmony_ci    int level, orientation, plane_index, i, y, ret;
1577cabdff1aSopenharmony_ci    uint8_t rc_header_bak[sizeof(s->header_state)];
1578cabdff1aSopenharmony_ci    uint8_t rc_block_bak[sizeof(s->block_state)];
1579cabdff1aSopenharmony_ci
1580cabdff1aSopenharmony_ci    if ((ret = ff_alloc_packet(avctx, pkt, s->b_width*s->b_height*MB_SIZE*MB_SIZE*3 + AV_INPUT_BUFFER_MIN_SIZE)) < 0)
1581cabdff1aSopenharmony_ci        return ret;
1582cabdff1aSopenharmony_ci
1583cabdff1aSopenharmony_ci    ff_init_range_encoder(c, pkt->data, pkt->size);
1584cabdff1aSopenharmony_ci    ff_build_rac_states(c, (1LL<<32)/20, 256-8);
1585cabdff1aSopenharmony_ci
1586cabdff1aSopenharmony_ci    for(i=0; i < s->nb_planes; i++){
1587cabdff1aSopenharmony_ci        int hshift= i ? s->chroma_h_shift : 0;
1588cabdff1aSopenharmony_ci        int vshift= i ? s->chroma_v_shift : 0;
1589cabdff1aSopenharmony_ci        for(y=0; y<AV_CEIL_RSHIFT(height, vshift); y++)
1590cabdff1aSopenharmony_ci            memcpy(&s->input_picture->data[i][y * s->input_picture->linesize[i]],
1591cabdff1aSopenharmony_ci                   &pict->data[i][y * pict->linesize[i]],
1592cabdff1aSopenharmony_ci                   AV_CEIL_RSHIFT(width, hshift));
1593cabdff1aSopenharmony_ci        s->mpvencdsp.draw_edges(s->input_picture->data[i], s->input_picture->linesize[i],
1594cabdff1aSopenharmony_ci                                AV_CEIL_RSHIFT(width, hshift), AV_CEIL_RSHIFT(height, vshift),
1595cabdff1aSopenharmony_ci                                EDGE_WIDTH >> hshift, EDGE_WIDTH >> vshift,
1596cabdff1aSopenharmony_ci                                EDGE_TOP | EDGE_BOTTOM);
1597cabdff1aSopenharmony_ci
1598cabdff1aSopenharmony_ci    }
1599cabdff1aSopenharmony_ci    emms_c();
1600cabdff1aSopenharmony_ci    pic = s->input_picture;
1601cabdff1aSopenharmony_ci    pic->pict_type = pict->pict_type;
1602cabdff1aSopenharmony_ci    pic->quality = pict->quality;
1603cabdff1aSopenharmony_ci
1604cabdff1aSopenharmony_ci    s->m.picture_number= avctx->frame_number;
1605cabdff1aSopenharmony_ci    if(avctx->flags&AV_CODEC_FLAG_PASS2){
1606cabdff1aSopenharmony_ci        s->m.pict_type = pic->pict_type = s->m.rc_context.entry[avctx->frame_number].new_pict_type;
1607cabdff1aSopenharmony_ci        s->keyframe = pic->pict_type == AV_PICTURE_TYPE_I;
1608cabdff1aSopenharmony_ci        if(!(avctx->flags&AV_CODEC_FLAG_QSCALE)) {
1609cabdff1aSopenharmony_ci            pic->quality = ff_rate_estimate_qscale(&s->m, 0);
1610cabdff1aSopenharmony_ci            if (pic->quality < 0)
1611cabdff1aSopenharmony_ci                return -1;
1612cabdff1aSopenharmony_ci        }
1613cabdff1aSopenharmony_ci    }else{
1614cabdff1aSopenharmony_ci        s->keyframe= avctx->gop_size==0 || avctx->frame_number % avctx->gop_size == 0;
1615cabdff1aSopenharmony_ci        s->m.pict_type = pic->pict_type = s->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
1616cabdff1aSopenharmony_ci    }
1617cabdff1aSopenharmony_ci
1618cabdff1aSopenharmony_ci    if(s->pass1_rc && avctx->frame_number == 0)
1619cabdff1aSopenharmony_ci        pic->quality = 2*FF_QP2LAMBDA;
1620cabdff1aSopenharmony_ci    if (pic->quality) {
1621cabdff1aSopenharmony_ci        s->qlog   = qscale2qlog(pic->quality);
1622cabdff1aSopenharmony_ci        s->lambda = pic->quality * 3/2;
1623cabdff1aSopenharmony_ci    }
1624cabdff1aSopenharmony_ci    if (s->qlog < 0 || (!pic->quality && (avctx->flags & AV_CODEC_FLAG_QSCALE))) {
1625cabdff1aSopenharmony_ci        s->qlog= LOSSLESS_QLOG;
1626cabdff1aSopenharmony_ci        s->lambda = 0;
1627cabdff1aSopenharmony_ci    }//else keep previous frame's qlog until after motion estimation
1628cabdff1aSopenharmony_ci
1629cabdff1aSopenharmony_ci    if (s->current_picture->data[0]) {
1630cabdff1aSopenharmony_ci        int w = s->avctx->width;
1631cabdff1aSopenharmony_ci        int h = s->avctx->height;
1632cabdff1aSopenharmony_ci
1633cabdff1aSopenharmony_ci        s->mpvencdsp.draw_edges(s->current_picture->data[0],
1634cabdff1aSopenharmony_ci                                s->current_picture->linesize[0], w   , h   ,
1635cabdff1aSopenharmony_ci                                EDGE_WIDTH  , EDGE_WIDTH  , EDGE_TOP | EDGE_BOTTOM);
1636cabdff1aSopenharmony_ci        if (s->current_picture->data[2]) {
1637cabdff1aSopenharmony_ci            s->mpvencdsp.draw_edges(s->current_picture->data[1],
1638cabdff1aSopenharmony_ci                                    s->current_picture->linesize[1], w>>s->chroma_h_shift, h>>s->chroma_v_shift,
1639cabdff1aSopenharmony_ci                                    EDGE_WIDTH>>s->chroma_h_shift, EDGE_WIDTH>>s->chroma_v_shift, EDGE_TOP | EDGE_BOTTOM);
1640cabdff1aSopenharmony_ci            s->mpvencdsp.draw_edges(s->current_picture->data[2],
1641cabdff1aSopenharmony_ci                                    s->current_picture->linesize[2], w>>s->chroma_h_shift, h>>s->chroma_v_shift,
1642cabdff1aSopenharmony_ci                                    EDGE_WIDTH>>s->chroma_h_shift, EDGE_WIDTH>>s->chroma_v_shift, EDGE_TOP | EDGE_BOTTOM);
1643cabdff1aSopenharmony_ci        }
1644cabdff1aSopenharmony_ci        emms_c();
1645cabdff1aSopenharmony_ci    }
1646cabdff1aSopenharmony_ci
1647cabdff1aSopenharmony_ci    ff_snow_frame_start(s);
1648cabdff1aSopenharmony_ci
1649cabdff1aSopenharmony_ci    s->m.current_picture_ptr= &s->m.current_picture;
1650cabdff1aSopenharmony_ci    s->m.current_picture.f = s->current_picture;
1651cabdff1aSopenharmony_ci    s->m.current_picture.f->pts = pict->pts;
1652cabdff1aSopenharmony_ci    if(pic->pict_type == AV_PICTURE_TYPE_P){
1653cabdff1aSopenharmony_ci        int block_width = (width +15)>>4;
1654cabdff1aSopenharmony_ci        int block_height= (height+15)>>4;
1655cabdff1aSopenharmony_ci        int stride= s->current_picture->linesize[0];
1656cabdff1aSopenharmony_ci
1657cabdff1aSopenharmony_ci        av_assert0(s->current_picture->data[0]);
1658cabdff1aSopenharmony_ci        av_assert0(s->last_picture[0]->data[0]);
1659cabdff1aSopenharmony_ci
1660cabdff1aSopenharmony_ci        s->m.avctx= s->avctx;
1661cabdff1aSopenharmony_ci        s->m.   last_picture.f = s->last_picture[0];
1662cabdff1aSopenharmony_ci        s->m.    new_picture   = s->input_picture;
1663cabdff1aSopenharmony_ci        s->m.   last_picture_ptr= &s->m.   last_picture;
1664cabdff1aSopenharmony_ci        s->m.linesize = stride;
1665cabdff1aSopenharmony_ci        s->m.uvlinesize= s->current_picture->linesize[1];
1666cabdff1aSopenharmony_ci        s->m.width = width;
1667cabdff1aSopenharmony_ci        s->m.height= height;
1668cabdff1aSopenharmony_ci        s->m.mb_width = block_width;
1669cabdff1aSopenharmony_ci        s->m.mb_height= block_height;
1670cabdff1aSopenharmony_ci        s->m.mb_stride=   s->m.mb_width+1;
1671cabdff1aSopenharmony_ci        s->m.b8_stride= 2*s->m.mb_width+1;
1672cabdff1aSopenharmony_ci        s->m.f_code=1;
1673cabdff1aSopenharmony_ci        s->m.pict_type = pic->pict_type;
1674cabdff1aSopenharmony_ci        s->m.motion_est= s->motion_est;
1675cabdff1aSopenharmony_ci        s->m.me.scene_change_score=0;
1676cabdff1aSopenharmony_ci        s->m.me.dia_size = avctx->dia_size;
1677cabdff1aSopenharmony_ci        s->m.quarter_sample= (s->avctx->flags & AV_CODEC_FLAG_QPEL)!=0;
1678cabdff1aSopenharmony_ci        s->m.out_format= FMT_H263;
1679cabdff1aSopenharmony_ci        s->m.unrestricted_mv= 1;
1680cabdff1aSopenharmony_ci
1681cabdff1aSopenharmony_ci        s->m.lambda = s->lambda;
1682cabdff1aSopenharmony_ci        s->m.qscale= (s->m.lambda*139 + FF_LAMBDA_SCALE*64) >> (FF_LAMBDA_SHIFT + 7);
1683cabdff1aSopenharmony_ci        s->lambda2= s->m.lambda2= (s->m.lambda*s->m.lambda + FF_LAMBDA_SCALE/2) >> FF_LAMBDA_SHIFT;
1684cabdff1aSopenharmony_ci
1685cabdff1aSopenharmony_ci        s->m.mecc= s->mecc; //move
1686cabdff1aSopenharmony_ci        s->m.qdsp= s->qdsp; //move
1687cabdff1aSopenharmony_ci        s->m.hdsp = s->hdsp;
1688cabdff1aSopenharmony_ci        ff_init_me(&s->m);
1689cabdff1aSopenharmony_ci        s->hdsp = s->m.hdsp;
1690cabdff1aSopenharmony_ci        s->mecc= s->m.mecc;
1691cabdff1aSopenharmony_ci    }
1692cabdff1aSopenharmony_ci
1693cabdff1aSopenharmony_ci    if(s->pass1_rc){
1694cabdff1aSopenharmony_ci        memcpy(rc_header_bak, s->header_state, sizeof(s->header_state));
1695cabdff1aSopenharmony_ci        memcpy(rc_block_bak, s->block_state, sizeof(s->block_state));
1696cabdff1aSopenharmony_ci    }
1697cabdff1aSopenharmony_ci
1698cabdff1aSopenharmony_ciredo_frame:
1699cabdff1aSopenharmony_ci
1700cabdff1aSopenharmony_ci    s->spatial_decomposition_count= 5;
1701cabdff1aSopenharmony_ci
1702cabdff1aSopenharmony_ci    while(   !(width >>(s->chroma_h_shift + s->spatial_decomposition_count))
1703cabdff1aSopenharmony_ci          || !(height>>(s->chroma_v_shift + s->spatial_decomposition_count)))
1704cabdff1aSopenharmony_ci        s->spatial_decomposition_count--;
1705cabdff1aSopenharmony_ci
1706cabdff1aSopenharmony_ci    if (s->spatial_decomposition_count <= 0) {
1707cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Resolution too low\n");
1708cabdff1aSopenharmony_ci        return AVERROR(EINVAL);
1709cabdff1aSopenharmony_ci    }
1710cabdff1aSopenharmony_ci
1711cabdff1aSopenharmony_ci    s->m.pict_type = pic->pict_type;
1712cabdff1aSopenharmony_ci    s->qbias = pic->pict_type == AV_PICTURE_TYPE_P ? 2 : 0;
1713cabdff1aSopenharmony_ci
1714cabdff1aSopenharmony_ci    ff_snow_common_init_after_header(avctx);
1715cabdff1aSopenharmony_ci
1716cabdff1aSopenharmony_ci    if(s->last_spatial_decomposition_count != s->spatial_decomposition_count){
1717cabdff1aSopenharmony_ci        for(plane_index=0; plane_index < s->nb_planes; plane_index++){
1718cabdff1aSopenharmony_ci            calculate_visual_weight(s, &s->plane[plane_index]);
1719cabdff1aSopenharmony_ci        }
1720cabdff1aSopenharmony_ci    }
1721cabdff1aSopenharmony_ci
1722cabdff1aSopenharmony_ci    encode_header(s);
1723cabdff1aSopenharmony_ci    s->m.misc_bits = 8*(s->c.bytestream - s->c.bytestream_start);
1724cabdff1aSopenharmony_ci    encode_blocks(s, 1);
1725cabdff1aSopenharmony_ci    s->m.mv_bits = 8*(s->c.bytestream - s->c.bytestream_start) - s->m.misc_bits;
1726cabdff1aSopenharmony_ci
1727cabdff1aSopenharmony_ci    for(plane_index=0; plane_index < s->nb_planes; plane_index++){
1728cabdff1aSopenharmony_ci        Plane *p= &s->plane[plane_index];
1729cabdff1aSopenharmony_ci        int w= p->width;
1730cabdff1aSopenharmony_ci        int h= p->height;
1731cabdff1aSopenharmony_ci        int x, y;
1732cabdff1aSopenharmony_ci//        int bits= put_bits_count(&s->c.pb);
1733cabdff1aSopenharmony_ci
1734cabdff1aSopenharmony_ci        if (!s->memc_only) {
1735cabdff1aSopenharmony_ci            //FIXME optimize
1736cabdff1aSopenharmony_ci            if(pict->data[plane_index]) //FIXME gray hack
1737cabdff1aSopenharmony_ci                for(y=0; y<h; y++){
1738cabdff1aSopenharmony_ci                    for(x=0; x<w; x++){
1739cabdff1aSopenharmony_ci                        s->spatial_idwt_buffer[y*w + x]= pict->data[plane_index][y*pict->linesize[plane_index] + x]<<FRAC_BITS;
1740cabdff1aSopenharmony_ci                    }
1741cabdff1aSopenharmony_ci                }
1742cabdff1aSopenharmony_ci            predict_plane(s, s->spatial_idwt_buffer, plane_index, 0);
1743cabdff1aSopenharmony_ci
1744cabdff1aSopenharmony_ci            if(   plane_index==0
1745cabdff1aSopenharmony_ci               && pic->pict_type == AV_PICTURE_TYPE_P
1746cabdff1aSopenharmony_ci               && !(avctx->flags&AV_CODEC_FLAG_PASS2)
1747cabdff1aSopenharmony_ci               && s->m.me.scene_change_score > s->scenechange_threshold){
1748cabdff1aSopenharmony_ci                ff_init_range_encoder(c, pkt->data, pkt->size);
1749cabdff1aSopenharmony_ci                ff_build_rac_states(c, (1LL<<32)/20, 256-8);
1750cabdff1aSopenharmony_ci                pic->pict_type= AV_PICTURE_TYPE_I;
1751cabdff1aSopenharmony_ci                s->keyframe=1;
1752cabdff1aSopenharmony_ci                s->current_picture->key_frame=1;
1753cabdff1aSopenharmony_ci                goto redo_frame;
1754cabdff1aSopenharmony_ci            }
1755cabdff1aSopenharmony_ci
1756cabdff1aSopenharmony_ci            if(s->qlog == LOSSLESS_QLOG){
1757cabdff1aSopenharmony_ci                for(y=0; y<h; y++){
1758cabdff1aSopenharmony_ci                    for(x=0; x<w; x++){
1759cabdff1aSopenharmony_ci                        s->spatial_dwt_buffer[y*w + x]= (s->spatial_idwt_buffer[y*w + x] + (1<<(FRAC_BITS-1))-1)>>FRAC_BITS;
1760cabdff1aSopenharmony_ci                    }
1761cabdff1aSopenharmony_ci                }
1762cabdff1aSopenharmony_ci            }else{
1763cabdff1aSopenharmony_ci                for(y=0; y<h; y++){
1764cabdff1aSopenharmony_ci                    for(x=0; x<w; x++){
1765cabdff1aSopenharmony_ci                        s->spatial_dwt_buffer[y*w + x]= s->spatial_idwt_buffer[y*w + x] * (1 << ENCODER_EXTRA_BITS);
1766cabdff1aSopenharmony_ci                    }
1767cabdff1aSopenharmony_ci                }
1768cabdff1aSopenharmony_ci            }
1769cabdff1aSopenharmony_ci
1770cabdff1aSopenharmony_ci            ff_spatial_dwt(s->spatial_dwt_buffer, s->temp_dwt_buffer, w, h, w, s->spatial_decomposition_type, s->spatial_decomposition_count);
1771cabdff1aSopenharmony_ci
1772cabdff1aSopenharmony_ci            if(s->pass1_rc && plane_index==0){
1773cabdff1aSopenharmony_ci                int delta_qlog = ratecontrol_1pass(s, pic);
1774cabdff1aSopenharmony_ci                if (delta_qlog <= INT_MIN)
1775cabdff1aSopenharmony_ci                    return -1;
1776cabdff1aSopenharmony_ci                if(delta_qlog){
1777cabdff1aSopenharmony_ci                    //reordering qlog in the bitstream would eliminate this reset
1778cabdff1aSopenharmony_ci                    ff_init_range_encoder(c, pkt->data, pkt->size);
1779cabdff1aSopenharmony_ci                    memcpy(s->header_state, rc_header_bak, sizeof(s->header_state));
1780cabdff1aSopenharmony_ci                    memcpy(s->block_state, rc_block_bak, sizeof(s->block_state));
1781cabdff1aSopenharmony_ci                    encode_header(s);
1782cabdff1aSopenharmony_ci                    encode_blocks(s, 0);
1783cabdff1aSopenharmony_ci                }
1784cabdff1aSopenharmony_ci            }
1785cabdff1aSopenharmony_ci
1786cabdff1aSopenharmony_ci            for(level=0; level<s->spatial_decomposition_count; level++){
1787cabdff1aSopenharmony_ci                for(orientation=level ? 1 : 0; orientation<4; orientation++){
1788cabdff1aSopenharmony_ci                    SubBand *b= &p->band[level][orientation];
1789cabdff1aSopenharmony_ci
1790cabdff1aSopenharmony_ci                    quantize(s, b, b->ibuf, b->buf, b->stride, s->qbias);
1791cabdff1aSopenharmony_ci                    if(orientation==0)
1792cabdff1aSopenharmony_ci                        decorrelate(s, b, b->ibuf, b->stride, pic->pict_type == AV_PICTURE_TYPE_P, 0);
1793cabdff1aSopenharmony_ci                    if (!s->no_bitstream)
1794cabdff1aSopenharmony_ci                    encode_subband(s, b, b->ibuf, b->parent ? b->parent->ibuf : NULL, b->stride, orientation);
1795cabdff1aSopenharmony_ci                    av_assert0(b->parent==NULL || b->parent->stride == b->stride*2);
1796cabdff1aSopenharmony_ci                    if(orientation==0)
1797cabdff1aSopenharmony_ci                        correlate(s, b, b->ibuf, b->stride, 1, 0);
1798cabdff1aSopenharmony_ci                }
1799cabdff1aSopenharmony_ci            }
1800cabdff1aSopenharmony_ci
1801cabdff1aSopenharmony_ci            for(level=0; level<s->spatial_decomposition_count; level++){
1802cabdff1aSopenharmony_ci                for(orientation=level ? 1 : 0; orientation<4; orientation++){
1803cabdff1aSopenharmony_ci                    SubBand *b= &p->band[level][orientation];
1804cabdff1aSopenharmony_ci
1805cabdff1aSopenharmony_ci                    dequantize(s, b, b->ibuf, b->stride);
1806cabdff1aSopenharmony_ci                }
1807cabdff1aSopenharmony_ci            }
1808cabdff1aSopenharmony_ci
1809cabdff1aSopenharmony_ci            ff_spatial_idwt(s->spatial_idwt_buffer, s->temp_idwt_buffer, w, h, w, s->spatial_decomposition_type, s->spatial_decomposition_count);
1810cabdff1aSopenharmony_ci            if(s->qlog == LOSSLESS_QLOG){
1811cabdff1aSopenharmony_ci                for(y=0; y<h; y++){
1812cabdff1aSopenharmony_ci                    for(x=0; x<w; x++){
1813cabdff1aSopenharmony_ci                        s->spatial_idwt_buffer[y*w + x]<<=FRAC_BITS;
1814cabdff1aSopenharmony_ci                    }
1815cabdff1aSopenharmony_ci                }
1816cabdff1aSopenharmony_ci            }
1817cabdff1aSopenharmony_ci            predict_plane(s, s->spatial_idwt_buffer, plane_index, 1);
1818cabdff1aSopenharmony_ci        }else{
1819cabdff1aSopenharmony_ci            //ME/MC only
1820cabdff1aSopenharmony_ci            if(pic->pict_type == AV_PICTURE_TYPE_I){
1821cabdff1aSopenharmony_ci                for(y=0; y<h; y++){
1822cabdff1aSopenharmony_ci                    for(x=0; x<w; x++){
1823cabdff1aSopenharmony_ci                        s->current_picture->data[plane_index][y*s->current_picture->linesize[plane_index] + x]=
1824cabdff1aSopenharmony_ci                            pict->data[plane_index][y*pict->linesize[plane_index] + x];
1825cabdff1aSopenharmony_ci                    }
1826cabdff1aSopenharmony_ci                }
1827cabdff1aSopenharmony_ci            }else{
1828cabdff1aSopenharmony_ci                memset(s->spatial_idwt_buffer, 0, sizeof(IDWTELEM)*w*h);
1829cabdff1aSopenharmony_ci                predict_plane(s, s->spatial_idwt_buffer, plane_index, 1);
1830cabdff1aSopenharmony_ci            }
1831cabdff1aSopenharmony_ci        }
1832cabdff1aSopenharmony_ci        if(s->avctx->flags&AV_CODEC_FLAG_PSNR){
1833cabdff1aSopenharmony_ci            int64_t error= 0;
1834cabdff1aSopenharmony_ci
1835cabdff1aSopenharmony_ci            if(pict->data[plane_index]) //FIXME gray hack
1836cabdff1aSopenharmony_ci                for(y=0; y<h; y++){
1837cabdff1aSopenharmony_ci                    for(x=0; x<w; x++){
1838cabdff1aSopenharmony_ci                        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];
1839cabdff1aSopenharmony_ci                        error += d*d;
1840cabdff1aSopenharmony_ci                    }
1841cabdff1aSopenharmony_ci                }
1842cabdff1aSopenharmony_ci            s->avctx->error[plane_index] += error;
1843cabdff1aSopenharmony_ci            s->encoding_error[plane_index] = error;
1844cabdff1aSopenharmony_ci        }
1845cabdff1aSopenharmony_ci
1846cabdff1aSopenharmony_ci    }
1847cabdff1aSopenharmony_ci    emms_c();
1848cabdff1aSopenharmony_ci
1849cabdff1aSopenharmony_ci    update_last_header_values(s);
1850cabdff1aSopenharmony_ci
1851cabdff1aSopenharmony_ci    ff_snow_release_buffer(avctx);
1852cabdff1aSopenharmony_ci
1853cabdff1aSopenharmony_ci    s->current_picture->coded_picture_number = avctx->frame_number;
1854cabdff1aSopenharmony_ci    s->current_picture->pict_type = pic->pict_type;
1855cabdff1aSopenharmony_ci    s->current_picture->quality = pic->quality;
1856cabdff1aSopenharmony_ci    s->m.frame_bits = 8*(s->c.bytestream - s->c.bytestream_start);
1857cabdff1aSopenharmony_ci    s->m.p_tex_bits = s->m.frame_bits - s->m.misc_bits - s->m.mv_bits;
1858cabdff1aSopenharmony_ci    s->m.current_picture.f->display_picture_number =
1859cabdff1aSopenharmony_ci    s->m.current_picture.f->coded_picture_number   = avctx->frame_number;
1860cabdff1aSopenharmony_ci    s->m.current_picture.f->quality                = pic->quality;
1861cabdff1aSopenharmony_ci    s->m.total_bits += 8*(s->c.bytestream - s->c.bytestream_start);
1862cabdff1aSopenharmony_ci    if(s->pass1_rc)
1863cabdff1aSopenharmony_ci        if (ff_rate_estimate_qscale(&s->m, 0) < 0)
1864cabdff1aSopenharmony_ci            return -1;
1865cabdff1aSopenharmony_ci    if(avctx->flags&AV_CODEC_FLAG_PASS1)
1866cabdff1aSopenharmony_ci        ff_write_pass1_stats(&s->m);
1867cabdff1aSopenharmony_ci    s->m.last_pict_type = s->m.pict_type;
1868cabdff1aSopenharmony_ci
1869cabdff1aSopenharmony_ci    emms_c();
1870cabdff1aSopenharmony_ci
1871cabdff1aSopenharmony_ci    ff_side_data_set_encoder_stats(pkt, s->current_picture->quality,
1872cabdff1aSopenharmony_ci                                   s->encoding_error,
1873cabdff1aSopenharmony_ci                                   (s->avctx->flags&AV_CODEC_FLAG_PSNR) ? SNOW_MAX_PLANES : 0,
1874cabdff1aSopenharmony_ci                                   s->current_picture->pict_type);
1875cabdff1aSopenharmony_ci
1876cabdff1aSopenharmony_ci    pkt->size = ff_rac_terminate(c, 0);
1877cabdff1aSopenharmony_ci    if (s->current_picture->key_frame)
1878cabdff1aSopenharmony_ci        pkt->flags |= AV_PKT_FLAG_KEY;
1879cabdff1aSopenharmony_ci    *got_packet = 1;
1880cabdff1aSopenharmony_ci
1881cabdff1aSopenharmony_ci    return 0;
1882cabdff1aSopenharmony_ci}
1883cabdff1aSopenharmony_ci
1884cabdff1aSopenharmony_cistatic av_cold int encode_end(AVCodecContext *avctx)
1885cabdff1aSopenharmony_ci{
1886cabdff1aSopenharmony_ci    SnowContext *s = avctx->priv_data;
1887cabdff1aSopenharmony_ci
1888cabdff1aSopenharmony_ci    ff_snow_common_end(s);
1889cabdff1aSopenharmony_ci    ff_rate_control_uninit(&s->m);
1890cabdff1aSopenharmony_ci    av_frame_free(&s->input_picture);
1891cabdff1aSopenharmony_ci    av_freep(&avctx->stats_out);
1892cabdff1aSopenharmony_ci
1893cabdff1aSopenharmony_ci    return 0;
1894cabdff1aSopenharmony_ci}
1895cabdff1aSopenharmony_ci
1896cabdff1aSopenharmony_ci#define OFFSET(x) offsetof(SnowContext, x)
1897cabdff1aSopenharmony_ci#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
1898cabdff1aSopenharmony_cistatic const AVOption options[] = {
1899cabdff1aSopenharmony_ci    {"motion_est", "motion estimation algorithm", OFFSET(motion_est), AV_OPT_TYPE_INT, {.i64 = FF_ME_EPZS }, FF_ME_ZERO, FF_ME_ITER, VE, "motion_est" },
1900cabdff1aSopenharmony_ci    { "zero", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_ME_ZERO }, 0, 0, VE, "motion_est" },
1901cabdff1aSopenharmony_ci    { "epzs", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_ME_EPZS }, 0, 0, VE, "motion_est" },
1902cabdff1aSopenharmony_ci    { "xone", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_ME_XONE }, 0, 0, VE, "motion_est" },
1903cabdff1aSopenharmony_ci    { "iter", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_ME_ITER }, 0, 0, VE, "motion_est" },
1904cabdff1aSopenharmony_ci    { "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 },
1905cabdff1aSopenharmony_ci    { "no_bitstream",   "Skip final bitstream writeout.",                    OFFSET(no_bitstream), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
1906cabdff1aSopenharmony_ci    { "intra_penalty",  "Penalty for intra blocks in block decission",      OFFSET(intra_penalty), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },
1907cabdff1aSopenharmony_ci    { "iterative_dia_size",  "Dia size for the iterative ME",          OFFSET(iterative_dia_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },
1908cabdff1aSopenharmony_ci    { "sc_threshold",   "Scene change threshold",                   OFFSET(scenechange_threshold), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, VE },
1909cabdff1aSopenharmony_ci    { "pred",           "Spatial decomposition type",                                OFFSET(pred), AV_OPT_TYPE_INT, { .i64 = 0 }, DWT_97, DWT_53, VE, "pred" },
1910cabdff1aSopenharmony_ci        { "dwt97", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, VE, "pred" },
1911cabdff1aSopenharmony_ci        { "dwt53", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, VE, "pred" },
1912cabdff1aSopenharmony_ci    { "rc_eq", "Set rate control equation. When computing the expression, besides the standard functions "
1913cabdff1aSopenharmony_ci     "defined in the section 'Expression Evaluation', the following functions are available: "
1914cabdff1aSopenharmony_ci     "bits2qp(bits), qp2bits(qp). Also the following constants are available: iTex pTex tex mv "
1915cabdff1aSopenharmony_ci     "fCode iCount mcVar var isI isP isB avgQP qComp avgIITex avgPITex avgPPTex avgBPTex avgTex.",
1916cabdff1aSopenharmony_ci                                                                                  OFFSET(m.rc_eq), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, VE },
1917cabdff1aSopenharmony_ci    { NULL },
1918cabdff1aSopenharmony_ci};
1919cabdff1aSopenharmony_ci
1920cabdff1aSopenharmony_cistatic const AVClass snowenc_class = {
1921cabdff1aSopenharmony_ci    .class_name = "snow encoder",
1922cabdff1aSopenharmony_ci    .item_name  = av_default_item_name,
1923cabdff1aSopenharmony_ci    .option     = options,
1924cabdff1aSopenharmony_ci    .version    = LIBAVUTIL_VERSION_INT,
1925cabdff1aSopenharmony_ci};
1926cabdff1aSopenharmony_ci
1927cabdff1aSopenharmony_ciconst FFCodec ff_snow_encoder = {
1928cabdff1aSopenharmony_ci    .p.name         = "snow",
1929cabdff1aSopenharmony_ci    .p.long_name    = NULL_IF_CONFIG_SMALL("Snow"),
1930cabdff1aSopenharmony_ci    .p.type         = AVMEDIA_TYPE_VIDEO,
1931cabdff1aSopenharmony_ci    .p.id           = AV_CODEC_ID_SNOW,
1932cabdff1aSopenharmony_ci    .priv_data_size = sizeof(SnowContext),
1933cabdff1aSopenharmony_ci    .init           = encode_init,
1934cabdff1aSopenharmony_ci    FF_CODEC_ENCODE_CB(encode_frame),
1935cabdff1aSopenharmony_ci    .close          = encode_end,
1936cabdff1aSopenharmony_ci    .p.pix_fmts     = (const enum AVPixelFormat[]){
1937cabdff1aSopenharmony_ci        AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV444P,
1938cabdff1aSopenharmony_ci        AV_PIX_FMT_GRAY8,
1939cabdff1aSopenharmony_ci        AV_PIX_FMT_NONE
1940cabdff1aSopenharmony_ci    },
1941cabdff1aSopenharmony_ci    .p.priv_class   = &snowenc_class,
1942cabdff1aSopenharmony_ci    .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE |
1943cabdff1aSopenharmony_ci                      FF_CODEC_CAP_INIT_CLEANUP,
1944cabdff1aSopenharmony_ci};
1945