#pragma once

#include <MMSystem.h>
#include "string_t"

struct VideoPalette_t
{
	INT		m_nEntries;			/**< to keep the compatibility with ffmpeg's palette */
	UINT8	m_Palette[256][4];  /**< 4-byte RGBA/YUVA palette */
};

/**
 * audio format description
 */
struct AudioFormat_t
{
    UINT32	m_nFourccFormat;                      /**< audio format fourcc */
    UINT	m_nRate;                              /**< audio sample-rate */

    /* Describes the channels configuration of the samples (ie. number of
     * channels which are available in the buffer, and positions). */
    UINT32  m_nPhysicalChannels;

    /* Describes from which original channels, before downmixing, the
     * buffer is derived. */
    UINT32  m_nOriginalChannels;

    /* Optional - for A/52, SPDIF and DTS types : */
    /* Bytes used by one compressed frame, depends on bitrate. */
    UINT m_nBytesPerFrame;

    /* Number of sampleframes contained in one compressed frame. */
    UINT m_nFrameLength;
    /* Please note that it may be completely arbitrary - buffers are not
     * obliged to contain a integral number of so-called "frames". It's
     * just here for the division :
     * buffer_size = i_nb_samples * i_bytes_per_frame / i_frame_length
     */

    /* FIXME ? (used by the codecs) */
    UINT m_nChannels;
    UINT m_nBlockAlign;
    UINT m_nBitsPerSample;
};

#define AUDIO_FMT_S16_NE MAKEFOURCC('s','1','6','l')
#define AUDIO_FMT_U16_NE MAKEFOURCC('u','1','6','l')

/**
 * video format description
 */
struct VideoFormat_t
{
    UINT32	m_nChroma;              /**< picture chroma */
    UINT	m_nAspect;              /**< aspect ratio */

    UINT m_nWidth;                  /**< picture width */
    UINT m_nHeight;                 /**< picture height */
    UINT m_nOffsetX;				/**< start offset of visible area */
    UINT m_nOffsetY;				/**< start offset of visible area */
    UINT m_nVisibleWidth;           /**< width of visible area */
    UINT m_nVisibleHeight;          /**< height of visible area */

    UINT m_nBitsPerPixel;           /**< number of bits per pixel */

    UINT m_nSarNum;                 /**< sample/pixel aspect ratio */
    UINT m_nSarDen;

    UINT m_nFrameRate;              /**< frame rate numerator */
    UINT m_nFrameRateBase;          /**< frame rate denominator */

    INT m_nMaskR;
	INT m_nMaskG;
	INT m_nMaskB;					 /**< color masks for RGB chroma */

    VideoPalette_t *m_pPalette;      /**< video palette from demuxer */

	VideoFormat_t()
	{

	}
};

/**
 * subtitles format description
 */
struct SubsFormat_t
{
    /* the character encoding of the text of the subtitle.
     * all gettext recognized shorts can be used */
    char *psz_encoding;


    int  i_x_origin; /**< x coordinate of the subtitle. 0 = left */
    int  i_y_origin; /**< y coordinate of the subtitle. 0 = top */

    struct
    {
        /*  */
        uint32_t palette[16+1];

        /* the width of the original movie the spu was extracted from */
        int i_original_frame_width;
        /* the height of the original movie the spu was extracted from */
        int i_original_frame_height;
    } spu;

    struct
    {
        int i_id;
    } dvb;
};

/**
 * ES definition
 */
typedef struct extra_languages_t
{
        char *psz_language;
        char *psz_description;
} extra_languages_t;

struct es_format_t
{
    int             i_cat;
    fourcc_t		i_codec;

    int             i_id;       /* -1: let the core mark the right id
                                   >=0: valid id */
    int             i_group;    /* -1 : standalone
                                   >= 0 then a "group" (program) is created
                                        for each value */
    int             i_priority; /*  -2 : mean not selectable by the users
                                    -1 : mean not selected by default even
                                        when no other stream
                                    >=0: priority */

    char            *psz_language;
    char            *psz_description;
    int             i_extra_languages;
    extra_languages_t *p_extra_languages;

    audio_format_t audio;
    video_format_t video;
    subs_format_t  subs;

    UINT   i_bitrate;

