changeset 809:ceded0279117

Merged in deepthidevaki/xhevc_deepthid (pull request #91) Added new IPFilter function pointers. Added TestSuite for new IPFilter primitives.
author nandaku2 <deepthi@multicorewareinc.com>
date Thu, 25 Apr 2013 15:35:32 +0530
parents 93dcae8999dd (current diff) 81b6dda66506 (diff)
children 0004001ac17b 995b6235dffc 8079c95648f2
files
diffstat 5 files changed, 557 insertions(+-), 7 deletions(-) [+]
line wrap: on
line diff
--- a/source/encoder/InterpolationFilter.cpp	Thu Apr 25 15:33:24 2013 +0530
+++ b/source/encoder/InterpolationFilter.cpp	Thu Apr 25 15:35:32 2013 +0530
@@ -24,6 +24,7 @@
 
 #include "InterpolationFilter.h"
 #include <cstring>
+#include <assert.h>
 
 #if _MSC_VER
 #pragma warning(disable: 4127) // conditional expression is constant, typical for templated functions
@@ -31,9 +32,9 @@
 #endif
 
 template<int N>
-void filterVertical_short_pel(int bit_Depth, short *src, int srcStride, Pel *dst, int dstStride, int width, int height, short const *coeff)
+void filterVertical_short_pel(int bitDepth, short *src, int srcStride, Pel *dst, int dstStride, int width, int height, short const *coeff)
 {
-    int bitDepth = 8;   //assuming bitDepth = 8
+    assert(bitDepth == 8);   //assuming bitDepth = 8
 
     int cStride = srcStride;
 
@@ -88,9 +89,10 @@ void filterVertical_short_pel(int bit_De
 }
 
 template<int N>
-void filterHorizontal_pel_pel(int bit_Depth, Pel *src, int srcStride, Pel *dst, int dstStride, int width, int height, short const *coeff)
+void filterHorizontal_pel_pel(int bitDepth, Pel *src, int srcStride, Pel *dst, int dstStride, int width, int height, short const *coeff)
 {
-    int bitDepth = 8;
+    assert(bitDepth == 8);
+
     int cStride = 1;
 
     src -= (N / 2 - 1) * cStride;
@@ -139,9 +141,9 @@ void filterHorizontal_pel_pel(int bit_De
 }
 
 template<int N>
-void filterHorizontal_pel_short(int bit_Depth, Pel *src, int srcStride, short *dst, int dstStride, int width, int height, short const *coeff)
+void filterHorizontal_pel_short(int bitDepth, Pel *src, int srcStride, short *dst, int dstStride, int width, int height, short const *coeff)
 {
-    int bitDepth = 8; //assuming bitdepth = 8
+    assert(bitDepth == 8); //assuming bitdepth = 8
 
     int cStride = 1;
 
@@ -203,6 +205,8 @@ void filterCopy(Pel *src, int srcStride,
 
 void filterConvertShortToPel(int bitDepth, short *src, int srcStride, Pel *dst, int dstStride, int width, int height)
 {
+    assert(bitDepth == 8);
+
     int shift = IF_INTERNAL_PREC - bitDepth;
     short offset = IF_INTERNAL_OFFS;
 
@@ -228,6 +232,8 @@ void filterConvertShortToPel(int bitDept
 
 void filterConvertPelToShort(int bitDepth, Pel *src, int srcStride, short *dst, int dstStride, int width, int height)
 {
+    assert(bitDepth == 8);
+
     int shift = IF_INTERNAL_PREC - bitDepth;
     int row, col;
 
--- a/source/encoder/primitives.h	Thu Apr 25 15:33:24 2013 +0530
+++ b/source/encoder/primitives.h	Thu Apr 25 15:35:32 2013 +0530
@@ -131,6 +131,27 @@ enum Butterflies
     NUM_BUTTERFLIES
 };
 
+enum IPFilterConf_P_P
+{
+    FILTER_H_P_P_8,
+    FILTER_H_P_P_4,
+    NUM_IPFILTER_P_P
+};
+
+enum IPFilterConf_P_S
+{
+    FILTER_H_P_S_8,
+    FILTER_H_P_S_4,
+    NUM_IPFILTER_P_S
+};
+
+enum IPFilterConf_S_P
+{
+    FILTER_V_S_P_8,
+    FILTER_V_S_P_4,
+    NUM_IPFILTER_S_P
+};
+
 // Returns a Partitions enum if the size matches a supported performance primitive,
 // else returns -1 (in which case you should use the slow path)
 int PartitionFromSizes(int Width, int Height);
@@ -140,6 +161,11 @@ typedef void (CDECL * mbdst)(short *bloc
 typedef void (CDECL * IPFilter)(const short *coeff, short *src, int srcStride, short *dst, int dstStride, int block_width,
                                 int block_height, int bitDepth);
 typedef void (CDECL * butterfly)(short *src, short *dst, int shift, int line);
+typedef void (CDECL * IPFilter_p_p)(int bit_Depth, pixel *src, int srcStride, pixel *dst, int dstStride, int width, int height, short const *coeff);
+typedef void (CDECL * IPFilter_p_s)(int bit_Depth, pixel *src, int srcStride, short *dst, int dstStride, int width, int height, short const *coeff);
+typedef void (CDECL * IPFilter_s_p)(int bit_Depth, short *src, int srcStride, pixel *dst, int dstStride, int width, int height, short const *coeff);
+typedef void (CDECL * IPFilterConvert_p_s)(int bit_Depth, pixel *src, int srcStride, short *dst, int dstStride, int width, int height);
+typedef void (CDECL * IPFilterConvert_s_p)(int bit_Depth, short *src, int srcStride, pixel *dst, int dstStride, int width, int height);
 
 /* Define a structure containing function pointers to optimized encoder
  * primitives.  Each pointer can reference either an assembly routine,
@@ -154,6 +180,11 @@ struct EncoderPrimitives
     IPFilter filter[NUM_FILTER];
     mbdst inversedst;
     butterfly partial_butterfly[NUM_BUTTERFLIES];
+    IPFilter_p_p ipFilter_p_p[NUM_IPFILTER_P_P];
+    IPFilter_p_s ipFilter_p_s[NUM_IPFILTER_P_S];
+    IPFilter_s_p ipFilter_s_p[NUM_IPFILTER_S_P];
+    IPFilterConvert_p_s ipfilterConvert_p_s;
+    IPFilterConvert_s_p ipfilterConvert_s_p;
 };
 
 /* This copy of the table is what gets used by all by the encoder.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/test/ipfilterharness.cpp	Thu Apr 25 15:35:32 2013 +0530
@@ -0,0 +1,450 @@
+/*****************************************************************************
+ * Copyright (C) 2013 x265 project
+ *
+ * Authors: Deepthi Devaki <deepthidevaki@multicorewareinc.com>,
+ *          Rajesh Paulraj <rajesh@multicorewareinc.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
+ *
+ * This program is also available under a commercial proprietary license.
+ * For more information, contact us at licensing@multicorewareinc.com.
+ *****************************************************************************/
+
+#include "ipfilterharness.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+using namespace x265;
+
+const short m_lumaFilter[4][8] =
+{
+    { 0, 0,   0, 64,  0,   0, 0,  0 },
+    { -1, 4, -10, 58, 17,  -5, 1,  0 },
+    { -1, 4, -11, 40, 40, -11, 4, -1 },
+    { 0, 1,  -5, 17, 58, -10, 4, -1 }
+};
+
+IPFilterHarness::IPFilterHarness()
+{
+    ipf_t_size = 200 * 200;
+    pixel_buff = (pixel*)malloc(ipf_t_size * sizeof(pixel));     // Assuming max_height = max_width = max_srcStride = max_dstStride = 100
+    short_buff = (short*)malloc(ipf_t_size * sizeof(short));
+    IPF_vec_output_s = (short*)malloc(ipf_t_size * sizeof(short)); // Output Buffer1
+    IPF_C_output_s = (short*)malloc(ipf_t_size * sizeof(short));   // Output Buffer2
+    IPF_vec_output_p = (pixel*)malloc(ipf_t_size * sizeof(pixel)); // Output Buffer1
+    IPF_C_output_p = (pixel*)malloc(ipf_t_size * sizeof(pixel));   // Output Buffer2
+
+    if (!pixel_buff || !short_buff || !IPF_vec_output_s || !IPF_vec_output_p || !IPF_C_output_s || !IPF_C_output_p)
+    {
+        fprintf(stderr, "init_IPFilter_buffers: malloc failed, unable to initiate tests!\n");
+        exit(-1);
+    }
+
+    for (int i = 0; i < ipf_t_size; i++)                         // Initialize input buffer
+    {
+        int isPositive = rand() & 1;                             // To randomly generate Positive and Negative values
+        isPositive = (isPositive) ? 1 : -1;
+        pixel_buff[i] = (rand() &  PIXEL_MAX);
+        short_buff[i] = (isPositive) * (rand() &  SHRT_MAX);
+    }
+}
+
+IPFilterHarness::~IPFilterHarness()
+{
+    free(IPF_vec_output_s);
+    free(IPF_C_output_s);
+    free(IPF_vec_output_p);
+    free(IPF_C_output_p);
+    free(short_buff);
+    free(pixel_buff);
+}
+
+bool IPFilterHarness::check_IPFilter_primitive(x265::IPFilter_p_p ref, x265::IPFilter_p_p opt)
+{
+    int rand_height = rand() % 100;                 // Randomly generated Height
+    int rand_width = rand() % 100;                  // Randomly generated Width
+    short rand_val, rand_srcStride, rand_dstStride;
+
+    for (int i = 0; i <= 100; i++)
+    {
+        memset(IPF_vec_output_p, 0, ipf_t_size);      // Initialize output buffer to zero
+        memset(IPF_C_output_p, 0, ipf_t_size);        // Initialize output buffer to zero
+
+        rand_val = rand() % 4;                     // Random offset in the filter
+        rand_srcStride = rand() % 100;              // Randomly generated srcStride
+        rand_dstStride = rand() % 100;              // Randomly generated dstStride
+
+        opt(8, pixel_buff + 3 * rand_srcStride,
+            rand_srcStride,
+            IPF_vec_output_p,
+            rand_dstStride,
+            rand_width,
+            rand_height,  m_lumaFilter[rand_val]
+            );
+        ref(8, pixel_buff + 3 * rand_srcStride,
+            rand_srcStride,
+            IPF_C_output_p,
+            rand_dstStride,
+            rand_width,
+            rand_height,  m_lumaFilter[rand_val]
+            );
+
+        if (memcmp(IPF_vec_output_p, IPF_C_output_p, ipf_t_size))
+            return false;
+    }
+
+    return true;
+}
+
+bool IPFilterHarness::check_IPFilter_primitive(x265::IPFilter_p_s ref, x265::IPFilter_p_s opt)
+{
+    int rand_height = rand() % 100;                 // Randomly generated Height
+    int rand_width = rand() % 100;                  // Randomly generated Width
+    short rand_val, rand_srcStride, rand_dstStride;
+
+    for (int i = 0; i <= 100; i++)
+    {
+        memset(IPF_vec_output_s, 0, ipf_t_size);      // Initialize output buffer to zero
+        memset(IPF_C_output_s, 0, ipf_t_size);        // Initialize output buffer to zero
+
+        rand_val = rand() % 4;                     // Random offset in the filter
+        rand_srcStride = rand() % 100;              // Randomly generated srcStride
+        rand_dstStride = rand() % 100;              // Randomly generated dstStride
+
+        opt(8, pixel_buff + 3 * rand_srcStride,
+            rand_srcStride,
+            IPF_vec_output_s,
+            rand_dstStride,
+            rand_width,
+            rand_height,  m_lumaFilter[rand_val]
+            );
+        ref(8, pixel_buff + 3 * rand_srcStride,
+            rand_srcStride,
+            IPF_C_output_s,
+            rand_dstStride,
+            rand_width,
+            rand_height,  m_lumaFilter[rand_val]
+            );
+
+        if (memcmp(IPF_vec_output_s, IPF_C_output_s, ipf_t_size))
+            return false;
+    }
+
+    return true;
+}
+
+bool IPFilterHarness::check_IPFilter_primitive(x265::IPFilter_s_p ref, x265::IPFilter_s_p opt)
+{
+    int rand_height = rand() % 100;                 // Randomly generated Height
+    int rand_width = rand() % 100;                  // Randomly generated Width
+    short rand_val, rand_srcStride, rand_dstStride;
+
+    for (int i = 0; i <= 100; i++)
+    {
+        memset(IPF_vec_output_p, 0, ipf_t_size);      // Initialize output buffer to zero
+        memset(IPF_C_output_p, 0, ipf_t_size);        // Initialize output buffer to zero
+
+        rand_val = rand() % 4;                     // Random offset in the filter
+        rand_srcStride = rand() % 100;              // Randomly generated srcStride
+        rand_dstStride = rand() % 100;              // Randomly generated dstStride
+
+        opt(8, short_buff + 3 * rand_srcStride,
+            rand_srcStride,
+            IPF_vec_output_p,
+            rand_dstStride,
+            rand_width,
+            rand_height,  m_lumaFilter[rand_val]
+            );
+        ref(8, short_buff + 3 * rand_srcStride,
+            rand_srcStride,
+            IPF_C_output_p,
+            rand_dstStride,
+            rand_width,
+            rand_height,  m_lumaFilter[rand_val]
+            );
+
+        if (memcmp(IPF_vec_output_p, IPF_C_output_p, ipf_t_size))
+            return false;
+    }
+
+    return true;
+}
+
+bool IPFilterHarness::check_IPFilter_primitive(x265::IPFilterConvert_p_s ref, x265::IPFilterConvert_p_s opt)
+{
+    int rand_height = rand() % 100;                 // Randomly generated Height
+    int rand_width = rand() % 100;                  // Randomly generated Width
+    short rand_val, rand_srcStride, rand_dstStride;
+
+    for (int i = 0; i <= 100; i++)
+    {
+        memset(IPF_vec_output_p, 0, ipf_t_size);      // Initialize output buffer to zero
+        memset(IPF_C_output_p, 0, ipf_t_size);        // Initialize output buffer to zero
+
+        rand_val = rand() % 4;                     // Random offset in the filter
+        rand_srcStride = rand() % 100;              // Randomly generated srcStride
+        rand_dstStride = rand() % 100;              // Randomly generated dstStride
+
+        opt(8, pixel_buff,
+            rand_srcStride,
+            IPF_vec_output_s,
+            rand_dstStride,
+            rand_width,
+            rand_height);
+        ref(8, pixel_buff,
+            rand_srcStride,
+            IPF_C_output_s,
+            rand_dstStride,
+            rand_width,
+            rand_height);
+
+        if (memcmp(IPF_vec_output_p, IPF_C_output_p, ipf_t_size))
+            return false;
+    }
+
+    return true;
+}
+
+bool IPFilterHarness::check_IPFilter_primitive(x265::IPFilterConvert_s_p ref, x265::IPFilterConvert_s_p opt)
+{
+    int rand_height = rand() % 100;                 // Randomly generated Height
+    int rand_width = rand() % 100;                  // Randomly generated Width
+    short rand_val, rand_srcStride, rand_dstStride;
+
+    for (int i = 0; i <= 100; i++)
+    {
+        memset(IPF_vec_output_p, 0, ipf_t_size);      // Initialize output buffer to zero
+        memset(IPF_C_output_p, 0, ipf_t_size);        // Initialize output buffer to zero
+
+        rand_val = rand() % 4;                     // Random offset in the filter
+        rand_srcStride = rand() % 100;              // Randomly generated srcStride
+        rand_dstStride = rand() % 100;              // Randomly generated dstStride
+
+        opt(8, short_buff,
+            rand_srcStride,
+            IPF_vec_output_p,
+            rand_dstStride,
+            rand_width,
+            rand_height);
+        ref(8, short_buff,
+            rand_srcStride,
+            IPF_C_output_p,
+            rand_dstStride,
+            rand_width,
+            rand_height);
+
+        if (memcmp(IPF_vec_output_p, IPF_C_output_p, ipf_t_size))
+            return false;
+    }
+
+    return true;
+}
+
+bool IPFilterHarness::testCorrectness(const EncoderPrimitives& ref, const EncoderPrimitives& opt)
+{
+    for (int value = 0; value < NUM_IPFILTER_P_P; value++)
+    {
+        if (opt.ipFilter_p_p[value])
+        {
+            if (!check_IPFilter_primitive(ref.ipFilter_p_p[value], opt.ipFilter_p_p[value]))
+            {
+                printf("\nfilter_H_P_P_%d failed\n", 8 / (value + 1));
+                return false;
+            }
+        }
+    }
+
+    for (int value = 0; value < NUM_IPFILTER_P_S; value++)
+    {
+        if (opt.ipFilter_p_s[value])
+        {
+            if (!check_IPFilter_primitive(ref.ipFilter_p_s[value], opt.ipFilter_p_s[value]))
+            {
+                printf("\nfilter_H_P_S_%d failed\n", 8 / (value + 1));
+                return false;
+            }
+        }
+    }
+
+    for (int value = 0; value < NUM_IPFILTER_S_P; value++)
+    {
+        if (opt.ipFilter_s_p[value])
+        {
+            if (!check_IPFilter_primitive(ref.ipFilter_s_p[value], opt.ipFilter_s_p[value]))
+            {
+                printf("\nfilter_H_S_P_%d failed\n", 8 / (value + 1));
+                return false;
+            }
+        }
+    }
+
+    if (opt.ipfilterConvert_p_s)
+    {
+        if (!check_IPFilter_primitive(ref.ipfilterConvert_p_s, opt.ipfilterConvert_p_s))
+        {
+            printf("\nfilterConvertPeltoShort failed\n");
+            return false;
+        }
+    }
+
+    if (opt.ipfilterConvert_s_p)
+    {
+        if (!check_IPFilter_primitive(ref.ipfilterConvert_s_p, opt.ipfilterConvert_s_p))
+        {
+            printf("\nfilterConvertShorttoPel failed\n");
+            return false;
+        }
+    }
+
+    return true;
+}
+
+#define FILTER_ITERATIONS   50000
+
+void IPFilterHarness::measureSpeed(const EncoderPrimitives& ref, const EncoderPrimitives& opt)
+{
+    Timer *t = Timer::CreateTimer();
+
+    int height = 64;
+    int width = 64;
+    short val = 2;
+    short srcStride = 96;
+    short dstStride = 96;
+
+    //for (int value = 0; value < 16; value++)
+    //{
+    //    memset(IPF_vec_output, 0, ipf_t_size);  // Initialize output buffer to zero
+    //    memset(IPF_C_output, 0, ipf_t_size);    // Initialize output buffer to zero
+    //    if (opt.filter[value])
+    //    {
+    //        printf("filter[%s]", FilterConf_names[value]);
+    //        REPORT_SPEEDUP(FILTER_ITERATIONS,
+    //                       opt.filter[value]((short*)(m_lumaFilter + val), pixel_buff + 3 * srcStride, srcStride,
+    //                                         IPF_vec_output, dstStride, height, width, BIT_DEPTH),
+    //                       ref.filter[value]((short*)(m_lumaFilter + val), pixel_buff + 3 * srcStride, srcStride,
+    //                                         IPF_vec_output, dstStride, height, width, BIT_DEPTH));
+    //    }
+    //}
+
+    for (int value = 0; value < NUM_IPFILTER_P_P; value++)
+    {
+        if (opt.ipFilter_p_p[value])
+        {
+            printf("filter_H_P_P_%d", 8 / (value + 1));
+            REPORT_SPEEDUP(FILTER_ITERATIONS,
+                           opt.ipFilter_p_p[value](8, pixel_buff + 3 * srcStride,
+                                                   srcStride,
+                                                   IPF_vec_output_p,
+                                                   dstStride,
+                                                   width,
+                                                   height,  m_lumaFilter[val]),
+                           ref.ipFilter_p_p[value](8, pixel_buff + 3 * srcStride,
+                                                   srcStride,
+                                                   IPF_C_output_p,
+                                                   dstStride,
+                                                   width,
+                                                   height,  m_lumaFilter[val]
+                                                   )
+                           );
+        }
+    }
+
+    for (int value = 0; value < NUM_IPFILTER_P_S; value++)
+    {
+        if (opt.ipFilter_p_s[value])
+        {
+            printf("filter_H_P_S_%d", 8 / (value + 1));
+            REPORT_SPEEDUP(FILTER_ITERATIONS,
+                           opt.ipFilter_p_s[value](8, pixel_buff + 3 * srcStride,
+                                                   srcStride,
+                                                   IPF_vec_output_s,
+                                                   dstStride,
+                                                   width,
+                                                   height,  m_lumaFilter[val]),
+                           ref.ipFilter_p_s[value](8, pixel_buff + 3 * srcStride,
+                                                   srcStride,
+                                                   IPF_C_output_s,
+                                                   dstStride,
+                                                   width,
+                                                   height,  m_lumaFilter[val]
+                                                   )
+                           );
+        }
+    }
+
+    for (int value = 0; value < NUM_IPFILTER_S_P; value++)
+    {
+        if (opt.ipFilter_s_p[value])
+        {
+            printf("filter_H_S_P_%d", 8 / (value + 1));
+            REPORT_SPEEDUP(FILTER_ITERATIONS,
+                           opt.ipFilter_s_p[value](8, short_buff + 3 * srcStride,
+                                                   srcStride,
+                                                   IPF_vec_output_p,
+                                                   dstStride,
+                                                   width,
+                                                   height,  m_lumaFilter[val]),
+                           ref.ipFilter_s_p[value](8, short_buff + 3 * srcStride,
+                                                   srcStride,
+                                                   IPF_C_output_p,
+                                                   dstStride,
+                                                   width,
+                                                   height,  m_lumaFilter[val]
+                                                   )
+                           );
+        }
+    }
+
+    if (opt.ipfilterConvert_p_s)
+    {
+        printf("filterConvertPeltoShort");
+        REPORT_SPEEDUP(FILTER_ITERATIONS,
+                       opt.ipfilterConvert_p_s(8, pixel_buff,
+                                               srcStride,
+                                               IPF_vec_output_s,
+                                               dstStride,
+                                               width,
+                                               height),
+                       ref.ipfilterConvert_p_s(8, pixel_buff,
+                                               srcStride,
+                                               IPF_C_output_s,
+                                               dstStride,
+                                               width,
+                                               height)
+                       );
+    }
+
+    if (opt.ipfilterConvert_s_p)
+    {
+        printf("filterConvertShorttoPel");
+        REPORT_SPEEDUP(FILTER_ITERATIONS,
+                       opt.ipfilterConvert_s_p(8, short_buff,
+                                               srcStride,
+                                               IPF_vec_output_p,
+                                               dstStride,
+                                               width,
+                                               height),
+                       ref.ipfilterConvert_s_p(8, short_buff,
+                                               srcStride,
+                                               IPF_C_output_p,
+                                               dstStride,
+                                               width,
+                                               height)
+                       );
+    }
+
+    t->Release();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/test/ipfilterharness.h	Thu Apr 25 15:35:32 2013 +0530
@@ -0,0 +1,60 @@
+/*****************************************************************************
+ * Copyright (C) 2013 x265 project
+ *
+ * Authors: Deepthi Devaki <deepthidevaki@multicorewareinc.com>,
+ *          Rajesh Paulraj <rajesh@multicorewareinc.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
+ *
+ * This program is also available under a commercial proprietary license.
+ * For more information, contact us at licensing@multicorewareinc.com.
+ *****************************************************************************/
+
+#ifndef _IPFILTERHARNESS_H_1
+#define _IPFILTERHARNESS_H_1 1
+
+#include "testharness.h"
+#include "primitives.h"
+
+class IPFilterHarness : public TestHarness
+{
+protected:
+
+    pixel *pixel_buff;
+    short *short_buff;
+
+    pixel *IPF_vec_output_p, *IPF_C_output_p;
+    short *IPF_vec_output_s, *IPF_C_output_s;
+
+    int ipf_t_size;
+
+    bool check_IPFilter_primitive(x265::IPFilter_p_p ref, x265::IPFilter_p_p opt);
+    bool check_IPFilter_primitive(x265::IPFilter_p_s ref, x265::IPFilter_p_s opt);
+    bool check_IPFilter_primitive(x265::IPFilter_s_p ref, x265::IPFilter_s_p opt);
+    bool check_IPFilter_primitive(x265::IPFilterConvert_p_s ref, x265::IPFilterConvert_p_s opt);
+    bool check_IPFilter_primitive(x265::IPFilterConvert_s_p ref, x265::IPFilterConvert_s_p opt);
+
+public:
+
+    IPFilterHarness();
+
+    virtual ~IPFilterHarness();
+
+    bool testCorrectness(const x265::EncoderPrimitives& ref, const x265::EncoderPrimitives& opt);
+
+    void measureSpeed(const x265::EncoderPrimitives& ref, const x265::EncoderPrimitives& opt);
+};
+
+#endif // ifndef _FILTERHARNESS_H_1
--- a/source/test/testbench.cpp	Thu Apr 25 15:33:24 2013 +0530
+++ b/source/test/testbench.cpp	Thu Apr 25 15:35:32 2013 +0530
@@ -27,6 +27,7 @@
 #include "pixelharness.h"
 #include "filterharness.h"
 #include "mbdstharness.h"
+#include "ipfilterharness.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -56,13 +57,15 @@ int main(int argc, char *argv[])
     PixelHarness  HPixel;
     FilterHarness HFilter;
     MBDstHarness  HMBDist;
+    IPFilterHarness HIPFilter;
 
     // To disable classes of tests, simply comment them out in this list
     TestHarness *harness[] =
     {
         &HPixel,
         &HFilter,
-        &HMBDist
+        &HMBDist,
+        &HIPFilter
     };
 
     EncoderPrimitives cprim;