0024391: Erased AIS object can not be displayed in AIS_InteractiveContext after AIS_I...
[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 #include <OpenGl_AVIWriter.hxx>
21
22 #if (defined(_WIN32) || defined(__WIN32__)) && defined(HAVE_VIDEOCAPTURE)
23   #ifdef _MSC_VER
24     #pragma comment (lib, "vfw32.lib")
25   #endif
26
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
485 #endif