/// <summary>
/// 指定したAVI_CONTAINER構造体にAVIファイルの情報を格納すると共に,
/// ファイルにヘッダー情報を書き込みます.
/// </summary>
/// <param name="file">書き込み対象のファイル</param>
/// <param name="scale"></param>
/// <param name="rate"></param>
/// <param name="compressed"></param>
public unsafe bool Open( string file, uint scale, uint rate, int width, int height, bool compressed, bool transparent, IntPtr hWnd ) {
#if DEBUG
Console.WriteLine( "AviWriterEx.Open(string,uint,uint,bool,IntPtr)" );
#endif
m_stream = new BinaryWriter( new FileStream( file, FileMode.Create, FileAccess.Write ) );
float fps = (float)rate / (float)scale;
m_main_header.dwMicroSecPerFrame = (uint)(1.0e6 / fps);// ! 1秒は10^6μ秒
m_main_header.dwReserved1 = 0;
m_main_header.dwFlags = 2064;
m_main_header.dwInitialFrames = 0;
m_main_header.dwStreams = 0;
m_main_header.dwScale = scale;
m_main_header.dwRate = rate;
m_main_header.dwStart = 0;
m_main_header.dwLength = 0;
m_rate = rate;
m_scale = scale;
Util.fwrite( "RIFF", m_stream );
Util.WriteDWORD( 0, m_stream );
Util.fwrite( "AVI ", m_stream );
Util.fwrite( "LIST", m_stream );
Util.WriteDWORD( 0x9cc, m_stream );
Util.fwrite( "hdrl", m_stream );
m_current_chunk = 0;
m_position_in_chunk = 0L;
m_std_index = new AVISTDINDEX( 0L );
m_super_index = new AVISUPERINDEX( 0 );
m_riff_position = 0x4;
m_compressed = compressed;
m_is_transparent = transparent;
m_stream_fcc_handler = 0;
m_hwnd = hWnd;
m_file = file;
m_opened = true;
if ( m_is_first ) {
int stride = 0;
using ( Bitmap b = new Bitmap( width, height, m_is_transparent ? PixelFormat.Format32bppArgb : PixelFormat.Format24bppRgb ) ) {
BitmapData bd = b.LockBits( new Rectangle( 0, 0, width, height ),
ImageLockMode.ReadOnly,
b.PixelFormat );
stride = bd.Stride;
b.UnlockBits( bd );
}
m_is_first = false;
m_main_header.dwWidth = (uint)width;
m_main_header.dwHeight = (uint)height;
m_main_header.dwMaxBytesPerSec = (uint)(stride * height * frameRate);
m_main_header.dwStreams = 1;
m_main_header.dwSuggestedBufferSize = (uint)(stride * height);
m_linesize = stride;
m_stream_header.fccType = Util.mmioFOURCC( "vids" );
m_stream_header.fccHandler = 0;
m_stream_header.dwFlags = 0;
m_stream_header.dwReserved1 = 0;
m_stream_header.dwInitialFrames = 0;
m_stream_header.dwScale = m_scale;
m_stream_header.dwRate = m_rate;
m_stream_header.dwStart = 0;
m_stream_header.dwSuggestedBufferSize = m_main_header.dwSuggestedBufferSize;
m_stream_header.dwQuality = 0;
m_stream_header.dwSampleSize = 0;
Util.aviWriteMainHeader( m_main_header, m_stream );
Util.fwrite( "LIST", m_stream );
Util.WriteDWORD( 0x874, m_stream );
Util.fwrite( "strl", m_stream );
Util.aviWriteStreamHeader( m_stream_header, m_main_header, m_stream );
Util.fwrite( "strf", m_stream );
BITMAPINFOHEADER bih = new BITMAPINFOHEADER(); //(BITMAPINFOHEADER)Marshal.PtrToStructure( Marshal.AllocHGlobal( sizeof( BITMAPINFOHEADER ) ), typeof( BITMAPINFOHEADER ) );
bih.biSize = (uint)(Marshal.SizeOf( bih ));
bih.biWidth = width;
bih.biHeight = height;
bih.biPlanes = 1;
bih.biBitCount = m_is_transparent ? (short)32 : (short)24;
bih.biCompression = 0;//BI_RGB
bih.biSizeImage = (uint)(stride * height);
bih.biXPelsPerMeter = 0;
bih.biYPelsPerMeter = 0;
bih.biClrUsed = 0;
bih.biClrImportant = 0;
if ( m_compressed ) {
m_p_compvar = Marshal.AllocHGlobal( sizeof( COMPVARS ) );
m_compvar = (COMPVARS*)m_p_compvar.ToPointer();
byte[] buf = new byte[sizeof( COMPVARS )];
for ( int i = 0; i < buf.Length; i++ ) {
buf[i] = 0x0;
}
Marshal.Copy( buf, 0, m_p_compvar, buf.Length );
m_compvar->cbSize = sizeof( COMPVARS );
int ret = VCM.ICCompressorChoose( m_hwnd, 0, IntPtr.Zero, IntPtr.Zero, m_compvar, "Select Video Compressor" );
if ( ret == 0 ) {
m_opened = false;
Marshal.FreeHGlobal( m_p_compvar );
m_stream.Close();
return false;
}
if ( m_compvar->hic != 0 ) {
m_p_bitmapinfo_in = Marshal.AllocHGlobal( sizeof( BITMAPINFO ) );
m_bitmapinfo_in = (BITMAPINFO*)m_p_bitmapinfo_in.ToPointer();
buf = new byte[sizeof( BITMAPINFO )];
for ( int i = 0; i < buf.Length; i++ ) {
buf[i] = 0x0;
}
Marshal.Copy( buf, 0, m_p_bitmapinfo_in, buf.Length );
m_bitmapinfo_in->bmiHeader = bih;
uint dwSize = VCM.ICCompressGetFormatSize( m_compvar->hic, m_bitmapinfo_in );
#if DEBUG
Console.WriteLine( "m_compvar->hic=" + m_compvar->hic );
Console.WriteLine( "ICCompressGetFormatSize=" + dwSize );
#endif
m_p_bitmapinfo_out = Marshal.AllocHGlobal( (int)dwSize );
m_bitmapinfo_out = (BITMAPINFO*)m_p_bitmapinfo_out.ToPointer();
buf = new byte[dwSize];
for ( int i = 0; i < buf.Length; i++ ) {
buf[i] = 0x0;
}
Marshal.Copy( buf, 0, m_p_bitmapinfo_out, buf.Length );
VCM.ICCompressGetFormat( m_compvar->hic, m_bitmapinfo_in, m_bitmapinfo_out );
m_bih_compression = m_bitmapinfo_out->bmiHeader.biCompression;
#if DEBUG
Console.WriteLine( "AddFrame(Bitmap)" );
Console.WriteLine( " biout.biSize=" + m_bitmapinfo_out->bmiHeader.biSize );
#endif
VCM.ICSeqCompressFrameStart( m_compvar, m_bitmapinfo_in );
bih = m_bitmapinfo_out->bmiHeader;
Util.WriteDWORD( bih.biSize, m_stream );// infoHeaderのサイズ
m_bitmapinfo_out->Write( m_stream );
} else {
m_compressed = false;
Util.WriteDWORD( bih.biSize, m_stream );// infoHeaderのサイズ
bih.Write( m_stream );
}
} else {
Util.WriteDWORD( bih.biSize, m_stream );// infoHeaderのサイズ
bih.Write( m_stream );
}
m_super_index_position = m_stream.BaseStream.Position;
Util.fwrite( "indx", m_stream ); //fcc
Util.WriteDWORD( 0x7f8, m_stream ); // cb
Util.WriteWORD( (byte)0x4, m_stream ); // wLongsPerEntry
Util.WriteBYTE( 0x0, m_stream ); // bIndexSubType
Util.WriteBYTE( Util.AVI_INDEX_OF_INDEXES, m_stream );// bIndexType
Util.WriteDWORD( 0x0, m_stream ); // nEntriesInUse
Util.fwrite( "00db", m_stream ); // dwChunkId
Util.WriteDWORD( 0x0, m_stream );
Util.WriteDWORD( 0x0, m_stream );
Util.WriteDWORD( 0x0, m_stream );
for ( int ii = 1; ii <= 126; ii++ ) {
Util.WriteQWORD( 0x0, m_stream );
Util.WriteDWORD( 0x0, m_stream );
Util.WriteDWORD( 0x0, m_stream );
}
Util.fwrite( "LIST", m_stream );
Util.WriteDWORD( 0x104, m_stream );
Util.fwrite( "odml", m_stream );
Util.fwrite( "dmlh", m_stream );
Util.WriteDWORD( 0xf8, m_stream );
Util.WriteDWORD( 0x0, m_stream );//ここ後で更新するべき
for ( int ii = 1; ii <= 61; ii++ ) {
Util.WriteDWORD( 0x0, m_stream );
}
Util.fwrite( "JUNK", m_stream );
Util.WriteDWORD( 0x60c, m_stream );
Util.WriteDWORD( 0, m_stream );//"This"が将来登録されたらやばいので
string msg = "This file was generated by [email protected];VfwBugCompatible=" + VfwBugCompatible;
const int tlen = 1544;
int remain = tlen - msg.Length;
Util.fwrite( msg, m_stream );
for ( int i = 1; i <= remain; i++ ) {
m_stream.Write( (byte)0 );
}
m_junk_length = 0xff4;
Util.fwrite( "LIST", m_stream );
m_movi_position = m_stream.BaseStream.Position;
Util.WriteDWORD( 0, m_stream );// call bmpQWordWrite( 0, avi%fp ) !// ******************ココの数字は一番最後に書き換える必要あり2040~2043あとdwTotalFrames(48~51)も
Util.fwrite( "movi", m_stream );
m_next_framedata_position = m_stream.BaseStream.Position;
m_std_index.SetBaseOffset( (ulong)m_next_framedata_position );
m_super_index.nEntriesInUse++;
}
return true;
}