| // Avisynth v2.5. Copyright 2002 Ben Rudiak-Gould et al. |
| // Avisynth v2.5. Copyright 2002 Ben Rudiak-Gould et al. |
| // http://www.avisynth.org |
| // http://www.avisynth.org |
| |
| |
| // This program is free software; you can redistribute it and/or modify |
| // This program is free software; you can redistribute it and/or modify |
| // it under the terms of the GNU General Public License as published by |
| // it under the terms of the GNU General Public License as published by |
| // the Free Software Foundation; either version 2 of the License, or |
| // the Free Software Foundation; either version 2 of the License, or |
| // (at your option) any later version. |
| // (at your option) any later version. |
| // |
| // |
| // This program is distributed in the hope that it will be useful, |
| // This program is distributed in the hope that it will be useful, |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| // GNU General Public License for more details. |
| // GNU General Public License for more details. |
| // |
| // |
| // You should have received a copy of the GNU General Public License |
| // You should have received a copy of the GNU General Public License |
| // along with this program; if not, write to the Free Software |
| // along with this program; if not, write to the Free Software |
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit |
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit |
| // http://www.gnu.org/copyleft/gpl.html . |
| // http://www.gnu.org/copyleft/gpl.html . |
| // |
| // |
| // Linking Avisynth statically or dynamically with other modules is making a |
| // Linking Avisynth statically or dynamically with other modules is making a |
| // combined work based on Avisynth. Thus, the terms and conditions of the GNU |
| // combined work based on Avisynth. Thus, the terms and conditions of the GNU |
| // General Public License cover the whole combination. |
| // General Public License cover the whole combination. |
| // |
| // |
| // As a special exception, the copyright holders of Avisynth give you |
| // As a special exception, the copyright holders of Avisynth give you |
| // permission to link Avisynth with independent modules that communicate with |
| // permission to link Avisynth with independent modules that communicate with |
| // Avisynth solely through the interfaces defined in avisynth.h, regardless of the license |
| // Avisynth solely through the interfaces defined in avisynth.h, regardless of the license |
| // terms of these independent modules, and to copy and distribute the |
| // terms of these independent modules, and to copy and distribute the |
| // resulting combined work under terms of your choice, provided that |
| // resulting combined work under terms of your choice, provided that |
| // every copy of the combined work is accompanied by a complete copy of |
| // every copy of the combined work is accompanied by a complete copy of |
| // the source code of Avisynth (the version of Avisynth used to produce the |
| // the source code of Avisynth (the version of Avisynth used to produce the |
| // combined work), being distributed under the terms of the GNU General |
| // combined work), being distributed under the terms of the GNU General |
| // Public License plus this exception. An independent module is a module |
| // Public License plus this exception. An independent module is a module |
| // which is not derived from or based on Avisynth, such as 3rd-party filters, |
| // which is not derived from or based on Avisynth, such as 3rd-party filters, |
| // import and export plugins, or graphical user interfaces. |
| // import and export plugins, or graphical user interfaces. |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| #ifndef __AVISYNTH_H__ |
| #ifndef __AVISYNTH_H__ |
| #define __AVISYNTH_H__ |
| #define __AVISYNTH_H__ |
| |
| |
| enum { AVISYNTH_INTERFACE_VERSION = 3 }; |
| enum { AVISYNTH_INTERFACE_VERSION = 3 }; |
| |
| |
| |
| |
| /* Define all types necessary for interfacing with avisynth.dll |
| /* Define all types necessary for interfacing with avisynth.dll |
| Moved from internal.h */ |
| Moved from internal.h */ |
| |
| |
| // Win32 API macros, notably the types BYTE, DWORD, ULONG, etc. |
| // Win32 API macros, notably the types BYTE, DWORD, ULONG, etc. |
| #include <windef.h> |
| #include <windef.h> |
| |
| |
| |
| #if (_MSC_VER >= 1400) |
| |
| extern "C" LONG __cdecl _InterlockedIncrement(LONG volatile * pn); |
| |
| extern "C" LONG __cdecl _InterlockedDecrement(LONG volatile * pn); |
| |
| #pragma intrinsic(_InterlockedIncrement) |
| |
| #pragma intrinsic(_InterlockedDecrement) |
| |
| #define InterlockedIncrement _InterlockedIncrement |
| |
| #define InterlockedDecrement _InterlockedDecrement |
| |
| #endif |
| |
| |
| // COM interface macros |
| // COM interface macros |
| #include <objbase.h> |
| #include <objbase.h> |
| |
| |
| |
| |
| // Raster types used by VirtualDub & Avisynth |
| // Raster types used by VirtualDub & Avisynth |
| #define in64 (__int64)(unsigned short) |
| #define in64 (__int64)(unsigned short) |
| typedef unsigned long Pixel; // this will break on 64-bit machines! |
| typedef unsigned long Pixel; // this will break on 64-bit machines! |
| typedef unsigned long Pixel32; |
| typedef unsigned long Pixel32; |
| typedef unsigned char Pixel8; |
| typedef unsigned char Pixel8; |
| typedef long PixCoord; |
| typedef long PixCoord; |
| typedef long PixDim; |
| typedef long PixDim; |
| typedef long PixOffset; |
| typedef long PixOffset; |
| |
| |
| |
| |
| /* Compiler-specific crap */ |
| /* Compiler-specific crap */ |
| |
| |
| // Tell MSVC to stop precompiling here |
| // Tell MSVC to stop precompiling here |
| #ifdef _MSC_VER |
| #ifdef _MSC_VER |
| #pragma hdrstop |
| #pragma hdrstop |
| #endif |
| #endif |
| |
| |
| // Set up debugging macros for MS compilers; for others, step down to the |
| // Set up debugging macros for MS compilers; for others, step down to the |
| // standard <assert.h> interface |
| // standard <assert.h> interface |
| #ifdef _MSC_VER |
| #ifdef _MSC_VER |
| #include <crtdbg.h> |
| #include <crtdbg.h> |
| #else |
| #else |
| #define _RPT0(a,b) ((void)0) |
| #define _RPT0(a,b) ((void)0) |
| #define _RPT1(a,b,c) ((void)0) |
| #define _RPT1(a,b,c) ((void)0) |
| #define _RPT2(a,b,c,d) ((void)0) |
| #define _RPT2(a,b,c,d) ((void)0) |
| #define _RPT3(a,b,c,d,e) ((void)0) |
| #define _RPT3(a,b,c,d,e) ((void)0) |
| #define _RPT4(a,b,c,d,e,f) ((void)0) |
| #define _RPT4(a,b,c,d,e,f) ((void)0) |
| |
| |
| #define _ASSERTE(x) assert(x) |
| #define _ASSERTE(x) assert(x) |
| #include <assert.h> |
| #include <assert.h> |
| #endif |
| #endif |
| |
| |
| |
| |
| |
| |
| // I had problems with Premiere wanting 1-byte alignment for its structures, |
| // I had problems with Premiere wanting 1-byte alignment for its structures, |
| // so I now set the Avisynth struct alignment explicitly here. |
| // so I now set the Avisynth struct alignment explicitly here. |
| #pragma pack(push,8) |
| #pragma pack(push,8) |
| |
| |
| #define FRAME_ALIGN 16 |
| #define FRAME_ALIGN 16 |
| // Default frame alignment is 16 bytes, to help P4, when using SSE2 |
| // Default frame alignment is 16 bytes, to help P4, when using SSE2 |
| |
| |
| // The VideoInfo struct holds global information about a clip (i.e. |
| // The VideoInfo struct holds global information about a clip (i.e. |
| // information that does not depend on the frame number). The GetVideoInfo |
| // information that does not depend on the frame number). The GetVideoInfo |
| // method in IClip returns this struct. |
| // method in IClip returns this struct. |
| |
| |
| // Audio Sample information |
| // Audio Sample information |
| typedef float SFLOAT; |
| typedef float SFLOAT; |
| |
| |
| enum {SAMPLE_INT8 = 1<<0, |
| enum {SAMPLE_INT8 = 1<<0, |
| SAMPLE_INT16 = 1<<1, |
| SAMPLE_INT16 = 1<<1, |
| SAMPLE_INT24 = 1<<2, // Int24 is a very stupid thing to code, but it's supported by some hardware. |
| SAMPLE_INT24 = 1<<2, // Int24 is a very stupid thing to code, but it's supported by some hardware. |
| SAMPLE_INT32 = 1<<3, |
| SAMPLE_INT32 = 1<<3, |
| SAMPLE_FLOAT = 1<<4}; |
| SAMPLE_FLOAT = 1<<4}; |
| |
| |
| enum { |
| enum { |
| PLANAR_Y=1<<0, |
| PLANAR_Y=1<<0, |
| PLANAR_U=1<<1, |
| PLANAR_U=1<<1, |
| PLANAR_V=1<<2, |
| PLANAR_V=1<<2, |
| PLANAR_ALIGNED=1<<3, |
| PLANAR_ALIGNED=1<<3, |
| PLANAR_Y_ALIGNED=PLANAR_Y|PLANAR_ALIGNED, |
| PLANAR_Y_ALIGNED=PLANAR_Y|PLANAR_ALIGNED, |
| PLANAR_U_ALIGNED=PLANAR_U|PLANAR_ALIGNED, |
| PLANAR_U_ALIGNED=PLANAR_U|PLANAR_ALIGNED, |
| PLANAR_V_ALIGNED=PLANAR_V|PLANAR_ALIGNED, |
| PLANAR_V_ALIGNED=PLANAR_V|PLANAR_ALIGNED, |
| }; |
| }; |
| |
| |
| class AvisynthError /* exception */ { |
| class AvisynthError /* exception */ { |
| public: |
| public: |
| const char* const msg; |
| const char* const msg; |
| AvisynthError(const char* _msg) : msg(_msg) {} |
| AvisynthError(const char* _msg) : msg(_msg) {} |
| }; |
| }; |
| |
| |
| struct VideoInfo { |
| struct VideoInfo { |
| int width, height; // width=0 means no video |
| int width, height; // width=0 means no video |
| unsigned fps_numerator, fps_denominator; |
| unsigned fps_numerator, fps_denominator; |
| int num_frames; |
| int num_frames; |
| // This is more extensible than previous versions. More properties can be added seeminglesly. |
| // This is more extensible than previous versions. More properties can be added seeminglesly. |
| |
| |
| // Colorspace properties. |
| // Colorspace properties. |
| enum { |
| enum { |
| CS_BGR = 1<<28, |
| CS_BGR = 1<<28, |
| CS_YUV = 1<<29, |
| CS_YUV = 1<<29, |
| CS_INTERLEAVED = 1<<30, |
| CS_INTERLEAVED = 1<<30, |
| CS_PLANAR = 1<<31 |
| CS_PLANAR = 1<<31 |
| }; |
| }; |
| |
| |
| // Specific colorformats |
| // Specific colorformats |
| enum { CS_UNKNOWN = 0, |
| enum { CS_UNKNOWN = 0, |
| CS_BGR24 = 1<<0 | CS_BGR | CS_INTERLEAVED, |
| CS_BGR24 = 1<<0 | CS_BGR | CS_INTERLEAVED, |
| CS_BGR32 = 1<<1 | CS_BGR | CS_INTERLEAVED, |
| CS_BGR32 = 1<<1 | CS_BGR | CS_INTERLEAVED, |
| CS_YUY2 = 1<<2 | CS_YUV | CS_INTERLEAVED, |
| CS_YUY2 = 1<<2 | CS_YUV | CS_INTERLEAVED, |
| CS_YV12 = 1<<3 | CS_YUV | CS_PLANAR, // y-v-u, 4:2:0 planar |
| CS_YV12 = 1<<3 | CS_YUV | CS_PLANAR, // y-v-u, 4:2:0 planar |
| CS_I420 = 1<<4 | CS_YUV | CS_PLANAR, // y-u-v, 4:2:0 planar |
| CS_I420 = 1<<4 | CS_YUV | CS_PLANAR, // y-u-v, 4:2:0 planar |
| CS_IYUV = 1<<4 | CS_YUV | CS_PLANAR, // same as above |
| CS_IYUV = 1<<4 | CS_YUV | CS_PLANAR, // same as above |
| }; |
| }; |
| int pixel_type; // changed to int as of 2.5 |
| int pixel_type; // changed to int as of 2.5 |
| |
| |
| |
| |
| int audio_samples_per_second; // 0 means no audio |
| int audio_samples_per_second; // 0 means no audio |
| int sample_type; // as of 2.5 |
| int sample_type; // as of 2.5 |
| __int64 num_audio_samples; // changed as of 2.5 |
| __int64 num_audio_samples; // changed as of 2.5 |
| int nchannels; // as of 2.5 |
| int nchannels; // as of 2.5 |
| |
| |
| // Imagetype properties |
| // Imagetype properties |
| |
| |
| int image_type; |
| int image_type; |
| |
| |
| enum { |
| enum { |
| IT_BFF = 1<<0, |
| IT_BFF = 1<<0, |
| IT_TFF = 1<<1, |
| IT_TFF = 1<<1, |
| IT_FIELDBASED = 1<<2 |
| IT_FIELDBASED = 1<<2 |
| }; |
| }; |
| |
| |
| // useful functions of the above |
| // useful functions of the above |
| bool HasVideo() const { return (width!=0); } |
| bool HasVideo() const { return (width!=0); } |
| bool HasAudio() const { return (audio_samples_per_second!=0); } |
| bool HasAudio() const { return (audio_samples_per_second!=0); } |
| bool IsRGB() const { return !!(pixel_type&CS_BGR); } |
| bool IsRGB() const { return !!(pixel_type&CS_BGR); } |
| bool IsRGB24() const { return (pixel_type&CS_BGR24)==CS_BGR24; } // Clear out additional properties |
| bool IsRGB24() const { return (pixel_type&CS_BGR24)==CS_BGR24; } // Clear out additional properties |
| bool IsRGB32() const { return (pixel_type & CS_BGR32) == CS_BGR32 ; } |
| bool IsRGB32() const { return (pixel_type & CS_BGR32) == CS_BGR32 ; } |
| bool IsYUV() const { return !!(pixel_type&CS_YUV ); } |
| bool IsYUV() const { return !!(pixel_type&CS_YUV ); } |
| bool IsYUY2() const { return (pixel_type & CS_YUY2) == CS_YUY2; } |
| bool IsYUY2() const { return (pixel_type & CS_YUY2) == CS_YUY2; } |
| bool IsYV12() const { return ((pixel_type & CS_YV12) == CS_YV12)||((pixel_type & CS_I420) == CS_I420); } |
| bool IsYV12() const { return ((pixel_type & CS_YV12) == CS_YV12)||((pixel_type & CS_I420) == CS_I420); } |
| bool IsColorSpace(int c_space) const { return ((pixel_type & c_space) == c_space); } |
| bool IsColorSpace(int c_space) const { return ((pixel_type & c_space) == c_space); } |
| bool Is(int property) const { return ((pixel_type & property)==property ); } |
| bool Is(int property) const { return ((pixel_type & property)==property ); } |
| bool IsPlanar() const { return !!(pixel_type & CS_PLANAR); } |
| bool IsPlanar() const { return !!(pixel_type & CS_PLANAR); } |
| bool IsFieldBased() const { return !!(image_type & IT_FIELDBASED); } |
| bool IsFieldBased() const { return !!(image_type & IT_FIELDBASED); } |
| bool IsParityKnown() const { return ((image_type & IT_FIELDBASED)&&(image_type & (IT_BFF|IT_TFF))); } |
| bool IsParityKnown() const { return ((image_type & IT_FIELDBASED)&&(image_type & (IT_BFF|IT_TFF))); } |
| bool IsBFF() const { return !!(image_type & IT_BFF); } |
| bool IsBFF() const { return !!(image_type & IT_BFF); } |
| bool IsTFF() const { return !!(image_type & IT_TFF); } |
| bool IsTFF() const { return !!(image_type & IT_TFF); } |
| |
| |
| bool IsVPlaneFirst() const {return ((pixel_type & CS_YV12) == CS_YV12); } // Don't use this |
| bool IsVPlaneFirst() const {return ((pixel_type & CS_YV12) == CS_YV12); } // Don't use this |
| int BytesFromPixels(int pixels) const { return pixels * (BitsPerPixel()>>3); } // Will not work on planar images, but will return only luma planes |
| int BytesFromPixels(int pixels) const { return pixels * (BitsPerPixel()>>3); } // Will not work on planar images, but will return only luma planes |
| int RowSize() const { return BytesFromPixels(width); } // Also only returns first plane on planar images |
| int RowSize() const { return BytesFromPixels(width); } // Also only returns first plane on planar images |
| int BMPSize() const { if (IsPlanar()) {int p = height * ((RowSize()+3) & ~3); p+=p>>1; return p; } return height * ((RowSize()+3) & ~3); } |
| int BMPSize() const { if (IsPlanar()) {int p = height * ((RowSize()+3) & ~3); p+=p>>1; return p; } return height * ((RowSize()+3) & ~3); } |
| __int64 AudioSamplesFromFrames(__int64 frames) const { return (fps_numerator && HasVideo()) ? ((__int64)(frames) * audio_samples_per_second * fps_denominator / fps_numerator) : 0; } |
| __int64 AudioSamplesFromFrames(__int64 frames) const { return (fps_numerator && HasVideo()) ? ((__int64)(frames) * audio_samples_per_second * fps_denominator / fps_numerator) : 0; } |
| int FramesFromAudioSamples(__int64 samples) const { return (fps_denominator && HasAudio()) ? (int)((samples * (__int64)fps_numerator)/((__int64)fps_denominator * (__int64)audio_samples_per_second)) : 0; } |
| int FramesFromAudioSamples(__int64 samples) const { return (fps_denominator && HasAudio()) ? (int)((samples * (__int64)fps_numerator)/((__int64)fps_denominator * (__int64)audio_samples_per_second)) : 0; } |
| __int64 AudioSamplesFromBytes(__int64 bytes) const { return HasAudio() ? bytes / BytesPerAudioSample() : 0; } |
| __int64 AudioSamplesFromBytes(__int64 bytes) const { return HasAudio() ? bytes / BytesPerAudioSample() : 0; } |
| __int64 BytesFromAudioSamples(__int64 samples) const { return samples * BytesPerAudioSample(); } |
| __int64 BytesFromAudioSamples(__int64 samples) const { return samples * BytesPerAudioSample(); } |
| int AudioChannels() const { return HasAudio() ? nchannels : 0; } |
| int AudioChannels() const { return HasAudio() ? nchannels : 0; } |
| int SampleType() const{ return sample_type;} |
| int SampleType() const{ return sample_type;} |
| bool IsSampleType(int testtype) const{ return !!(sample_type&testtype);} |
| bool IsSampleType(int testtype) const{ return !!(sample_type&testtype);} |
| int SamplesPerSecond() const { return audio_samples_per_second; } |
| int SamplesPerSecond() const { return audio_samples_per_second; } |
| int BytesPerAudioSample() const { return nchannels*BytesPerChannelSample();} |
| int BytesPerAudioSample() const { return nchannels*BytesPerChannelSample();} |
| void SetFieldBased(bool isfieldbased) { if (isfieldbased) image_type|=IT_FIELDBASED; else image_type&=~IT_FIELDBASED; } |
| void SetFieldBased(bool isfieldbased) { if (isfieldbased) image_type|=IT_FIELDBASED; else image_type&=~IT_FIELDBASED; } |
| void Set(int property) { image_type|=property; } |
| void Set(int property) { image_type|=property; } |
| void Clear(int property) { image_type&=~property; } |
| void Clear(int property) { image_type&=~property; } |
| |
| |
| int BitsPerPixel() const { |
| int BitsPerPixel() const { |
| switch (pixel_type) { |
| switch (pixel_type) { |
| case CS_BGR24: |
| case CS_BGR24: |
| return 24; |
| return 24; |
| case CS_BGR32: |
| case CS_BGR32: |
| return 32; |
| return 32; |
| case CS_YUY2: |
| case CS_YUY2: |
| return 16; |
| return 16; |
| case CS_YV12: |
| case CS_YV12: |
| case CS_I420: |
| case CS_I420: |
| return 12; |
| return 12; |
| default: |
| default: |
| return 0; |
| return 0; |
| } |
| } |
| } |
| } |
| |
| |
| int BytesPerChannelSample() const { |
| int BytesPerChannelSample() const { |
| switch (sample_type) { |
| switch (sample_type) { |
| case SAMPLE_INT8: |
| case SAMPLE_INT8: |
| return sizeof(signed char); |
| return sizeof(signed char); |
| case SAMPLE_INT16: |
| case SAMPLE_INT16: |
| return sizeof(signed short); |
| return sizeof(signed short); |
| case SAMPLE_INT24: |
| case SAMPLE_INT24: |
| return 3; |
| return 3; |
| case SAMPLE_INT32: |
| case SAMPLE_INT32: |
| return sizeof(signed int); |
| return sizeof(signed int); |
| case SAMPLE_FLOAT: |
| case SAMPLE_FLOAT: |
| return sizeof(SFLOAT); |
| return sizeof(SFLOAT); |
| default: |
| default: |
| _ASSERTE("Sample type not recognized!"); |
| _ASSERTE("Sample type not recognized!"); |
| return 0; |
| return 0; |
| } |
| } |
| } |
| } |
| |
| |
| // useful mutator |
| // useful mutator |
| void SetFPS(unsigned numerator, unsigned denominator) { |
| void SetFPS(unsigned numerator, unsigned denominator) { |
| if ((numerator == 0) || (denominator == 0)) { |
| if ((numerator == 0) || (denominator == 0)) { |
| fps_numerator = 0; |
| fps_numerator = 0; |
| fps_denominator = 1; |
| fps_denominator = 1; |
| } |
| } |
| else { |
| else { |
| unsigned x=numerator, y=denominator; |
| unsigned x=numerator, y=denominator; |
| while (y) { // find gcd |
| while (y) { // find gcd |
| unsigned t = x%y; x = y; y = t; |
| unsigned t = x%y; x = y; y = t; |
| } |
| } |
| fps_numerator = numerator/x; |
| fps_numerator = numerator/x; |
| fps_denominator = denominator/x; |
| fps_denominator = denominator/x; |
| } |
| } |
| } |
| } |
| |
| |
| // Range protected multiply-divide of FPS |
| // Range protected multiply-divide of FPS |
| void MulDivFPS(unsigned multiplier, unsigned divisor) { |
| void MulDivFPS(unsigned multiplier, unsigned divisor) { |
| unsigned __int64 numerator = UInt32x32To64(fps_numerator, multiplier); |
| unsigned __int64 numerator = UInt32x32To64(fps_numerator, multiplier); |
| unsigned __int64 denominator = UInt32x32To64(fps_denominator, divisor); |
| unsigned __int64 denominator = UInt32x32To64(fps_denominator, divisor); |
| |
| |
| unsigned __int64 x=numerator, y=denominator; |
| unsigned __int64 x=numerator, y=denominator; |
| while (y) { // find gcd |
| while (y) { // find gcd |
| unsigned __int64 t = x%y; x = y; y = t; |
| unsigned __int64 t = x%y; x = y; y = t; |
| } |
| } |
| numerator /= x; // normalize |
| numerator /= x; // normalize |
| denominator /= x; |
| denominator /= x; |
| |
| |
| unsigned __int64 temp = numerator | denominator; // Just looking top bit |
| unsigned __int64 temp = numerator | denominator; // Just looking top bit |
| unsigned u = 0; |
| unsigned u = 0; |
| while (temp & 0xffffffff80000000) { // or perhaps > 16777216*2 |
| while (temp & 0xffffffff80000000ull) { // or perhaps > 16777216*2 |
| temp = Int64ShrlMod32(temp, 1); |
| temp = Int64ShrlMod32(temp, 1); |
| u++; |
| u++; |
| } |
| } |
| if (u) { // Scale to fit |
| if (u) { // Scale to fit |
| const unsigned round = 1 << (u-1); |
| const unsigned round = 1 << (u-1); |
| SetFPS( (unsigned)Int64ShrlMod32(numerator + round, u), |
| SetFPS( (unsigned)Int64ShrlMod32(numerator + round, u), |
| (unsigned)Int64ShrlMod32(denominator + round, u) ); |
| (unsigned)Int64ShrlMod32(denominator + round, u) ); |
| } |
| } |
| else { |
| else { |
| fps_numerator = (unsigned)numerator; |
| fps_numerator = (unsigned)numerator; |
| fps_denominator = (unsigned)denominator; |
| fps_denominator = (unsigned)denominator; |
| } |
| } |
| } |
| } |
| |
| |
| // Test for same colorspace |
| // Test for same colorspace |
| bool IsSameColorspace(const VideoInfo& vi) const { |
| bool IsSameColorspace(const VideoInfo& vi) const { |
| if (vi.pixel_type == pixel_type) return TRUE; |
| if (vi.pixel_type == pixel_type) return TRUE; |
| if (IsYV12() && vi.IsYV12()) return TRUE; |
| if (IsYV12() && vi.IsYV12()) return TRUE; |
| return FALSE; |
| return FALSE; |
| } |
| } |
| |
| |
| }; |
| }; |
| |
| |
| |
| |
| |
| |
| |
| |
| // VideoFrameBuffer holds information about a memory block which is used |
| // VideoFrameBuffer holds information about a memory block which is used |
| // for video data. For efficiency, instances of this class are not deleted |
| // for video data. For efficiency, instances of this class are not deleted |
| // when the refcount reaches zero; instead they're stored in a linked list |
| // when the refcount reaches zero; instead they're stored in a linked list |
| // to be reused. The instances are deleted when the corresponding AVS |
| // to be reused. The instances are deleted when the corresponding AVS |
| // file is closed. |
| // file is closed. |
| |
| |
| class VideoFrameBuffer { |
| class VideoFrameBuffer { |
| BYTE* const data; |
| BYTE* const data; |
| const int data_size; |
| const int data_size; |
| // sequence_number is incremented every time the buffer is changed, so |
| // sequence_number is incremented every time the buffer is changed, so |
| // that stale views can tell they're no longer valid. |
| // that stale views can tell they're no longer valid. |
| long sequence_number; |
| volatile long sequence_number; |
| |
| |
| friend class VideoFrame; |
| friend class VideoFrame; |
| friend class Cache; |
| friend class Cache; |
| |
| friend class CacheMT; |
| friend class ScriptEnvironment; |
| friend class ScriptEnvironment; |
| long refcount; |
| volatile long refcount; |
| |
| |
| public: |
| public: |
| VideoFrameBuffer(int size); |
| VideoFrameBuffer(int size); |
| VideoFrameBuffer(); |
| VideoFrameBuffer(); |
| ~VideoFrameBuffer(); |
| ~VideoFrameBuffer(); |
| |
| |
| const BYTE* GetReadPtr() const { return data; } |
| const BYTE* GetReadPtr() const { return data; } |
| BYTE* GetWritePtr() { ++sequence_number; return data; } |
| BYTE* GetWritePtr() { InterlockedIncrement(&sequence_number); return data; } |
| int GetDataSize() { return data_size; } |
| int GetDataSize() { return data_size; } |
| int GetSequenceNumber() { return sequence_number; } |
| int GetSequenceNumber() { return sequence_number; } |
| int GetRefcount() { return refcount; } |
| int GetRefcount() { return refcount; } |
| }; |
| }; |
| |
| |
| |
| |
| class IClip; |
| class IClip; |
| class PClip; |
| class PClip; |
| class PVideoFrame; |
| class PVideoFrame; |
| class IScriptEnvironment; |
| class IScriptEnvironment; |
| class AVSValue; |
| class AVSValue; |
| |
| |
| |
| |
| // VideoFrame holds a "window" into a VideoFrameBuffer. Operator new |
| // VideoFrame holds a "window" into a VideoFrameBuffer. Operator new |
| // is overloaded to recycle class instances. |
| // is overloaded to recycle class instances. |
| |
| |
| class VideoFrame { |
| class VideoFrame { |
| int refcount; |
| volatile long refcount; |
| VideoFrameBuffer* const vfb; |
| VideoFrameBuffer* const vfb; |
| const int offset, pitch, row_size, height, offsetU, offsetV, pitchUV; // U&V offsets are from top of picture. |
| const int offset, pitch, row_size, height, offsetU, offsetV, pitchUV; // U&V offsets are from top of picture. |
| |
| |
| friend class PVideoFrame; |
| friend class PVideoFrame; |
| void AddRef() { InterlockedIncrement((long *)&refcount); } |
| void AddRef() { InterlockedIncrement(&refcount); } |
| void Release() { if (refcount==1) InterlockedDecrement(&vfb->refcount); InterlockedDecrement((long *)&refcount); } |
| void Release() { VideoFrameBuffer* vfb_local = vfb; if (!InterlockedDecrement(&refcount)) InterlockedDecrement(&vfb_local->refcount); } |
| |
| |
| friend class ScriptEnvironment; |
| |
| friend class Cache; |
| friend class Cache; |
| |
| friend class CacheMT; |
| |
| friend class ScriptEnvironment; |
| |
| |
| VideoFrame(VideoFrameBuffer* _vfb, int _offset, int _pitch, int _row_size, int _height); |
| VideoFrame(VideoFrameBuffer* _vfb, int _offset, int _pitch, int _row_size, int _height); |
| VideoFrame(VideoFrameBuffer* _vfb, int _offset, int _pitch, int _row_size, int _height, int _offsetU, int _offsetV, int _pitchUV); |
| VideoFrame(VideoFrameBuffer* _vfb, int _offset, int _pitch, int _row_size, int _height, int _offsetU, int _offsetV, int _pitchUV); |
| |
| |
| void* operator new(unsigned size); |
| void* operator new(unsigned size); |
| // TESTME: OFFSET U/V may be switched to what could be expected from AVI standard! |
| // TESTME: OFFSET U/V may be switched to what could be expected from AVI standard! |
| public: |
| public: |
| int GetPitch() const { return pitch; } |
| int GetPitch() const { return pitch; } |
| int GetPitch(int plane) const { switch (plane) {case PLANAR_U: case PLANAR_V: return pitchUV;} return pitch; } |
| int GetPitch(int plane) const { switch (plane) {case PLANAR_U: case PLANAR_V: return pitchUV;} return pitch; } |
| int GetRowSize() const { return row_size; } |
| int GetRowSize() const { return row_size; } |
| int GetRowSize(int plane) const { |
| __declspec(noinline) int GetRowSize(int plane) const { |
| switch (plane) { |
| switch (plane) { |
| case PLANAR_U: case PLANAR_V: if (pitchUV) return row_size>>1; else return 0; |
| case PLANAR_U: case PLANAR_V: if (pitchUV) return row_size>>1; else return 0; |
| case PLANAR_U_ALIGNED: case PLANAR_V_ALIGNED: |
| case PLANAR_U_ALIGNED: case PLANAR_V_ALIGNED: |
| if (pitchUV) { |
| if (pitchUV) { |
| int r = ((row_size+FRAME_ALIGN-1)&(~(FRAME_ALIGN-1)) )>>1; // Aligned rowsize |
| int r = ((row_size+FRAME_ALIGN-1)&(~(FRAME_ALIGN-1)) )>>1; // Aligned rowsize |
| if (r<=pitchUV) |
| if (r<=pitchUV) |
| return r; |
| return r; |
| return row_size>>1; |
| return row_size>>1; |
| } else return 0; |
| } else return 0; |
| case PLANAR_Y_ALIGNED: |
| case PLANAR_Y_ALIGNED: |
| int r = (row_size+FRAME_ALIGN-1)&(~(FRAME_ALIGN-1)); // Aligned rowsize |
| int r = (row_size+FRAME_ALIGN-1)&(~(FRAME_ALIGN-1)); // Aligned rowsize |
| if (r<=pitch) |
| if (r<=pitch) |
| return r; |
| return r; |
| return row_size; |
| return row_size; |
| } |
| } |
| return row_size; } |
| return row_size; } |
| int GetHeight() const { return height; } |
| int GetHeight() const { return height; } |
| int GetHeight(int plane) const { switch (plane) {case PLANAR_U: case PLANAR_V: if (pitchUV) return height>>1; return 0;} return height; } |
| int GetHeight(int plane) const { switch (plane) {case PLANAR_U: case PLANAR_V: if (pitchUV) return height>>1; return 0;} return height; } |
| |
| |
| // generally you shouldn't use these three |
| // generally you shouldn't use these three |
| VideoFrameBuffer* GetFrameBuffer() const { return vfb; } |
| VideoFrameBuffer* GetFrameBuffer() const { return vfb; } |
| int GetOffset() const { return offset; } |
| int GetOffset() const { return offset; } |
| int GetOffset(int plane) const { switch (plane) {case PLANAR_U: return offsetU;case PLANAR_V: return offsetV;default: return offset;}; } |
| int GetOffset(int plane) const { switch (plane) {case PLANAR_U: return offsetU;case PLANAR_V: return offsetV;default: return offset;}; } |
| |
| |
| // in plugins use env->SubFrame() |
| // in plugins use env->SubFrame() |
| |
| //If you really want to use these remember to increase vfb->refcount before calling and decrement it afterwards. |
| VideoFrame* Subframe(int rel_offset, int new_pitch, int new_row_size, int new_height) const; |
| VideoFrame* Subframe(int rel_offset, int new_pitch, int new_row_size, int new_height) const; |
| VideoFrame* Subframe(int rel_offset, int new_pitch, int new_row_size, int new_height, int rel_offsetU, int rel_offsetV, int pitchUV) const; |
| VideoFrame* Subframe(int rel_offset, int new_pitch, int new_row_size, int new_height, int rel_offsetU, int rel_offsetV, int pitchUV) const; |
| |
| |
| |
| |
| const BYTE* GetReadPtr() const { return vfb->GetReadPtr() + offset; } |
| const BYTE* GetReadPtr() const { return vfb->GetReadPtr() + offset; } |
| const BYTE* GetReadPtr(int plane) const { return vfb->GetReadPtr() + GetOffset(plane); } |
| const BYTE* GetReadPtr(int plane) const { return vfb->GetReadPtr() + GetOffset(plane); } |
| |
| |
| bool IsWritable() const { return (refcount == 1 && vfb->refcount == 1); } |
| bool IsWritable() const { return (refcount == 1 && vfb->refcount == 1); } |
| |
| |
| BYTE* GetWritePtr() const { |
| BYTE* GetWritePtr() const { |
| if (vfb->GetRefcount()>1) { |
| //Vit-Start: Hideous hack in lieu of proper multithreading fixes in AviSynth. Used to assert false on refcount > 1, now give it a second then carry on regardless... =/ |
| _ASSERT(FALSE); |
| int count = 20; |
| //throw AvisynthError("Internal Error - refcount was more than one!"); |
| while (vfb->GetRefcount()>1 && count-- > 0) { |
| |
| Sleep(50); |
| } |
| } |
| |
| //Vit-End |
| return IsWritable() ? (vfb->GetWritePtr() + offset) : 0; |
| return IsWritable() ? (vfb->GetWritePtr() + offset) : 0; |
| } |
| } |
| |
| |
| BYTE* GetWritePtr(int plane) const { |
| BYTE* GetWritePtr(int plane) const { |
| if (plane==PLANAR_Y) { |
| if (plane==PLANAR_Y) { |
| if (vfb->GetRefcount()>1) { |
| //Vit-Start: Hideous hack in lieu of proper multithreading fixes in AviSynth. Used to assert false on refcount > 1, now give it a second then carry on regardless... =/ |
| _ASSERT(FALSE); |
| int count = 20; |
| // throw AvisynthError("Internal Error - refcount was more than one!"); |
| while (vfb->GetRefcount()>1 && count-- > 0) { |
| |
| Sleep(50); |
| } |
| } |
| |
| //Vit-End |
| return IsWritable() ? vfb->GetWritePtr() + GetOffset(plane) : 0; |
| return IsWritable() ? vfb->GetWritePtr() + GetOffset(plane) : 0; |
| } |
| } |
| return vfb->data + GetOffset(plane); |
| return vfb->data + GetOffset(plane); |
| } |
| } |
| |
| |
| ~VideoFrame() { InterlockedDecrement(&vfb->refcount); } |
| ~VideoFrame() { VideoFrameBuffer* vfb_local = vfb; if (InterlockedDecrement(&refcount) >= 0) InterlockedDecrement(&vfb_local->refcount); } |
| }; |
| }; |
| |
| |
| enum { |
| enum { |
| CACHE_NOTHING=0, |
| CACHE_NOTHING=0, |
| CACHE_RANGE=1, |
| CACHE_RANGE=1, |
| CACHE_ALL=2, |
| CACHE_ALL=2, |
| CACHE_AUDIO=3, |
| CACHE_AUDIO=3, |
| CACHE_AUDIO_NONE=4, |
| CACHE_AUDIO_NONE=4, |
| CACHE_AUDIO_AUTO=5 |
| CACHE_AUDIO_AUTO=5 |
| }; |
| }; |
| |
| |
| // Base class for all filters. |
| // Base class for all filters. |
| class IClip { |
| class IClip { |
| friend class PClip; |
| friend class PClip; |
| friend class AVSValue; |
| friend class AVSValue; |
| int refcnt; |
| volatile long refcnt; |
| void AddRef() { InterlockedIncrement((long *)&refcnt); } |
| void AddRef() { InterlockedIncrement(&refcnt); } |
| void Release() { InterlockedDecrement((long *)&refcnt); if (!refcnt) delete this; } |
| void Release() { if (!InterlockedDecrement(&refcnt)) delete this; } |
| public: |
| public: |
| IClip() : refcnt(0) {} |
| IClip() : refcnt(0) {} |
| |
| |
| virtual int __stdcall GetVersion() { return AVISYNTH_INTERFACE_VERSION; } |
| virtual int __stdcall GetVersion() { return AVISYNTH_INTERFACE_VERSION; } |
| |
| |
| virtual PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env) = 0; |
| virtual PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env) = 0; |
| virtual bool __stdcall GetParity(int n) = 0; // return field parity if field_based, else parity of first field in frame |
| virtual bool __stdcall GetParity(int n) = 0; // return field parity if field_based, else parity of first field in frame |
| virtual void __stdcall GetAudio(void* buf, __int64 start, __int64 count, IScriptEnvironment* env) = 0; // start and count are in samples |
| virtual void __stdcall GetAudio(void* buf, __int64 start, __int64 count, IScriptEnvironment* env) = 0; // start and count are in samples |
| virtual void __stdcall SetCacheHints(int cachehints,int frame_range) = 0 ; // We do not pass cache requests upwards, only to the next filter. |
| virtual void __stdcall SetCacheHints(int cachehints,int frame_range) = 0 ; // We do not pass cache requests upwards, only to the next filter. |
| virtual const VideoInfo& __stdcall GetVideoInfo() = 0; |
| virtual const VideoInfo& __stdcall GetVideoInfo() = 0; |
| virtual __stdcall ~IClip() {} |
| virtual ~IClip() {} |
| }; |
| }; |
| |
| |
| |
| |
| // smart pointer to IClip |
| // smart pointer to IClip |
| class PClip { |
| class PClip { |
| |
| |
| IClip* p; |
| IClip* p; |
| |
| |
| IClip* GetPointerWithAddRef() const { if (p) p->AddRef(); return p; } |
| IClip* GetPointerWithAddRef() const { if (p) p->AddRef(); return p; } |
| friend class AVSValue; |
| friend class AVSValue; |
| friend class VideoFrame; |
| friend class VideoFrame; |
| |
| |
| void Init(IClip* x) { |
| void Init(IClip* x) { |
| if (x) x->AddRef(); |
| if (x) x->AddRef(); |
| p=x; |
| p=x; |
| } |
| } |
| void Set(IClip* x) { |
| void Set(IClip* x) { |
| if (x) x->AddRef(); |
| if (x) x->AddRef(); |
| if (p) p->Release(); |
| if (p) p->Release(); |
| p=x; |
| p=x; |
| } |
| } |
| |
| |
| public: |
| public: |
| PClip() { p = 0; } |
| PClip() { p = 0; } |
| PClip(const PClip& x) { Init(x.p); } |
| PClip(const PClip& x) { Init(x.p); } |
| PClip(IClip* x) { Init(x); } |
| PClip(IClip* x) { Init(x); } |
| void operator=(IClip* x) { Set(x); } |
| void operator=(IClip* x) { Set(x); } |
| void operator=(const PClip& x) { Set(x.p); } |
| void operator=(const PClip& x) { Set(x.p); } |
| |
| |
| IClip* operator->() const { return p; } |
| IClip* operator->() const { return p; } |
| |
| |
| // useful in conditional expressions |
| // useful in conditional expressions |
| operator void*() const { return p; } |
| operator void*() const { return p; } |
| bool operator!() const { return !p; } |
| bool operator!() const { return !p; } |
| |
| |
| ~PClip() { if (p) p->Release(); } |
| ~PClip() { if (p) p->Release(); } |
| }; |
| }; |
| |
| |
| |
| |
| // smart pointer to VideoFrame |
| // smart pointer to VideoFrame |
| class PVideoFrame { |
| class PVideoFrame { |
| |
| |
| VideoFrame* p; |
| VideoFrame* p; |
| |
| |
| void Init(VideoFrame* x) { |
| void Init(VideoFrame* x) { |
| if (x) x->AddRef(); |
| if (x) x->AddRef(); |
| p=x; |
| p=x; |
| } |
| } |
| void Set(VideoFrame* x) { |
| void Set(VideoFrame* x) { |
| if (x) x->AddRef(); |
| if (x) x->AddRef(); |
| if (p) p->Release(); |
| if (p) p->Release(); |
| p=x; |
| p=x; |
| } |
| } |
| |
| |
| public: |
| public: |
| PVideoFrame() { p = 0; } |
| PVideoFrame() { p = 0; } |
| PVideoFrame(const PVideoFrame& x) { Init(x.p); } |
| PVideoFrame(const PVideoFrame& x) { Init(x.p); } |
| PVideoFrame(VideoFrame* x) { Init(x); } |
| PVideoFrame(VideoFrame* x) { Init(x); } |
| void operator=(VideoFrame* x) { Set(x); } |
| void operator=(VideoFrame* x) { Set(x); } |
| void operator=(const PVideoFrame& x) { Set(x.p); } |
| void operator=(const PVideoFrame& x) { Set(x.p); } |
| |
| |
| VideoFrame* operator->() const { return p; } |
| VideoFrame* operator->() const { return p; } |
| |
| |
| // for conditional expressions |
| // for conditional expressions |
| operator void*() const { return p; } |
| operator void*() const { return p; } |
| bool operator!() const { return !p; } |
| bool operator!() const { return !p; } |
| |
| |
| ~PVideoFrame() { if (p) p->Release();} |
| ~PVideoFrame() { if (p) p->Release();} |
| }; |
| }; |
| |
| |
| |
| |
| class AVSValue { |
| class AVSValue { |
| public: |
| public: |
| |
| |
| AVSValue() { type = 'v'; } |
| AVSValue() { type = 'v'; } |
| AVSValue(IClip* c) { type = 'c'; clip = c; if (c) c->AddRef(); } |
| AVSValue(IClip* c) { type = 'c'; clip = c; if (c) c->AddRef(); } |
| AVSValue(const PClip& c) { type = 'c'; clip = c.GetPointerWithAddRef(); } |
| AVSValue(const PClip& c) { type = 'c'; clip = c.GetPointerWithAddRef(); } |
| AVSValue(bool b) { type = 'b'; boolean = b; } |
| AVSValue(bool b) { type = 'b'; boolean = b; } |
| AVSValue(int i) { type = 'i'; integer = i; } |
| AVSValue(int i) { type = 'i'; integer = i; } |
| // AVSValue(__int64 l) { type = 'l'; longlong = l; } |
| // AVSValue(__int64 l) { type = 'l'; longlong = l; } |
| AVSValue(float f) { type = 'f'; floating_pt = f; } |
| AVSValue(float f) { type = 'f'; floating_pt = f; } |
| AVSValue(double f) { type = 'f'; floating_pt = float(f); } |
| AVSValue(double f) { type = 'f'; floating_pt = float(f); } |
| AVSValue(const char* s) { type = 's'; string = s; } |
| AVSValue(const char* s) { type = 's'; string = s; } |
| AVSValue(const AVSValue* a, int size) { type = 'a'; array = a; array_size = size; } |
| AVSValue(const AVSValue* a, int size) { type = 'a'; array = a; array_size = size; } |
| AVSValue(const AVSValue& v) { Assign(&v, true); } |
| AVSValue(const AVSValue& v) { Assign(&v, true); } |
| |
| |
| ~AVSValue() { if (IsClip() && clip) clip->Release(); } |
| ~AVSValue() { if (IsClip() && clip) clip->Release(); } |
| AVSValue& operator=(const AVSValue& v) { Assign(&v, false); return *this; } |
| AVSValue& operator=(const AVSValue& v) { Assign(&v, false); return *this; } |
| |
| |
| // Note that we transparently allow 'int' to be treated as 'float'. |
| // Note that we transparently allow 'int' to be treated as 'float'. |
| // There are no int<->bool conversions, though. |
| // There are no int<->bool conversions, though. |
| |
| |
| bool Defined() const { return type != 'v'; } |
| bool Defined() const { return type != 'v'; } |
| bool IsClip() const { return type == 'c'; } |
| bool IsClip() const { return type == 'c'; } |
| bool IsBool() const { return type == 'b'; } |
| bool IsBool() const { return type == 'b'; } |
| bool IsInt() const { return type == 'i'; } |
| bool IsInt() const { return type == 'i'; } |
| // bool IsLong() const { return (type == 'l'|| type == 'i'); } |
| // bool IsLong() const { return (type == 'l'|| type == 'i'); } |
| bool IsFloat() const { return type == 'f' || type == 'i'; } |
| bool IsFloat() const { return type == 'f' || type == 'i'; } |
| bool IsString() const { return type == 's'; } |
| bool IsString() const { return type == 's'; } |
| bool IsArray() const { return type == 'a'; } |
| bool IsArray() const { return type == 'a'; } |
| |
| |
| PClip AsClip() const { _ASSERTE(IsClip()); return IsClip()?clip:0; } |
| PClip AsClip() const { _ASSERTE(IsClip()); return IsClip()?clip:0; } |
| bool AsBool() const { _ASSERTE(IsBool()); return boolean; } |
| bool AsBool() const { _ASSERTE(IsBool()); return boolean; } |
| int AsInt() const { _ASSERTE(IsInt()); return integer; } |
| int AsInt() const { _ASSERTE(IsInt()); return integer; } |
| // int AsLong() const { _ASSERTE(IsLong()); return longlong; } |
| // int AsLong() const { _ASSERTE(IsLong()); return longlong; } |
| const char* AsString() const { _ASSERTE(IsString()); return IsString()?string:0; } |
| const char* AsString() const { _ASSERTE(IsString()); return IsString()?string:0; } |
| double AsFloat() const { _ASSERTE(IsFloat()); return IsInt()?integer:floating_pt; } |
| double AsFloat() const { _ASSERTE(IsFloat()); return IsInt()?integer:floating_pt; } |
| |
| |
| bool AsBool(bool def) const { _ASSERTE(IsBool()||!Defined()); return IsBool() ? boolean : def; } |
| bool AsBool(bool def) const { _ASSERTE(IsBool()||!Defined()); return IsBool() ? boolean : def; } |
| int AsInt(int def) const { _ASSERTE(IsInt()||!Defined()); return IsInt() ? integer : def; } |
| int AsInt(int def) const { _ASSERTE(IsInt()||!Defined()); return IsInt() ? integer : def; } |
| double AsFloat(double def) const { _ASSERTE(IsFloat()||!Defined()); return IsInt() ? integer : type=='f' ? floating_pt : def; } |
| double AsFloat(double def) const { _ASSERTE(IsFloat()||!Defined()); return IsInt() ? integer : type=='f' ? floating_pt : def; } |
| const char* AsString(const char* def) const { _ASSERTE(IsString()||!Defined()); return IsString() ? string : def; } |
| const char* AsString(const char* def) const { _ASSERTE(IsString()||!Defined()); return IsString() ? string : def; } |
| |
| |
| int ArraySize() const { _ASSERTE(IsArray()); return IsArray()?array_size:1; } |
| int ArraySize() const { _ASSERTE(IsArray()); return IsArray()?array_size:1; } |
| |
| |
| const AVSValue& operator[](int index) const { |
| const AVSValue& operator[](int index) const { |
| _ASSERTE(IsArray() && index>=0 && index<array_size); |
| _ASSERTE(IsArray() && index>=0 && index<array_size); |
| return (IsArray() && index>=0 && index<array_size) ? array[index] : *this; |
| return (IsArray() && index>=0 && index<array_size) ? array[index] : *this; |
| } |
| } |
| |
| |
| private: |
| private: |
| |
| |
| short type; // 'a'rray, 'c'lip, 'b'ool, 'i'nt, 'f'loat, 's'tring, 'v'oid, or 'l'ong |
| short type; // 'a'rray, 'c'lip, 'b'ool, 'i'nt, 'f'loat, 's'tring, 'v'oid, or 'l'ong |
| short array_size; |
| short array_size; |
| union { |
| union { |
| IClip* clip; |
| IClip* clip; |
| bool boolean; |
| bool boolean; |
| int integer; |
| int integer; |
| float floating_pt; |
| float floating_pt; |
| const char* string; |
| const char* string; |
| const AVSValue* array; |
| const AVSValue* array; |
| // __int64 longlong; |
| // __int64 longlong; |
| }; |
| }; |
| |
| |
| void Assign(const AVSValue* src, bool init) { |
| void Assign(const AVSValue* src, bool init) { |
| if (src->IsClip() && src->clip) |
| if (src->IsClip() && src->clip) |
| src->clip->AddRef(); |
| src->clip->AddRef(); |
| if (!init && IsClip() && clip) |
| if (!init && IsClip() && clip) |
| clip->Release(); |
| clip->Release(); |
| // make sure this copies the whole struct! |
| // make sure this copies the whole struct! |
| ((__int32*)this)[0] = ((__int32*)src)[0]; |
| ((__int32*)this)[0] = ((__int32*)src)[0]; |
| ((__int32*)this)[1] = ((__int32*)src)[1]; |
| ((__int32*)this)[1] = ((__int32*)src)[1]; |
| } |
| } |
| }; |
| }; |
| |
| |
| |
| |
| // instantiable null filter |
| // instantiable null filter |
| class GenericVideoFilter : public IClip { |
| class GenericVideoFilter : public IClip { |
| protected: |
| protected: |
| PClip child; |
| PClip child; |
| VideoInfo vi; |
| VideoInfo vi; |
| public: |
| public: |
| GenericVideoFilter(PClip _child) : child(_child) { vi = child->GetVideoInfo(); } |
| GenericVideoFilter(PClip _child) : child(_child) { vi = child->GetVideoInfo(); } |
| PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env) { return child->GetFrame(n, env); } |
| PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env) { return child->GetFrame(n, env); } |
| void __stdcall GetAudio(void* buf, __int64 start, __int64 count, IScriptEnvironment* env) { child->GetAudio(buf, start, count, env); } |
| void __stdcall GetAudio(void* buf, __int64 start, __int64 count, IScriptEnvironment* env) { child->GetAudio(buf, start, count, env); } |
| const VideoInfo& __stdcall GetVideoInfo() { return vi; } |
| const VideoInfo& __stdcall GetVideoInfo() { return vi; } |
| bool __stdcall GetParity(int n) { return child->GetParity(n); } |
| bool __stdcall GetParity(int n) { return child->GetParity(n); } |
| void __stdcall SetCacheHints(int cachehints,int frame_range) { } ; // We do not pass cache requests upwards, only to the next filter. |
| void __stdcall SetCacheHints(int cachehints,int frame_range) { } ; // We do not pass cache requests upwards, only to the next filter. |
| }; |
| }; |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| /* Helper classes useful to plugin authors */ |
| /* Helper classes useful to plugin authors */ |
| |
| |
| class AlignPlanar : public GenericVideoFilter |
| class AlignPlanar : public GenericVideoFilter |
| { |
| { |
| public: |
| public: |
| AlignPlanar(PClip _clip); |
| AlignPlanar(PClip _clip); |
| static PClip Create(PClip clip); |
| static PClip Create(PClip clip); |
| PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env); |
| PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env); |
| }; |
| }; |
| |
| |
| |
| |
| |
| |
| class FillBorder : public GenericVideoFilter |
| class FillBorder : public GenericVideoFilter |
| { |
| { |
| public: |
| public: |
| FillBorder(PClip _clip); |
| FillBorder(PClip _clip); |
| static PClip Create(PClip clip); |
| static PClip Create(PClip clip); |
| PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env); |
| PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env); |
| }; |
| }; |
| |
| |
| |
| |
| |
| |
| class ConvertAudio : public GenericVideoFilter |
| class ConvertAudio : public GenericVideoFilter |
| /** |
| /** |
| * Helper class to convert audio to any format |
| * Helper class to convert audio to any format |
| **/ |
| **/ |
| { |
| { |
| public: |
| public: |
| ConvertAudio(PClip _clip, int prefered_format); |
| ConvertAudio(PClip _clip, int prefered_format); |
| void __stdcall GetAudio(void* buf, __int64 start, __int64 count, IScriptEnvironment* env); |
| void __stdcall GetAudio(void* buf, __int64 start, __int64 count, IScriptEnvironment* env); |
| void __stdcall SetCacheHints(int cachehints,int frame_range); // We do pass cache requests upwards, to the cache! |
| void __stdcall SetCacheHints(int cachehints,int frame_range); // We do pass cache requests upwards, to the cache! |
| |
| |
| static PClip Create(PClip clip, int sample_type, int prefered_type); |
| static PClip Create(PClip clip, int sample_type, int prefered_type); |
| static AVSValue __cdecl Create_float(AVSValue args, void*, IScriptEnvironment*); |
| static AVSValue __cdecl Create_float(AVSValue args, void*, IScriptEnvironment*); |
| static AVSValue __cdecl Create_32bit(AVSValue args, void*, IScriptEnvironment*); |
| static AVSValue __cdecl Create_32bit(AVSValue args, void*, IScriptEnvironment*); |
| static AVSValue __cdecl Create_24bit(AVSValue args, void*, IScriptEnvironment*); |
| static AVSValue __cdecl Create_24bit(AVSValue args, void*, IScriptEnvironment*); |
| static AVSValue __cdecl Create_16bit(AVSValue args, void*, IScriptEnvironment*); |
| static AVSValue __cdecl Create_16bit(AVSValue args, void*, IScriptEnvironment*); |
| static AVSValue __cdecl Create_8bit (AVSValue args, void*, IScriptEnvironment*); |
| static AVSValue __cdecl Create_8bit (AVSValue args, void*, IScriptEnvironment*); |
| static AVSValue __cdecl Create_Any (AVSValue args, void*, IScriptEnvironment*); |
| static AVSValue __cdecl Create_Any (AVSValue args, void*, IScriptEnvironment*); |
| virtual ~ConvertAudio(); |
| virtual ~ConvertAudio(); |
| |
| |
| private: |
| private: |
| void convertToFloat(char* inbuf, float* outbuf, char sample_type, int count); |
| void convertToFloat(char* inbuf, float* outbuf, char sample_type, int count); |
| void convertToFloat_3DN(char* inbuf, float* outbuf, char sample_type, int count); |
| void convertToFloat_3DN(char* inbuf, float* outbuf, char sample_type, int count); |
| void convertToFloat_SSE(char* inbuf, float* outbuf, char sample_type, int count); |
| void convertToFloat_SSE(char* inbuf, float* outbuf, char sample_type, int count); |
| void convertToFloat_SSE2(char* inbuf, float* outbuf, char sample_type, int count); |
| void convertToFloat_SSE2(char* inbuf, float* outbuf, char sample_type, int count); |
| void convertFromFloat(float* inbuf, void* outbuf, char sample_type, int count); |
| void convertFromFloat(float* inbuf, void* outbuf, char sample_type, int count); |
| void convertFromFloat_3DN(float* inbuf, void* outbuf, char sample_type, int count); |
| void convertFromFloat_3DN(float* inbuf, void* outbuf, char sample_type, int count); |
| void convertFromFloat_SSE(float* inbuf, void* outbuf, char sample_type, int count); |
| void convertFromFloat_SSE(float* inbuf, void* outbuf, char sample_type, int count); |
| void convertFromFloat_SSE2(float* inbuf, void* outbuf, char sample_type, int count); |
| void convertFromFloat_SSE2(float* inbuf, void* outbuf, char sample_type, int count); |
| |
| |
| __inline int Saturate_int8(float n); |
| __inline int Saturate_int8(float n); |
| __inline short Saturate_int16(float n); |
| __inline short Saturate_int16(float n); |
| __inline int Saturate_int24(float n); |
| __inline int Saturate_int24(float n); |
| __inline int Saturate_int32(float n); |
| __inline int Saturate_int32(float n); |
| |
| |
| char src_format; |
| char src_format; |
| char dst_format; |
| char dst_format; |
| int src_bps; |
| int src_bps; |
| char *tempbuffer; |
| char *tempbuffer; |
| SFLOAT *floatbuffer; |
| SFLOAT *floatbuffer; |
| int tempbuffer_size; |
| int tempbuffer_size; |
| }; |
| }; |
| |
| |
| |
| |
| // For GetCPUFlags. These are backwards-compatible with those in VirtualDub. |
| // For GetCPUFlags. These are backwards-compatible with those in VirtualDub. |
| enum { |
| enum { |
| /* slowest CPU to support extension */ |
| /* slowest CPU to support extension */ |
| CPUF_FORCE = 0x01, // N/A |
| CPUF_FORCE = 0x01, // N/A |
| CPUF_FPU = 0x02, // 386/486DX |
| CPUF_FPU = 0x02, // 386/486DX |
| CPUF_MMX = 0x04, // P55C, K6, PII |
| CPUF_MMX = 0x04, // P55C, K6, PII |
| CPUF_INTEGER_SSE = 0x08, // PIII, Athlon |
| CPUF_INTEGER_SSE = 0x08, // PIII, Athlon |
| CPUF_SSE = 0x10, // PIII, Athlon XP/MP |
| CPUF_SSE = 0x10, // PIII, Athlon XP/MP |
| CPUF_SSE2 = 0x20, // PIV, Hammer |
| CPUF_SSE2 = 0x20, // PIV, Hammer |
| CPUF_3DNOW = 0x40, // K6-2 |
| CPUF_3DNOW = 0x40, // K6-2 |
| CPUF_3DNOW_EXT = 0x80, // Athlon |
| CPUF_3DNOW_EXT = 0x80, // Athlon |
| CPUF_X86_64 = 0xA0, // Hammer (note: equiv. to 3DNow + SSE2, which |
| CPUF_X86_64 = 0xA0, // Hammer (note: equiv. to 3DNow + SSE2, which |
| // only Hammer will have anyway) |
| // only Hammer will have anyway) |
| CPUF_SSE3 = 0x100, // PIV+, Hammer |
| CPUF_SSE3 = 0x100, // PIV+, Hammer |
| }; |
| }; |
| #define MAX_INT 0x7fffffff |
| #define MAX_INT 0x7fffffff |
| #define MIN_INT -0x7fffffff // ::FIXME:: research why this is not 0x80000000 |
| #define MIN_INT -0x7fffffff // ::FIXME:: research why this is not 0x80000000 |
| |
| |
| |
| |
| |
| |
| |
| class IClipLocalStorage; |
| |
| |
| class IScriptEnvironment { |
| class IScriptEnvironment { |
| public: |
| public: |
| virtual __stdcall ~IScriptEnvironment() {} |
| virtual ~IScriptEnvironment() {} |
| |
| |
| virtual /*static*/ long __stdcall GetCPUFlags() = 0; |
| virtual /*static*/ long __stdcall GetCPUFlags() = 0; |
| |
| |
| virtual char* __stdcall SaveString(const char* s, int length = -1) = 0; |
| virtual char* __stdcall SaveString(const char* s, int length = -1) = 0; |
| virtual char* __stdcall Sprintf(const char* fmt, ...) = 0; |
| virtual char* __stdcall Sprintf(const char* fmt, ...) = 0; |
| // note: val is really a va_list; I hope everyone typedefs va_list to a pointer |
| // note: val is really a va_list; I hope everyone typedefs va_list to a pointer |
| virtual char* __stdcall VSprintf(const char* fmt, void* val) = 0; |
| virtual char* __stdcall VSprintf(const char* fmt, void* val) = 0; |
| |
| |
| __declspec(noreturn) virtual void __stdcall ThrowError(const char* fmt, ...) = 0; |
| __declspec(noreturn) virtual void __stdcall ThrowError(const char* fmt, ...) = 0; |
| |
| |
| class NotFound /*exception*/ {}; // thrown by Invoke and GetVar |
| class NotFound /*exception*/ {}; // thrown by Invoke and GetVar |
| |
| |
| typedef AVSValue (__cdecl *ApplyFunc)(AVSValue args, void* user_data, IScriptEnvironment* env); |
| typedef AVSValue (__cdecl *ApplyFunc)(AVSValue args, void* user_data, IScriptEnvironment* env); |
| |
| |
| virtual void __stdcall AddFunction(const char* name, const char* params, ApplyFunc apply, void* user_data) = 0; |
| virtual void __stdcall AddFunction(const char* name, const char* params, ApplyFunc apply, void* user_data) = 0; |
| virtual bool __stdcall FunctionExists(const char* name) = 0; |
| virtual bool __stdcall FunctionExists(const char* name) = 0; |
| virtual AVSValue __stdcall Invoke(const char* name, const AVSValue args, const char** arg_names=0) = 0; |
| virtual AVSValue __stdcall Invoke(const char* name, const AVSValue args, const char** arg_names=0) = 0; |
| |
| |
| virtual AVSValue __stdcall GetVar(const char* name) = 0; |
| virtual AVSValue __stdcall GetVar(const char* name) = 0; |
| virtual bool __stdcall SetVar(const char* name, const AVSValue& val) = 0; |
| virtual bool __stdcall SetVar(const char* name, const AVSValue& val) = 0; |
| virtual bool __stdcall SetGlobalVar(const char* name, const AVSValue& val) = 0; |
| virtual bool __stdcall SetGlobalVar(const char* name, const AVSValue& val) = 0; |
| |
| |
| virtual void __stdcall PushContext(int level=0) = 0; |
| virtual void __stdcall PushContext(int level=0) = 0; |
| virtual void __stdcall PopContext() = 0; |
| virtual void __stdcall PopContext() = 0; |
| |
| |
| // align should be 4 or 8 |
| // align should be 4 or 8 |
| virtual PVideoFrame __stdcall NewVideoFrame(const VideoInfo& vi, int align=FRAME_ALIGN) = 0; |
| virtual PVideoFrame __stdcall NewVideoFrame(const VideoInfo& vi, int align=FRAME_ALIGN) = 0; |
| |
| |
| virtual bool __stdcall MakeWritable(PVideoFrame* pvf) = 0; |
| virtual bool __stdcall MakeWritable(PVideoFrame* pvf) = 0; |
| |
| |
| virtual /*static*/ void __stdcall BitBlt(BYTE* dstp, int dst_pitch, const BYTE* srcp, int src_pitch, int row_size, int height) = 0; |
| virtual /*static*/ void __stdcall BitBlt(BYTE* dstp, int dst_pitch, const BYTE* srcp, int src_pitch, int row_size, int height) = 0; |
| |
| |
| typedef void (__cdecl *ShutdownFunc)(void* user_data, IScriptEnvironment* env); |
| typedef void (__cdecl *ShutdownFunc)(void* user_data, IScriptEnvironment* env); |
| virtual void __stdcall AtExit(ShutdownFunc function, void* user_data) = 0; |
| virtual void __stdcall AtExit(ShutdownFunc function, void* user_data) = 0; |
| |
| |
| virtual void __stdcall CheckVersion(int version = AVISYNTH_INTERFACE_VERSION) = 0; |
| virtual void __stdcall CheckVersion(int version = AVISYNTH_INTERFACE_VERSION) = 0; |
| |
| |
| virtual PVideoFrame __stdcall Subframe(PVideoFrame src, int rel_offset, int new_pitch, int new_row_size, int new_height) = 0; |
| virtual PVideoFrame __stdcall Subframe(PVideoFrame src, int rel_offset, int new_pitch, int new_row_size, int new_height) = 0; |
| |
| |
| virtual int __stdcall SetMemoryMax(int mem) = 0; |
| virtual int __stdcall SetMemoryMax(int mem) = 0; |
| |
| |
| virtual int __stdcall SetWorkingDir(const char * newdir) = 0; |
| virtual int __stdcall SetWorkingDir(const char * newdir) = 0; |
| |
| |
| virtual void* __stdcall ManageCache(int key, void* data) = 0; |
| virtual void* __stdcall ManageCache(int key, void* data) = 0; |
| |
| |
| enum PlanarChromaAlignmentMode { |
| enum PlanarChromaAlignmentMode { |
| PlanarChromaAlignmentOff, |
| PlanarChromaAlignmentOff, |
| PlanarChromaAlignmentOn, |
| PlanarChromaAlignmentOn, |
| PlanarChromaAlignmentTest }; |
| PlanarChromaAlignmentTest }; |
| |
| |
| virtual bool __stdcall PlanarChromaAlignment(PlanarChromaAlignmentMode key) = 0; |
| virtual bool __stdcall PlanarChromaAlignment(PlanarChromaAlignmentMode key) = 0; |
| |
| |
| virtual PVideoFrame __stdcall SubframePlanar(PVideoFrame src, int rel_offset, int new_pitch, int new_row_size, int new_height, int rel_offsetU, int rel_offsetV, int new_pitchUV) = 0; |
| virtual PVideoFrame __stdcall SubframePlanar(PVideoFrame src, int rel_offset, int new_pitch, int new_row_size, int new_height, int rel_offsetU, int rel_offsetV, int new_pitchUV) = 0; |
| |
| |
| |
| virtual void __stdcall SetMTMode(int mode,int threads,bool temporary)=0; |
| |
| virtual int __stdcall GetMTMode(bool return_nthreads)=0; |
| |
| |
| |
| virtual IClipLocalStorage* __stdcall AllocClipLocalStorage()=0; |
| |
| |
| |
| virtual void __stdcall SaveClipLocalStorage()=0; |
| |
| virtual void __stdcall RestoreClipLocalStorage()=0; |
| }; |
| }; |
| |
| |
| |
| |
| // avisynth.dll exports this; it's a way to use it as a library, without |
| // avisynth.dll exports this; it's a way to use it as a library, without |
| // writing an AVS script or without going through AVIFile. |
| // writing an AVS script or without going through AVIFile. |
| IScriptEnvironment* __stdcall CreateScriptEnvironment(int version = AVISYNTH_INTERFACE_VERSION); |
| IScriptEnvironment* __stdcall CreateScriptEnvironment(int version = AVISYNTH_INTERFACE_VERSION); |
| |
| |
| |
| |
| #pragma pack(pop) |
| #pragma pack(pop) |
| |
| |
| #endif //__AVISYNTH_H__ |
| #endif //__AVISYNTH_H__ |
| |
| |