PageRenderTime 116ms CodeModel.GetById 9ms app.highlight 98ms RepoModel.GetById 1ms app.codeStats 1ms

/libavcodec/mpegvideo_common.h

http://github.com/FFmpeg/FFmpeg
C++ Header | 899 lines | 740 code | 91 blank | 68 comment | 150 complexity | 75c72890800928e24ee78e65fa485498 MD5 | raw file
  1/*
  2 * The simplest mpeg encoder (well, it was the simplest!)
  3 * Copyright (c) 2000,2001 Fabrice Bellard
  4 * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
  5 *
  6 * 4MV & hq & B-frame encoding stuff by Michael Niedermayer <michaelni@gmx.at>
  7 *
  8 * This file is part of FFmpeg.
  9 *
 10 * FFmpeg is free software; you can redistribute it and/or
 11 * modify it under the terms of the GNU Lesser General Public
 12 * License as published by the Free Software Foundation; either
 13 * version 2.1 of the License, or (at your option) any later version.
 14 *
 15 * FFmpeg is distributed in the hope that it will be useful,
 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 18 * Lesser General Public License for more details.
 19 *
 20 * You should have received a copy of the GNU Lesser General Public
 21 * License along with FFmpeg; if not, write to the Free Software
 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 23 */
 24
 25/**
 26 * @file
 27 * The simplest mpeg encoder (well, it was the simplest!).
 28 */
 29
 30#ifndef AVCODEC_MPEGVIDEO_COMMON_H
 31#define AVCODEC_MPEGVIDEO_COMMON_H
 32
 33#include <string.h>
 34#include "avcodec.h"
 35#include "dsputil.h"
 36#include "mpegvideo.h"
 37#include "mjpegenc.h"
 38#include "msmpeg4.h"
 39#include "faandct.h"
 40#include <limits.h>
 41
 42int dct_quantize_c(MpegEncContext *s, DCTELEM *block, int n, int qscale, int *overflow);
 43
 44/**
 45 * Allocate a Picture.
 46 * The pixels are allocated/set by calling get_buffer() if shared = 0.
 47 */
 48int alloc_picture(MpegEncContext *s, Picture *pic, int shared);
 49
 50/**
 51 * Set the given MpegEncContext to common defaults (same for encoding and decoding).
 52 * The changed fields will not depend upon the prior state of the MpegEncContext.
 53 */
 54void MPV_common_defaults(MpegEncContext *s);
 55
 56static inline void gmc1_motion(MpegEncContext *s,
 57                               uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
 58                               uint8_t **ref_picture)
 59{
 60    uint8_t *ptr;
 61    int offset, src_x, src_y, linesize, uvlinesize;
 62    int motion_x, motion_y;
 63    int emu=0;
 64
 65    motion_x= s->sprite_offset[0][0];
 66    motion_y= s->sprite_offset[0][1];
 67    src_x = s->mb_x * 16 + (motion_x >> (s->sprite_warping_accuracy+1));
 68    src_y = s->mb_y * 16 + (motion_y >> (s->sprite_warping_accuracy+1));
 69    motion_x<<=(3-s->sprite_warping_accuracy);
 70    motion_y<<=(3-s->sprite_warping_accuracy);
 71    src_x = av_clip(src_x, -16, s->width);
 72    if (src_x == s->width)
 73        motion_x =0;
 74    src_y = av_clip(src_y, -16, s->height);
 75    if (src_y == s->height)
 76        motion_y =0;
 77
 78    linesize = s->linesize;
 79    uvlinesize = s->uvlinesize;
 80
 81    ptr = ref_picture[0] + (src_y * linesize) + src_x;
 82
 83    if(s->flags&CODEC_FLAG_EMU_EDGE){
 84        if(   (unsigned)src_x >= s->h_edge_pos - 17
 85           || (unsigned)src_y >= s->v_edge_pos - 17){
 86            s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr, linesize, 17, 17, src_x, src_y, s->h_edge_pos, s->v_edge_pos);
 87            ptr= s->edge_emu_buffer;
 88        }
 89    }
 90
 91    if((motion_x|motion_y)&7){
 92        s->dsp.gmc1(dest_y  , ptr  , linesize, 16, motion_x&15, motion_y&15, 128 - s->no_rounding);
 93        s->dsp.gmc1(dest_y+8, ptr+8, linesize, 16, motion_x&15, motion_y&15, 128 - s->no_rounding);
 94    }else{
 95        int dxy;
 96
 97        dxy= ((motion_x>>3)&1) | ((motion_y>>2)&2);
 98        if (s->no_rounding){
 99            s->dsp.put_no_rnd_pixels_tab[0][dxy](dest_y, ptr, linesize, 16);
100        }else{
101            s->dsp.put_pixels_tab       [0][dxy](dest_y, ptr, linesize, 16);
102        }
103    }
104
105    if(CONFIG_GRAY && s->flags&CODEC_FLAG_GRAY) return;
106
107    motion_x= s->sprite_offset[1][0];
108    motion_y= s->sprite_offset[1][1];
109    src_x = s->mb_x * 8 + (motion_x >> (s->sprite_warping_accuracy+1));
110    src_y = s->mb_y * 8 + (motion_y >> (s->sprite_warping_accuracy+1));
111    motion_x<<=(3-s->sprite_warping_accuracy);
112    motion_y<<=(3-s->sprite_warping_accuracy);
113    src_x = av_clip(src_x, -8, s->width>>1);
114    if (src_x == s->width>>1)
115        motion_x =0;
116    src_y = av_clip(src_y, -8, s->height>>1);
117    if (src_y == s->height>>1)
118        motion_y =0;
119
120    offset = (src_y * uvlinesize) + src_x;
121    ptr = ref_picture[1] + offset;
122    if(s->flags&CODEC_FLAG_EMU_EDGE){
123        if(   (unsigned)src_x >= (s->h_edge_pos>>1) - 9
124           || (unsigned)src_y >= (s->v_edge_pos>>1) - 9){
125            s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr, uvlinesize, 9, 9, src_x, src_y, s->h_edge_pos>>1, s->v_edge_pos>>1);
126            ptr= s->edge_emu_buffer;
127            emu=1;
128        }
129    }
130    s->dsp.gmc1(dest_cb, ptr, uvlinesize, 8, motion_x&15, motion_y&15, 128 - s->no_rounding);
131
132    ptr = ref_picture[2] + offset;
133    if(emu){
134        s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr, uvlinesize, 9, 9, src_x, src_y, s->h_edge_pos>>1, s->v_edge_pos>>1);
135        ptr= s->edge_emu_buffer;
136    }
137    s->dsp.gmc1(dest_cr, ptr, uvlinesize, 8, motion_x&15, motion_y&15, 128 - s->no_rounding);
138
139    return;
140}
141
142static inline void gmc_motion(MpegEncContext *s,
143                               uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
144                               uint8_t **ref_picture)
145{
146    uint8_t *ptr;
147    int linesize, uvlinesize;
148    const int a= s->sprite_warping_accuracy;
149    int ox, oy;
150
151    linesize = s->linesize;
152    uvlinesize = s->uvlinesize;
153
154    ptr = ref_picture[0];
155
156    ox= s->sprite_offset[0][0] + s->sprite_delta[0][0]*s->mb_x*16 + s->sprite_delta[0][1]*s->mb_y*16;
157    oy= s->sprite_offset[0][1] + s->sprite_delta[1][0]*s->mb_x*16 + s->sprite_delta[1][1]*s->mb_y*16;
158
159    s->dsp.gmc(dest_y, ptr, linesize, 16,
160           ox,
161           oy,
162           s->sprite_delta[0][0], s->sprite_delta[0][1],
163           s->sprite_delta[1][0], s->sprite_delta[1][1],
164           a+1, (1<<(2*a+1)) - s->no_rounding,
165           s->h_edge_pos, s->v_edge_pos);
166    s->dsp.gmc(dest_y+8, ptr, linesize, 16,
167           ox + s->sprite_delta[0][0]*8,
168           oy + s->sprite_delta[1][0]*8,
169           s->sprite_delta[0][0], s->sprite_delta[0][1],
170           s->sprite_delta[1][0], s->sprite_delta[1][1],
171           a+1, (1<<(2*a+1)) - s->no_rounding,
172           s->h_edge_pos, s->v_edge_pos);
173
174    if(CONFIG_GRAY && s->flags&CODEC_FLAG_GRAY) return;
175
176    ox= s->sprite_offset[1][0] + s->sprite_delta[0][0]*s->mb_x*8 + s->sprite_delta[0][1]*s->mb_y*8;
177    oy= s->sprite_offset[1][1] + s->sprite_delta[1][0]*s->mb_x*8 + s->sprite_delta[1][1]*s->mb_y*8;
178
179    ptr = ref_picture[1];
180    s->dsp.gmc(dest_cb, ptr, uvlinesize, 8,
181           ox,
182           oy,
183           s->sprite_delta[0][0], s->sprite_delta[0][1],
184           s->sprite_delta[1][0], s->sprite_delta[1][1],
185           a+1, (1<<(2*a+1)) - s->no_rounding,
186           s->h_edge_pos>>1, s->v_edge_pos>>1);
187
188    ptr = ref_picture[2];
189    s->dsp.gmc(dest_cr, ptr, uvlinesize, 8,
190           ox,
191           oy,
192           s->sprite_delta[0][0], s->sprite_delta[0][1],
193           s->sprite_delta[1][0], s->sprite_delta[1][1],
194           a+1, (1<<(2*a+1)) - s->no_rounding,
195           s->h_edge_pos>>1, s->v_edge_pos>>1);
196}
197
198static inline int hpel_motion(MpegEncContext *s,
199                                  uint8_t *dest, uint8_t *src,
200                                  int field_based, int field_select,
201                                  int src_x, int src_y,
202                                  int width, int height, int stride,
203                                  int h_edge_pos, int v_edge_pos,
204                                  int w, int h, op_pixels_func *pix_op,
205                                  int motion_x, int motion_y)
206{
207    int dxy;
208    int emu=0;
209
210    dxy = ((motion_y & 1) << 1) | (motion_x & 1);
211    src_x += motion_x >> 1;
212    src_y += motion_y >> 1;
213
214    /* WARNING: do no forget half pels */
215    src_x = av_clip(src_x, -16, width); //FIXME unneeded for emu?
216    if (src_x == width)
217        dxy &= ~1;
218    src_y = av_clip(src_y, -16, height);
219    if (src_y == height)
220        dxy &= ~2;
221    src += src_y * stride + src_x;
222
223    if(s->unrestricted_mv && (s->flags&CODEC_FLAG_EMU_EDGE)){
224        if(   (unsigned)src_x > h_edge_pos - (motion_x&1) - w
225           || (unsigned)src_y > v_edge_pos - (motion_y&1) - h){
226            s->dsp.emulated_edge_mc(s->edge_emu_buffer, src, s->linesize, w+1, (h+1)<<field_based,
227                             src_x, src_y<<field_based, h_edge_pos, s->v_edge_pos);
228            src= s->edge_emu_buffer;
229            emu=1;
230        }
231    }
232    if(field_select)
233        src += s->linesize;
234    pix_op[dxy](dest, src, stride, h);
235    return emu;
236}
237
238static av_always_inline
239void mpeg_motion_internal(MpegEncContext *s,
240                 uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
241                 int field_based, int bottom_field, int field_select,
242                 uint8_t **ref_picture, op_pixels_func (*pix_op)[4],
243                 int motion_x, int motion_y, int h, int is_mpeg12, int mb_y)
244{
245    uint8_t *ptr_y, *ptr_cb, *ptr_cr;
246    int dxy, uvdxy, mx, my, src_x, src_y,
247        uvsrc_x, uvsrc_y, v_edge_pos, uvlinesize, linesize;
248
249#if 0
250if(s->quarter_sample)
251{
252    motion_x>>=1;
253    motion_y>>=1;
254}
255#endif
256
257    v_edge_pos = s->v_edge_pos >> field_based;
258    linesize   = s->current_picture.f.linesize[0] << field_based;
259    uvlinesize = s->current_picture.f.linesize[1] << field_based;
260
261    dxy = ((motion_y & 1) << 1) | (motion_x & 1);
262    src_x = s->mb_x* 16               + (motion_x >> 1);
263    src_y =(   mb_y<<(4-field_based)) + (motion_y >> 1);
264
265    if (!is_mpeg12 && s->out_format == FMT_H263) {
266        if((s->workaround_bugs & FF_BUG_HPEL_CHROMA) && field_based){
267            mx = (motion_x>>1)|(motion_x&1);
268            my = motion_y >>1;
269            uvdxy = ((my & 1) << 1) | (mx & 1);
270            uvsrc_x = s->mb_x* 8               + (mx >> 1);
271            uvsrc_y =(   mb_y<<(3-field_based))+ (my >> 1);
272        }else{
273            uvdxy = dxy | (motion_y & 2) | ((motion_x & 2) >> 1);
274            uvsrc_x = src_x>>1;
275            uvsrc_y = src_y>>1;
276        }
277    }else if(!is_mpeg12 && s->out_format == FMT_H261){//even chroma mv's are full pel in H261
278        mx = motion_x / 4;
279        my = motion_y / 4;
280        uvdxy = 0;
281        uvsrc_x = s->mb_x*8 + mx;
282        uvsrc_y =    mb_y*8 + my;
283    } else {
284        if(s->chroma_y_shift){
285            mx = motion_x / 2;
286            my = motion_y / 2;
287            uvdxy = ((my & 1) << 1) | (mx & 1);
288            uvsrc_x = s->mb_x* 8               + (mx >> 1);
289            uvsrc_y =(   mb_y<<(3-field_based))+ (my >> 1);
290        } else {
291            if(s->chroma_x_shift){
292            //Chroma422
293                mx = motion_x / 2;
294                uvdxy = ((motion_y & 1) << 1) | (mx & 1);
295                uvsrc_x = s->mb_x* 8           + (mx >> 1);
296                uvsrc_y = src_y;
297            } else {
298            //Chroma444
299                uvdxy = dxy;
300                uvsrc_x = src_x;
301                uvsrc_y = src_y;
302            }
303        }
304    }
305
306    ptr_y  = ref_picture[0] + src_y * linesize + src_x;
307    ptr_cb = ref_picture[1] + uvsrc_y * uvlinesize + uvsrc_x;
308    ptr_cr = ref_picture[2] + uvsrc_y * uvlinesize + uvsrc_x;
309
310    if(   (unsigned)src_x > s->h_edge_pos - (motion_x&1) - 16
311       || (unsigned)src_y >    v_edge_pos - (motion_y&1) - h){
312            if(is_mpeg12 || s->codec_id == CODEC_ID_MPEG2VIDEO ||
313               s->codec_id == CODEC_ID_MPEG1VIDEO){
314                av_log(s->avctx,AV_LOG_DEBUG,
315                        "MPEG motion vector out of boundary (%d %d)\n", src_x, src_y);
316                return;
317            }
318            s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr_y, s->linesize,
319                                17, 17+field_based,
320                                src_x, src_y<<field_based,
321                                s->h_edge_pos, s->v_edge_pos);
322            ptr_y = s->edge_emu_buffer;
323            if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){
324                uint8_t *uvbuf= s->edge_emu_buffer+18*s->linesize;
325                s->dsp.emulated_edge_mc(uvbuf ,
326                                    ptr_cb, s->uvlinesize,
327                                    9, 9+field_based,
328                                    uvsrc_x, uvsrc_y<<field_based,
329                                    s->h_edge_pos>>1, s->v_edge_pos>>1);
330                s->dsp.emulated_edge_mc(uvbuf+16,
331                                    ptr_cr, s->uvlinesize,
332                                    9, 9+field_based,
333                                    uvsrc_x, uvsrc_y<<field_based,
334                                    s->h_edge_pos>>1, s->v_edge_pos>>1);
335                ptr_cb= uvbuf;
336                ptr_cr= uvbuf+16;
337            }
338    }
339
340    if(bottom_field){ //FIXME use this for field pix too instead of the obnoxious hack which changes picture.data
341        dest_y += s->linesize;
342        dest_cb+= s->uvlinesize;
343        dest_cr+= s->uvlinesize;
344    }
345
346    if(field_select){
347        ptr_y += s->linesize;
348        ptr_cb+= s->uvlinesize;
349        ptr_cr+= s->uvlinesize;
350    }
351
352    pix_op[0][dxy](dest_y, ptr_y, linesize, h);
353
354    if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){
355        pix_op[s->chroma_x_shift][uvdxy]
356                (dest_cb, ptr_cb, uvlinesize, h >> s->chroma_y_shift);
357        pix_op[s->chroma_x_shift][uvdxy]
358                (dest_cr, ptr_cr, uvlinesize, h >> s->chroma_y_shift);
359    }
360    if(!is_mpeg12 && (CONFIG_H261_ENCODER || CONFIG_H261_DECODER) &&
361         s->out_format == FMT_H261){
362        ff_h261_loop_filter(s);
363    }
364}
365/* apply one mpeg motion vector to the three components */
366static av_always_inline
367void mpeg_motion(MpegEncContext *s,
368                 uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
369                 int field_based, int bottom_field, int field_select,
370                 uint8_t **ref_picture, op_pixels_func (*pix_op)[4],
371                 int motion_x, int motion_y, int h, int mb_y)
372{
373#if !CONFIG_SMALL
374    if(s->out_format == FMT_MPEG1)
375        mpeg_motion_internal(s, dest_y, dest_cb, dest_cr, field_based,
376                    bottom_field, field_select, ref_picture, pix_op,
377                    motion_x, motion_y, h, 1, mb_y);
378    else
379#endif
380        mpeg_motion_internal(s, dest_y, dest_cb, dest_cr, field_based,
381                    bottom_field, field_select, ref_picture, pix_op,
382                    motion_x, motion_y, h, 0, mb_y);
383}
384
385//FIXME move to dsputil, avg variant, 16x16 version
386static inline void put_obmc(uint8_t *dst, uint8_t *src[5], int stride){
387    int x;
388    uint8_t * const top   = src[1];
389    uint8_t * const left  = src[2];
390    uint8_t * const mid   = src[0];
391    uint8_t * const right = src[3];
392    uint8_t * const bottom= src[4];
393#define OBMC_FILTER(x, t, l, m, r, b)\
394    dst[x]= (t*top[x] + l*left[x] + m*mid[x] + r*right[x] + b*bottom[x] + 4)>>3
395#define OBMC_FILTER4(x, t, l, m, r, b)\
396    OBMC_FILTER(x         , t, l, m, r, b);\
397    OBMC_FILTER(x+1       , t, l, m, r, b);\
398    OBMC_FILTER(x  +stride, t, l, m, r, b);\
399    OBMC_FILTER(x+1+stride, t, l, m, r, b);
400
401    x=0;
402    OBMC_FILTER (x  , 2, 2, 4, 0, 0);
403    OBMC_FILTER (x+1, 2, 1, 5, 0, 0);
404    OBMC_FILTER4(x+2, 2, 1, 5, 0, 0);
405    OBMC_FILTER4(x+4, 2, 0, 5, 1, 0);
406    OBMC_FILTER (x+6, 2, 0, 5, 1, 0);
407    OBMC_FILTER (x+7, 2, 0, 4, 2, 0);
408    x+= stride;
409    OBMC_FILTER (x  , 1, 2, 5, 0, 0);
410    OBMC_FILTER (x+1, 1, 2, 5, 0, 0);
411    OBMC_FILTER (x+6, 1, 0, 5, 2, 0);
412    OBMC_FILTER (x+7, 1, 0, 5, 2, 0);
413    x+= stride;
414    OBMC_FILTER4(x  , 1, 2, 5, 0, 0);
415    OBMC_FILTER4(x+2, 1, 1, 6, 0, 0);
416    OBMC_FILTER4(x+4, 1, 0, 6, 1, 0);
417    OBMC_FILTER4(x+6, 1, 0, 5, 2, 0);
418    x+= 2*stride;
419    OBMC_FILTER4(x  , 0, 2, 5, 0, 1);
420    OBMC_FILTER4(x+2, 0, 1, 6, 0, 1);
421    OBMC_FILTER4(x+4, 0, 0, 6, 1, 1);
422    OBMC_FILTER4(x+6, 0, 0, 5, 2, 1);
423    x+= 2*stride;
424    OBMC_FILTER (x  , 0, 2, 5, 0, 1);
425    OBMC_FILTER (x+1, 0, 2, 5, 0, 1);
426    OBMC_FILTER4(x+2, 0, 1, 5, 0, 2);
427    OBMC_FILTER4(x+4, 0, 0, 5, 1, 2);
428    OBMC_FILTER (x+6, 0, 0, 5, 2, 1);
429    OBMC_FILTER (x+7, 0, 0, 5, 2, 1);
430    x+= stride;
431    OBMC_FILTER (x  , 0, 2, 4, 0, 2);
432    OBMC_FILTER (x+1, 0, 1, 5, 0, 2);
433    OBMC_FILTER (x+6, 0, 0, 5, 1, 2);
434    OBMC_FILTER (x+7, 0, 0, 4, 2, 2);
435}
436
437/* obmc for 1 8x8 luma block */
438static inline void obmc_motion(MpegEncContext *s,
439                               uint8_t *dest, uint8_t *src,
440                               int src_x, int src_y,
441                               op_pixels_func *pix_op,
442                               int16_t mv[5][2]/* mid top left right bottom*/)
443#define MID    0
444{
445    int i;
446    uint8_t *ptr[5];
447
448    assert(s->quarter_sample==0);
449
450    for(i=0; i<5; i++){
451        if(i && mv[i][0]==mv[MID][0] && mv[i][1]==mv[MID][1]){
452            ptr[i]= ptr[MID];
453        }else{
454            ptr[i]= s->obmc_scratchpad + 8*(i&1) + s->linesize*8*(i>>1);
455            hpel_motion(s, ptr[i], src, 0, 0,
456                        src_x, src_y,
457                        s->width, s->height, s->linesize,
458                        s->h_edge_pos, s->v_edge_pos,
459                        8, 8, pix_op,
460                        mv[i][0], mv[i][1]);
461        }
462    }
463
464    put_obmc(dest, ptr, s->linesize);
465}
466
467static inline void qpel_motion(MpegEncContext *s,
468                               uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
469                               int field_based, int bottom_field, int field_select,
470                               uint8_t **ref_picture, op_pixels_func (*pix_op)[4],
471                               qpel_mc_func (*qpix_op)[16],
472                               int motion_x, int motion_y, int h)
473{
474    uint8_t *ptr_y, *ptr_cb, *ptr_cr;
475    int dxy, uvdxy, mx, my, src_x, src_y, uvsrc_x, uvsrc_y, v_edge_pos, linesize, uvlinesize;
476
477    dxy = ((motion_y & 3) << 2) | (motion_x & 3);
478    src_x = s->mb_x *  16                 + (motion_x >> 2);
479    src_y = s->mb_y * (16 >> field_based) + (motion_y >> 2);
480
481    v_edge_pos = s->v_edge_pos >> field_based;
482    linesize = s->linesize << field_based;
483    uvlinesize = s->uvlinesize << field_based;
484
485    if(field_based){
486        mx= motion_x/2;
487        my= motion_y>>1;
488    }else if(s->workaround_bugs&FF_BUG_QPEL_CHROMA2){
489        static const int rtab[8]= {0,0,1,1,0,0,0,1};
490        mx= (motion_x>>1) + rtab[motion_x&7];
491        my= (motion_y>>1) + rtab[motion_y&7];
492    }else if(s->workaround_bugs&FF_BUG_QPEL_CHROMA){
493        mx= (motion_x>>1)|(motion_x&1);
494        my= (motion_y>>1)|(motion_y&1);
495    }else{
496        mx= motion_x/2;
497        my= motion_y/2;
498    }
499    mx= (mx>>1)|(mx&1);
500    my= (my>>1)|(my&1);
501
502    uvdxy= (mx&1) | ((my&1)<<1);
503    mx>>=1;
504    my>>=1;
505
506    uvsrc_x = s->mb_x *  8                 + mx;
507    uvsrc_y = s->mb_y * (8 >> field_based) + my;
508
509    ptr_y  = ref_picture[0] +   src_y *   linesize +   src_x;
510    ptr_cb = ref_picture[1] + uvsrc_y * uvlinesize + uvsrc_x;
511    ptr_cr = ref_picture[2] + uvsrc_y * uvlinesize + uvsrc_x;
512
513    if(   (unsigned)src_x > s->h_edge_pos - (motion_x&3) - 16
514       || (unsigned)src_y >    v_edge_pos - (motion_y&3) - h  ){
515        s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr_y, s->linesize,
516                            17, 17+field_based, src_x, src_y<<field_based,
517                            s->h_edge_pos, s->v_edge_pos);
518        ptr_y= s->edge_emu_buffer;
519        if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){
520            uint8_t *uvbuf= s->edge_emu_buffer + 18*s->linesize;
521            s->dsp.emulated_edge_mc(uvbuf, ptr_cb, s->uvlinesize,
522                                9, 9 + field_based,
523                                uvsrc_x, uvsrc_y<<field_based,
524                                s->h_edge_pos>>1, s->v_edge_pos>>1);
525            s->dsp.emulated_edge_mc(uvbuf + 16, ptr_cr, s->uvlinesize,
526                                9, 9 + field_based,
527                                uvsrc_x, uvsrc_y<<field_based,
528                                s->h_edge_pos>>1, s->v_edge_pos>>1);
529            ptr_cb= uvbuf;
530            ptr_cr= uvbuf + 16;
531        }
532    }
533
534    if(!field_based)
535        qpix_op[0][dxy](dest_y, ptr_y, linesize);
536    else{
537        if(bottom_field){
538            dest_y += s->linesize;
539            dest_cb+= s->uvlinesize;
540            dest_cr+= s->uvlinesize;
541        }
542
543        if(field_select){
544            ptr_y  += s->linesize;
545            ptr_cb += s->uvlinesize;
546            ptr_cr += s->uvlinesize;
547        }
548        //damn interlaced mode
549        //FIXME boundary mirroring is not exactly correct here
550        qpix_op[1][dxy](dest_y  , ptr_y  , linesize);
551        qpix_op[1][dxy](dest_y+8, ptr_y+8, linesize);
552    }
553    if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){
554        pix_op[1][uvdxy](dest_cr, ptr_cr, uvlinesize, h >> 1);
555        pix_op[1][uvdxy](dest_cb, ptr_cb, uvlinesize, h >> 1);
556    }
557}
558
559/**
560 * h263 chroma 4mv motion compensation.
561 */
562static inline void chroma_4mv_motion(MpegEncContext *s,
563                                     uint8_t *dest_cb, uint8_t *dest_cr,
564                                     uint8_t **ref_picture,
565                                     op_pixels_func *pix_op,
566                                     int mx, int my){
567    int dxy, emu=0, src_x, src_y, offset;
568    uint8_t *ptr;
569
570    /* In case of 8X8, we construct a single chroma motion vector
571       with a special rounding */
572    mx= ff_h263_round_chroma(mx);
573    my= ff_h263_round_chroma(my);
574
575    dxy = ((my & 1) << 1) | (mx & 1);
576    mx >>= 1;
577    my >>= 1;
578
579    src_x = s->mb_x * 8 + mx;
580    src_y = s->mb_y * 8 + my;
581    src_x = av_clip(src_x, -8, (s->width >> 1));
582    if (src_x == (s->width >> 1))
583        dxy &= ~1;
584    src_y = av_clip(src_y, -8, (s->height >> 1));
585    if (src_y == (s->height >> 1))
586        dxy &= ~2;
587
588    offset = src_y * s->uvlinesize + src_x;
589    ptr = ref_picture[1] + offset;
590    if(s->flags&CODEC_FLAG_EMU_EDGE){
591        if(   (unsigned)src_x > (s->h_edge_pos>>1) - (dxy &1) - 8
592           || (unsigned)src_y > (s->v_edge_pos>>1) - (dxy>>1) - 8){
593            s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize,
594                                9, 9, src_x, src_y,
595                                s->h_edge_pos>>1, s->v_edge_pos>>1);
596            ptr= s->edge_emu_buffer;
597            emu=1;
598        }
599    }
600    pix_op[dxy](dest_cb, ptr, s->uvlinesize, 8);
601
602    ptr = ref_picture[2] + offset;
603    if(emu){
604        s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize,
605                            9, 9, src_x, src_y,
606                            s->h_edge_pos>>1, s->v_edge_pos>>1);
607        ptr= s->edge_emu_buffer;
608    }
609    pix_op[dxy](dest_cr, ptr, s->uvlinesize, 8);
610}
611
612static inline void prefetch_motion(MpegEncContext *s, uint8_t **pix, int dir){
613    /* fetch pixels for estimated mv 4 macroblocks ahead
614     * optimized for 64byte cache lines */
615    const int shift = s->quarter_sample ? 2 : 1;
616    const int mx= (s->mv[dir][0][0]>>shift) + 16*s->mb_x + 8;
617    const int my= (s->mv[dir][0][1]>>shift) + 16*s->mb_y;
618    int off= mx + (my + (s->mb_x&3)*4)*s->linesize + 64;
619    s->dsp.prefetch(pix[0]+off, s->linesize, 4);
620    off= (mx>>1) + ((my>>1) + (s->mb_x&7))*s->uvlinesize + 64;
621    s->dsp.prefetch(pix[1]+off, pix[2]-pix[1], 2);
622}
623
624/**
625 * motion compensation of a single macroblock
626 * @param s context
627 * @param dest_y luma destination pointer
628 * @param dest_cb chroma cb/u destination pointer
629 * @param dest_cr chroma cr/v destination pointer
630 * @param dir direction (0->forward, 1->backward)
631 * @param ref_picture array[3] of pointers to the 3 planes of the reference picture
632 * @param pix_op halfpel motion compensation function (average or put normally)
633 * @param qpix_op qpel motion compensation function (average or put normally)
634 * the motion vectors are taken from s->mv and the MV type from s->mv_type
635 */
636static av_always_inline void MPV_motion_internal(MpegEncContext *s,
637                              uint8_t *dest_y, uint8_t *dest_cb,
638                              uint8_t *dest_cr, int dir,
639                              uint8_t **ref_picture,
640                              op_pixels_func (*pix_op)[4],
641                              qpel_mc_func (*qpix_op)[16], int is_mpeg12)
642{
643    int dxy, mx, my, src_x, src_y, motion_x, motion_y;
644    int mb_x, mb_y, i;
645    uint8_t *ptr, *dest;
646
647    mb_x = s->mb_x;
648    mb_y = s->mb_y;
649
650    prefetch_motion(s, ref_picture, dir);
651
652    if(!is_mpeg12 && s->obmc && s->pict_type != AV_PICTURE_TYPE_B){
653        int16_t mv_cache[4][4][2];
654        const int xy= s->mb_x + s->mb_y*s->mb_stride;
655        const int mot_stride= s->b8_stride;
656        const int mot_xy= mb_x*2 + mb_y*2*mot_stride;
657
658        assert(!s->mb_skipped);
659
660        memcpy(mv_cache[1][1], s->current_picture.f.motion_val[0][mot_xy             ], sizeof(int16_t) * 4);
661        memcpy(mv_cache[2][1], s->current_picture.f.motion_val[0][mot_xy + mot_stride], sizeof(int16_t) * 4);
662        memcpy(mv_cache[3][1], s->current_picture.f.motion_val[0][mot_xy + mot_stride], sizeof(int16_t) * 4);
663
664        if (mb_y == 0 || IS_INTRA(s->current_picture.f.mb_type[xy - s->mb_stride])) {
665            memcpy(mv_cache[0][1], mv_cache[1][1], sizeof(int16_t)*4);
666        }else{
667            memcpy(mv_cache[0][1], s->current_picture.f.motion_val[0][mot_xy - mot_stride], sizeof(int16_t) * 4);
668        }
669
670        if (mb_x == 0 || IS_INTRA(s->current_picture.f.mb_type[xy - 1])) {
671            AV_COPY32(mv_cache[1][0], mv_cache[1][1]);
672            AV_COPY32(mv_cache[2][0], mv_cache[2][1]);
673        }else{
674            AV_COPY32(mv_cache[1][0], s->current_picture.f.motion_val[0][mot_xy - 1]);
675            AV_COPY32(mv_cache[2][0], s->current_picture.f.motion_val[0][mot_xy - 1 + mot_stride]);
676        }
677
678        if (mb_x + 1 >= s->mb_width || IS_INTRA(s->current_picture.f.mb_type[xy + 1])) {
679            AV_COPY32(mv_cache[1][3], mv_cache[1][2]);
680            AV_COPY32(mv_cache[2][3], mv_cache[2][2]);
681        }else{
682            AV_COPY32(mv_cache[1][3], s->current_picture.f.motion_val[0][mot_xy + 2]);
683            AV_COPY32(mv_cache[2][3], s->current_picture.f.motion_val[0][mot_xy + 2 + mot_stride]);
684        }
685
686        mx = 0;
687        my = 0;
688        for(i=0;i<4;i++) {
689            const int x= (i&1)+1;
690            const int y= (i>>1)+1;
691            int16_t mv[5][2]= {
692                {mv_cache[y][x  ][0], mv_cache[y][x  ][1]},
693                {mv_cache[y-1][x][0], mv_cache[y-1][x][1]},
694                {mv_cache[y][x-1][0], mv_cache[y][x-1][1]},
695                {mv_cache[y][x+1][0], mv_cache[y][x+1][1]},
696                {mv_cache[y+1][x][0], mv_cache[y+1][x][1]}};
697            //FIXME cleanup
698            obmc_motion(s, dest_y + ((i & 1) * 8) + (i >> 1) * 8 * s->linesize,
699                        ref_picture[0],
700                        mb_x * 16 + (i & 1) * 8, mb_y * 16 + (i >>1) * 8,
701                        pix_op[1],
702                        mv);
703
704            mx += mv[0][0];
705            my += mv[0][1];
706        }
707        if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY))
708            chroma_4mv_motion(s, dest_cb, dest_cr, ref_picture, pix_op[1], mx, my);
709
710        return;
711    }
712
713    switch(s->mv_type) {
714    case MV_TYPE_16X16:
715        if(s->mcsel){
716            if(s->real_sprite_warping_points==1){
717                gmc1_motion(s, dest_y, dest_cb, dest_cr,
718                            ref_picture);
719            }else{
720                gmc_motion(s, dest_y, dest_cb, dest_cr,
721                            ref_picture);
722            }
723        }else if(!is_mpeg12 && s->quarter_sample){
724            qpel_motion(s, dest_y, dest_cb, dest_cr,
725                        0, 0, 0,
726                        ref_picture, pix_op, qpix_op,
727                        s->mv[dir][0][0], s->mv[dir][0][1], 16);
728        }else if(!is_mpeg12 && (CONFIG_WMV2_DECODER || CONFIG_WMV2_ENCODER) && s->mspel && s->codec_id == CODEC_ID_WMV2){
729            ff_mspel_motion(s, dest_y, dest_cb, dest_cr,
730                        ref_picture, pix_op,
731                        s->mv[dir][0][0], s->mv[dir][0][1], 16);
732        }else
733        {
734            mpeg_motion(s, dest_y, dest_cb, dest_cr,
735                        0, 0, 0,
736                        ref_picture, pix_op,
737                        s->mv[dir][0][0], s->mv[dir][0][1], 16, mb_y);
738        }
739        break;
740    case MV_TYPE_8X8:
741    if (!is_mpeg12) {
742        mx = 0;
743        my = 0;
744        if(s->quarter_sample){
745            for(i=0;i<4;i++) {
746                motion_x = s->mv[dir][i][0];
747                motion_y = s->mv[dir][i][1];
748
749                dxy = ((motion_y & 3) << 2) | (motion_x & 3);
750                src_x = mb_x * 16 + (motion_x >> 2) + (i & 1) * 8;
751                src_y = mb_y * 16 + (motion_y >> 2) + (i >>1) * 8;
752
753                /* WARNING: do no forget half pels */
754                src_x = av_clip(src_x, -16, s->width);
755                if (src_x == s->width)
756                    dxy &= ~3;
757                src_y = av_clip(src_y, -16, s->height);
758                if (src_y == s->height)
759                    dxy &= ~12;
760
761                ptr = ref_picture[0] + (src_y * s->linesize) + (src_x);
762                if(s->flags&CODEC_FLAG_EMU_EDGE){
763                    if(   (unsigned)src_x > s->h_edge_pos - (motion_x&3) - 8
764                       || (unsigned)src_y > s->v_edge_pos - (motion_y&3) - 8 ){
765                        s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr,
766                                            s->linesize, 9, 9,
767                                            src_x, src_y,
768                                            s->h_edge_pos, s->v_edge_pos);
769                        ptr= s->edge_emu_buffer;
770                    }
771                }
772                dest = dest_y + ((i & 1) * 8) + (i >> 1) * 8 * s->linesize;
773                qpix_op[1][dxy](dest, ptr, s->linesize);
774
775                mx += s->mv[dir][i][0]/2;
776                my += s->mv[dir][i][1]/2;
777            }
778        }else{
779            for(i=0;i<4;i++) {
780                hpel_motion(s, dest_y + ((i & 1) * 8) + (i >> 1) * 8 * s->linesize,
781                            ref_picture[0], 0, 0,
782                            mb_x * 16 + (i & 1) * 8, mb_y * 16 + (i >>1) * 8,
783                            s->width, s->height, s->linesize,
784                            s->h_edge_pos, s->v_edge_pos,
785                            8, 8, pix_op[1],
786                            s->mv[dir][i][0], s->mv[dir][i][1]);
787
788                mx += s->mv[dir][i][0];
789                my += s->mv[dir][i][1];
790            }
791        }
792
793        if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY))
794            chroma_4mv_motion(s, dest_cb, dest_cr, ref_picture, pix_op[1], mx, my);
795    }
796        break;
797    case MV_TYPE_FIELD:
798        if (s->picture_structure == PICT_FRAME) {
799            if(!is_mpeg12 && s->quarter_sample){
800                for(i=0; i<2; i++){
801                    qpel_motion(s, dest_y, dest_cb, dest_cr,
802                                1, i, s->field_select[dir][i],
803                                ref_picture, pix_op, qpix_op,
804                                s->mv[dir][i][0], s->mv[dir][i][1], 8);
805                }
806            }else{
807                /* top field */
808                mpeg_motion(s, dest_y, dest_cb, dest_cr,
809                            1, 0, s->field_select[dir][0],
810                            ref_picture, pix_op,
811                            s->mv[dir][0][0], s->mv[dir][0][1], 8, mb_y);
812                /* bottom field */
813                mpeg_motion(s, dest_y, dest_cb, dest_cr,
814                            1, 1, s->field_select[dir][1],
815                            ref_picture, pix_op,
816                            s->mv[dir][1][0], s->mv[dir][1][1], 8, mb_y);
817            }
818        } else {
819            if(s->picture_structure != s->field_select[dir][0] + 1 && s->pict_type != AV_PICTURE_TYPE_B && !s->first_field){
820                ref_picture = s->current_picture_ptr->f.data;
821            }
822
823            mpeg_motion(s, dest_y, dest_cb, dest_cr,
824                        0, 0, s->field_select[dir][0],
825                        ref_picture, pix_op,
826                        s->mv[dir][0][0], s->mv[dir][0][1], 16, mb_y>>1);
827        }
828        break;
829    case MV_TYPE_16X8:
830        for(i=0; i<2; i++){
831            uint8_t ** ref2picture;
832
833            if(s->picture_structure == s->field_select[dir][i] + 1
834               || s->pict_type == AV_PICTURE_TYPE_B || s->first_field){
835                ref2picture= ref_picture;
836            }else{
837                ref2picture = s->current_picture_ptr->f.data;
838            }
839
840            mpeg_motion(s, dest_y, dest_cb, dest_cr,
841                        0, 0, s->field_select[dir][i],
842                        ref2picture, pix_op,
843                        s->mv[dir][i][0], s->mv[dir][i][1] + 16*i, 8, mb_y>>1);
844
845            dest_y += 16*s->linesize;
846            dest_cb+= (16>>s->chroma_y_shift)*s->uvlinesize;
847            dest_cr+= (16>>s->chroma_y_shift)*s->uvlinesize;
848        }
849        break;
850    case MV_TYPE_DMV:
851        if(s->picture_structure == PICT_FRAME){
852            for(i=0; i<2; i++){
853                int j;
854                for(j=0; j<2; j++){
855                    mpeg_motion(s, dest_y, dest_cb, dest_cr,
856                                1, j, j^i,
857                                ref_picture, pix_op,
858                                s->mv[dir][2*i + j][0], s->mv[dir][2*i + j][1], 8, mb_y);
859                }
860                pix_op = s->dsp.avg_pixels_tab;
861            }
862        }else{
863            for(i=0; i<2; i++){
864                mpeg_motion(s, dest_y, dest_cb, dest_cr,
865                            0, 0, s->picture_structure != i+1,
866                            ref_picture, pix_op,
867                            s->mv[dir][2*i][0],s->mv[dir][2*i][1],16, mb_y>>1);
868
869                // after put we make avg of the same block
870                pix_op=s->dsp.avg_pixels_tab;
871
872                //opposite parity is always in the same frame if this is second field
873                if(!s->first_field){
874                    ref_picture = s->current_picture_ptr->f.data;
875                }
876            }
877        }
878    break;
879    default: assert(0);
880    }
881}
882
883static inline void MPV_motion(MpegEncContext *s,
884                              uint8_t *dest_y, uint8_t *dest_cb,
885                              uint8_t *dest_cr, int dir,
886                              uint8_t **ref_picture,
887                              op_pixels_func (*pix_op)[4],
888                              qpel_mc_func (*qpix_op)[16])
889{
890#if !CONFIG_SMALL
891    if(s->out_format == FMT_MPEG1)
892        MPV_motion_internal(s, dest_y, dest_cb, dest_cr, dir,
893                            ref_picture, pix_op, qpix_op, 1);
894    else
895#endif
896        MPV_motion_internal(s, dest_y, dest_cb, dest_cr, dir,
897                            ref_picture, pix_op, qpix_op, 0);
898}
899#endif /* AVCODEC_MPEGVIDEO_COMMON_H */