    bool_t     b_packetized; /* wether the data is packetized
                                    (ie. not truncated) */
    int     i_extra;
    void    *p_extra;

};

/* ES Categories */
#define UNKNOWN_ES      0x00
#define VIDEO_ES        0x01
#define AUDIO_ES        0x02
#define SPU_ES          0x03
#define NAV_ES          0x04

static inline void es_format_Init( es_format_t *fmt,
                                   int i_cat, fourcc_t i_codec )
{
    fmt->i_cat                  = i_cat;
    fmt->i_codec                = i_codec;
    fmt->i_id                   = -1;
    fmt->i_group                = 0;
    fmt->i_priority             = 0;
    fmt->psz_language           = NULL;
    fmt->psz_description        = NULL;

    fmt->i_extra_languages      = 0;
    fmt->p_extra_languages      = NULL;

    memset( &fmt->audio, 0, sizeof(audio_format_t) );
    memset( &fmt->video, 0, sizeof(video_format_t) );
    memset( &fmt->subs, 0, sizeof(subs_format_t) );

    fmt->b_packetized           = TRUE;
    fmt->i_bitrate              = 0;
    fmt->i_extra                = 0;
    fmt->p_extra                = NULL;
}

static inline void es_format_Copy( es_format_t *dst, es_format_t *src )
{
    int i;
    memcpy( dst, src, sizeof( es_format_t ) );
    if( src->psz_language )
         dst->psz_language = strdup( src->psz_language );
    if( src->psz_description )
        dst->psz_description = strdup( src->psz_description );
    if( src->i_extra > 0 )
    {
        dst->i_extra = src->i_extra;
        dst->p_extra = malloc( src->i_extra );
        memcpy( dst->p_extra, src->p_extra, src->i_extra );
    }
    else
    {
        dst->i_extra = 0;
        dst->p_extra = NULL;
    }

    if( src->subs.psz_encoding )
        dst->subs.psz_encoding = strdup( src->subs.psz_encoding );

    if( src->video.p_palette )
    {
        dst->video.p_palette =
            (video_palette_t*)malloc( sizeof( video_palette_t ) );
        memcpy( dst->video.p_palette, src->video.p_palette,
                sizeof( video_palette_t ) );
    }

    dst->i_extra_languages = src->i_extra_languages;
    if( dst->i_extra_languages )
        dst->p_extra_languages = (extra_languages_t*)
            malloc(dst->i_extra_languages * sizeof(*dst->p_extra_languages ));
    for( i = 0; i < dst->i_extra_languages; i++ ) {
        if( src->p_extra_languages[i].psz_language )
            dst->p_extra_languages[i].psz_language = strdup(src->p_extra_languages[i].psz_language);
        else
            dst->p_extra_languages[i].psz_language = NULL;
        if( src->p_extra_languages[i].psz_description )
            dst->p_extra_languages[i].psz_description = strdup(src->p_extra_languages[i].psz_description);
        else
            dst->p_extra_languages[i].psz_description = NULL;
    }
}

static inline void es_format_Clean( es_format_t *fmt )
{
    if( fmt->psz_language ) free( fmt->psz_language );
    fmt->psz_language = NULL;

    if( fmt->psz_description ) free( fmt->psz_description );
    fmt->psz_description = NULL;

    if( fmt->i_extra > 0 ) free( fmt->p_extra );
    fmt->i_extra = 0; fmt->p_extra = NULL;

    if( fmt->video.p_palette )
        free( fmt->video.p_palette );
    fmt->video.p_palette = NULL;

    if( fmt->subs.psz_encoding ) free( fmt->subs.psz_encoding );
    fmt->subs.psz_encoding = NULL;

    if( fmt->i_extra_languages && fmt->p_extra_languages ) {
        int i = 0;
        while( i < fmt->i_extra_languages ) {
            if( fmt->p_extra_languages[i].psz_language )
                free( fmt->p_extra_languages[i].psz_language );
            if( fmt->p_extra_languages[i].psz_description )
                free( fmt->p_extra_languages[i].psz_description );
            i++;
        }
        free(fmt->p_extra_languages);
    }
    fmt->i_extra_languages = 0;
    fmt->p_extra_languages = NULL;
}

#endif
