chMB() is a define to MessageBoxA( 0, text, "title", MB_OK );so it displays the text and I can see results. My problem is with the following codez:
CString szWow;
szWow.Format( "%u", idCandidate );
chMB( szWow );
const __int64 i64set = i64VoteAmount+1;
CString addvote;
addvote.Format( "UPDATE dbo.CONSULENTRIES set m_uVoteAmount = %u WHERE m_idCandidate = %u", i64set, idCandidate );
chMB( addvote );
chMB( szWow ); displayes 5
althought chMB( addVote ) displayes:
UPDATE dbo.CONSULENTRIES set m_uVoteAmount = 1 WHERE m_idCandidate = 0
why is idCandidate 0 on this string format??? O___O
in case you need here is teh full codez:
VOTEAPPL CConsulApplication::VoteForApplied( const u_long idVoter, const __int64 idCandidate )
{
if( idVoter && idCandidate )
{
/* Check if alredy voted */
CQuery* pQuery = new CQuery;
if( !pQuery->Connect( 3, DSN_NAME_CHARACTER01, DB_ADMIN_ID_CHARACTER01, DB_ADMIN_PASS_CHARACTER01 ) )
{
pQuery->DisConnect();
SAFE_DELETE( pQuery );
return VAPL_FAILURE;
}
CString szVoted;
szVoted.Format( "SELECT * FROM dbo.CONSULVOTE WHERE m_idVoter = %u", idVoter );
if( !pQuery->Exec( szVoted ) )
{
pQuery->DisConnect();
SAFE_DELETE( pQuery );
return VAPL_FAILURE;
}
pQuery->Fetch();
__int64 i64Voter = pQuery->GetInt64( "m_idVoter" );
if( i64Voter != 0 )
{
pQuery->DisConnect();
SAFE_DELETE( pQuery );
return VAPL_VOTED;
}
pQuery->DisConnect();
SAFE_DELETE( pQuery );
/* Get content and check if candidate exists */
CQuery* pQuery2 = new CQuery;
if( !pQuery2->Connect( 3, DSN_NAME_CHARACTER01, DB_ADMIN_ID_CHARACTER01, DB_ADMIN_PASS_CHARACTER01 ) )
{
pQuery2->DisConnect();
SAFE_DELETE( pQuery2 );
return VAPL_FAILURE;
}
CString szCandidate;
szCandidate.Format( "SELECT * FROM dbo.CONSULENTRIES WHERE m_idCandidate = %u", idCandidate );
if( !pQuery2->Exec( szCandidate ) )
{
pQuery2->DisConnect();
SAFE_DELETE( pQuery2 );
return VAPL_FAILURE;
}
pQuery2->Fetch();
__int64 i64Candidate = pQuery2->GetInt64( "m_idCandidate" );
__int64 i64VoteAmount = pQuery2->GetInt64( "m_uVoteAmount" );
if( i64Candidate != 0 )
{
/* Insert at database that this guy has voted */
CQuery* pInsertQuery = new CQuery;
if( !pInsertQuery->Connect( 3, DSN_NAME_CHARACTER01, DB_ADMIN_ID_CHARACTER01, DB_ADMIN_PASS_CHARACTER01 ) )
{
pInsertQuery->DisConnect();
SAFE_DELETE( pInsertQuery );
return VAPL_FAILURE;
}
CString szInsert;
szInsert.Format( "INSERT INTO dbo.CONSULVOTE values(%u,%u)", idVoter, idCandidate );
if( !pInsertQuery->Exec( szInsert ) )
{
pInsertQuery->DisConnect();
SAFE_DELETE( pInsertQuery );
return VAPL_FAILURE;
}
pInsertQuery->DisConnect();
SAFE_DELETE( pInsertQuery );
/* Update vote amount */
CQuery* pUpdate = new CQuery;
if( !pUpdate->Connect( 3, DSN_NAME_CHARACTER01, DB_ADMIN_ID_CHARACTER01, DB_ADMIN_PASS_CHARACTER01 ) )
{
pUpdate->DisConnect();
SAFE_DELETE( pUpdate );
return VAPL_FAILURE;
}
CString szWow;
szWow.Format( "%u", idCandidate );
chMB( szWow );
const __int64 i64set = i64VoteAmount+1;
CString addvote;
addvote.Format( "UPDATE dbo.CONSULENTRIES set m_uVoteAmount = %u WHERE m_idCandidate = %u", i64set, idCandidate );
chMB( addvote );
if( !pUpdate->Exec( addvote ) )
{
pUpdate->DisConnect();
SAFE_DELETE( pUpdate );
return VAPL_FAILURE;
}
pUpdate->DisConnect();
SAFE_DELETE( pUpdate );
return VAPL_SUCCESS;
}
pQuery2->DisConnect();
SAFE_DELETE( pQuery2 );
return VAPL_FAILURE;
}
return VAPL_FAILURE;
}
The problem is here:
addvote.Format( "UPDATE dbo.CONSULENTRIES set m_uVoteAmount = %u WHERE m_idCandidate = %u", i64set, idCandidate );
The format string contains %u while the variable after the format string (i64set) is of a wrong type (__int64).
Try changing the type (%u corresponds to type unsigned int) or the format specifier:
addvote.Format( "UPDATE dbo.CONSULENTRIES set m_uVoteAmount = %I64d WHERE m_idCandidate = %u", i64set, idCandidate );
Related
I'm developing an application which captures frames using DXGI mechanism from an application.
First creation of the IDXGIOutputDuplication is correct. When the application changes its display (for example from fullscreen to windowed or vice versa), the frame acquire failed (expected behaviour), then I recreate the IDXGIOutputDuplication and regularly the call to DuplicateOutput crash.
Below creation of the D3d11 device:
D3D_FEATURE_LEVEL FeatureLevels[] =
{
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_1
};
UINT NumFeatureLevels = ARRAYSIZE( FeatureLevels );
D3D_FEATURE_LEVEL FeatureLevel = D3D_FEATURE_LEVEL_11_1;
D3D11CreateDevice( _pDxgiAdapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr, 0, FeatureLevels, NumFeatureLevels, D3D11_SDK_VERSION, &_pD3D11Device, &FeatureLevel, &_pD3D11DeviceCtx );
_pDxgiAdapter is created before the device.
Below creation of the IDXGIOutputDuplication:
int DxgiVideoCapture::open() {
findDxgiAdapter();
if( nullptr != _pDxgiAdapter ) {
// Duplicate output
uint32_t ui32OutputIndex = 0;
HRESULT hr = S_OK;
while( SUCCEEDED( hr ) ) {
IDXGIOutput* pDxgiOutput = nullptr;
hr = _pDxgiAdapter->EnumOutputs( ui32OutputIndex, &pDxgiOutput );
if( SUCCEEDED( hr ) ) {
IDXGIOutput1* pDxgiOutput1 = nullptr;
if( SUCCEEDED ( pDxgiOutput->QueryInterface( __uuidof( IDXGIOutput1 ), ( void** )&pDxgiOutput1 ) ) ) {
uint32_t ui32EnumMode = 0;
uint32_t ui32Flags = 0xffffffff;
}
if( SUCCEEDED ( pDxgiOutput->QueryInterface( __uuidof( IDXGIOutput1 ), ( void** )&_pDxgiOutput1 ) ) ) {
LOGI( "/!\\ Call which crash regularly /!\\" );
HRESULT hrDup = _pDxgiOutput1->DuplicateOutput( _pD3D11Device, &_pOutputDuplication );
if( SUCCEEDED( hrDup ) ) {
LOGI( "Output duplication created." );
} else {
switch( hrDup ) {
case E_INVALIDARG :
{
LOGW( "Invalid device or output already duplicated" );
}
break;
case E_ACCESSDENIED :
{
LOGW( "Access denied" );
}
break;
case DXGI_ERROR_UNSUPPORTED :
{
LOGW( "DXGI_ERROR_UNSUPPORTED" );
}
break;
case DXGI_ERROR_NOT_CURRENTLY_AVAILABLE :
{
LOGW( "DXGI_ERROR_NOT_CURRENTLY_AVAILABLE" );
}
break;
case DXGI_ERROR_SESSION_DISCONNECTED :
{
LOGW( "DXGI_ERROR_NOT_CURRENTLY_AVAILABLE" );
}
break;
default:
{
LOGW( "default" );
}
}
} else {
LOGE( "Unable to retrieve interface creating the ouput duplication" );
}
}
pDxgiOutput->Release();
}
ui32OutputIndex++;
}
return RET_OK;
}
Below the frame acquisition:
int DxgiVideoCapture::captureGameFrame() {
int iRet = RET_ERROR;
ID3D11Texture2D* pCapturedTexture = nullptr;
DXGI_OUTDUPL_FRAME_INFO frameInfo;
ZeroMemory(&frameInfo, sizeof(frameInfo));
HRESULT hr = _pOutputDuplication->AcquireNextFrame( 1000, &frameInfo, &_pDxgiResource );
if( FAILED( hr ) ) {
if( hr == DXGI_ERROR_WAIT_TIMEOUT ) {
LOGW( "Wait for %d ms timed out", 1000);
}
if (hr == DXGI_ERROR_INVALID_CALL) {
LOGW( "Invalid Call, previous frame not released?" );
}
if (hr == DXGI_ERROR_ACCESS_LOST) {
LOGW( "Error Access lost - is it a game end ?" );
}
iRet = RET_RESET_CAPTURE;
return iRet;
}
if( FAILED( hr = _pDxgiResource->QueryInterface( __uuidof( ID3D11Texture2D ), ( void** ) &pCapturedTexture ) ) ) {
LOGW( "unable to retrieve D3D11 texture 0x%x", hr );
return RET_WARNING;
} else {
// Store window of the game
D3D11_TEXTURE2D_DESC d3D11TextureDesc;
pCapturedTexture->GetDesc( &d3D11TextureDesc );
// Compute the zone to extract.
D3D11_BOX srcBox;
memset( &srcBox, 0, sizeof( srcBox ) );
if( _pGameWindow->getLeftPos() > 0 ) {
srcBox.left = _pGameWindow->getLeftPos();
}
if( _pGameWindow->getTopPos() > 0 ) {
srcBox.top = _pGameWindow->getTopPos();
}
srcBox.front = 0;
srcBox.right = _pGameWindow->getLeftPos() + _pGameWindow->getWidth();
if( srcBox.right > _pGameWindow->getMonitorWidth() ) {
srcBox.right = _pGameWindow->getMonitorWidth();
}
if( ( srcBox.right - srcBox.left ) % 2 != 0 ) {
srcBox.right--;
}
srcBox.bottom = _pGameWindow->getTopPos() + _pGameWindow->getHeight();
if( srcBox.bottom > _pGameWindow->getMonitorHeight() ) {
srcBox.bottom = _pGameWindow->getMonitorHeight();
}
if( ( srcBox.bottom - srcBox.top ) % 2 != 0 ) {
srcBox.bottom--;
}
srcBox.back = 1;
// AVFrame info are udpate just when the captured game window and the texture are diffrent.
// In the same time texture is reallocated.
if( ( ( srcBox.right - srcBox.left ) != _CapturedTextureDesc.Width )
|| ( ( srcBox.bottom - srcBox.top ) != _CapturedTextureDesc.Height )
) {
LOGD( "Game window: %dx%d ; %d->%d", _pGameWindow->getLeftPos(), _pGameWindow->getTopPos(), _pGameWindow->getWidth(), _pGameWindow->getHeight() );
LOGD( "Texture creation %dx%d -> %dx%d", srcBox.left, srcBox.top, srcBox.right, srcBox.bottom );
// Create the new texture
iRet = createCapturedTexture( srcBox.right - srcBox.left, srcBox.bottom - srcBox.top );
}
DirectX11Util::GetInstance()->getD3D11DeviceContext()->CopySubresourceRegion( _pGameTexture, 0, 0, 0, 0, pCapturedTexture, 0, &srcBox );
}
if( nullptr != _pDxgiResource ) {
_pOutputDuplication->ReleaseFrame();
pCapturedTexture->Release();
_pDxgiResource->Release();
_pDxgiResource = nullptr;
}
iRet = RET_OK;
return iRet;
}
Below the release of the D3d11 capture before recreation of the IDXGIOutputDuplication:
int DxgiVideoCapture::close() {
if( nullptr != _pGameTexture ) {
ZeroMemory( &_CapturedTextureDesc, sizeof( D3D11_TEXTURE2D_DESC ) );
_pGameTexture->Release();
_pGameTexture = nullptr;
}
if( nullptr != _pDxgiResource ){
_pOutputDuplication->ReleaseFrame();
_pDxgiResource->Release();
_pDxgiResource = nullptr;
}
if( nullptr != _pOutputDuplication ) {
_pOutputDuplication->Release();
_pOutputDuplication = nullptr;
}
return RET_OK;
}
What I would like to know is how can I invest this crash (application ends without any message). To be more accurate I cross compile my application, but the behaviour seems the same. Do you have any idea how to invest this issue ?
Tell me if you want more details.
Thanks in advance !
I'm trying to modify the RCData of a compiled AutoHotkey script:
void ReplaceStringTable() {
HANDLE hRes = BeginUpdateResource( _T( "C:\\Users\\CAIO\\Documents\\Github\\main\\scripts\\ahkDebug\\Novo(a) AutoHotkey Script.exe" ), FALSE );
if ( hRes != NULL ) {
std::wstring data[] = { L"MsgBox Test" };
std::vector< WORD > buffer;
for ( size_t index = 0;
index < sizeof( data ) / sizeof( data[ 0 ] );
++index ) {
size_t pos = buffer.size();
buffer.resize( pos + data[ index ].size() + 1 );
buffer[ pos++ ] = static_cast< WORD >( data[ index ].size() );
copy( data[ index ].begin(), data[ index ].end(),
buffer.begin() + pos );
}
UpdateResource( hRes,
RT_RCDATA,
L">AUTOHOTKEY SCRIPT<", //MAKEINTRESOURCE( 1 ),
1033, //MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
reinterpret_cast< void* >( &buffer[ 0 ] ),
buffer.size() * sizeof( WORD ) );
EndUpdateResource( hRes, FALSE );
}
}
However, this is the result after running the code:
The code does add an empty blank line (line 1), this line makes the exe not work correctly, how do I get rid of it?
You need to use std::string instead of std::wstring, as AHK is expecting 8bit characters, not 16bit characters. Also, you need to get rid of your vector, as AHK does not expect each line to be prefixed by its length.
Try this instead:
void ReplaceStringTable() {
HANDLE hRes = BeginUpdateResource( TEXT( "C:\\Users\\CAIO\\Documents\\Github\\main\\scripts\\ahkDebug\\Novo(a) AutoHotkey Script.exe" ), FALSE );
if ( hRes != NULL ) {
std::string data = "MsgBox Test";
UpdateResource( hRes,
RT_RCDATA,
L">AUTOHOTKEY SCRIPT<", //MAKEINTRESOURCE( 1 ),
1033, //MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
const_cast<char*>(data.c_str()),
data.size() );
EndUpdateResource( hRes, FALSE );
}
}
I have a macro, and i use it this way:
int GL = 0;
GL = GetLastError();
DEBUG_MESSAGE( ERR, "RegOpenKeyEx failed. Error code = '%u'. Error description = '%s'", GL, GetErrorText( GL ) );
The function GetErrorText returns a char *, which is the corresponding errortext belonging to the error code.
The problem is, that when i call my macro, it won't call GetErrorText function.
The output will be this : RegOpenKeyEx failed. Error code = '5'. Error description = ''
The Macro is defined this way:
#define DEBUG_MESSAGE( Type, debug_message, ... ) { _debugLog.message( Type, debug_message, ##__VA_ARGS__ ); }
And this is the function what the macro calls:
void log::message( int Type, const char * message, ... )
{
char MessageExpanded[ 2048 ] = { 0 };
va_list args;
int len;
write_indentation();
memset( Message, 0, sizeof( Message ) );
memset( MessageExpanded, 0, sizeof( MessageExpanded ) );
va_start( args, message );
len = _vscprintf( message, args ) + 1; // _vscprintf doesn't count terminating '\0'
vsprintf_s( Message, len, message, args );
va_end( args );
sprintf( MessageExpanded, "%s %s", Spaces, Message );
LOG( MessageExpanded, context.c_str(), "", Type, CurrentFileName );
}//log::message
Is there a way to solve this somehow?
Thanks in advance!
Update:
char * GetErrorText( DWORD dwLastError )
{
DEBUG_METHOD( INFO );
DEBUG_MESSAGE( INFO, "Argument1 = '%d'", dwLastError );
HMODULE hModule = NULL; // default to system source
LPSTR MessageBuffer;
DWORD dwBufferLength;
char Error[ SMALL ] = { 0 };
char * ErrorMsg = NULL;
DWORD dwFormatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM;
// If dwLastError is in the network range, load the message source.
if ( dwLastError >= NERR_BASE && dwLastError <= MAX_NERR )
{
hModule = LoadLibraryEx( TEXT( "netmsg.dll" ), NULL, LOAD_LIBRARY_AS_DATAFILE );
if ( hModule != NULL ) dwFormatFlags |= FORMAT_MESSAGE_FROM_HMODULE;
}
// Call FormatMessage() to allow for message text to be acquired from the system or from the supplied module handle.
if ( dwBufferLength = FormatMessageA(
dwFormatFlags,
hModule, // module to get message from (NULL == system)
dwLastError,
MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // default language
( LPSTR )&MessageBuffer,
0,
NULL
)
)
{
memset( Error, 0, sizeof( Error ) );
//printf( "\n%s", MessageBuffer );
sprintf( Error, "%s", MessageBuffer );
ErrorMsg = Error;
// Free the buffer allocated by the system.
LocalFree( MessageBuffer );
}
// If we loaded a message source, unload it.
if ( hModule != NULL ) FreeLibrary( hModule );
return ErrorMsg;
}//GetErrorText
GetErrorText() is returning a pointer to a local buffer:
char Error[ SMALL ] = { 0 };
So the pointer it returns is invalid by the time _debugLog.message() is called.
How can I pin application icon to metro start screen in win8 programmatically(c++)? I know how to do it manually. I also know that it will be added automatically once I launch that application.
I found this solution here
BOOL PinToStart( LPCWSTR szFilePath )
{
BOOL bSuccess = FALSE;
// break into file name and path
WCHAR lpszDirectoryName[ MAX_PATH ] = { 0 };
LPCWSTR lpszFileName = ::PathFindFileName( szFilePath );
wcscpy_s( lpszDirectoryName, szFilePath );
::PathRemoveFileSpec( lpszDirectoryName );
// load shell32.dll
HMODULE hShell32 = LoadLibrary( L"SHELL32" );
if( hShell32 != NULL )
{
// get the localized translation of 'Pin to Start' verb
WCHAR szPinToStartLocalized[ MAX_PATH ] = { 0 };
int nPinToStartLocalizedLength = LoadString( (HINSTANCE)hShell32, 51201, szPinToStartLocalized, MAX_PATH );
if( nPinToStartLocalizedLength > 0 )
{
// create the shell object
IShellDispatch *pShellDispatch = NULL;
HRESULT hr = CoCreateInstance(CLSID_Shell, NULL, CLSCTX_INPROC_SERVER, IID_IShellDispatch, (void**)&pShellDispatch);
if( SUCCEEDED( hr ) )
{
Folder *pFolder = NULL;
variant_t vaDirectory( lpszDirectoryName );
// get the namespace
if( SUCCEEDED( pShellDispatch->NameSpace( vaDirectory, &pFolder ) ) )
{
FolderItem *pItem = NULL;
bstr_t vaFileName( lpszFileName );
// parse the name
if( SUCCEEDED( pFolder->ParseName( vaFileName, &pItem ) ) )
{
FolderItemVerbs* pVerbs = NULL;
// get the verbs
if( SUCCEEDED( pItem->Verbs(&pVerbs) ) )
{
long nCount = 0;
if( SUCCEEDED ( pVerbs->get_Count( &nCount ) ) )
{
variant_t vaIndex;
vaIndex.vt = VT_I4;
// iterate through verbs
for( vaIndex.lVal = 0; vaIndex.lVal<nCount; vaIndex.lVal++ )
{
FolderItemVerb* pVerb = NULL;
if( SUCCEEDED( pVerbs->Item( vaIndex, &pVerb ) ) )
{
BSTR bstrVerbName = NULL;
// check for 'Pin to Start' verb
if( SUCCEEDED( pVerb->get_Name( &bstrVerbName ) ) )
{
if( 0 == wcscmp( bstrVerbName, szPinToStartLocalized ) )
{
bSuccess = SUCCEEDED( pVerb->DoIt() );
vaIndex.lVal = nCount; // break for
}
::SysFreeString( bstrVerbName );
}
pVerb->Release();
} // if
} // for
}
pVerbs->Release();
}
pItem->Release();
}
pFolder->Release();
}
pShellDispatch->Release();
}
}
::FreeLibrary( hShell32 );
}
return bSuccess;
}
Hope it's help you
I am using a specialized network streaming camera and I am trying to save the video stream off in a file. at the moment the code saves the video but in an ackward RGB format which screws up the color and then saves it using VFW. Am i doing this correctly and this is supposed to create avi with mismatched colors or did i setup something wrong in the BITMAPINFOHEADER areas?
void PvSbProUISampleDlg::OnBnClickedSave()
{
// TODO: Add your control notification handler code here
CString StringValue;
mMovieSave.GetWindowTextW(StringValue);
if (StringValue == L"Save")
{
CString codecValue;
mMovieCodecSelected.GetWindowTextW(codecValue);
if (codecValue.IsEmpty()){
MessageBox( L"Please select a codec before saving to file",
L"Select Codec!",
MB_OK | MB_ICONEXCLAMATION );
return;
}
CString fileNameValue;
mFileName.GetWindowTextW(fileNameValue);
if (fileNameValue.IsEmpty()){
MessageBox( L"Please select a file location",
L"Select File!",
MB_OK | MB_ICONEXCLAMATION );
return;
}
if (!StartMovie())
return;
mSavingMovie = true;
mMovieSave.SetWindowTextW(L"Saving");
}
else
{
mVideoMutex.Lock();
PvResult aResult = mVideoCompressor->Stop();
mSavingMovie = false;
mVideoMutex.Unlock();
if (!aResult.IsOK())
{
MessageBox( mLocation,
L"Can't Stop Video Compressor!",
MB_OK | MB_ICONEXCLAMATION );
return;
}
mMovieSave.SetWindowTextW(L"Save");
}
}
I set up the video stream and select uncompressed AVI for my codec. I click "save" button which then calls the function below
bool PvSbProUISampleDlg::StartMovie()
{
if ( !mDevice.IsConnected() )
{
MessageBox( L"Need to connect to device",
L"Cannot start Video Compressor!",
MB_OK | MB_ICONEXCLAMATION );
return false;
}
if (!mPipeline.IsStarted() )
{
return false;
}
if (mSavingMovie)
return false;
PvInt64 width;
PvInt64 height;
PvInt64 bitCount;
if (!GetImageWidth(width).IsOK())
return false;
if (!GetImageHeight(height).IsOK())
return false;
if (!GetPixelBitCount(bitCount).IsOK())
return false;
// Start the movie compressor
if ( !mVideoCompressor->Start( mLocation,
width,
height,
bitCount/8,
59).IsOK())
{
MessageBox( mLocation,
L"Cannot start Video Compressor!",
MB_OK | MB_ICONEXCLAMATION );
return false;
}
return true;
}
the function gets the video size info and then calls the actually compression to start
PvResult VideoCompressor::Start(const CString& aFileName, unsigned short aSizeX, unsigned short aSizeY, unsigned short aBPP, double aFPS)
{
IAVIFile *lAVIFile = NULL;
IAVIStream *lAVIStream = NULL;
IAVIStream *lAVICompressedStream = NULL;
AVISTREAMINFO lAVISTREAMINFO;
AVICOMPRESSOPTIONS lAVICOMPRESSOPTIONS;
// Try to match the image format with the Video Compressor capabilities
BITMAPINFO lTempBI;
lTempBI.bmiHeader.biSize = sizeof( BITMAPINFO );
lTempBI.bmiHeader.biWidth = aSizeX;
lTempBI.bmiHeader.biHeight = aSizeY;
lTempBI.bmiHeader.biPlanes = 1;
lTempBI.bmiHeader.biBitCount = aBPP * 8;
lTempBI.bmiHeader.biCompression = BI_RGB;
lTempBI.bmiHeader.biSizeImage = aSizeX * aSizeY * aBPP;
lTempBI.bmiHeader.biXPelsPerMeter = 1280;
lTempBI.bmiHeader.biYPelsPerMeter = 720;
lTempBI.bmiHeader.biClrUsed = 0;
lTempBI.bmiHeader.biClrImportant = 0;
//lTempBI.bmiHeader.
if( ( mCOMPVARS.hic != NULL ) && // if not the "Full Frames (uncompressed)"
( ICCompressQuery( mCOMPVARS.hic, &lTempBI, NULL ) != ICERR_OK ) )
{
mLastVideoError = "Image format not accepted by compressor!";
CleanUp(lAVIFile, lAVIStream ,lAVICompressedStream);
return PvResult::Code::GENERIC_ERROR;
}
// Try to open the stream for writing
if( mTempBuffer )
delete [] mTempBuffer;
mTempBuffer = new unsigned char[ aSizeX * aSizeY * aBPP ];
if( mTempBuffer == NULL )
{
mLastVideoError = "Cannot allocate memory for a temporary buffer!";
CleanUp(lAVIFile, lAVIStream ,lAVICompressedStream);
return PvResult::Code::GENERIC_ERROR;
}
if( AVIFileOpen( &lAVIFile, aFileName, OF_CREATE | OF_WRITE, NULL ) != 0 )
{
mLastVideoError = "Cannot open movie file for writing!";
CleanUp(lAVIFile, lAVIStream ,lAVICompressedStream);
return PvResult::Code::GENERIC_ERROR;
}
// Fill out AVIStream information
memset( &lAVISTREAMINFO, 0, sizeof( AVISTREAMINFO ) );
lAVISTREAMINFO.fccType = streamtypeVIDEO;
lAVISTREAMINFO.fccHandler = mCOMPVARS.fccHandler;
lAVISTREAMINFO.dwFlags = 0;
lAVISTREAMINFO.dwCaps = 0;
lAVISTREAMINFO.wPriority = 0;
lAVISTREAMINFO.wLanguage = 0;
lAVISTREAMINFO.dwScale = 100;
lAVISTREAMINFO.dwRate = (unsigned long)( aFPS * 100.0 );
lAVISTREAMINFO.dwStart = 0;
lAVISTREAMINFO.dwLength = 0;
lAVISTREAMINFO.dwInitialFrames = 0;
lAVISTREAMINFO.dwQuality = mCOMPVARS.lQ;
lAVISTREAMINFO.dwSuggestedBufferSize = aSizeX * aSizeY * aBPP;
lAVISTREAMINFO.dwSampleSize = aSizeX * aSizeY * aBPP;
SetRect(&lAVISTREAMINFO.rcFrame, 0, aSizeY, aSizeX, 0);
// Convert to a wchar_t*
char *orig = "Video Stream";
size_t origsize = strlen(orig) + 1;
const size_t newsize = 64;
size_t convertedChars = 0;
mbstowcs_s(&convertedChars, lAVISTREAMINFO.szName, origsize, orig, _TRUNCATE);
if( AVIFileCreateStream( lAVIFile, &lAVIStream, &lAVISTREAMINFO ) != 0 )
{
mLastVideoError = "Cannot create video stream!";
CleanUp(lAVIFile, lAVIStream ,lAVICompressedStream);
return PvResult::Code::GENERIC_ERROR;
}
BITMAPINFOHEADER lBIH;
lBIH.biSize = sizeof( BITMAPINFOHEADER );
lBIH.biWidth = aSizeX;
lBIH.biHeight = aSizeY;
lBIH.biPlanes = 1;
lBIH.biBitCount = aBPP * 8;
lBIH.biCompression = BI_RGB;
lBIH.biSizeImage = aSizeX * aSizeY * aBPP;
lBIH.biXPelsPerMeter = 1280;
lBIH.biYPelsPerMeter = 720;
lBIH.biClrUsed = 0;
lBIH.biClrImportant = 0;
memset( &lAVICOMPRESSOPTIONS, 0, sizeof( AVICOMPRESSOPTIONS ) );
lAVICOMPRESSOPTIONS.fccType = streamtypeVIDEO;
lAVICOMPRESSOPTIONS.fccHandler = mCOMPVARS.fccHandler;
lAVICOMPRESSOPTIONS.dwKeyFrameEvery = 15;
lAVICOMPRESSOPTIONS.dwQuality = mCOMPVARS.lQ;
lAVICOMPRESSOPTIONS.dwBytesPerSecond = 0;
lAVICOMPRESSOPTIONS.dwFlags = AVICOMPRESSF_KEYFRAMES; //| AVICOMPRESSF_VALID;//|AVICOMPRESSF_DATARATE;
lAVICOMPRESSOPTIONS.lpFormat = &lBIH;
lAVICOMPRESSOPTIONS.cbFormat = sizeof( lBIH );
lAVICOMPRESSOPTIONS.lpParms = 0;
lAVICOMPRESSOPTIONS.cbParms = 0;
lAVICOMPRESSOPTIONS.dwInterleaveEvery = 0;
HRESULT lR = AVIMakeCompressedStream( &lAVICompressedStream, lAVIStream, &lAVICOMPRESSOPTIONS, NULL);
if( lR == AVIERR_NOCOMPRESSOR )
{
mLastVideoError = "Cannot find a suitable compressor!";
CleanUp(lAVIFile, lAVIStream ,lAVICompressedStream);
return PvResult::Code::GENERIC_ERROR;
}
else if( lR == AVIERR_MEMORY )
{
mLastVideoError = "Not enough memory to start the compressor!";
CleanUp(lAVIFile, lAVIStream ,lAVICompressedStream);
return PvResult::Code::GENERIC_ERROR;
}
else if( lR == AVIERR_UNSUPPORTED )
{
mLastVideoError = "Compression is not supported for this image buffer!";
CleanUp(lAVIFile, lAVIStream ,lAVICompressedStream);
return PvResult::Code::GENERIC_ERROR;
}
if( AVIStreamSetFormat( lAVICompressedStream, 0, &lBIH, sizeof( lBIH ) ) != 0 )
{
mLastVideoError = "Cannot set stream format. It probably isn't supported by the Codec!";
CleanUp(lAVIFile, lAVIStream ,lAVICompressedStream);
return PvResult::Code::GENERIC_ERROR;
}
///////////////////
HRESULT hr;
//IBaseFilter mux = Null;
//IFileSinkFilter sink = null;
// Guid x = new Guid( 0xe436eb88, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70 );
//ICaptureGraphBuilder2::SetOutputFileName(
//////////////////
// finishing up
mAVIFile = lAVIFile;
mAVIStream = lAVIStream;
mAVICompressedStream = lAVICompressedStream;
mSizeX = aSizeX;
mSizeY = aSizeY;
mBPP = aBPP;
mImageSize = aSizeX * aSizeY * aBPP;
mLastSample = 0;
mCompressing = true;
return PvResult::Code::OK;
}
this compresses the stream
PvResult VideoCompressor::Compress(PvBuffer *aPvBuffer)
{
if (!mCompressing)
return PvResult::Code::GENERIC_ERROR;
ASSERT( mTempBuffer != NULL );
long lSamplesWritten, lBytesWritten;
int numberOfLines = 0;
PvUInt8 * aBuffer = aPvBuffer->GetDataPointer();
for( unsigned short lLine = 0; lLine < mSizeY; lLine++ )
{
numberOfLines = lLine;
unsigned char *lCurLine = (unsigned char *)aBuffer + (lLine ) * mSizeX * mBPP;
unsigned char *lCurLineInv = mTempBuffer + (mSizeY - lLine - 1) * mSizeX * mBPP;
::memcpy( lCurLineInv, lCurLine, mSizeX * mBPP );
}
if( AVIStreamWrite( mAVICompressedStream, mLastSample, 1, mTempBuffer, mImageSize, 0,
&lSamplesWritten, &lBytesWritten ) != 0 ||
lSamplesWritten < 1 ||
lBytesWritten < 1 )
{
mLastVideoError = "Cannot compress image!";
return PvResult::Code::GENERIC_ERROR;
}
mLastSample ++;
return PvResult::Code::OK;
}
this is what it should look like:
http://i13.photobucket.com/albums/a269/Masterg_/Untitled-16.png
this is what it saves as ( minus the guy):
http://i13.photobucket.com/albums/a269/Masterg_/vlcsnap-2011-06-07-13h11m34s97.png
From MSDN we have:
Syntax
DWORD ICCompressQuery(
hic,
lpbiInput,
lpbiOutput );
Parameters
hic : Handle to a compressor.
lpbiInput : Pointer to a BITMAPINFO structure containing the input format.
lpbiOutput : Pointer to a BITMAPINFO structure containing the output format. You can
specify zero for this parameter to
indicate any output format is
acceptable.
I might be wrong, but it seems to me that you are trying to "force" this input format whitout taking into account the actual format you are passing as input. If your input format does not match the "forced" one, weird result must be expected.
If your actual input format is not compatible with your compressor, you could try usign a ColorSpace converter filter before your compressor.