I'm having this error and I can't find how to solve this. Which parameter should i change? I am having this error.
error C2664: 'WinBioLocateSensorWithCallback' : cannot convert parameter 2 from 'void (__stdcall *)(void)' to 'PWINBIO_LOCATE_SENSOR_CALLBACK'
Thanks for your help guys!
Here is the code
#include <Windows.h>
#include <Conio.h>
#include <Stdio.h>
#include <WinBio.h>
VOID CALLBACK LocateSensorCallback();
HRESULT LocateSensorWithCallback(BOOL bCancel)
{
HRESULT hr = S_OK;
WINBIO_SESSION_HANDLE sessionHandle = NULL;
WINBIO_UNIT_ID unitId = 0;
// Connect to the system pool.
hr = WinBioOpenSession(
WINBIO_TYPE_FINGERPRINT, // Service provider
WINBIO_POOL_SYSTEM, // Pool type
WINBIO_FLAG_DEFAULT, // Configuration and access
NULL, // Array of biometric unit IDs
0, // Count of biometric unit IDs
NULL, // Database ID
&sessionHandle // [out] Session handle
);
if (FAILED(hr))
{
wprintf_s(L"\n WinBioOpenSession failed. hr = 0x%x\n", hr);
goto e_Exit;
}
wprintf_s(L"\n Calling WinBioLocateSensorWithCallback.");
hr = WinBioLocateSensorWithCallback(
sessionHandle, // Open biometric session
LocateSensorCallback, // Callback function
NULL // Optional context
);
if (FAILED(hr))
{
wprintf_s(L"\n WinBioLocateSensorWithCallback failed.");
wprintf_s(L"hr = 0x%x\n", hr);
goto e_Exit;
}
wprintf_s(L"\n Swipe the sensor ...\n");
// Cancel the identification if the bCancel flag is set.
if (bCancel)
{
wprintf_s(L"\n Starting CANCEL timer...\n");
Sleep( 7000 );
wprintf_s(L"\n Calling WinBioCancel\n");
hr = WinBioCancel( sessionHandle );
if (FAILED(hr))
{
wprintf_s(L"\n WinBioCancel failed. hr = 0x%x\n", hr);
goto e_Exit;
}
}
// Wait for the asynchronous identification process to complete
// or be canceled.
hr = WinBioWait( sessionHandle );
if (FAILED(hr))
{
wprintf_s(L"\n WinBioWait failed. hr = 0x%x\n", hr);
}
e_Exit:
if (sessionHandle != NULL)
{
wprintf_s(L"\n Closing the session.\n");
hr = WinBioCloseSession(sessionHandle);
if (FAILED(hr))
{
wprintf_s(L"\n WinBioCloseSession failed. hr = 0x%x\n", hr);
}
sessionHandle = NULL;
}
wprintf_s(L"\n Hit any key to exit...");
_getch();
return hr;
}
//------------------------------------------------------------------------
// The following function is the callback for
// WinBioLocateSensorWithCallback. The function filters the response
// from the biometric subsystem and writes a result to the console window.
//
VOID CALLBACK LocateSensorCallback(
__in_opt PVOID LocateCallbackContext,
__in HRESULT OperationStatus,
__in WINBIO_UNIT_ID UnitId
)
{
UNREFERENCED_PARAMETER(LocateCallbackContext);
wprintf_s(L"\n LocateSensorCallback executing.");
// A sensor could not be located.
if (FAILED(OperationStatus))
{
wprintf_s(L"\n LocateSensorCallback failed.");
wprintf_s(L"OperationStatus = 0x%x\n", OperationStatus);
}
// A sensor was located.
else
{
wprintf_s(L"\n Selected unit ID: %d\n", UnitId);
}
}
void main()
{
LocateSensorWithCallback(1);
}
Your problem is that your definition for LocateSensorCallback doesn't match the signature that the WinBioLocateSensorWithCallback function expects.
Change your forward declaration at the top from
VOID CALLBACK LocateSensorCallback();
to match the actual function:
VOID CALLBACK LocateSensorCallback(
__in_opt PVOID LocateCallbackContext,
__in HRESULT OperationStatus,
__in WINBIO_UNIT_ID UnitId
);
Related
I'm working on an application which polls for the states and peak levels of audio sessions on the default audio rendering endpoint every X milliseconds, and implements some logic based on that.
It seems to run fine on Windows 10, but on Windows 7 I get occasional crashes when I change the default playback device (e.g. when I switch between my USB headset and the PC speaker).
The exact line where the crash occurs changes between runs, but it's usually when I access the IAudioSessionControl or IAudioSessionControl2 pointers to make various WASAPI calls.
What I could glean from the stack traces created by ProcDump and analyzed by WinDbg is that the COM objects representing audio sessions are destroyed when the default playback device has changed
(even though I had obtained and am still holding pointers to those objects' interfaces), and then my polling thread crashes randomly in places where I access them through the interface pointers.
I figured that maybe I'm doing something wrong, so this led me to Matthew van Eerde's
blog
and sample, where he does the same querying (and more), but for all available audio endpoints in the system.
So I modified his sample program to do it every 5 milliseconds and only for the default rendering endpoint, and I get the same occasional crashes on Windows 7.
Here is a stripped-down version of the sample, which sometimes results in crashes when switching between playback devices.
I usually get the crash within ~2 minutes of switching back-and-forth between devices. YMMV.
#include <windows.h>
#include <atlbase.h>
#include <stdio.h>
#include <mmdeviceapi.h>
#include <audiopolicy.h>
#include <endpointvolume.h>
#include <functiondiscoverykeys_devpkey.h>
#define LOG(format, ...) wprintf(format L"\n", __VA_ARGS__)
class CoUninitializeOnExit {
public:
CoUninitializeOnExit() {}
~CoUninitializeOnExit() {
CoUninitialize();
}
};
class PropVariantClearOnExit {
public:
PropVariantClearOnExit(PROPVARIANT *p) : m_p(p) {}
~PropVariantClearOnExit() {
PropVariantClear(m_p);
}
private:
PROPVARIANT *m_p;
};
int _cdecl wmain() {
HRESULT hr = S_OK;
hr = CoInitialize(NULL);
if (FAILED(hr)) {
LOG(L"CoInitialize failed: hr = 0x%08x", hr);
return -__LINE__;
}
CoUninitializeOnExit cuoe;
while (1)
{
Sleep(5);
// get default device
CComPtr<IMMDeviceEnumerator> pMMDeviceEnumerator;
hr = pMMDeviceEnumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator));
if (FAILED(hr)) {
LOG(L"CoCreateInstance(IMMDeviceEnumerator) failed: hr = 0x%08x", hr);
return -__LINE__;
}
CComPtr<IMMDevice> pMMDevice;
hr = pMMDeviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pMMDevice);
if (FAILED(hr)) {
LOG(L"IMMDeviceEnumerator::GetDefaultAudioEndpoint failed: hr = 0x%08x", hr);
return -__LINE__;
}
// get the name of the endpoint
CComPtr<IPropertyStore> pPropertyStore;
hr = pMMDevice->OpenPropertyStore(STGM_READ, &pPropertyStore);
if (FAILED(hr)) {
LOG(L"IMMDevice::OpenPropertyStore failed: hr = 0x%08x", hr);
return -__LINE__;
}
PROPVARIANT v; PropVariantInit(&v);
PropVariantClearOnExit pvcoe(&v);
hr = pPropertyStore->GetValue(PKEY_Device_FriendlyName, &v);
if (FAILED(hr)) {
LOG(L"IPropertyStore::GetValue(PKEY_Device_FriendlyName) failed: hr = 0x%08x", hr);
return -__LINE__;
}
if (VT_LPWSTR != v.vt) {
LOG(L"PKEY_Device_FriendlyName has unexpected vartype %u", v.vt);
return -__LINE__;
}
LOG(L"Selected playback device: %s\n", v.pwszVal);
// get a session enumerator
CComPtr<IAudioSessionManager2> pAudioSessionManager2;
hr = pMMDevice->Activate(
__uuidof(IAudioSessionManager2),
CLSCTX_ALL,
nullptr,
reinterpret_cast<void **>(&pAudioSessionManager2)
);
if (FAILED(hr)) {
LOG(L"IMMDevice::Activate(IAudioSessionManager2) failed: hr = 0x%08x", hr);
return -__LINE__;
}
CComPtr<IAudioSessionEnumerator> pAudioSessionEnumerator;
hr = pAudioSessionManager2->GetSessionEnumerator(&pAudioSessionEnumerator);
if (FAILED(hr)) {
LOG(L"IAudioSessionManager2::GetSessionEnumerator() failed: hr = 0x%08x", hr);
return -__LINE__;
}
// iterate over all the sessions
int count = 0;
hr = pAudioSessionEnumerator->GetCount(&count);
if (FAILED(hr)) {
LOG(L"IAudioSessionEnumerator::GetCount() failed: hr = 0x%08x", hr);
return -__LINE__;
}
for (int session = 0; session < count; session++) {
// get the session control
CComPtr<IAudioSessionControl> pAudioSessionControl;
hr = pAudioSessionEnumerator->GetSession(session, &pAudioSessionControl);
if (FAILED(hr)) {
LOG(L"IAudioSessionEnumerator::GetSession() failed: hr = 0x%08x", hr);
return -__LINE__;
}
AudioSessionState state;
hr = pAudioSessionControl->GetState(&state);
if (FAILED(hr)) {
LOG(L"IAudioSessionControl::GetState() failed: hr = 0x%08x", hr);
return -__LINE__;
}
CComPtr<IAudioSessionControl2> pAudioSessionControl2;
hr = pAudioSessionControl->QueryInterface(IID_PPV_ARGS(&pAudioSessionControl2));
if (FAILED(hr)) {
LOG(L"IAudioSessionControl::QueryInterface(IAudioSessionControl2) failed: hr = 0x%08x", hr);
return -__LINE__;
}
DWORD pid = 0;
hr = pAudioSessionControl2->GetProcessId(&pid);
if (FAILED(hr)) {
LOG(L"IAudioSessionControl2::GetProcessId() failed: hr = 0x%08x", hr);
return -__LINE__;
}
hr = pAudioSessionControl2->IsSystemSoundsSession();
if (FAILED(hr)) {
LOG(L"IAudioSessionControl2::IsSystemSoundsSession() failed: hr = 0x%08x", hr);
return -__LINE__;
}
bool bIsSystemSoundsSession = (S_OK == hr);
// get the current audio peak meter level for this session
CComPtr<IAudioMeterInformation> pAudioMeterInformation;
hr = pAudioSessionControl->QueryInterface(IID_PPV_ARGS(&pAudioMeterInformation));
if (FAILED(hr)) {
LOG(L"IAudioSessionControl::QueryInterface(IAudioMeterInformation) failed: hr = 0x%08x", hr);
return -__LINE__;
}
float peak = 0.0f;
hr = pAudioMeterInformation->GetPeakValue(&peak);
if (FAILED(hr)) {
LOG(L"IAudioMeterInformation::GetPeakValue() failed: hr = 0x%08x", hr);
return -__LINE__;
}
LOG(
L" Session #%d\n"
L" State: %d\n"
L" Peak value: %g\n"
L" Process ID: %u\n"
L" System sounds session: %s",
session,
state,
peak,
pid,
(bIsSystemSoundsSession ? L"yes" : L"no")
);
} // session
} // while
return 0;
}
Here is one instance of a crash dump analysis: https://pastebin.com/tvRV8ukY.
Is this an issue with the Windows 7 implementation of the Core Audio APIs, or am I doing something wrong?
Thanks.
I eventually contacted Matthew van Eerde by e-mail, and he said it does look like a race condition in Core Audio API on Windows 7, and my best bet is to file a support request to Microsoft.
Thanks for your help, Matthew!
I am trying to read fingerprints and save them using WBF.
I tried the sample code, however, I get an error code back. I am able to use the fingerprint reader to log into windows, but am unable to capture samples from it.
I am running Windows 10 on a Lenovo Yoga system, and VS 2015 Community.
This is what I get when I run my code:
Calling WinBioCaptureSampleWithCallback
Swipe the sensor ...
CaptureSampleCallback executing
Swipe processed - Unit ID: 0
WinBioCaptureSampleWithCallback failed. OperationStatus = 0x80004001
Press any key to exit...
Thank you!
Sample code:
HRESULT CaptureSampleWithCallback(BOOL bCancel)
{
HRESULT hr = S_OK;
WINBIO_SESSION_HANDLE sessionHandle = NULL;
// Connect to the system pool.
hr = WinBioOpenSession(
WINBIO_TYPE_FINGERPRINT, // Service provider
WINBIO_POOL_SYSTEM, // Pool type
WINBIO_FLAG_RAW, // Raw access
NULL, // Array of biometric unit IDs
0, // Count of biometric unit IDs
WINBIO_DB_DEFAULT, // Default database
&sessionHandle // [out] Session handle
);
if (FAILED(hr))
{
wprintf_s(L"\n WinBioOpenSession failed. hr = 0x%x\n", hr);
goto e_Exit;
}
// Capture a biometric sample asynchronously.
wprintf_s(L"\n Calling WinBioCaptureSampleWithCallback ");
hr = WinBioCaptureSampleWithCallback(
sessionHandle, // Open session handle
WINBIO_NO_PURPOSE_AVAILABLE, // Intended use of the sample
WINBIO_DATA_FLAG_RAW, // Sample format
CaptureSampleCallback, // Callback function
NULL // Optional context
);
if (FAILED(hr))
{
wprintf_s(L"\n WinBioCaptureSampleWithCallback failed. ");
wprintf_s(L"hr = 0x%x\n", hr);
goto e_Exit;
}
wprintf_s(L"\n Swipe the sensor ...\n");
// Cancel the capture process if the bCancel flag is set.
if (bCancel)
{
wprintf_s(L"\n Starting CANCEL timer...");
Sleep( 7000 );
wprintf_s(L"\n Calling WinBioCancel\n");
hr = WinBioCancel( sessionHandle );
if (FAILED(hr))
{
wprintf_s(L"\n WinBioCancel failed. hr = 0x%x\n", hr);
goto e_Exit;
}
}
// Wait for the asynchronous capture process to complete
// or be canceled.
hr = WinBioWait( sessionHandle );
if (FAILED(hr))
{
wprintf_s(L"\n WinBioWait failed. hr = 0x%x\n", hr);
}
e_Exit:
if (sessionHandle != NULL)
{
WinBioCloseSession(sessionHandle);
sessionHandle = NULL;
}
wprintf_s(L"\n Press any key to exit...");
_getch();
return hr;
}
//------------------------------------------------------------------------
// The following function is the callback for WinBioCaptureSampleWithCallback.
// The function filters the response from the biometric subsystem and
// writes a result to the console window.
//
VOID CALLBACK CaptureSampleCallback(
__in_opt PVOID CaptureCallbackContext,
__in HRESULT OperationStatus,
__in WINBIO_UNIT_ID UnitId,
__in_bcount(SampleSize) PWINBIO_BIR Sample,
__in SIZE_T SampleSize,
__in WINBIO_REJECT_DETAIL RejectDetail
)
{
UNREFERENCED_PARAMETER(CaptureCallbackContext);
wprintf_s(L"\n CaptureSampleCallback executing");
wprintf_s(L"\n Swipe processed - Unit ID: %d", UnitId);
if (FAILED(OperationStatus))
{
if (OperationStatus == WINBIO_E_BAD_CAPTURE)
{
wprintf_s(L"\n Bad capture; reason: %d\n", RejectDetail);
}
else
{
wprintf_s(L"\n WinBioCaptureSampleWithCallback failed. ");
wprintf_s(L" OperationStatus = 0x%x\n", OperationStatus);
}
goto e_Exit;
}
wprintf_s(L"\n Captured %d bytes.\n", SampleSize);
e_Exit:
if (Sample != NULL)
{
WinBioFree(Sample);
Sample = NULL;
}
}
Have you checked on google or with the SDK documentation what OperationStatus = 0x80004001 translates to? I am thinking you need to stop the windows service for the fingerprint before you embark on trying out the project you are developing on Visual Studio 2015.
I am having trouble with a video recording application that I am writing using Microsoft Media Foundation.
Specifically, the read/write function (which I put on a loop that lives on it's own thread) doesn't make it pass the call to ReadSample:
HRESULT WinCapture::rwFunction(void) {
HRESULT hr;
DWORD streamIndex, flags;
LONGLONG llTimeStamp;
IMFSample *pSample = NULL;
EnterCriticalSection(&m_critsec);
// Read another sample.
hr = m_pReader->ReadSample(
(DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM,
0,
&streamIndex, // actual
&flags,//NULL, // flags
&llTimeStamp,//NULL, // timestamp
&pSample // sample
);
if (FAILED(hr)) { goto done; }
hr = m_pWriter->WriteSample(0, pSample);
goto done;
done:
return hr;
SafeRelease(&pSample);
LeaveCriticalSection(&m_critsec);
}
The value of hr is an exception code: 0xc00d3704 so the code snippet skips the call to WriteSample.
It is a lot of steps, but I am fairly certain that I am setting up m_pReader (type IMFSource *) correctly.
HRESULT WinCapture::OpenMediaSource(IMFMediaSource *pSource)
{
HRESULT hr = S_OK;
IMFAttributes *pAttributes = NULL;
hr = MFCreateAttributes(&pAttributes, 2);
// use a callback
//if (SUCCEEDED(hr))
//{
// hr = pAttributes->SetUnknown(MF_SOURCE_READER_ASYNC_CALLBACK, this);
//}
// set the desired format type
DWORD dwFormatIndex = (DWORD)formatIdx;
IMFPresentationDescriptor *pPD = NULL;
IMFStreamDescriptor *pSD = NULL;
IMFMediaTypeHandler *pHandler = NULL;
IMFMediaType *pType = NULL;
// create the source reader
if (SUCCEEDED(hr))
{
hr = MFCreateSourceReaderFromMediaSource(
pSource,
pAttributes,
&m_pReader
);
}
// steps to set the selected format type
hr = pSource->CreatePresentationDescriptor(&pPD);
if (FAILED(hr))
{
goto done;
}
BOOL fSelected;
hr = pPD->GetStreamDescriptorByIndex(0, &fSelected, &pSD);
if (FAILED(hr))
{
goto done;
}
hr = pSD->GetMediaTypeHandler(&pHandler);
if (FAILED(hr))
{
goto done;
}
hr = pHandler->GetMediaTypeByIndex(dwFormatIndex, &pType);
if (FAILED(hr))
{
goto done;
}
hr = pHandler->SetCurrentMediaType(pType);
{
goto done;
}
hr = m_pReader->SetCurrentMediaType(
(DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM,
NULL,
pType
);
// set to maximum framerate?
hr = pHandler->GetCurrentMediaType(&pType);
if (FAILED(hr))
{
goto done;
}
// Get the maximum frame rate for the selected capture format.
// Note: To get the minimum frame rate, use the
// MF_MT_FRAME_RATE_RANGE_MIN attribute instead.
PROPVARIANT var;
if (SUCCEEDED(pType->GetItem(MF_MT_FRAME_RATE_RANGE_MAX, &var)))
{
hr = pType->SetItem(MF_MT_FRAME_RATE, var);
PropVariantClear(&var);
if (FAILED(hr))
{
goto done;
}
hr = pHandler->SetCurrentMediaType(pType);
{
goto done;
}
hr = m_pReader->SetCurrentMediaType(
(DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM,
NULL,
pType
);
}
goto done;
done:
SafeRelease(&pPD);
SafeRelease(&pSD);
SafeRelease(&pHandler);
SafeRelease(&pType);
SafeRelease(&pAttributes);
return hr;
}
This code is all copied from Microsoft documentation pages and the SDK sample code. The variable formatIdx is 0, I get it from enumerating the camera formats and choosing the first one.
UPDATE
I have rewritten this program so that it uses callbacks instead of a blocking read/write function and I have exactly the same issue.
Here I get the device and initiate the callback method:
HRESULT WinCapture::initCapture(const WCHAR *pwszFileName, IMFMediaSource *pSource) {
HRESULT hr = S_OK;
EncodingParameters params;
params.subtype = MFVideoFormat_WMV3; // TODO, paramterize this
params.bitrate = TARGET_BIT_RATE;
m_llBaseTime = 0;
IMFMediaType *pType = NULL;
DWORD sink_stream = 0;
EnterCriticalSection(&m_critsec);
hr = m_ppDevices[selectedDevice]->ActivateObject(IID_PPV_ARGS(&pSource));
//m_bIsCapturing = false; // this is set externally here
if (SUCCEEDED(hr))
hr = OpenMediaSource(pSource); // also creates the reader
if (SUCCEEDED(hr))
{
hr = m_pReader->GetCurrentMediaType(
(DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM,
&pType
);
}
// Create the sink writer
if (SUCCEEDED(hr))
{
hr = MFCreateSinkWriterFromURL(
pwszFileName,
NULL,
NULL,
&m_pWriter
);
}
if (SUCCEEDED(hr))
hr = ConfigureEncoder(params, pType, m_pWriter, &sink_stream);
// kick off the recording
if (SUCCEEDED(hr))
{
m_llBaseTime = 0;
m_bIsCapturing = TRUE;
hr = m_pReader->ReadSample(
(DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM,
0,
NULL,
NULL,
NULL,
NULL
);
}
SafeRelease(&pType);
SafeRelease(&pSource);
pType = NULL;
LeaveCriticalSection(&m_critsec);
return hr;
}
The OpenMediaSource method is here:
HRESULT WinCapture::OpenMediaSource(IMFMediaSource *pSource)
{
HRESULT hr = S_OK;
IMFAttributes *pAttributes = NULL;
hr = MFCreateAttributes(&pAttributes, 2);
// use a callback
if (SUCCEEDED(hr))
{
hr = pAttributes->SetUnknown(MF_SOURCE_READER_ASYNC_CALLBACK, this);
}
// set the desired format type
DWORD dwFormatIndex = (DWORD)formatIdx;
IMFPresentationDescriptor *pPD = NULL;
IMFStreamDescriptor *pSD = NULL;
IMFMediaTypeHandler *pHandler = NULL;
IMFMediaType *pType = NULL;
// create the source reader
if (SUCCEEDED(hr))
{
hr = MFCreateSourceReaderFromMediaSource(
pSource,
pAttributes,
&m_pReader
);
}
// steps to set the selected format type
if (SUCCEEDED(hr)) hr = pSource->CreatePresentationDescriptor(&pPD);
if (FAILED(hr))
{
goto done;
}
BOOL fSelected;
hr = pPD->GetStreamDescriptorByIndex(0, &fSelected, &pSD);
if (FAILED(hr))
{
goto done;
}
hr = pSD->GetMediaTypeHandler(&pHandler);
if (FAILED(hr))
{
goto done;
}
hr = pHandler->GetMediaTypeByIndex(dwFormatIndex, &pType);
if (FAILED(hr))
{
goto done;
}
hr = pHandler->SetCurrentMediaType(pType);
if (FAILED(hr))
{
goto done;
}
// get available framerates
hr = MFGetAttributeRatio(pType, MF_MT_FRAME_RATE, &frameRate, &denominator);
std::cout << "frameRate " << frameRate << " denominator " << denominator << std::endl;
hr = m_pReader->SetCurrentMediaType(
(DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM,
NULL,
pType
);
// set to maximum framerate?
hr = pHandler->GetCurrentMediaType(&pType);
if (FAILED(hr))
{
goto done;
}
goto done;
done:
SafeRelease(&pPD);
SafeRelease(&pSD);
SafeRelease(&pHandler);
SafeRelease(&pType);
SafeRelease(&pAttributes);
return hr;
}
Here, formatIdx is a field of this class that get sets by the user via the GUI. I leave it 0 in order to test. So, I don't think I am missing any steps to get the camera going, but maybe I am.
When I inspect what applications are using the webcam (using this method) after the call to ActivateObject, I see that my application is using the webcam as expected. But, when I enter the callback routine, I see there are two instances of my application using the webcam. This is the same using a blocking method.
I don't know if that is good or bad, but when I enter my callback method:
HRESULT WinCapture::OnReadSample(
HRESULT hrStatus,
DWORD /*dwStreamIndex*/,
DWORD /*dwStreamFlags*/,
LONGLONG llTimeStamp,
IMFSample *pSample // Can be NULL
)
{
EnterCriticalSection(&m_critsec);
if (!IsCapturing() || m_bIsCapturing == false)
{
LeaveCriticalSection(&m_critsec);
return S_OK;
}
HRESULT hr = S_OK;
if (FAILED(hrStatus))
{
hr = hrStatus;
goto done;
}
if (pSample)
{
if (m_bFirstSample)
{
m_llBaseTime = llTimeStamp;
m_bFirstSample = FALSE;
}
// rebase the time stamp
llTimeStamp -= m_llBaseTime;
hr = pSample->SetSampleTime(llTimeStamp);
if (FAILED(hr)) { goto done; }
hr = m_pWriter->WriteSample(0, pSample);
if (FAILED(hr)) { goto done; }
}
// Read another sample.
hr = m_pReader->ReadSample(
(DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM,
0,
NULL, // actual
NULL, // flags
NULL, // timestamp
NULL // sample
);
done:
if (FAILED(hr))
{
//NotifyError(hr);
}
LeaveCriticalSection(&m_critsec);
return hr;
}
hrStatus is the 0x00d3704 error I was getting before, and the callback goes straight to done thus killing the callbacks.
Finally, I should say that I am modeling (read, 'copying') my code from the example MFCaptureToFile in the Windows SDK Samples and that doesn't work either. Although, there I get this weird negative number for the failed HRESULT: -1072875772.
If you have got error [0xC00D3704] - it means that source does not initialized. Such error can be caused by mistake of initialization, busy camera by another application (process) or unsupport of the camera by UVC driver(old cameras support DirectShow driver with partly compatibleness with UVC. It is possible read some general info from old cameras via UVC as friendly name, symbolic link. However, old cameras support DirectShow models - PUSH, while camera pushes bytes into the pipeline, while Media Foundation PULL data - sends special signal and wait data).
For checking your code I would like advise to research articles about capturing video from web cam on site "CodeProject" - search "videoInput" name.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 9 years ago.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Improve this question
I'm currently working on a Fingerprint verification project and I've already configured all the drivers properly. I'm using Microsoft Fingerprint Reader and it works when i tested it with the software DigitalPersona during login. I currently have windows sdk 7.0A and I'm using Microsoft Visual Studio 2010.
I created an "empty project" for this code and I've linked additional library dependencies to the windows sdk and type the winbio.lib under the "input" for additional dependencies. i got this error.
error C2065: 'CaptureSampleCallback' : undeclared identifier
Here's the code, i followed exactly the microsoft's sample but it can't work =(
http://msdn.microsoft.com/en-us/library/windows/desktop/dd401603(v=vs.85).aspx
#include <Windows.h>
#include <Conio.h>
#include <Stdio.h>
#include <WinBio.h>
HRESULT CaptureSampleWithCallback(BOOL bCancel)
{
HRESULT hr = S_OK;
WINBIO_SESSION_HANDLE sessionHandle = NULL;
// Connect to the system pool.
hr = WinBioOpenSession(
WINBIO_TYPE_FINGERPRINT, // Service provider
WINBIO_POOL_SYSTEM, // Pool type
WINBIO_FLAG_RAW, // Raw access
NULL, // Array of biometric unit IDs
0, // Count of biometric unit IDs
WINBIO_DB_DEFAULT, // Default database
&sessionHandle // [out] Session handle
);
if (FAILED(hr))
{
wprintf_s(L"\n WinBioOpenSession failed. hr = 0x%x\n", hr);
goto e_Exit;
}
// Capture a biometric sample asynchronously.
wprintf_s(L"\n Calling WinBioCaptureSampleWithCallback ");
hr = WinBioCaptureSampleWithCallback(
sessionHandle, // Open session handle
WINBIO_NO_PURPOSE_AVAILABLE, // Intended use of the sample
WINBIO_DATA_FLAG_RAW, // Sample format
CaptureSampleCallback, // Callback function
NULL // Optional context
);
if (FAILED(hr))
{
wprintf_s(L"\n WinBioCaptureSampleWithCallback failed. ");
wprintf_s(L"hr = 0x%x\n", hr);
goto e_Exit;
}
wprintf_s(L"\n Swipe the sensor ...\n");
// Cancel the capture process if the bCancel flag is set.
if (bCancel)
{
wprintf_s(L"\n Starting CANCEL timer...");
Sleep( 7000 );
wprintf_s(L"\n Calling WinBioCancel\n");
hr = WinBioCancel( sessionHandle );
if (FAILED(hr))
{
wprintf_s(L"\n WinBioCancel failed. hr = 0x%x\n", hr);
goto e_Exit;
}
}
// Wait for the asynchronous capture process to complete
// or be canceled.
hr = WinBioWait( sessionHandle );
if (FAILED(hr))
{
wprintf_s(L"\n WinBioWait failed. hr = 0x%x\n", hr);
}
e_Exit:
if (sessionHandle != NULL)
{
WinBioCloseSession(sessionHandle);
sessionHandle = NULL;
}
wprintf_s(L"\n Press any key to exit...");
_getch();
return hr;
}
//------------------------------------------------------------------------
// The following function is the callback for WinBioCaptureSampleWithCallback.
// The function filters the response from the biometric subsystem and
// writes a result to the console window.
//
VOID CALLBACK CaptureSampleCallback(
__in_opt PVOID CaptureCallbackContext,
__in HRESULT OperationStatus,
__in WINBIO_UNIT_ID UnitId,
__in_bcount(SampleSize) PWINBIO_BIR Sample,
__in SIZE_T SampleSize,
__in WINBIO_REJECT_DETAIL RejectDetail
)
{
UNREFERENCED_PARAMETER(CaptureCallbackContext);
wprintf_s(L"\n CaptureSampleCallback executing");
wprintf_s(L"\n Swipe processed - Unit ID: %d", UnitId);
if (FAILED(OperationStatus))
{
if (OperationStatus == WINBIO_E_BAD_CAPTURE)
{
wprintf_s(L"\n Bad capture; reason: %d\n", RejectDetail);
}
else
{
wprintf_s(L"\n WinBioCaptureSampleWithCallback failed. ");
wprintf_s(L" OperationStatus = 0x%x\n", OperationStatus);
}
goto e_Exit;
}
wprintf_s(L"\n Captured %d bytes.\n", SampleSize);
e_Exit:
if (Sample != NULL)
{
WinBioFree(Sample);
Sample = NULL;
}
}
You have two solutions:
A. function prototype before calling CaptureSampleCallback
VOID CALLBACK CaptureSampleCallback(
__in_opt PVOID CaptureCallbackContext,
__in HRESULT OperationStatus,
__in WINBIO_UNIT_ID UnitId,
__in_bcount(SampleSize) PWINBIO_BIR Sample,
__in SIZE_T SampleSize,
__in WINBIO_REJECT_DETAIL RejectDetail
);
B. Move definition of function CaptureSampleCallback before CaptureSampleWithCallback
I keep getting "E_INVALIDARG" when calling RenderStream().
My program output is:
SUCCESS - Initialized COM library.
SUCCESS - Created the Filter Graph Manager.
SUCCESS - Created the Media Control and Media Event Interfaces.
SUCCESS - Enumerated devices.
--------------DEVICE INFORMATION--------------
Integrated Webcam
------------END DEVICE INFORMATION------------
SUCCESS - Bound to moniker.
Here is the code:
#include "stdafx.h"
#include <dshow.h> //direct show
#include <windows.h> //windows
#pragma comment(lib,"Strmiids.lib") //used for direct show
HRESULT InitCaptureGraphBuilder(
IGraphBuilder **ppGraph, // Receives the pointer.
ICaptureGraphBuilder2 **ppBuild // Receives the pointer.
)
{
if (!ppGraph || !ppBuild)
{
return E_POINTER;
}
IGraphBuilder *pGraph = NULL;
ICaptureGraphBuilder2 *pBuild = NULL;
// Create the Capture Graph Builder.
HRESULT hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void**)&pBuild );
if (SUCCEEDED(hr))
{
// Create the Filter Graph Manager.
hr = CoCreateInstance(CLSID_FilterGraph, 0, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void**)&pGraph);
if (SUCCEEDED(hr))
{
// Initialize the Capture Graph Builder.
pBuild->SetFiltergraph(pGraph);
// Return both interface pointers to the caller.
*ppBuild = pBuild;
*ppGraph = pGraph; // The caller must release both interfaces.
return S_OK;
}
else
{
pBuild->Release();
}
}
return hr; // Failed
}
HRESULT EnumerateDevices(REFGUID category, IEnumMoniker **ppEnum)
{
// Create the System Device Enumerator.
ICreateDevEnum *pDevEnum;
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDevEnum));
if (SUCCEEDED(hr))
{
// Create an enumerator for the category.
hr = pDevEnum->CreateClassEnumerator(category, ppEnum, 0);
if (hr == S_FALSE)
{
hr = VFW_E_NOT_FOUND; // The category is empty. Treat as an error.
}
pDevEnum->Release();
}
return hr;
}
void DisplayDeviceInformation(IEnumMoniker *pEnum, IMoniker** pMoniker)
{
while (pEnum->Next(1, pMoniker, NULL) == S_OK)
{
IPropertyBag *pPropBag;
HRESULT hr = (*pMoniker)->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
if (FAILED(hr))
{
(*pMoniker)->Release();
continue;
}
VARIANT var;
VariantInit(&var);
// Get description or friendly name.
hr = pPropBag->Read(L"Description", &var, 0);
if (FAILED(hr))
{
hr = pPropBag->Read(L"FriendlyName", &var, 0);
}
if (SUCCEEDED(hr))
{
printf("%S\n", var.bstrVal);
if(0 == wcscmp(var.bstrVal, L"Integrated Webcam"))
{
VariantClear(&var);
pPropBag->Release();
return;
}
VariantClear(&var);
}
hr = pPropBag->Write(L"FriendlyName", &var);
pPropBag->Release();
}
}
void main()
{
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
IGraphBuilder *pGraph = NULL;
ICaptureGraphBuilder2 *pBuild = NULL;
IMediaControl *pControl = NULL;
IMediaEvent *pEvent = NULL;
if (FAILED(hr))
{
printf("ERROR - Could not initialize COM library\n");
return;
}
printf("SUCCESS - Initialized COM library.\n");
hr = InitCaptureGraphBuilder(&pGraph, &pBuild);
if (FAILED(hr))
{
printf("ERROR - Could not create the Filter Graph Manager.\n");
return;
}
printf("SUCCESS - Created the Filter Graph Manager.\n");
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
if (FAILED(hr))
{
printf("ERROR - Could not create the Media Control or Media Event Interfaces.\n");
return;
}
printf("SUCCESS - Created the Media Control and Media Event Interfaces.\n");
IEnumMoniker *pEnum;
hr = EnumerateDevices(CLSID_VideoInputDeviceCategory, &pEnum);
if(FAILED(hr))
{
printf("ERROR - Failed to enumerate devices.\n");
return;
}
printf("SUCCESS - Enumerated devices.\n");
IMoniker* pMoniker = NULL;
printf("--------------DEVICE INFORMATION--------------\n");
DisplayDeviceInformation(pEnum, &pMoniker);
printf("------------END DEVICE INFORMATION------------\n");
IBaseFilter *pCap = NULL;
hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCap);
if(FAILED(hr))
{
printf("ERROR - Failed to bind to moniker.\n");
return;
}
printf("SUCCESS - Bound to moniker.\n");
hr = pBuild->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pCap, NULL, NULL);
if(FAILED(hr))
{
printf("ERROR - RenderStream() failed.\n");
return;
}
printf("SUCCESS - RenderStream() succeeded.\n");
hr = pControl->Run();
if(FAILED(hr))
{
printf("ERROR - Run() failed.\n");
return;
}
printf("SUCCESS - Running.\n");
long evCode;
hr = pEvent->WaitForCompletion(INFINITE, &evCode);
if(FAILED(hr))
{
printf("ERROR - WaitForCompletion() failed.\n");
return;
}
hr = pControl->Stop();
if(FAILED(hr))
{
printf("ERROR - Stop() failed.\n");
return;
}
printf("SUCCESS - Stopping.\n");
pControl->Release();
pEvent->Release();
pGraph->Release();
pMoniker->Release();
pEnum->Release();
CoUninitialize();
}
Before using RenderStream you need to IGraphBuilder::AddFilter your camera filter to the graph.