0022734: Memory allocation error in OpenGl
[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
21#include <OpenGl_AVIWriter.hxx>
22
23#ifdef WNT
24OpenGl_AVIWriter* OpenGl_AVIWriter::MyAVIWriterInstance = 0L;
25
26OpenGl_AVIWriter * OpenGl_AVIWriter::GetInstance()
27{
28 return MyAVIWriterInstance;
29}
30
31//=======================================================================
32//function : OpenGl_AVIWriter
33//purpose :
34//=======================================================================
35
36Standard_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
93Standard_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
107void 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
119void OpenGl_AVIWriter::StopRecording()
120{
121 myIsAllowRecord = Standard_False;
122}
123
124//=======================================================================
125//function : ReleaseMemory
126//purpose :
127//=======================================================================
128
129void 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
170void OpenGl_AVIWriter::SetErrorMessage(const char * theErrorMessage)
171{
172 myErrMsg = (Standard_CString)theErrorMessage;
173}
174
175//=======================================================================
176//function : InitMovieCreation
177//purpose :
178//=======================================================================
179
180HRESULT 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
289HRESULT 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
311HRESULT 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
352HRESULT OpenGl_AVIWriter::AppendDummy(HBITMAP)
353{
354 return E_FAIL;
355}
356
357//=======================================================================
358//function : AppendNewFrame
359//purpose :
360//=======================================================================
361
362HRESULT OpenGl_AVIWriter::AppendNewFrame(HBITMAP hBitmap)
363{
364 return (this->*pAppendFrame[myAppendFuncSelector])((HBITMAP)hBitmap);
365}
366
367//=======================================================================
368//function : AppendNewFrame
369//purpose :
370//=======================================================================
371
372HRESULT 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
388HRESULT 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
408HRESULT 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
437HRESULT 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
450void 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
471Standard_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