Empty outputInfoList for second graphic card - c++

I have two discrete video adapters on my PC: GTX 1060 and RTX 2080 ti.
I would like to use second one for my DXUT app. I found command line argument -adapter# to specify it, however, my program crashed when I run with -adapter1 (1 is adapter ordinal for RTX2080) option.
I started debugging and figured out the following issue: EnumOutputs returns only DXGI_ERROR_NOT_FOUND.
For GTX1060 first EnumOutputs call returns correct output.
Code section:
HRESULT CD3D11Enumeration::EnumerateOutputs( _In_ CD3D11EnumAdapterInfo* pAdapterInfo )
{
HRESULT hr;
IDXGIOutput* pOutput;
for( int iOutput = 0; ; ++iOutput )
{
pOutput = nullptr;
//next line returns at once DXGI_ERROR_NOT_FOUND for RTX2080
hr = pAdapterInfo->m_pAdapter->EnumOutputs( iOutput, &pOutput );
if( DXGI_ERROR_NOT_FOUND == hr )
{
return S_OK;
}
...
}
hr = EnumerateOutputs( pAdapterInfo );
if( FAILED( hr ) || pAdapterInfo->outputInfoList.empty() ) //failed here cause second condition is true
{
delete pAdapterInfo;
continue;
}
Who know how to fix this problem?
All drivers are up to date.
P.S. I also tried to specify graphic card via Windows and GeForce software, but It seems appropriate only for laptop case with both integrate/discrete cards.

Oh my God..
The problem is only GTX1060 connected to my monitor.
My tutor explained me that it's impossible to render frame buffer in this case.

Related

Implement Microsoft Speech Platform languages in SAPI 5

I created a little program in C++ where I use the SAPI library. In my code, I list the number of voices installed on my system. When I compile, I get 11, but there are only 8 installed and the only voice speaking is Microsoft Anna. I checked it in the registry (HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\Voices).
I have several languages installed , especially languages from the Microsoft Speech Platform but none can be used.
Furthermore, when I change the voice ID, I get an unhandled exception error and I think it is because the chosen ID does not exist.
Here is my code
#include "stdafx.h"
int main( int argc, char* argv[] )
{
CComPtr<ISpObjectToken> cpVoiceToken;
CComPtr<IEnumSpObjectTokens> cpEnum;
ISpVoice * pVoice = NULL;
ULONG count = 0;
string str;
if( FAILED( ::CoInitialize( NULL ) ) )
return FALSE;
HRESULT hr = CoCreateInstance( CLSID_SpVoice, NULL, CLSCTX_ALL,
IID_ISpVoice, ( void ** )&pVoice );
if( SUCCEEDED( hr ) )
{
//Enumerate Voices
hr = SpEnumTokens( SPCAT_VOICES, NULL /*L"Gender=Female"*/, NULL, &cpEnum);
printf( "Success\n" );
}
else
{
printf( "Failed to initialize SAPI" );
}
if( SUCCEEDED( hr ) )
{
//Get number of voices
hr = cpEnum->GetCount( &count );
printf( "TTS voices found: %i\n", count );
}
else
{
printf( "Failed to enumerate voices" );
hr = S_OK;
}
if( SUCCEEDED( hr ) )
{
cpVoiceToken.Release();
cpEnum->Item( 3, &cpVoiceToken ); //3 represents the ID of the voice
pVoice->SetVoice( cpVoiceToken );
hr = pVoice->Speak( L"You have selected Microsoft Server Speech Text to Speech Voice (en-GB, Hazel) as the computer's default voice.", 0, NULL ); //speak sentence
pVoice->Release();
pVoice = NULL;
}
::CoUninitialize();
system( "PAUSE" );
}
The only voice working is Microsoft Anna, and I don't understand why. If the other languages were not available, the program won't show me that there are so many(11). I wonder if the Microsoft Speech Platform languages are compatible with SAPI.
After many tries and fails, I managed to find an answer to my problem.
I compiled my program in Win32. So I decided to change it to x64 and I recompiled the solution. I changed the voice ID in my program, and the voices from the Microsoft Speech Platform worked. This means that the MS Speech Platform languages are 64 bit voices and Microsoft Anna is a 32 bit voice.
The following post inspired me.

Using xaudio2 and a parallel port together

I am using C++ to code a neuroscience experiment in my research lab. We are studying tactile perception, and we use a parallel port to trigger our brain stimulating device. The timing is very important.
We recently started using xaudio2 to play very simple WAV files, which are used to trigger our vibrotactile stimulators (for example, our "tactile" stimuli are 100 and 200 Hz sounds with a duration of 100 ms, that move a piezo-electric stimulator that is placed on the hand).
Our problem is that we need to send out 3 commands to the brain stimulator via the parallel port: once 40 ms before the tactile stimulus, once 10 ms after the start of the stimulus, and a third time 60 ms into the stimulus. Remember, the tactile stimulus lasts 100 ms.
However, the way xaudio2 triggers sound is that it plays the wave and blocks until it is finished. As a consequence, the program ignores the two parallel port commands which should be sent during the stimulus.
Does anybody know how I can make sure the tactile stimulus is still triggered for the entirety of its 100 ms duration, but also send out parallel port commands during it? I am using the MSDN XAudio2Samples as the basic structure for playing the wav files, and the PlayWave function is the one which "blocks" any other input while the Wav file is playing -- but I can't figure out how to modify it so that it will also take my parallel port commands (which are Out32(888,1)) while a sound is being played.
Thank you!
Here is the code for the PlayWave function:
//--------------------------------------------------------------------------------------
// Name: PlayWave
// Desc: Plays a wave and blocks until the wave finishes playing
//--------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT PlayWave( IXAudio2* pXaudio2, LPCWSTR szFilename )
{
//
// Locate the wave file
//
WCHAR strFilePath[MAX_PATH];
HRESULT hr = FindMediaFileCch( strFilePath, MAX_PATH, szFilename );
if( FAILED( hr ) )
{
wprintf( L"Failed to find media file: %s\n", szFilename );
return hr;
}
//
// Read in the wave file
//
std::unique_ptr<uint8_t[]> waveFile;
DirectX::WAVData waveData;
if ( FAILED( hr = DirectX::LoadWAVAudioFromFileEx( strFilePath, waveFile, waveData ) ) )
{
wprintf( L"Failed reading WAV file: %#X (%s)\n", hr, strFilePath );
return hr;
}
//
// Play the wave using a XAudio2SourceVoice
//
// Create the source voice
IXAudio2SourceVoice* pSourceVoice;
if( FAILED( hr = pXaudio2->CreateSourceVoice( &pSourceVoice, waveData.wfx ) ) )
{
wprintf( L"Error %#X creating source voice\n", hr );
return hr;
}
// Submit the wave sample data using an XAUDIO2_BUFFER structure
XAUDIO2_BUFFER buffer = {0};
buffer.pAudioData = waveData.startAudio;
buffer.Flags = XAUDIO2_END_OF_STREAM; // tell the source voice not to expect any data after this buffer
buffer.AudioBytes = waveData.audioBytes;
if ( waveData.loopLength > 0 )
{
buffer.LoopBegin = waveData.loopStart;
buffer.LoopLength = waveData.loopLength;
buffer.LoopCount = 1; // We'll just assume we play the loop twice
}
#if (_WIN32_WINNT < 0x0602 /*_WIN32_WINNT_WIN8*/)
if ( waveData.seek )
{
XAUDIO2_BUFFER_WMA xwmaBuffer = {0};
xwmaBuffer.pDecodedPacketCumulativeBytes = waveData.seek;
xwmaBuffer.PacketCount = waveData.seekCount;
if( FAILED( hr = pSourceVoice->SubmitSourceBuffer( &buffer, &xwmaBuffer ) ) )
{
wprintf( L"Error %#X submitting source buffer (xWMA)\n", hr );
pSourceVoice->DestroyVoice();
return hr;
}
}
#else
if ( waveData.seek )
{
wprintf( L"This platform does not support xWMA or XMA2\n" );
pSourceVoice->DestroyVoice();
return hr;
}
#endif
else if( FAILED( hr = pSourceVoice->SubmitSourceBuffer( &buffer ) ) )
{
wprintf( L"Error %#X submitting source buffer\n", hr );
pSourceVoice->DestroyVoice();
return hr;
}
hr = pSourceVoice->Start( 0 );
// Let the sound play
BOOL isRunning = TRUE;
while( SUCCEEDED( hr ) && isRunning )
{
XAUDIO2_VOICE_STATE state;
pSourceVoice->GetState( &state );
isRunning = ( state.BuffersQueued > 0 ) != 0;
// Wait till the escape key is pressed
if( GetAsyncKeyState( VK_ESCAPE ) )
break;
Sleep( 10 );
}
// Wait till the escape key is released
while( GetAsyncKeyState( VK_ESCAPE ) )
Sleep( 10 );
pSourceVoice->DestroyVoice();
return hr;
}

WIA 2.0, C++: IWiaDevMgr2::EnumDeviceInfo doesn't detect connected camera

I'm trying to write a program that transfers images and videos from a camera (for my personal use, on Win 8.1). I'm using Microsoft's example code as a starting point (WIA Tutorial), and I've hit a wall trying to detect connected camera devices. The problem is that there are no errors and the code seems to work, but it just doesn't detect any connected camera (I've tried with two different cameras), while the camera is clearly detected by the OS (shows up in Windows Explorer).
Am I missing something? Is IWiaDevMgr2::EnumDeviceInfo not the way to detect connected devices? Here's the code I'm using:
HRESULT WiaCreateDeviceManager(IWiaDevMgr2 **ppWiaDevMgr)
{
if(NULL == ppWiaDevMgr) return E_INVALIDARG;
*ppWiaDevMgr = NULL;
// Create an instance of the device manager
HRESULT hr = CoCreateInstance(CLSID_WiaDevMgr2, NULL, CLSCTX_LOCAL_SERVER, IID_IWiaDevMgr2, (void**)ppWiaDevMgr);
return hr;
}
HRESULT WiaEnumerateDevices(IWiaDevMgr2 *pWiaDevMgr)
{
if(NULL == pWiaDevMgr)
{
return E_INVALIDARG;
}
// Get a device enumerator interface
IEnumWIA_DEV_INFO *pWiaEnumDevInfo = NULL;
HRESULT hr = pWiaDevMgr->EnumDeviceInfo(WIA_DEVINFO_ENUM_LOCAL, &pWiaEnumDevInfo);
assert(hr == S_OK);
if(SUCCEEDED(hr))
{
ULONG count(911);
HRESULT res = pWiaEnumDevInfo->GetCount(&count);
if(res == S_OK) printf("EnumDeviceInfo: count = %lu\n", count); // count is always zero
else printf("IEnumWIA_DEV_INFO::GetCount() failed!\n");
// Loop until you get an error or pWiaEnumDevInfo->Next returns
// S_FALSE to signal the end of the list.
while(S_OK == hr)
{
// Get the next device's property storage interface pointer
IWiaPropertyStorage *pWiaPropertyStorage = NULL;
hr = pWiaEnumDevInfo->Next(1, &pWiaPropertyStorage, NULL);
// pWiaEnumDevInfo->Next will return S_FALSE when the list is
// exhausted, so check for S_OK before using the returned
// value.
if(hr == S_OK)
{
// Do something with the device's IWiaPropertyStorage*
WiaReadProperties(pWiaPropertyStorage); // this line is never reached
// Release the device's IWiaPropertyStorage*
pWiaPropertyStorage->Release();
pWiaPropertyStorage = NULL;
}
}
// If the result of the enumeration is S_FALSE (which
// is normal), change it to S_OK.
if(S_FALSE == hr) hr = S_OK;
// Release the enumerator
pWiaEnumDevInfo->Release();
pWiaEnumDevInfo = NULL;
}
return hr;
}
int main()
{
...
IWiaDevMgr2 *wiamgr;
WiaCreateDeviceManager(&wiamgr);
HRESULT res = WiaEnumerateDevices(wiamgr); // res is always S_OK, but no device is detected
...
}
Apparently, WIA does not support camera devices on Windows Vista and later. I've only seen this implied or mentioned in passing twice in the WIA documentation, the last time being on this page. I can't believe this is happening, after I've spent so much time researching WIA. Apparently, I'm supposed to be using WPD for cameras, not WIA.
Edit: That being said, I'm still not sure what's going on. If I can't use WIA programmatically on Win 8.1, then why do these PowerShell commands work?
$WIAdialog = New-Object -ComObject "WIA.CommonDialog"
$Device = $WIAdialog.ShowSelectDevice()
$i=$WIAdialog.ShowAcquireImage()
$i.SaveFile("$pwd\test.$($i.fileExtension)")
Is it that only the API doesn't work for cameras, while the Scripting Model does?

