0023316: OpenGl package can not be compiled on RedHat40-64
[occt.git] / src / OpenGl / OpenGl_AVIWriter.cxx
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
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