/*
 * Copyright (c) 2007 Bobby Bingham
 *
 * 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
 */

/**
 * @file
 * format and noformat video filters
 */

#include <string.h>

#include "libavutil/internal.h"
#include "libavutil/mem.h"
#include "libavutil/pixdesc.h"
#include "libavutil/opt.h"

#include "avfilter.h"
#include "formats.h"
#include "internal.h"
#include "video.h"

typedef struct FormatContext {
    const AVClass *class;
    char *pix_fmts;

    /**
     * pix_fmts parsed into AVPixelFormats and terminated with
     * AV_PIX_FMT_NONE
     */
    enum AVPixelFormat *formats;
} FormatContext;

static av_cold void uninit(AVFilterContext *ctx)
{
    FormatContext *s = ctx->priv;
    av_freep(&s->formats);
}

static av_cold int init(AVFilterContext *ctx)
{
    FormatContext *s = ctx->priv;
    char *cur, *sep;
    int nb_formats = 1;
    int i;
    int ret;

    if (!s->pix_fmts) {
        av_log(ctx, AV_LOG_ERROR, "Empty output format string.\n");
        return AVERROR(EINVAL);
    }

    /* count the formats */
    cur = s->pix_fmts;
    while ((cur = strchr(cur, '|'))) {
        nb_formats++;
        if (*cur)
            cur++;
    }

    s->formats = av_malloc_array(nb_formats + 1, sizeof(*s->formats));
    if (!s->formats)
        return AVERROR(ENOMEM);

    /* parse the list of formats */
    cur = s->pix_fmts;
    for (i = 0; i < nb_formats; i++) {
        sep = strchr(cur, '|');
        if (sep)
            *sep++ = 0;

        if ((ret = ff_parse_pixel_format(&s->formats[i], cur, ctx)) < 0)
            return ret;

        cur = sep;
    }
    s->formats[nb_formats] = AV_PIX_FMT_NONE;

    if (!strcmp(ctx->filter->name, "noformat")) {
        const AVPixFmtDescriptor *desc = NULL;
        enum AVPixelFormat *formats_allowed;
        int nb_formats_lavu = 0, nb_formats_allowed = 0;

        /* count the formats known to lavu */
        while ((desc = av_pix_fmt_desc_next(desc)))
            nb_formats_lavu++;

        formats_allowed = av_malloc_array(nb_formats_lavu + 1, sizeof(*formats_allowed));
        if (!formats_allowed)
            return AVERROR(ENOMEM);

        /* for each format known to lavu, check if it's in the list of
         * forbidden formats */
        while ((desc = av_pix_fmt_desc_next(desc))) {
            enum AVPixelFormat pix_fmt = av_pix_fmt_desc_get_id(desc);

            for (i = 0; i < nb_formats; i++) {
                if (s->formats[i] == pix_fmt)
                    break;
            }
            if (i < nb_formats)
                continue;

            formats_allowed[nb_formats_allowed++] = pix_fmt;
        }
        formats_allowed[nb_formats_allowed] = AV_PIX_FMT_NONE;
        av_freep(&s->formats);
        s->formats = formats_allowed;
    }

    return 0;
}

static int query_formats(AVFilterContext *ctx)
{
    FormatContext *s = ctx->priv;
    AVFilterFormats *formats = ff_make_format_list(s->formats);

    if (!formats)
        return AVERROR(ENOMEM);

    return ff_set_common_formats(ctx, formats);
}


#define OFFSET(x) offsetof(FormatContext, x)
static const AVOption options[] = {
    { "pix_fmts", "A '|'-separated list of pixel formats", OFFSET(pix_fmts), AV_OPT_TYPE_STRING, .flags = AV_OPT_FLAG_VIDEO_PARAM },
    { NULL }
};

#if CONFIG_FORMAT_FILTER

#define format_options options
AVFILTER_DEFINE_CLASS(format);

static const AVFilterPad avfilter_vf_format_inputs[] = {
    {
        .name             = "default",
        .type             = AVMEDIA_TYPE_VIDEO,
        .get_video_buffer = ff_null_get_video_buffer,
    },
    { NULL }
};

static const AVFilterPad avfilter_vf_format_outputs[] = {
    {
        .name = "default",
        .type = AVMEDIA_TYPE_VIDEO
    },
    { NULL }
};

AVFilter ff_vf_format = {
    .name          = "format",
    .description   = NULL_IF_CONFIG_SMALL("Convert the input video to one of the specified pixel formats."),

    .init          = init,
    .uninit        = uninit,

    .query_formats = query_formats,

    .priv_size     = sizeof(FormatContext),
    .priv_class    = &format_class,

    .inputs        = avfilter_vf_format_inputs,
    .outputs       = avfilter_vf_format_outputs,
};
#endif /* CONFIG_FORMAT_FILTER */

#if CONFIG_NOFORMAT_FILTER

#define noformat_options options
AVFILTER_DEFINE_CLASS(noformat);

static const AVFilterPad avfilter_vf_noformat_inputs[] = {
    {
        .name             = "default",
        .type             = AVMEDIA_TYPE_VIDEO,
        .get_video_buffer = ff_null_get_video_buffer,
    },
    { NULL }
};

static const AVFilterPad avfilter_vf_noformat_outputs[] = {
    {
        .name = "default",
        .type = AVMEDIA_TYPE_VIDEO
    },
    { NULL }
};

AVFilter ff_vf_noformat = {
    .name          = "noformat",
    .description   = NULL_IF_CONFIG_SMALL("Force libavfilter not to use any of the specified pixel formats for the input to the next filter."),

    .init          = init,
    .uninit        = uninit,

    .query_formats = query_formats,

    .priv_size     = sizeof(FormatContext),
    .priv_class    = &noformat_class,

    .inputs        = avfilter_vf_noformat_inputs,
    .outputs       = avfilter_vf_noformat_outputs,
};
#endif /* CONFIG_NOFORMAT_FILTER */