IDirectDrawSurface7::Blt returned E_INVALIDARG

Step1:
Image* image = NULL;
image = Bitmap::FromFile(m_lpwFPSImagePath[i], TRUE);
DDSURFACEDESC2 ddsd;
DDCOLORKEY ddck;
ZeroMemory( &ddsd, sizeof( ddsd ) );
ddsd.dwSize = sizeof( ddsd );
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
ddsd.dwWidth = image->GetWidth();;
ddsd.dwHeight = image->GetHeight();
hr = m_pDevice->CreateSurface(&ddsd, &m_pFPSTexture, NULL );
if( hr != DD_OK )
{
if(hr == DDERR_OUTOFVIDEOMEMORY)
{
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN |
DDSCAPS_SYSTEMMEMORY;
hr = m_pDevice->CreateSurface(&ddsd, &m_pFPSTexture, NULL );
}
}
Step2:
RECT SrcRect={0,0,fTexWidth,fTexHeight};
RECT DstRect = {0,0,60,20};
hr = m_pPrimarySurf->Blt(&DstRect,
m_pFPSTexture,&SrcRect,DDBLT_WAIT,NULL);
Note:
The image size is : 3170 x 64
m_pPrimarySurf->Blt(...) returned E_INVALIDARG . So why ?
Thx !
Happened to me too. I fixed it by changing driver type. When I created DirectDraw object, I specified that software only rendering should be used. LPDIRECTDRAW dd; HRESULT const dd_created = DirectDrawCreate(reinterpret_cast<GUID*>(DDCREATE_EMULATIONONLY), &dd, nullptr); as stated in DirectDrawCreate function documentation on MSDN. I'm running x86 application on Windows 10 x64 version 10.0.18363.1082, inside VirtualBox 5.2.42_Ubuntu r137960 inside Ubuntu x64 18.04.5 LTS on Lenovo laptop with IntelĀ® UHD Graphics 620 (WHL GT2) graphics.

