├── .gitignore ├── vapoursynth ├── src │ ├── GNUmakefile │ ├── merge_frames.c │ ├── horizontal_dilation.c │ ├── combmask.h │ ├── configure │ ├── is_combed.c │ ├── adapt_motion.c │ ├── combmask.c │ ├── write_combmask.c │ └── VapourSynth.h ├── readme.rst └── LICENSE.LGPLv2.1 └── avisynth ├── src ├── CombMask.h ├── cpu_check.cpp ├── plugin.cpp ├── MaskedMerge.cpp ├── simd.h └── CombMask.cpp ├── readme.txt ├── vs2015 └── CombMask.vcxproj └── LICENSE.GPLv2 /.gitignore: -------------------------------------------------------------------------------- 1 | *.dll 2 | *.exe 3 | *.sln 4 | *.db 5 | *.opendb 6 | *.filters 7 | *.user 8 | avisynth/vs2015/.vs/* 9 | avisynth/vs2015/Debug/* 10 | avisynth/vs2015/Release/* 11 | avisynth/vs2015/x64/* 12 | avisynth/archives/* 13 | -------------------------------------------------------------------------------- /vapoursynth/src/GNUmakefile: -------------------------------------------------------------------------------- 1 | include config.mak 2 | 3 | vpath %.c $(SRCDIR) 4 | vpath %.h $(SRCDIR) 5 | 6 | SRCS = adapt_motion.c combmask.c horizontal_dilation.c is_combed.c \ 7 | merge_frames.c write_combmask.c 8 | 9 | OBJS = $(SRCS:%.c=%.o) 10 | 11 | .PHONY: all install clean distclean dep 12 | 13 | all: $(LIBNAME) 14 | 15 | $(LIBNAME): $(OBJS) 16 | $(LD) -o $@ $(LDFLAGS) $^ 17 | $(if $(STRIP), $(STRIP) $@) 18 | 19 | %.o: %.c .depend 20 | $(CC) -c $(CFLAGS) -o $@ $< 21 | 22 | install: all 23 | install -d $(libdir) 24 | install -m 755 $(LIBNAME) $(libdir) 25 | 26 | clean: 27 | $(RM) $(OBJS) *.dll *.so *.dylib .depend 28 | 29 | distclean: clean 30 | $(RM) config.* 31 | 32 | dep: .depend 33 | 34 | ifneq ($(wildcard .depend),) 35 | include .depend 36 | endif 37 | 38 | .depend: config.mak 39 | @$(RM) .depend 40 | @$(foreach SRC, $(SRCS:%=$(SRCDIR)/%), $(CC) $(SRC) $(CFLAGS) -msse2 -MT $(SRC:$(SRCDIR)/%.c=%.o) -MM >> .depend;) 41 | 42 | config.mak: 43 | ./configure 44 | -------------------------------------------------------------------------------- /vapoursynth/src/merge_frames.c: -------------------------------------------------------------------------------- 1 | /* 2 | merge_frames.c: Copyright (C) 2012-2013 Oka Motofumi 3 | 4 | Author: Oka Motofumi (chikuzen.mo at gmail dot com) 5 | 6 | This file is part of CombMask. 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public 10 | License as published by the Free Software Foundation; either 11 | version 2.1 of the License, or (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public 19 | License along with the author; if not, write to the Free Software 20 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 | */ 22 | 23 | 24 | #include 25 | #include "combmask.h" 26 | 27 | 28 | static void CM_FUNC_ALIGN VS_CC 29 | merge_frames_all(maskedmerge_t *mh, const VSAPI *vsapi, const VSFrameRef *mask, 30 | const VSFrameRef *alt, VSFrameRef *dst) 31 | { 32 | int err; 33 | int is_combed = vsapi->propGetInt(vsapi->getFramePropsRO(mask), "_Combed", 34 | 0, &err); 35 | if (err == 0 && is_combed == 0) { 36 | return; 37 | } 38 | 39 | int adjust = 16 / mh->vi->format->bytesPerSample; 40 | 41 | for (int p = 0; p < mh->vi->format->numPlanes; p++) { 42 | if (mh->planes[p] == 0) { 43 | continue; 44 | } 45 | 46 | const __m128i *altp = (__m128i *)vsapi->getReadPtr(alt, p); 47 | const __m128i *maskp = (__m128i *)vsapi->getReadPtr(mask, p); 48 | __m128i *dstp = (__m128i *)vsapi->getWritePtr(dst, p); 49 | 50 | int width = (vsapi->getFrameWidth(dst, p) + adjust - 1) / adjust; 51 | int height = vsapi->getFrameHeight(dst, p); 52 | int stride = vsapi->getStride(dst, p) / adjust; 53 | 54 | for (int y = 0; y < height; y++) { 55 | for (int x = 0; x < width; x++) { 56 | __m128i xmm0 = _mm_load_si128(dstp + x); 57 | __m128i xmm1 = _mm_load_si128(altp + x); 58 | __m128i xmm2 = _mm_load_si128(maskp + x); 59 | 60 | xmm0 = _mm_andnot_si128(xmm2, xmm0); 61 | xmm1 = _mm_and_si128(xmm2, xmm1); 62 | xmm0 = _mm_or_si128(xmm0, xmm1); 63 | 64 | _mm_store_si128(dstp + x, xmm0); 65 | } 66 | altp += stride; 67 | maskp += stride; 68 | dstp += stride; 69 | } 70 | } 71 | } 72 | 73 | 74 | const func_merge_frames merge_frames = merge_frames_all; 75 | -------------------------------------------------------------------------------- /vapoursynth/readme.rst: -------------------------------------------------------------------------------- 1 | ==================================== 2 | CombMask - VapourSynth plugin 3 | ==================================== 4 | 5 | CombMask is a simple filter set for create comb mask and merge clips. 6 | 7 | Both functions support 8/9/10/16bit integer planar formats. 8 | 9 | CombMask: 10 | -------- 11 | Create a binary(0 and maximum value) combmask clip. '_Combed' prop is set to all the frames.:: 12 | 13 | comb.CombMask(clip clip[, int cthresh, int mthresh, int mi, int[] planes]) 14 | 15 | cthresh - spatial combing threshold. default is 6(8bit), 12(9bit), 24(10bit) or 1536(16bit). 16 | 17 | mthresh - motion adaptive threshold. default is 9, 18, 36 or 2304. 18 | 19 | mi - The # of combed pixels inside any of 8x16 size blocks on a plane for the frame to be detected as combed. If number of combed pixels is over this value, _Combed prop will be set to the mask as true. Value range is between 0 and 128. Default is 40. 20 | 21 | planes - Choose which planes to process. default will process all planes. Allowed values are 0, 1, and 2.:: 22 | 23 | 0 = Y (luma) or R (red) 24 | 1 = U (Cb) or G (green) 25 | 2 = V (Cr) or B (blue) 26 | 27 | examples 28 | planes=[0] = processes the Y or R plane only. 29 | planes=[1,2] = processes the U V or G B planes only. 30 | 31 | note: The metric of combing detection is similler to IsCombedTIVTC(metric=0) by Kevin Stone(aka. tritical). 32 | 33 | CMaskedMerge: 34 | ------------- 35 | An exclusive masking filter for CombMask. 36 | 37 | This filter can process only binary(0 and maximum value) mask, and skip merging process if the mask says '_Combed is false'. 38 | 39 | Therefore, this filter is faster than std.MaskedMerge() if 'mask' is created by CombMask():: 40 | 41 | comb.CMaskedMerge(clip base, clip alt, clip mask[, int[] planes]) 42 | 43 | base - base clip. 44 | 45 | alt - alternate clip which will be merged to base. 46 | 47 | mask - mask clip. 48 | 49 | planes - same as CombMask. 50 | 51 | note: base, alt and mask must be the same format/resolution. 52 | 53 | Examples: 54 | --------- 55 | :: 56 | 57 | import vapoursynth as vs 58 | core = vs.get_core() 59 | core.std.LoadPlugin('/path/to/combmask.dll') 60 | core.std.LoadPlugin('/path/to/vivtc.dll') 61 | core.std.LoadPlugin('/path/to/eedi3.dll') 62 | clip = something 63 | base = core.vivtc.VFM(clip, 1) 64 | alt = core.eedi3.eedi3(clip, 1) 65 | mask = core.comb.CombMask(base) 66 | 67 | # merge two clips 68 | merged = core.comb.CMaskedMerge(base, alt, mask) 69 | 70 | # replace only comed frames 71 | def func(n, f): 72 | if f.props._Combed == True: 73 | return 1 74 | return 0 75 | 76 | replaced = core.std.SelectClip(clips=[base, alt], src=mask, selector=func) 77 | 78 | 79 | How to compile: 80 | --------------- 81 | on unix like system(include mingw), type as follows:: 82 | 83 | $ git clone git://github.com/chikuzen/CombMask.git 84 | $ cd ./CombMask/vapoursynth/src 85 | $ ./configure 86 | $ make install 87 | 88 | if you want to use msvc++, then:: 89 | 90 | - rename all *.c to *.cpp 91 | - create vcxproj yourself 92 | 93 | This plugin requires SSE2 capable cpu. Thus ARM and PowerPC are unsupported. 94 | 95 | Source code: 96 | ------------ 97 | https://github.com/chikuzen/CombMask 98 | 99 | 100 | Author: Oka Motofumi (chikuzen.mo at gmail dot com) 101 | -------------------------------------------------------------------------------- /vapoursynth/src/horizontal_dilation.c: -------------------------------------------------------------------------------- 1 | /* 2 | horizontal_dilation.c: Copyright (C) 2012-2013 Oka Motofumi 3 | 4 | Author: Oka Motofumi (chikuzen.mo at gmail dot com) 5 | 6 | This file is part of CombMask. 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public 10 | License as published by the Free Software Foundation; either 11 | version 2.1 of the License, or (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public 19 | License along with the author; if not, write to the Free Software 20 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 | */ 22 | 23 | 24 | #include 25 | #include 26 | 27 | #define USE_ALIGNED_MALLOC 28 | #include "combmask.h" 29 | 30 | 31 | static void CM_FUNC_ALIGN VS_CC 32 | horizontal_dilation_8bit(combmask_t *ch, VSFrameRef *cmask, const VSAPI *vsapi) 33 | { 34 | uint8_t *tmp = (uint8_t *)_aligned_malloc(((ch->vi->width + 63) / 32) * 32, 16); 35 | uint8_t *buff = tmp + 16; 36 | 37 | for (int p = 0; p < ch->vi->format->numPlanes; p++) { 38 | if (ch->planes[p] == 0) { 39 | continue; 40 | } 41 | 42 | int width = vsapi->getFrameWidth(cmask, p); 43 | int height = vsapi->getFrameHeight(cmask, p); 44 | int stride = vsapi->getStride(cmask, p); 45 | uint8_t *maskp = vsapi->getWritePtr(cmask, p); 46 | 47 | for (int y = 0; y < height; y++) { 48 | memcpy(buff, maskp, stride); 49 | buff[-1] = buff[0]; 50 | buff[width] = buff[width - 1]; 51 | 52 | for (int x = 0; x < width; x += 16) { 53 | __m128i xmm0 = _mm_load_si128((__m128i*)(buff + x)); 54 | __m128i xmm1 = _mm_loadu_si128((__m128i*)(buff + x + 1)); 55 | __m128i xmm2 = _mm_loadu_si128((__m128i*)(buff + x - 1)); 56 | xmm0 = _mm_or_si128(xmm0, _mm_or_si128(xmm1, xmm2)); 57 | _mm_store_si128((__m128i*)(maskp + x), xmm0); 58 | } 59 | maskp += stride; 60 | } 61 | } 62 | 63 | _aligned_free(tmp); 64 | } 65 | 66 | 67 | static void CM_FUNC_ALIGN VS_CC 68 | horizontal_dilation_16bit(combmask_t *ch, VSFrameRef *cmask, const VSAPI *vsapi) 69 | { 70 | uint16_t *tmp = (uint16_t *)_aligned_malloc(((ch->vi->width * 2 + 63) / 32) * 32, 16); 71 | uint16_t *buff = tmp + 8; 72 | 73 | for (int p = 0; p < ch->vi->format->numPlanes; p++) { 74 | if (ch->planes[p] == 0) { 75 | continue; 76 | } 77 | 78 | int width = vsapi->getFrameWidth(cmask, p); 79 | int height = vsapi->getFrameHeight(cmask, p); 80 | int stride = vsapi->getStride(cmask, p) / 2; 81 | uint16_t *maskp = (uint16_t *)vsapi->getWritePtr(cmask, p); 82 | 83 | for (int y = 0; y < height; y++) { 84 | memcpy(buff, maskp, stride * 2); 85 | buff[-1] = buff[0]; 86 | buff[width] = buff[width - 1]; 87 | 88 | for (int x = 0; x < width; x += 8) { 89 | __m128i xmm0 = _mm_load_si128((__m128i*)(buff + x)); 90 | __m128i xmm1 = _mm_loadu_si128((__m128i*)(buff + x + 1)); 91 | __m128i xmm2 = _mm_loadu_si128((__m128i*)(buff + x - 1)); 92 | xmm0 = _mm_or_si128(xmm0, _mm_or_si128(xmm1, xmm2)); 93 | _mm_store_si128((__m128i*)(maskp + x), xmm0); 94 | } 95 | maskp += stride; 96 | } 97 | } 98 | 99 | _aligned_free(tmp); 100 | } 101 | 102 | 103 | const func_h_dilation h_dilation_funcs[] = { 104 | horizontal_dilation_8bit, 105 | horizontal_dilation_16bit, 106 | horizontal_dilation_16bit 107 | }; 108 | -------------------------------------------------------------------------------- /avisynth/src/CombMask.h: -------------------------------------------------------------------------------- 1 | #ifndef COMB_MASK_H 2 | #define COMB_MASK_H 3 | 4 | #include 5 | #include 6 | #define WIN32_LEAN_AND_MEAN 7 | #define VC_EXTRALEAN 8 | #define NOMINMAX 9 | #define NOGDI 10 | #include 11 | #include 12 | 13 | #define CMASK_VERSION "1.1.1" 14 | 15 | 16 | typedef IScriptEnvironment ise_t; 17 | 18 | 19 | enum arch_t { 20 | NO_SIMD = 0, 21 | USE_SSE2 = 1, 22 | USE_AVX2 = 2, 23 | }; 24 | 25 | 26 | class Buffer { 27 | ise_t* env; 28 | bool isPlus; 29 | void* orig; 30 | public: 31 | uint8_t* buffp; 32 | Buffer(size_t pitch, int height, int hsize, size_t align, bool ip, ise_t* e); 33 | ~Buffer(); 34 | }; 35 | 36 | 37 | class GVFmod : public GenericVideoFilter { 38 | protected: 39 | bool isPlus; 40 | int numPlanes; 41 | size_t align; 42 | 43 | GVFmod(PClip c, bool chroma, arch_t a, bool ip) : 44 | GenericVideoFilter(c), align(a == USE_AVX2 ? 32 : 16), isPlus(ip) 45 | { 46 | numPlanes = (vi.IsY8() || !chroma) ? 1 : 3; 47 | } 48 | int __stdcall SetCacheHints(int hints, int) 49 | { 50 | return hints == CACHE_GET_MTMODE ? MT_NICE_FILTER : 0; 51 | } 52 | }; 53 | 54 | 55 | class CombMask : public GVFmod { 56 | int cthresh; 57 | int mthresh; 58 | bool expand; 59 | bool needBuff; 60 | size_t buffPitch; 61 | Buffer* buff; 62 | 63 | void (__stdcall *writeCombMask)( 64 | uint8_t* dstp, const uint8_t* srcp, const int dpitch, const int cpitch, 65 | const int cthresh, const int width, const int height); 66 | 67 | void (__stdcall *writeMotionMask)( 68 | uint8_t* tmpp, uint8_t* dstp, const uint8_t* srcp, const uint8_t* prevp, 69 | const int tpitch, const int dpitch, const int spitch, const int ppitch, 70 | const int mthresh, const int width, const int height); 71 | 72 | void (__stdcall *andMasks)( 73 | uint8_t* dstp, const uint8_t* altp, const int dpitch, const int apitch, 74 | const int width, const int height); 75 | 76 | void (__stdcall *expandMask)( 77 | uint8_t* dstp, uint8_t* srcp, const int dpitch, const int spitch, 78 | const int width, const int height); 79 | 80 | public: 81 | CombMask(PClip c, int cth, int mth, bool chroma, arch_t arch, bool expand, 82 | int metric, bool is_avsplus); 83 | ~CombMask(); 84 | PVideoFrame __stdcall GetFrame(int n, ise_t* env); 85 | }; 86 | 87 | 88 | typedef bool (__stdcall *check_combed_t)( 89 | PVideoFrame& cmask, int mi, int blockx, int blocky, bool is_avsplus, 90 | ise_t* env); 91 | 92 | 93 | class MaskedMerge : public GVFmod { 94 | PClip altc; 95 | PClip maskc; 96 | int mi; 97 | int blockx; 98 | int blocky; 99 | 100 | check_combed_t checkCombed; 101 | 102 | void (__stdcall *mergeFrames)( 103 | int mum_planes, PVideoFrame& src, PVideoFrame& alt, PVideoFrame& mask, 104 | PVideoFrame& dst); 105 | 106 | public: 107 | MaskedMerge(PClip c, PClip a, PClip m, int mi, int blockx, int blocky, 108 | bool chroma, arch_t arch, bool is_avsplus); 109 | ~MaskedMerge() {} 110 | PVideoFrame __stdcall GetFrame(int n, ise_t* env); 111 | }; 112 | 113 | 114 | check_combed_t get_check_combed(arch_t arch); 115 | 116 | 117 | static inline void validate(bool cond, const char* msg) 118 | { 119 | if (cond) throw std::runtime_error(msg); 120 | } 121 | 122 | 123 | static inline void* 124 | alloc_buffer(size_t size, size_t align, bool is_avsplus, ise_t* env) 125 | { 126 | if (is_avsplus) { 127 | return static_cast( 128 | env)->Allocate(size, align, AVS_POOLED_ALLOC); 129 | } 130 | return _aligned_malloc(size, align); 131 | } 132 | 133 | 134 | static inline void 135 | free_buffer(void* buff, bool is_avsplus, ise_t* env) 136 | { 137 | if (is_avsplus) { 138 | static_cast(env)->Free(buff); 139 | return; 140 | } 141 | _aligned_free(buff); 142 | } 143 | 144 | #endif 145 | 146 | -------------------------------------------------------------------------------- /vapoursynth/src/combmask.h: -------------------------------------------------------------------------------- 1 | /* 2 | combmask.h: Copyright (C) 2012-2013 Oka Motofumi 3 | 4 | Author: Oka Motofumi (chikuzen.mo at gmail dot com) 5 | 6 | This file is part of CombMask. 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public 10 | License as published by the Free Software Foundation; either 11 | version 2.1 of the License, or (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public 19 | License along with the author; if not, write to the Free Software 20 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 | */ 22 | 23 | 24 | #ifndef VS_COMBMASK_H 25 | #define VS_COMBMASK_H 26 | 27 | #include 28 | #include "VapourSynth.h" 29 | 30 | #define COMBMASK_VERSION "0.0.1" 31 | 32 | #define MM_MIN_EPU16(X, Y) (_mm_subs_epu16(X, _mm_subs_epu16(X, Y))) 33 | #define MM_MAX_EPU16(X, Y) (_mm_adds_epu16(Y, _mm_subs_epu16(X, Y))) 34 | 35 | #ifdef _MSC_VER 36 | #pragma warning(disable:4996 4244) 37 | #endif 38 | 39 | #ifdef __MINGW32__ 40 | #define CM_FUNC_ALIGN __attribute__((force_align_arg_pointer)) 41 | #else 42 | #define CM_FUNC_ALIGN 43 | #endif 44 | 45 | typedef struct combmask combmask_t; 46 | 47 | typedef struct maskedmerge maskedmerge_t; 48 | 49 | typedef void (VS_CC *func_write_combmask)(combmask_t *ch, const VSAPI *vsapi, 50 | const VSFrameRef *src, 51 | VSFrameRef *cmask); 52 | 53 | typedef void (VS_CC *func_adapt_motion)(combmask_t *ch, const VSAPI *vsapi, 54 | const VSFrameRef *src, 55 | const VSFrameRef *prev, 56 | VSFrameRef *cmask); 57 | 58 | typedef void (VS_CC *func_write_motionmask)(int mthresh, int width, 59 | int height, int stride, 60 | __m128i *maskp, __m128i *srcp, 61 | __m128i *prevp); 62 | 63 | typedef int (VS_CC *func_is_combed)(combmask_t *ch, VSFrameRef *cmask, 64 | const VSAPI *vsapi); 65 | 66 | typedef void (VS_CC *func_h_dilation)(combmask_t *ch, VSFrameRef *cmask, 67 | const VSAPI *vsapi); 68 | 69 | typedef void (VS_CC *func_merge_frames)(maskedmerge_t *mh, const VSAPI *vsapi, 70 | const VSFrameRef *mask, 71 | const VSFrameRef *alt, 72 | VSFrameRef *dst); 73 | 74 | 75 | struct combmask { 76 | VSNodeRef *node; 77 | const VSVideoInfo *vi; 78 | int planes[3]; 79 | int cthresh; 80 | int mthresh; 81 | int mi; 82 | func_write_combmask write_combmask; 83 | func_write_motionmask write_motionmask; 84 | func_is_combed is_combed; 85 | func_h_dilation horizontal_dilation; 86 | }; 87 | 88 | struct maskedmerge { 89 | VSNodeRef *base; 90 | VSNodeRef *altc; 91 | VSNodeRef *mask; 92 | const VSVideoInfo *vi; 93 | int planes[3]; 94 | }; 95 | 96 | 97 | extern const func_adapt_motion adapt_motion; 98 | extern const func_write_combmask write_combmask_funcs[]; 99 | extern const func_write_motionmask write_motionmask_funcs[]; 100 | extern const func_is_combed is_combed_funcs[]; 101 | extern const func_h_dilation h_dilation_funcs[]; 102 | extern const func_merge_frames merge_frames; 103 | 104 | 105 | #ifdef USE_ALIGNED_MALLOC 106 | # ifdef _WIN32 107 | # include 108 | # else 109 | static inline void *_aligned_malloc(size_t size, size_t alignment) 110 | { 111 | void *p; 112 | int ret = posix_memalign(&p, alignment, size); 113 | return (ret == 0) ? p : 0; 114 | } 115 | 116 | static inline void _aligned_free(void *p) 117 | { 118 | free(p); 119 | } 120 | # endif // _WIN32 121 | #endif // USE_ALIGNED_MALLOC 122 | 123 | #endif // VS_COMBMASK_H 124 | -------------------------------------------------------------------------------- /avisynth/src/cpu_check.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | cpu_check.cpp 3 | 4 | This file is a part of TMM2 5 | 6 | Copyright (C) 2016 OKA Motofumi 7 | 8 | This program is free software; you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation; either version 2 of the License, or 11 | (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software 20 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA. 21 | */ 22 | 23 | #include 24 | #include 25 | 26 | 27 | enum { 28 | CPU_NO_X86_SIMD = 0x000000, 29 | CPU_SSE2_SUPPORT = 0x000001, 30 | CPU_SSE3_SUPPORT = 0x000002, 31 | CPU_SSSE3_SUPPORT = 0x000004, 32 | CPU_SSE4_1_SUPPORT = 0x000008, 33 | CPU_SSE4_2_SUPPORT = 0x000010, 34 | CPU_SSE4_A_SUPPORT = 0x000020, 35 | CPU_FMA4_SUPPORT = 0x000040, 36 | CPU_FMA3_SUPPORT = 0x000080, 37 | CPU_AVX_SUPPORT = 0x000100, 38 | CPU_AVX2_SUPPORT = 0x000200, 39 | CPU_AVX512F_SUPPORT = 0x000400, 40 | CPU_AVX512DQ_SUPPORT = 0x000800, 41 | CPU_AVX512IFMA52_SUPPORT = 0x001000, 42 | CPU_AVX512PF_SUPPORT = 0x002000, 43 | CPU_AVX512ER_SUPPORT = 0x004000, 44 | CPU_AVX512CD_SUPPORT = 0x008000, 45 | CPU_AVX512BW_SUPPORT = 0x010000, 46 | CPU_AVX512VL_SUPPORT = 0x020000, 47 | CPU_AVX512VBMI_SUPPORT = 0x040000, 48 | }; 49 | 50 | 51 | 52 | 53 | static __forceinline bool is_bit_set(int bitfield, int bit) 54 | { 55 | return (bitfield & (1 << bit)) != 0; 56 | } 57 | 58 | static uint32_t get_simd_support_info(void) 59 | { 60 | uint32_t ret = 0; 61 | int regs[4] = {0}; 62 | 63 | __cpuid(regs, 0x00000001); 64 | if (is_bit_set(regs[3], 26)) { 65 | ret |= CPU_SSE2_SUPPORT; 66 | } 67 | if (is_bit_set(regs[2], 0)) { 68 | ret |= CPU_SSE3_SUPPORT; 69 | } 70 | if (is_bit_set(regs[2], 9)) { 71 | ret |= CPU_SSSE3_SUPPORT; 72 | } 73 | if (is_bit_set(regs[2], 19)) { 74 | ret |= CPU_SSE4_1_SUPPORT; 75 | } 76 | if (is_bit_set(regs[2], 26)) { 77 | ret |= CPU_SSE4_2_SUPPORT; 78 | } 79 | if (is_bit_set(regs[2], 27)) { 80 | if (is_bit_set(regs[2], 28)) { 81 | ret |= CPU_AVX_SUPPORT; 82 | } 83 | if (is_bit_set(regs[2], 12)) { 84 | ret |= CPU_FMA3_SUPPORT; 85 | } 86 | } 87 | 88 | regs[3] = 0; 89 | __cpuid(regs, 0x80000001); 90 | if (is_bit_set(regs[3], 6)) { 91 | ret |= CPU_SSE4_A_SUPPORT; 92 | } 93 | if (is_bit_set(regs[3], 16)) { 94 | ret |= CPU_FMA4_SUPPORT; 95 | } 96 | 97 | __cpuid(regs, 0x00000000); 98 | if (regs[0] < 7) { 99 | return ret; 100 | } 101 | 102 | __cpuidex(regs, 0x00000007, 0); 103 | if (is_bit_set(regs[1], 5)) { 104 | ret |= CPU_AVX2_SUPPORT; 105 | } 106 | if (!is_bit_set(regs[1], 16)) { 107 | return ret; 108 | } 109 | 110 | ret |= CPU_AVX512F_SUPPORT; 111 | if (is_bit_set(regs[1], 17)) { 112 | ret |= CPU_AVX512DQ_SUPPORT; 113 | } 114 | if (is_bit_set(regs[1], 21)) { 115 | ret |= CPU_AVX512IFMA52_SUPPORT; 116 | } 117 | if (is_bit_set(regs[1], 26)) { 118 | ret |= CPU_AVX512PF_SUPPORT; 119 | } 120 | if (is_bit_set(regs[1], 27)) { 121 | ret |= CPU_AVX512ER_SUPPORT; 122 | } 123 | if (is_bit_set(regs[1], 28)) { 124 | ret |= CPU_AVX512CD_SUPPORT; 125 | } 126 | if (is_bit_set(regs[1], 30)) { 127 | ret |= CPU_AVX512BW_SUPPORT; 128 | } 129 | if (is_bit_set(regs[1], 31)) { 130 | ret |= CPU_AVX512VL_SUPPORT; 131 | } 132 | if (is_bit_set(regs[2], 1)) { 133 | ret |= CPU_AVX512VBMI_SUPPORT; 134 | } 135 | 136 | return ret; 137 | } 138 | 139 | bool has_sse2() 140 | { 141 | return (get_simd_support_info() & CPU_SSE2_SUPPORT) != 0; 142 | } 143 | 144 | bool has_avx2() 145 | { 146 | return (get_simd_support_info() & CPU_AVX2_SUPPORT) != 0; 147 | } 148 | -------------------------------------------------------------------------------- /avisynth/src/plugin.cpp: -------------------------------------------------------------------------------- 1 | #include "CombMask.h" 2 | 3 | extern bool has_sse2(); 4 | extern bool has_avx2(); 5 | 6 | 7 | static arch_t get_arch(int opt, bool is_avsplus) 8 | { 9 | if (opt == 0 || !has_sse2()) { 10 | return NO_SIMD; 11 | } 12 | #if !defined(__AVX2__) 13 | return USE_SSE2; 14 | #else 15 | if (opt == 1 || !has_avx2() || !is_avsplus) { 16 | return USE_SSE2; 17 | } 18 | return USE_AVX2; 19 | #endif 20 | } 21 | 22 | 23 | static AVSValue __cdecl 24 | create_combmask(AVSValue args, void* user_data, ise_t* env) 25 | { 26 | enum { CLIP, CTHRESH, MTHRESH, CHROMA, EXPAND, METRIC, OPT }; 27 | 28 | PClip clip = args[CLIP].AsClip(); 29 | int metric = args[METRIC].AsInt(0); 30 | int cth = args[CTHRESH].AsInt(metric == 0 ? 6 : 10); 31 | int mth = args[MTHRESH].AsInt(9); 32 | bool ch = args[CHROMA].AsBool(true); 33 | bool expand = args[EXPAND].AsBool(true); 34 | bool is_avsplus = env->FunctionExists("SetFilterMTMode"); 35 | arch_t arch = get_arch(args[OPT].AsInt(-1), is_avsplus); 36 | 37 | try{ 38 | return new CombMask(clip, cth, mth, ch, arch, expand, metric, is_avsplus); 39 | 40 | } catch (std::runtime_error& e) { 41 | env->ThrowError("CombMask: %s", e.what()); 42 | } 43 | 44 | return 0; 45 | } 46 | 47 | 48 | static AVSValue __cdecl 49 | create_maskedmerge(AVSValue args, void*, IScriptEnvironment* env) 50 | { 51 | enum { BASE, ALT, MASK, MI, BLOCKX, BLOCKY, CHROMA, OPT }; 52 | try { 53 | validate(!args[BASE].Defined(), "base clip is not set."); 54 | validate(!args[ALT].Defined(), "alt clip is not set."); 55 | validate(!args[MASK].Defined(), "mask clip is not set."); 56 | 57 | PClip base = args[BASE].AsClip(); 58 | PClip alt = args[ALT].AsClip(); 59 | PClip mask = args[MASK].AsClip(); 60 | 61 | int mi = args[MI].AsInt(40); 62 | int bx = args[BLOCKX].AsInt(8); 63 | int by = args[BLOCKY].AsInt(8); 64 | bool ch = args[CHROMA].AsBool(true); 65 | bool is_avsplus = env->FunctionExists("SetFilterMTMode"); 66 | arch_t arch = get_arch(args[OPT].AsInt(-1), is_avsplus); 67 | 68 | return new MaskedMerge(base, alt, mask, mi, bx, by, ch, arch, is_avsplus); 69 | } catch (std::runtime_error& e) { 70 | env->ThrowError("MaskedMerge: %s", e.what()); 71 | } 72 | return 0; 73 | } 74 | 75 | 76 | static AVSValue __cdecl 77 | create_iscombed(AVSValue args, void*, ise_t* env) 78 | { 79 | enum { CLIP, CTHRESH, MTHRESH, MI, BLOCKX, BLOCKY, METRIC, OPT }; 80 | CombMask* cm = nullptr; 81 | 82 | try { 83 | AVSValue cf = env->GetVar("current_frame"); 84 | validate(!cf.IsInt(), 85 | "This filter can only be used within ConditionalFilter."); 86 | int n = cf.AsInt(); 87 | 88 | PClip clip = args[CLIP].AsClip(); 89 | int metric = args[METRIC].AsInt(0); 90 | int cth = args[CTHRESH].AsInt(metric == 0 ? 6 : 10); 91 | int mth = args[MTHRESH].AsInt(9); 92 | int mi = args[MI].AsInt(80); 93 | int blockx = args[BLOCKX].AsInt(16); 94 | int blocky = args[BLOCKY].AsInt(16); 95 | bool is_avsplus = env->FunctionExists("SetFilterMTMode"); 96 | arch_t arch = get_arch(args[OPT].AsInt(-1), is_avsplus); 97 | 98 | validate(mi < 0 || mi > 128, "MI must be between 0 and 128."); 99 | validate(blockx != 8 && blockx != 16 && blockx != 32, 100 | "blockx must be set to 8, 16 or 32."); 101 | validate(blocky != 8 && blocky != 16 && blocky != 32, 102 | "blocky must be set to 8, 16 or 32."); 103 | 104 | cm = new CombMask(clip, cth, mth, false, arch, false, metric, is_avsplus); 105 | 106 | bool is_combed = (get_check_combed(arch))( 107 | cm->GetFrame(n, env), mi, blockx, blocky, is_avsplus, env); 108 | 109 | delete cm; 110 | 111 | return AVSValue(is_combed); 112 | 113 | } catch (std::runtime_error& e) { 114 | if (cm) delete cm; 115 | env->ThrowError("IsCombed: %s", e.what()); 116 | } 117 | return 0; 118 | } 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | const AVS_Linkage* AVS_linkage = nullptr; 128 | 129 | 130 | extern "C" __declspec(dllexport) const char* __stdcall 131 | AvisynthPluginInit3(IScriptEnvironment* env, const AVS_Linkage* const vectors) 132 | { 133 | AVS_linkage = vectors; 134 | 135 | env->AddFunction( 136 | "CombMask", "c[cthresh]i[mthresh]i[chroma]b[expand]b[metric]i[opt]i", 137 | create_combmask, nullptr); 138 | env->AddFunction( 139 | "MaskedMerge", 140 | "[base]c[alt]c[mask]c[MI]i[blockx]i[blocky]i[chroma]b[opt]i", 141 | create_maskedmerge, nullptr); 142 | env->AddFunction( 143 | "IsCombed", 144 | "c[cthresh]i[mthresh]i[MI]i[blockx]i[blocky]i[metric]i[opt]i", 145 | create_iscombed, nullptr); 146 | 147 | return "CombMask filter for Avisynth2.6/Avisynth+ version " CMASK_VERSION; 148 | } 149 | -------------------------------------------------------------------------------- /vapoursynth/src/configure: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if test x"$1" = x"-h" -o x"$1" = x"--help" ; then 4 | cat << EOF 5 | Usage: ./configure [options] 6 | 7 | options: 8 | -h, --help print this message 9 | 10 | --install=PATH set dir for install library 11 | [/usr/local/lib/vapoursynth] 12 | --cc=CC use a defined compiler for compilation and linking 13 | [gcc] 14 | --target-os=OS build programs to run on OS [auto] 15 | --cross-prefix=PREFIX use PREFIX for compilation tools [none] 16 | --sysroot=DIR specify toolchain's directory [none] 17 | --enable-debug compile with debug symbols and never strip 18 | 19 | --extra-cflags=XCFLAGS add XCFLAGS to CFLAGS 20 | --extra-ldflags=XLDFLAGS add XLDFLAGS to LDFLAGS 21 | 22 | EOF 23 | exit 1 24 | fi 25 | 26 | error_exit() 27 | { 28 | echo error: $1 29 | exit 1 30 | } 31 | 32 | log_echo() 33 | { 34 | echo $1 35 | echo >> config.log 36 | echo ---------------------------------- >> config.log 37 | echo $1 >> config.log 38 | } 39 | 40 | cc_check() 41 | { 42 | echo 'int main(void){return 0;}' > conftest.c 43 | echo "$CC conftest.c $1 $2 -o conftest" >> config.log 44 | $CC conftest.c $1 $2 -o conftest 2> /dev/null 45 | ret=$? 46 | echo $ret >> config.log 47 | rm -f conftest* 48 | return $ret 49 | } 50 | 51 | rm -f config.* conftest* .depend 52 | SRCDIR="$(cd $(dirname $0); pwd)" 53 | test "$SRCDIR" = "$(pwd)" && SRCDIR=. 54 | test -n "$(echo $SRCDIR | grep ' ')" && \ 55 | error_exit "out-of-tree builds are impossible with whitespace in source path" 56 | 57 | echo 58 | echo generating config.mak ... 59 | echo 60 | 61 | echo 62 | libdir="/usr/local/lib/vapoursynth" 63 | TARGET_OS="" 64 | CROSS="" 65 | SYSROOT="" 66 | CC="gcc" 67 | LD="gcc" 68 | STRIP="strip" 69 | DEBUG="" 70 | LIBNAME="" 71 | CFLAGS="-Wshadow -Wall -Wextra -Wno-unused-parameter -std=gnu99 -msse2 -I. -I$SRCDIR" 72 | LDFLAGS="-shared" 73 | 74 | echo all command lines: > config.log 75 | echo "$*" >> config.log 76 | 77 | for opt; do 78 | optarg="${opt#*=}" 79 | case "$opt" in 80 | --cc=*) 81 | CC="$optarg" 82 | LD="$optarg" 83 | ;; 84 | --target-os=*) 85 | TARGET_OS="$optarg" 86 | ;; 87 | --cross-prefix=*) 88 | CROSS="$optarg" 89 | ;; 90 | --sysroot=*) 91 | CFLAGS="$CFLAGS --sysroot=$optarg" 92 | LDFLAGS="$LDFLAGS --sysroot=$optarg" 93 | ;; 94 | --enable-debug) 95 | DEBUG="enabled" 96 | ;; 97 | --extra-cflags=*) 98 | XCFLAGS="$optarg" 99 | ;; 100 | --extra-ldflags=*) 101 | XLDFLAGS="$optarg" 102 | ;; 103 | --install=*) 104 | libdir="$optarg" 105 | ;; 106 | *) 107 | error_exit "unknown option $opt" 108 | ;; 109 | esac 110 | done 111 | 112 | CC="${CROSS}${CC}" 113 | LD="${CROSS}${LD}" 114 | STRIP="${CROSS}${STRIP}" 115 | for f in "$CC" "$LD" "$STRIP"; do 116 | test -n "$(which $f 2> /dev/null)" || error_exit "$f is not executable" 117 | done 118 | test -n "$DEBUG" && STRIP="" 119 | 120 | if test -n "$TARGET_OS"; then 121 | TARGET_OS=$(echo $TARGET_OS | tr '[A-Z]' '[a-z]') 122 | else 123 | TARGET_OS=$($CC -dumpmachine | tr '[A-Z]' '[a-z]') 124 | fi 125 | case "$TARGET_OS" in 126 | *mingw*) 127 | LIBNAME="combmask.dll" 128 | LDFLAGS="$LDFLAGS -Wl,--dll,--add-stdcall-alias" 129 | ;; 130 | *linux*) 131 | LIBNAME="libcombmask.so" 132 | CFLAGS="$CFLAGS -fPIC" 133 | LDFLAGS="-fPIC $LDFLAGS" 134 | ;; 135 | *darwin*) 136 | LIBNAME="libcombmask.dylib" 137 | test -n "$STRIP" && STRIP="$STRIP -x" 138 | LDFLAGS="$LDFLAGS -dynamiclib -Wl,-undefined,suppress -Wl,-read_only_relocs,suppress -Wl,-flat_namespace" 139 | echo "The autor has no Mac environment. Thus, this script has not tested. May the force be with you." 140 | ;; 141 | *) 142 | error_exit "target is unsupported system." 143 | ;; 144 | esac 145 | 146 | log_echo "CFLAGS/LDFLAGS checking..." 147 | 148 | CFLAGS="$CFLAGS $XCFLAGS" 149 | LDFLAGS="$LDFLAGS -L. $XLDFLAGS" 150 | 151 | if test -n "$DEBUG"; then 152 | CFLAGS="$CFLAGS -g3 -O0" 153 | else 154 | CFLAGS="-Os -g0 -ffast-math -fomit-frame-pointer -fno-zero-initialized-in-bss $CFLAGS" 155 | fi 156 | 157 | if ! cc_check "$CFLAGS" "$LDFLAGS"; then 158 | error_exit "invalid CFLAGS/LDFLAGS" 159 | fi 160 | 161 | if cc_check "-march=i686 -mfpmath=sse $CFLAGS" "$LDFLAGS"; then 162 | CFLAGS="-march=i686 -mfpmath=sse $CFLAGS" 163 | fi 164 | 165 | if cc_check "$CFLAGS -fexcess-precision=fast" "$LDFLAGS"; then 166 | CFLAGS="$CFLAGS -fexcess-precision=fast" 167 | fi 168 | 169 | cat >> config.mak << EOF 170 | SRCDIR = $SRCDIR 171 | CC = $CC 172 | LD = $LD 173 | STRIP = $STRIP 174 | LIBNAME = $LIBNAME 175 | CFLAGS = $CFLAGS 176 | LDFLAGS = $LDFLAGS 177 | libdir = $libdir 178 | EOF 179 | 180 | cat >> config.log << EOF 181 | --------------------------------- 182 | setting 183 | --------------------------------- 184 | EOF 185 | cat config.mak >> config.log 186 | 187 | test "$SRCDIR" = "." || ln -sf $SRCDIR/GNUmakefile . 188 | 189 | echo configure finished 190 | exit 0 191 | -------------------------------------------------------------------------------- /vapoursynth/src/is_combed.c: -------------------------------------------------------------------------------- 1 | /* 2 | is_combed.c: Copyright (C) 2012-2013 Oka Motofumi 3 | 4 | Author: Oka Motofumi (chikuzen.mo at gmail dot com) 5 | 6 | This file is part of CombMask. 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public 10 | License as published by the Free Software Foundation; either 11 | version 2.1 of the License, or (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public 19 | License along with the author; if not, write to the Free Software 20 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 | */ 22 | 23 | 24 | #include 25 | #include "combmask.h" 26 | 27 | #ifdef _MSC_VER 28 | #define CM_ALIGN __declspec(align(16)) 29 | #else 30 | #define CM_ALIGN __attribute__((aligned(16))) 31 | #endif 32 | 33 | 34 | static int CM_FUNC_ALIGN VS_CC 35 | is_combed_8bit(combmask_t *ch, VSFrameRef *cmask, const VSAPI *vsapi) 36 | { 37 | int mi = ch->mi; 38 | int p = ch->planes[0] ? 0 : ch->planes[1] ? 1 : 2; 39 | 40 | int width = vsapi->getFrameWidth(cmask, p) / 16; 41 | int height = vsapi->getFrameHeight(cmask, p) / 16; 42 | int stride_0 = vsapi->getStride(cmask, p) / 16; 43 | int stride_1 = stride_0 * 16; 44 | 45 | const __m128i *srcp = (__m128i*)vsapi->getReadPtr(cmask, p); 46 | 47 | __m128i zero = _mm_setzero_si128(); 48 | __m128i all1 = _mm_cmpeq_epi32(zero, zero); 49 | __m128i one = _mm_set1_epi8((char)1); 50 | 51 | CM_ALIGN int64_t array[2]; 52 | __m128i *arr = (__m128i *)array; 53 | 54 | for (int y = 0; y < height; y++) { 55 | for (int x = 0; x < width; x++) { 56 | __m128i sum = zero; 57 | 58 | for (int i = 0; i < 16; i++) { 59 | // 0xFF == -1, thus the range of each bytes of sum is -16 to 0. 60 | __m128i xmm0 = _mm_load_si128(srcp + x + stride_0 * i); 61 | sum = _mm_add_epi8(sum, xmm0); 62 | } 63 | 64 | sum = _mm_xor_si128(sum, all1); 65 | sum = _mm_add_epi8(sum, one); // -x = ~x + 1 66 | sum = _mm_sad_epu8(sum, zero); 67 | _mm_store_si128(arr, sum); 68 | 69 | if (array[0] > mi || array[1] > mi) { 70 | ch->horizontal_dilation(ch, cmask, vsapi); 71 | return 1; 72 | } 73 | } 74 | srcp += stride_1; 75 | } 76 | 77 | return 0; 78 | } 79 | 80 | 81 | static int CM_FUNC_ALIGN VS_CC 82 | is_combed_9_10(combmask_t *ch, VSFrameRef *cmask, const VSAPI *vsapi) 83 | { 84 | int mi = ch->mi; 85 | int p = ch->planes[0] ? 0 : ch->planes[1] ? 1 : 2; 86 | 87 | int width = vsapi->getFrameWidth(cmask, p) / 8; 88 | int height = vsapi->getFrameHeight(cmask, p) / 16; 89 | int stride_0 = vsapi->getStride(cmask, p) / 16; 90 | int stride_1 = stride_0 * 16; 91 | 92 | const __m128i *srcp = (__m128i*)vsapi->getReadPtr(cmask, p); 93 | 94 | __m128i zero = _mm_setzero_si128(); 95 | __m128i one = _mm_srli_epi16(_mm_cmpeq_epi32(zero, zero), 15); 96 | 97 | CM_ALIGN int64_t array[2]; 98 | __m128i *arr = (__m128i *)array; 99 | 100 | for (int y = 0; y < height; y++) { 101 | for (int x = 0; x < width; x++) { 102 | __m128i sum = zero; 103 | 104 | for (int i = 0; i < 16; i++) { 105 | __m128i xmm0 = _mm_load_si128(srcp + x + stride_0 * i); 106 | xmm0 = _mm_and_si128(xmm0, one); 107 | sum = _mm_add_epi16(sum, xmm0); 108 | } 109 | 110 | sum = _mm_sad_epu8(sum, zero); 111 | _mm_store_si128(arr, sum); 112 | 113 | if (array[0] + array[1] > mi) { 114 | ch->horizontal_dilation(ch, cmask, vsapi); 115 | return 1; 116 | } 117 | } 118 | srcp += stride_1; 119 | } 120 | 121 | return 0; 122 | } 123 | 124 | 125 | static int CM_FUNC_ALIGN VS_CC 126 | is_combed_16bit(combmask_t *ch, VSFrameRef *cmask, const VSAPI *vsapi) 127 | { 128 | int mi = ch->mi; 129 | int p = ch->planes[0] ? 0 : ch->planes[1] ? 1 : 2; 130 | 131 | int width = vsapi->getFrameWidth(cmask, p) / 8; 132 | int height = vsapi->getFrameHeight(cmask, p) / 16; 133 | int stride_0 = vsapi->getStride(cmask, p) / 16; 134 | int stride_1 = stride_0 * 16; 135 | 136 | const __m128i *srcp = (__m128i*)vsapi->getReadPtr(cmask, p); 137 | 138 | __m128i zero = _mm_setzero_si128(); 139 | __m128i all1 = _mm_cmpeq_epi32(zero, zero); 140 | __m128i one = _mm_srli_epi16(all1, 15); 141 | 142 | CM_ALIGN int64_t array[2]; 143 | __m128i *arr = (__m128i *)array; 144 | 145 | for (int y = 0; y < height; y++) { 146 | for (int x = 0; x < width; x++) { 147 | __m128i sum = zero; 148 | 149 | for (int i = 0; i < 16; i++) { 150 | // 0xFFFF == -1, thus the range of each 2bytes of sum is -16 to 0. 151 | __m128i xmm0 = _mm_load_si128(srcp + x + stride_0 * i); 152 | sum = _mm_add_epi16(sum, xmm0); 153 | } 154 | 155 | sum = _mm_xor_si128(sum, all1); 156 | sum = _mm_add_epi16(sum, one); // -x = ~x + 1 157 | sum = _mm_sad_epu8(sum, zero); 158 | _mm_store_si128(arr, sum); 159 | 160 | if (array[0] + array[1] > mi) { 161 | ch->horizontal_dilation(ch, cmask, vsapi); 162 | return 1; 163 | } 164 | } 165 | srcp += stride_1; 166 | } 167 | 168 | return 0; 169 | } 170 | 171 | 172 | const func_is_combed is_combed_funcs[] = { 173 | is_combed_8bit, 174 | is_combed_9_10, 175 | is_combed_16bit 176 | }; 177 | -------------------------------------------------------------------------------- /avisynth/readme.txt: -------------------------------------------------------------------------------- 1 | CombMask - Combmask create filter for Avisynth2.6x/Avisynth+ 2 | 3 | 4 | description: 5 | CombMask is a simple filter that creates a comb mask that can (could) be 6 | used by other filters like MaskTools2. 7 | The mask consists of binaries of 0(not combed) and 255(combed). 8 | 9 | MaskedMerge is an exclusive masking filter for CombMask. This is often faster 10 | than MaskTools2's mt_merge(). 11 | 12 | IsCombed is a is a utility function that can be used within AviSynth's 13 | conditionalfilter to test whether or not a frame is combed and returns true 14 | if it is and false if it isn't. 15 | 16 | These filters are written from scratch, but most of logics are come from 17 | tritical's TIVTC plugin. 18 | 19 | 20 | syntax: 21 | CombMask(clip, int "cthresh", int "mthresh", bool "chroma", bool "expand", 22 | int "metric", int opt) 23 | 24 | cthresh: 25 | spatial combing threshold. 26 | 0 to 255, default is 6 (metric=0) 27 | 0 to 65025, default is 10 (metric=1) 28 | 29 | mthresh: 30 | motion adaptive threshold. 31 | 0 to 255, default is 9. 32 | 33 | chroma: 34 | Whether processing is performed to UV planes or not. 35 | default is true. 36 | 37 | expand: 38 | When set this to true, left and right pixels of combed pixel also 39 | assumed to combed. 40 | default is true. 41 | 42 | metric: 43 | Sets which spatial combing metric is used to detect combed pixels. 44 | Possible options: 45 | 46 | Assume 5 neighboring pixels (a,b,c,d,e) positioned vertically. 47 | 48 | a 49 | b 50 | c 51 | d 52 | e 53 | 54 | 0: d1 = c - b; 55 | d2 = c - d; 56 | if ((d1 > cthresh && d2 > cthresh) || (d1 < -cthresh && d2 < -cthresh)) 57 | { 58 | if (abs(a+4*c+e-3*(b+d)) > cthresh*6) it's combed; 59 | } 60 | 61 | 1: val = (b - c) * (d - c); 62 | if (val > cthresh) it's combed; 63 | 64 | default is 0. 65 | 66 | opt: 67 | specify which CPU optimization are used. 68 | 0 - Use C++ routine. 69 | 1 - Use SSE2 routin if possible. When SSE2 can't be used, fallback to 0. 70 | others(default) - Use AVX2 routine if possible. 71 | When AVX2 can't be used, fallback to 1. 72 | 73 | 74 | MaskedMerge(clip base, clip alt, clip mask, int "MI", int "blockx", int "blocky", 75 | bool "chroma", int opt) 76 | 77 | base: base clip. 78 | 79 | alt: alternate clip which will be merged to base. 80 | 81 | mask: mask clip. 82 | 83 | MI(0 to blockx*blocky , default is 80): 84 | The # of combed pixels inside any of blockx * blocky size blocks on the Y-plane 85 | for the frame to be detected as combed. 86 | if the frame is not combed, merge process will be skipped. 87 | 88 | blockx: 89 | Sets the x-axis size of the window used during combed frame detection. This has 90 | to do with the size of the area in which MI number of pixels are required to be 91 | detected as combed for a frame to be declared combed. 92 | Possible values are 8, 16(default) or 32. 93 | 94 | blockx: 95 | Sets the y-axis size of the window used during combed frame detection. This has 96 | to do with the size of the area in which MI number of pixels are required to be 97 | detected as combed for a frame to be declared combed. 98 | Possible values are 8, 16(default) or 32. 99 | 100 | chroma: 101 | Whether processing is performed to UV planes or not. 102 | Default is true. 103 | 104 | opt: 105 | same as CombMask. 106 | 107 | 108 | IsCombed(clip, int "cthresh", int "mthresh",int "MI", int "blockx", int "blocky", 109 | int "metric", int "opt") 110 | 111 | cthresh: Same as CombMask. 112 | 113 | mthresh: Same as CombMask. 114 | 115 | MI: Same as MaskedMerge. 116 | 117 | blockx: Same as MaskedMerge. 118 | 119 | blockx: Same as MaskedMerge. 120 | 121 | metric: Same as CombMask. 122 | 123 | opt: same as CombMask. 124 | 125 | 126 | note: 127 | 128 | - CombMask_avx2.dll is compiled with /arch:AVX2. 129 | 130 | - On Avisynth2.6, AVX2 can not to be enabled even if you use CombMask_avx2.dll. 131 | 132 | - On Avisynth+MT, CombMask and MaskedMerge are set as MT_NICE_FILTER automatically. 133 | 134 | - This plugin's filters require appropriate memory alignments. 135 | Thus, if you want to crop the left side of your source clip before these filters, 136 | you have to set crop(align=true). 137 | 138 | usage: 139 | 140 | LoadPlugin("CombMask.dll) 141 | src = SourceFilter("foo\bar\fizz\buzz") 142 | deint = src.some_deinterlace_filter() 143 | deint2 = src.another_filter() 144 | mask = deint.CombMask() 145 | last = deint.MaskedMerge(deint2, mask) 146 | return last 147 | 148 | 149 | LoadPlugin("CombMask.dll") 150 | src = a_YV12_clip 151 | combed = src.ConvertToYV16(interlaced=true) 152 | nocomb = src.ConvertToYV16(interlaced=false) 153 | ConditionalFilter(src, combed, nocomb, "IsCombed", "=", "true") 154 | 155 | 156 | reqirement: 157 | 158 | - Avisynth2.60 or later / Avisynth+ r2005 or greater. 159 | - Windows Vista sp2 / 7 sp1 / 8.1 / 10. 160 | - Microsoft Visual C++ 2015 Redistributable Package 161 | - SSE2 capable CPU 162 | 163 | 164 | author: 165 | Oka Motofumi (chikuzen.mo at gmail dot com) 166 | -------------------------------------------------------------------------------- /vapoursynth/src/adapt_motion.c: -------------------------------------------------------------------------------- 1 | /* 2 | adapt_motion.c: Copyright (C) 2012-2013 Oka Motofumi 3 | 4 | Author: Oka Motofumi (chikuzen.mo at gmail dot com) 5 | 6 | This file is part of CombMask. 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public 10 | License as published by the Free Software Foundation; either 11 | version 2.1 of the License, or (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public 19 | License along with the author; if not, write to the Free Software 20 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 | */ 22 | 23 | 24 | #include 25 | 26 | #define USE_ALIGNED_MALLOC 27 | #include "combmask.h" 28 | 29 | 30 | static void CM_FUNC_ALIGN VS_CC 31 | vertical_proc(__m128i *center, int width, int height, __m128i *dst) 32 | { 33 | __m128i *top = center + width; 34 | __m128i *bottom = top; 35 | 36 | for (int y = 0; y < height; y++) { 37 | for (int x = 0; x < width; x++) { 38 | __m128i xmm0 = _mm_load_si128(top + x); 39 | __m128i xmm1 = _mm_load_si128(center + x); 40 | __m128i xmm2 = _mm_load_si128(bottom + x); 41 | xmm0 = _mm_or_si128(xmm0, xmm2); 42 | xmm1 = _mm_or_si128(xmm1, xmm0); 43 | _mm_store_si128(dst + x, xmm1); 44 | } 45 | top = center; 46 | center = bottom; 47 | bottom = y < height - 2 ? bottom + width : bottom - width; 48 | dst += width; 49 | } 50 | } 51 | 52 | 53 | static void CM_FUNC_ALIGN VS_CC 54 | write_motionmask_8bit(int mthresh, int width, int height, int stride, 55 | __m128i *maskp, __m128i *srcp, __m128i *prevp) 56 | { 57 | __m128i xmth = _mm_set1_epi8((int8_t)mthresh); 58 | __m128i zero = _mm_setzero_si128(); 59 | __m128i all1 = _mm_cmpeq_epi32(zero, zero); 60 | 61 | for (int y = 0; y < height; y++) { 62 | for (int x = 0; x < width; x++) { 63 | __m128i xmm0 = _mm_load_si128(srcp + x); 64 | __m128i xmm1 = _mm_load_si128(prevp + x); 65 | 66 | __m128i xmm2 = _mm_max_epu8(xmm0, xmm1); 67 | xmm0 = _mm_min_epu8(xmm0, xmm1); 68 | xmm2 = _mm_subs_epu8(xmm2, xmm0); 69 | xmm2 = _mm_subs_epu8(xmm2, xmth); 70 | xmm2 = _mm_cmpeq_epi8(xmm2, zero); 71 | xmm2 = _mm_xor_si128(xmm2, all1); 72 | 73 | _mm_store_si128(maskp + x, xmm2); 74 | } 75 | srcp += stride; 76 | prevp += stride; 77 | maskp += width; 78 | } 79 | } 80 | 81 | 82 | static void CM_FUNC_ALIGN VS_CC 83 | write_motionmask_9_10(int mthresh, int width, int height, int stride, 84 | __m128i *maskp, __m128i *srcp, __m128i *prevp) 85 | { 86 | __m128i xmth = _mm_set1_epi16((int16_t)mthresh); 87 | 88 | for (int y = 0; y < height; y++) { 89 | for (int x = 0; x < width; x++) { 90 | __m128i xmm0 = _mm_load_si128(srcp + x); 91 | __m128i xmm1 = _mm_load_si128(prevp + x); 92 | 93 | __m128i xmm2 = _mm_max_epi16(xmm0, xmm1); 94 | xmm0 = _mm_min_epi16(xmm0, xmm1); 95 | xmm2 = _mm_sub_epi16(xmm2, xmm0); 96 | xmm2 = _mm_cmpgt_epi16(xmm2, xmth); 97 | 98 | _mm_store_si128(maskp, xmm2); 99 | } 100 | srcp += stride; 101 | prevp += stride; 102 | maskp += width; 103 | } 104 | } 105 | 106 | 107 | static void CM_FUNC_ALIGN VS_CC 108 | write_motionmask_16bit(int mthresh, int width, int height, int stride, 109 | __m128i *maskp, __m128i *srcp, __m128i *prevp) 110 | { 111 | __m128i xmth = _mm_set1_epi16((int16_t)mthresh); 112 | __m128i zero = _mm_setzero_si128(); 113 | __m128i all1 = _mm_cmpeq_epi32(zero, zero); 114 | 115 | for (int y = 0; y < height; y++) { 116 | for (int x = 0; x < width; x++) { 117 | __m128i xmm0 = _mm_load_si128(srcp + x); 118 | __m128i xmm1 = _mm_load_si128(prevp + x); 119 | 120 | __m128i xmm2 = MM_MAX_EPU16(xmm0, xmm1); 121 | xmm0 = MM_MIN_EPU16(xmm0, xmm1); 122 | xmm2 = _mm_subs_epu16(xmm2, xmm0); 123 | xmm2 = _mm_subs_epu16(xmm2, xmth); 124 | xmm2 = _mm_cmpeq_epi16(xmm2, zero); 125 | xmm2 = _mm_xor_si128(xmm2, all1); 126 | 127 | _mm_store_si128(maskp, xmm2); 128 | } 129 | srcp += stride; 130 | prevp += stride; 131 | maskp += width; 132 | } 133 | } 134 | 135 | 136 | static void CM_FUNC_ALIGN VS_CC 137 | adapt_motion_all(combmask_t *ch, const VSAPI *vsapi, const VSFrameRef *src, 138 | const VSFrameRef *prev, VSFrameRef *cmask) 139 | { 140 | int adjust = 16 / ch->vi->format->bytesPerSample; 141 | 142 | for (int p = 0; p < ch->vi->format->numPlanes; p++) { 143 | if (ch->planes[p] == 0) { 144 | continue; 145 | } 146 | 147 | int stride = vsapi->getStride(cmask, p) / 16; 148 | int width = (vsapi->getFrameWidth(cmask, p) + adjust - 1) / adjust; 149 | int height = vsapi->getFrameHeight(cmask, p); 150 | 151 | __m128i *mmtemp = (__m128i *)_aligned_malloc(width * height * 16 * 2, 16); 152 | __m128i *mmaskp = mmtemp + width * height; 153 | 154 | ch->write_motionmask(ch->mthresh, width, height, stride, mmtemp, 155 | (__m128i *)vsapi->getReadPtr(src, p), 156 | (__m128i *)vsapi->getReadPtr(prev, p)); 157 | vertical_proc(mmtemp, width, height, mmaskp); 158 | 159 | __m128i *cmaskp = (__m128i *)vsapi->getWritePtr(cmask, p); 160 | 161 | for (int y = 0; y < height; y++) { 162 | for (int x = 0; x < width; x++) { 163 | __m128i xmm0 = _mm_load_si128(cmaskp + x); 164 | __m128i xmm1 = _mm_load_si128(mmaskp + x); 165 | xmm0 = _mm_and_si128(xmm0, xmm1); 166 | _mm_store_si128(cmaskp + x, xmm0); 167 | } 168 | cmaskp += stride; 169 | mmaskp += width; 170 | } 171 | _aligned_free(mmtemp); 172 | } 173 | } 174 | 175 | 176 | const func_adapt_motion adapt_motion = adapt_motion_all; 177 | 178 | const func_write_motionmask write_motionmask_funcs[] = { 179 | write_motionmask_8bit, 180 | write_motionmask_9_10, 181 | write_motionmask_16bit 182 | }; 183 | -------------------------------------------------------------------------------- /avisynth/vs2015/CombMask.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {6B5469DF-E6CA-4A4E-B879-9672E926A88A} 23 | Win32Proj 24 | 8.1 25 | 26 | 27 | 28 | DynamicLibrary 29 | true 30 | v140 31 | MultiByte 32 | 33 | 34 | DynamicLibrary 35 | false 36 | v140 37 | MultiByte 38 | true 39 | 40 | 41 | Application 42 | true 43 | v140 44 | 45 | 46 | DynamicLibrary 47 | false 48 | v140 49 | MultiByte 50 | true 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | true 72 | 73 | 74 | false 75 | 76 | 77 | 78 | WIN32;_DEBUG;_WINDOWS;_USRDLL;COMBMASK_EXPORTS;%(PreprocessorDefinitions) 79 | MultiThreadedDebugDLL 80 | Level3 81 | ProgramDatabase 82 | Disabled 83 | C:\my_projects\AviSynthPlus\avs_core\include;%(AdditionalIncludeDirectories) 84 | AdvancedVectorExtensions2 85 | Fast 86 | 87 | 88 | MachineX86 89 | true 90 | Windows 91 | 92 | 93 | 94 | 95 | WIN32;NDEBUG;_WINDOWS;_USRDLL;COMBMASK_EXPORTS;%(PreprocessorDefinitions) 96 | MultiThreadedDLL 97 | Level3 98 | ProgramDatabase 99 | C:\my_projects\AviSynthPlus\avs_core\include;%(AdditionalIncludeDirectories) 100 | AnySuitable 101 | true 102 | Speed 103 | true 104 | true 105 | StreamingSIMDExtensions2 106 | Fast 107 | 108 | 109 | MachineX86 110 | true 111 | Windows 112 | true 113 | true 114 | 115 | 116 | 117 | 118 | C:\my_projects\AviSynthPlus\avs_core\include;%(AdditionalIncludeDirectories) 119 | AnySuitable 120 | true 121 | Speed 122 | true 123 | true 124 | NotSet 125 | Fast 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /avisynth/src/MaskedMerge.cpp: -------------------------------------------------------------------------------- 1 | #include "CombMask.h" 2 | #include "simd.h" 3 | 4 | 5 | template 6 | static bool __stdcall 7 | check_combed_simd(PVideoFrame& cmask, int mi, int blockx, int blocky, 8 | bool is_avsplus, ise_t* env) 9 | { 10 | const int width = cmask->GetRowSize(PLANAR_Y) & (~(blockx - 1)); 11 | const int height = cmask->GetHeight(PLANAR_Y) & (~(blocky - 1)); 12 | const int pitch = cmask->GetPitch(PLANAR_Y); 13 | 14 | const uint8_t* srcp = cmask->GetReadPtr(PLANAR_Y); 15 | 16 | size_t pitch_a = (width + 31) & (~31); 17 | uint8_t* arr = reinterpret_cast( 18 | alloc_buffer(pitch_a * 4, 32, is_avsplus, env)); 19 | int64_t* array[] = { 20 | reinterpret_cast(arr), 21 | reinterpret_cast(arr + pitch_a), 22 | reinterpret_cast(arr + pitch_a * 2), 23 | reinterpret_cast(arr + pitch_a * 3), 24 | }; 25 | int length = width / sizeof(int64_t); 26 | int stepx = blockx / 8; 27 | int stepy = blocky / 8; 28 | 29 | const V zero = setzero(); 30 | 31 | for (int y = 0; y < height; y += 32) { 32 | for (int j = 0; j < 4; ++j) { 33 | for (int x = 0; x < width; x += sizeof(V)) { 34 | // 0xFF == -1, thus the range of each bytes of sum is -8 to 0. 35 | V sum = load(srcp + x); 36 | sum = add_i8(sum, load(srcp + x + pitch * 1)); 37 | sum = add_i8(sum, load(srcp + x + pitch * 2)); 38 | sum = add_i8(sum, load(srcp + x + pitch * 3)); 39 | sum = add_i8(sum, load(srcp + x + pitch * 4)); 40 | sum = add_i8(sum, load(srcp + x + pitch * 5)); 41 | sum = add_i8(sum, load(srcp + x + pitch * 6)); 42 | sum = add_i8(sum, load(srcp + x + pitch * 7)); 43 | sum = sad_u8(sub_i8(zero, sum), zero); 44 | store(arr + x + pitch_a * j, sum); 45 | } 46 | srcp += pitch * 8; 47 | } 48 | 49 | for (int xx = 0; xx < length; xx += stepx) { 50 | int64_t sum = 0; 51 | for (int by = 0; by < stepy; ++by) { 52 | for (int bx = 0; bx < stepx; ++bx) { 53 | sum += array[by][xx + bx]; 54 | } 55 | } 56 | if (sum > mi) { 57 | free_buffer(arr, is_avsplus, env); 58 | return true; 59 | } 60 | } 61 | } 62 | free_buffer(arr, is_avsplus, env); 63 | return false; 64 | } 65 | 66 | 67 | static bool __stdcall 68 | check_combed_c(PVideoFrame& cmask, int mi, int blockx, int blocky, bool, ise_t*) 69 | { 70 | const int width = cmask->GetRowSize(PLANAR_Y) & (~(blockx - 1)); 71 | const int height = cmask->GetHeight(PLANAR_Y) & (~(blocky - 1)); 72 | const int pitch = cmask->GetPitch(PLANAR_Y); 73 | 74 | const uint8_t* srcp = cmask->GetReadPtr(PLANAR_Y); 75 | 76 | for (int y = 0; y < height; y += blocky) { 77 | for (int x = 0; x < width; x += blockx) { 78 | int count = 0; 79 | for (int i = 0; i < blocky; ++i) { 80 | for (int j = 0; j < blockx; ++j) { 81 | count += (srcp[x + j + i * pitch] & 1); 82 | } 83 | } 84 | if (count > mi) { 85 | return true; 86 | } 87 | } 88 | srcp += pitch * blocky; 89 | } 90 | return false; 91 | } 92 | 93 | 94 | template 95 | static void __stdcall 96 | merge_frames_simd(int num_planes, PVideoFrame& src, PVideoFrame& alt, 97 | PVideoFrame& mask, PVideoFrame& dst) 98 | { 99 | static const int planes[] = { PLANAR_Y, PLANAR_U, PLANAR_V }; 100 | 101 | for (int p = 0; p < num_planes; ++p) { 102 | const int plane = planes[p]; 103 | 104 | const uint8_t* srcp = src->GetReadPtr(plane); 105 | const uint8_t* altp = alt->GetReadPtr(plane); 106 | const uint8_t* mskp = mask->GetReadPtr(plane); 107 | uint8_t* dstp = dst->GetWritePtr(plane); 108 | 109 | const int width = src->GetRowSize(plane); 110 | const int height = src->GetHeight(plane); 111 | 112 | const int spitch = src->GetPitch(plane); 113 | const int apitch = alt->GetPitch(plane); 114 | const int mpitch = mask->GetPitch(plane); 115 | const int dpitch = dst->GetPitch(plane); 116 | 117 | for (int y = 0; y < height; y++) { 118 | for (int x = 0; x < width; x += sizeof(V)) { 119 | const V s = load(srcp + x); 120 | const V a = load(altp + x); 121 | const V m = load(mskp + x); 122 | 123 | stream(dstp + x, blendv(s, a, m)); 124 | } 125 | srcp += spitch; 126 | altp += apitch; 127 | mskp += mpitch; 128 | dstp += dpitch; 129 | } 130 | } 131 | } 132 | 133 | 134 | static void __stdcall 135 | merge_frames_c(int num_planes, PVideoFrame& src, PVideoFrame& alt, 136 | PVideoFrame& mask, PVideoFrame& dst) 137 | { 138 | static const int planes[] = { PLANAR_Y, PLANAR_U, PLANAR_V }; 139 | 140 | for (int p = 0; p < num_planes; ++p) { 141 | const int plane = planes[p]; 142 | const uint8_t* srcp = src->GetReadPtr(plane); 143 | const uint8_t* altp = alt->GetReadPtr(plane); 144 | const uint8_t* mskp = mask->GetReadPtr(plane); 145 | uint8_t* dstp = dst->GetWritePtr(plane); 146 | 147 | const int width = src->GetRowSize(plane); 148 | const int height = src->GetHeight(plane); 149 | 150 | const int spitch = src->GetPitch(plane); 151 | const int apitch = alt->GetPitch(plane); 152 | const int mpitch = mask->GetPitch(plane); 153 | const int dpitch = dst->GetPitch(plane); 154 | 155 | for (int y = 0; y < height; y++) { 156 | for (int x = 0; x < width; x++) { 157 | dstp[x] = (srcp[x] & (~mskp[x])) | (altp[x] & mskp[x]); 158 | } 159 | srcp += spitch; 160 | altp += apitch; 161 | mskp += mpitch; 162 | dstp += dpitch; 163 | } 164 | } 165 | } 166 | 167 | 168 | 169 | 170 | check_combed_t get_check_combed(arch_t arch) 171 | { 172 | 173 | #if defined(__AVX2__) 174 | if (arch == USE_AVX2) { 175 | return check_combed_simd<__m256i>; 176 | } 177 | #endif 178 | if (arch == USE_SSE2) { 179 | return check_combed_simd<__m128i>; 180 | } 181 | return check_combed_c; 182 | } 183 | 184 | 185 | 186 | MaskedMerge:: 187 | MaskedMerge(PClip c, PClip a, PClip m, int _mi, int bx, int by, bool chroma, 188 | arch_t arch, bool ip) : 189 | GVFmod(c, chroma, arch, ip), altc(a), maskc(m), mi(_mi), blockx(bx), 190 | blocky(by) 191 | { 192 | validate(!vi.IsPlanar(), "planar format only."); 193 | validate(mi < 0 || mi > 128, "mi must be between 0 and 128."); 194 | validate(blockx < 8 || blockx > 32 || blockx % 8 > 0, 195 | "blockx must be set to 8, 16 or 32."); 196 | validate(blocky < 8 || blocky > 32 || blocky % 8 > 0, 197 | "blocky must be set to 8, 16 or 32."); 198 | 199 | const VideoInfo& a_vi = altc->GetVideoInfo(); 200 | const VideoInfo& m_vi = maskc->GetVideoInfo(); 201 | validate(!vi.IsSameColorspace(a_vi) || !vi.IsSameColorspace(m_vi), 202 | "unmatch colorspaces."); 203 | validate(vi.width != a_vi.width || vi.width != m_vi.width || 204 | vi.height != a_vi.height || vi.height != m_vi.height, 205 | "unmatch resolutions."); 206 | 207 | switch (arch) { 208 | #if defined(__AVX2__) 209 | case USE_AVX2: 210 | mergeFrames = merge_frames_simd<__m256i>; 211 | break; 212 | #endif 213 | case USE_SSE2: 214 | mergeFrames = merge_frames_simd<__m128i>; 215 | break; 216 | default: 217 | mergeFrames = merge_frames_c; 218 | } 219 | 220 | checkCombed = get_check_combed(arch); 221 | } 222 | 223 | 224 | PVideoFrame __stdcall MaskedMerge::GetFrame(int n, ise_t* env) 225 | { 226 | PVideoFrame src = child->GetFrame(n, env); 227 | PVideoFrame mask = maskc->GetFrame(n, env); 228 | if (mi > 0 && !checkCombed(mask, mi, blockx, blocky, isPlus, env)) { 229 | return src; 230 | } 231 | 232 | PVideoFrame alt = altc->GetFrame(n, env); 233 | PVideoFrame dst = env->NewVideoFrame(vi); 234 | 235 | mergeFrames(numPlanes, src, alt, mask, dst); 236 | 237 | if (numPlanes == 1 && !vi.IsY8()) { 238 | const int src_pitch = src->GetPitch(PLANAR_U); 239 | const int dst_pitch = dst->GetPitch(PLANAR_U); 240 | const int width = src->GetRowSize(PLANAR_U); 241 | const int height = src->GetHeight(PLANAR_U); 242 | env->BitBlt(dst->GetWritePtr(PLANAR_U), dst_pitch, 243 | src->GetReadPtr(PLANAR_U), src_pitch, width, height); 244 | env->BitBlt(dst->GetWritePtr(PLANAR_V), dst_pitch, 245 | src->GetReadPtr(PLANAR_V), src_pitch, width, height); 246 | } 247 | 248 | return dst; 249 | } 250 | 251 | -------------------------------------------------------------------------------- /avisynth/src/simd.h: -------------------------------------------------------------------------------- 1 | #ifndef COMB_MASK_SIMD_H 2 | #define COMB_MASK_SIMD_H 3 | 4 | 5 | #include 6 | #if defined(__AVX2__) 7 | #include 8 | #else 9 | #include 10 | #endif 11 | 12 | #define FINLINE __forceinline 13 | #define SFINLINE static __forceinline 14 | 15 | 16 | template 17 | SFINLINE V load(const uint8_t* p); 18 | 19 | template 20 | SFINLINE V loadu(const uint8_t* p); 21 | 22 | template 23 | SFINLINE V load_half(const uint8_t* p); 24 | 25 | template 26 | SFINLINE V set1_i16(int16_t val); 27 | 28 | template 29 | SFINLINE V set1_i8(int8_t val); 30 | 31 | template 32 | SFINLINE V setzero(); 33 | 34 | 35 | 36 | template <> 37 | FINLINE __m128i load(const uint8_t* p) 38 | { 39 | return _mm_load_si128(reinterpret_cast(p)); 40 | } 41 | 42 | template <> 43 | FINLINE __m128i loadu(const uint8_t* p) 44 | { 45 | return _mm_loadu_si128(reinterpret_cast(p)); 46 | } 47 | 48 | template <> 49 | FINLINE __m128i load_half(const uint8_t* p) 50 | { 51 | __m128i t = _mm_loadl_epi64(reinterpret_cast(p)); 52 | return _mm_unpacklo_epi8(t, _mm_setzero_si128()); 53 | } 54 | 55 | template <> 56 | FINLINE __m128i set1_i16(int16_t val) 57 | { 58 | return _mm_set1_epi16(val); 59 | } 60 | 61 | template <> 62 | FINLINE __m128i set1_i8(int8_t val) 63 | { 64 | return _mm_set1_epi8(val); 65 | } 66 | 67 | template <> 68 | FINLINE __m128i setzero() 69 | { 70 | return _mm_setzero_si128(); 71 | } 72 | 73 | SFINLINE void store_half(uint8_t* p, const __m128i& x) 74 | { 75 | __m128i t = _mm_packs_epi16(x, x); 76 | _mm_storel_epi64(reinterpret_cast<__m128i*>(p), t); 77 | } 78 | 79 | SFINLINE void store_half_us(uint8_t* p, const __m128i& x) 80 | { 81 | __m128i t = _mm_packus_epi16(x, x); 82 | _mm_storel_epi64(reinterpret_cast<__m128i*>(p), t); 83 | } 84 | 85 | SFINLINE void store(uint8_t* p, const __m128i& x) 86 | { 87 | _mm_store_si128(reinterpret_cast<__m128i*>(p), x); 88 | } 89 | 90 | SFINLINE void stream(uint8_t* p, const __m128i& x) 91 | { 92 | _mm_stream_si128(reinterpret_cast<__m128i*>(p), x); 93 | } 94 | 95 | SFINLINE __m128i add_i16(const __m128i& x, const __m128i& y) 96 | { 97 | return _mm_add_epi16(x, y); 98 | } 99 | 100 | SFINLINE __m128i add_i8(const __m128i& x, const __m128i& y) 101 | { 102 | return _mm_add_epi8(x, y); 103 | } 104 | 105 | SFINLINE __m128i sub_i16(const __m128i& x, const __m128i& y) 106 | { 107 | return _mm_sub_epi16(x, y); 108 | } 109 | 110 | SFINLINE __m128i sub_i8(const __m128i& x, const __m128i& y) 111 | { 112 | return _mm_sub_epi8(x, y); 113 | } 114 | 115 | SFINLINE __m128i subs(const __m128i& x, const __m128i& y) 116 | { 117 | return _mm_subs_epu8(x, y); 118 | } 119 | 120 | SFINLINE __m128i mullo(const __m128i& x, const __m128i& y) 121 | { 122 | return _mm_mullo_epi16(x, y); 123 | } 124 | 125 | SFINLINE __m128i mulhi(const __m128i& x, const __m128i& y) 126 | { 127 | return _mm_mulhi_epi16(x, y); 128 | } 129 | 130 | SFINLINE __m128i or_reg(const __m128i& x, const __m128i& y) 131 | { 132 | return _mm_or_si128(x, y); 133 | } 134 | 135 | SFINLINE __m128i xor_reg(const __m128i& x, const __m128i& y) 136 | { 137 | return _mm_xor_si128(x, y); 138 | } 139 | 140 | SFINLINE __m128i and_reg(const __m128i& x, const __m128i& y) 141 | { 142 | return _mm_and_si128(x, y); 143 | } 144 | 145 | SFINLINE __m128i andnot(const __m128i& x, const __m128i& y) 146 | { 147 | return _mm_andnot_si128(x, y); 148 | } 149 | 150 | SFINLINE __m128i min_i16(const __m128i& x, const __m128i& y) 151 | { 152 | return _mm_min_epi16(x, y); 153 | } 154 | 155 | SFINLINE __m128i min_u16(const __m128i& x, const __m128i& y) 156 | { 157 | return _mm_subs_epu16(x, _mm_subs_epu16(x, y)); 158 | } 159 | 160 | SFINLINE __m128i min_u8(const __m128i& x, const __m128i& y) 161 | { 162 | return _mm_min_epu8(x, y); 163 | } 164 | 165 | SFINLINE __m128i max_i16(const __m128i& x, const __m128i& y) 166 | { 167 | return _mm_max_epi16(x, y); 168 | } 169 | 170 | SFINLINE __m128i max_u16(const __m128i& x, const __m128i& y) 171 | { 172 | return _mm_adds_epu16(y, _mm_subs_epu16(x, y)); 173 | } 174 | 175 | SFINLINE __m128i max_u8(const __m128i& x, const __m128i& y) 176 | { 177 | return _mm_max_epu8(x, y); 178 | } 179 | 180 | SFINLINE __m128i cmpeq_i8(const __m128i& x, const __m128i& y) 181 | { 182 | return _mm_cmpeq_epi8(x, y); 183 | } 184 | 185 | SFINLINE __m128i cmpeq_i16(const __m128i& x, const __m128i& y) 186 | { 187 | return _mm_cmpeq_epi16(x, y); 188 | } 189 | 190 | SFINLINE __m128i cmpgt_i16(const __m128i& x, const __m128i& y) 191 | { 192 | return _mm_cmpgt_epi16(x, y); 193 | } 194 | 195 | SFINLINE __m128i absdiff_i16(const __m128i& x, const __m128i& y) 196 | { 197 | return max_i16(sub_i16(x, y), sub_i16(y, x)); 198 | } 199 | 200 | SFINLINE __m128i lshift_i16(const __m128i& x, int n) 201 | { 202 | return _mm_slli_epi16(x, n); 203 | } 204 | 205 | SFINLINE __m128i sad_u8(const __m128i& x, const __m128i& y) 206 | { 207 | return _mm_sad_epu8(x, y); 208 | } 209 | 210 | SFINLINE __m128i blendv(const __m128i& x, const __m128i& y, const __m128i& m) 211 | { 212 | return or_reg(and_reg(m, y), andnot(m, x)); 213 | } 214 | 215 | #if defined(__AVX2__) 216 | 217 | template <> 218 | FINLINE __m256i load(const uint8_t* p) 219 | { 220 | return _mm256_load_si256(reinterpret_cast(p)); 221 | } 222 | 223 | template<> 224 | FINLINE __m256i loadu(const uint8_t* p) 225 | { 226 | return _mm256_loadu_si256(reinterpret_cast(p)); 227 | } 228 | 229 | template <> 230 | FINLINE __m256i load_half(const uint8_t* p) 231 | { 232 | __m128i t = _mm_load_si128(reinterpret_cast(p)); 233 | return _mm256_cvtepu8_epi16(t); 234 | } 235 | 236 | template <> 237 | FINLINE __m256i set1_i16(int16_t val) 238 | { 239 | return _mm256_set1_epi16(val); 240 | } 241 | 242 | template <> 243 | FINLINE __m256i set1_i8(int8_t val) 244 | { 245 | return _mm256_set1_epi8(val); 246 | } 247 | 248 | template <> 249 | FINLINE __m256i setzero() 250 | { 251 | return _mm256_setzero_si256(); 252 | } 253 | 254 | SFINLINE void store_half(uint8_t* p, const __m256i& x) 255 | { 256 | __m256i t = _mm256_packs_epi16(x, _mm256_permute2x128_si256(x, x, 0x01)); 257 | _mm_store_si128(reinterpret_cast<__m128i*>(p), _mm256_extracti128_si256(t, 0)); 258 | } 259 | 260 | SFINLINE void store(uint8_t* p, const __m256i& x) 261 | { 262 | _mm256_store_si256(reinterpret_cast<__m256i*>(p), x); 263 | } 264 | 265 | SFINLINE void stream(uint8_t* p, const __m256i& x) 266 | { 267 | _mm256_stream_si256(reinterpret_cast<__m256i*>(p), x); 268 | } 269 | 270 | SFINLINE __m256i add_i16(const __m256i& x, const __m256i& y) 271 | { 272 | return _mm256_add_epi16(x, y); 273 | } 274 | 275 | SFINLINE __m256i add_i8(const __m256i& x, const __m256i& y) 276 | { 277 | return _mm256_add_epi8(x, y); 278 | } 279 | 280 | SFINLINE __m256i sub_i16(const __m256i& x, const __m256i& y) 281 | { 282 | return _mm256_sub_epi16(x, y); 283 | } 284 | 285 | SFINLINE __m256i sub_i8(const __m256i& x, const __m256i& y) 286 | { 287 | return _mm256_sub_epi8(x, y); 288 | } 289 | 290 | SFINLINE __m256i subs(const __m256i& x, const __m256i& y) 291 | { 292 | return _mm256_subs_epu8(x, y); 293 | } 294 | 295 | SFINLINE __m256i mullo(const __m256i& x, const __m256i& y) 296 | { 297 | return _mm256_mullo_epi16(x, y); 298 | } 299 | 300 | SFINLINE __m256i mulhi(const __m256i& x, const __m256i& y) 301 | { 302 | return _mm256_mulhi_epi16(x, y); 303 | } 304 | 305 | SFINLINE __m256i or_reg(const __m256i& x, const __m256i& y) 306 | { 307 | return _mm256_or_si256(x, y); 308 | } 309 | 310 | SFINLINE __m256i xor_reg(const __m256i& x, const __m256i& y) 311 | { 312 | return _mm256_xor_si256(x, y); 313 | } 314 | 315 | SFINLINE __m256i and_reg(const __m256i& x, const __m256i& y) 316 | { 317 | return _mm256_and_si256(x, y); 318 | } 319 | 320 | SFINLINE __m256i andnot(const __m256i& x, const __m256i& y) 321 | { 322 | return _mm256_andnot_si256(x, y); 323 | } 324 | 325 | SFINLINE __m256i min_i16(const __m256i& x, const __m256i& y) 326 | { 327 | return _mm256_min_epi16(x, y); 328 | } 329 | 330 | SFINLINE __m256i min_u16(const __m256i& x, const __m256i& y) 331 | { 332 | return _mm256_min_epu16(x, y); 333 | } 334 | 335 | SFINLINE __m256i min_u8(const __m256i& x, const __m256i& y) 336 | { 337 | return _mm256_min_epu8(x, y); 338 | } 339 | 340 | SFINLINE __m256i max_i16(const __m256i& x, const __m256i& y) 341 | { 342 | return _mm256_max_epi16(x, y); 343 | } 344 | 345 | SFINLINE __m256i max_u16(const __m256i& x, const __m256i& y) 346 | { 347 | return _mm256_max_epu16(x, y); 348 | } 349 | 350 | SFINLINE __m256i max_u8(const __m256i& x, const __m256i& y) 351 | { 352 | return _mm256_max_epu8(x, y); 353 | } 354 | 355 | SFINLINE __m256i cmpgt_i16(const __m256i& x, const __m256i& y) 356 | { 357 | return _mm256_cmpgt_epi16(x, y); 358 | } 359 | 360 | SFINLINE __m256i cmpeq_i8(const __m256i& x, const __m256i& y) 361 | { 362 | return _mm256_cmpeq_epi8(x, y); 363 | } 364 | 365 | SFINLINE __m256i cmpeq_i16(const __m256i& x, const __m256i& y) 366 | { 367 | return _mm256_cmpeq_epi16(x, y); 368 | } 369 | 370 | SFINLINE __m256i absdiff_i16(const __m256i& x, const __m256i& y) 371 | { 372 | return _mm256_abs_epi16(sub_i16(x, y)); 373 | } 374 | 375 | SFINLINE __m256i lshift_i16(const __m256i& x, int n) 376 | { 377 | return _mm256_slli_epi16(x, n); 378 | } 379 | 380 | SFINLINE __m256i sad_u8(const __m256i& x, const __m256i& y) 381 | { 382 | return _mm256_sad_epu8(x, y); 383 | } 384 | 385 | SFINLINE __m256i blendv(const __m256i& x, const __m256i& y, const __m256i& m) 386 | { 387 | return _mm256_blendv_epi8(x, y, m); 388 | } 389 | #endif 390 | 391 | 392 | template 393 | SFINLINE V mul3(const V& x) 394 | { 395 | return add_i16(x, add_i16(x, x)); 396 | } 397 | 398 | template 399 | SFINLINE V absdiff_u8(const V& x, const V& y) 400 | { 401 | return or_reg(subs(x, y), subs(y, x)); 402 | } 403 | 404 | template 405 | SFINLINE V cmpgt_u8(const V& x, const V& y, const V& all) 406 | { 407 | return xor_reg(cmpeq_i8(max_u8(x, y), y), all); 408 | } 409 | 410 | template 411 | SFINLINE V cmpgt_u16(const V& x, const V& y, const V& all) 412 | { 413 | return xor_reg(cmpeq_i16(max_u16(x, y), y), all); 414 | } 415 | 416 | template 417 | SFINLINE V cmplt_u8(const V& x, const V& y, const V& all) 418 | { 419 | return xor_reg(cmpeq_i8(max_u8(x, y), y), all); 420 | } 421 | 422 | 423 | 424 | 425 | 426 | 427 | #endif 428 | 429 | -------------------------------------------------------------------------------- /vapoursynth/src/combmask.c: -------------------------------------------------------------------------------- 1 | /* 2 | combmask.c: Copyright (C) 2012-2013 Oka Motofumi 3 | 4 | Author: Oka Motofumi (chikuzen.mo at gmail dot com) 5 | 6 | This file is part of CombMask. 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public 10 | License as published by the Free Software Foundation; either 11 | version 2.1 of the License, or (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public 19 | License along with the author; if not, write to the Free Software 20 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 | */ 22 | 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include "VapourSynth.h" 29 | #include "combmask.h" 30 | 31 | #ifdef _MSC_VER 32 | #define snprintf _snprintf 33 | #endif 34 | 35 | 36 | static int VS_CC 37 | set_planes(int *planes, const VSMap *in, const VSAPI *vsapi) 38 | { 39 | int num = vsapi->propNumElements(in, "planes"); 40 | if (num < 1) { 41 | for (int i = 0; i < 3; planes[i++] = 1); 42 | return 0; 43 | } 44 | 45 | for (int i = 0; i < num; i++) { 46 | int p = (int)vsapi->propGetInt(in, "planes", i, NULL); 47 | if (p < 0 || p > 2) { 48 | return -1; 49 | } 50 | planes[p] = 1; 51 | } 52 | 53 | return 0; 54 | } 55 | 56 | 57 | static void 58 | set_param_int(int *param, const char *name, int undef, int min, int max, 59 | const VSMap *in, const VSAPI *vsapi, char *buff) 60 | { 61 | int err; 62 | *param = (int)vsapi->propGetInt(in, name, 0, &err); 63 | if (err) { 64 | *param = undef; 65 | } 66 | 67 | if (*param < min || *param > max) { 68 | sprintf(buff, "%s must be between %d and %d.", name, min, max); 69 | } 70 | } 71 | 72 | 73 | 74 | static const VSFrameRef * VS_CC 75 | get_frame_combmask(int n, int activation_reason, void **instance_data, 76 | void **frame_data, VSFrameContext *frame_ctx, VSCore *core, 77 | const VSAPI *vsapi) 78 | { 79 | combmask_t *ch = (combmask_t *)*instance_data; 80 | int p = n == 0 ? 1 : n - 1; 81 | 82 | if (activation_reason == arInitial) { 83 | vsapi->requestFrameFilter(n, ch->node, frame_ctx); 84 | if (ch->mthresh > 0) { 85 | vsapi->requestFrameFilter(p, ch->node, frame_ctx); 86 | } 87 | return NULL; 88 | } 89 | 90 | if (activation_reason != arAllFramesReady) { 91 | return NULL; 92 | } 93 | 94 | const VSFrameRef *src = vsapi->getFrameFilter(n, ch->node, frame_ctx); 95 | 96 | VSFrameRef *cmask = vsapi->newVideoFrame(ch->vi->format, ch->vi->width, 97 | ch->vi->height, NULL, core); 98 | 99 | ch->write_combmask(ch, vsapi, src, cmask); 100 | 101 | if (ch->mthresh > 0) { 102 | const VSFrameRef *prev = vsapi->getFrameFilter(p, ch->node, frame_ctx); 103 | adapt_motion(ch, vsapi, src, prev, cmask); 104 | vsapi->freeFrame(prev); 105 | } 106 | 107 | vsapi->freeFrame(src); 108 | 109 | vsapi->propSetInt(vsapi->getFramePropsRW(cmask), "_Combed", 110 | ch->is_combed(ch, cmask, vsapi), paReplace); 111 | 112 | return cmask; 113 | } 114 | 115 | 116 | static void VS_CC 117 | init_combmask(VSMap *in, VSMap *out, void **instance_data, VSNode *node, 118 | VSCore *core, const VSAPI *vsapi) 119 | { 120 | combmask_t *ch = (combmask_t *)*instance_data; 121 | vsapi->setVideoInfo(ch->vi, 1, node); 122 | vsapi->clearMap(in); 123 | } 124 | 125 | 126 | static void VS_CC 127 | close_combmask(void *instance_data, VSCore *core, const VSAPI *vsapi) 128 | { 129 | combmask_t * ch = (combmask_t *)instance_data; 130 | if (!ch) { 131 | return; 132 | } 133 | if (ch->node) { 134 | vsapi->freeNode(ch->node); 135 | ch->node = NULL; 136 | } 137 | free(ch); 138 | ch = NULL; 139 | } 140 | 141 | 142 | static void VS_CC 143 | create_combmask(const VSMap *in, VSMap *out, void *user_data, VSCore *core, 144 | const VSAPI *vsapi) 145 | { 146 | #define RET_IF_ERROR(cond, ...) \ 147 | { \ 148 | if (cond) { \ 149 | close_combmask(ch, core, vsapi); \ 150 | snprintf(msg, 240, __VA_ARGS__); \ 151 | vsapi->setError(out, msg_buff); \ 152 | return; \ 153 | } \ 154 | } 155 | 156 | char msg_buff[256] = "CombMask: "; 157 | char *msg = msg_buff + strlen(msg_buff); 158 | 159 | combmask_t *ch = (combmask_t *)calloc(sizeof(combmask_t), 1); 160 | RET_IF_ERROR(!ch, "failed to allocate handler."); 161 | 162 | ch->node = vsapi->propGetNode(in, "clip", 0, 0); 163 | ch->vi = vsapi->getVideoInfo(ch->node); 164 | RET_IF_ERROR(ch->vi->width == 0 || ch->vi->height == 0 || !ch->vi->format, 165 | "clip is not constant resolution/format."); 166 | RET_IF_ERROR(ch->vi->format->sampleType != stInteger, 167 | "clip is not integer format."); 168 | 169 | RET_IF_ERROR(set_planes(ch->planes, in, vsapi), "planes index out of range"); 170 | 171 | int mag = 1 << (ch->vi->format->bitsPerSample - 8); 172 | int max = (1 << ch->vi->format->bitsPerSample) - 1; 173 | char err[256] = {0}; 174 | 175 | set_param_int(&ch->cthresh, "cthresh", 6 * mag, 0, max, in, vsapi, err); 176 | RET_IF_ERROR(err[0], "%s", err); 177 | 178 | set_param_int(&ch->mthresh, "mthresh", 9 * mag, 0, max, in, vsapi, err); 179 | RET_IF_ERROR(err[0], "%s", err); 180 | 181 | set_param_int(&ch->mi, "mi", 40, 0, 128, in, vsapi, err); 182 | RET_IF_ERROR(err[0], "%s", err); 183 | 184 | if (ch->vi->numFrames == 1) { 185 | ch->mthresh = 0; 186 | } 187 | 188 | int func_index = ch->vi->format->bytesPerSample - 1; 189 | if (ch->vi->format->bitsPerSample == 16) { 190 | func_index = 2; 191 | } 192 | 193 | ch->write_combmask = write_combmask_funcs[func_index]; 194 | ch->write_motionmask = write_motionmask_funcs[func_index]; 195 | ch->is_combed = is_combed_funcs[func_index]; 196 | ch->horizontal_dilation = h_dilation_funcs[func_index]; 197 | 198 | vsapi->createFilter(in, out, "CombMask", init_combmask, get_frame_combmask, 199 | close_combmask, fmParallel, 0, ch, core); 200 | 201 | #undef RET_IF_ERROR 202 | } 203 | 204 | 205 | 206 | static const VSFrameRef * VS_CC 207 | get_frame_maskedmerge(int n, int activation_reason, void **instance_data, 208 | void **frame_data, VSFrameContext *frame_ctx, 209 | VSCore *core, const VSAPI *vsapi) 210 | { 211 | maskedmerge_t *mh = (maskedmerge_t *)*instance_data; 212 | 213 | if (activation_reason == arInitial) { 214 | vsapi->requestFrameFilter(n, mh->base, frame_ctx); 215 | vsapi->requestFrameFilter(n, mh->altc, frame_ctx); 216 | vsapi->requestFrameFilter(n, mh->mask, frame_ctx); 217 | return NULL; 218 | } 219 | 220 | if (activation_reason != arAllFramesReady) { 221 | return NULL; 222 | } 223 | 224 | const VSFrameRef *base = vsapi->getFrameFilter(n, mh->base, frame_ctx); 225 | 226 | VSFrameRef *dst = vsapi->copyFrame(base, core); 227 | vsapi->freeFrame(base); 228 | 229 | const VSFrameRef *alt = vsapi->getFrameFilter(n, mh->altc, frame_ctx); 230 | const VSFrameRef *mask = vsapi->getFrameFilter(n, mh->mask, frame_ctx); 231 | 232 | merge_frames(mh, vsapi, mask, alt, dst); 233 | 234 | vsapi->freeFrame(alt); 235 | vsapi->freeFrame(mask); 236 | 237 | return dst; 238 | } 239 | 240 | 241 | static void VS_CC 242 | init_maskedmerge(VSMap *in, VSMap *out, void **instance_data, VSNode *node, 243 | VSCore *core, const VSAPI *vsapi) 244 | { 245 | maskedmerge_t *mh = (maskedmerge_t *)*instance_data; 246 | vsapi->setVideoInfo(mh->vi, 1, node); 247 | vsapi->clearMap(in); 248 | } 249 | 250 | 251 | static void VS_CC 252 | close_maskedmerge(void *instance_data, VSCore *core, const VSAPI *vsapi) 253 | { 254 | maskedmerge_t *mh = (maskedmerge_t *)instance_data; 255 | if (!mh) { 256 | return; 257 | } 258 | if (mh->base) { 259 | vsapi->freeNode(mh->base); 260 | mh->base = NULL; 261 | } 262 | if (mh->altc) { 263 | vsapi->freeNode(mh->altc); 264 | mh->altc = NULL; 265 | } 266 | if (mh->mask) { 267 | vsapi->freeNode(mh->mask); 268 | mh->mask = NULL; 269 | } 270 | free(mh); 271 | mh = NULL; 272 | } 273 | 274 | 275 | static void VS_CC 276 | is_valid_node(const VSVideoInfo *base, const VSVideoInfo *target, 277 | char *buff, const char *name) 278 | { 279 | if (base->width != target->width || base->height != target->height) { 280 | sprintf(buff, "base and %s are not the same resolution.", name); 281 | return; 282 | } 283 | if (base->format != target->format) { 284 | sprintf(buff, "base and %s are not the same format.", name); 285 | } 286 | } 287 | 288 | 289 | static void VS_CC 290 | create_maskedmerge(const VSMap *in, VSMap *out, void *user_data, VSCore *core, 291 | const VSAPI *vsapi) 292 | { 293 | #define RET_IF_ERROR(cond, ...) \ 294 | { \ 295 | if (cond) { \ 296 | close_maskedmerge(mh, core, vsapi); \ 297 | snprintf(msg, 240, __VA_ARGS__); \ 298 | vsapi->setError(out, msg_buff); \ 299 | return; \ 300 | } \ 301 | } 302 | 303 | char msg_buff[256] = "CMaskedMerge: "; 304 | char *msg = msg_buff + strlen(msg_buff); 305 | 306 | maskedmerge_t *mh = (maskedmerge_t *)calloc(sizeof(maskedmerge_t), 1); 307 | RET_IF_ERROR(!mh, "failed to allocate handler."); 308 | 309 | mh->base = vsapi->propGetNode(in, "base", 0, 0); 310 | mh->vi = vsapi->getVideoInfo(mh->base); 311 | RET_IF_ERROR(mh->vi->width == 0 || mh->vi->height == 0 || !mh->vi->format, 312 | "base is not constant resolution/format."); 313 | RET_IF_ERROR(mh->vi->format->sampleType != stInteger, 314 | "clip is not integer format."); 315 | 316 | char err[256] = {0}; 317 | 318 | mh->altc = vsapi->propGetNode(in, "alt", 0, 0); 319 | is_valid_node(mh->vi, vsapi->getVideoInfo(mh->altc), "alt", err); 320 | RET_IF_ERROR(err[0], "%s", err); 321 | 322 | mh->mask = vsapi->propGetNode(in, "mask", 0, 0); 323 | is_valid_node(mh->vi, vsapi->getVideoInfo(mh->mask), "mask", err); 324 | RET_IF_ERROR(err[0], "%s", err); 325 | 326 | RET_IF_ERROR(set_planes(mh->planes, in, vsapi), 327 | "planes index out of range"); 328 | 329 | vsapi->createFilter(in, out, "CMaskedMerge", init_maskedmerge, 330 | get_frame_maskedmerge, close_maskedmerge, fmParallel, 331 | 0, mh, core); 332 | 333 | #undef RET_IF_ERROR 334 | } 335 | 336 | 337 | VS_EXTERNAL_API(void) 338 | VapourSynthPluginInit(VSConfigPlugin conf, VSRegisterFunction reg, 339 | VSPlugin *plugin) 340 | { 341 | conf("chikuzen.does.not.have.his.own.domain.combmask", "comb", 342 | "comb filters v" 343 | COMBMASK_VERSION, VAPOURSYNTH_API_VERSION, 1, plugin); 344 | reg("CombMask", 345 | "clip:clip;cthresh:int:opt;mthresh:int:opt;mi:int:opt;planes:int[]:opt;", 346 | create_combmask, NULL, plugin); 347 | reg("CMaskedMerge", 348 | "base:clip;alt:clip;mask:clip;planes:int[]:opt;", create_maskedmerge, 349 | NULL, plugin); 350 | } -------------------------------------------------------------------------------- /vapoursynth/src/write_combmask.c: -------------------------------------------------------------------------------- 1 | /* 2 | write_combmask.c: Copyright (C) 2012-2013 Oka Motofumi 3 | 4 | Author: Oka Motofumi (chikuzen.mo at gmail dot com) 5 | 6 | This file is part of CombMask. 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU Lesser General Public 10 | License as published by the Free Software Foundation; either 11 | version 2.1 of the License, or (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | Lesser General Public License for more details. 17 | 18 | You should have received a copy of the GNU Lesser General Public 19 | License along with the author; if not, write to the Free Software 20 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 | */ 22 | 23 | 24 | #include 25 | #include 26 | #include 27 | #include "combmask.h" 28 | 29 | 30 | static void CM_FUNC_ALIGN VS_CC 31 | write_combmask_8bit(combmask_t *ch, const VSAPI *vsapi, const VSFrameRef *src, 32 | VSFrameRef *cmask) 33 | { 34 | __m128i xcth = _mm_set1_epi8((int8_t)ch->cthresh); 35 | __m128i xct6 = _mm_set1_epi16((int16_t)(ch->cthresh * 6)); 36 | __m128i zero = _mm_setzero_si128(); 37 | 38 | for (int p = 0; p < ch->vi->format->numPlanes; p++) { 39 | 40 | __m128i* dstp = (__m128i*)vsapi->getWritePtr(cmask, p); 41 | 42 | int height = vsapi->getFrameHeight(src, p); 43 | int stride = vsapi->getStride(src, p) / 16; 44 | 45 | if (ch->planes[p] == 0 || height < 3) { 46 | memset(dstp, 0, stride * height * 16); 47 | continue; 48 | } 49 | 50 | int width = (vsapi->getFrameWidth(src, p) + 15) / 16; 51 | 52 | const __m128i* srcpc = (__m128i*)vsapi->getReadPtr(src, p); 53 | const __m128i* srcpb = srcpc + stride; 54 | const __m128i* srcpa = srcpb + stride; 55 | const __m128i* srcpd = srcpc + stride; 56 | const __m128i* srcpe = srcpd + stride; 57 | 58 | for (int y = 0; y < height; y++) { 59 | for (int x = 0; x < width; x++) { 60 | __m128i xmm0 = _mm_load_si128(srcpc + x); 61 | __m128i xmm1 = _mm_load_si128(srcpb + x); 62 | __m128i xmm2 = _mm_load_si128(srcpd + x); 63 | 64 | __m128i xmm3 = _mm_subs_epu8(xmm0, _mm_max_epu8(xmm1, xmm2)); 65 | xmm3 = _mm_cmpeq_epi8(zero, _mm_subs_epu8(xmm3, xcth)); // !(d1 > cthresh && d2 > cthresh) 66 | 67 | __m128i xmm4 = _mm_subs_epu8(_mm_min_epu8(xmm1, xmm2), xmm0); 68 | xmm4 = _mm_cmpeq_epi8(zero, _mm_subs_epu8(xmm4, xcth)); // !(d1 < -cthresh && d2 < -cthresh) 69 | 70 | xmm3 = _mm_and_si128(xmm3, xmm4); 71 | 72 | xmm4 = _mm_add_epi16(_mm_unpacklo_epi8(xmm1, zero), 73 | _mm_unpacklo_epi8(xmm2, zero)); // lo of (b+d) 74 | xmm1 = _mm_add_epi16(_mm_unpackhi_epi8(xmm1, zero), 75 | _mm_unpackhi_epi8(xmm2, zero)); // hi of (b+d) 76 | xmm4 = _mm_add_epi16(xmm4, _mm_add_epi16(xmm4, xmm4)); // lo of 3*(b+d) 77 | xmm1 = _mm_add_epi16(xmm1, _mm_add_epi16(xmm1, xmm1)); // hi of 3*(b+d) 78 | 79 | xmm2 = _mm_load_si128(srcpa + x); 80 | __m128i xmm5 = _mm_add_epi16(_mm_slli_epi16(_mm_unpacklo_epi8(xmm0, zero), 2), 81 | _mm_unpacklo_epi8(xmm2, zero)); 82 | xmm2 = _mm_add_epi16(_mm_slli_epi16(_mm_unpackhi_epi8(xmm0, zero), 2), 83 | _mm_unpackhi_epi8(xmm2, zero)); 84 | 85 | xmm0 = _mm_load_si128(srcpe + x); 86 | xmm5 = _mm_add_epi16(xmm5, _mm_unpacklo_epi8(xmm0, zero)); 87 | xmm2 = _mm_add_epi16(xmm2, _mm_unpackhi_epi8(xmm0, zero)); 88 | 89 | xmm0 = _mm_max_epi16(xmm4, xmm5); 90 | xmm4 = _mm_min_epi16(xmm4, xmm5); 91 | xmm0 = _mm_sub_epi16(xmm0, xmm4); 92 | xmm0 = _mm_cmpgt_epi16(xmm0, xct6); 93 | 94 | xmm4 = _mm_max_epi16(xmm1, xmm2); 95 | xmm1 = _mm_min_epi16(xmm1, xmm2); 96 | xmm4 = _mm_sub_epi16(xmm4, xmm1); 97 | xmm4 = _mm_cmpgt_epi16(xmm4, xct6); 98 | 99 | xmm1 = _mm_packs_epi16(xmm0, xmm4); 100 | 101 | xmm3 = _mm_andnot_si128(xmm3, xmm1); 102 | 103 | _mm_store_si128(dstp + x, xmm3); 104 | } 105 | dstp += stride; 106 | srcpa = srcpb; 107 | srcpb = srcpc; 108 | srcpc = srcpd; 109 | srcpd = srcpe; 110 | srcpe = (y < height - 3) ? srcpe + stride : srcpe - stride; 111 | } 112 | } 113 | } 114 | 115 | 116 | static void CM_FUNC_ALIGN VS_CC 117 | write_combmask_9_10(combmask_t *ch, const VSAPI *vsapi, const VSFrameRef *src, 118 | VSFrameRef *cmask) 119 | { 120 | __m128i xcth = _mm_set1_epi16((int16_t)ch->cthresh); 121 | __m128i xct6p = _mm_set1_epi32((int16_t)(ch->cthresh * 6)); 122 | __m128i xct6n = _mm_set1_epi32((int16_t)(ch->cthresh * -6)); 123 | int shift = 16 - ch->vi->format->bitsPerSample; 124 | 125 | for (int p = 0; p < ch->vi->format->numPlanes; p++) { 126 | 127 | __m128i* dstp = (__m128i*)vsapi->getWritePtr(cmask, p); 128 | 129 | int height = vsapi->getFrameHeight(src, p); 130 | int stride = vsapi->getStride(cmask, p) / 16; 131 | 132 | if (ch->planes[p] == 0 || height < 3) { 133 | memset(dstp, 0, stride * height * 16); 134 | continue; 135 | } 136 | 137 | int width = (vsapi->getFrameWidth(src, p) + 7) / 8; 138 | 139 | const __m128i* srcpc = (__m128i*)vsapi->getReadPtr(src, p); 140 | const __m128i* srcpb = srcpc + stride; 141 | const __m128i* srcpa = srcpb + stride; 142 | const __m128i* srcpd = srcpc + stride; 143 | const __m128i* srcpe = srcpd + stride; 144 | 145 | for (int y = 0; y < height; y++) { 146 | for (int x = 0; x < width; x++) { 147 | __m128i xmm0 = _mm_load_si128(srcpc + x); 148 | __m128i xmm1 = _mm_load_si128(srcpb + x); 149 | __m128i xmm2 = _mm_load_si128(srcpd + x); 150 | 151 | __m128i xmm3 = _mm_cmpgt_epi16(_mm_sub_epi16(xmm0, xmm1), xcth); 152 | __m128i xmm4 = _mm_cmpgt_epi16(_mm_sub_epi16(xmm0, xmm2), xcth); 153 | xmm3 = _mm_and_si128(xmm3, xmm4); 154 | 155 | xmm4 = _mm_cmpgt_epi16(_mm_sub_epi16(xmm1, xmm0), xcth); 156 | __m128i xmm5 = _mm_cmpgt_epi16(_mm_sub_epi16(xmm2, xmm0), xcth); 157 | xmm4 = _mm_and_si128(xmm4, xmm5); 158 | 159 | xmm3 = _mm_and_si128(xmm3, xmm4); 160 | 161 | xmm1 = _mm_add_epi16(xmm1, xmm2); // b + d 162 | xmm1 = _mm_add_epi16(xmm1, _mm_add_epi16(xmm1, xmm1)); //3 * (b + d) 163 | xmm0 = _mm_slli_epi16(xmm0, 2); // 4 * c 164 | 165 | xmm2 = _mm_add_epi16(_mm_load_si128(srcpa + x), 166 | _mm_load_si128(srcpe + x)); // a + e 167 | xmm0 = _mm_add_epi16(xmm0, xmm2); // a + 4 * c + e 168 | xmm0 = _mm_sub_epi16(xmm0, xmm1); // a+4*c+e-3*(b+d) 169 | 170 | xmm1 = _mm_cmpgt_epi16(xmm0, xct6p); 171 | xmm0 = _mm_cmplt_epi16(xmm0, xct6n); 172 | 173 | xmm0 = _mm_or_si128(xmm0, xmm1); 174 | 175 | xmm0 = _mm_srli_epi16(_mm_and_si128(xmm0, xmm3), shift); 176 | 177 | _mm_store_si128(dstp + x, xmm0); 178 | } 179 | dstp += stride; 180 | srcpa = srcpb; 181 | srcpb = srcpc; 182 | srcpc = srcpd; 183 | srcpd = srcpe; 184 | srcpe = (y < height - 3) ? srcpe + stride : srcpe - stride; 185 | } 186 | } 187 | } 188 | 189 | 190 | static void CM_FUNC_ALIGN VS_CC 191 | write_combmask_16bit(combmask_t *ch, const VSAPI *vsapi, const VSFrameRef *src, 192 | VSFrameRef *cmask) 193 | { 194 | __m128i xcth = _mm_set1_epi16((int16_t)ch->cthresh); 195 | __m128i xct6p = _mm_set1_epi16((int16_t)(ch->cthresh * 6)); 196 | __m128i xct6n = _mm_set1_epi16((int16_t)(ch->cthresh * -6)); 197 | __m128i zero = _mm_setzero_si128(); 198 | 199 | for (int p = 0; p < ch->vi->format->numPlanes; p++) { 200 | 201 | __m128i* dstp = (__m128i*)vsapi->getWritePtr(cmask, p); 202 | 203 | int height = vsapi->getFrameHeight(src, p); 204 | int stride = vsapi->getStride(cmask, p) / 16; 205 | 206 | if (ch->planes[p] == 0 || height < 3) { 207 | memset(dstp, 0, stride * height * 16); 208 | continue; 209 | } 210 | 211 | int width = (vsapi->getFrameWidth(src, p) + 7) / 8; 212 | 213 | const __m128i* srcpc = (__m128i*)vsapi->getReadPtr(src, p); 214 | const __m128i* srcpb = srcpc + stride; 215 | const __m128i* srcpa = srcpb + stride; 216 | const __m128i* srcpd = srcpc + stride; 217 | const __m128i* srcpe = srcpd + stride; 218 | 219 | for (int y = 0; y < height; y++) { 220 | for (int x = 0; x < width; x++) { 221 | __m128i xmm0 = _mm_load_si128(srcpc + x); 222 | __m128i xmm1 = _mm_load_si128(srcpb + x); 223 | __m128i xmm2 = _mm_load_si128(srcpd + x); 224 | 225 | __m128i xmm3 = _mm_subs_epu16(xmm0, MM_MAX_EPU16(xmm1, xmm2)); 226 | xmm3 = _mm_cmpeq_epi16(zero, _mm_subs_epu16(xmm3, xcth)); // !(d1 > cthresh && d2 > cthresh) 227 | 228 | __m128i xmm4 = _mm_subs_epu16(MM_MIN_EPU16(xmm1, xmm2), xmm0); 229 | xmm4 = _mm_cmpeq_epi16(zero, _mm_subs_epu16(xmm4, xcth)); // !(d1 < -cthresh && d2 < -cthresh) 230 | 231 | xmm3 = _mm_and_si128(xmm3, xmm4); 232 | 233 | xmm4 = _mm_add_epi32(_mm_unpacklo_epi16(xmm1, zero), 234 | _mm_unpacklo_epi16(xmm2, zero)); // lo of (b+d) 235 | xmm1 = _mm_add_epi32(_mm_unpackhi_epi16(xmm1, zero), 236 | _mm_unpackhi_epi16(xmm2, zero)); // hi of (b+d) 237 | xmm4 = _mm_add_epi32(xmm4, _mm_add_epi32(xmm4, xmm4)); // lo of 3*(b+d) 238 | xmm1 = _mm_add_epi32(xmm1, _mm_add_epi32(xmm1, xmm1)); // hi of 3*(b+d) 239 | 240 | xmm4 = _mm_sub_epi32(_mm_slli_epi32(_mm_unpacklo_epi16(xmm0, zero), 2), xmm4); // lo of 4*c-3*(b+d) 241 | xmm1 = _mm_sub_epi32(_mm_slli_epi32(_mm_unpackhi_epi16(xmm0, zero), 2), xmm1); // hi of 4*c-3*(b+d) 242 | 243 | xmm0 = _mm_load_si128(srcpa + x); 244 | xmm4 = _mm_add_epi32(xmm4, _mm_unpacklo_epi16(xmm0, zero)); // lo of a+4*c-3*(b+d) 245 | xmm1 = _mm_add_epi32(xmm1, _mm_unpackhi_epi16(xmm0, zero)); // hi of a+4*c-3*(b+d) 246 | 247 | xmm0 = _mm_load_si128(srcpe + x); 248 | xmm4 = _mm_add_epi32(xmm4, _mm_unpacklo_epi16(xmm0, zero)); // lo of a+4*c+e-3*(b+d) 249 | xmm1 = _mm_add_epi32(xmm1, _mm_unpackhi_epi16(xmm0, zero)); // hi of a+4*c+e-3*(b+d) 250 | 251 | xmm4 = _mm_or_si128(_mm_cmpgt_epi32(xmm4, xct6p), 252 | _mm_cmplt_epi32(xmm4, xct6n)); 253 | xmm1 = _mm_or_si128(_mm_cmpgt_epi32(xmm1, xct6p), 254 | _mm_cmplt_epi32(xmm1, xct6n)); 255 | xmm1 = _mm_packs_epi32(xmm4, xmm1); 256 | 257 | xmm3 = _mm_andnot_si128(xmm3, xmm1); 258 | 259 | _mm_store_si128(dstp + x, xmm3); 260 | } 261 | dstp += stride; 262 | srcpa = srcpb; 263 | srcpb = srcpc; 264 | srcpc = srcpd; 265 | srcpd = srcpe; 266 | srcpe = (y < height - 3) ? srcpe + stride : srcpe - stride; 267 | } 268 | } 269 | 270 | } 271 | 272 | 273 | const func_write_combmask write_combmask_funcs[] = { 274 | write_combmask_8bit, 275 | write_combmask_9_10, 276 | write_combmask_16bit 277 | }; 278 | -------------------------------------------------------------------------------- /vapoursynth/src/VapourSynth.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 Fredrik Mellbin 3 | * 4 | * This file is part of VapourSynth. 5 | * 6 | * VapourSynth is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * VapourSynth is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with VapourSynth; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #ifndef VAPOURSYNTH_H 22 | #define VAPOURSYNTH_H 23 | 24 | #include 25 | 26 | #define VAPOURSYNTH_API_VERSION 3 27 | 28 | // Convenience for C++ users. 29 | #ifdef __cplusplus 30 | # define VS_EXTERN_C extern "C" 31 | #else 32 | # define VS_EXTERN_C 33 | #endif 34 | 35 | #ifdef _WIN32 36 | # define VS_CC __stdcall 37 | #else 38 | # define VS_CC 39 | #endif 40 | 41 | // And now for some symbol hide-and-seek... 42 | #if defined(_WIN32) // Windows being special 43 | # define VS_EXTERNAL_API(ret) VS_EXTERN_C __declspec(dllexport) ret VS_CC 44 | #elif defined(__GNUC__) && __GNUC__ >= 4 45 | # define VS_EXTERNAL_API(ret) VS_EXTERN_C __attribute__((visibility("default"))) ret VS_CC 46 | #else 47 | # define VS_EXTERNAL_API(ret) VS_EXTERN_C ret VS_CC 48 | #endif 49 | 50 | #if !defined(VS_CORE_EXPORTS) && defined(_WIN32) 51 | # define VS_API(ret) VS_EXTERN_C __declspec(dllimport) ret VS_CC 52 | #else 53 | # define VS_API(ret) VS_EXTERNAL_API(ret) 54 | #endif 55 | 56 | typedef struct VSFrameRef VSFrameRef; 57 | typedef struct VSNodeRef VSNodeRef; 58 | typedef struct VSCore VSCore; 59 | typedef struct VSPlugin VSPlugin; 60 | typedef struct VSNode VSNode; 61 | typedef struct VSFuncRef VSFuncRef; 62 | typedef struct VSMap VSMap; 63 | typedef struct VSAPI VSAPI; 64 | typedef struct VSFrameContext VSFrameContext; 65 | 66 | typedef enum VSColorFamily { 67 | // all planar formats 68 | cmGray = 1000000, 69 | cmRGB = 2000000, 70 | cmYUV = 3000000, 71 | cmYCoCg = 4000000, 72 | // special for compatibility 73 | cmCompat = 9000000 74 | } VSColorFamily; 75 | 76 | typedef enum VSSampleType { 77 | stInteger = 0, 78 | stFloat = 1 79 | } VSSampleType; 80 | 81 | // The +10 is so people won't be using the constants interchangably "by accident" 82 | typedef enum VSPresetFormat { 83 | pfNone = 0, 84 | 85 | pfGray8 = cmGray + 10, 86 | pfGray16, 87 | 88 | pfGrayH, 89 | pfGrayS, 90 | 91 | pfYUV420P8 = cmYUV + 10, 92 | pfYUV422P8, 93 | pfYUV444P8, 94 | pfYUV410P8, 95 | pfYUV411P8, 96 | pfYUV440P8, 97 | 98 | pfYUV420P9, 99 | pfYUV422P9, 100 | pfYUV444P9, 101 | 102 | pfYUV420P10, 103 | pfYUV422P10, 104 | pfYUV444P10, 105 | 106 | pfYUV420P16, 107 | pfYUV422P16, 108 | pfYUV444P16, 109 | 110 | pfYUV444PH, 111 | pfYUV444PS, 112 | 113 | pfRGB24 = cmRGB + 10, 114 | pfRGB27, 115 | pfRGB30, 116 | pfRGB48, 117 | 118 | pfRGBH, 119 | pfRGBS, 120 | 121 | // special for compatibility, if you implement these in any filter I'll personally kill you 122 | // I'll also change their ids around to break your stuff regularly 123 | pfCompatBGR32 = cmCompat + 10, 124 | pfCompatYUY2 125 | } VSPresetFormat; 126 | 127 | typedef enum VSFilterMode { 128 | fmParallel = 100, // completely parallel execution 129 | fmParallelRequests = 200, // for filters that are serial in nature but can request one or more frames they need in advance 130 | fmUnordered = 300, // for filters that modify their internal state every request 131 | fmSerial = 400 // for source filters and compatibility with other filtering architectures 132 | } VSFilterMode; 133 | 134 | typedef struct VSFormat { 135 | char name[32]; 136 | int id; 137 | int colorFamily; // see VSColorFamily 138 | int sampleType; // see VSSampleType 139 | int bitsPerSample; // number of significant bits 140 | int bytesPerSample; // actual storage is always in a power of 2 and the smallest possible that can fit the number of bits used per sample 141 | 142 | int subSamplingW; // log2 subsampling factor, applied to second and third plane 143 | int subSamplingH; 144 | 145 | int numPlanes; // implicit from colorFamily 146 | } VSFormat; 147 | 148 | typedef enum VSNodeFlags { 149 | nfNoCache = 1, 150 | } NodeFlags; 151 | 152 | typedef enum VSGetPropErrors { 153 | peUnset = 1, 154 | peType = 2, 155 | peIndex = 4 156 | } GetPropErrors; 157 | 158 | typedef enum VSPropAppendMode { 159 | paReplace = 0, 160 | paAppend = 1, 161 | paTouch = 2 162 | } PropAppendMode; 163 | 164 | typedef struct VSCoreInfo { 165 | const char *versionString; 166 | int core; 167 | int api; 168 | int numThreads; 169 | int64_t maxFramebufferSize; 170 | int64_t usedFramebufferSize; 171 | } VSCoreInfo; 172 | 173 | typedef struct VSVideoInfo { 174 | const VSFormat *format; 175 | int64_t fpsNum; 176 | int64_t fpsDen; 177 | int width; 178 | int height; 179 | int numFrames; 180 | int flags; 181 | } VSVideoInfo; 182 | 183 | typedef enum VSActivationReason { 184 | arInitial = 0, 185 | arFrameReady = 1, 186 | arAllFramesReady = 2, 187 | arError = -1 188 | } ActivationReason; 189 | 190 | typedef enum VSMessageType { 191 | mtDebug = 0, 192 | mtWarnin = 1, 193 | mtCritical = 2, 194 | mtFatal 195 | } VSMessageType; 196 | 197 | // core function typedefs 198 | typedef VSCore *(VS_CC *VSCreateCore)(int threads); 199 | typedef void (VS_CC *VSFreeCore)(VSCore *core); 200 | typedef const VSCoreInfo *(VS_CC *VSGetCoreInfo)(VSCore *core); 201 | 202 | // function/filter typedefs 203 | typedef void (VS_CC *VSPublicFunction)(const VSMap *in, VSMap *out, void *userData, VSCore *core, const VSAPI *vsapi); 204 | typedef void (VS_CC *VSFreeFuncData)(void *userData); 205 | typedef void (VS_CC *VSFilterInit)(VSMap *in, VSMap *out, void **instanceData, VSNode *node, VSCore *core, const VSAPI *vsapi); 206 | typedef const VSFrameRef *(VS_CC *VSFilterGetFrame)(int n, int activationReason, void **instanceData, void **frameData, VSFrameContext *frameCtx, VSCore *core, const VSAPI *vsapi); 207 | typedef int (VS_CC *VSGetOutputIndex)(VSFrameContext *frameCtx); 208 | typedef void (VS_CC *VSFilterFree)(void *instanceData, VSCore *core, const VSAPI *vsapi); 209 | typedef void (VS_CC *VSRegisterFunction)(const char *name, const char *args, VSPublicFunction argsFunc, void *functionData, VSPlugin *plugin); 210 | typedef void (VS_CC *VSCreateFilter)(const VSMap *in, VSMap *out, const char *name, VSFilterInit init, VSFilterGetFrame getFrame, VSFilterFree free, int filterMode, int flags, void *instanceData, VSCore *core); 211 | typedef VSMap *(VS_CC *VSInvoke)(VSPlugin *plugin, const char *name, const VSMap *args); 212 | typedef void (VS_CC *VSSetError)(VSMap *map, const char *errorMessage); 213 | typedef const char *(VS_CC *VSGetError)(const VSMap *map); 214 | typedef void (VS_CC *VSSetFilterError)(const char *errorMessage, VSFrameContext *frameCtx); 215 | 216 | typedef const VSFormat *(VS_CC *VSGetFormatPreset)(int id, VSCore *core); 217 | typedef const VSFormat *(VS_CC *VSRegisterFormat)(int colorFamily, int sampleType, int bitsPerSample, int subSamplingW, int subSamplingH, VSCore *core); 218 | 219 | // frame and clip handling 220 | typedef void (VS_CC *VSFrameDoneCallback)(void *userData, const VSFrameRef *f, int n, VSNodeRef *, const char *errorMsg); 221 | typedef void (VS_CC *VSGetFrameAsync)(int n, VSNodeRef *node, VSFrameDoneCallback callback, void *userData); 222 | typedef const VSFrameRef *(VS_CC *VSGetFrame)(int n, VSNodeRef *node, char *errorMsg, int bufSize); 223 | typedef void (VS_CC *VSRequestFrameFilter)(int n, VSNodeRef *node, VSFrameContext *frameCtx); 224 | typedef const VSFrameRef *(VS_CC *VSGetFrameFilter)(int n, VSNodeRef *node, VSFrameContext *frameCtx); 225 | typedef const VSFrameRef *(VS_CC *VSCloneFrameRef)(const VSFrameRef *f); 226 | typedef VSNodeRef *(VS_CC *VSCloneNodeRef)(VSNodeRef *node); 227 | typedef VSFuncRef *(VS_CC *VSCloneFuncRef)(VSFuncRef *f); 228 | typedef void (VS_CC *VSFreeFrame)(const VSFrameRef *f); 229 | typedef void (VS_CC *VSFreeNode)(VSNodeRef *node); 230 | typedef void (VS_CC *VSFreeFunc)(VSFuncRef *f); 231 | typedef VSFrameRef *(VS_CC *VSNewVideoFrame)(const VSFormat *format, int width, int height, const VSFrameRef *propSrc, VSCore *core); 232 | typedef VSFrameRef *(VS_CC *VSNewVideoFrame2)(const VSFormat *format, int width, int height, const VSFrameRef **planeSrc, const int *planes, const VSFrameRef *propSrc, VSCore *core); 233 | typedef VSFrameRef *(VS_CC *VSCopyFrame)(const VSFrameRef *f, VSCore *core); 234 | typedef void (VS_CC *VSCopyFrameProps)(const VSFrameRef *src, VSFrameRef *dst, VSCore *core); 235 | typedef int (VS_CC *VSGetStride)(const VSFrameRef *f, int plane); 236 | typedef const uint8_t *(VS_CC *VSGetReadPtr)(const VSFrameRef *f, int plane); 237 | typedef uint8_t *(VS_CC *VSGetWritePtr)(VSFrameRef *f, int plane); 238 | 239 | // property access 240 | typedef const VSVideoInfo *(VS_CC *VSGetVideoInfo)(VSNodeRef *node); 241 | typedef void (VS_CC *VSSetVideoInfo)(const VSVideoInfo *vi, int numOutputs, VSNode *node); 242 | typedef const VSFormat *(VS_CC *VSGetFrameFormat)(const VSFrameRef *f); 243 | typedef int (VS_CC *VSGetFrameWidth)(const VSFrameRef *f, int plane); 244 | typedef int (VS_CC *VSGetFrameHeight)(const VSFrameRef *f, int plane); 245 | typedef const VSMap *(VS_CC *VSGetFramePropsRO)(const VSFrameRef *f); 246 | typedef VSMap *(VS_CC *VSGetFramePropsRW)(VSFrameRef *f); 247 | typedef int (VS_CC *VSPropNumKeys)(const VSMap *map); 248 | typedef const char *(VS_CC *VSPropGetKey)(const VSMap *map, int index); 249 | typedef int (VS_CC *VSPropNumElements)(const VSMap *map, const char *key); 250 | typedef char(VS_CC *VSPropGetType)(const VSMap *map, const char *key); 251 | 252 | typedef VSMap *(VS_CC *VSCreateMap)(void); 253 | typedef void (VS_CC *VSFreeMap)(VSMap *map); 254 | typedef void (VS_CC *VSClearMap)(VSMap *map); 255 | 256 | typedef int64_t (VS_CC *VSPropGetInt)(const VSMap *map, const char *key, int index, int *error); 257 | typedef double(VS_CC *VSPropGetFloat)(const VSMap *map, const char *key, int index, int *error); 258 | typedef const char *(VS_CC *VSPropGetData)(const VSMap *map, const char *key, int index, int *error); 259 | typedef int (VS_CC *VSPropGetDataSize)(const VSMap *map, const char *key, int index, int *error); 260 | typedef VSNodeRef *(VS_CC *VSPropGetNode)(const VSMap *map, const char *key, int index, int *error); 261 | typedef const VSFrameRef *(VS_CC *VSPropGetFrame)(const VSMap *map, const char *key, int index, int *error); 262 | typedef VSFuncRef *(VS_CC *VSPropGetFunc)(const VSMap *map, const char *key, int index, int *error); 263 | 264 | typedef int (VS_CC *VSPropDeleteKey)(VSMap *map, const char *key); 265 | typedef int (VS_CC *VSPropSetInt)(VSMap *map, const char *key, int64_t i, int append); 266 | typedef int (VS_CC *VSPropSetFloat)(VSMap *map, const char *key, double d, int append); 267 | typedef int (VS_CC *VSPropSetData)(VSMap *map, const char *key, const char *data, int size, int append); 268 | typedef int (VS_CC *VSPropSetNode)(VSMap *map, const char *key, VSNodeRef *node, int append); 269 | typedef int (VS_CC *VSPropSetFrame)(VSMap *map, const char *key, const VSFrameRef *f, int append); 270 | typedef int (VS_CC *VSPropSetFunc)(VSMap *map, const char *key, VSFuncRef *func, int append); 271 | 272 | // mixed 273 | 274 | typedef void (VS_CC *VSConfigPlugin)(const char *identifier, const char *defaultNamespace, const char *name, int apiVersion, int readonly, VSPlugin *plugin); 275 | typedef void (VS_CC *VSInitPlugin)(VSConfigPlugin configFunc, VSRegisterFunction registerFunc, VSPlugin *plugin); 276 | 277 | typedef VSPlugin *(VS_CC *VSGetPluginId)(const char *identifier, VSCore *core); 278 | typedef VSPlugin *(VS_CC *VSGetPluginNs)(const char *ns, VSCore *core); 279 | 280 | typedef VSMap *(VS_CC *VSGetPlugins)(VSCore *core); 281 | typedef VSMap *(VS_CC *VSGetFunctions)(VSPlugin *plugin); 282 | 283 | typedef void (VS_CC *VSCallFunc)(VSFuncRef *func, const VSMap *in, VSMap *out, VSCore *core, const VSAPI *vsapi); 284 | typedef VSFuncRef *(VS_CC *VSCreateFunc)(VSPublicFunction func, void *userData, VSFreeFuncData free); 285 | 286 | typedef void (VS_CC *VSQueryCompletedFrame)(VSNodeRef **node, int *n, VSFrameContext *frameCtx); 287 | typedef void (VS_CC *VSReleaseFrameEarly)(VSNodeRef *node, int n, VSFrameContext *frameCtx); 288 | 289 | typedef int64_t (VS_CC *VSSetMaxCacheSize)(int64_t bytes, VSCore *core); 290 | 291 | typedef void (VS_CC *VSMessageHandler)(int msgType, const char *msg); 292 | typedef void (VS_CC *VSSetMessageHandler)(VSMessageHandler handler); 293 | 294 | struct VSAPI { 295 | VSCreateCore createCore; 296 | VSFreeCore freeCore; 297 | VSGetCoreInfo getCoreInfo; 298 | 299 | VSCloneFrameRef cloneFrameRef; 300 | VSCloneNodeRef cloneNodeRef; 301 | VSCloneFuncRef cloneFuncRef; 302 | 303 | VSFreeFrame freeFrame; 304 | VSFreeNode freeNode; 305 | VSFreeFunc freeFunc; 306 | 307 | VSNewVideoFrame newVideoFrame; 308 | VSCopyFrame copyFrame; 309 | VSCopyFrameProps copyFrameProps; 310 | 311 | VSRegisterFunction registerFunction; 312 | VSGetPluginId getPluginId; 313 | VSGetPluginNs getPluginNs; 314 | VSGetPlugins getPlugins; 315 | VSGetFunctions getFunctions; 316 | VSCreateFilter createFilter; // do never use inside a filter's getframe function 317 | VSSetError setError; // use to signal errors outside filter getframe functions 318 | VSGetError getError; // use to query errors, returns 0 if no error 319 | VSSetFilterError setFilterError; // use to signal errors in the filter getframe function 320 | VSInvoke invoke; // may not be used inside a filter's getframe method 321 | 322 | VSGetFormatPreset getFormatPreset; //threadsafe 323 | VSRegisterFormat registerFormat; // threadsafe 324 | 325 | VSGetFrame getFrame; // do never use inside a filter's getframe function, for external applications using the core as a library or for requesting frames in a filter constructor 326 | VSGetFrameAsync getFrameAsync; // do never use inside a filter's getframe function, for external applications using the core as a library or for requesting frames in a filter constructor 327 | VSGetFrameFilter getFrameFilter; // only use inside a filter's getframe function 328 | VSRequestFrameFilter requestFrameFilter; // only use inside a filter's getframe function 329 | VSQueryCompletedFrame queryCompletedFrame; // only use inside a filter's getframe function 330 | VSReleaseFrameEarly releaseFrameEarly; // only use inside a filter's getframe function 331 | 332 | VSGetStride getStride; 333 | VSGetReadPtr getReadPtr; 334 | VSGetWritePtr getWritePtr; 335 | 336 | VSCreateFunc createFunc; 337 | VSCallFunc callFunc; 338 | 339 | //property access functions 340 | VSCreateMap createMap; 341 | VSFreeMap freeMap; 342 | VSClearMap clearMap; 343 | 344 | VSGetVideoInfo getVideoInfo; 345 | VSSetVideoInfo setVideoInfo; 346 | VSGetFrameFormat getFrameFormat; 347 | VSGetFrameWidth getFrameWidth; 348 | VSGetFrameHeight getFrameHeight; 349 | VSGetFramePropsRO getFramePropsRO; 350 | VSGetFramePropsRW getFramePropsRW; 351 | 352 | VSPropNumKeys propNumKeys; 353 | VSPropGetKey propGetKey; 354 | VSPropNumElements propNumElements; 355 | VSPropGetType propGetType; 356 | VSPropGetInt propGetInt; 357 | VSPropGetFloat propGetFloat; 358 | VSPropGetData propGetData; 359 | VSPropGetDataSize propGetDataSize; 360 | VSPropGetNode propGetNode; 361 | VSPropGetFrame propGetFrame; 362 | VSPropGetFunc propGetFunc; 363 | 364 | VSPropDeleteKey propDeleteKey; 365 | VSPropSetInt propSetInt; 366 | VSPropSetFloat propSetFloat; 367 | VSPropSetData propSetData; 368 | VSPropSetNode propSetNode; 369 | VSPropSetFrame propSetFrame; 370 | VSPropSetFunc propSetFunc; 371 | 372 | VSSetMaxCacheSize setMaxCacheSize; 373 | VSGetOutputIndex getOutputIndex; 374 | VSNewVideoFrame2 newVideoFrame2; 375 | 376 | VSSetMessageHandler setMessageHandler; 377 | }; 378 | 379 | VS_API(const VSAPI *) getVapourSynthAPI(int version); 380 | 381 | #endif // VAPOURSYNTH_H 382 | -------------------------------------------------------------------------------- /avisynth/src/CombMask.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | CombMask for AviSynth2.6x 3 | 4 | Copyright (C) 2013 Oka Motofumi 5 | 6 | Authors: Oka Motofumi (chikuzen.mo at gmail dot com) 7 | 8 | This program is free software; you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation; either version 2 of the License, or 11 | (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software 20 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA. 21 | */ 22 | 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include "CombMask.h" 29 | #include "simd.h" 30 | 31 | 32 | 33 | static __forceinline int absdiff(int x, int y) noexcept 34 | { 35 | return x > y ? x - y : y - x; 36 | } 37 | 38 | /* 39 | How to detect combs (quoted from TFM - README.txt written by tritical) 40 | 41 | Assume 5 neighboring pixels (a,b,c,d,e) positioned vertically. 42 | 43 | a 44 | b 45 | c 46 | d 47 | e 48 | 49 | metric 0: 50 | 51 | d1 = c - b; 52 | d2 = c - d; 53 | if ((d1 > cthresh && d2 > cthresh) || (d1 < -cthresh && d2 < -cthresh)) { 54 | if (abs(a + 4*c + e - 3*(b + d)) > cthresh*6) it's combed; 55 | } 56 | 57 | metric 1: 58 | 59 | val = (b - c) * (d - c); 60 | if (val > cthresh * cthresh) it's combed; 61 | */ 62 | 63 | 64 | static void __stdcall 65 | comb_mask_0_c(uint8_t* dstp, const uint8_t* srcp, const int dpitch, 66 | const int spitch, const int cthresh, const int width, 67 | const int height) noexcept 68 | { 69 | const uint8_t* sc = srcp; 70 | const uint8_t* sb = sc + spitch; 71 | const uint8_t* sa = sb + spitch; 72 | const uint8_t* sd = sc + spitch; 73 | const uint8_t* se = sd + spitch; 74 | 75 | const int cth6 = cthresh * 6; 76 | 77 | for (int y = 0; y < height; ++y) { 78 | for (int x = 0; x < width; ++x) { 79 | dstp[x] = 0; 80 | int d1 = sc[x] - sb[x]; 81 | int d2 = sc[x] - sd[x]; 82 | if ((d1 > cthresh && d2 > cthresh) 83 | || (d1 < -cthresh && d2 < -cthresh)) { 84 | int f0 = sa[x] + 4 * sc[x] + se[x]; 85 | int f1 = 3 * (sb[x] + sd[x]); 86 | if (absdiff(f0, f1) > cth6) { 87 | dstp[x] = 0xFF; 88 | } 89 | } 90 | } 91 | sa = sb; 92 | sb = sc; 93 | sc = sd; 94 | sd = se; 95 | se += (y < height - 3) ? spitch : -spitch; 96 | dstp += dpitch; 97 | } 98 | } 99 | 100 | 101 | static void __stdcall 102 | comb_mask_1_c(uint8_t* dstp, const uint8_t* srcp, const int dpitch, 103 | const int spitch, const int cthresh, const int width, 104 | const int height) noexcept 105 | { 106 | const uint8_t* sc = srcp; 107 | const uint8_t* sb = sc + spitch; 108 | const uint8_t* sd = sc + spitch; 109 | 110 | for (int y = 0; y < height; ++y) { 111 | for (int x = 0; x < width; ++x) { 112 | int val = (sb[x] - sc[x]) * (sd[x] - sc[x]); 113 | dstp[x] = val > cthresh ? 0xFF : 0; 114 | } 115 | sb = sc; 116 | sc = sd; 117 | sd += (y < height - 2) ? spitch : -spitch; 118 | dstp += dpitch; 119 | } 120 | } 121 | 122 | 123 | template 124 | static void __stdcall 125 | comb_mask_0_simd(uint8_t* dstp, const uint8_t* srcp, const int dpitch, 126 | const int spitch, const int cthresh, const int width, 127 | const int height) noexcept 128 | { 129 | const uint8_t* sc = srcp; 130 | const uint8_t* sb = sc + spitch; 131 | const uint8_t* sa = sb + spitch; 132 | const uint8_t* sd = sc + spitch; 133 | const uint8_t* se = sd + spitch; 134 | 135 | int16_t cth16 = static_cast(cthresh); 136 | const V cthp = set1_i16(cth16); 137 | const V cthn = set1_i16(-cth16); 138 | const V cth6 = set1_i16(cth16 * 6); 139 | 140 | constexpr int step = sizeof(V) / 2; 141 | 142 | for (int y = 0; y < height; ++y) { 143 | for (int x = 0; x < width; x += step) { 144 | V xc = load_half(sc + x); 145 | V xb = load_half(sb + x); 146 | V xd = load_half(sd + x); 147 | V d1 = sub_i16(xc, xb); 148 | V d2 = sub_i16(xc, xd); 149 | V mask0 = or_reg( 150 | and_reg(cmpgt_i16(d1, cthp), cmpgt_i16(d2, cthp)), 151 | and_reg(cmpgt_i16(cthn, d1), cmpgt_i16(cthn, d2))); 152 | d2 = mul3(add_i16(xb, xd)); 153 | d1 = add_i16(load_half(sa + x), load_half(se + x)); 154 | d1 = add_i16(d1, lshift_i16(xc, 2)); 155 | mask0 = and_reg(mask0, cmpgt_i16(absdiff_i16(d1, d2), cth6)); 156 | store_half(dstp + x, mask0); 157 | } 158 | sa = sb; 159 | sb = sc; 160 | sc = sd; 161 | sd = se; 162 | se += (y < height - 3) ? spitch : -spitch; 163 | dstp += dpitch; 164 | } 165 | } 166 | 167 | 168 | template 169 | static void __stdcall 170 | comb_mask_1_simd(uint8_t* dstp, const uint8_t* srcp, const int dpitch, 171 | const int spitch, const int cthresh, const int width, 172 | const int height) noexcept 173 | { 174 | const uint8_t* sc = srcp; 175 | const uint8_t* sb = sc + spitch; 176 | const uint8_t* sd = sc + spitch; 177 | 178 | const V cth = set1_i16(static_cast(cthresh)); 179 | const V all = cmpeq_i8(cth, cth); 180 | 181 | constexpr int step = sizeof(V) / 2; 182 | 183 | for (int y = 0; y < height; ++y) { 184 | for (int x = 0; x < width; x += step) { 185 | V xb = load_half(sb + x); 186 | V xc = load_half(sc + x); 187 | V xd = load_half(sd + x); 188 | xb = sub_i16(xb, xc); 189 | xd = sub_i16(xd, xc); 190 | xc = andnot(mulhi(xb, xd), mullo(xb, xd)); 191 | xc = cmpgt_u16(xc, cth, all); 192 | store_half(dstp + x, xc); 193 | } 194 | sb = sc; 195 | sc = sd; 196 | sd += (y < height - 2) ? spitch : -spitch; 197 | dstp += dpitch; 198 | } 199 | } 200 | 201 | 202 | static void __stdcall 203 | motion_mask_c(uint8_t* tmpp, uint8_t* dstp, const uint8_t* srcp, 204 | const uint8_t* prevp, const int tpitch, const int dpitch, 205 | const int spitch, const int ppitch, const int mthresh, 206 | const int width, const int height) noexcept 207 | { 208 | uint8_t* tx = tmpp; 209 | for (int y = 0; y < height; ++y) { 210 | for (int x = 0; x < width; ++x) { 211 | tx[x] = absdiff(srcp[x], prevp[x]) > mthresh ? 0xFF : 0; 212 | } 213 | tx += tpitch; 214 | srcp += spitch; 215 | prevp += ppitch; 216 | } 217 | 218 | const uint8_t* t0 = tmpp; 219 | const uint8_t *t1 = tmpp; 220 | const uint8_t *t2 = tmpp + tpitch; 221 | 222 | for (int y = 0; y < height; ++y) { 223 | for (int x = 0; x < width; ++x) { 224 | dstp[x] = (t0[x] | t1[x] | t2[x]); 225 | } 226 | t0 = t1; 227 | t1 = t2; 228 | if (y < height - 2) { 229 | t2 += tpitch; 230 | } 231 | dstp += dpitch; 232 | } 233 | } 234 | 235 | 236 | template 237 | static void __stdcall 238 | motion_mask_simd(uint8_t* tmpp, uint8_t* dstp, const uint8_t* srcp, 239 | const uint8_t* prevp, const int tpitch, const int dpitch, 240 | const int spitch, const int ppitch, const int mthresh, 241 | const int width, const int height) noexcept 242 | { 243 | uint8_t* tx = tmpp; 244 | const V mth = set1_i8(static_cast(mthresh)); 245 | const V all = cmpeq_i8(mth, mth); 246 | 247 | for (int y = 0; y < height; ++y) { 248 | for (int x = 0; x < width; x += sizeof(V)) { 249 | V diff = absdiff_u8(load(srcp + x), load(prevp + x)); 250 | V dst = cmpgt_u8(diff, mth, all); 251 | store(tx + x, dst); 252 | } 253 | tx += tpitch; 254 | srcp += spitch; 255 | prevp += ppitch; 256 | } 257 | 258 | const uint8_t* t0 = tmpp; 259 | const uint8_t* t1 = tmpp; 260 | const uint8_t* t2 = tmpp + tpitch; 261 | 262 | for (int y = 0; y < height; ++y) { 263 | for (int x = 0; x < width; x += sizeof(V)) { 264 | V dst = or_reg(load(t0 + x), load(t1 + x)); 265 | dst = or_reg(dst, load(t2 + x)); 266 | store(dstp + x, dst); 267 | } 268 | t0 = t1; 269 | t1 = t2; 270 | if (y < height - 2) { 271 | t2 += tpitch; 272 | } 273 | dstp += dpitch; 274 | } 275 | } 276 | 277 | 278 | static void __stdcall 279 | and_masks_c(uint8_t* dstp, const uint8_t* altp, const int dpitch, 280 | const int apitch, const int width, const int height) noexcept 281 | { 282 | for (int y = 0; y < height; ++y) { 283 | for (int x = 0; x < width; ++x) { 284 | dstp[x] &= altp[x]; 285 | } 286 | dstp += dpitch; 287 | altp += apitch; 288 | } 289 | } 290 | 291 | 292 | template 293 | static void __stdcall 294 | and_masks_simd(uint8_t* dstp, const uint8_t* altp, const int dpitch, 295 | const int apitch, const int width, const int height) noexcept 296 | { 297 | for (int y = 0; y < height; ++y) { 298 | for (int x = 0; x < width; x += sizeof(V)) { 299 | V d = load(dstp + x); 300 | V a = load(altp + x); 301 | store(dstp + x, and_reg(d, a)); 302 | } 303 | dstp += dpitch; 304 | altp += apitch; 305 | } 306 | } 307 | 308 | 309 | static void __stdcall 310 | expand_mask_c(uint8_t* dstp, uint8_t* srcp, const int dpitch, const int spitch, 311 | const int width, const int height) noexcept 312 | { 313 | for (int y = 0; y < height; ++y) { 314 | srcp[-1] = srcp[0]; 315 | srcp[width] = srcp[width - 1]; 316 | for (int x = 0; x < width; ++x) { 317 | dstp[x] = (srcp[x - 1] | srcp[x] | srcp[x + 1]); 318 | } 319 | srcp += spitch; 320 | dstp += dpitch; 321 | } 322 | } 323 | 324 | 325 | template 326 | static void __stdcall 327 | expand_mask_simd(uint8_t* dstp, uint8_t* srcp, const int dpitch, 328 | const int spitch, const int width, const int height) noexcept 329 | { 330 | for (int y = 0; y < height; ++y) { 331 | srcp[-1] = srcp[0]; 332 | srcp[width] = srcp[width - 1]; 333 | for (int x = 0; x < width; x += sizeof(V)) { 334 | V s0 = loadu(srcp + x - 1); 335 | V s1 = load(srcp + x); 336 | V s2 = loadu(srcp + x + 1); 337 | stream(dstp + x, or_reg(or_reg(s0, s1), s2)); 338 | } 339 | srcp += spitch; 340 | dstp += dpitch; 341 | } 342 | } 343 | 344 | 345 | Buffer::Buffer(size_t pitch, int height, int hsize, size_t align, bool ip, 346 | ise_t* e) : 347 | env(e), isPlus(ip) 348 | { 349 | size_t size = pitch * height * hsize + align; 350 | orig = alloc_buffer(size, align, isPlus, env); 351 | buffp = reinterpret_cast(orig) + align; 352 | } 353 | 354 | 355 | Buffer::~Buffer() 356 | { 357 | free_buffer(orig, isPlus, env); 358 | } 359 | 360 | 361 | 362 | CombMask::CombMask(PClip c, int cth, int mth, bool ch, arch_t arch, bool e, 363 | int metric, bool plus) : 364 | GVFmod(c, ch, arch, plus), cthresh(cth), mthresh(mth), expand(e), 365 | buff(nullptr) 366 | { 367 | validate(!vi.IsPlanar(), "planar format only."); 368 | validate(metric != 0 && metric != 1, "metric must be set to 0 or 1."); 369 | if (metric == 0) { 370 | validate(cthresh < 0 || cthresh > 255, 371 | "cthresh must be between 0 and 255 on metric 0."); 372 | } else { 373 | validate(cthresh < 0 || cthresh > 65025, 374 | "cthresh must be between 0 and 65025 on metric 1."); 375 | } 376 | validate(mthresh < 0 || mthresh > 255, "mthresh must be between 0 and 255."); 377 | 378 | 379 | buffPitch = vi.width + align - 1; 380 | if (expand) { 381 | buffPitch += 2; 382 | } 383 | buffPitch &= (~(align - 1)); 384 | needBuff = mthresh > 0 || expand; 385 | 386 | switch (arch) { 387 | #if defined(__AVX2__) 388 | case USE_AVX2: 389 | writeCombMask = metric == 0 ? comb_mask_0_simd<__m256i> 390 | : comb_mask_1_simd<__m256i>; 391 | writeMotionMask = motion_mask_simd<__m256i>; 392 | andMasks = and_masks_simd<__m256i>; 393 | expandMask = expand_mask_simd<__m256i>; 394 | break; 395 | #endif 396 | case USE_SSE2: 397 | writeCombMask = metric == 0 ? comb_mask_0_simd<__m128i> 398 | : comb_mask_1_simd<__m128i>; 399 | writeMotionMask = motion_mask_simd<__m128i>; 400 | andMasks = and_masks_simd<__m128i>; 401 | expandMask = expand_mask_simd<__m128i>; 402 | break; 403 | default: 404 | writeCombMask = metric == 0 ? comb_mask_0_c : comb_mask_1_c; 405 | writeMotionMask = motion_mask_c; 406 | andMasks = and_masks_c; 407 | expandMask = expand_mask_c; 408 | } 409 | 410 | if (mthresh > 0 && child->SetCacheHints(CACHE_GET_WINDOW, 0) < 3) { 411 | child->SetCacheHints(CACHE_WINDOW, 3); 412 | } 413 | 414 | if (!isPlus && needBuff) { 415 | buff = new Buffer(buffPitch, vi.height, mthresh > 0 ? 2 : 1, align, 416 | false, nullptr); 417 | 418 | } 419 | } 420 | 421 | 422 | CombMask::~CombMask() 423 | { 424 | if (!isPlus && needBuff) { 425 | delete buff; 426 | } 427 | } 428 | 429 | 430 | PVideoFrame __stdcall CombMask::GetFrame(int n, ise_t* env) 431 | { 432 | static const int planes[] = { PLANAR_Y, PLANAR_U, PLANAR_V }; 433 | 434 | PVideoFrame src = child->GetFrame(n, env); 435 | 436 | PVideoFrame prev = mthresh == 0 ? PVideoFrame() 437 | : child->GetFrame(std::max(n - 1, 0), env); 438 | 439 | PVideoFrame dst = env->NewVideoFrame(vi, align); 440 | 441 | Buffer* b = buff; 442 | uint8_t *buffp, *tmpp; 443 | if (needBuff) { 444 | if (isPlus) { 445 | b = new Buffer(buffPitch, vi.height, mthresh > 0 ? 2 : 1, align, 446 | isPlus, env); 447 | } 448 | buffp = b->buffp; 449 | tmpp = buffp + vi.height * buffPitch; 450 | } 451 | 452 | for (int p = 0; p < numPlanes; ++p) { 453 | const int plane = planes[p]; 454 | 455 | const uint8_t* srcp = src->GetReadPtr(plane); 456 | uint8_t* dstp = dst->GetWritePtr(plane); 457 | const int spitch = src->GetPitch(plane); 458 | const int dpitch = dst->GetPitch(plane); 459 | const int width = src->GetRowSize(plane); 460 | const int height = src->GetHeight(plane); 461 | 462 | if (!needBuff) { 463 | writeCombMask(dstp, srcp, dpitch, spitch, cthresh, width, height); 464 | continue; 465 | } 466 | 467 | writeCombMask(buffp, srcp, buffPitch, spitch, cthresh, width, height); 468 | 469 | if (mthresh == 0) { 470 | expandMask(dstp, buffp, dpitch, buffPitch, width, height); 471 | continue; 472 | } 473 | 474 | writeMotionMask(tmpp, dstp, srcp, prev->GetReadPtr(plane), buffPitch, 475 | dpitch, spitch, prev->GetPitch(plane), mthresh, width, 476 | height); 477 | 478 | if (!expand) { 479 | andMasks(dstp, buffp, dpitch, buffPitch, width, height); 480 | continue; 481 | } 482 | 483 | andMasks(buffp, dstp, buffPitch, dpitch, width, height); 484 | 485 | expandMask(dstp, buffp, dpitch, buffPitch, width, height); 486 | } 487 | 488 | if (isPlus && needBuff) { 489 | delete b; 490 | } 491 | 492 | return dst; 493 | } 494 | 495 | -------------------------------------------------------------------------------- /avisynth/LICENSE.GPLv2: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /vapoursynth/LICENSE.LGPLv2.1: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 2.1, February 1999 3 | 4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | [This is the first released version of the Lesser GPL. It also counts 10 | as the successor of the GNU Library Public License, version 2, hence 11 | the version number 2.1.] 12 | 13 | Preamble 14 | 15 | The licenses for most software are designed to take away your 16 | freedom to share and change it. By contrast, the GNU General Public 17 | Licenses are intended to guarantee your freedom to share and change 18 | free software--to make sure the software is free for all its users. 19 | 20 | This license, the Lesser General Public License, applies to some 21 | specially designated software packages--typically libraries--of the 22 | Free Software Foundation and other authors who decide to use it. You 23 | can use it too, but we suggest you first think carefully about whether 24 | this license or the ordinary General Public License is the better 25 | strategy to use in any particular case, based on the explanations below. 26 | 27 | When we speak of free software, we are referring to freedom of use, 28 | not price. Our General Public Licenses are designed to make sure that 29 | you have the freedom to distribute copies of free software (and charge 30 | for this service if you wish); that you receive source code or can get 31 | it if you want it; that you can change the software and use pieces of 32 | it in new free programs; and that you are informed that you can do 33 | these things. 34 | 35 | To protect your rights, we need to make restrictions that forbid 36 | distributors to deny you these rights or to ask you to surrender these 37 | rights. These restrictions translate to certain responsibilities for 38 | you if you distribute copies of the library or if you modify it. 39 | 40 | For example, if you distribute copies of the library, whether gratis 41 | or for a fee, you must give the recipients all the rights that we gave 42 | you. You must make sure that they, too, receive or can get the source 43 | code. If you link other code with the library, you must provide 44 | complete object files to the recipients, so that they can relink them 45 | with the library after making changes to the library and recompiling 46 | it. And you must show them these terms so they know their rights. 47 | 48 | We protect your rights with a two-step method: (1) we copyright the 49 | library, and (2) we offer you this license, which gives you legal 50 | permission to copy, distribute and/or modify the library. 51 | 52 | To protect each distributor, we want to make it very clear that 53 | there is no warranty for the free library. Also, if the library is 54 | modified by someone else and passed on, the recipients should know 55 | that what they have is not the original version, so that the original 56 | author's reputation will not be affected by problems that might be 57 | introduced by others. 58 | 59 | Finally, software patents pose a constant threat to the existence of 60 | any free program. We wish to make sure that a company cannot 61 | effectively restrict the users of a free program by obtaining a 62 | restrictive license from a patent holder. Therefore, we insist that 63 | any patent license obtained for a version of the library must be 64 | consistent with the full freedom of use specified in this license. 65 | 66 | Most GNU software, including some libraries, is covered by the 67 | ordinary GNU General Public License. This license, the GNU Lesser 68 | General Public License, applies to certain designated libraries, and 69 | is quite different from the ordinary General Public License. We use 70 | this license for certain libraries in order to permit linking those 71 | libraries into non-free programs. 72 | 73 | When a program is linked with a library, whether statically or using 74 | a shared library, the combination of the two is legally speaking a 75 | combined work, a derivative of the original library. The ordinary 76 | General Public License therefore permits such linking only if the 77 | entire combination fits its criteria of freedom. The Lesser General 78 | Public License permits more lax criteria for linking other code with 79 | the library. 80 | 81 | We call this license the "Lesser" General Public License because it 82 | does Less to protect the user's freedom than the ordinary General 83 | Public License. It also provides other free software developers Less 84 | of an advantage over competing non-free programs. These disadvantages 85 | are the reason we use the ordinary General Public License for many 86 | libraries. However, the Lesser license provides advantages in certain 87 | special circumstances. 88 | 89 | For example, on rare occasions, there may be a special need to 90 | encourage the widest possible use of a certain library, so that it becomes 91 | a de-facto standard. To achieve this, non-free programs must be 92 | allowed to use the library. A more frequent case is that a free 93 | library does the same job as widely used non-free libraries. In this 94 | case, there is little to gain by limiting the free library to free 95 | software only, so we use the Lesser General Public License. 96 | 97 | In other cases, permission to use a particular library in non-free 98 | programs enables a greater number of people to use a large body of 99 | free software. For example, permission to use the GNU C Library in 100 | non-free programs enables many more people to use the whole GNU 101 | operating system, as well as its variant, the GNU/Linux operating 102 | system. 103 | 104 | Although the Lesser General Public License is Less protective of the 105 | users' freedom, it does ensure that the user of a program that is 106 | linked with the Library has the freedom and the wherewithal to run 107 | that program using a modified version of the Library. 108 | 109 | The precise terms and conditions for copying, distribution and 110 | modification follow. Pay close attention to the difference between a 111 | "work based on the library" and a "work that uses the library". The 112 | former contains code derived from the library, whereas the latter must 113 | be combined with the library in order to run. 114 | 115 | GNU LESSER GENERAL PUBLIC LICENSE 116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 117 | 118 | 0. This License Agreement applies to any software library or other 119 | program which contains a notice placed by the copyright holder or 120 | other authorized party saying it may be distributed under the terms of 121 | this Lesser General Public License (also called "this License"). 122 | Each licensee is addressed as "you". 123 | 124 | A "library" means a collection of software functions and/or data 125 | prepared so as to be conveniently linked with application programs 126 | (which use some of those functions and data) to form executables. 127 | 128 | The "Library", below, refers to any such software library or work 129 | which has been distributed under these terms. A "work based on the 130 | Library" means either the Library or any derivative work under 131 | copyright law: that is to say, a work containing the Library or a 132 | portion of it, either verbatim or with modifications and/or translated 133 | straightforwardly into another language. (Hereinafter, translation is 134 | included without limitation in the term "modification".) 135 | 136 | "Source code" for a work means the preferred form of the work for 137 | making modifications to it. For a library, complete source code means 138 | all the source code for all modules it contains, plus any associated 139 | interface definition files, plus the scripts used to control compilation 140 | and installation of the library. 141 | 142 | Activities other than copying, distribution and modification are not 143 | covered by this License; they are outside its scope. The act of 144 | running a program using the Library is not restricted, and output from 145 | such a program is covered only if its contents constitute a work based 146 | on the Library (independent of the use of the Library in a tool for 147 | writing it). Whether that is true depends on what the Library does 148 | and what the program that uses the Library does. 149 | 150 | 1. You may copy and distribute verbatim copies of the Library's 151 | complete source code as you receive it, in any medium, provided that 152 | you conspicuously and appropriately publish on each copy an 153 | appropriate copyright notice and disclaimer of warranty; keep intact 154 | all the notices that refer to this License and to the absence of any 155 | warranty; and distribute a copy of this License along with the 156 | Library. 157 | 158 | You may charge a fee for the physical act of transferring a copy, 159 | and you may at your option offer warranty protection in exchange for a 160 | fee. 161 | 162 | 2. You may modify your copy or copies of the Library or any portion 163 | of it, thus forming a work based on the Library, and copy and 164 | distribute such modifications or work under the terms of Section 1 165 | above, provided that you also meet all of these conditions: 166 | 167 | a) The modified work must itself be a software library. 168 | 169 | b) You must cause the files modified to carry prominent notices 170 | stating that you changed the files and the date of any change. 171 | 172 | c) You must cause the whole of the work to be licensed at no 173 | charge to all third parties under the terms of this License. 174 | 175 | d) If a facility in the modified Library refers to a function or a 176 | table of data to be supplied by an application program that uses 177 | the facility, other than as an argument passed when the facility 178 | is invoked, then you must make a good faith effort to ensure that, 179 | in the event an application does not supply such function or 180 | table, the facility still operates, and performs whatever part of 181 | its purpose remains meaningful. 182 | 183 | (For example, a function in a library to compute square roots has 184 | a purpose that is entirely well-defined independent of the 185 | application. Therefore, Subsection 2d requires that any 186 | application-supplied function or table used by this function must 187 | be optional: if the application does not supply it, the square 188 | root function must still compute square roots.) 189 | 190 | These requirements apply to the modified work as a whole. If 191 | identifiable sections of that work are not derived from the Library, 192 | and can be reasonably considered independent and separate works in 193 | themselves, then this License, and its terms, do not apply to those 194 | sections when you distribute them as separate works. But when you 195 | distribute the same sections as part of a whole which is a work based 196 | on the Library, the distribution of the whole must be on the terms of 197 | this License, whose permissions for other licensees extend to the 198 | entire whole, and thus to each and every part regardless of who wrote 199 | it. 200 | 201 | Thus, it is not the intent of this section to claim rights or contest 202 | your rights to work written entirely by you; rather, the intent is to 203 | exercise the right to control the distribution of derivative or 204 | collective works based on the Library. 205 | 206 | In addition, mere aggregation of another work not based on the Library 207 | with the Library (or with a work based on the Library) on a volume of 208 | a storage or distribution medium does not bring the other work under 209 | the scope of this License. 210 | 211 | 3. You may opt to apply the terms of the ordinary GNU General Public 212 | License instead of this License to a given copy of the Library. To do 213 | this, you must alter all the notices that refer to this License, so 214 | that they refer to the ordinary GNU General Public License, version 2, 215 | instead of to this License. (If a newer version than version 2 of the 216 | ordinary GNU General Public License has appeared, then you can specify 217 | that version instead if you wish.) Do not make any other change in 218 | these notices. 219 | 220 | Once this change is made in a given copy, it is irreversible for 221 | that copy, so the ordinary GNU General Public License applies to all 222 | subsequent copies and derivative works made from that copy. 223 | 224 | This option is useful when you wish to copy part of the code of 225 | the Library into a program that is not a library. 226 | 227 | 4. You may copy and distribute the Library (or a portion or 228 | derivative of it, under Section 2) in object code or executable form 229 | under the terms of Sections 1 and 2 above provided that you accompany 230 | it with the complete corresponding machine-readable source code, which 231 | must be distributed under the terms of Sections 1 and 2 above on a 232 | medium customarily used for software interchange. 233 | 234 | If distribution of object code is made by offering access to copy 235 | from a designated place, then offering equivalent access to copy the 236 | source code from the same place satisfies the requirement to 237 | distribute the source code, even though third parties are not 238 | compelled to copy the source along with the object code. 239 | 240 | 5. A program that contains no derivative of any portion of the 241 | Library, but is designed to work with the Library by being compiled or 242 | linked with it, is called a "work that uses the Library". Such a 243 | work, in isolation, is not a derivative work of the Library, and 244 | therefore falls outside the scope of this License. 245 | 246 | However, linking a "work that uses the Library" with the Library 247 | creates an executable that is a derivative of the Library (because it 248 | contains portions of the Library), rather than a "work that uses the 249 | library". The executable is therefore covered by this License. 250 | Section 6 states terms for distribution of such executables. 251 | 252 | When a "work that uses the Library" uses material from a header file 253 | that is part of the Library, the object code for the work may be a 254 | derivative work of the Library even though the source code is not. 255 | Whether this is true is especially significant if the work can be 256 | linked without the Library, or if the work is itself a library. The 257 | threshold for this to be true is not precisely defined by law. 258 | 259 | If such an object file uses only numerical parameters, data 260 | structure layouts and accessors, and small macros and small inline 261 | functions (ten lines or less in length), then the use of the object 262 | file is unrestricted, regardless of whether it is legally a derivative 263 | work. (Executables containing this object code plus portions of the 264 | Library will still fall under Section 6.) 265 | 266 | Otherwise, if the work is a derivative of the Library, you may 267 | distribute the object code for the work under the terms of Section 6. 268 | Any executables containing that work also fall under Section 6, 269 | whether or not they are linked directly with the Library itself. 270 | 271 | 6. As an exception to the Sections above, you may also combine or 272 | link a "work that uses the Library" with the Library to produce a 273 | work containing portions of the Library, and distribute that work 274 | under terms of your choice, provided that the terms permit 275 | modification of the work for the customer's own use and reverse 276 | engineering for debugging such modifications. 277 | 278 | You must give prominent notice with each copy of the work that the 279 | Library is used in it and that the Library and its use are covered by 280 | this License. You must supply a copy of this License. If the work 281 | during execution displays copyright notices, you must include the 282 | copyright notice for the Library among them, as well as a reference 283 | directing the user to the copy of this License. Also, you must do one 284 | of these things: 285 | 286 | a) Accompany the work with the complete corresponding 287 | machine-readable source code for the Library including whatever 288 | changes were used in the work (which must be distributed under 289 | Sections 1 and 2 above); and, if the work is an executable linked 290 | with the Library, with the complete machine-readable "work that 291 | uses the Library", as object code and/or source code, so that the 292 | user can modify the Library and then relink to produce a modified 293 | executable containing the modified Library. (It is understood 294 | that the user who changes the contents of definitions files in the 295 | Library will not necessarily be able to recompile the application 296 | to use the modified definitions.) 297 | 298 | b) Use a suitable shared library mechanism for linking with the 299 | Library. A suitable mechanism is one that (1) uses at run time a 300 | copy of the library already present on the user's computer system, 301 | rather than copying library functions into the executable, and (2) 302 | will operate properly with a modified version of the library, if 303 | the user installs one, as long as the modified version is 304 | interface-compatible with the version that the work was made with. 305 | 306 | c) Accompany the work with a written offer, valid for at 307 | least three years, to give the same user the materials 308 | specified in Subsection 6a, above, for a charge no more 309 | than the cost of performing this distribution. 310 | 311 | d) If distribution of the work is made by offering access to copy 312 | from a designated place, offer equivalent access to copy the above 313 | specified materials from the same place. 314 | 315 | e) Verify that the user has already received a copy of these 316 | materials or that you have already sent this user a copy. 317 | 318 | For an executable, the required form of the "work that uses the 319 | Library" must include any data and utility programs needed for 320 | reproducing the executable from it. However, as a special exception, 321 | the materials to be distributed need not include anything that is 322 | normally distributed (in either source or binary form) with the major 323 | components (compiler, kernel, and so on) of the operating system on 324 | which the executable runs, unless that component itself accompanies 325 | the executable. 326 | 327 | It may happen that this requirement contradicts the license 328 | restrictions of other proprietary libraries that do not normally 329 | accompany the operating system. Such a contradiction means you cannot 330 | use both them and the Library together in an executable that you 331 | distribute. 332 | 333 | 7. You may place library facilities that are a work based on the 334 | Library side-by-side in a single library together with other library 335 | facilities not covered by this License, and distribute such a combined 336 | library, provided that the separate distribution of the work based on 337 | the Library and of the other library facilities is otherwise 338 | permitted, and provided that you do these two things: 339 | 340 | a) Accompany the combined library with a copy of the same work 341 | based on the Library, uncombined with any other library 342 | facilities. This must be distributed under the terms of the 343 | Sections above. 344 | 345 | b) Give prominent notice with the combined library of the fact 346 | that part of it is a work based on the Library, and explaining 347 | where to find the accompanying uncombined form of the same work. 348 | 349 | 8. You may not copy, modify, sublicense, link with, or distribute 350 | the Library except as expressly provided under this License. Any 351 | attempt otherwise to copy, modify, sublicense, link with, or 352 | distribute the Library is void, and will automatically terminate your 353 | rights under this License. However, parties who have received copies, 354 | or rights, from you under this License will not have their licenses 355 | terminated so long as such parties remain in full compliance. 356 | 357 | 9. You are not required to accept this License, since you have not 358 | signed it. However, nothing else grants you permission to modify or 359 | distribute the Library or its derivative works. These actions are 360 | prohibited by law if you do not accept this License. Therefore, by 361 | modifying or distributing the Library (or any work based on the 362 | Library), you indicate your acceptance of this License to do so, and 363 | all its terms and conditions for copying, distributing or modifying 364 | the Library or works based on it. 365 | 366 | 10. Each time you redistribute the Library (or any work based on the 367 | Library), the recipient automatically receives a license from the 368 | original licensor to copy, distribute, link with or modify the Library 369 | subject to these terms and conditions. You may not impose any further 370 | restrictions on the recipients' exercise of the rights granted herein. 371 | You are not responsible for enforcing compliance by third parties with 372 | this License. 373 | 374 | 11. If, as a consequence of a court judgment or allegation of patent 375 | infringement or for any other reason (not limited to patent issues), 376 | conditions are imposed on you (whether by court order, agreement or 377 | otherwise) that contradict the conditions of this License, they do not 378 | excuse you from the conditions of this License. If you cannot 379 | distribute so as to satisfy simultaneously your obligations under this 380 | License and any other pertinent obligations, then as a consequence you 381 | may not distribute the Library at all. For example, if a patent 382 | license would not permit royalty-free redistribution of the Library by 383 | all those who receive copies directly or indirectly through you, then 384 | the only way you could satisfy both it and this License would be to 385 | refrain entirely from distribution of the Library. 386 | 387 | If any portion of this section is held invalid or unenforceable under any 388 | particular circumstance, the balance of the section is intended to apply, 389 | and the section as a whole is intended to apply in other circumstances. 390 | 391 | It is not the purpose of this section to induce you to infringe any 392 | patents or other property right claims or to contest validity of any 393 | such claims; this section has the sole purpose of protecting the 394 | integrity of the free software distribution system which is 395 | implemented by public license practices. Many people have made 396 | generous contributions to the wide range of software distributed 397 | through that system in reliance on consistent application of that 398 | system; it is up to the author/donor to decide if he or she is willing 399 | to distribute software through any other system and a licensee cannot 400 | impose that choice. 401 | 402 | This section is intended to make thoroughly clear what is believed to 403 | be a consequence of the rest of this License. 404 | 405 | 12. If the distribution and/or use of the Library is restricted in 406 | certain countries either by patents or by copyrighted interfaces, the 407 | original copyright holder who places the Library under this License may add 408 | an explicit geographical distribution limitation excluding those countries, 409 | so that distribution is permitted only in or among countries not thus 410 | excluded. In such case, this License incorporates the limitation as if 411 | written in the body of this License. 412 | 413 | 13. The Free Software Foundation may publish revised and/or new 414 | versions of the Lesser General Public License from time to time. 415 | Such new versions will be similar in spirit to the present version, 416 | but may differ in detail to address new problems or concerns. 417 | 418 | Each version is given a distinguishing version number. If the Library 419 | specifies a version number of this License which applies to it and 420 | "any later version", you have the option of following the terms and 421 | conditions either of that version or of any later version published by 422 | the Free Software Foundation. If the Library does not specify a 423 | license version number, you may choose any version ever published by 424 | the Free Software Foundation. 425 | 426 | 14. If you wish to incorporate parts of the Library into other free 427 | programs whose distribution conditions are incompatible with these, 428 | write to the author to ask for permission. For software which is 429 | copyrighted by the Free Software Foundation, write to the Free 430 | Software Foundation; we sometimes make exceptions for this. Our 431 | decision will be guided by the two goals of preserving the free status 432 | of all derivatives of our free software and of promoting the sharing 433 | and reuse of software generally. 434 | 435 | NO WARRANTY 436 | 437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 446 | 447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 456 | DAMAGES. 457 | 458 | END OF TERMS AND CONDITIONS 459 | 460 | How to Apply These Terms to Your New Libraries 461 | 462 | If you develop a new library, and you want it to be of the greatest 463 | possible use to the public, we recommend making it free software that 464 | everyone can redistribute and change. You can do so by permitting 465 | redistribution under these terms (or, alternatively, under the terms of the 466 | ordinary General Public License). 467 | 468 | To apply these terms, attach the following notices to the library. It is 469 | safest to attach them to the start of each source file to most effectively 470 | convey the exclusion of warranty; and each file should have at least the 471 | "copyright" line and a pointer to where the full notice is found. 472 | 473 | 474 | Copyright (C) 475 | 476 | This library is free software; you can redistribute it and/or 477 | modify it under the terms of the GNU Lesser General Public 478 | License as published by the Free Software Foundation; either 479 | version 2.1 of the License, or (at your option) any later version. 480 | 481 | This library is distributed in the hope that it will be useful, 482 | but WITHOUT ANY WARRANTY; without even the implied warranty of 483 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 484 | Lesser General Public License for more details. 485 | 486 | You should have received a copy of the GNU Lesser General Public 487 | License along with this library; if not, write to the Free Software 488 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 489 | 490 | Also add information on how to contact you by electronic and paper mail. 491 | 492 | You should also get your employer (if you work as a programmer) or your 493 | school, if any, to sign a "copyright disclaimer" for the library, if 494 | necessary. Here is a sample; alter the names: 495 | 496 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 497 | library `Frob' (a library for tweaking knobs) written by James Random Hacker. 498 | 499 | , 1 April 1990 500 | Ty Coon, President of Vice 501 | 502 | That's all there is to it! 503 | --------------------------------------------------------------------------------