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