1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-05-01 10:26:12 +03:00
occt/src/OpenGl/OpenGl_AVIWriter.cxx
kgv 16fa0dfb08 0023488: Make video recording functionality (OpenGl_AVIWriter) optional
CSF_AviLibs missing in EXTERNLIB of TKOpenGl toolkit. This cause incorrect project generation.
HAVE_VIDEOCAPTURE now should be defined to enable video recording capabilities on Windows.
2012-11-02 15:56:36 +04:00

486 lines
16 KiB
C++
Executable File

// Created on: 2007-04-15
// Created by: Alexey MORENOV & Alexander GRIGORIEV
// Copyright (c) 2007-2012 OPEN CASCADE SAS
//
// The content of this file is subject to the Open CASCADE Technology Public
// License Version 6.5 (the "License"). You may not use the content of this file
// except in compliance with the License. Please obtain a copy of the License
// at http://www.opencascade.org and read it completely before using this file.
//
// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
//
// The Original Code and all software distributed under the License is
// distributed on an "AS IS" basis, without warranty of any kind, and the
// Initial Developer hereby disclaims all such warranties, including without
// limitation, any warranties of merchantability, fitness for a particular
// purpose or non-infringement. Please see the License for the specific terms
// and conditions governing the rights and limitations under the License.
#include <OpenGl_AVIWriter.hxx>
#if (defined(_WIN32) || defined(__WIN32__)) && defined(HAVE_VIDEOCAPTURE)
#ifdef _MSC_VER
#pragma comment (lib, "vfw32.lib")
#endif
OpenGl_AVIWriter* OpenGl_AVIWriter::MyAVIWriterInstance = 0L;
OpenGl_AVIWriter * OpenGl_AVIWriter::GetInstance()
{
return MyAVIWriterInstance;
}
//=======================================================================
//function : OpenGl_AVIWriter
//purpose :
//=======================================================================
Standard_EXPORT OpenGl_AVIWriter::OpenGl_AVIWriter
(const char * theFileName,
DWORD dwCodec /* = mmioFOURCC('M','P','G','4') */,
Standard_Integer theFrameRate /* = 25 */)
: myhHeap (0L),
myhWindow (0L),
myhAviDC (0L),
mylpBits (0L),
mylSample (0L),
mypAviFile (0L),
mypAviStream (0L),
mypAviCompressedStream(0L),
myFileName (0L),
myIsAllowRecord (Standard_False),
myAppendFuncSelector(1) //0=Dummy 1=FirstTime 2=Usual
{
::AVIFileInit();
if (theFileName != 0L && theFileName[0] != '\0') {
const size_t aLen = strlen(theFileName) + 1;
myFileName = new char [aLen];
memcpy(myFileName, theFileName, aLen);
myErrMsg = (Standard_CString)"Method Succeeded";
pAppendFrame[0]= &OpenGl_AVIWriter::AppendDummy;
pAppendFrame[1]= &OpenGl_AVIWriter::AppendFrameFirstTime;
pAppendFrame[2]= &OpenGl_AVIWriter::AppendFrameUsual;
pAppendFrameBits[0]=&OpenGl_AVIWriter::AppendDummyBits;
pAppendFrameBits[1]=&OpenGl_AVIWriter::AppendFrameBitsFirstTime;
pAppendFrameBits[2]=&OpenGl_AVIWriter::AppendFrameBitsUsual;
MyAVIWriterInstance = this;
ZeroMemory(&myAviStreamInfo,sizeof(AVISTREAMINFO));
myAviStreamInfo.fccType = streamtypeVIDEO;
myAviStreamInfo.fccHandler = dwCodec;
myAviStreamInfo.dwScale = 1;
myAviStreamInfo.dwRate = theFrameRate; // Frames Per Second;
myAviStreamInfo.dwQuality = 100;/*//-1; // Default Quality*/
ZeroMemory(&myAviCompressOptions,sizeof(AVICOMPRESSOPTIONS));
myAviCompressOptions.fccType = streamtypeVIDEO;
myAviCompressOptions.fccHandler = myAviStreamInfo.fccHandler;
myAviCompressOptions.dwFlags =
AVICOMPRESSF_KEYFRAMES|AVICOMPRESSF_VALID|AVICOMPRESSF_DATARATE;
myAviCompressOptions.dwKeyFrameEvery = 1;
myAviCompressOptions.dwBytesPerSecond = 125000;
myAviCompressOptions.dwQuality = 100;
}
}
//=======================================================================
//function : ~OpenGl_AVIWriter
//purpose :
//=======================================================================
Standard_EXPORT OpenGl_AVIWriter::~OpenGl_AVIWriter(void)
{
ReleaseMemory();
AVIFileExit();
if (myFileName)
delete [] myFileName;
MyAVIWriterInstance = 0L;
}
//=======================================================================
//function : StartRecording
//purpose :
//=======================================================================
void OpenGl_AVIWriter::StartRecording(const HANDLE hWin)
{
if (hWin != NULL)
myhWindow = hWin;
myIsAllowRecord = Standard_True;
}
//=======================================================================
//function : StopRecording
//purpose :
//=======================================================================
void OpenGl_AVIWriter::StopRecording()
{
myIsAllowRecord = Standard_False;
}
//=======================================================================
//function : ReleaseMemory
//purpose :
//=======================================================================
void OpenGl_AVIWriter::ReleaseMemory()
{
myAppendFuncSelector=0; //Point to DummyFunction
if(myhAviDC)
{
DeleteDC(myhAviDC);
myhAviDC=NULL;
}
if(mypAviCompressedStream)
{
AVIStreamRelease(mypAviCompressedStream);
mypAviCompressedStream=NULL;
}
if(mypAviStream)
{
AVIStreamRelease(mypAviStream);
mypAviStream=NULL;
}
if(mypAviFile)
{
AVIFileRelease(mypAviFile);
mypAviFile=NULL;
}
if(mylpBits)
{
HeapFree(myhHeap,HEAP_NO_SERIALIZE,mylpBits);
mylpBits=NULL;
}
if(myhHeap)
{
HeapDestroy(myhHeap);
myhHeap=NULL;
}
}
//=======================================================================
//function : SetErrorMessage
//purpose :
//=======================================================================
void OpenGl_AVIWriter::SetErrorMessage(const char * theErrorMessage)
{
myErrMsg = (Standard_CString)theErrorMessage;
}
//=======================================================================
//function : InitMovieCreation
//purpose :
//=======================================================================
HRESULT OpenGl_AVIWriter::InitMovieCreation (int nFrameWidth,
int nFrameHeight,
int nBitsPerPixel)
{
int nMaxWidth=GetSystemMetrics(SM_CXSCREEN),
nMaxHeight=GetSystemMetrics(SM_CYSCREEN);
myhAviDC = CreateCompatibleDC(NULL);
if(myhAviDC==NULL)
{
SetErrorMessage("Unable to Create Compatible DC");
return E_FAIL;
}
if (nFrameWidth > nMaxWidth)
nMaxWidth= nFrameWidth;
if (nFrameHeight > nMaxHeight)
nMaxHeight = nFrameHeight;
myhHeap=HeapCreate(HEAP_NO_SERIALIZE, nMaxWidth*nMaxHeight*4, 0);
if(myhHeap==NULL)
{
SetErrorMessage("Unable to Create Heap");
return E_FAIL;
}
mylpBits=HeapAlloc(myhHeap, HEAP_ZERO_MEMORY|HEAP_NO_SERIALIZE,
nMaxWidth*nMaxHeight*4);
if(mylpBits==NULL)
{
SetErrorMessage("Unable to Allocate Memory on Heap");
return E_FAIL;
}
HRESULT hr;
hr = ::AVIFileOpen(&mypAviFile, myFileName, OF_CREATE|OF_WRITE, NULL);
if (!hr == AVIERR_OK)
{
SetErrorMessage("Unable to Create the Movie File");
return E_FAIL;
}
/*
if(FAILED(::AVIFileOpen(&mypAviFile, myszFileName, OF_CREATE|OF_WRITE, NULL)))
{
SetErrorMessage("Unable to Create the Movie File");
return E_FAIL;
}
*/
myAviStreamInfo.dwSuggestedBufferSize = nMaxWidth * nMaxHeight * 4;
SetRect(&myAviStreamInfo.rcFrame, 0, 0, nFrameWidth, nFrameHeight);
strncpy(myAviStreamInfo.szName, "Video Stream", 64);
if(FAILED(AVIFileCreateStream(mypAviFile,&mypAviStream,&myAviStreamInfo)))
{
SetErrorMessage("Unable to Create Video Stream in the Movie File");
return E_FAIL;
}
if(FAILED(AVIMakeCompressedStream(&mypAviCompressedStream,
mypAviStream,
&myAviCompressOptions,
NULL)))
{
// One reason this error might occur is if you are using a Codec that is not
// available on your system. Check the mmioFOURCC() code you are using and
// make sure you have that codec installed properly on your machine.
SetErrorMessage("Unable to Create Compressed Stream: "
"Check your CODEC options");
return E_FAIL;
}
BITMAPINFO bmpInfo;
ZeroMemory(&bmpInfo,sizeof(BITMAPINFO));
bmpInfo.bmiHeader.biPlanes = 1;
bmpInfo.bmiHeader.biWidth = nFrameWidth;
bmpInfo.bmiHeader.biHeight = nFrameHeight;
bmpInfo.bmiHeader.biCompression = BI_RGB;
bmpInfo.bmiHeader.biBitCount = nBitsPerPixel;
bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpInfo.bmiHeader.biSizeImage = (bmpInfo.bmiHeader.biWidth *
bmpInfo.bmiHeader.biHeight*
bmpInfo.bmiHeader.biBitCount)/8;
if(FAILED(AVIStreamSetFormat(mypAviCompressedStream,
0,
(LPVOID)&bmpInfo,
bmpInfo.bmiHeader.biSize)))
{
// One reason this error might occur is if your bitmap does not meet
// the Codec requirements.
// For example,
// your bitmap is 32bpp while the Codec supports only 16 or 24 bpp; Or
// your bitmap is 274 * 258 size, while the Codec supports only sizes
// that are powers of 2; etc...
// Possible solution to avoid this is: make your bitmap suit the codec
// requirements, or Choose a codec that is suitable for your bitmap.
SetErrorMessage("Unable to Set Video Stream Format");
return E_FAIL;
}
return S_OK; // Everything went Fine
}
//=======================================================================
//function : AppendFrameFirstTime
//purpose :
//=======================================================================
HRESULT OpenGl_AVIWriter::AppendFrameFirstTime(HBITMAP hBitmap)
{
BITMAP Bitmap;
GetObject(hBitmap, sizeof(BITMAP), &Bitmap);
if(SUCCEEDED(InitMovieCreation( Bitmap.bmWidth,
Bitmap.bmHeight,
Bitmap.bmBitsPixel)))
{
myAppendFuncSelector = 2; //Point to the UsualAppend Function
return AppendFrameUsual(hBitmap);
}
ReleaseMemory();
return E_FAIL;
}
//=======================================================================
//function : AppendFrameUsual
//purpose :
//=======================================================================
HRESULT OpenGl_AVIWriter::AppendFrameUsual(HBITMAP hBitmap)
{
BITMAPINFO bmpInfo;
bmpInfo.bmiHeader.biBitCount=0;
bmpInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
GetDIBits(myhAviDC,hBitmap,0,0,NULL,&bmpInfo,DIB_RGB_COLORS);
bmpInfo.bmiHeader.biCompression=BI_RGB;
GetDIBits(myhAviDC,
hBitmap,
0,
bmpInfo.bmiHeader.biHeight,
mylpBits,
&bmpInfo,
DIB_RGB_COLORS);
if(FAILED(AVIStreamWrite(mypAviCompressedStream,
mylSample++,
1,
mylpBits,
bmpInfo.bmiHeader.biSizeImage,
0,
NULL,
NULL)))
{
SetErrorMessage("Unable to Write Video Stream to the output Movie File");
ReleaseMemory();
return E_FAIL;
}
return S_OK;
}
//=======================================================================
//function : AppendDummy
//purpose :
//=======================================================================
HRESULT OpenGl_AVIWriter::AppendDummy(HBITMAP)
{
return E_FAIL;
}
//=======================================================================
//function : AppendNewFrame
//purpose :
//=======================================================================
HRESULT OpenGl_AVIWriter::AppendNewFrame(HBITMAP hBitmap)
{
return (this->*pAppendFrame[myAppendFuncSelector])((HBITMAP)hBitmap);
}
//=======================================================================
//function : AppendNewFrame
//purpose :
//=======================================================================
HRESULT OpenGl_AVIWriter::AppendNewFrame(int nWidth,
int nHeight,
LPVOID pBits,
int nBitsPerPixel)
{
return (this->*pAppendFrameBits[myAppendFuncSelector])(nWidth,
nHeight,
pBits,
nBitsPerPixel);
}
//=======================================================================
//function : AppendFrameFirstTime
//purpose :
//=======================================================================
HRESULT OpenGl_AVIWriter::AppendFrameBitsFirstTime(int nWidth,
int nHeight,
LPVOID pBits,
int nBitsPerPixel)
{
if(SUCCEEDED(InitMovieCreation(nWidth, nHeight, nBitsPerPixel)))
{
myAppendFuncSelector=2; //Point to the UsualAppend Function
return AppendFrameBitsUsual(nWidth, nHeight, pBits, nBitsPerPixel);
}
ReleaseMemory();
return E_FAIL;
}
//=======================================================================
//function : AppendFrameUsual
//purpose :
//=======================================================================
HRESULT OpenGl_AVIWriter::AppendFrameBitsUsual(int nWidth,
int nHeight,
LPVOID pBits,
int nBitsPerPixel)
{
DWORD dwSize=nWidth*nHeight*nBitsPerPixel/8;
if(FAILED(AVIStreamWrite(mypAviCompressedStream,
mylSample++,
1,
pBits,
dwSize,
0,
NULL,
NULL)))
{
SetErrorMessage("Unable to Write Video Stream to the output Movie File");
ReleaseMemory();
return E_FAIL;
}
return S_OK;
}
//=======================================================================
//function : AppendDummy
//purpose :
//=======================================================================
HRESULT OpenGl_AVIWriter::AppendDummyBits(int nWidth,
int nHeight,
LPVOID pBits,
int nBitsPerPixel)
{
return E_FAIL;
}
//=======================================================================
//function : AviWriter
//purpose :
//=======================================================================
void OpenGl_AVIWriter_AVIWriter(void * pp,
int nWidth,
int nHeight,
int nBitsPerPixel)
{
if (OpenGl_AVIWriter::GetInstance() != 0L)
if (OpenGl_AVIWriter::GetInstance()->IsRecording())
{
OpenGl_AVIWriter::GetInstance()->AppendNewFrame(nWidth,
nHeight,
pp,
nBitsPerPixel);
}
}
//=======================================================================
//function : AllowWriting
//purpose :
//=======================================================================
Standard_Boolean OpenGl_AVIWriter_AllowWriting(void * hWin)
{
Standard_Boolean aResult(Standard_False);
const OpenGl_AVIWriter * anInst = OpenGl_AVIWriter::GetInstance();
if (anInst != 0L) {
if (hWin == NULL || anInst->HWindow() == hWin)
aResult = static_cast<Standard_Boolean> (anInst->IsRecording());
}
return aResult;
}
#endif