7fd59977 |
1 | // File: OpenGl_AVIWriter.cxx |
2 | // Created: 15.04.07 13:44 |
3 | // Author: Alexey MORENOV & Alexander GRIGORIEV |
4 | // Copyright: Open CASCADE 2007 |
5 | |
6 | #include <OpenGl_AVIWriter.hxx> |
7 | |
8 | #ifdef WNT |
9 | OpenGl_AVIWriter* OpenGl_AVIWriter::MyAVIWriterInstance = 0L; |
10 | |
11 | OpenGl_AVIWriter * OpenGl_AVIWriter::GetInstance() |
12 | { |
13 | return MyAVIWriterInstance; |
14 | } |
15 | |
16 | //======================================================================= |
17 | //function : OpenGl_AVIWriter |
18 | //purpose : |
19 | //======================================================================= |
20 | |
21 | Standard_EXPORT OpenGl_AVIWriter::OpenGl_AVIWriter |
22 | (const char * theFileName, |
23 | DWORD dwCodec /* = mmioFOURCC('M','P','G','4') */, |
24 | Standard_Integer theFrameRate /* = 25 */) |
25 | : myhHeap (0L), |
26 | myhWindow (0L), |
27 | myhAviDC (0L), |
28 | mylpBits (0L), |
29 | mylSample (0L), |
30 | mypAviFile (0L), |
31 | mypAviStream (0L), |
32 | mypAviCompressedStream(0L), |
33 | myFileName (0L), |
34 | myIsAllowRecord (Standard_False), |
35 | myAppendFuncSelector(1) //0=Dummy 1=FirstTime 2=Usual |
36 | { |
37 | ::AVIFileInit(); |
38 | if (theFileName != 0L && theFileName[0] != '\0') { |
39 | |
40 | const size_t aLen = strlen(theFileName) + 1; |
41 | myFileName = new char [aLen]; |
42 | memcpy(myFileName, theFileName, aLen); |
43 | myErrMsg = (Standard_CString)"Method Succeeded"; |
44 | |
45 | pAppendFrame[0]= &OpenGl_AVIWriter::AppendDummy; |
46 | pAppendFrame[1]= &OpenGl_AVIWriter::AppendFrameFirstTime; |
47 | pAppendFrame[2]= &OpenGl_AVIWriter::AppendFrameUsual; |
48 | |
49 | pAppendFrameBits[0]=&OpenGl_AVIWriter::AppendDummyBits; |
50 | pAppendFrameBits[1]=&OpenGl_AVIWriter::AppendFrameBitsFirstTime; |
51 | pAppendFrameBits[2]=&OpenGl_AVIWriter::AppendFrameBitsUsual; |
52 | |
53 | MyAVIWriterInstance = this; |
54 | |
55 | ZeroMemory(&myAviStreamInfo,sizeof(AVISTREAMINFO)); |
56 | myAviStreamInfo.fccType = streamtypeVIDEO; |
57 | myAviStreamInfo.fccHandler = dwCodec; |
58 | myAviStreamInfo.dwScale = 1; |
59 | myAviStreamInfo.dwRate = theFrameRate; // Frames Per Second; |
60 | myAviStreamInfo.dwQuality = 100;/*//-1; // Default Quality*/ |
61 | |
62 | ZeroMemory(&myAviCompressOptions,sizeof(AVICOMPRESSOPTIONS)); |
63 | myAviCompressOptions.fccType = streamtypeVIDEO; |
64 | myAviCompressOptions.fccHandler = myAviStreamInfo.fccHandler; |
65 | myAviCompressOptions.dwFlags = |
66 | AVICOMPRESSF_KEYFRAMES|AVICOMPRESSF_VALID|AVICOMPRESSF_DATARATE; |
67 | myAviCompressOptions.dwKeyFrameEvery = 1; |
68 | myAviCompressOptions.dwBytesPerSecond = 125000; |
69 | myAviCompressOptions.dwQuality = 100; |
70 | } |
71 | } |
72 | |
73 | //======================================================================= |
74 | //function : ~OpenGl_AVIWriter |
75 | //purpose : |
76 | //======================================================================= |
77 | |
78 | Standard_EXPORT OpenGl_AVIWriter::~OpenGl_AVIWriter(void) |
79 | { |
80 | ReleaseMemory(); |
81 | AVIFileExit(); |
82 | if (myFileName) |
83 | delete [] myFileName; |
84 | MyAVIWriterInstance = 0L; |
85 | } |
86 | |
87 | //======================================================================= |
88 | //function : StartRecording |
89 | //purpose : |
90 | //======================================================================= |
91 | |
92 | void OpenGl_AVIWriter::StartRecording(const HANDLE hWin) |
93 | { |
94 | if (hWin != NULL) |
95 | myhWindow = hWin; |
96 | myIsAllowRecord = Standard_True; |
97 | } |
98 | |
99 | //======================================================================= |
100 | //function : StopRecording |
101 | //purpose : |
102 | //======================================================================= |
103 | |
104 | void OpenGl_AVIWriter::StopRecording() |
105 | { |
106 | myIsAllowRecord = Standard_False; |
107 | } |
108 | |
109 | //======================================================================= |
110 | //function : ReleaseMemory |
111 | //purpose : |
112 | //======================================================================= |
113 | |
114 | void OpenGl_AVIWriter::ReleaseMemory() |
115 | { |
116 | myAppendFuncSelector=0; //Point to DummyFunction |
117 | |
118 | if(myhAviDC) |
119 | { |
120 | DeleteDC(myhAviDC); |
121 | myhAviDC=NULL; |
122 | } |
123 | if(mypAviCompressedStream) |
124 | { |
125 | AVIStreamRelease(mypAviCompressedStream); |
126 | mypAviCompressedStream=NULL; |
127 | } |
128 | if(mypAviStream) |
129 | { |
130 | AVIStreamRelease(mypAviStream); |
131 | mypAviStream=NULL; |
132 | } |
133 | if(mypAviFile) |
134 | { |
135 | AVIFileRelease(mypAviFile); |
136 | mypAviFile=NULL; |
137 | } |
138 | if(mylpBits) |
139 | { |
140 | HeapFree(myhHeap,HEAP_NO_SERIALIZE,mylpBits); |
141 | mylpBits=NULL; |
142 | } |
143 | if(myhHeap) |
144 | { |
145 | HeapDestroy(myhHeap); |
146 | myhHeap=NULL; |
147 | } |
148 | } |
149 | |
150 | //======================================================================= |
151 | //function : SetErrorMessage |
152 | //purpose : |
153 | //======================================================================= |
154 | |
155 | void OpenGl_AVIWriter::SetErrorMessage(const char * theErrorMessage) |
156 | { |
157 | myErrMsg = (Standard_CString)theErrorMessage; |
158 | } |
159 | |
160 | //======================================================================= |
161 | //function : InitMovieCreation |
162 | //purpose : |
163 | //======================================================================= |
164 | |
165 | HRESULT OpenGl_AVIWriter::InitMovieCreation (int nFrameWidth, |
166 | int nFrameHeight, |
167 | int nBitsPerPixel) |
168 | { |
169 | int nMaxWidth=GetSystemMetrics(SM_CXSCREEN), |
170 | nMaxHeight=GetSystemMetrics(SM_CYSCREEN); |
171 | |
172 | myhAviDC = CreateCompatibleDC(NULL); |
173 | if(myhAviDC==NULL) |
174 | { |
175 | SetErrorMessage("Unable to Create Compatible DC"); |
176 | return E_FAIL; |
177 | } |
178 | |
179 | if (nFrameWidth > nMaxWidth) |
180 | nMaxWidth= nFrameWidth; |
181 | if (nFrameHeight > nMaxHeight) |
182 | nMaxHeight = nFrameHeight; |
183 | |
184 | myhHeap=HeapCreate(HEAP_NO_SERIALIZE, nMaxWidth*nMaxHeight*4, 0); |
185 | if(myhHeap==NULL) |
186 | { |
187 | SetErrorMessage("Unable to Create Heap"); |
188 | return E_FAIL; |
189 | } |
190 | |
191 | mylpBits=HeapAlloc(myhHeap, HEAP_ZERO_MEMORY|HEAP_NO_SERIALIZE, |
192 | nMaxWidth*nMaxHeight*4); |
193 | if(mylpBits==NULL) |
194 | { |
195 | SetErrorMessage("Unable to Allocate Memory on Heap"); |
196 | return E_FAIL; |
197 | } |
198 | |
199 | HRESULT hr; |
200 | hr = ::AVIFileOpen(&mypAviFile, myFileName, OF_CREATE|OF_WRITE, NULL); |
201 | if (!hr == AVIERR_OK) |
202 | { |
203 | SetErrorMessage("Unable to Create the Movie File"); |
204 | return E_FAIL; |
205 | } |
206 | /* |
207 | if(FAILED(::AVIFileOpen(&mypAviFile, myszFileName, OF_CREATE|OF_WRITE, NULL))) |
208 | { |
209 | SetErrorMessage("Unable to Create the Movie File"); |
210 | return E_FAIL; |
211 | } |
212 | */ |
213 | |
214 | myAviStreamInfo.dwSuggestedBufferSize = nMaxWidth * nMaxHeight * 4; |
215 | SetRect(&myAviStreamInfo.rcFrame, 0, 0, nFrameWidth, nFrameHeight); |
216 | strncpy(myAviStreamInfo.szName, "Video Stream", 64); |
217 | |
218 | if(FAILED(AVIFileCreateStream(mypAviFile,&mypAviStream,&myAviStreamInfo))) |
219 | { |
220 | SetErrorMessage("Unable to Create Video Stream in the Movie File"); |
221 | return E_FAIL; |
222 | } |
223 | |
224 | if(FAILED(AVIMakeCompressedStream(&mypAviCompressedStream, |
225 | mypAviStream, |
226 | &myAviCompressOptions, |
227 | NULL))) |
228 | { |
229 | // One reason this error might occur is if you are using a Codec that is not |
230 | // available on your system. Check the mmioFOURCC() code you are using and |
231 | // make sure you have that codec installed properly on your machine. |
232 | SetErrorMessage("Unable to Create Compressed Stream: " |
233 | "Check your CODEC options"); |
234 | return E_FAIL; |
235 | } |
236 | |
237 | BITMAPINFO bmpInfo; |
238 | ZeroMemory(&bmpInfo,sizeof(BITMAPINFO)); |
239 | bmpInfo.bmiHeader.biPlanes = 1; |
240 | bmpInfo.bmiHeader.biWidth = nFrameWidth; |
241 | bmpInfo.bmiHeader.biHeight = nFrameHeight; |
242 | bmpInfo.bmiHeader.biCompression = BI_RGB; |
243 | bmpInfo.bmiHeader.biBitCount = nBitsPerPixel; |
244 | bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); |
245 | bmpInfo.bmiHeader.biSizeImage = (bmpInfo.bmiHeader.biWidth * |
246 | bmpInfo.bmiHeader.biHeight* |
247 | bmpInfo.bmiHeader.biBitCount)/8; |
248 | |
249 | if(FAILED(AVIStreamSetFormat(mypAviCompressedStream, |
250 | 0, |
251 | (LPVOID)&bmpInfo, |
252 | bmpInfo.bmiHeader.biSize))) |
253 | { |
254 | // One reason this error might occur is if your bitmap does not meet |
255 | // the Codec requirements. |
256 | // For example, |
257 | // your bitmap is 32bpp while the Codec supports only 16 or 24 bpp; Or |
258 | // your bitmap is 274 * 258 size, while the Codec supports only sizes |
259 | // that are powers of 2; etc... |
260 | // Possible solution to avoid this is: make your bitmap suit the codec |
261 | // requirements, or Choose a codec that is suitable for your bitmap. |
262 | SetErrorMessage("Unable to Set Video Stream Format"); |
263 | return E_FAIL; |
264 | } |
265 | |
266 | return S_OK; // Everything went Fine |
267 | } |
268 | |
269 | //======================================================================= |
270 | //function : AppendFrameFirstTime |
271 | //purpose : |
272 | //======================================================================= |
273 | |
274 | HRESULT OpenGl_AVIWriter::AppendFrameFirstTime(HBITMAP hBitmap) |
275 | { |
276 | BITMAP Bitmap; |
277 | GetObject(hBitmap, sizeof(BITMAP), &Bitmap); |
278 | |
279 | if(SUCCEEDED(InitMovieCreation( Bitmap.bmWidth, |
280 | Bitmap.bmHeight, |
281 | Bitmap.bmBitsPixel))) |
282 | { |
283 | myAppendFuncSelector = 2; //Point to the UsualAppend Function |
284 | return AppendFrameUsual(hBitmap); |
285 | } |
286 | |
287 | ReleaseMemory(); |
288 | return E_FAIL; |
289 | } |
290 | |
291 | //======================================================================= |
292 | //function : AppendFrameUsual |
293 | //purpose : |
294 | //======================================================================= |
295 | |
296 | HRESULT OpenGl_AVIWriter::AppendFrameUsual(HBITMAP hBitmap) |
297 | { |
298 | BITMAPINFO bmpInfo; |
299 | |
300 | bmpInfo.bmiHeader.biBitCount=0; |
301 | bmpInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); |
302 | |
303 | GetDIBits(myhAviDC,hBitmap,0,0,NULL,&bmpInfo,DIB_RGB_COLORS); |
304 | |
305 | bmpInfo.bmiHeader.biCompression=BI_RGB; |
306 | |
307 | GetDIBits(myhAviDC, |
308 | hBitmap, |
309 | 0, |
310 | bmpInfo.bmiHeader.biHeight, |
311 | mylpBits, |
312 | &bmpInfo, |
313 | DIB_RGB_COLORS); |
314 | |
315 | if(FAILED(AVIStreamWrite(mypAviCompressedStream, |
316 | mylSample++, |
317 | 1, |
318 | mylpBits, |
319 | bmpInfo.bmiHeader.biSizeImage, |
320 | 0, |
321 | NULL, |
322 | NULL))) |
323 | { |
324 | SetErrorMessage("Unable to Write Video Stream to the output Movie File"); |
325 | ReleaseMemory(); |
326 | return E_FAIL; |
327 | } |
328 | |
329 | return S_OK; |
330 | } |
331 | |
332 | //======================================================================= |
333 | //function : AppendDummy |
334 | //purpose : |
335 | //======================================================================= |
336 | |
337 | HRESULT OpenGl_AVIWriter::AppendDummy(HBITMAP) |
338 | { |
339 | return E_FAIL; |
340 | } |
341 | |
342 | //======================================================================= |
343 | //function : AppendNewFrame |
344 | //purpose : |
345 | //======================================================================= |
346 | |
347 | HRESULT OpenGl_AVIWriter::AppendNewFrame(HBITMAP hBitmap) |
348 | { |
349 | return (this->*pAppendFrame[myAppendFuncSelector])((HBITMAP)hBitmap); |
350 | } |
351 | |
352 | //======================================================================= |
353 | //function : AppendNewFrame |
354 | //purpose : |
355 | //======================================================================= |
356 | |
357 | HRESULT OpenGl_AVIWriter::AppendNewFrame(int nWidth, |
358 | int nHeight, |
359 | LPVOID pBits, |
360 | int nBitsPerPixel) |
361 | { |
362 | return (this->*pAppendFrameBits[myAppendFuncSelector])(nWidth, |
363 | nHeight, |
364 | pBits, |
365 | nBitsPerPixel); |
366 | } |
367 | |
368 | //======================================================================= |
369 | //function : AppendFrameFirstTime |
370 | //purpose : |
371 | //======================================================================= |
372 | |
373 | HRESULT OpenGl_AVIWriter::AppendFrameBitsFirstTime(int nWidth, |
374 | int nHeight, |
375 | LPVOID pBits, |
376 | int nBitsPerPixel) |
377 | { |
378 | if(SUCCEEDED(InitMovieCreation(nWidth, nHeight, nBitsPerPixel))) |
379 | { |
380 | myAppendFuncSelector=2; //Point to the UsualAppend Function |
381 | return AppendFrameBitsUsual(nWidth, nHeight, pBits, nBitsPerPixel); |
382 | } |
383 | ReleaseMemory(); |
384 | |
385 | return E_FAIL; |
386 | } |
387 | |
388 | //======================================================================= |
389 | //function : AppendFrameUsual |
390 | //purpose : |
391 | //======================================================================= |
392 | |
393 | HRESULT OpenGl_AVIWriter::AppendFrameBitsUsual(int nWidth, |
394 | int nHeight, |
395 | LPVOID pBits, |
396 | int nBitsPerPixel) |
397 | { |
398 | DWORD dwSize=nWidth*nHeight*nBitsPerPixel/8; |
399 | |
400 | if(FAILED(AVIStreamWrite(mypAviCompressedStream, |
401 | mylSample++, |
402 | 1, |
403 | pBits, |
404 | dwSize, |
405 | 0, |
406 | NULL, |
407 | NULL))) |
408 | { |
409 | SetErrorMessage("Unable to Write Video Stream to the output Movie File"); |
410 | ReleaseMemory(); |
411 | return E_FAIL; |
412 | } |
413 | |
414 | return S_OK; |
415 | } |
416 | |
417 | //======================================================================= |
418 | //function : AppendDummy |
419 | //purpose : |
420 | //======================================================================= |
421 | |
422 | HRESULT OpenGl_AVIWriter::AppendDummyBits(int nWidth, |
423 | int nHeight, |
424 | LPVOID pBits, |
425 | int nBitsPerPixel) |
426 | { |
427 | return E_FAIL; |
428 | } |
429 | |
430 | //======================================================================= |
431 | //function : AviWriter |
432 | //purpose : |
433 | //======================================================================= |
434 | |
435 | void OpenGl_AVIWriter_AVIWriter(void * pp, |
436 | int nWidth, |
437 | int nHeight, |
438 | int nBitsPerPixel) |
439 | { |
440 | if (OpenGl_AVIWriter::GetInstance() != 0L) |
441 | if (OpenGl_AVIWriter::GetInstance()->IsRecording()) |
442 | { |
443 | |
444 | OpenGl_AVIWriter::GetInstance()->AppendNewFrame(nWidth, |
445 | nHeight, |
446 | pp, |
447 | nBitsPerPixel); |
448 | } |
449 | } |
450 | |
451 | //======================================================================= |
452 | //function : AllowWriting |
453 | //purpose : |
454 | //======================================================================= |
455 | |
456 | Standard_Boolean OpenGl_AVIWriter_AllowWriting(void * hWin) |
457 | { |
458 | Standard_Boolean aResult(Standard_False); |
459 | const OpenGl_AVIWriter * anInst = OpenGl_AVIWriter::GetInstance(); |
460 | if (anInst != 0L) { |
461 | if (hWin == NULL || anInst->HWindow() == hWin) |
462 | aResult = static_cast<Standard_Boolean> (anInst->IsRecording()); |
463 | } |
464 | return aResult; |
465 | } |
466 | |
467 | #endif //WNT |