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