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