yading@10: /* yading@10: * Copyright (C) 2013 Wei Gao yading@10: * yading@10: * yading@10: * This file is part of FFmpeg. yading@10: * yading@10: * FFmpeg is free software; you can redistribute it and/or yading@10: * modify it under the terms of the GNU Lesser General Public yading@10: * License as published by the Free Software Foundation; either yading@10: * version 2.1 of the License, or (at your option) any later version. yading@10: * yading@10: * FFmpeg is distributed in the hope that it will be useful, yading@10: * but WITHOUT ANY WARRANTY; without even the implied warranty of yading@10: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU yading@10: * Lesser General Public License for more details. yading@10: * yading@10: * You should have received a copy of the GNU Lesser General Public yading@10: * License along with FFmpeg; if not, write to the Free Software yading@10: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA yading@10: */ yading@10: yading@10: #ifndef AVFILTER_DESHAKE_KERNEL_H yading@10: #define AVFILTER_DESHAKE_KERNEL_H yading@10: yading@10: #include "libavutil/opencl.h" yading@10: yading@10: const char *ff_kernel_deshake_opencl = AV_OPENCL_KERNEL( yading@10: yading@10: inline unsigned char pixel(global const unsigned char *src, float x, float y, yading@10: int w, int h,int stride, unsigned char def) yading@10: { yading@10: return (x < 0 || y < 0 || x >= w || y >= h) ? def : src[(int)x + (int)y * stride]; yading@10: } yading@10: unsigned char interpolate_nearest(float x, float y, global const unsigned char *src, yading@10: int width, int height, int stride, unsigned char def) yading@10: { yading@10: return pixel(src, (int)(x + 0.5), (int)(y + 0.5), width, height, stride, def); yading@10: } yading@10: yading@10: unsigned char interpolate_bilinear(float x, float y, global const unsigned char *src, yading@10: int width, int height, int stride, unsigned char def) yading@10: { yading@10: int x_c, x_f, y_c, y_f; yading@10: int v1, v2, v3, v4; yading@10: yading@10: if (x < -1 || x > width || y < -1 || y > height) { yading@10: return def; yading@10: } else { yading@10: x_f = (int)x; yading@10: x_c = x_f + 1; yading@10: yading@10: y_f = (int)y; yading@10: y_c = y_f + 1; yading@10: yading@10: v1 = pixel(src, x_c, y_c, width, height, stride, def); yading@10: v2 = pixel(src, x_c, y_f, width, height, stride, def); yading@10: v3 = pixel(src, x_f, y_c, width, height, stride, def); yading@10: v4 = pixel(src, x_f, y_f, width, height, stride, def); yading@10: yading@10: return (v1*(x - x_f)*(y - y_f) + v2*((x - x_f)*(y_c - y)) + yading@10: v3*(x_c - x)*(y - y_f) + v4*((x_c - x)*(y_c - y))); yading@10: } yading@10: } yading@10: yading@10: unsigned char interpolate_biquadratic(float x, float y, global const unsigned char *src, yading@10: int width, int height, int stride, unsigned char def) yading@10: { yading@10: int x_c, x_f, y_c, y_f; yading@10: unsigned char v1, v2, v3, v4; yading@10: float f1, f2, f3, f4; yading@10: yading@10: if (x < - 1 || x > width || y < -1 || y > height) yading@10: return def; yading@10: else { yading@10: x_f = (int)x; yading@10: x_c = x_f + 1; yading@10: y_f = (int)y; yading@10: y_c = y_f + 1; yading@10: yading@10: v1 = pixel(src, x_c, y_c, width, height, stride, def); yading@10: v2 = pixel(src, x_c, y_f, width, height, stride, def); yading@10: v3 = pixel(src, x_f, y_c, width, height, stride, def); yading@10: v4 = pixel(src, x_f, y_f, width, height, stride, def); yading@10: yading@10: f1 = 1 - sqrt((x_c - x) * (y_c - y)); yading@10: f2 = 1 - sqrt((x_c - x) * (y - y_f)); yading@10: f3 = 1 - sqrt((x - x_f) * (y_c - y)); yading@10: f4 = 1 - sqrt((x - x_f) * (y - y_f)); yading@10: return (v1 * f1 + v2 * f2 + v3 * f3 + v4 * f4) / (f1 + f2 + f3 + f4); yading@10: } yading@10: } yading@10: yading@10: inline const float clipf(float a, float amin, float amax) yading@10: { yading@10: if (a < amin) return amin; yading@10: else if (a > amax) return amax; yading@10: else return a; yading@10: } yading@10: yading@10: inline int mirror(int v, int m) yading@10: { yading@10: while ((unsigned)v > (unsigned)m) { yading@10: v = -v; yading@10: if (v < 0) yading@10: v += 2 * m; yading@10: } yading@10: return v; yading@10: } yading@10: yading@10: kernel void avfilter_transform(global unsigned char *src, yading@10: global unsigned char *dst, yading@10: global float *matrix, yading@10: global float *matrix2, yading@10: int interpolate, yading@10: int fillmethod, yading@10: int src_stride_lu, yading@10: int dst_stride_lu, yading@10: int src_stride_ch, yading@10: int dst_stride_ch, yading@10: int height, yading@10: int width, yading@10: int ch, yading@10: int cw) yading@10: { yading@10: int global_id = get_global_id(0); yading@10: yading@10: global unsigned char *dst_y = dst; yading@10: global unsigned char *dst_u = dst_y + height * dst_stride_lu; yading@10: global unsigned char *dst_v = dst_u + ch * dst_stride_ch; yading@10: yading@10: global unsigned char *src_y = src; yading@10: global unsigned char *src_u = src_y + height * src_stride_lu; yading@10: global unsigned char *src_v = src_u + ch * src_stride_ch; yading@10: yading@10: global unsigned char *tempdst; yading@10: global unsigned char *tempsrc; yading@10: yading@10: int x; yading@10: int y; yading@10: float x_s; yading@10: float y_s; yading@10: int tempsrc_stride; yading@10: int tempdst_stride; yading@10: int temp_height; yading@10: int temp_width; yading@10: int curpos; yading@10: unsigned char def = 0; yading@10: if (global_id < width*height) { yading@10: y = global_id/width; yading@10: x = global_id%width; yading@10: x_s = x * matrix[0] + y * matrix[1] + matrix[2]; yading@10: y_s = x * matrix[3] + y * matrix[4] + matrix[5]; yading@10: tempdst = dst_y; yading@10: tempsrc = src_y; yading@10: tempsrc_stride = src_stride_lu; yading@10: tempdst_stride = dst_stride_lu; yading@10: temp_height = height; yading@10: temp_width = width; yading@10: } else if ((global_id >= width*height)&&(global_id < width*height + ch*cw)) { yading@10: y = (global_id - width*height)/cw; yading@10: x = (global_id - width*height)%cw; yading@10: x_s = x * matrix2[0] + y * matrix2[1] + matrix2[2]; yading@10: y_s = x * matrix2[3] + y * matrix2[4] + matrix2[5]; yading@10: tempdst = dst_u; yading@10: tempsrc = src_u; yading@10: tempsrc_stride = src_stride_ch; yading@10: tempdst_stride = dst_stride_ch; yading@10: temp_height = ch; yading@10: temp_width = cw; yading@10: } else { yading@10: y = (global_id - width*height - ch*cw)/cw; yading@10: x = (global_id - width*height - ch*cw)%cw; yading@10: x_s = x * matrix2[0] + y * matrix2[1] + matrix2[2]; yading@10: y_s = x * matrix2[3] + y * matrix2[4] + matrix2[5]; yading@10: tempdst = dst_v; yading@10: tempsrc = src_v; yading@10: tempsrc_stride = src_stride_ch; yading@10: tempdst_stride = dst_stride_ch; yading@10: temp_height = ch; yading@10: temp_width = cw; yading@10: } yading@10: curpos = y * tempdst_stride + x; yading@10: switch (fillmethod) { yading@10: case 0: //FILL_BLANK yading@10: def = 0; yading@10: break; yading@10: case 1: //FILL_ORIGINAL yading@10: def = tempsrc[y*tempsrc_stride+x]; yading@10: break; yading@10: case 2: //FILL_CLAMP yading@10: y_s = clipf(y_s, 0, temp_height - 1); yading@10: x_s = clipf(x_s, 0, temp_width - 1); yading@10: def = tempsrc[(int)y_s * tempsrc_stride + (int)x_s]; yading@10: break; yading@10: case 3: //FILL_MIRROR yading@10: y_s = mirror(y_s,temp_height - 1); yading@10: x_s = mirror(x_s,temp_width - 1); yading@10: def = tempsrc[(int)y_s * tempsrc_stride + (int)x_s]; yading@10: break; yading@10: } yading@10: switch (interpolate) { yading@10: case 0: //INTERPOLATE_NEAREST yading@10: tempdst[curpos] = interpolate_nearest(x_s, y_s, tempsrc, temp_width, temp_height, tempsrc_stride, def); yading@10: break; yading@10: case 1: //INTERPOLATE_BILINEAR yading@10: tempdst[curpos] = interpolate_bilinear(x_s, y_s, tempsrc, temp_width, temp_height, tempsrc_stride, def); yading@10: break; yading@10: case 2: //INTERPOLATE_BIQUADRATIC yading@10: tempdst[curpos] = interpolate_biquadratic(x_s, y_s, tempsrc, temp_width, temp_height, tempsrc_stride, def); yading@10: break; yading@10: default: yading@10: return; yading@10: } yading@10: } yading@10: ); yading@10: yading@10: #endif /* AVFILTER_DESHAKE_KERNEL_H */