Search code examples
c++intel-ipp

Intel IPP ippsFree() crashes


I tried following code to check how fast the Intel IPP is for resizing / converting images, but it keeps on crashing at ippsFree(pSpec) at the end, and I cannot figure out, why.

#include <stdint.h>
#include <memory>
#include <Windows.h>
#include <time.h>

#include "ipp.h"

int main(...) {
    srand(time(NULL));

    int width = 640;
    int height = 480;
    int channels = 2;
    IppiResizeYUV422Spec* pSpec;
    IppiSize dstSize, srcSize;
    IppiPoint dstOffset = { 0, 0 };
    srcSize.width = width;
    srcSize.height = height;
    dstSize.width = 2 * width;
    dstSize.height = 2 * height;
    std::unique_ptr<unsigned char[]> sourceData;
    std::unique_ptr<unsigned char[]> destinationData;
    std::unique_ptr<unsigned char[]> destinationDataRGB;
    std::unique_ptr<unsigned char[]> workBuffer;

    sourceData.reset(new unsigned char[srcSize.width * srcSize.height * channels]);
    destinationData.reset(new unsigned char[dstSize.width * dstSize.height * channels]);
    destinationDataRGB.reset(new unsigned char[dstSize.width * dstSize.height * 3]);
    workBuffer.reset(new unsigned char[dstSize.width * dstSize.height * channels]);

    memset(sourceData.get(), 0, srcSize.width * srcSize.height * channels);
    memset(destinationData.get(), 0, dstSize.width * dstSize.height * channels);
    memset(workBuffer.get(), 0, dstSize.width * dstSize.height * channels);

    IppStatus error;
    int specSize = 0, initSize = 0, buffSize = 0;
    error = ippiResizeGetSize_8u(srcSize, dstSize, IppiInterpolationType::ippNearest, 0, &specSize, &initSize);

    pSpec = (IppiResizeYUV422Spec*) ippsMalloc_8u(specSize);
    error = ippiResizeYUV422NearestInit(srcSize, dstSize, pSpec);

    IppiRect srcRoi = { 0, 0, srcSize.width, srcSize.height };

    int64_t timerIPP9 = 0;
    LARGE_INTEGER start, end;
    LARGE_INTEGER tps;
    QueryPerformanceFrequency(&tps);

    for (unsigned int index = 0; index < 100; ++index) {
        for (unsigned int imageIdx = 0; imageIdx < srcSize.width * srcSize.height * channels; ++imageIdx) {
            sourceData.get()[imageIdx] = (rand() & 0xFF);
        }

        QueryPerformanceCounter(&start);
        error = ippiResizeYUV422Nearest_8u_C2R(
            sourceData.get(),
            srcSize.width * channels,
            destinationData.get(),
            dstSize.width * channels,
            dstOffset,
            dstSize,
            pSpec,
            workBuffer.get());
        QueryPerformanceCounter(&end);

        timerIPP9 += end.QuadPart - start.QuadPart;

        QueryPerformanceCounter(&start);
        ippiYCbCr422ToRGB_8u_C2C3R(destinationData.get(), dstSize.width * channels, destinationDataRGB.get(), dstSize.width * 3, dstSize);
        QueryPerformanceCounter(&end);

        timerIPP9 += end.QuadPart - start.QuadPart;
        printf("Test: %d, time: %d ms\r", index, timerIPP9 * 1000 / tps.QuadPart);
    }

    ippsFree(pSpec);
    printf("\n");
    printf("Time taken: %d ms\n", timerIPP9 * 1000 / tps.QuadPart);
    system("Pause");
    return 0;
}

I am just piping random data into the converter, but it should be able to deal with the noise (as it still is a valid image).


Solution

  • I think I solved the puzzle...

    All you need to do is replacing the following like of code:

    error = ippiResizeGetSize_8u(srcSize, dstSize, IppiInterpolationType::ippNearest, 0, &specSize, &initSize);
    

    With the following one:

    error = ippiResizeYUV422GetSize(srcSize, dstSize, IppiInterpolationType::ippNearest, 0, &specSize, &initSize);
    

    According to IPP documentation:

    Description This function initializes the IppiResizeYUV422Spec structure for the resize algorithm with the nearest neighbor interpolation method.
    To calculate the size of the spec structure object, call the ippiResizeYUV422GetSize function.

    See: http://hpc.ipp.ac.cn/wp-content/uploads/2015/12/documentation_2016/en/ipp/common/ipp_manual/GUID-15B51AB0-7F73-4E13-AC81-753259CE0E2C.htm

    When executing ippiResizeYUV422GetSize, value of specSize equals 11776.
    When executing ippiResizeGetSize_8u, value of specSize equals 9240.
    The smaller allocated size results corrupted heap.