/*	
 *	clipcvid.h
 *
 *	Cinepakデコーダ
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2007 Naoyuki Sawa
 *
 *	* Fri Nov 16 16:28:45 JST 2007 Naoyuki Sawa
 *	- 1st リリース。
 *	- 実装のために参考にした資料を、「keep/Cinepak資料.7z」に保存しました。
 *	* Fri Nov 16 22:35:55 JST 2007 Naoyuki Sawa
 *	- CVIDSTRIP構造体の並びを、{v1[256],v4[256]}→{v4[256],v1[256]} に変更しました。
 *	* Sat Nov 17 20:54:00 JST 2007 Naoyuki Sawa
 *	- CVIDCODEBOOKビットフィールドの並びを、{v0,v1,v2,v3}→{v0,v2,v1,v3} に変更しました。
 *	* Wed Nov 18 21:37:53 JST 2015 Naoyuki Sawa
 *	- 'extern "C" {'〜'}'で囲みました。.cppを含むWin32プロジェクトからもインクルード出来るようにするためです。
 */
#ifndef __CLIP_CVID_H__
#define __CLIP_CVID_H__

#ifdef  __cplusplus
extern "C" {
#endif//__cplusplus

/****************************************************************************
 *	
 ****************************************************************************/

/*{{レイアウト固定*/
/* 効率良く4ピクセルづつプロットできるよう、{v0,v1,v2,v3}ではなく{v0,v2,v1,v3}の並びとしました。
 * 詳しくは、ASM版cvid_decode()のソースコードを参照してください。
 */
typedef struct _CVIDCODEBOOK {
	unsigned char y0 : 4;	/* +0,1 */
	unsigned char y2 : 4;
	unsigned char y1 : 4;	/* +1,1 */
	unsigned char y3 : 4;
} CVIDCODEBOOK;			/* =2 */
/*}}レイアウト固定*/

/*{{レイアウト固定*/
/* v1よりもv4の方が使用頻度が高いので、素早くアクセスできるよう、v1よりもv4を先に配置しました。
 * 詳しくは、ASM版cvid_decode()のソースコードを参照してください。
 */
typedef struct _CVIDSTRIP {
	CVIDCODEBOOK v4[256];	/* +   0,512 */
	CVIDCODEBOOK v1[256];	/* + 512,512 */
} CVIDSTRIP;			/* =1024 */
/*}}レイアウト固定*/

typedef struct _CVIDDRIVER {
/*{{レイアウト固定*/
	SURFACE surface;					/* + 0,12 (+0=w,+2=h,+4=vbuff,+8=zbuff) */
	unsigned char* buffer/*[strh.dwSuggestedBufferSize]*/;	/* +12, 4 */
	int num_strips;						/* +16, 4 */
	CVIDSTRIP* strips/*[num_strips]*/;			/* +20, 4 */
/*}}レイアウト固定*/
	HMMIO mmio;		/* ファイルハンドル */
	MMCKINFO mmci_riff;	/* RIFF('AVI ')チャンク */
	MMCKINFO mmci_movi;	/* LIST('movi')チャンク */
	MMCKINFO mmci_rec;	/* LIST('rec ')チャンク (ckidによって内外を判断) */
	int stri;		/* 何番目のストリームがCinepakビデオストリームか */
	AVIStreamHeader strh;	/* ストリームヘッダ (フレームレートなど) */
	BITMAPINFOHEADER strf;	/* ストリームフォーマット (解像度など) */
	int loop;		/* 0=再生終了, 1〜=残りループ回数, -1=無限ループ */
	int loop_pos;		/* ループ位置のファイルポインタ */
} CVIDDRIVER;

extern CVIDDRIVER cvid_driver;

/****************************************************************************
 *	
 ****************************************************************************/

#ifdef DEBUG
void cvid_enum(const char* fname);
#endif /*DEBUG*/

/* AVI形式のCinepakビデオストリームのデコードを準備します。
 * [in]
 *	fname		AVIファイル名。
 *	loop		1〜 = ループ回数, -1 = 無限ループ。
 * [out]
 *	cvid_driver
 *	.surface.w,h	4x4ピクセルの倍数に切り上げた解像度。
 *	.strh		フレーム間のインターバル[ms]は、以下の式で計算できます。
 *			=(1000*cvid_driver.strh.dwScale/cvid_driver.strh.dwRate)
 *	.strf		実サイズ。cvid_init()内のコメントを参照してください。
 * [note]
 *	* cvid_init()を呼ぶと、再生するファイルを開いたままの状態となります。
 *	  不要になったら、cvid_free()を呼び出して、ファイルを閉じてください。
 */
void cvid_init(const char* fname, int loop);

/* デコードを終了し、ファイルを閉じます。
 */
void cvid_free();

/* 1フレーム、デコードします。
 * [out]
 *	戻り値		再生継続ならば、0を返します。
 *			もうフレームが無く、再生終了ならば、0以外を返します。
 *			cvid_init()を呼び出した時にループを指定した場合には、
 *			適切な回数ループした後に、0以外(再生終了)を返します。
 *	cvid_driver
 *	.surface.vbuff	再生継続(戻り値0)の場合、フレームの画像を格納します。
 *			再生終了(戻り値0以外)の場合、前回の内容を維持します。
 * [note]
 *	* アプリケーションから、cvid_driver.surface.vbuffの内容を書き換えてはいけません。
 *	  Cinepakはフレーム間の差分更新であり、毎フレームの出力は変化部分だけだからです。
 */
int cvid_update();

#ifdef  __cplusplus
}//extern "C"
#endif//__cplusplus

#endif /*__CLIP_CVID_H__*/
