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