/*
 * 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 "swscale.h"
#include "rgb2rgb.h"
#include "libavutil/mem.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;
}
