/*
 * Dirac decoder support via libdirac library
 * Copyright (c) 2005 BBC, Andrew Kennedy <dirac at rd dot bbc dot co dot uk>
 * Copyright (c) 2006-2008 BBC, Anuradha Suraparaju <asuraparaju at gmail dot com >
 *
 * 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
* Dirac decoder support via libdirac library; more details about the Dirac
* project can be found at http://dirac.sourceforge.net/.
* The libdirac_decoder library implements Dirac specification version 2.2
* (http://dirac.sourceforge.net/specification.html).
*/

#include "libavutil/imgutils.h"
#include "libdirac.h"

#undef NDEBUG
#include <assert.h>

#include <libdirac_decoder/dirac_parser.h>

/** contains a single frame returned from Dirac */
typedef struct DiracDecoderParams {
    /** decoder handle */
    dirac_decoder_t* p_decoder;

    /** buffer to hold decoded frame */
    unsigned char* p_out_frame_buf;
} DiracDecoderParams;


/**
* returns FFmpeg chroma format
*/
static enum PixelFormat get_chroma_format(dirac_chroma_t dirac_pix_fmt)
{
    int num_formats = sizeof(dirac_pixel_format_map) /
                      sizeof(dirac_pixel_format_map[0]);
    int idx;

    for (idx = 0; idx < num_formats; ++idx)
        if (dirac_pixel_format_map[idx].dirac_pix_fmt == dirac_pix_fmt)
            return dirac_pixel_format_map[idx].ff_pix_fmt;
    return PIX_FMT_NONE;
}

static av_cold int libdirac_decode_init(AVCodecContext *avccontext)
{

    DiracDecoderParams *p_dirac_params = avccontext->priv_data;
    p_dirac_params->p_decoder =  dirac_decoder_init(avccontext->debug);

    if (!p_dirac_params->p_decoder)
        return -1;

    return 0;
}

static int libdirac_decode_frame(AVCodecContext *avccontext,
                                 void *data, int *data_size,
                                 AVPacket *avpkt)
{
    const uint8_t *buf = avpkt->data;
    int buf_size = avpkt->size;

    DiracDecoderParams *p_dirac_params = avccontext->priv_data;
    AVPicture *picture = data;
    AVPicture pic;
    int pict_size;
    unsigned char *buffer[3];

    *data_size = 0;

    if (buf_size > 0) {
        /* set data to decode into buffer */
        dirac_buffer(p_dirac_params->p_decoder, buf, buf + buf_size);
        if ((buf[4] & 0x08) == 0x08 && (buf[4] & 0x03))
            avccontext->has_b_frames = 1;
    }
    while (1) {
         /* parse data and process result */
        DecoderState state = dirac_parse(p_dirac_params->p_decoder);
        switch (state) {
        case STATE_BUFFER:
            return buf_size;

        case STATE_SEQUENCE:
        {
            /* tell FFmpeg about sequence details */
            dirac_sourceparams_t *src_params = &p_dirac_params->p_decoder->src_params;

            if (av_image_check_size(src_params->width, src_params->height,
                                    0, avccontext) < 0) {
                av_log(avccontext, AV_LOG_ERROR, "Invalid dimensions (%dx%d)\n",
                       src_params->width, src_params->height);
                avccontext->height = avccontext->width = 0;
                return -1;
            }

            avccontext->height = src_params->height;
            avccontext->width  = src_params->width;

            avccontext->pix_fmt = get_chroma_format(src_params->chroma);
            if (avccontext->pix_fmt == PIX_FMT_NONE) {
                av_log(avccontext, AV_LOG_ERROR,
                       "Dirac chroma format %d not supported currently\n",
                       src_params->chroma);
                return -1;
            }

            avccontext->time_base.den = src_params->frame_rate.numerator;
            avccontext->time_base.num = src_params->frame_rate.denominator;

            /* calculate output dimensions */
            avpicture_fill(&pic, NULL, avccontext->pix_fmt,
                           avccontext->width, avccontext->height);

            pict_size = avpicture_get_size(avccontext->pix_fmt,
                                           avccontext->width,
                                           avccontext->height);

            /* allocate output buffer */
            if (!p_dirac_params->p_out_frame_buf)
                p_dirac_params->p_out_frame_buf = av_malloc(pict_size);
            buffer[0] = p_dirac_params->p_out_frame_buf;
            buffer[1] = p_dirac_params->p_out_frame_buf +
                        pic.linesize[0] * avccontext->height;
            buffer[2] = buffer[1] +
                        pic.linesize[1] * src_params->chroma_height;

            /* tell Dirac about output destination */
            dirac_set_buf(p_dirac_params->p_decoder, buffer, NULL);
            break;
        }
        case STATE_SEQUENCE_END:
            break;

        case STATE_PICTURE_AVAIL:
            /* fill picture with current buffer data from Dirac */
            avpicture_fill(picture, p_dirac_params->p_out_frame_buf,
                           avccontext->pix_fmt,
                           avccontext->width, avccontext->height);
            *data_size = sizeof(AVPicture);
            return buf_size;

        case STATE_INVALID:
            return -1;

        default:
            break;
        }
    }

    return buf_size;
}


static av_cold int libdirac_decode_close(AVCodecContext *avccontext)
{
    DiracDecoderParams *p_dirac_params = avccontext->priv_data;
    dirac_decoder_close(p_dirac_params->p_decoder);

    av_freep(&p_dirac_params->p_out_frame_buf);

    return 0;
}

static void libdirac_flush(AVCodecContext *avccontext)
{
    /* Got a seek request. We will need free memory held in the private
     * context and free the current Dirac decoder handle and then open
     * a new decoder handle. */
    libdirac_decode_close(avccontext);
    libdirac_decode_init(avccontext);
    return;
}



AVCodec ff_libdirac_decoder = {
    .name           = "libdirac",
    .type           = AVMEDIA_TYPE_VIDEO,
    .id             = CODEC_ID_DIRAC,
    .priv_data_size = sizeof(DiracDecoderParams),
    .init           = libdirac_decode_init,
    .close          = libdirac_decode_close,
    .decode         = libdirac_decode_frame,
    .capabilities   = CODEC_CAP_DELAY,
    .flush = libdirac_flush,
    .long_name = NULL_IF_CONFIG_SMALL("libdirac Dirac 2.2"),
};
