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