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 = 0;
00182 int emu=0;
00183
00184 src_x += motion_x >> 1;
00185 src_y += motion_y >> 1;
00186
00187
00188 src_x = av_clip(src_x, -16, s->width);
00189 if (src_x != s->width)
00190 dxy |= motion_x & 1;
00191 src_y = av_clip(src_y, -16, s->height);
00192 if (src_y != s->height)
00193 dxy |= (motion_y & 1) << 1;
00194 src += src_y * s->linesize + src_x;
00195
00196 if(s->unrestricted_mv && (s->flags&CODEC_FLAG_EMU_EDGE)){
00197 if( (unsigned)src_x > FFMAX(s->h_edge_pos - (motion_x&1) - 8, 0)
00198 || (unsigned)src_y > FFMAX(s->v_edge_pos - (motion_y&1) - 8, 0)){
00199 s->dsp.emulated_edge_mc(s->edge_emu_buffer, src, s->linesize, 9, 9,
00200 src_x, src_y, s->h_edge_pos, s->v_edge_pos);
00201 src= s->edge_emu_buffer;
00202 emu=1;
00203 }
00204 }
00205 pix_op[dxy](dest, src, s->linesize, 8);
00206 return emu;
00207 }
00208
00209 static av_always_inline
00210 void mpeg_motion_internal(MpegEncContext *s,
00211 uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
00212 int field_based, int bottom_field, int field_select,
00213 uint8_t **ref_picture, op_pixels_func (*pix_op)[4],
00214 int motion_x, int motion_y, int h, int is_mpeg12, int mb_y)
00215 {
00216 uint8_t *ptr_y, *ptr_cb, *ptr_cr;
00217 int dxy, uvdxy, mx, my, src_x, src_y,
00218 uvsrc_x, uvsrc_y, v_edge_pos, uvlinesize, linesize;
00219
00220 #if 0
00221 if(s->quarter_sample)
00222 {
00223 motion_x>>=1;
00224 motion_y>>=1;
00225 }
00226 #endif
00227
00228 v_edge_pos = s->v_edge_pos >> field_based;
00229 linesize = s->current_picture.f.linesize[0] << field_based;
00230 uvlinesize = s->current_picture.f.linesize[1] << field_based;
00231
00232 dxy = ((motion_y & 1) << 1) | (motion_x & 1);
00233 src_x = s->mb_x* 16 + (motion_x >> 1);
00234 src_y =( mb_y<<(4-field_based)) + (motion_y >> 1);
00235
00236 if (!is_mpeg12 && s->out_format == FMT_H263) {
00237 if((s->workaround_bugs & FF_BUG_HPEL_CHROMA) && field_based){
00238 mx = (motion_x>>1)|(motion_x&1);
00239 my = motion_y >>1;
00240 uvdxy = ((my & 1) << 1) | (mx & 1);
00241 uvsrc_x = s->mb_x* 8 + (mx >> 1);
00242 uvsrc_y =( mb_y<<(3-field_based))+ (my >> 1);
00243 }else{
00244 uvdxy = dxy | (motion_y & 2) | ((motion_x & 2) >> 1);
00245 uvsrc_x = src_x>>1;
00246 uvsrc_y = src_y>>1;
00247 }
00248 }else if(!is_mpeg12 && s->out_format == FMT_H261){
00249 mx = motion_x / 4;
00250 my = motion_y / 4;
00251 uvdxy = 0;
00252 uvsrc_x = s->mb_x*8 + mx;
00253 uvsrc_y = mb_y*8 + my;
00254 } else {
00255 if(s->chroma_y_shift){
00256 mx = motion_x / 2;
00257 my = motion_y / 2;
00258 uvdxy = ((my & 1) << 1) | (mx & 1);
00259 uvsrc_x = s->mb_x* 8 + (mx >> 1);
00260 uvsrc_y =( mb_y<<(3-field_based))+ (my >> 1);
00261 } else {
00262 if(s->chroma_x_shift){
00263
00264 mx = motion_x / 2;
00265 uvdxy = ((motion_y & 1) << 1) | (mx & 1);
00266 uvsrc_x = s->mb_x* 8 + (mx >> 1);
00267 uvsrc_y = src_y;
00268 } else {
00269
00270 uvdxy = dxy;
00271 uvsrc_x = src_x;
00272 uvsrc_y = src_y;
00273 }
00274 }
00275 }
00276
00277 ptr_y = ref_picture[0] + src_y * linesize + src_x;
00278 ptr_cb = ref_picture[1] + uvsrc_y * uvlinesize + uvsrc_x;
00279 ptr_cr = ref_picture[2] + uvsrc_y * uvlinesize + uvsrc_x;
00280
00281 if( (unsigned)src_x > FFMAX(s->h_edge_pos - (motion_x&1) - 16, 0)
00282 || (unsigned)src_y > FFMAX( v_edge_pos - (motion_y&1) - h , 0)){
00283 if(is_mpeg12 || s->codec_id == AV_CODEC_ID_MPEG2VIDEO ||
00284 s->codec_id == AV_CODEC_ID_MPEG1VIDEO){
00285 av_log(s->avctx,AV_LOG_DEBUG,
00286 "MPEG motion vector out of boundary (%d %d)\n", src_x, src_y);
00287 return;
00288 }
00289 s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr_y, s->linesize,
00290 17, 17+field_based,
00291 src_x, src_y<<field_based,
00292 s->h_edge_pos, s->v_edge_pos);
00293 ptr_y = s->edge_emu_buffer;
00294 if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){
00295 uint8_t *uvbuf= s->edge_emu_buffer+18*s->linesize;
00296 s->dsp.emulated_edge_mc(uvbuf ,
00297 ptr_cb, s->uvlinesize,
00298 9, 9+field_based,
00299 uvsrc_x, uvsrc_y<<field_based,
00300 s->h_edge_pos>>1, s->v_edge_pos>>1);
00301 s->dsp.emulated_edge_mc(uvbuf+16,
00302 ptr_cr, s->uvlinesize,
00303 9, 9+field_based,
00304 uvsrc_x, uvsrc_y<<field_based,
00305 s->h_edge_pos>>1, s->v_edge_pos>>1);
00306 ptr_cb= uvbuf;
00307 ptr_cr= uvbuf+16;
00308 }
00309 }
00310
00311 if(bottom_field){
00312 dest_y += s->linesize;
00313 dest_cb+= s->uvlinesize;
00314 dest_cr+= s->uvlinesize;
00315 }
00316
00317 if(field_select){
00318 ptr_y += s->linesize;
00319 ptr_cb+= s->uvlinesize;
00320 ptr_cr+= s->uvlinesize;
00321 }
00322
00323 pix_op[0][dxy](dest_y, ptr_y, linesize, h);
00324
00325 if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){
00326 pix_op[s->chroma_x_shift][uvdxy]
00327 (dest_cb, ptr_cb, uvlinesize, h >> s->chroma_y_shift);
00328 pix_op[s->chroma_x_shift][uvdxy]
00329 (dest_cr, ptr_cr, uvlinesize, h >> s->chroma_y_shift);
00330 }
00331 if(!is_mpeg12 && (CONFIG_H261_ENCODER || CONFIG_H261_DECODER) &&
00332 s->out_format == FMT_H261){
00333 ff_h261_loop_filter(s);
00334 }
00335 }
00336
00337 static void mpeg_motion(MpegEncContext *s,
00338 uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
00339 int field_select, uint8_t **ref_picture,
00340 op_pixels_func (*pix_op)[4],
00341 int motion_x, int motion_y, int h, int mb_y)
00342 {
00343 #if !CONFIG_SMALL
00344 if(s->out_format == FMT_MPEG1)
00345 mpeg_motion_internal(s, dest_y, dest_cb, dest_cr, 0, 0,
00346 field_select, ref_picture, pix_op,
00347 motion_x, motion_y, h, 1, mb_y);
00348 else
00349 #endif
00350 mpeg_motion_internal(s, dest_y, dest_cb, dest_cr, 0, 0,
00351 field_select, ref_picture, pix_op,
00352 motion_x, motion_y, h, 0, mb_y);
00353 }
00354
00355 static void mpeg_motion_field(MpegEncContext *s, uint8_t *dest_y,
00356 uint8_t *dest_cb, uint8_t *dest_cr,
00357 int bottom_field, int field_select,
00358 uint8_t **ref_picture,
00359 op_pixels_func (*pix_op)[4],
00360 int motion_x, int motion_y, int h, int mb_y)
00361 {
00362 #if !CONFIG_SMALL
00363 if(s->out_format == FMT_MPEG1)
00364 mpeg_motion_internal(s, dest_y, dest_cb, dest_cr, 1,
00365 bottom_field, field_select, ref_picture, pix_op,
00366 motion_x, motion_y, h, 1, mb_y);
00367 else
00368 #endif
00369 mpeg_motion_internal(s, dest_y, dest_cb, dest_cr, 1,
00370 bottom_field, field_select, ref_picture, pix_op,
00371 motion_x, motion_y, h, 0, mb_y);
00372 }
00373
00374
00375 static inline void put_obmc(uint8_t *dst, uint8_t *src[5], int stride){
00376 int x;
00377 uint8_t * const top = src[1];
00378 uint8_t * const left = src[2];
00379 uint8_t * const mid = src[0];
00380 uint8_t * const right = src[3];
00381 uint8_t * const bottom= src[4];
00382 #define OBMC_FILTER(x, t, l, m, r, b)\
00383 dst[x]= (t*top[x] + l*left[x] + m*mid[x] + r*right[x] + b*bottom[x] + 4)>>3
00384 #define OBMC_FILTER4(x, t, l, m, r, b)\
00385 OBMC_FILTER(x , t, l, m, r, b);\
00386 OBMC_FILTER(x+1 , t, l, m, r, b);\
00387 OBMC_FILTER(x +stride, t, l, m, r, b);\
00388 OBMC_FILTER(x+1+stride, t, l, m, r, b);
00389
00390 x=0;
00391 OBMC_FILTER (x , 2, 2, 4, 0, 0);
00392 OBMC_FILTER (x+1, 2, 1, 5, 0, 0);
00393 OBMC_FILTER4(x+2, 2, 1, 5, 0, 0);
00394 OBMC_FILTER4(x+4, 2, 0, 5, 1, 0);
00395 OBMC_FILTER (x+6, 2, 0, 5, 1, 0);
00396 OBMC_FILTER (x+7, 2, 0, 4, 2, 0);
00397 x+= stride;
00398 OBMC_FILTER (x , 1, 2, 5, 0, 0);
00399 OBMC_FILTER (x+1, 1, 2, 5, 0, 0);
00400 OBMC_FILTER (x+6, 1, 0, 5, 2, 0);
00401 OBMC_FILTER (x+7, 1, 0, 5, 2, 0);
00402 x+= stride;
00403 OBMC_FILTER4(x , 1, 2, 5, 0, 0);
00404 OBMC_FILTER4(x+2, 1, 1, 6, 0, 0);
00405 OBMC_FILTER4(x+4, 1, 0, 6, 1, 0);
00406 OBMC_FILTER4(x+6, 1, 0, 5, 2, 0);
00407 x+= 2*stride;
00408 OBMC_FILTER4(x , 0, 2, 5, 0, 1);
00409 OBMC_FILTER4(x+2, 0, 1, 6, 0, 1);
00410 OBMC_FILTER4(x+4, 0, 0, 6, 1, 1);
00411 OBMC_FILTER4(x+6, 0, 0, 5, 2, 1);
00412 x+= 2*stride;
00413 OBMC_FILTER (x , 0, 2, 5, 0, 1);
00414 OBMC_FILTER (x+1, 0, 2, 5, 0, 1);
00415 OBMC_FILTER4(x+2, 0, 1, 5, 0, 2);
00416 OBMC_FILTER4(x+4, 0, 0, 5, 1, 2);
00417 OBMC_FILTER (x+6, 0, 0, 5, 2, 1);
00418 OBMC_FILTER (x+7, 0, 0, 5, 2, 1);
00419 x+= stride;
00420 OBMC_FILTER (x , 0, 2, 4, 0, 2);
00421 OBMC_FILTER (x+1, 0, 1, 5, 0, 2);
00422 OBMC_FILTER (x+6, 0, 0, 5, 1, 2);
00423 OBMC_FILTER (x+7, 0, 0, 4, 2, 2);
00424 }
00425
00426
00427 static inline void obmc_motion(MpegEncContext *s,
00428 uint8_t *dest, uint8_t *src,
00429 int src_x, int src_y,
00430 op_pixels_func *pix_op,
00431 int16_t mv[5][2])
00432 #define MID 0
00433 {
00434 int i;
00435 uint8_t *ptr[5];
00436
00437 av_assert2(s->quarter_sample==0);
00438
00439 for(i=0; i<5; i++){
00440 if(i && mv[i][0]==mv[MID][0] && mv[i][1]==mv[MID][1]){
00441 ptr[i]= ptr[MID];
00442 }else{
00443 ptr[i]= s->obmc_scratchpad + 8*(i&1) + s->linesize*8*(i>>1);
00444 hpel_motion(s, ptr[i], src,
00445 src_x, src_y,
00446 pix_op,
00447 mv[i][0], mv[i][1]);
00448 }
00449 }
00450
00451 put_obmc(dest, ptr, s->linesize);
00452 }
00453
00454 static inline void qpel_motion(MpegEncContext *s,
00455 uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
00456 int field_based, int bottom_field, int field_select,
00457 uint8_t **ref_picture, op_pixels_func (*pix_op)[4],
00458 qpel_mc_func (*qpix_op)[16],
00459 int motion_x, int motion_y, int h)
00460 {
00461 uint8_t *ptr_y, *ptr_cb, *ptr_cr;
00462 int dxy, uvdxy, mx, my, src_x, src_y, uvsrc_x, uvsrc_y, v_edge_pos, linesize, uvlinesize;
00463
00464 dxy = ((motion_y & 3) << 2) | (motion_x & 3);
00465 src_x = s->mb_x * 16 + (motion_x >> 2);
00466 src_y = s->mb_y * (16 >> field_based) + (motion_y >> 2);
00467
00468 v_edge_pos = s->v_edge_pos >> field_based;
00469 linesize = s->linesize << field_based;
00470 uvlinesize = s->uvlinesize << field_based;
00471
00472 if(field_based){
00473 mx= motion_x/2;
00474 my= motion_y>>1;
00475 }else if(s->workaround_bugs&FF_BUG_QPEL_CHROMA2){
00476 static const int rtab[8]= {0,0,1,1,0,0,0,1};
00477 mx= (motion_x>>1) + rtab[motion_x&7];
00478 my= (motion_y>>1) + rtab[motion_y&7];
00479 }else if(s->workaround_bugs&FF_BUG_QPEL_CHROMA){
00480 mx= (motion_x>>1)|(motion_x&1);
00481 my= (motion_y>>1)|(motion_y&1);
00482 }else{
00483 mx= motion_x/2;
00484 my= motion_y/2;
00485 }
00486 mx= (mx>>1)|(mx&1);
00487 my= (my>>1)|(my&1);
00488
00489 uvdxy= (mx&1) | ((my&1)<<1);
00490 mx>>=1;
00491 my>>=1;
00492
00493 uvsrc_x = s->mb_x * 8 + mx;
00494 uvsrc_y = s->mb_y * (8 >> field_based) + my;
00495
00496 ptr_y = ref_picture[0] + src_y * linesize + src_x;
00497 ptr_cb = ref_picture[1] + uvsrc_y * uvlinesize + uvsrc_x;
00498 ptr_cr = ref_picture[2] + uvsrc_y * uvlinesize + uvsrc_x;
00499
00500 if( (unsigned)src_x > FFMAX(s->h_edge_pos - (motion_x&3) - 16, 0)
00501 || (unsigned)src_y > FFMAX( v_edge_pos - (motion_y&3) - h , 0)){
00502 s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr_y, s->linesize,
00503 17, 17+field_based, src_x, src_y<<field_based,
00504 s->h_edge_pos, s->v_edge_pos);
00505 ptr_y= s->edge_emu_buffer;
00506 if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){
00507 uint8_t *uvbuf= s->edge_emu_buffer + 18*s->linesize;
00508 s->dsp.emulated_edge_mc(uvbuf, ptr_cb, s->uvlinesize,
00509 9, 9 + field_based,
00510 uvsrc_x, uvsrc_y<<field_based,
00511 s->h_edge_pos>>1, s->v_edge_pos>>1);
00512 s->dsp.emulated_edge_mc(uvbuf + 16, ptr_cr, s->uvlinesize,
00513 9, 9 + field_based,
00514 uvsrc_x, uvsrc_y<<field_based,
00515 s->h_edge_pos>>1, s->v_edge_pos>>1);
00516 ptr_cb= uvbuf;
00517 ptr_cr= uvbuf + 16;
00518 }
00519 }
00520
00521 if(!field_based)
00522 qpix_op[0][dxy](dest_y, ptr_y, linesize);
00523 else{
00524 if(bottom_field){
00525 dest_y += s->linesize;
00526 dest_cb+= s->uvlinesize;
00527 dest_cr+= s->uvlinesize;
00528 }
00529
00530 if(field_select){
00531 ptr_y += s->linesize;
00532 ptr_cb += s->uvlinesize;
00533 ptr_cr += s->uvlinesize;
00534 }
00535
00536
00537 qpix_op[1][dxy](dest_y , ptr_y , linesize);
00538 qpix_op[1][dxy](dest_y+8, ptr_y+8, linesize);
00539 }
00540 if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)){
00541 pix_op[1][uvdxy](dest_cr, ptr_cr, uvlinesize, h >> 1);
00542 pix_op[1][uvdxy](dest_cb, ptr_cb, uvlinesize, h >> 1);
00543 }
00544 }
00545
00549 static void chroma_4mv_motion(MpegEncContext *s,
00550 uint8_t *dest_cb, uint8_t *dest_cr,
00551 uint8_t **ref_picture,
00552 op_pixels_func *pix_op,
00553 int mx, int my)
00554 {
00555 int dxy, emu=0, src_x, src_y, offset;
00556 uint8_t *ptr;
00557
00558
00559
00560 mx= ff_h263_round_chroma(mx);
00561 my= ff_h263_round_chroma(my);
00562
00563 dxy = ((my & 1) << 1) | (mx & 1);
00564 mx >>= 1;
00565 my >>= 1;
00566
00567 src_x = s->mb_x * 8 + mx;
00568 src_y = s->mb_y * 8 + my;
00569 src_x = av_clip(src_x, -8, (s->width >> 1));
00570 if (src_x == (s->width >> 1))
00571 dxy &= ~1;
00572 src_y = av_clip(src_y, -8, (s->height >> 1));
00573 if (src_y == (s->height >> 1))
00574 dxy &= ~2;
00575
00576 offset = src_y * s->uvlinesize + src_x;
00577 ptr = ref_picture[1] + offset;
00578 if(s->flags&CODEC_FLAG_EMU_EDGE){
00579 if( (unsigned)src_x > FFMAX((s->h_edge_pos>>1) - (dxy &1) - 8, 0)
00580 || (unsigned)src_y > FFMAX((s->v_edge_pos>>1) - (dxy>>1) - 8, 0)){
00581 s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize,
00582 9, 9, src_x, src_y,
00583 s->h_edge_pos>>1, s->v_edge_pos>>1);
00584 ptr= s->edge_emu_buffer;
00585 emu=1;
00586 }
00587 }
00588 pix_op[dxy](dest_cb, ptr, s->uvlinesize, 8);
00589
00590 ptr = ref_picture[2] + offset;
00591 if(emu){
00592 s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize,
00593 9, 9, src_x, src_y,
00594 s->h_edge_pos>>1, s->v_edge_pos>>1);
00595 ptr= s->edge_emu_buffer;
00596 }
00597 pix_op[dxy](dest_cr, ptr, s->uvlinesize, 8);
00598 }
00599
00600 static inline void prefetch_motion(MpegEncContext *s, uint8_t **pix, int dir){
00601
00602
00603 const int shift = s->quarter_sample ? 2 : 1;
00604 const int mx= (s->mv[dir][0][0]>>shift) + 16*s->mb_x + 8;
00605 const int my= (s->mv[dir][0][1]>>shift) + 16*s->mb_y;
00606 int off= mx + (my + (s->mb_x&3)*4)*s->linesize + 64;
00607 s->dsp.prefetch(pix[0]+off, s->linesize, 4);
00608 off= (mx>>1) + ((my>>1) + (s->mb_x&7))*s->uvlinesize + 64;
00609 s->dsp.prefetch(pix[1]+off, pix[2]-pix[1], 2);
00610 }
00611
00624 static av_always_inline void MPV_motion_internal(MpegEncContext *s,
00625 uint8_t *dest_y, uint8_t *dest_cb,
00626 uint8_t *dest_cr, int dir,
00627 uint8_t **ref_picture,
00628 op_pixels_func (*pix_op)[4],
00629 qpel_mc_func (*qpix_op)[16], int is_mpeg12)
00630 {
00631 int dxy, mx, my, src_x, src_y, motion_x, motion_y;
00632 int mb_x, mb_y, i;
00633 uint8_t *ptr, *dest;
00634
00635 mb_x = s->mb_x;
00636 mb_y = s->mb_y;
00637
00638 prefetch_motion(s, ref_picture, dir);
00639
00640 if(!is_mpeg12 && s->obmc && s->pict_type != AV_PICTURE_TYPE_B){
00641 LOCAL_ALIGNED_8(int16_t, mv_cache, [4], [4][2]);
00642 AVFrame *cur_frame = &s->current_picture.f;
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 AV_COPY32(mv_cache[1][1], cur_frame->motion_val[0][mot_xy ]);
00650 AV_COPY32(mv_cache[1][2], cur_frame->motion_val[0][mot_xy + 1]);
00651
00652 AV_COPY32(mv_cache[2][1], cur_frame->motion_val[0][mot_xy + mot_stride ]);
00653 AV_COPY32(mv_cache[2][2], cur_frame->motion_val[0][mot_xy + mot_stride + 1]);
00654
00655 AV_COPY32(mv_cache[3][1], cur_frame->motion_val[0][mot_xy + mot_stride ]);
00656 AV_COPY32(mv_cache[3][2], cur_frame->motion_val[0][mot_xy + mot_stride + 1]);
00657
00658 if (mb_y == 0 || IS_INTRA(cur_frame->mb_type[xy - s->mb_stride])) {
00659 AV_COPY32(mv_cache[0][1], mv_cache[1][1]);
00660 AV_COPY32(mv_cache[0][2], mv_cache[1][2]);
00661 }else{
00662 AV_COPY32(mv_cache[0][1], cur_frame->motion_val[0][mot_xy - mot_stride ]);
00663 AV_COPY32(mv_cache[0][2], cur_frame->motion_val[0][mot_xy - mot_stride + 1]);
00664 }
00665
00666 if (mb_x == 0 || IS_INTRA(cur_frame->mb_type[xy - 1])) {
00667 AV_COPY32(mv_cache[1][0], mv_cache[1][1]);
00668 AV_COPY32(mv_cache[2][0], mv_cache[2][1]);
00669 }else{
00670 AV_COPY32(mv_cache[1][0], cur_frame->motion_val[0][mot_xy - 1]);
00671 AV_COPY32(mv_cache[2][0], cur_frame->motion_val[0][mot_xy - 1 + mot_stride]);
00672 }
00673
00674 if (mb_x + 1 >= s->mb_width || IS_INTRA(cur_frame->mb_type[xy + 1])) {
00675 AV_COPY32(mv_cache[1][3], mv_cache[1][2]);
00676 AV_COPY32(mv_cache[2][3], mv_cache[2][2]);
00677 }else{
00678 AV_COPY32(mv_cache[1][3], cur_frame->motion_val[0][mot_xy + 2]);
00679 AV_COPY32(mv_cache[2][3], cur_frame->motion_val[0][mot_xy + 2 + mot_stride]);
00680 }
00681
00682 mx = 0;
00683 my = 0;
00684 for(i=0;i<4;i++) {
00685 const int x= (i&1)+1;
00686 const int y= (i>>1)+1;
00687 int16_t mv[5][2]= {
00688 {mv_cache[y][x ][0], mv_cache[y][x ][1]},
00689 {mv_cache[y-1][x][0], mv_cache[y-1][x][1]},
00690 {mv_cache[y][x-1][0], mv_cache[y][x-1][1]},
00691 {mv_cache[y][x+1][0], mv_cache[y][x+1][1]},
00692 {mv_cache[y+1][x][0], mv_cache[y+1][x][1]}};
00693
00694 obmc_motion(s, dest_y + ((i & 1) * 8) + (i >> 1) * 8 * s->linesize,
00695 ref_picture[0],
00696 mb_x * 16 + (i & 1) * 8, mb_y * 16 + (i >>1) * 8,
00697 pix_op[1],
00698 mv);
00699
00700 mx += mv[0][0];
00701 my += mv[0][1];
00702 }
00703 if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY))
00704 chroma_4mv_motion(s, dest_cb, dest_cr, ref_picture, pix_op[1], mx, my);
00705
00706 return;
00707 }
00708
00709 switch(s->mv_type) {
00710 case MV_TYPE_16X16:
00711 if(s->mcsel){
00712 if(s->real_sprite_warping_points==1){
00713 gmc1_motion(s, dest_y, dest_cb, dest_cr,
00714 ref_picture);
00715 }else{
00716 gmc_motion(s, dest_y, dest_cb, dest_cr,
00717 ref_picture);
00718 }
00719 }else if(!is_mpeg12 && s->quarter_sample){
00720 qpel_motion(s, dest_y, dest_cb, dest_cr,
00721 0, 0, 0,
00722 ref_picture, pix_op, qpix_op,
00723 s->mv[dir][0][0], s->mv[dir][0][1], 16);
00724 } else if (!is_mpeg12 && (CONFIG_WMV2_DECODER || CONFIG_WMV2_ENCODER) &&
00725 s->mspel && s->codec_id == AV_CODEC_ID_WMV2) {
00726 ff_mspel_motion(s, dest_y, dest_cb, dest_cr,
00727 ref_picture, pix_op,
00728 s->mv[dir][0][0], s->mv[dir][0][1], 16);
00729 }else
00730 {
00731 mpeg_motion(s, dest_y, dest_cb, dest_cr, 0,
00732 ref_picture, pix_op,
00733 s->mv[dir][0][0], s->mv[dir][0][1], 16, mb_y);
00734 }
00735 break;
00736 case MV_TYPE_8X8:
00737 if (!is_mpeg12) {
00738 mx = 0;
00739 my = 0;
00740 if(s->quarter_sample){
00741 for(i=0;i<4;i++) {
00742 motion_x = s->mv[dir][i][0];
00743 motion_y = s->mv[dir][i][1];
00744
00745 dxy = ((motion_y & 3) << 2) | (motion_x & 3);
00746 src_x = mb_x * 16 + (motion_x >> 2) + (i & 1) * 8;
00747 src_y = mb_y * 16 + (motion_y >> 2) + (i >>1) * 8;
00748
00749
00750 src_x = av_clip(src_x, -16, s->width);
00751 if (src_x == s->width)
00752 dxy &= ~3;
00753 src_y = av_clip(src_y, -16, s->height);
00754 if (src_y == s->height)
00755 dxy &= ~12;
00756
00757 ptr = ref_picture[0] + (src_y * s->linesize) + (src_x);
00758 if(s->flags&CODEC_FLAG_EMU_EDGE){
00759 if( (unsigned)src_x > FFMAX(s->h_edge_pos - (motion_x&3) - 8, 0)
00760 || (unsigned)src_y > FFMAX(s->v_edge_pos - (motion_y&3) - 8, 0)){
00761 s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr,
00762 s->linesize, 9, 9,
00763 src_x, src_y,
00764 s->h_edge_pos, s->v_edge_pos);
00765 ptr= s->edge_emu_buffer;
00766 }
00767 }
00768 dest = dest_y + ((i & 1) * 8) + (i >> 1) * 8 * s->linesize;
00769 qpix_op[1][dxy](dest, ptr, s->linesize);
00770
00771 mx += s->mv[dir][i][0]/2;
00772 my += s->mv[dir][i][1]/2;
00773 }
00774 }else{
00775 for(i=0;i<4;i++) {
00776 hpel_motion(s, dest_y + ((i & 1) * 8) + (i >> 1) * 8 * s->linesize,
00777 ref_picture[0],
00778 mb_x * 16 + (i & 1) * 8, mb_y * 16 + (i >>1) * 8,
00779 pix_op[1],
00780 s->mv[dir][i][0], s->mv[dir][i][1]);
00781
00782 mx += s->mv[dir][i][0];
00783 my += s->mv[dir][i][1];
00784 }
00785 }
00786
00787 if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY))
00788 chroma_4mv_motion(s, dest_cb, dest_cr, ref_picture, pix_op[1], mx, my);
00789 }
00790 break;
00791 case MV_TYPE_FIELD:
00792 if (s->picture_structure == PICT_FRAME) {
00793 if(!is_mpeg12 && s->quarter_sample){
00794 for(i=0; i<2; i++){
00795 qpel_motion(s, dest_y, dest_cb, dest_cr,
00796 1, i, s->field_select[dir][i],
00797 ref_picture, pix_op, qpix_op,
00798 s->mv[dir][i][0], s->mv[dir][i][1], 8);
00799 }
00800 }else{
00801
00802 mpeg_motion_field(s, dest_y, dest_cb, dest_cr,
00803 0, s->field_select[dir][0],
00804 ref_picture, pix_op,
00805 s->mv[dir][0][0], s->mv[dir][0][1], 8, mb_y);
00806
00807 mpeg_motion_field(s, dest_y, dest_cb, dest_cr,
00808 1, s->field_select[dir][1],
00809 ref_picture, pix_op,
00810 s->mv[dir][1][0], s->mv[dir][1][1], 8, mb_y);
00811 }
00812 } else {
00813 if(s->picture_structure != s->field_select[dir][0] + 1 && s->pict_type != AV_PICTURE_TYPE_B && !s->first_field){
00814 ref_picture = s->current_picture_ptr->f.data;
00815 }
00816
00817 mpeg_motion(s, dest_y, dest_cb, dest_cr,
00818 s->field_select[dir][0],
00819 ref_picture, pix_op,
00820 s->mv[dir][0][0], s->mv[dir][0][1], 16, mb_y>>1);
00821 }
00822 break;
00823 case MV_TYPE_16X8:
00824 for(i=0; i<2; i++){
00825 uint8_t ** ref2picture;
00826
00827 if(s->picture_structure == s->field_select[dir][i] + 1
00828 || s->pict_type == AV_PICTURE_TYPE_B || s->first_field){
00829 ref2picture= ref_picture;
00830 }else{
00831 ref2picture = s->current_picture_ptr->f.data;
00832 }
00833
00834 mpeg_motion(s, dest_y, dest_cb, dest_cr,
00835 s->field_select[dir][i],
00836 ref2picture, pix_op,
00837 s->mv[dir][i][0], s->mv[dir][i][1] + 16*i, 8, mb_y>>1);
00838
00839 dest_y += 16*s->linesize;
00840 dest_cb+= (16>>s->chroma_y_shift)*s->uvlinesize;
00841 dest_cr+= (16>>s->chroma_y_shift)*s->uvlinesize;
00842 }
00843 break;
00844 case MV_TYPE_DMV:
00845 if(s->picture_structure == PICT_FRAME){
00846 for(i=0; i<2; i++){
00847 int j;
00848 for(j=0; j<2; j++){
00849 mpeg_motion_field(s, dest_y, dest_cb, dest_cr,
00850 j, j^i, ref_picture, pix_op,
00851 s->mv[dir][2*i + j][0],
00852 s->mv[dir][2*i + j][1], 8, mb_y);
00853 }
00854 pix_op = s->dsp.avg_pixels_tab;
00855 }
00856 }else{
00857 for(i=0; i<2; i++){
00858 mpeg_motion(s, dest_y, dest_cb, dest_cr,
00859 s->picture_structure != i+1,
00860 ref_picture, pix_op,
00861 s->mv[dir][2*i][0],s->mv[dir][2*i][1],16, mb_y>>1);
00862
00863
00864 pix_op=s->dsp.avg_pixels_tab;
00865
00866
00867 if(!s->first_field){
00868 ref_picture = s->current_picture_ptr->f.data;
00869 }
00870 }
00871 }
00872 break;
00873 default: av_assert2(0);
00874 }
00875 }
00876
00877 void ff_MPV_motion(MpegEncContext *s,
00878 uint8_t *dest_y, uint8_t *dest_cb,
00879 uint8_t *dest_cr, int dir,
00880 uint8_t **ref_picture,
00881 op_pixels_func (*pix_op)[4],
00882 qpel_mc_func (*qpix_op)[16])
00883 {
00884 #if !CONFIG_SMALL
00885 if(s->out_format == FMT_MPEG1)
00886 MPV_motion_internal(s, dest_y, dest_cb, dest_cr, dir,
00887 ref_picture, pix_op, qpix_op, 1);
00888 else
00889 #endif
00890 MPV_motion_internal(s, dest_y, dest_cb, dest_cr, dir,
00891 ref_picture, pix_op, qpix_op, 0);
00892 }