/*
 * Copyright (C) 2002 Michael Niedermayer <michaelni@gmx.at>
 *
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * FFmpeg 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include <stdio.h>
#include <string.h>              /* for memset() */
#include <stdlib.h>
#include <inttypes.h>

#include "libavutil/mem.h"

#include "libswscale/swscale.h"
#include "libswscale/rgb2rgb.h"

#define SIZE    1000
#define srcByte 0x55
#define dstByte 0xBB

#define FUNC(s, d, n) { s, d, #n, n }

int main(int argc, char **argv)
{
    int i, funcNum;
    uint8_t *srcBuffer = av_malloc(SIZE);
    uint8_t *dstBuffer = av_malloc(SIZE);
    int failedNum      = 0;
    int passedNum      = 0;

    if (!srcBuffer || !dstBuffer)
        return -1;

    av_log(NULL, AV_LOG_INFO, "memory corruption test ...\n");
    ff_sws_rgb2rgb_init();

    for (funcNum = 0; ; funcNum++) {
        struct func_info_s {
            int src_bpp;
            int dst_bpp;
            const char *name;
            void (*func)(const uint8_t *src, uint8_t *dst, int src_size);
        } func_info[] = {
            FUNC(2, 2, rgb12to15),
            FUNC(2, 2, rgb15to16),
            FUNC(2, 3, rgb15to24),
            FUNC(2, 4, rgb15to32),
            FUNC(2, 3, rgb16to24),
            FUNC(2, 4, rgb16to32),
            FUNC(3, 2, rgb24to15),
            FUNC(3, 2, rgb24to16),
            FUNC(3, 4, rgb24to32),
            FUNC(4, 2, rgb32to15),
            FUNC(4, 2, rgb32to16),
            FUNC(4, 3, rgb32to24),
            FUNC(2, 2, rgb16to15),
            FUNC(2, 2, rgb12tobgr12),
            FUNC(2, 2, rgb15tobgr15),
            FUNC(2, 2, rgb15tobgr16),
            FUNC(2, 3, rgb15tobgr24),
            FUNC(2, 4, rgb15tobgr32),
            FUNC(2, 2, rgb16tobgr15),
            FUNC(2, 2, rgb16tobgr16),
            FUNC(2, 3, rgb16tobgr24),
            FUNC(2, 4, rgb16tobgr32),
            FUNC(3, 2, rgb24tobgr15),
            FUNC(3, 2, rgb24tobgr16),
            FUNC(3, 3, rgb24tobgr24),
            FUNC(3, 4, rgb24tobgr32),
            FUNC(4, 2, rgb32tobgr15),
            FUNC(4, 2, rgb32tobgr16),
            FUNC(4, 3, rgb32tobgr24),
            FUNC(4, 4, shuffle_bytes_2103), /* rgb32tobgr32 */
            FUNC(6, 6, rgb48tobgr48_nobswap),
            FUNC(6, 6, rgb48tobgr48_bswap),
            FUNC(8, 6, rgb64to48_nobswap),
            FUNC(8, 6, rgb64to48_bswap),
            FUNC(8, 6, rgb64tobgr48_nobswap),
            FUNC(8, 6, rgb64tobgr48_bswap),
            FUNC(0, 0, NULL)
        };
        int width;
        int failed = 0;
        int srcBpp = 0;
        int dstBpp = 0;

        if (!func_info[funcNum].func)
            break;

        av_log(NULL, AV_LOG_INFO, ".");
        memset(srcBuffer, srcByte, SIZE);

        for (width = 63; width > 0; width--) {
            int dstOffset;
            for (dstOffset = 128; dstOffset < 196; dstOffset += 4) {
                int srcOffset;
                memset(dstBuffer, dstByte, SIZE);

                for (srcOffset = 128; srcOffset < 196; srcOffset += 4) {
                    uint8_t *src     = srcBuffer + srcOffset;
                    uint8_t *dst     = dstBuffer + dstOffset;
                    const char *name = NULL;

                    // don't fill the screen with shit ...
                    if (failed)
                        break;

                    srcBpp = func_info[funcNum].src_bpp;
                    dstBpp = func_info[funcNum].dst_bpp;
                    name   = func_info[funcNum].name;

                    func_info[funcNum].func(src, dst, width * srcBpp);

                    if (!srcBpp)
                        break;

                    for (i = 0; i < SIZE; i++) {
                        if (srcBuffer[i] != srcByte) {
                            av_log(NULL, AV_LOG_INFO,
                                   "src damaged at %d w:%d src:%d dst:%d %s\n",
                                   i, width, srcOffset, dstOffset, name);
                            failed = 1;
                            break;
                        }
                    }
                    for (i = 0; i < dstOffset; i++) {
                        if (dstBuffer[i] != dstByte) {
                            av_log(NULL, AV_LOG_INFO,
                                   "dst damaged at %d w:%d src:%d dst:%d %s\n",
                                   i, width, srcOffset, dstOffset, name);
                            failed = 1;
                            break;
                        }
                    }
                    for (i = dstOffset + width * dstBpp; i < SIZE; i++) {
                        if (dstBuffer[i] != dstByte) {
                            av_log(NULL, AV_LOG_INFO,
                                   "dst damaged at %d w:%d src:%d dst:%d %s\n",
                                   i, width, srcOffset, dstOffset, name);
                            failed = 1;
                            break;
                        }
                    }
                }
            }
        }
        if (failed)
            failedNum++;
        else if (srcBpp)
            passedNum++;
    }

    av_log(NULL, AV_LOG_INFO,
           "\n%d converters passed, %d converters randomly overwrote memory\n",
           passedNum, failedNum);
    return failedNum;
}
