Desenvolver e Download de Software Open Source

Browse Subversion Repository

Contents of /trunk/Boare.Lib.Media/AviWriterVcm.cs

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6 - (show annotations) (download)
Thu Jun 25 14:16:22 2009 UTC (14 years, 10 months ago) by kbinani
File size: 26491 byte(s)


1 /*
2 * AviWriter.cs
3 * Copyright (c) 2007-2009 kbinani
4 *
5 * This file is part of Boare.Lib.Media.
6 *
7 * Boare.Lib.Media is free software; you can redistribute it and/or
8 * modify it under the terms of the BSD License.
9 *
10 * Boare.Lib.Media is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 */
14 using System;
15 using System.Drawing;
16 using System.Drawing.Imaging;
17 using System.IO;
18 using System.Runtime.InteropServices;
19
20 using bocoree;
21
22 namespace Boare.Lib.Media {
23
24 public unsafe class AviWriterVcm : IAviWriter {
25 private const long _THRESHOLD = 1000000000L; //AVIXリストの最大サイズ(byte)
26 private MainAVIHeader m_main_header;
27 private AVIStreamHeader m_stream_header;
28 private BinaryWriter m_stream;
29 private int m_current_chunk = 0;
30 private long m_position_in_chunk = 0L;
31 private long m_split_sreshold = 160000000L; //AVIリストの最大サイズ(byte)
32 private AVISTDINDEX m_std_index;
33 private AVISUPERINDEX m_super_index;
34 private int m_linesize;//bitmapの1行分のデータサイズ(byte)
35 private bool m_is_first = true;
36 private long m_riff_position;//"RIFF*"の*が記入されているファイルの絶対位置。RIFF-AVI のときは必ず4。RIFF-AVIXの時は変化する
37 private long m_movi_position;
38 private long m_next_framedata_position;//次に00dbデータを記入するべき場所
39 private long m_avix_position;
40 private int m_junk_length;
41 private uint m_scale;
42 private uint m_rate;
43 private bool m_compressed = false;
44 private IntPtr m_hwnd = IntPtr.Zero;
45 private uint m_stream_fcc_handler = 808810089;
46 private string m_file;
47 //private int m_addr_compvar;
48 //private COMPVARS m_compvar;
49 private COMPVARS* m_compvar;
50 private BITMAPINFO* m_bitmapinfo_in;
51 private BITMAPINFO* m_bitmapinfo_out;
52 private IntPtr m_p_compvar;
53 private IntPtr m_p_bitmapinfo_in;
54 private IntPtr m_p_bitmapinfo_out;
55 private uint m_bih_compression = 0;
56 private long m_super_index_position;
57 private bool m_closed = false;
58 private bool m_opened = false;
59 private bool m_is_transparent = false;
60 /// <summary>
61 /// 現在記入中のmoviチャンクのサイズ
62 /// </summary>
63 private long m_this_movi_size = 0;
64
65 private static bool s_vfw_bug_compati = false;
66
67 public Size Size {
68 get {
69 return new Size( (int)m_main_header.dwWidth, (int)m_main_header.dwHeight );
70 }
71 }
72
73 public uint Scale {
74 get {
75 return m_scale;
76 }
77 }
78
79 public uint Rate {
80 get {
81 return m_rate;
82 }
83 }
84
85 /// <summary>
86 /// Video For Windows APIとバグコンパチブルな動作をするかどうかを表す値を取得または設定します
87 /// </summary>
88 public static bool VfwBugCompatible {
89 get {
90 return s_vfw_bug_compati;
91 }
92 set {
93 s_vfw_bug_compati = value;
94 }
95 }
96
97 internal float frameRate {
98 get {
99 return (float)m_rate / (float)m_scale;
100 }
101 }
102
103 /// <summary>
104 /// 指定したAVI_CONTAINER構造体にAVIファイルの情報を格納すると共に,
105 /// ファイルにヘッダー情報を書き込みます.
106 /// </summary>
107 /// <param name="file">書き込み対象のファイル</param>
108 /// <param name="scale"></param>
109 /// <param name="rate"></param>
110 /// <param name="compressed"></param>
111 public unsafe bool Open( string file, uint scale, uint rate, int width, int height, bool compressed, bool transparent, IntPtr hWnd ) {
112 #if DEBUG
113 Console.WriteLine( "AviWriterEx.Open(string,uint,uint,bool,IntPtr)" );
114 #endif
115 m_stream = new BinaryWriter( new FileStream( file, FileMode.Create, FileAccess.Write ) );
116 float fps = (float)rate / (float)scale;
117 m_main_header.dwMicroSecPerFrame = (uint)(1.0e6 / fps);// ! 1秒は10^6μ秒
118 m_main_header.dwReserved1 = 0;
119 m_main_header.dwFlags = 2064;
120 m_main_header.dwInitialFrames = 0;
121 m_main_header.dwStreams = 0;
122 m_main_header.dwScale = scale;
123 m_main_header.dwRate = rate;
124 m_main_header.dwStart = 0;
125 m_main_header.dwLength = 0;
126 m_rate = rate;
127 m_scale = scale;
128 Util.fwrite( "RIFF", m_stream );
129 Util.WriteDWORD( 0, m_stream );
130 Util.fwrite( "AVI ", m_stream );
131 Util.fwrite( "LIST", m_stream );
132 Util.WriteDWORD( 0x9cc, m_stream );
133 Util.fwrite( "hdrl", m_stream );
134 m_current_chunk = 0;
135 m_position_in_chunk = 0L;
136 m_std_index = new AVISTDINDEX( 0L );
137 m_super_index = new AVISUPERINDEX( 0 );
138 m_riff_position = 0x4;
139 m_compressed = compressed;
140 m_is_transparent = transparent;
141 m_stream_fcc_handler = 0;
142 m_hwnd = hWnd;
143 m_file = file;
144 m_opened = true;
145 if ( m_is_first ) {
146 int stride = 0;
147 using ( Bitmap b = new Bitmap( width, height, m_is_transparent ? PixelFormat.Format32bppArgb : PixelFormat.Format24bppRgb ) ) {
148 BitmapData bd = b.LockBits( new Rectangle( 0, 0, width, height ),
149 ImageLockMode.ReadOnly,
150 b.PixelFormat );
151 stride = bd.Stride;
152 b.UnlockBits( bd );
153 }
154 m_is_first = false;
155 m_main_header.dwWidth = (uint)width;
156 m_main_header.dwHeight = (uint)height;
157 m_main_header.dwMaxBytesPerSec = (uint)(stride * height * frameRate);
158 m_main_header.dwStreams = 1;
159 m_main_header.dwSuggestedBufferSize = (uint)(stride * height);
160 m_linesize = stride;
161
162 m_stream_header.fccType = Util.mmioFOURCC( "vids" );
163 m_stream_header.fccHandler = 0;
164 m_stream_header.dwFlags = 0;
165 m_stream_header.dwReserved1 = 0;
166 m_stream_header.dwInitialFrames = 0;
167 m_stream_header.dwScale = m_scale;
168 m_stream_header.dwRate = m_rate;
169 m_stream_header.dwStart = 0;
170 m_stream_header.dwSuggestedBufferSize = m_main_header.dwSuggestedBufferSize;
171 m_stream_header.dwQuality = 0;
172 m_stream_header.dwSampleSize = 0;
173
174 Util.aviWriteMainHeader( m_main_header, m_stream );
175
176 Util.fwrite( "LIST", m_stream );
177 Util.WriteDWORD( 0x874, m_stream );
178 Util.fwrite( "strl", m_stream );
179
180 Util.aviWriteStreamHeader( m_stream_header, m_main_header, m_stream );
181
182 Util.fwrite( "strf", m_stream );
183 BITMAPINFOHEADER bih = new BITMAPINFOHEADER(); //(BITMAPINFOHEADER)Marshal.PtrToStructure( Marshal.AllocHGlobal( sizeof( BITMAPINFOHEADER ) ), typeof( BITMAPINFOHEADER ) );
184 bih.biSize = (uint)(Marshal.SizeOf( bih ));
185 bih.biWidth = width;
186 bih.biHeight = height;
187 bih.biPlanes = 1;
188 bih.biBitCount = m_is_transparent ? (short)32 : (short)24;
189 bih.biCompression = 0;//BI_RGB
190 bih.biSizeImage = (uint)(stride * height);
191 bih.biXPelsPerMeter = 0;
192 bih.biYPelsPerMeter = 0;
193 bih.biClrUsed = 0;
194 bih.biClrImportant = 0;
195
196 if ( m_compressed ) {
197 m_p_compvar = Marshal.AllocHGlobal( sizeof( COMPVARS ) );
198 m_compvar = (COMPVARS*)m_p_compvar.ToPointer();
199 byte[] buf = new byte[sizeof( COMPVARS )];
200 for ( int i = 0; i < buf.Length; i++ ) {
201 buf[i] = 0x0;
202 }
203 Marshal.Copy( buf, 0, m_p_compvar, buf.Length );
204 m_compvar->cbSize = sizeof( COMPVARS );
205 int ret = VCM.ICCompressorChoose( m_hwnd, 0, IntPtr.Zero, IntPtr.Zero, m_compvar, "Select Video Compressor" );
206 if ( ret == 0 ) {
207 m_opened = false;
208 Marshal.FreeHGlobal( m_p_compvar );
209 m_stream.Close();
210 return false;
211 }
212 if ( m_compvar->hic != 0 ) {
213 m_p_bitmapinfo_in = Marshal.AllocHGlobal( sizeof( BITMAPINFO ) );
214 m_bitmapinfo_in = (BITMAPINFO*)m_p_bitmapinfo_in.ToPointer();
215 buf = new byte[sizeof( BITMAPINFO )];
216 for ( int i = 0; i < buf.Length; i++ ) {
217 buf[i] = 0x0;
218 }
219 Marshal.Copy( buf, 0, m_p_bitmapinfo_in, buf.Length );
220 m_bitmapinfo_in->bmiHeader = bih;
221 uint dwSize = VCM.ICCompressGetFormatSize( m_compvar->hic, m_bitmapinfo_in );
222 #if DEBUG
223 Console.WriteLine( "m_compvar->hic=" + m_compvar->hic );
224 Console.WriteLine( "ICCompressGetFormatSize=" + dwSize );
225 #endif
226 m_p_bitmapinfo_out = Marshal.AllocHGlobal( (int)dwSize );
227 m_bitmapinfo_out = (BITMAPINFO*)m_p_bitmapinfo_out.ToPointer();
228 buf = new byte[dwSize];
229 for ( int i = 0; i < buf.Length; i++ ) {
230 buf[i] = 0x0;
231 }
232 Marshal.Copy( buf, 0, m_p_bitmapinfo_out, buf.Length );
233 VCM.ICCompressGetFormat( m_compvar->hic, m_bitmapinfo_in, m_bitmapinfo_out );
234 m_bih_compression = m_bitmapinfo_out->bmiHeader.biCompression;
235 #if DEBUG
236 Console.WriteLine( "AddFrame(Bitmap)" );
237 Console.WriteLine( " biout.biSize=" + m_bitmapinfo_out->bmiHeader.biSize );
238 #endif
239 VCM.ICSeqCompressFrameStart( m_compvar, m_bitmapinfo_in );
240 bih = m_bitmapinfo_out->bmiHeader;
241 Util.WriteDWORD( bih.biSize, m_stream );// infoHeaderのサイズ
242 m_bitmapinfo_out->Write( m_stream );
243 } else {
244 m_compressed = false;
245 Util.WriteDWORD( bih.biSize, m_stream );// infoHeaderのサイズ
246 bih.Write( m_stream );
247 }
248 } else {
249 Util.WriteDWORD( bih.biSize, m_stream );// infoHeaderのサイズ
250 bih.Write( m_stream );
251 }
252
253 m_super_index_position = m_stream.BaseStream.Position;
254 Util.fwrite( "indx", m_stream ); //fcc
255 Util.WriteDWORD( 0x7f8, m_stream ); // cb
256 Util.WriteWORD( (byte)0x4, m_stream ); // wLongsPerEntry
257 Util.WriteBYTE( 0x0, m_stream ); // bIndexSubType
258 Util.WriteBYTE( Util.AVI_INDEX_OF_INDEXES, m_stream );// bIndexType
259 Util.WriteDWORD( 0x0, m_stream ); // nEntriesInUse
260 Util.fwrite( "00db", m_stream ); // dwChunkId
261 Util.WriteDWORD( 0x0, m_stream );
262 Util.WriteDWORD( 0x0, m_stream );
263 Util.WriteDWORD( 0x0, m_stream );
264 for ( int ii = 1; ii <= 126; ii++ ) {
265 Util.WriteQWORD( 0x0, m_stream );
266 Util.WriteDWORD( 0x0, m_stream );
267 Util.WriteDWORD( 0x0, m_stream );
268 }
269
270 Util.fwrite( "LIST", m_stream );
271 Util.WriteDWORD( 0x104, m_stream );
272 Util.fwrite( "odml", m_stream );
273 Util.fwrite( "dmlh", m_stream );
274 Util.WriteDWORD( 0xf8, m_stream );
275 Util.WriteDWORD( 0x0, m_stream );//ここ後で更新するべき
276 for ( int ii = 1; ii <= 61; ii++ ) {
277 Util.WriteDWORD( 0x0, m_stream );
278 }
279
280 Util.fwrite( "JUNK", m_stream );
281 Util.WriteDWORD( 0x60c, m_stream );
282 Util.WriteDWORD( 0, m_stream );//"This"が将来登録されたらやばいので
283 string msg = "This file was generated by AviWriter@Boare.Lib.Media;VfwBugCompatible=" + VfwBugCompatible;
284 const int tlen = 1544;
285 int remain = tlen - msg.Length;
286 Util.fwrite( msg, m_stream );
287 for ( int i = 1; i <= remain; i++ ) {
288 m_stream.Write( (byte)0 );
289 }
290 m_junk_length = 0xff4;
291
292 Util.fwrite( "LIST", m_stream );
293 m_movi_position = m_stream.BaseStream.Position;
294 Util.WriteDWORD( 0, m_stream );// call bmpQWordWrite( 0, avi%fp ) !// ******************ココの数字は一番最後に書き換える必要あり2040~2043あとdwTotalFrames(48~51)も
295 Util.fwrite( "movi", m_stream );
296 m_next_framedata_position = m_stream.BaseStream.Position;
297
298 m_std_index.SetBaseOffset( (ulong)m_next_framedata_position );
299 m_super_index.nEntriesInUse++;
300 }
301 return true;
302 }
303
304 public bool Open( string file, uint scale, uint rate, int width, int height, IntPtr hwnd ) {
305 return Open( file, scale, rate, width, height, false, false, hwnd );
306 }
307
308 //todo: AVIMainHeader.dwTotalFramesに、ファイル全体のフレーム数を入れる(仕様違反)
309 //todo: AVIStreamHeader.dwLengthに、ファイル全体のフレーム数を入れる(仕様違反)
310 /// <summary>
311 /// 全てのインデックスを更新し、ファイルが(動画ファイルとして)使用できる状態にします
312 /// この関数を読んだあとでも,さらにaviAddFrame関数を使うことでフレームを追加することが出来ます.
313 /// </summary>
314 public void UpdateIndex() {
315 _avisuperindex_entry entry = m_super_index.aIndex[m_current_chunk];
316 entry.qwOffset = (ulong)m_stream.BaseStream.Position;
317 entry.dwSize = m_std_index.cb;
318 m_super_index.aIndex[m_current_chunk] = entry;
319 if ( m_stream.BaseStream.Position != m_next_framedata_position ) {
320 m_stream.BaseStream.Seek( m_next_framedata_position, SeekOrigin.Begin );
321 }
322 m_std_index.Write( m_stream );
323 int frames = (int)m_super_index.aIndex[m_current_chunk].dwDuration;
324 m_avix_position = m_stream.BaseStream.Position;
325
326 if ( m_current_chunk == 0 ) {
327 uint i, step, number;
328 step = m_main_header.dwSuggestedBufferSize + 8;
329
330 Util.fwrite( "idx1", m_stream );
331 Util.WriteDWORD( (uint)(16 * frames), m_stream );
332 for ( i = 1; i <= frames; i++ ) {
333 Util.fwrite( "00db", m_stream );
334 Util.WriteDWORD( Util.AVIF_HASINDEX, m_stream );
335 Util.WriteDWORD( (uint)(4 + (i - 1) * step), m_stream );
336 Util.WriteDWORD( m_main_header.dwSuggestedBufferSize, m_stream );
337 }
338 m_avix_position = m_stream.BaseStream.Position;
339
340 number = (uint)frames;
341 m_stream.Seek( 0x30, SeekOrigin.Begin );
342 Util.WriteDWORD( number, m_stream );
343 m_stream.Seek( 0x8c, SeekOrigin.Begin );
344 Util.WriteDWORD( number, m_stream );
345
346 //odml dlmhのdwTotalFrames
347 m_stream.Seek( 0x8e8, SeekOrigin.Begin );
348 Util.WriteDWORD( (uint)frames, m_stream );
349
350 // LIST****moviの****の数値を計算
351 number = 4;//"movi"
352 number += (uint)(m_this_movi_size + 8 * frames);// (uint)(frames * (m_linesize * m_main_header.dwHeight + 8));//フレーム数*(フレームのサイズ+"00db"+00dbチャンクのサイズ)
353 number += 4 + 4 + (uint)m_std_index.cb; //ix00のサイズ
354 m_stream.BaseStream.Seek( m_movi_position, SeekOrigin.Begin );
355 Util.WriteDWORD( number, m_stream );
356
357 //number = 4096 + (this.mainHeader.dwSuggestedBufferSize + 24) * this.noOfFrame;
358 //avi_writeIsolate( this.fp, number, 4 ); // RIFF****AVI の ****部分
359 number = (uint)m_junk_length/* 0xff4*/; //JUNKの終わりまでのサイズ。これは固定
360 number += 4;//"movi"
361 number += (uint)(m_this_movi_size + 8 * frames);//00db...の合計サイズ
362 number += 4 + 4 + (uint)m_std_index.cb;
363 number += (uint)(4 + 4 + 16 * frames);//idx1のサイズ
364 m_stream.BaseStream.Seek( m_riff_position, SeekOrigin.Begin );
365 Util.WriteDWORD( number, m_stream );
366 UpdateIndexOfIndex();
367 } else {
368 // LIST****moviの****を更新
369 uint number = 4;
370 number += (uint)(m_this_movi_size + frames * 8);
371 number += 8 + (uint)m_std_index.cb;
372 m_stream.BaseStream.Seek( m_movi_position, SeekOrigin.Begin );
373 Util.WriteDWORD( number, m_stream );
374
375 // odml dlmhのdwTotalFrames
376 uint frames2 = 0;
377 for ( int j = 0; j <= m_current_chunk; j++ ) {
378 frames2 += (uint)m_super_index.aIndex[j].dwDuration;
379 }
380 m_stream.BaseStream.Seek( 0x8e8, SeekOrigin.Begin );
381 Util.WriteDWORD( frames2, m_stream );
382
383 m_stream.Seek( 48, SeekOrigin.Begin );
384 Util.WriteDWORD( frames2, m_stream );
385
386 m_stream.Seek( 140, SeekOrigin.Begin );
387 Util.WriteDWORD( frames2, m_stream );
388
389 //RIFF****AVIXの****を更新
390 long num2 = m_junk_length + number;
391 m_stream.BaseStream.Seek( m_riff_position, SeekOrigin.Begin );
392 Util.WriteDWORD( (uint)num2, m_stream );
393 UpdateIndexOfIndex();
394 }
395 }
396
397 /// <summary>
398 /// aviファイルを閉じます
399 /// </summary>
400 public unsafe void Close() {
401 UpdateIndex();
402 m_stream.Close();
403 if ( m_compressed ) {
404 m_stream_fcc_handler = m_compvar->fccHandler;
405 VCM.ICSeqCompressFrameEnd( m_compvar );
406 VCM.ICCompressorFree( m_compvar );
407 using ( FileStream fs = new FileStream( m_file, FileMode.Open ) ) {
408 fs.Seek( 0x70, SeekOrigin.Begin );
409 {
410 byte ch3 = (byte)(m_stream_fcc_handler >> 24);
411 uint b = (uint)(m_stream_fcc_handler - (ch3 << 24));
412 byte ch2 = (byte)(b >> 16);
413 b = (uint)(b - (ch2 << 16));
414 byte ch1 = (byte)(b >> 8);
415 byte ch0 = (byte)(b - (ch1 << 8));
416 fs.Write( new byte[] { ch0, ch1, ch2, ch3 }, 0, 4 );
417 }
418 fs.Seek( 0xbc, SeekOrigin.Begin );
419 {
420 byte ch3 = (byte)(m_bih_compression >> 24);
421 uint b = (uint)(m_bih_compression - (ch3 << 24));
422 byte ch2 = (byte)(b >> 16);
423 b = (uint)(b - (ch2 << 16));
424 byte ch1 = (byte)(b >> 8);
425 byte ch0 = (byte)(b - (ch1 << 8));
426 fs.Write( new byte[] { ch0, ch1, ch2, ch3 }, 0, 4 );
427 }
428 }
429 }
430 m_closed = true;
431 }
432
433 ~AviWriterVcm() {
434 if ( m_opened && !m_closed ) {
435 Close();
436 }
437 }
438
439 /// <summary>
440 /// 最初の[AVI :AVI[LIST:hdrl[LIST:strl]]]に書き込まれているsuper indexチャンク[indx]を更新します
441 /// </summary>
442 private void UpdateIndexOfIndex() {
443 m_stream.Seek( (int)m_super_index_position, SeekOrigin.Begin );
444 m_super_index.Write( m_stream );
445 }
446
447
448 /// <summary>
449 /// aviファイルにフレームを1つ追加します.
450 /// </summary>
451 /// <param name="bmp"></param>
452 public unsafe void AddFrame( Bitmap bmp ) {
453 int width, height, lineSize;
454 BitmapData bmpDat;
455 if ( m_is_transparent ) {
456 bmpDat = bmp.LockBits( new Rectangle( 0, 0, bmp.Width, bmp.Height ),
457 ImageLockMode.ReadOnly,
458 PixelFormat.Format32bppArgb );
459 } else {
460 bmpDat = bmp.LockBits( new Rectangle( 0, 0, (int)bmp.Width, (int)bmp.Height ),
461 ImageLockMode.ReadOnly,
462 PixelFormat.Format24bppRgb );
463 }
464
465 if ( m_next_framedata_position != m_stream.BaseStream.Position ) {
466 m_stream.BaseStream.Seek( m_next_framedata_position, SeekOrigin.Begin );
467 }
468
469 long chunk_size = m_next_framedata_position - m_riff_position;
470 if ( (m_current_chunk == 0 && chunk_size > m_split_sreshold) ||
471 (m_current_chunk > 0 && chunk_size > _THRESHOLD) ) {
472 // AVIXリストへの書き込みに移行
473 UpdateIndex();
474 m_stream.BaseStream.Seek( m_avix_position, SeekOrigin.Begin );
475 Util.fwrite( "RIFF", m_stream );
476 m_riff_position = m_stream.BaseStream.Position;
477 Util.WriteDWORD( 0, m_stream );
478 Util.fwrite( "AVIX", m_stream );
479 long current = m_stream.BaseStream.Position;
480 if ( (current + 12) % 0x800 != 0 ) {
481 long additional = (current + 20) % 0x800;
482 additional = 0x800 - ((current + 20) % 0x800);
483 m_junk_length = (int)additional + 20;
484 Util.fwrite( "JUNK", m_stream );
485 Util.WriteDWORD( (uint)additional, m_stream );
486 for ( long ii = 0; ii < additional; ii++ ) {
487 Util.WriteBYTE( (byte)0, m_stream );
488 }
489 } else {
490 m_junk_length = 0;
491 }
492 m_junk_length = 0;
493
494 Util.fwrite( "LIST", m_stream );
495 m_movi_position = m_stream.BaseStream.Position;
496 Util.WriteDWORD( 0, m_stream );//後で更新するべき
497 Util.fwrite( "movi", m_stream );
498 m_next_framedata_position = m_stream.BaseStream.Position;
499 m_std_index.aIndex.Clear();
500 m_std_index.SetBaseOffset( (ulong)m_next_framedata_position );
501 m_current_chunk++;
502 m_super_index.nEntriesInUse++;
503 }
504
505 // フレームを書き込む処理
506 width = (int)m_main_header.dwWidth;
507 height = (int)m_main_header.dwHeight;
508 if ( width != bmpDat.Width ) {
509 return;
510 }
511 if ( height != bmpDat.Height ) {
512 return;
513 }
514 lineSize = bmpDat.Stride;
515
516 if ( m_compressed ) {
517 int is_key_frame = 0;
518 int size = bmpDat.Stride * bmpDat.Height;
519 try {
520 IntPtr dat = VCM.ICSeqCompressFrame( m_compvar, 0, bmpDat.Scan0, &is_key_frame, &size );
521 if ( !dat.Equals( IntPtr.Zero ) ) {
522 byte[] ndat = new byte[size];
523 Marshal.Copy( dat, ndat, 0, size );
524 m_std_index.AddIndex( (uint)((ulong)m_stream.BaseStream.Position - m_std_index.qwBaseOffset) + 8, (uint)size );
525 Util.fwrite( "00db", m_stream );
526 Util.WriteDWORD( (uint)size, m_stream );
527 m_stream.Write( ndat, 0, size );
528 m_this_movi_size += size;
529 }
530 } catch {
531 }
532 } else {
533 m_std_index.AddIndex( (uint)((ulong)m_stream.BaseStream.Position - m_std_index.qwBaseOffset) + 8, (uint)(lineSize * height) );
534 Util.fwrite( "00db", m_stream );
535 int address = bmpDat.Scan0.ToInt32();
536 byte[] bitmapData = new byte[bmpDat.Stride * bmpDat.Height];
537 Marshal.Copy( new IntPtr( address ), bitmapData, 0, bitmapData.Length );
538 Util.WriteDWORD( m_main_header.dwSuggestedBufferSize, m_stream );
539 m_stream.Write( bitmapData );
540 m_this_movi_size += bitmapData.Length;
541 }
542 m_next_framedata_position = m_stream.BaseStream.Position;
543 _avisuperindex_entry entry = m_super_index.aIndex[m_current_chunk];
544 entry.dwDuration++;
545 m_super_index.aIndex[m_current_chunk] = entry;
546 m_stream.Flush();
547 bmp.UnlockBits( bmpDat );
548 }
549 }
550 }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26