00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <string.h>
00025 #include "libavutil/avassert.h"
00026 #include "avcodec.h"
00027 #include "dsputil.h"
00028 #include "mpegvideo.h"
00029 #include "mjpegenc.h"
00030 #include "msmpeg4.h"
00031 #include <limits.h>
00032
00033 static void gmc1_motion(MpegEncContext *s,
00034 uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
00035 uint8_t **ref_picture)
00036 {
00037 uint8_t *ptr;
00038 int offset, src_x, src_y, linesize, uvlinesize;
00039 int motion_x, motion_y;
00040 int emu=0;
00041
00042 motion_x= s->sprite_offset[0][0];
00043 motion_y= s->sprite_offset[0][1];
00044 src_x = s->mb_x * 16 + (motion_x >> (s->sprite_warping_accuracy+1));
00045 src_y = s->mb_y * 16 + (motion_y >> (s->sprite_warping_accuracy+1));
00046 motion_x<<=(3-s->sprite_warping_accuracy);
00047 motion_y<<=(3-s->sprite_warping_accuracy);
00048 src_x = av_clip(src_x, -16, s->width);
00049 if (src_x == s->width)
00050 motion_x =0;
00051 src_y = av_clip(src_y, -16, s->height);
00052 if (src_y == s->height)
00053 motion_y =0;
00054
00055 linesize = s->linesize;
00056 uvlinesize = s->uvlinesize;
00057
00058 ptr = ref_picture[0] + (src_y * linesize) + src_x;
00059
00060 if(s->flags&CODEC_FLAG_EMU_EDGE){
00061 if( (unsigned)src_x >= FFMAX(s->h_edge_pos - 17, 0)
00062 || (unsigned)src_y >= FFMAX(s->v_edge_pos - 17, 0)){
00063 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);
00064 ptr= s->edge_emu_buffer;
00065 }
00066 }
00067
00068 if((motion_x|motion_y)&7){
00069 s->dsp.gmc1(dest_y , ptr , linesize, 16, motion_x&15, motion_y&15, 128 - s->no_rounding);
00070 s->dsp.gmc1(dest_y+8, ptr+8, linesize, 16, motion_x&15, motion_y&15, 128 - s->no_rounding);
00071 }else{
00072 int dxy;
00073
00074 dxy= ((motion_x>>3)&1) | ((motion_y>>2)&2);
00075 if (s->no_rounding){
00076 s->dsp.put_no_rnd_pixels_tab[0][dxy](dest_y, ptr, linesize, 16);
00077 }else{
00078 s->dsp.put_pixels_tab [0][dxy](dest_y, ptr, linesize, 16);
00079 }
00080 }
00081
00082 if(CONFIG_GRAY && s->flags&CODEC_FLAG_GRAY) return;
00083
00084 motion_x= s->sprite_offset[1][0];
00085 motion_y= s->sprite_offset[1][1];
00086 src_x = s->mb_x * 8 + (motion_x >> (s->sprite_warping_accuracy+1));
00087 src_y = s->mb_y * 8 + (motion_y >> (s->sprite_warping_accuracy+1));
00088 motion_x<<=(3-s->sprite_warping_accuracy);
00089 motion_y<<=(3-s->sprite_warping_accuracy);
00090 src_x = av_clip(src_x, -8, s->width>>1);
00091 if (src_x == s->width>>1)
00092 motion_x =0;
00093 src_y = av_clip(src_y, -8, s->height>>1);
00094 if (src_y == s->height>>1)
00095 motion_y =0;
00096
00097 offset = (src_y * uvlinesize) + src_x;
00098 ptr = ref_picture[1] + offset;
00099 if(s->flags&CODEC_FLAG_EMU_EDGE){
00100 if( (unsigned)src_x >= FFMAX((s->h_edge_pos>>1) - 9, 0)
00101 || (unsigned)src_y >= FFMAX((s->v_edge_pos>>1) - 9, 0)){
00102 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);
00103 ptr= s->edge_emu_buffer;
00104 emu=1;
00105 }
00106 }
00107 s->dsp.gmc1(dest_cb, ptr, uvlinesize, 8, motion_x&15, motion_y&15, 128 - s->no_rounding);
00108
00109 ptr = ref_picture[2] + offset;
00110 if(emu){
00111 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);
00112 ptr= s->edge_emu_buffer;
00113 }
00114 s->dsp.gmc1(dest_cr, ptr, uvlinesize, 8, motion_x&15, motion_y&15, 128 - s->no_rounding);
00115
00116 return;
00117 }
00118
00119 static void gmc_motion(MpegEncContext *s,
00120 uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
00121 uint8_t **ref_picture)
00122 {
00123 uint8_t *ptr;
00124 int linesize, uvlinesize;
00125 const int a= s->sprite_warping_accuracy;
00126 int ox, oy;
00127
00128 linesize = s->linesize;
00129 uvlinesize = s->uvlinesize;
00130
00131 ptr = ref_picture[0];
00132
00133 ox= s->sprite_offset[0][0] + s->sprite_delta[0][0]*s->mb_x*16 + s->sprite_delta[0][1]*s->mb_y*16;
00134 oy= s->sprite_offset[0][1] + s->sprite_delta[1][0]*s->mb_x*16 + s->sprite_delta[1][1]*s->mb_y*16;
00135
00136 s->dsp.gmc(dest_y, ptr, linesize, 16,
00137 ox,
00138 oy,
00139 s->sprite_delta[0][0], s->sprite_delta[0][1],
00140 s->sprite_delta[1][0], s->sprite_delta[1][1],
00141 a+1, (1<<(2*a+1)) - s->no_rounding,
00142 s->h_edge_pos, s->v_edge_pos);
00143 s->dsp.gmc(dest_y+8, ptr, linesize, 16,
00144 ox + s->sprite_delta[0][0]*8,
00145 oy + s->sprite_delta[1][0]*8,
00146 s->sprite_delta[0][0], s->sprite_delta[0][1],
00147 s->sprite_delta[1][0], s->sprite_delta[1][1],
00148 a+1, (1<<(2*a+1)) - s->no_rounding,
00149 s->h_edge_pos, s->v_edge_pos);
00150
00151 if(CONFIG_GRAY && s->flags&CODEC_FLAG_GRAY) return;
00152
00153 ox= s->sprite_offset[1][0] + s->sprite_delta[0][0]*s->mb_x*8 + s->sprite_delta[0][1]*s->mb_y*8;
00154 oy= s->sprite_offset[1][1] + s->sprite_delta[1][0]*s->mb_x*8 + s->sprite_delta[1][1]*s->mb_y*8;
00155
00156 ptr = ref_picture[1];
00157 s->dsp.gmc(dest_cb, ptr, uvlinesize, 8,
00158 ox,
00159 oy,
00160 s->sprite_delta[0][0], s->sprite_delta[0][1],
00161 s->sprite_delta[1][0], s->sprite_delta[1][1],
00162 a+1, (1<<(2*a+1)) - s->no_rounding,
00163 s->h_edge_pos>>1, s->v_edge_pos>>1);
00164
00165 ptr = ref_picture[2];
00166 s->dsp.gmc(dest_cr, ptr, uvlinesize, 8,
00167 ox,
00168 oy,
00169 s->sprite_delta[0][0], s->sprite_delta[0][1],
00170 s->sprite_delta[1][0], s->sprite_delta[1][1],
00171 a+1, (1<<(2*a+1)) - s->no_rounding,
00172 s->h_edge_pos>>1, s->v_edge_pos>>1);
00173 }
00174
00175 static inline int hpel_motion(MpegEncContext *s,
00176 uint8_t *dest, uint8_t *src,
00177 int src_x, int src_y,
00178 op_pixels_func *pix_op,
00179 int motion_x, int motion_y)
00180 {
00181 int dxy;
00182 int emu=0;
00183
00184 dxy = ((motion_y & 1) << 1) | (motion_x & 1);
00185 src_x += motion_x >> 1;
00186 src_y += motion_y >> 1;
00187
00188
00189 src_x = av_clip(src_x, -16, s->width);
00190 if (src_x == s->width)
00191 dxy &= ~1;
00192 src_y = av_clip(src_y, -16, s->height);
00193 if (src_y == s->height)
00194 dxy &= ~2;
00195 src += src_y * s->linesize + src_x;
00196
00197 if(s->unrestricted_mv && (s->flags&CODEC_FLAG_EMU_EDGE)){
00198 if( (unsigned)src_x > FFMAX(s->h_edge_pos - (motion_x&1) - 8, 0)
00199 || (unsigned)src_y > FFMAX(s->v_edge_pos - (motion_y&1) - 8, 0)){
00200 s->dsp.emulated_edge_mc(s->edge_emu_buffer, src, s->linesize, 9, 9,
00201 src_x, src_y, s->h_edge_pos, s->v_edge_pos);
00202 src= s->edge_emu_buffer;
00203 emu=1;
00204 }
00205 }
00206 pix_op[dxy](dest, src, s->linesize, 8);
00207 return emu;
00208 }
00209
00210 static av_always_inline
00211 void mpeg_motion_internal(MpegEncContext *s,
00212 uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
00213 int field_based, int bottom_field, int field_select,
00214 uint8_t **ref_picture, op_pixels_func (*pix_op)[4],
00215 int motion_x, int motion_y, int h, int is_mpeg12, int mb_y)
00216 {
00217 uint8_t *ptr_y, *ptr_cb, *ptr_cr;
00218 int dxy, uvdxy, mx, my, src_x, src_y,
00219 uvsrc_x, uvsrc_y, v_edge_pos, uvlinesize, linesize;
00220
00221 #if 0
00222 if(s->quarter_sample)
00223 {
00224 motion_x>>=1;
00225 motion_y>>=1;
00226 }
00227 #endif
00228
00229 v_edge_pos = s->v_edge_pos >> field_based;
00230 linesize = s->current_picture.f.linesize[0] << field_based;
00231 uvlinesize = s->current_picture.f.linesize[1] << field_based;
00232
00233 dxy = ((motion_y & 1) << 1) | (motion_x & 1);
00234 src_x = s->mb_x* 16 + (motion_x >> 1);
00235 src_y =( mb_y<<(4-field_based)) + (motion_y >> 1);
00236
00237 if (!is_mpeg12 && s->out_format == FMT_H263) {
00238 if((s->workaround_bugs & FF_BUG_HPEL_CHROMA) && field_based){
00239 mx = (motion_x>>1)|(motion_x&1);
00240 my = motion_y >>1;
00241 uvdxy = ((my & 1) << 1) | (mx & 1);
00242 uvsrc_x = s->mb_x* 8 + (mx >> 1);
00243 uvsrc_y =( mb_y<<(3-field_based))+ (my >> 1);
00244 }else{
00245 uvdxy = dxy | (motion_y & 2) | ((motion_x & 2) >> 1);
00246 uvsrc_x = src_x>>1;
00247 uvsrc_y = src_y>>1;
00248 }
00249 }else if(!is_mpeg12 && s->out_format == FMT_H261){
00250 mx = motion_x / 4;
00251 my = motion_y / 4;
00252 uvdxy = 0;
00253 uvsrc_x = s->mb_x*8 + mx;
00254 uvsrc_y = mb_y*8 + my;
00255 } else {
00256 if(s->chroma_y_shift){
00257 mx = motion_x / 2;
00258 my = motion_y / 2;
00259 uvdxy = ((my & 1) << 1) | (mx & 1);
00260 uvsrc_x = s->mb_x* 8 + (mx >> 1);
00261 uvsrc_y =( mb_y<<(3-field_based))+ (my >> 1);
00262 } else {
00263 if(s->chroma_x_shift){
00264
00265 mx = motion_x / 2;
00266 uvdxy = ((motion_y & 1) << 1) | (mx & 1);
00267 uvsrc_x = s->mb_x* 8 + (mx >> 1);
00268 uvsrc_y = src_y;
00269 } else {
00270
00271 uvdxy = dxy;
00272 uvsrc_x = src_x;
00273 uvsrc_y = src_y;
00274 }
00275 }
00276 }
00277
00278 ptr_y = ref_picture[0] + src_y * linesize + src_x;
00279 ptr_cb = ref_picture[1] + uvsrc_y * uvlinesize + uvsrc_x;
00280 ptr_cr = ref_picture[2] + uvsrc_y * uvlinesize + uvsrc_x;
00281
00282 if( (unsigned)src_x > FFMAX(s->h_edge_pos - (motion_x&1) - 16, 0)
00283 || (unsigned)src_y > FFMAX( v_edge_pos - (motion_y&1) - h , 0)){
00284 if(is_mpeg12 || s->codec_id == AV_CODEC_ID_MPEG2VIDEO ||
00285 s->codec_id == AV_CODEC_ID_MPEG1VIDEO){
00286 av_log(s->avctx,AV_LOG_DEBUG,
00287 "MPEG motion vector out of boundary (%d %d)\n", src_x, src_y);
00288 return;
00289 }
00290 s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr_y, s->linesize,
00291 17, 17+field_based,
00292 src_x, src_y<<field_based,
00293 s->h_edge_pos, s->v_edge_pos);
00294 ptr_y = s->edge_emu_buffer;
00295 if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){
00296 uint8_t *uvbuf= s->edge_emu_buffer+18*s->linesize;
00297 s->dsp.emulated_edge_mc(uvbuf ,
00298 ptr_cb, s->uvlinesize,
00299 9, 9+field_based,
00300 uvsrc_x, uvsrc_y<<field_based,
00301 s->h_edge_pos>>1, s->v_edge_pos>>1);
00302 s->dsp.emulated_edge_mc(uvbuf+16,
00303 ptr_cr, s->uvlinesize,
00304 9, 9+field_based,
00305 uvsrc_x, uvsrc_y<<field_based,
00306 s->h_edge_pos>>1, s->v_edge_pos>>1);
00307 ptr_cb= uvbuf;
00308 ptr_cr= uvbuf+16;
00309 }
00310 }
00311
00312 if(bottom_field){
00313 dest_y += s->linesize;
00314 dest_cb+= s->uvlinesize;
00315 dest_cr+= s->uvlinesize;
00316 }
00317
00318 if(field_select){
00319 ptr_y += s->linesize;
00320 ptr_cb+= s->uvlinesize;
00321 ptr_cr+= s->uvlinesize;
00322 }
00323
00324 pix_op[0][dxy](dest_y, ptr_y, linesize, h);
00325
00326 if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){
00327 pix_op[s->chroma_x_shift][uvdxy]
00328 (dest_cb, ptr_cb, uvlinesize, h >> s->chroma_y_shift);
00329 pix_op[s->chroma_x_shift][uvdxy]
00330 (dest_cr, ptr_cr, uvlinesize, h >> s->chroma_y_shift);
00331 }
00332 if(!is_mpeg12 && (CONFIG_H261_ENCODER || CONFIG_H261_DECODER) &&
00333 s->out_format == FMT_H261){
00334 ff_h261_loop_filter(s);
00335 }
00336 }
00337
00338 static void mpeg_motion(MpegEncContext *s,
00339 uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
00340 int field_select, uint8_t **ref_picture,
00341 op_pixels_func (*pix_op)[4],
00342 int motion_x, int motion_y, int h, int mb_y)
00343 {
00344 #if !CONFIG_SMALL
00345 if(s->out_format == FMT_MPEG1)
00346 mpeg_motion_internal(s, dest_y, dest_cb, dest_cr, 0, 0,
00347 field_select, ref_picture, pix_op,
00348 motion_x, motion_y, h, 1, mb_y);
00349 else
00350 #endif
00351 mpeg_motion_internal(s, dest_y, dest_cb, dest_cr, 0, 0,
00352 field_select, ref_picture, pix_op,
00353 motion_x, motion_y, h, 0, mb_y);
00354 }
00355
00356 static void mpeg_motion_field(MpegEncContext *s, uint8_t *dest_y,
00357 uint8_t *dest_cb, uint8_t *dest_cr,
00358 int bottom_field, int field_select,
00359 uint8_t **ref_picture,
00360 op_pixels_func (*pix_op)[4],
00361 int motion_x, int motion_y, int h, int mb_y)
00362 {
00363 #if !CONFIG_SMALL
00364 if(s->out_format == FMT_MPEG1)
00365 mpeg_motion_internal(s, dest_y, dest_cb, dest_cr, 1,
00366 bottom_field, field_select, ref_picture, pix_op,
00367 motion_x, motion_y, h, 1, mb_y);
00368 else
00369 #endif
00370 mpeg_motion_internal(s, dest_y, dest_cb, dest_cr, 1,
00371 bottom_field, field_select, ref_picture, pix_op,
00372 motion_x, motion_y, h, 0, mb_y);
00373 }
00374
00375
00376 static inline void put_obmc(uint8_t *dst, uint8_t *src[5], int stride){
00377 int x;
00378 uint8_t * const top = src[1];
00379 uint8_t * const left = src[2];
00380 uint8_t * const mid = src[0];
00381 uint8_t * const right = src[3];
00382 uint8_t * const bottom= src[4];
00383 #define OBMC_FILTER(x, t, l, m, r, b)\
00384 dst[x]= (t*top[x] + l*left[x] + m*mid[x] + r*right[x] + b*bottom[x] + 4)>>3
00385 #define OBMC_FILTER4(x, t, l, m, r, b)\
00386 OBMC_FILTER(x , t, l, m, r, b);\
00387 OBMC_FILTER(x+1 , t, l, m, r, b);\
00388 OBMC_FILTER(x +stride, t, l, m, r, b);\
00389 OBMC_FILTER(x+1+stride, t, l, m, r, b);
00390
00391 x=0;
00392 OBMC_FILTER (x , 2, 2, 4, 0, 0);
00393 OBMC_FILTER (x+1, 2, 1, 5, 0, 0);
00394 OBMC_FILTER4(x+2, 2, 1, 5, 0, 0);
00395 OBMC_FILTER4(x+4, 2, 0, 5, 1, 0);
00396 OBMC_FILTER (x+6, 2, 0, 5, 1, 0);
00397 OBMC_FILTER (x+7, 2, 0, 4, 2, 0);
00398 x+= stride;
00399 OBMC_FILTER (x , 1, 2, 5, 0, 0);
00400 OBMC_FILTER (x+1, 1, 2, 5, 0, 0);
00401 OBMC_FILTER (x+6, 1, 0, 5, 2, 0);
00402 OBMC_FILTER (x+7, 1, 0, 5, 2, 0);
00403 x+= stride;
00404 OBMC_FILTER4(x , 1, 2, 5, 0, 0);
00405 OBMC_FILTER4(x+2, 1, 1, 6, 0, 0);
00406 OBMC_FILTER4(x+4, 1, 0, 6, 1, 0);
00407 OBMC_FILTER4(x+6, 1, 0, 5, 2, 0);
00408 x+= 2*stride;
00409 OBMC_FILTER4(x , 0, 2, 5, 0, 1);
00410 OBMC_FILTER4(x+2, 0, 1, 6, 0, 1);
00411 OBMC_FILTER4(x+4, 0, 0, 6, 1, 1);
00412 OBMC_FILTER4(x+6, 0, 0, 5, 2, 1);
00413 x+= 2*stride;
00414 OBMC_FILTER (x , 0, 2, 5, 0, 1);
00415 OBMC_FILTER (x+1, 0, 2, 5, 0, 1);
00416 OBMC_FILTER4(x+2, 0, 1, 5, 0, 2);
00417 OBMC_FILTER4(x+4, 0, 0, 5, 1, 2);
00418 OBMC_FILTER (x+6, 0, 0, 5, 2, 1);
00419 OBMC_FILTER (x+7, 0, 0, 5, 2, 1);
00420 x+= stride;
00421 OBMC_FILTER (x , 0, 2, 4, 0, 2);
00422 OBMC_FILTER (x+1, 0, 1, 5, 0, 2);
00423 OBMC_FILTER (x+6, 0, 0, 5, 1, 2);
00424 OBMC_FILTER (x+7, 0, 0, 4, 2, 2);
00425 }
00426
00427
00428 static inline void obmc_motion(MpegEncContext *s,
00429 uint8_t *dest, uint8_t *src,
00430 int src_x, int src_y,
00431 op_pixels_func *pix_op,
00432 int16_t mv[5][2])
00433 #define MID 0
00434 {
00435 int i;
00436 uint8_t *ptr[5];
00437
00438 av_assert2(s->quarter_sample==0);
00439
00440 for(i=0; i<5; i++){
00441 if(i && mv[i][0]==mv[MID][0] && mv[i][1]==mv[MID][1]){
00442 ptr[i]= ptr[MID];
00443 }else{
00444 ptr[i]= s->obmc_scratchpad + 8*(i&1) + s->linesize*8*(i>>1);
00445 hpel_motion(s, ptr[i], src,
00446 src_x, src_y,
00447 pix_op,
00448 mv[i][0], mv[i][1]);
00449 }
00450 }
00451
00452 put_obmc(dest, ptr, s->linesize);
00453 }
00454
00455 static inline void qpel_motion(MpegEncContext *s,
00456 uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
00457 int field_based, int bottom_field, int field_select,
00458 uint8_t **ref_picture, op_pixels_func (*pix_op)[4],
00459 qpel_mc_func (*qpix_op)[16],
00460 int motion_x, int motion_y, int h)
00461 {
00462 uint8_t *ptr_y, *ptr_cb, *ptr_cr;
00463 int dxy, uvdxy, mx, my, src_x, src_y, uvsrc_x, uvsrc_y, v_edge_pos, linesize, uvlinesize;
00464
00465 dxy = ((motion_y & 3) << 2) | (motion_x & 3);
00466 src_x = s->mb_x * 16 + (motion_x >> 2);
00467 src_y = s->mb_y * (16 >> field_based) + (motion_y >> 2);
00468
00469 v_edge_pos = s->v_edge_pos >> field_based;
00470 linesize = s->linesize << field_based;
00471 uvlinesize = s->uvlinesize << field_based;
00472
00473 if(field_based){
00474 mx= motion_x/2;
00475 my= motion_y>>1;
00476 }else if(s->workaround_bugs&FF_BUG_QPEL_CHROMA2){
00477 static const int rtab[8]= {0,0,1,1,0,0,0,1};
00478 mx= (motion_x>>1) + rtab[motion_x&7];
00479 my= (motion_y>>1) + rtab[motion_y&7];
00480 }else if(s->workaround_bugs&FF_BUG_QPEL_CHROMA){
00481 mx= (motion_x>>1)|(motion_x&1);
00482 my= (motion_y>>1)|(motion_y&1);
00483 }else{
00484 mx= motion_x/2;
00485 my= motion_y/2;
00486 }
00487 mx= (mx>>1)|(mx&1);
00488 my= (my>>1)|(my&1);
00489
00490 uvdxy= (mx&1) | ((my&1)<<1);
00491 mx>>=1;
00492 my>>=1;
00493
00494 uvsrc_x = s->mb_x * 8 + mx;
00495 uvsrc_y = s->mb_y * (8 >> field_based) + my;
00496
00497 ptr_y = ref_picture[0] + src_y * linesize + src_x;
00498 ptr_cb = ref_picture[1] + uvsrc_y * uvlinesize + uvsrc_x;
00499 ptr_cr = ref_picture[2] + uvsrc_y * uvlinesize + uvsrc_x;
00500
00501 if( (unsigned)src_x > FFMAX(s->h_edge_pos - (motion_x&3) - 16, 0)
00502 || (unsigned)src_y > FFMAX( v_edge_pos - (motion_y&3) - h , 0)){
00503 s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr_y, s->linesize,
00504 17, 17+field_based, src_x, src_y<<field_based,
00505 s->h_edge_pos, s->v_edge_pos);
00506 ptr_y= s->edge_emu_buffer;
00507 if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){
00508 uint8_t *uvbuf= s->edge_emu_buffer + 18*s->linesize;
00509 s->dsp.emulated_edge_mc(uvbuf, ptr_cb, s->uvlinesize,
00510 9, 9 + field_based,
00511 uvsrc_x, uvsrc_y<<field_based,
00512 s->h_edge_pos>>1, s->v_edge_pos>>1);
00513 s->dsp.emulated_edge_mc(uvbuf + 16, ptr_cr, s->uvlinesize,
00514 9, 9 + field_based,
00515 uvsrc_x, uvsrc_y<<field_based,
00516 s->h_edge_pos>>1, s->v_edge_pos>>1);
00517 ptr_cb= uvbuf;
00518 ptr_cr= uvbuf + 16;
00519 }
00520 }
00521
00522 if(!field_based)
00523 qpix_op[0][dxy](dest_y, ptr_y, linesize);
00524 else{
00525 if(bottom_field){
00526 dest_y += s->linesize;
00527 dest_cb+= s->uvlinesize;
00528 dest_cr+= s->uvlinesize;
00529 }
00530
00531 if(field_select){
00532 ptr_y += s->linesize;
00533 ptr_cb += s->uvlinesize;
00534 ptr_cr += s->uvlinesize;
00535 }
00536
00537
00538 qpix_op[1][dxy](dest_y , ptr_y , linesize);
00539 qpix_op[1][dxy](dest_y+8, ptr_y+8, linesize);
00540 }
00541 if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){
00542 pix_op[1][uvdxy](dest_cr, ptr_cr, uvlinesize, h >> 1);
00543 pix_op[1][uvdxy](dest_cb, ptr_cb, uvlinesize, h >> 1);
00544 }
00545 }
00546
00550 static void chroma_4mv_motion(MpegEncContext *s,
00551 uint8_t *dest_cb, uint8_t *dest_cr,
00552 uint8_t **ref_picture,
00553 op_pixels_func *pix_op,
00554 int mx, int my)
00555 {
00556 int dxy, emu=0, src_x, src_y, offset;
00557 uint8_t *ptr;
00558
00559
00560
00561 mx= ff_h263_round_chroma(mx);
00562 my= ff_h263_round_chroma(my);
00563
00564 dxy = ((my & 1) << 1) | (mx & 1);
00565 mx >>= 1;
00566 my >>= 1;
00567
00568 src_x = s->mb_x * 8 + mx;
00569 src_y = s->mb_y * 8 + my;
00570 src_x = av_clip(src_x, -8, (s->width >> 1));
00571 if (src_x == (s->width >> 1))
00572 dxy &= ~1;
00573 src_y = av_clip(src_y, -8, (s->height >> 1));
00574 if (src_y == (s->height >> 1))
00575 dxy &= ~2;
00576
00577 offset = src_y * s->uvlinesize + src_x;
00578 ptr = ref_picture[1] + offset;
00579 if(s->flags&CODEC_FLAG_EMU_EDGE){
00580 if( (unsigned)src_x > FFMAX((s->h_edge_pos>>1) - (dxy &1) - 8, 0)
00581 || (unsigned)src_y > FFMAX((s->v_edge_pos>>1) - (dxy>>1) - 8, 0)){
00582 s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize,
00583 9, 9, src_x, src_y,
00584 s->h_edge_pos>>1, s->v_edge_pos>>1);
00585 ptr= s->edge_emu_buffer;
00586 emu=1;
00587 }
00588 }
00589 pix_op[dxy](dest_cb, ptr, s->uvlinesize, 8);
00590
00591 ptr = ref_picture[2] + offset;
00592 if(emu){
00593 s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize,
00594 9, 9, src_x, src_y,
00595 s->h_edge_pos>>1, s->v_edge_pos>>1);
00596 ptr= s->edge_emu_buffer;
00597 }
00598 pix_op[dxy](dest_cr, ptr, s->uvlinesize, 8);
00599 }
00600
00601 static inline void prefetch_motion(MpegEncContext *s, uint8_t **pix, int dir){
00602
00603
00604 const int shift = s->quarter_sample ? 2 : 1;
00605 const int mx= (s->mv[dir][0][0]>>shift) + 16*s->mb_x + 8;
00606 const int my= (s->mv[dir][0][1]>>shift) + 16*s->mb_y;
00607 int off= mx + (my + (s->mb_x&3)*4)*s->linesize + 64;
00608 s->dsp.prefetch(pix[0]+off, s->linesize, 4);
00609 off= (mx>>1) + ((my>>1) + (s->mb_x&7))*s->uvlinesize + 64;
00610 s->dsp.prefetch(pix[1]+off, pix[2]-pix[1], 2);
00611 }
00612
00625 static av_always_inline void MPV_motion_internal(MpegEncContext *s,
00626 uint8_t *dest_y, uint8_t *dest_cb,
00627 uint8_t *dest_cr, int dir,
00628 uint8_t **ref_picture,
00629 op_pixels_func (*pix_op)[4],
00630 qpel_mc_func (*qpix_op)[16], int is_mpeg12)
00631 {
00632 int dxy, mx, my, src_x, src_y, motion_x, motion_y;
00633 int mb_x, mb_y, i;
00634 uint8_t *ptr, *dest;
00635
00636 mb_x = s->mb_x;
00637 mb_y = s->mb_y;
00638
00639 prefetch_motion(s, ref_picture, dir);
00640
00641 if(!is_mpeg12 && s->obmc && s->pict_type != AV_PICTURE_TYPE_B){
00642 int16_t mv_cache[4][4][2];
00643 const int xy= s->mb_x + s->mb_y*s->mb_stride;
00644 const int mot_stride= s->b8_stride;
00645 const int mot_xy= mb_x*2 + mb_y*2*mot_stride;
00646
00647 av_assert2(!s->mb_skipped);
00648
00649 memcpy(mv_cache[1][1], s->current_picture.f.motion_val[0][mot_xy ], sizeof(int16_t) * 4);
00650 memcpy(mv_cache[2][1], s->current_picture.f.motion_val[0][mot_xy + mot_stride], sizeof(int16_t) * 4);
00651 memcpy(mv_cache[3][1], s->current_picture.f.motion_val[0][mot_xy + mot_stride], sizeof(int16_t) * 4);
00652
00653 if (mb_y == 0 || IS_INTRA(s->current_picture.f.mb_type[xy - s->mb_stride])) {
00654 memcpy(mv_cache[0][1], mv_cache[1][1], sizeof(int16_t)*4);
00655 }else{
00656 memcpy(mv_cache[0][1], s->current_picture.f.motion_val[0][mot_xy - mot_stride], sizeof(int16_t) * 4);
00657 }
00658
00659 if (mb_x == 0 || IS_INTRA(s->current_picture.f.mb_type[xy - 1])) {
00660 AV_COPY32(mv_cache[1][0], mv_cache[1][1]);
00661 AV_COPY32(mv_cache[2][0], mv_cache[2][1]);
00662 }else{
00663 AV_COPY32(mv_cache[1][0], s->current_picture.f.motion_val[0][mot_xy - 1]);
00664 AV_COPY32(mv_cache[2][0], s->current_picture.f.motion_val[0][mot_xy - 1 + mot_stride]);
00665 }
00666
00667 if (mb_x + 1 >= s->mb_width || IS_INTRA(s->current_picture.f.mb_type[xy + 1])) {
00668 AV_COPY32(mv_cache[1][3], mv_cache[1][2]);
00669 AV_COPY32(mv_cache[2][3], mv_cache[2][2]);
00670 }else{
00671 AV_COPY32(mv_cache[1][3], s->current_picture.f.motion_val[0][mot_xy + 2]);
00672 AV_COPY32(mv_cache[2][3], s->current_picture.f.motion_val[0][mot_xy + 2 + mot_stride]);
00673 }
00674
00675 mx = 0;
00676 my = 0;
00677 for(i=0;i<4;i++) {
00678 const int x= (i&1)+1;
00679 const int y= (i>>1)+1;
00680 int16_t mv[5][2]= {
00681 {mv_cache[y][x ][0], mv_cache[y][x ][1]},
00682 {mv_cache[y-1][x][0], mv_cache[y-1][x][1]},
00683 {mv_cache[y][x-1][0], mv_cache[y][x-1][1]},
00684 {mv_cache[y][x+1][0], mv_cache[y][x+1][1]},
00685 {mv_cache[y+1][x][0], mv_cache[y+1][x][1]}};
00686
00687 obmc_motion(s, dest_y + ((i & 1) * 8) + (i >> 1) * 8 * s->linesize,
00688 ref_picture[0],
00689 mb_x * 16 + (i & 1) * 8, mb_y * 16 + (i >>1) * 8,
00690 pix_op[1],
00691 mv);
00692
00693 mx += mv[0][0];
00694 my += mv[0][1];
00695 }
00696 if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY))
00697 chroma_4mv_motion(s, dest_cb, dest_cr, ref_picture, pix_op[1], mx, my);
00698
00699 return;
00700 }
00701
00702 switch(s->mv_type) {
00703 case MV_TYPE_16X16:
00704 if(s->mcsel){
00705 if(s->real_sprite_warping_points==1){
00706 gmc1_motion(s, dest_y, dest_cb, dest_cr,
00707 ref_picture);
00708 }else{
00709 gmc_motion(s, dest_y, dest_cb, dest_cr,
00710 ref_picture);
00711 }
00712 }else if(!is_mpeg12 && s->quarter_sample){
00713 qpel_motion(s, dest_y, dest_cb, dest_cr,
00714 0, 0, 0,
00715 ref_picture, pix_op, qpix_op,
00716 s->mv[dir][0][0], s->mv[dir][0][1], 16);
00717 } else if (!is_mpeg12 && (CONFIG_WMV2_DECODER || CONFIG_WMV2_ENCODER) &&
00718 s->mspel && s->codec_id == AV_CODEC_ID_WMV2) {
00719 ff_mspel_motion(s, dest_y, dest_cb, dest_cr,
00720 ref_picture, pix_op,
00721 s->mv[dir][0][0], s->mv[dir][0][1], 16);
00722 }else
00723 {
00724 mpeg_motion(s, dest_y, dest_cb, dest_cr, 0,
00725 ref_picture, pix_op,
00726 s->mv[dir][0][0], s->mv[dir][0][1], 16, mb_y);
00727 }
00728 break;
00729 case MV_TYPE_8X8:
00730 if (!is_mpeg12) {
00731 mx = 0;
00732 my = 0;
00733 if(s->quarter_sample){
00734 for(i=0;i<4;i++) {
00735 motion_x = s->mv[dir][i][0];
00736 motion_y = s->mv[dir][i][1];
00737
00738 dxy = ((motion_y & 3) << 2) | (motion_x & 3);
00739 src_x = mb_x * 16 + (motion_x >> 2) + (i & 1) * 8;
00740 src_y = mb_y * 16 + (motion_y >> 2) + (i >>1) * 8;
00741
00742
00743 src_x = av_clip(src_x, -16, s->width);
00744 if (src_x == s->width)
00745 dxy &= ~3;
00746 src_y = av_clip(src_y, -16, s->height);
00747 if (src_y == s->height)
00748 dxy &= ~12;
00749
00750 ptr = ref_picture[0] + (src_y * s->linesize) + (src_x);
00751 if(s->flags&CODEC_FLAG_EMU_EDGE){
00752 if( (unsigned)src_x > FFMAX(s->h_edge_pos - (motion_x&3) - 8, 0)
00753 || (unsigned)src_y > FFMAX(s->v_edge_pos - (motion_y&3) - 8, 0)){
00754 s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr,
00755 s->linesize, 9, 9,
00756 src_x, src_y,
00757 s->h_edge_pos, s->v_edge_pos);
00758 ptr= s->edge_emu_buffer;
00759 }
00760 }
00761 dest = dest_y + ((i & 1) * 8) + (i >> 1) * 8 * s->linesize;
00762 qpix_op[1][dxy](dest, ptr, s->linesize);
00763
00764 mx += s->mv[dir][i][0]/2;
00765 my += s->mv[dir][i][1]/2;
00766 }
00767 }else{
00768 for(i=0;i<4;i++) {
00769 hpel_motion(s, dest_y + ((i & 1) * 8) + (i >> 1) * 8 * s->linesize,
00770 ref_picture[0],
00771 mb_x * 16 + (i & 1) * 8, mb_y * 16 + (i >>1) * 8,
00772 pix_op[1],
00773 s->mv[dir][i][0], s->mv[dir][i][1]);
00774
00775 mx += s->mv[dir][i][0];
00776 my += s->mv[dir][i][1];
00777 }
00778 }
00779
00780 if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY))
00781 chroma_4mv_motion(s, dest_cb, dest_cr, ref_picture, pix_op[1], mx, my);
00782 }
00783 break;
00784 case MV_TYPE_FIELD:
00785 if (s->picture_structure == PICT_FRAME) {
00786 if(!is_mpeg12 && s->quarter_sample){
00787 for(i=0; i<2; i++){
00788 qpel_motion(s, dest_y, dest_cb, dest_cr,
00789 1, i, s->field_select[dir][i],
00790 ref_picture, pix_op, qpix_op,
00791 s->mv[dir][i][0], s->mv[dir][i][1], 8);
00792 }
00793 }else{
00794
00795 mpeg_motion_field(s, dest_y, dest_cb, dest_cr,
00796 0, s->field_select[dir][0],
00797 ref_picture, pix_op,
00798 s->mv[dir][0][0], s->mv[dir][0][1], 8, mb_y);
00799
00800 mpeg_motion_field(s, dest_y, dest_cb, dest_cr,
00801 1, s->field_select[dir][1],
00802 ref_picture, pix_op,
00803 s->mv[dir][1][0], s->mv[dir][1][1], 8, mb_y);
00804 }
00805 } else {
00806 if(s->picture_structure != s->field_select[dir][0] + 1 && s->pict_type != AV_PICTURE_TYPE_B && !s->first_field){
00807 ref_picture = s->current_picture_ptr->f.data;
00808 }
00809
00810 mpeg_motion(s, dest_y, dest_cb, dest_cr,
00811 s->field_select[dir][0],
00812 ref_picture, pix_op,
00813 s->mv[dir][0][0], s->mv[dir][0][1], 16, mb_y>>1);
00814 }
00815 break;
00816 case MV_TYPE_16X8:
00817 for(i=0; i<2; i++){
00818 uint8_t ** ref2picture;
00819
00820 if(s->picture_structure == s->field_select[dir][i] + 1
00821 || s->pict_type == AV_PICTURE_TYPE_B || s->first_field){
00822 ref2picture= ref_picture;
00823 }else{
00824 ref2picture = s->current_picture_ptr->f.data;
00825 }
00826
00827 mpeg_motion(s, dest_y, dest_cb, dest_cr,
00828 s->field_select[dir][i],
00829 ref2picture, pix_op,
00830 s->mv[dir][i][0], s->mv[dir][i][1] + 16*i, 8, mb_y>>1);
00831
00832 dest_y += 16*s->linesize;
00833 dest_cb+= (16>>s->chroma_y_shift)*s->uvlinesize;
00834 dest_cr+= (16>>s->chroma_y_shift)*s->uvlinesize;
00835 }
00836 break;
00837 case MV_TYPE_DMV:
00838 if(s->picture_structure == PICT_FRAME){
00839 for(i=0; i<2; i++){
00840 int j;
00841 for(j=0; j<2; j++){
00842 mpeg_motion_field(s, dest_y, dest_cb, dest_cr,
00843 j, j^i, ref_picture, pix_op,
00844 s->mv[dir][2*i + j][0],
00845 s->mv[dir][2*i + j][1], 8, mb_y);
00846 }
00847 pix_op = s->dsp.avg_pixels_tab;
00848 }
00849 }else{
00850 for(i=0; i<2; i++){
00851 mpeg_motion(s, dest_y, dest_cb, dest_cr,
00852 s->picture_structure != i+1,
00853 ref_picture, pix_op,
00854 s->mv[dir][2*i][0],s->mv[dir][2*i][1],16, mb_y>>1);
00855
00856
00857 pix_op=s->dsp.avg_pixels_tab;
00858
00859
00860 if(!s->first_field){
00861 ref_picture = s->current_picture_ptr->f.data;
00862 }
00863 }
00864 }
00865 break;
00866 default: av_assert2(0);
00867 }
00868 }
00869
00870 void ff_MPV_motion(MpegEncContext *s,
00871 uint8_t *dest_y, uint8_t *dest_cb,
00872 uint8_t *dest_cr, int dir,
00873 uint8_t **ref_picture,
00874 op_pixels_func (*pix_op)[4],
00875 qpel_mc_func (*qpix_op)[16])
00876 {
00877 #if !CONFIG_SMALL
00878 if(s->out_format == FMT_MPEG1)
00879 MPV_motion_internal(s, dest_y, dest_cb, dest_cr, dir,
00880 ref_picture, pix_op, qpix_op, 1);
00881 else
00882 #endif
00883 MPV_motion_internal(s, dest_y, dest_cb, dest_cr, dir,
00884 ref_picture, pix_op, qpix_op, 0);
00885 }