/*
 * 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
 * FIFO buffering video filter
 */

#include "avfilter.h"
#include "video.h"

typedef struct BufPic {
    AVFilterBufferRef *picref;
    struct BufPic     *next;
} BufPic;

typedef struct {
    BufPic  root;
    BufPic *last;   ///< last buffered picture
} FifoContext;

static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
{
    FifoContext *fifo = ctx->priv;
    fifo->last = &fifo->root;

    av_log(ctx, AV_LOG_INFO, "\n");
    return 0;
}

static av_cold void uninit(AVFilterContext *ctx)
{
    FifoContext *fifo = ctx->priv;
    BufPic *pic, *tmp;

    for (pic = fifo->root.next; pic; pic = tmp) {
        tmp = pic->next;
        avfilter_unref_buffer(pic->picref);
        av_free(pic);
    }
}

static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
{
    FifoContext *fifo = inlink->dst->priv;

    fifo->last->next = av_mallocz(sizeof(BufPic));
    fifo->last = fifo->last->next;
    fifo->last->picref = picref;
}

static void end_frame(AVFilterLink *inlink) { }

static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) { }

static int request_frame(AVFilterLink *outlink)
{
    FifoContext *fifo = outlink->src->priv;
    BufPic *tmp;
    int ret;

    if (!fifo->root.next) {
        if ((ret = avfilter_request_frame(outlink->src->inputs[0])) < 0)
            return ret;
    }

    /* by doing this, we give ownership of the reference to the next filter,
     * so we don't have to worry about dereferencing it ourselves. */
    avfilter_start_frame(outlink, fifo->root.next->picref);
    avfilter_draw_slice (outlink, 0, outlink->h, 1);
    avfilter_end_frame  (outlink);

    if (fifo->last == fifo->root.next)
        fifo->last = &fifo->root;
    tmp = fifo->root.next->next;
    av_free(fifo->root.next);
    fifo->root.next = tmp;

    return 0;
}

AVFilter avfilter_vf_fifo = {
    .name      = "fifo",
    .description = NULL_IF_CONFIG_SMALL("Buffer input images and send them when they are requested."),

    .init      = init,
    .uninit    = uninit,

    .priv_size = sizeof(FifoContext),

    .inputs    = (const AVFilterPad[]) {{ .name      = "default",
                                    .type            = AVMEDIA_TYPE_VIDEO,
                                    .get_video_buffer= ff_null_get_video_buffer,
                                    .start_frame     = start_frame,
                                    .draw_slice      = draw_slice,
                                    .end_frame       = end_frame,
                                    .rej_perms       = AV_PERM_REUSE2, },
                                  { .name = NULL}},
    .outputs   = (const AVFilterPad[]) {{ .name      = "default",
                                    .type            = AVMEDIA_TYPE_VIDEO,
                                    .request_frame   = request_frame, },
                                  { .name = NULL}},
};
