//	VirtualDub - Video processing and capture application
//	Copyright (C) 1998-2003 Avery Lee
//
//	This program is free software; you can redistribute it and/or modify
//	it under the terms of the GNU General Public License as published by
//	the Free Software Foundation; either version 2 of the License, or
//	(at your option) any later version.
//
//	This program 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 General Public License for more details.
//
//	You should have received a copy of the GNU General Public License
//	along with this program; if not, write to the Free Software
//	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

#ifndef f_DUBOUTPUT_H
#define f_DUBOUTPUT_H

#include <vector>
#include <vd2/system/VDString.h>
#include <vd2/system/vdalloc.h>
#include "AVIStripeSystem.h"
#include "fixes.h"

class AVIOutput;

class VDINTERFACE IVDDubberOutputSystem {
public:
	virtual AVIOutput *CreateSegment() = 0;
	virtual void CloseSegment(AVIOutput *pSegment, bool bLast) = 0;
	virtual void SetVideo(const AVIStreamHeader_fixed& asi, const void *pFormat, int cbFormat) = 0;
	virtual void SetAudio(const AVIStreamHeader_fixed& asi, const void *pFormat, int cbFormat, bool bInterleaved) = 0;
	virtual bool AcceptsVideo() = 0;
	virtual bool AcceptsAudio() = 0;
	virtual bool IsRealTime() = 0;
};

class VDAVIOutputFileSystem : public IVDDubberOutputSystem {
public:
	VDAVIOutputFileSystem();
	~VDAVIOutputFileSystem();

	void SetCaching(bool bAllowOSCaching);
	void SetIndexing(bool bAllowHierarchicalExtensions);
	void Set1GBLimit(bool bUse1GBLimit);
	void SetBuffer(int bufferSize);

	void SetFilename(const wchar_t *pszFilename);
	void SetFilenamePattern(const wchar_t *pszSegmentPrefix, const wchar_t *pszExt, int nMinimumDigits);

	AVIOutput *CreateSegment();
	void CloseSegment(AVIOutput *pSegment, bool bLast);
	void SetVideo(const AVIStreamHeader_fixed& asi, const void *pFormat, int cbFormat);
	void SetAudio(const AVIStreamHeader_fixed& asi, const void *pFormat, int cbFormat, bool bInterleaved);
	bool AcceptsVideo();
	bool AcceptsAudio();
	bool IsRealTime() { return false; }

private:
	VDStringW	mSegmentBaseName;
	VDStringW	mSegmentExt;
	int			mSegmentDigits;
	int			mCurrentSegment;
	int			mBufferSize;
	bool		mbInterleaved;
	bool		mbAllowCaching;
	bool		mbAllowIndexing;
	bool		mbUse1GBLimit;

	AVIStreamHeader_fixed	mVideoStreamInfo;
	std::vector<char>		mVideoFormat;
	AVIStreamHeader_fixed	mAudioStreamInfo;
	std::vector<char>		mAudioFormat;
};

class VDAVIOutputStripedSystem : public IVDDubberOutputSystem {
public:
	VDAVIOutputStripedSystem(const wchar_t *pszFilename);
	~VDAVIOutputStripedSystem();

	void Set1GBLimit(bool bUse1GBLimit);

	AVIOutput *CreateSegment();
	void CloseSegment(AVIOutput *pSegment, bool bLast);
	void SetVideo(const AVIStreamHeader_fixed& asi, const void *pFormat, int cbFormat);
	void SetAudio(const AVIStreamHeader_fixed& asi, const void *pFormat, int cbFormat, bool bInterleaved);
	bool AcceptsVideo();
	bool AcceptsAudio();
	bool IsRealTime() { return false; }

private:
	bool		mbUse1GBLimit;

	AVIStreamHeader_fixed	mVideoStreamInfo;
	std::vector<char>		mVideoFormat;
	AVIStreamHeader_fixed	mAudioStreamInfo;
	std::vector<char>		mAudioFormat;

	vdautoptr<AVIStripeSystem>	mpStripeSystem;
};

class VDAVIOutputWAVSystem : public IVDDubberOutputSystem {
public:
	VDAVIOutputWAVSystem(const wchar_t *pszFilename);
	~VDAVIOutputWAVSystem();

	AVIOutput *CreateSegment();
	void CloseSegment(AVIOutput *pSegment, bool bLast);
	void SetVideo(const AVIStreamHeader_fixed& asi, const void *pFormat, int cbFormat);
	void SetAudio(const AVIStreamHeader_fixed& asi, const void *pFormat, int cbFormat, bool bInterleaved);
	bool AcceptsVideo();
	bool AcceptsAudio();
	bool IsRealTime() { return false; }

private:
	VDStringW	mFilename;

	AVIStreamHeader_fixed	mAudioStreamInfo;
	std::vector<char>		mAudioFormat;
};

class VDAVIOutputImagesSystem : public IVDDubberOutputSystem {
public:
	VDAVIOutputImagesSystem();
	~VDAVIOutputImagesSystem();

	void SetFilenamePattern(const wchar_t *pszSegmentPrefix, const wchar_t *pszSegmentSuffix, int nMinimumDigits);
	void SetFormat(int format);

	AVIOutput *CreateSegment();
	void CloseSegment(AVIOutput *pSegment, bool bLast);
	void SetVideo(const AVIStreamHeader_fixed& asi, const void *pFormat, int cbFormat);
	void SetAudio(const AVIStreamHeader_fixed& asi, const void *pFormat, int cbFormat, bool bInterleaved);
	bool AcceptsVideo();
	bool AcceptsAudio();
	bool IsRealTime() { return false; }

private:
	VDStringW	mSegmentPrefix;
	VDStringW	mSegmentSuffix;
	int			mSegmentDigits;
	int			mFormat;			// from AVIOutputImages

	AVIStreamHeader_fixed	mVideoStreamInfo;
	std::vector<char>		mVideoFormat;
	AVIStreamHeader_fixed	mAudioStreamInfo;
	std::vector<char>		mAudioFormat;
};

class VDAVIOutputPreviewSystem : public IVDDubberOutputSystem {
public:
	VDAVIOutputPreviewSystem();
	~VDAVIOutputPreviewSystem();

	AVIOutput *CreateSegment();
	void CloseSegment(AVIOutput *pSegment, bool bLast);
	void SetVideo(const AVIStreamHeader_fixed& asi, const void *pFormat, int cbFormat);
	void SetAudio(const AVIStreamHeader_fixed& asi, const void *pFormat, int cbFormat, bool bInterleaved);
	bool AcceptsVideo();
	bool AcceptsAudio();
	bool IsRealTime() { return true; }

private:
	AVIStreamHeader_fixed	mVideoStreamInfo;
	std::vector<char>		mVideoFormat;
	AVIStreamHeader_fixed	mAudioStreamInfo;
	std::vector<char>		mAudioFormat;
};

#endif
