#ifndef AVIFILE_READHANDLERS_H
#define AVIFILE_READHANDLERS_H

/**
 *
 * Interfaces that provide uniform access to data in AVI, local and
 * networked ASF files.
 *
 */

#include <avifmt.h>
#include <StreamInfo.h>
#include <formats.h>
#include <except.h>
#include <string>
#include <vector>

class IMediaReadStream {
  public:
    static const framepos_t ERR = ~0U;

    virtual ~IMediaReadStream() {}
    /* Return structure describing main stream header */
    virtual HRESULT GetHeader(void *pheader, size_t n) const = 0;

    /* return true if frame no. pos ( -1 means current frame ) is keyframe */
    virtual bool IsKeyFrame(framepos_t pos = ERR) const		= 0;

    /* seek to position lStart in stream */
    virtual HRESULT Seek(framepos_t lStart)			= 0;

    /* seek to time lTime */
    virtual HRESULT SeekTime(double time)			= 0;
    virtual HRESULT SeekToPrevKeyFrame()			= 0;

    /* Read up to lSamples into user-specified buffer, starting from
       current position, and increase counter.
       For video stream lpBuffer may be 0, in which case lSamples
       should be 1 and function returns size of next video frame
       in plBytes. */
    virtual HRESULT Read(size_t lSamples, void *lpBuffer, size_t cbBuffer,
    			 size_t* plBytes, size_t* plSamples)	= 0;
    virtual HRESULT SkipFrame()					= 0;
    virtual HRESULT SkipTo(double time)				= 0;

    /* current stream position */
    virtual framepos_t GetPos() const				= 0;

    /**
     * position of previous, next or nearest key frame
     * related to frame pos ( -1 current frame )
     */
    virtual framepos_t GetPrevKeyFrame(framepos_t pos = ERR) const = 0;
    virtual framepos_t GetNextKeyFrame(framepos_t pos = ERR) const = 0;
    virtual framepos_t GetNearestKeyFrame(framepos_t pos = ERR) const = 0;

    /* length of the stream in samples - equal to last frame position */
    virtual unsigned int GetLength() const			= 0;

    /* length of the stream in seconds */
    virtual double GetLengthTime() const			= 0;

    /* timestamp of sample no. lSample ( ERR = current sample ) */
    virtual double GetSampleTime(framepos_t lSample = ERR) const = 0;

    /* various usefull stream information */
    virtual StreamInfo* GetStreamInfo() const		= 0;

    /* retrieval of stream-specific format data */
    virtual HRESULT GetFormatSize(size_t* plSize) const	= 0;
    virtual HRESULT GetFormat(void *pFormat, size_t* plSize) const = 0;

    /* 1 cache full, 0 cache empty */
    virtual double CacheSize() const				= 0;

    /* clear the internal stream cache */
    virtual void ClearCache()					= 0;

    /* usually 'vids' or 'auds' -> fccvids, fccauds */
    virtual fourcc_t GetFourCC() const				= 0;

    /* returns 0 for video ( frames of variable size ), >0 for audio */
    virtual size_t GetSampleSize() const			= 0;
};

class IMediaReadHandler {
public:
    virtual ~IMediaReadHandler() {}
    /* vids/auds, 0-... */
    virtual IMediaReadStream *GetStream(fourcc_t fccType, size_t lParam) = 0;
    virtual HRESULT GetHeader(void* pheader, size_t n) const 	= 0;

    /* All calls for network-oriented readers should be interruptible  */
    virtual void Interrupt() 					= 0;

    /* in case of asynchronous opening */
    virtual bool IsOpened() const 				= 0;
    virtual bool IsValid() const				= 0;
    virtual bool IsRedirector() const 				= 0;
    virtual bool GetURLs(std::vector<std::string> &urls) const 	= 0;
};

/*  Read handler for AVI file  */
IMediaReadHandler *CreateAviMediaReadHandler(const char *pszFile) throw(FatalError);

/*  Read handler for ASF/WMV/ASX file  */
IMediaReadHandler *CreateASFReadHandler(const char *pszFile) throw(FatalError);

#endif // AVIFILE_READHANDLERS_H
