#ifndef AVIFILE_IVIDEODECODER_H
#define AVIFILE_IVIDEODECODER_H

#include "infotypes.h"
#include "image.h"

AVM_BEGIN_NAMESPACE;

/**
 *
 *  Class for video decompression.
 *
 *  Usage:
 *
 *  IVideoDecoder::Create() call tries to load video codec
 *  corresponding to your format,
 *  Start() starts decompression and Stop() stops it.
 *
 * SetDestFmt() sets desired bit depth and color space of output picture.
 * Returns zero on success, -1 if format is unsupported and
 * +1 if there was no 'native' support for the depth and library
 * is going to perform internal conversion of format. Most decoders
 * support depths 15, 16, 24 or 32. Many of them also allow to use some
 * YUV formats. You can check if your particular decoder is able to decode
 * into the particular YUV format by calling GetCapabilities(),
 * which returns bitwise OR of supported formats.
 *
 * DecodeFrame() decodes a single frame. Returns >=0 on success,
 * of <0 on failure (it is not fatal ( maybe it was
 * just one defective bit in file, after next keyframe everything
 * will be OK ).
 *
 * SetDirection() allows to 'flip' output picture. By default picture
 * is flipped ( DestFmt().biHeight<0 ), so that output image can
 * be simply memcpy()'ed to the X screen. It should be turned on
 * if image will be used for recompression, because some video encoders
 * will refuse to encode images with negative biHeight. Call it before
 * Start().
 *
 * Some decoders allow tweaking of their parameters. There are two ways
 * of doing it. 1) Use Get/SetExtendedAttr() to store parameter values
 * in registry. Decoders read these values during Start(), so you should
 * perform Restart() if you need to change parameters in run-time.
 *
 * There's more convenient way, which is supported by a few DirectShow
 * codecs. If GetRtConfig() returns nonzero, you can
 * use IRtConfig methods to adjust picture properties between Start() and
 * Stop(). These adjustments are applied from the first frame following
 * method call.
 *
 * List of valid parameters is available IRtConfig::GetCodecInfo().decoder_info.
 * See include/infotypes.h for details on accessing it.
 *
 */


class IVideoDecoder
{
public:
    /**
     * internaly used flag to mark that decoder
     * has not produced new picture from given data
     */
    static const int NO_PICTURE = 0x40000000;
    static const int NEXT_PICTURE = 0x20000000;
    enum CAPS
    {
	CAP_NONE = 0,
        // packed
	CAP_IYUV = 1,
	CAP_YUY2 = 2,
	CAP_UYVY = 4,
	CAP_YVYU = 8,
        // planar
	CAP_YV12 = 128,
	CAP_I420 = 256,
	CAP_YVU9 = 512,

	// for DR1 rendering this align is needed
        // this also mean codec will properly handly strides
        // IT'S FOR PRIVATE USAGE and will be changed
	CAP_ALIGN64 = 1 << 30,
	CAP_ALIGN16 = 1 << 31,
    };

    IVideoDecoder(const CodecInfo& info, const BITMAPINFOHEADER& format);
    virtual ~IVideoDecoder();

    /* Functions which may be reimplemented */

    /**
     * Codec's curently selected destination format
     */
    virtual const BITMAPINFOHEADER& GetDestFmt() const;
    /**
     * Capability flags for this codec
     */
    virtual CAPS GetCapabilities() const;
    virtual const CodecInfo& GetCodecInfo() const;
    /**
     * Use this method instead of dynamic_cast - some gcc compilers
     * (even the new ones seems to have some serious problems with that)
     */
    virtual IRtConfig* GetRtConfig(); // can't be const

    virtual void Flush(); // call after seek
    virtual int Restart();
    virtual int SetDirection(int dir);
    virtual int Start();
    virtual int Stop();

    /* Functions which must be implemented by each decoder */

    /**
     * Passes the data to decoder.
     * 'render' flag signals decoder if the frame will be rendered.
     * If it is 'false', decoder may speed up the decoding process
     * by not filling CImage object. This feature is available only
     * for a few decoders, such as Indeo Video 5.0.
     * also it will be faster with ffmpeg decoder
     *
     * dest -  points to memory area (size respects BITMAPINFOHEADER.biSize)
     * src  -  source of bitstream data
     * size -  size of bitstream data
     * is_keyframe - flag to make visible to decoder that this is keyframe
     *               most new decoders will decide this from content
     *               of bitstream - but for some older codecs this
     *		     flags is necessary
     * returns <0 if some error appears
     * INTERNAL flags:
     *         | NO_PICTURE - no picture was generated
     *         | NEXT_PICTURE  - another picture is needed
     *         when picture is generated codec might actually return it
     *         in differenet locations (out != 0)
     */
    virtual int DecodeFrame(CImage* dest, const void* src, uint_t size,
			    int is_keyframe, bool render = true,
			    CImage** out = 0)				=0;
    /**
     * Select destination decoder output
     * by default it will be BGR24
     */
    virtual int SetDestFmt(int bits = 24, fourcc_t csp = 0)		=0;

#ifdef AVM_COMPATIBLE
    /** \deprecated backward compatible **/
    int DecodeFrame(const void* src, uint_t size, framepos_t p, double t,
		    int is_keyframe, bool render = true);
    /** \deprecated backward compatible **/
    CImage* GetFrame() const { m_pImage->AddRef(); return m_pImage; }
#endif

protected:
    const CodecInfo& m_Info;
    BITMAPINFOHEADER* m_pFormat;
    BitmapInfo m_Dest;
    CImage* m_pImage; // for backward compatibility
};

// declaration of IRtConfig moved to image.h
// used also by IVideoRenderer

AVM_END_NAMESPACE;

#ifdef AVM_COMPATIBLE
typedef avm::IRtConfig IRtConfig;
typedef avm::IVideoDecoder IVideoDecoder;
#endif

#endif // AVIFILE_IVIDEODECODER_H