Windows Media Foundation recording audio

I'm using the windows media foundation api to enumerate both my microphones and available cameras, which both work.
Here is my enumeration code:
class deviceInput {
public:
deviceInput( REFGUID source );
~deviceInput();
int listDevices(bool refresh = false);
IMFActivate *getDevice(unsigned int deviceId);
const WCHAR *getDeviceName(unsigned int deviceId);
private:
void Clear();
HRESULT EnumerateDevices();
UINT32 m_count;
IMFActivate **m_devices;
REFGUID m_source;
};
deviceInput::deviceInput( REFGUID source )
: m_devices( NULL )
, m_count( 0 )
, m_source( source )
{ }
deviceInput::~deviceInput()
{
Clear();
}
int deviceInput::listDevices(bool refresh)
{
if ( refresh || !m_devices ) {
if ( FAILED(this->EnumerateDevices()) ) return -1;
}
return m_count;
}
IMFActivate *deviceInput::getDevice(unsigned int deviceId)
{
if ( deviceId >= m_count ) return NULL;
IMFActivate *device = m_devices[deviceId];
device->AddRef();
return device;
}
const WCHAR *deviceInput::getDeviceName(unsigned int deviceId)
{
if ( deviceId >= m_count ) return NULL;
HRESULT hr = S_OK;
WCHAR *devName = NULL;
UINT32 length;
hr = m_devices[deviceId]->GetAllocatedString( MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, &devName, &length );
if ( FAILED(hr) ) return NULL;
return devName;
}
void deviceInput::Clear()
{
if ( m_devices ) {
for (UINT32 i = 0; i < m_count; i++) SafeRelease( &m_devices[i] );
CoTaskMemFree( m_devices );
}
m_devices = NULL;
m_count = 0;
}
HRESULT deviceInput::EnumerateDevices()
{
HRESULT hr = S_OK;
IMFAttributes *pAttributes = NULL;
Clear();
hr = MFCreateAttributes(&pAttributes, 1);
if ( SUCCEEDED(hr) ) hr = pAttributes->SetGUID( MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, m_source );
if ( SUCCEEDED(hr) ) hr = MFEnumDeviceSources( pAttributes, &m_devices, &m_count );
SafeRelease( &pAttributes );
return hr;
}
To grab audio or camera capture devices, I specify either MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID or MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID and that works no problem, and I can grab the names of the devices, as well as the IMFActivate. I have code to record the webcam to an output video file, however, I'm having a tough time figuring out how to record the audio to a file. I'm under the impression that I need to use an IMFSinkWriter, but I can't find any examples that use an audio capture IMFActivate and IMFSinkWriter.
I'm not much of a windows api programmer, so I'm sure there's a fairly straight forward answer, but COM stuff is just a bit over my head. As far as audio format, I don't really care, as long as it gets into a file - can be wav, wma, or whatever. Even though I'm recording video, I need the video and audio files separate, so I can't just figure out how to add the audio into my video encoding.
I apologize for the late response, and I hope you can still find this valuable. I recently completed a project similar to yours (recording webcam video along with a selected microphone to a single video file with audio). The key is to creating an aggregate media source.
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd388085(v=vs.85).aspx
HRESULT CreateAggregateMediaSource(IMFMediaSource *videoSource,
IMFMediaSource *audioSource,
IMFMediaSource **aggregateSource)
{
*aggregateSource = nullptr;
IMFCollection *pCollection = nullptr;
HRESULT hr = ::MFCreateCollection(&pCollection);
if (S_OK == hr)
hr = pCollection->AddElement(videoSource);
if (S_OK == hr)
hr = pCollection->AddElement(audioSource);
if (S_OK == hr)
hr = ::MFCreateAggregateSource(pCollection, aggregateSource);
SafeRelease(&pCollection);
return hr;
}
When configuring the sink writer, you will add 2 streams (one for audio and one for video).
Of course, you will also configure the writer correctly for the input stream types.
HRESULT hr = S_OK;
IMFMediaType *videoInputType = nullptr;
IMFMediaType *videoOutputType = nullptr;
DWORD videoOutStreamIndex = 0u;
DWORD audioOutStreamIndex = 0u;
IMFSinkWriter *writer = nullptr;
// [other create and configure writer]
if (S_OK == hr))
hr = writer->AddStream(videoOutputType, &videoOutStreamIndex);
// [more configuration code]
if (S_OK == hr)
hr = writer->AddStream(audioOutputType, &audioOutStreamIndex);
Then when reading the samples, you will need to pay close attention to the reader streamIndex, and sending them to the writer appropriately. You will also need to pay close attention to the format that the codec expects. For instance, IEEE float vs PCM, etc. Good luck, and I hope it is not too late.
Did you have hard time to manage DirectShow audio capture in Record directshow audio device to file?
Capturing with Media Foundation is hardly any simpler. Not even mentioning that in general there are a lot more resources on DirectShow out there....
MSDN offers you a WavSink Sample that implements audio capture into file:
Shows how to implement a custom media sink in Microsoft Media Foundation. The sample implements an archive sink that writes uncompressed PCM audio to a .wav file.
I am not sure why they decided to not make this a standard component. Having Media Foundation inferior to DirectShow in many ways, they could at least make this small thing as an advantage. Anyway, you have the sample and it looks like a good start.