/******************************************************** Classes for reading & writing AVIs Copyright 2000 Eugene Kuznetsov (divx@euro.ru) *********************************************************/ #ifndef _AVIFILE_H #define _AVIFILE_H #include #include #include #include #include #include #include class AviStream { protected: AVIStreamHeader m_header; public: enum StreamType{ Audio, Video, Other }; }; /** * * * This class provides means of sequential access to data from one * stream, usually video or soundtrack. Though AVI files rarely contain * more than one soundtrack or streams of other kind, they are also supported. * * It maintains an internal position counter, which can be read with * @ref GetPos()/@ref GetTime() and changed with @ref Seek()/@ref SeekToTime(). * This counter is modified by all reading functions; function that reads * 10 frames will increase counter by 10. * * IAviReadStream is capable of implicit video and audio decompression, * so that you won't need to work with decoders directly. All you need is * to call @ref StartStreaming(), and if it succeeds ( does not throw exception ), * call members that decompress data into internal buffer ( @ref ReadFrame() ), * return this buffer ( @ref GetFrame() ) or decompress data into your memory * ( @ref ReadFrames() ). * * If you want to have direct access to compressed data, use @ref ReadDirect(). * Note that this call is incompatible with streaming, so calls to @ref ReadDirect() * between @ref StartStreaming() and @ref StopStreaming() will fail. It is done so * because dropping even one data frame during sequence decompression will ruin * current picture. * * */ class IAviReadStream : public AviStream { public: virtual ~IAviReadStream(); virtual StreamType GetType() const =0; virtual const AVIStreamHeader& GetHeader() const =0; /** * For video stream returns video format information ( usually in * BITMAPINFOHEADER format ). For other stream types fails. */ virtual HRESULT GetVideoFormatInfo(void* bi) const =0; /** * For audio stream returns audio format information. Stores main * format info in bi - WAVEFORMATEX structure - and pointer * to complete format in ext if ext is nonzero and if its size is * more than 18=sizeof(WAVEFORMATEX). * If *ext!=NULL on return, you should free it with delete * when it's not needed anymore. * * For other stream types fails. */ virtual HRESULT GetAudioFormatInfo(void* bi, char** ext) const =0; /** * Total length of stream in samples. */ virtual Unsigned GetEndPos() const =0; /** * Total length of stream in seconds. */ virtual double GetEndTime() const =0; /** * Duration of one frame/sample. */ virtual double GetFrameTime() const =0; //these four are only meaningful for video streams, but no checking //is done //-1 means current frame virtual Unsigned GetNextKeyFrame(int frame=-1) const =0; virtual Unsigned GetPrevKeyFrame(int frame=-1) const =0; virtual int ToNextKeyFrame() =0; virtual int ToPrevKeyFrame() =0; /** * Seeks to position pos in stream. In video streams, if * streaming is started, it will need to decompress all * video frames since last key-frame before pos, and thus can * be quite slow. */ virtual HRESULT Seek(Unsigned pos) =0; virtual Unsigned SeekToKeyframe(Unsigned pos) =0; /** * For video stream seeks to nearest keyframe. */ virtual double SeekToTime(double time) =0; /** * Current time in stream. */ virtual double GetTime() const =0; /** * Current position in stream. */ virtual Unsigned GetPos() const =0; /** * Returns flags associated with current frame. You'll need this * function if you use IVideoDecoder for decompression. Then, * pass resulting value to decoder together with frame data. */ virtual HRESULT GetFrameFlags(int* flags) const =0; // Initializes decoders. virtual HRESULT StartStreaming() =0; virtual bool IsStreaming() const =0; /** * Specifies desired output format. Call after StartStreaming. * Only valid for video streams. Not implemented. */ virtual HRESULT SetOutputFormat() =0; /** * Returns current output format. Call after StartStreaming. */ virtual HRESULT GetOutputFormat(void* format, Unsigned size) =0; virtual IVideoDecoder* GetDecoder() =0; // virtual HRESULT SetBitDepth(Unsigned depth) =0; /** * True if decoder shouldn't flip vertically picture * By default decoder produces flipped picture: it allows to do * simple memcpy() to video surface. Unfortunately, not all encoders * are able to compress 'flipped' video formats. */ virtual HRESULT SetDirection(bool direction) =0; /* For video streams: */ /** * Reads one frame, decompresses it into internal buffer * and increases position counter. */ virtual HRESULT ReadFrame() =0; /** * Returns pointer to internal frame buffer. */ virtual CImage* GetFrame() =0; /** * Can be calculated from video format as width*height*bpp/8 */ virtual int GetFrameSize() =0; /* For audio streams: */ /** * Reads and decompresses variable number of frames into * user-supplied buffer. */ virtual HRESULT ReadFrames(void* buffer, Unsigned bufsize, Unsigned samples, Unsigned& samples_read, Unsigned& bytes_read) =0; /** * Closes decoders. */ virtual HRESULT StopStreaming() =0; /** * Directly reads data from file. Incompatible with * streaming. */ virtual HRESULT ReadDirect(char* buffer, Unsigned bufsize, Unsigned samples, Unsigned& samples_read, Unsigned& bytes_read) =0; /** * Checks for end of stream. Nonzero if true. */ virtual HRESULT Eof() const =0; }; class IAviReadFile { public: virtual ~IAviReadFile(); virtual Unsigned StreamCount() =0; virtual Unsigned VideoStreamCount() =0; virtual Unsigned AudioStreamCount() =0; virtual IAviReadStream* GetStream(Unsigned stream_id, AviStream::StreamType type) =0; virtual HRESULT GetFileHeader(MainAVIHeader* header) =0; // virtual int AddRef() =0; // virtual int Release() =0; }; class IAviWriteStream : public AviStream { friend class IAviWriteFile; public: virtual ~IAviWriteStream() =0; // // these two should be called before data insertion begins // // // for video streams, specify time in microsecs per frame in frame_rate // for audio streams - count of bytes per second // virtual HRESULT AddChunk(const char* chunk, Unsigned size, Unsigned flags=0) =0; virtual Unsigned GetLength() =0; virtual StreamType GetType() const =0; }; class IAviVideoWriteStream : public AviStream { public: virtual ~IAviVideoWriteStream(); virtual HRESULT Start() =0; virtual HRESULT AddFrame(CImage* chunk) =0; virtual HRESULT Stop() =0; //0..10000 virtual HRESULT SetQuality(int quality) =0; virtual HRESULT SetKeyFrame(int frequency) =0; virtual Unsigned GetLength() =0; }; class IAviAudioWriteStream : public AviStream { public: virtual ~IAviAudioWriteStream(){} virtual HRESULT Start() =0; virtual HRESULT AddData(void* data, int size) =0; virtual HRESULT Stop() =0; //0..10 virtual HRESULT SetQuality(int quality) =0; virtual Unsigned GetLength() =0; }; class IAviWriteFile { friend class IAviWriteStream; public: virtual ~IAviWriteFile(); virtual IAviVideoWriteStream* AddVideoStream(int fourcc, BITMAPINFOHEADER* srchdr, int frame_rate, int flags=0) =0; virtual IAviAudioWriteStream* AddAudioStream(int fourcc, WAVEFORMATEX* fmt, int bitrate, int flags=0) =0; virtual IAviWriteStream* AddStream(enum AviStream::StreamType type, const char* format, Unsigned format_size, int handler, int frame_rate, int samplesize=0, int quality=0, int flags=0) =0; virtual HRESULT Reserve(Unsigned size) =0; virtual HRESULT WriteChunk(int fourcc, char* data, int size) =0; virtual long long FileSize() =0; }; class IAviSegWriteFile: public IAviWriteFile { public: virtual void Segment() =0; }; IAviReadFile* CreateIAviReadFile(const char* name); IAviWriteFile* CreateIAviWriteFile(const char* name, int flags=0, int mask=00777); IAviSegWriteFile* CreateSegmentedFile(const char* name, unsigned long flimit=0x7F000000, int flags=0, int mask=00777); #endif