//au2802プロジェクト  
// グラフィック描画のためにlist0808.cppを使用する
// C/C++の設定をマルチスレッドに変更 
#include <Windows.h>
#include <vfw.h>
// Video for Windows include file
// 併せてvfw32.libの追加が必要
// PlaySoundのためwinmm.libの追加が必要
#include <stdio.h>
#include <conio.h>		// getch()の宣言
#include <math.h>		// fabs();
#include "list0808.h"

void f_avi( char * );
////////

void main()
{
	char * pfn;
	pfn = file_open(  );
	f_avi( pfn );
	printf("quit?");
	getch();
	gr_quit();	
	return ;

}

void f_avi( char * pfn )
{
	int i, j, jj, k;
	PAVIFILE	paviin;
	AVIFILEINFO pfi;
	AVISTREAMINFO si[2];
	PAVISTREAM pvs[2];
	HRESULT rc;
	PGETFRAME pvf;
	LPBITMAPINFOHEADER pbmpih;
	char cbuf[100];
	int  nsw = 0;		//av28
	int  ssw = 0;
	int  msw = 0;
	int  au;
	int  vi;
	double * a0;
	double * v0;
	double * v1;		// av_1	diff
	double as,vs,vs1;
	short int  * ap;	

	rc = AVIFileOpen( &paviin, pfn, OF_READ, NULL);
	if( rc ) { printf( "open err\n" );
		return;
	}

	pfi.dwStreams = 0;
	AVIFileInfo(paviin, &pfi, sizeof(AVIFILEINFO));
	printf( "strs = %d \n", pfi.dwStreams);

	for( i = 0; i < pfi.dwStreams; i++ ){
		AVIFileGetStream( paviin, &(pvs[i]), 0, i );
		AVIStreamAddRef(pvs[i]);	// ストリームの参照カウントを1増やす
		AVIStreamInfo( pvs[i], &(si[i]), sizeof(AVISTREAMINFO) );
		if( si[i].fccType == streamtypeVIDEO )
			vi = i;
		if( si[i].fccType == streamtypeAUDIO )
			au = i;
	}
	pvf = AVIStreamGetFrameOpen( pvs[vi], 
		(LPBITMAPINFOHEADER)AVIGETFRAMEF_BESTDISPLAYFMT);
			// 解凍の準備
	printf("vi_S=%d vi_R=%d vi_length=%d \n",
		si[vi].dwScale, si[vi].dwRate, si[vi].dwLength);
	int nfh = si[vi].rcFrame.bottom - si[vi].rcFrame.top;
	int nfw = si[vi].rcFrame.right  - si[vi].rcFrame.left; 
	printf( "h = %d w = %d\n", nfh , nfw);
	printf(	"au_S=%d au_R=%d au_length=%d %d(frame)\n",
		si[au].dwScale, si[au].dwRate, si[au].dwLength, si[au].dwLength/1067);		
	printf("non_monitor - nキー , 表示 - s以外のキー ?");
	if(getch() == 'n')
		nsw = 1;
	if( nsw == 0 ){
		printf("\nコマ送り - sキー , 連続表示 - s以外のキー ?");
		if(getch() == 's')
			ssw = 1;
		printf("\n白黒 - mキー , カラー - m以外のキー ?");
		if(getch() == 'm')
			msw = 1;
	}

	a0 = (double *) malloc( si[vi].dwLength * sizeof(double));
	v0 = (double *) malloc( si[vi].dwLength * sizeof(double));
	v1 = (double *) malloc( si[vi].dwLength * sizeof(double));

	// 以下の関数はlist0808.cppで定義されている 	
	gr_init( nfw, nfh );		// グラフィックウィンドウを生成
	gr_clr();			// 仮想画面クリア
	gr_draw();			// 仮想画面をグラフィックウィンドウにコピー
	gr_active();	
		
	int cnt = 0x40 + nfw * nfh *3 +100;
	printf("cnt = %d\n",cnt);
	BYTE * bmp0;
	BYTE * bmp1;
	bmp0 = (BYTE *)malloc( cnt );
	bmp1 = (BYTE *)malloc( cnt );
	int nn,m,km;

	long ab,ab2;
	BYTE * pbuf;	
	PCMWAVEFORMAT pwf;
	BYTE *fp;
	int n ;
	char fname[100];
	int ns =  1067 * 2;			// 1/29.97秒
	pbuf = (BYTE *)malloc( ns + 1000);	// 1/29.97秒 * 32kHz
	pwf.wf.wFormatTag = WAVE_FORMAT_PCM;
	//MMREG.H(1394):#define WAVE_FORMAT_PCM     1
	//MMSYSTEM.H(703):#define WAVE_FORMAT_PCM     1
	pwf.wf.nChannels       =      1;
	pwf.wf.nSamplesPerSec  =  32000;
	pwf.wf.nAvgBytesPerSec =  64000;
	pwf.wf.nBlockAlign     =      2;
	pwf.wBitsPerSample     =     16;
	BYTE * pp;
	// 1フレーム毎切り出しのループ
	for( jj = 0; jj< si[vi].dwLength; jj++){
		// ビデオストリームから1フレーム切り出す
		// 0フレームが最初のフレーム
		pbmpih = (LPBITMAPINFOHEADER)AVIStreamGetFrame(pvf,jj);
		int	cnt = (pbmpih -> biSize) + (pbmpih->biSizeImage);
//		printf( "j= %d pbmp = %d bmpih.h = %d size =%d all = %d\n", 
//			jj,pbmpih -> biSize  , pbmpih->biBitCount , 
//			pbmpih->biSizeImage, cnt);
		// 描画ウィンドウへ描画のための準備、list0808.cppの関数
		// ppにbmpのデータ部分の先頭が渡される
		pp = gr_set_bmph( pbmpih );
		vs = 0;	
		vs1 = 0;
		for(k = 0;k < nfh ;k++){
			for(m =0;m< nfw ;m++){
				km = (k * nfw + m ) * 3;
				if( msw ){
					nn =( pp[km ]	
						+ pp[km  +1]	
						+ pp[km  +2] )/3;
					bmp0[km ]=	bmp0[km +1]	
						= bmp0[km +2] = nn;
				}
				else{
					bmp0[km ]    = pp[km ];
					bmp0[km  +1] = pp[km +1]	;
					bmp0[km  +2] = pp[km +2] ;
				}
				// av	:画面平均輝度の計算
				vs = vs +  pp[km ] + pp[km +1] + pp[km +2] ;
				// av_1	:平均変化量の計算
				vs1 = vs1 +	fabs( bmp0[km ]   - bmp1[km ]  )
					      +	fabs( bmp0[km +1] - bmp1[km +1])
					      + fabs( bmp0[km +2] - bmp1[km +2]);
				bmp1[km   ] = bmp0[km   ];
				bmp1[km +1]	= bmp0[km +1];
				bmp1[km +2]	= bmp0[km +2];
			}
		}
		// 画素数で割る	
		v0[jj]=vs  / (640.0 * 480.0 * 3);		// av	
		v1[jj]=vs1 / (640.0 * 480.0 * 3);		// av_1 			
		wsprintf(cbuf,"[%s] frame %d/%d ",pfn, jj, si[vi].dwLength);
		gr_caption( cbuf );
		if( nsw == 0){
			gr_bmp( bmp0);
			gr_draw();
		}
		if( ssw ){
			int r;
			r = MessageBox(NULL,  
		"次のフレーム-はい 前のフレーム-いいえ 連続表示-キャンセル",
				"...",
				MB_YESNOCANCEL);
			if( r == IDNO )
				jj=jj-2;
			if( r == IDCANCEL )
				ssw = 0;
		}
		// オーディオの処理
		wsprintf( cbuf,"RIFF");
		fp = pbuf;
		fp = swrite( (BYTE *)cbuf,  4, fp);
		n = 20 + 16 + 8 + ns;
		fp = swrite( (BYTE *)(&n), 4, fp);
		wsprintf(cbuf,"WAVEfmt ");
		fp = swrite( (BYTE *)cbuf, 8, fp);
		n = 16;	
		fp = swrite( (BYTE *)(&n), 4, fp);
		fp = swrite( (BYTE *)(&pwf), 16, fp);
		wsprintf(cbuf,"data");
		fp = swrite( (BYTE *)cbuf, 4,fp);
		fp = swrite( (BYTE *)(&ns), 4, fp);
		// オーディオのストリームを1フレーム(nsサンプル)分読み出す	
		AVIStreamRead( pvs[au], jj * ns/2, ns, fp, ns, &ab, &ab2);
		if( nsw == 0){			// av28	
			PlaySound( (char *)pbuf, NULL, 
				SND_MEMORY | SND_SYNC);	
		}
		// 1フレーム分平均の音の大きさを計算
		ap = (short int *)fp;
		as = 0;
		for(j = 0;j < ns/2; j++){
			as = as + fabs( (double)ap[j] );
		}
		a0[jj]= as / (double)(ns/2);
		printf("frame= %4d v0= %7.3f v1= %7.3f a0= %7.1f\n", 
			jj, v0[jj], v1[jj], a0[jj]);
	}
	AVIStreamGetFrameClose(pvf);
	AVIStreamRelease( pvs[0]);
	AVIStreamRelease( pvs[1]);
	AVIFileRelease( paviin );

	// csv形式で計算結果をファイルに保存
	char ccbuf[100];
	char cb2[100];
	i =0;
	while( pfn[i] != '.'){
		ccbuf[i] = pfn[i];
		i++;
	}
	ccbuf[i]=0;
	sprintf(cb2,"%s_2.csv",ccbuf);
	FILE *fp2;
	fp2 = fopen(cb2,"w");
	for(i = 0;i< si[vi].dwLength;i++)
		fprintf(fp2, "%f,%f,%f \n", v0[i], v1[i], a0[i] );
	fclose(fp2 );

}