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 Libav. 9 * 10 * Libav 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 * Libav 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 Libav; 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 >= FFMAX(s->h_edge_pos - 17, 0) 85 || (unsigned)src_y >= FFMAX(s->v_edge_pos - 17, 0)){ 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 >= FFMAX((s->h_edge_pos>>1) - 9, 0) 124 || (unsigned)src_y >= FFMAX((s->v_edge_pos>>1) - 9, 0)){ 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 > FFMAX(h_edge_pos - (motion_x&1) - w, 0) 225 || (unsigned)src_y > FFMAX(v_edge_pos - (motion_y&1) - h, 0)){ 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 > FFMAX(s->h_edge_pos - (motion_x&1) - 16, 0) 311 || (unsigned)src_y > FFMAX( v_edge_pos - (motion_y&1) - h , 0)){ 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 > FFMAX(s->h_edge_pos - (motion_x&3) - 16, 0) 514 || (unsigned)src_y > FFMAX( v_edge_pos - (motion_y&3) - h , 0)){ 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 > FFMAX((s->h_edge_pos>>1) - (dxy &1) - 8, 0) 592 || (unsigned)src_y > FFMAX((s->v_edge_pos>>1) - (dxy>>1) - 8, 0)){ 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) && 729 s->mspel && s->codec_id == CODEC_ID_WMV2) { 730 ff_mspel_motion(s, dest_y, dest_cb, dest_cr, 731 ref_picture, pix_op, 732 s->mv[dir][0][0], s->mv[dir][0][1], 16); 733 }else 734 { 735 mpeg_motion(s, dest_y, dest_cb, dest_cr, 736 0, 0, 0, 737 ref_picture, pix_op, 738 s->mv[dir][0][0], s->mv[dir][0][1], 16, mb_y); 739 } 740 break; 741 case MV_TYPE_8X8: 742 if (!is_mpeg12) { 743 mx = 0; 744 my = 0; 745 if(s->quarter_sample){ 746 for(i=0;i<4;i++) { 747 motion_x = s->mv[dir][i][0]; 748 motion_y = s->mv[dir][i][1]; 749 750 dxy = ((motion_y & 3) << 2) | (motion_x & 3); 751 src_x = mb_x * 16 + (motion_x >> 2) + (i & 1) * 8; 752 src_y = mb_y * 16 + (motion_y >> 2) + (i >>1) * 8; 753 754 /* WARNING: do no forget half pels */ 755 src_x = av_clip(src_x, -16, s->width); 756 if (src_x == s->width) 757 dxy &= ~3; 758 src_y = av_clip(src_y, -16, s->height); 759 if (src_y == s->height) 760 dxy &= ~12; 761 762 ptr = ref_picture[0] + (src_y * s->linesize) + (src_x); 763 if(s->flags&CODEC_FLAG_EMU_EDGE){ 764 if( (unsigned)src_x > FFMAX(s->h_edge_pos - (motion_x&3) - 8, 0) 765 || (unsigned)src_y > FFMAX(s->v_edge_pos - (motion_y&3) - 8, 0)){ 766 s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr, 767 s->linesize, 9, 9, 768 src_x, src_y, 769 s->h_edge_pos, s->v_edge_pos); 770 ptr= s->edge_emu_buffer; 771 } 772 } 773 dest = dest_y + ((i & 1) * 8) + (i >> 1) * 8 * s->linesize; 774 qpix_op[1][dxy](dest, ptr, s->linesize); 775 776 mx += s->mv[dir][i][0]/2; 777 my += s->mv[dir][i][1]/2; 778 } 779 }else{ 780 for(i=0;i<4;i++) { 781 hpel_motion(s, dest_y + ((i & 1) * 8) + (i >> 1) * 8 * s->linesize, 782 ref_picture[0], 0, 0, 783 mb_x * 16 + (i & 1) * 8, mb_y * 16 + (i >>1) * 8, 784 s->width, s->height, s->linesize, 785 s->h_edge_pos, s->v_edge_pos, 786 8, 8, pix_op[1], 787 s->mv[dir][i][0], s->mv[dir][i][1]); 788 789 mx += s->mv[dir][i][0]; 790 my += s->mv[dir][i][1]; 791 } 792 } 793 794 if(!CONFIG_GRAY || !(s->flags&CODEC_FLAG_GRAY)) 795 chroma_4mv_motion(s, dest_cb, dest_cr, ref_picture, pix_op[1], mx, my); 796 } 797 break; 798 case MV_TYPE_FIELD: 799 if (s->picture_structure == PICT_FRAME) { 800 if(!is_mpeg12 && s->quarter_sample){ 801 for(i=0; i<2; i++){ 802 qpel_motion(s, dest_y, dest_cb, dest_cr, 803 1, i, s->field_select[dir][i], 804 ref_picture, pix_op, qpix_op, 805 s->mv[dir][i][0], s->mv[dir][i][1], 8); 806 } 807 }else{ 808 /* top field */ 809 mpeg_motion(s, dest_y, dest_cb, dest_cr, 810 1, 0, s->field_select[dir][0], 811 ref_picture, pix_op, 812 s->mv[dir][0][0], s->mv[dir][0][1], 8, mb_y); 813 /* bottom field */ 814 mpeg_motion(s, dest_y, dest_cb, dest_cr, 815 1, 1, s->field_select[dir][1], 816 ref_picture, pix_op, 817 s->mv[dir][1][0], s->mv[dir][1][1], 8, mb_y); 818 } 819 } else { 820 if(s->picture_structure != s->field_select[dir][0] + 1 && s->pict_type != AV_PICTURE_TYPE_B && !s->first_field){ 821 ref_picture = s->current_picture_ptr->f.data; 822 } 823 824 mpeg_motion(s, dest_y, dest_cb, dest_cr, 825 0, 0, s->field_select[dir][0], 826 ref_picture, pix_op, 827 s->mv[dir][0][0], s->mv[dir][0][1], 16, mb_y>>1); 828 } 829 break; 830 case MV_TYPE_16X8: 831 for(i=0; i<2; i++){ 832 uint8_t ** ref2picture; 833 834 if(s->picture_structure == s->field_select[dir][i] + 1 835 || s->pict_type == AV_PICTURE_TYPE_B || s->first_field){ 836 ref2picture= ref_picture; 837 }else{ 838 ref2picture = s->current_picture_ptr->f.data; 839 } 840 841 mpeg_motion(s, dest_y, dest_cb, dest_cr, 842 0, 0, s->field_select[dir][i], 843 ref2picture, pix_op, 844 s->mv[dir][i][0], s->mv[dir][i][1] + 16*i, 8, mb_y>>1); 845 846 dest_y += 16*s->linesize; 847 dest_cb+= (16>>s->chroma_y_shift)*s->uvlinesize; 848 dest_cr+= (16>>s->chroma_y_shift)*s->uvlinesize; 849 } 850 break; 851 case MV_TYPE_DMV: 852 if(s->picture_structure == PICT_FRAME){ 853 for(i=0; i<2; i++){ 854 int j; 855 for(j=0; j<2; j++){ 856 mpeg_motion(s, dest_y, dest_cb, dest_cr, 857 1, j, j^i, 858 ref_picture, pix_op, 859 s->mv[dir][2*i + j][0], s->mv[dir][2*i + j][1], 8, mb_y); 860 } 861 pix_op = s->dsp.avg_pixels_tab; 862 } 863 }else{ 864 for(i=0; i<2; i++){ 865 mpeg_motion(s, dest_y, dest_cb, dest_cr, 866 0, 0, s->picture_structure != i+1, 867 ref_picture, pix_op, 868 s->mv[dir][2*i][0],s->mv[dir][2*i][1],16, mb_y>>1); 869 870 // after put we make avg of the same block 871 pix_op=s->dsp.avg_pixels_tab; 872 873 //opposite parity is always in the same frame if this is second field 874 if(!s->first_field){ 875 ref_picture = s->current_picture_ptr->f.data; 876 } 877 } 878 } 879 break; 880 default: assert(0); 881 } 882} 883 884static inline void MPV_motion(MpegEncContext *s, 885 uint8_t *dest_y, uint8_t *dest_cb, 886 uint8_t *dest_cr, int dir, 887 uint8_t **ref_picture, 888 op_pixels_func (*pix_op)[4], 889 qpel_mc_func (*qpix_op)[16]) 890{ 891#if !CONFIG_SMALL 892 if(s->out_format == FMT_MPEG1) 893 MPV_motion_internal(s, dest_y, dest_cb, dest_cr, dir, 894 ref_picture, pix_op, qpix_op, 1); 895 else 896#endif 897 MPV_motion_internal(s, dest_y, dest_cb, dest_cr, dir, 898 ref_picture, pix_op, qpix_op, 0); 899} 900#endif /* AVCODEC_MPEGVIDEO_COMMON_H */ 901