0023243: Adapt OpenGL viewer for using in Cocoa applications on Mac OS X
[occt.git] / src / OpenGl / OpenGl_AVIWriter.cxx
CommitLineData
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 27OpenGl_AVIWriter* OpenGl_AVIWriter::MyAVIWriterInstance = 0L;
28
29OpenGl_AVIWriter * OpenGl_AVIWriter::GetInstance()
30{
31 return MyAVIWriterInstance;
32}
33
34//=======================================================================
35//function : OpenGl_AVIWriter
36//purpose :
37//=======================================================================
38
39Standard_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
96Standard_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
110void 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
122void OpenGl_AVIWriter::StopRecording()
123{
124 myIsAllowRecord = Standard_False;
125}
126
127//=======================================================================
128//function : ReleaseMemory
129//purpose :
130//=======================================================================
131
132void 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
173void OpenGl_AVIWriter::SetErrorMessage(const char * theErrorMessage)
174{
175 myErrMsg = (Standard_CString)theErrorMessage;
176}
177
178//=======================================================================
179//function : InitMovieCreation
180//purpose :
181//=======================================================================
182
183HRESULT 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
292HRESULT 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
314HRESULT 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
355HRESULT OpenGl_AVIWriter::AppendDummy(HBITMAP)
356{
357 return E_FAIL;
358}
359
360//=======================================================================
361//function : AppendNewFrame
362//purpose :
363//=======================================================================
364
365HRESULT OpenGl_AVIWriter::AppendNewFrame(HBITMAP hBitmap)
366{
367 return (this->*pAppendFrame[myAppendFuncSelector])((HBITMAP)hBitmap);
368}
369
370//=======================================================================
371//function : AppendNewFrame
372//purpose :
373//=======================================================================
374
375HRESULT 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
391HRESULT 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
411HRESULT 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
440HRESULT 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
453void 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
474Standard_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