| /* | |
| * Copyright (c) 2002-2012 Michael Niedermayer | |
| * Copyright (C) 2012 Ronald S. Bultje | |
| * | |
| * This file is part of FFmpeg. | |
| * | |
| * FFmpeg is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU Lesser General Public | |
| * License as published by the Free Software Foundation; either | |
| * version 2.1 of the License, or (at your option) any later version. | |
| * | |
| * FFmpeg is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with FFmpeg; if not, write to the Free Software | |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
| */ | |
| #include "bit_depth_template.c" | |
| #if BIT_DEPTH != 8 | |
| // ff_emulated_edge_mc_8 is used by the x86 MpegVideoDSP API. | |
| static | |
| #endif | |
| void FUNC(ff_emulated_edge_mc)(uint8_t *buf, const uint8_t *src, | |
| ptrdiff_t buf_linesize, | |
| ptrdiff_t src_linesize, | |
| int block_w, int block_h, | |
| int src_x, int src_y, int w, int h) | |
| { | |
| int x, y; | |
| int start_y, start_x, end_y, end_x; | |
| if (!w || !h) | |
| return; | |
| av_assert2(block_w * sizeof(pixel) <= FFABS(buf_linesize)); | |
| if (src_y >= h) { | |
| src -= src_y * src_linesize; | |
| src += (h - 1) * src_linesize; | |
| src_y = h - 1; | |
| } else if (src_y <= -block_h) { | |
| src -= src_y * src_linesize; | |
| src += (1 - block_h) * src_linesize; | |
| src_y = 1 - block_h; | |
| } | |
| if (src_x >= w) { | |
| // The subtracted expression has an unsigned type and must thus not be negative | |
| src -= (1 + src_x - w) * sizeof(pixel); | |
| src_x = w - 1; | |
| } else if (src_x <= -block_w) { | |
| src += (1 - block_w - src_x) * sizeof(pixel); | |
| src_x = 1 - block_w; | |
| } | |
| start_y = FFMAX(0, -src_y); | |
| start_x = FFMAX(0, -src_x); | |
| end_y = FFMIN(block_h, h-src_y); | |
| end_x = FFMIN(block_w, w-src_x); | |
| av_assert2(start_y < end_y && block_h); | |
| av_assert2(start_x < end_x && block_w); | |
| w = end_x - start_x; | |
| src += start_y * src_linesize + start_x * (ptrdiff_t)sizeof(pixel); | |
| buf += start_x * sizeof(pixel); | |
| // top | |
| for (y = 0; y < start_y; y++) { | |
| memcpy(buf, src, w * sizeof(pixel)); | |
| buf += buf_linesize; | |
| } | |
| // copy existing part | |
| for (; y < end_y; y++) { | |
| memcpy(buf, src, w * sizeof(pixel)); | |
| src += src_linesize; | |
| buf += buf_linesize; | |
| } | |
| // bottom | |
| src -= src_linesize; | |
| for (; y < block_h; y++) { | |
| memcpy(buf, src, w * sizeof(pixel)); | |
| buf += buf_linesize; | |
| } | |
| buf -= block_h * buf_linesize + start_x * (ptrdiff_t)sizeof(pixel); | |
| while (block_h--) { | |
| pixel *bufp = (pixel *) buf; | |
| // left | |
| for(x = 0; x < start_x; x++) { | |
| bufp[x] = bufp[start_x]; | |
| } | |
| // right | |
| for (x = end_x; x < block_w; x++) { | |
| bufp[x] = bufp[end_x - 1]; | |
| } | |
| buf += buf_linesize; | |
| } | |
| } |