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