I am trying to use OleCreatePropertyFrame() to set the WebCam properties on the filter Capture pin (controls frame rate, etc). The amcap program released by Microsoft does this.
The amcap program builds a filter graph, and then uses:
hr = gcap.pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE,
&MEDIATYPE_Interleaved, gcap.pVCap,
IID_IAMVideoCompression, (void **)&gcap.pVC);
To find the interface for which to extract the property pages.
I want to get it work by directly finding the capture pin on the filter.
https://learn.microsoft.com/en-us/windows/win32/api/strmif/nn-strmif-iamstreamconfig
seems to imply this should work.
In the following code, the call to OleCreatePropertyFrame() segment faults.
I can't tell why ..
Is this approach just not going to work?
//==========================================================================
// first find the cam filter
// this parts works
// I can use pSrc to look at the filter property pages using OleCreatePropertyFrame()
//==========================================================================
IBaseFilter *pSrc = NULL;
HRESULT hr = S_OK;
IMoniker* pMoniker =NULL;
ICreateDevEnum *pDevEnum =NULL;
IEnumMoniker *pClassEnum = NULL;
hr = CoCreateInstance (CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,
IID_ICreateDevEnum, (void **) &pDevEnum);
my_assert(!FAILED(hr),"");
hr = pDevEnum->CreateClassEnumerator (CLSID_VideoInputDeviceCategory, &pClassEnum, 0);
my_assert(!FAILED(hr) && pClassEnum!=NULL,"");
hr = pClassEnum->Next (1, &pMoniker, NULL); // pick first device
my_assert(!FAILED(hr),"");
hr = pMoniker->BindToObject(0,0,IID_IBaseFilter, (void**)&pSrc);
my_assert(!FAILED(hr),"");
SAFE_RELEASE(pMoniker);
SAFE_RELEASE(pDevEnum);
SAFE_RELEASE(pClassEnum);
//=======================================================
// now find the interface on the capture pin
// no assertions trigger, I believe I find the capture pin correctly
// It seems like I find the capture pin property pages correctly as well
// However, it segfaults when I call OleCreatePropertyFrame()
//==================================================================
ISpecifyPropertyPages *pProp = NULL;
IUnknown *pFilterUnk =NULL;
IAMStreamConfig *pConfig = NULL;
IEnumPins *pEnum = NULL;
IPin *pPin = NULL;
hr = pSrc->EnumPins(&pEnum);
my_assert(!FAILED(hr),"");
while(pEnum->Next(1, &pPin, 0) == S_OK){
IKsPropertySet *pKs = NULL;
hr = pPin->QueryInterface(IID_PPV_ARGS(&pKs));
my_assert(!FAILED(hr),"");
DWORD cbReturned = 0;
GUID myPinCategory;
hr = pKs->Get(AMPROPSETID_Pin, AMPROPERTY_PIN_CATEGORY, NULL, 0,
&myPinCategory, sizeof(GUID), &cbReturned);
my_assert(!FAILED(hr),"");
SAFE_RELEASE(pKs);
if (myPinCategory!=PIN_CATEGORY_CAPTURE){
pPin->Release();
continue;
}
//IAMStreamConfig *pConfig = NULL;
hr = pPin->QueryInterface(IID_PPV_ARGS(&pConfig));
my_assert(!FAILED(hr),"could not find stream config interface");
hr = pConfig->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pProp);
my_assert(SUCCEEDED(hr),"");
pFilterUnk = (IUnknown *)pConfig;
pPin->Release();
break;
}
pEnum->Release();
if (pProp==NULL || pFilterUnk==NULL){
SAFE_RELEASE(pFilterUnk);
return("ERROR: can not find capture pin");
}
CAUUID caGUID;
hr = pProp->GetPages(&caGUID);
my_assert(SUCCEEDED(hr),"");
HWND ghApp = (HWND)pc->winId();
OleCreatePropertyFrame(
ghApp, // Parent window
0, 0, // location on the screen
filterName,
1, // Number of objects (just the filter)
&pFilterUnk, // Array of object pointers.
caGUID.cElems, // Number of property pages
caGUID.pElems, // Array of property page CLSIDs
0, // Locale identifier
0, NULL // Reserved
);
If order to use OleCreatePropertyFrame on webcam capture pins, it seems like the webcam filter must be in graph. This ends up being pretty easy to do:
hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
CLSCTX_INPROC_SERVER,IID_ICaptureGraphBuilder2, (void**)&pBuilder);
my_assert(pBuilder!=NULL && !FAILED(hr),"");
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,
IID_IGraphBuilder, (void **)&pFg);
my_assert(pFg!=NULL && !FAILED(hr),"");
hr = pBuilder->SetFiltergraph(pFg);
my_assert(!FAILED(hr),"");
hr = pFg->AddFilter(pSrc, L"my-cam");
my_assert(!FAILED(hr),"");
hr = pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE,
&MEDIATYPE_Video, pSrc,IID_IAMStreamConfig,
(void **)&pConfig);
my_assert(pConfig!=NULL && !FAILED(hr),"");
Related
Im using a Elgato Game Capture HD60 to live prewview a GoPro Hero 5 in my application. Now i want to save the stream as a JPG in my folder. But i cant find out how to.
To bind the pin
DsROTEntry rot; //Used for remotely connecting to graph
IFilterGraph2 graph;
ICaptureGraphBuilder2 captureGraph;
IBaseFilter elgatoFilter;
IBaseFilter smartTeeFilter;
IBaseFilter videoRendererFilter;
Size videoSize;
private IPin GetPin(PinDirection pinDir, IBaseFilter filter)
{
IEnumPins epins;
int hr = filter.EnumPins(out epins);
if (hr < 0)
return null;
IntPtr fetched = Marshal.AllocCoTaskMem(4);
IPin[] pins = new IPin[1];
epins.Reset();
while (epins.Next(1, pins, fetched) == 0)
{
PinInfo pinfo;
pins[0].QueryPinInfo(out pinfo);
bool found = (pinfo.dir == pinDir);
DsUtils.FreePinInfo(pinfo);
if (found)
return pins[0];
}
return null;
}
private IPin GetPin(PinDirection pinDir, string name, IBaseFilter filter)
{
IEnumPins epins;
int hr = filter.EnumPins(out epins);
if (hr < 0)
return null;
IntPtr fetched = Marshal.AllocCoTaskMem(4);
IPin[] pins = new IPin[1];
epins.Reset();
while (epins.Next(1, pins, fetched) == 0)
{
PinInfo pinfo;
pins[0].QueryPinInfo(out pinfo);
bool found = (pinfo.dir == pinDir && pinfo.name == name);
DsUtils.FreePinInfo(pinfo);
if (found)
return pins[0];
}
return null;
}
And to start the stream
private void button1_Click(object sender, EventArgs e)
{
//Set the video size to use for capture and recording
videoSize = new Size(1280, 720);
//Initialize filter graph and capture graph
graph = (IFilterGraph2)new FilterGraph();
captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();
captureGraph.SetFiltergraph(graph);
rot = new DsROTEntry(graph);
//Create filter for Elgato
Guid elgatoGuid = new Guid("39F50F4C-99E1-464A-B6F9-D605B4FB5918");
Type comType = Type.GetTypeFromCLSID(elgatoGuid);
elgatoFilter = (IBaseFilter)Activator.CreateInstance(comType);
graph.AddFilter(elgatoFilter, "Elgato Video Capture Filter");
//Create smart tee filter, add to graph, connect Elgato's video out to smart tee in
smartTeeFilter = (IBaseFilter)new SmartTee();
graph.AddFilter(smartTeeFilter, "Smart Tee");
IPin outPin = GetPin(PinDirection.Output, "Video", elgatoFilter);
IPin inPin = GetPin(PinDirection.Input, smartTeeFilter);
graph.Connect(outPin, inPin);
//Create video renderer filter, add it to graph, connect smartTee Preview pin to video renderer's input pin
videoRendererFilter = (IBaseFilter)new VideoRenderer();
graph.AddFilter(videoRendererFilter, "Video Renderer");
outPin = GetPin(PinDirection.Output, "Preview", smartTeeFilter);
inPin = GetPin(PinDirection.Input, videoRendererFilter);
graph.Connect(outPin, inPin);
//Render stream from video renderer
captureGraph.RenderStream(PinCategory.Preview, MediaType.Video, videoRendererFilter, null, null);
//Set the video preview to be the videoFeed panel
IVideoWindow vw = (IVideoWindow)graph;
vw.put_Owner(pictureBox1.Handle);
vw.put_MessageDrain(this.Handle);
vw.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipSiblings | WindowStyle.ClipChildren);
vw.SetWindowPosition(0, 0, 1280, 720);
//Start the preview
IMediaControl mediaControl = graph as IMediaControl;
mediaControl.Run();
}
Can you run the filter graph successfully, and which step did you get error info?
You can get sample code \Samples\Capture\PlayCap to see how to build video capture filter graph.
If you want to get a video snapshot, you can get the sample code at \Samples\Capture\DxSnap.
You can modify the video source index and video snapshot size to get what you want.
const int VIDEODEVICE = 0; // zero based index of video capture device to use
const int VIDEOWIDTH = 2048; // Depends on video device caps
const int VIDEOHEIGHT = 1536; // Depends on video device caps
const int VIDEOBITSPERPIXEL = 24; // BitsPerPixel values determined by device
I'm using SlimDX to create a texture consisting of 13046 different DataRectangles. Here's my code. It's breaking on the Texture2D constructor with "E_INVALIDARG: An invalid parameter was passed to the returning function (-2147024809)." inParms is just a struct containing handle to a Panel.
public Renderer(Parameters inParms, ref DataRectangle[] inShapes)
{
Texture2DDescription description = new Texture2DDescription()
{
Width = 500,
Height = 500,
MipLevels = 1,
ArraySize = inShapes.Length,
Format = Format.R32G32B32_Float,
SampleDescription = new SampleDescription(1, 0),
Usage = ResourceUsage.Default,
BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource,
CpuAccessFlags = CpuAccessFlags.None,
OptionFlags = ResourceOptionFlags.None
};
SwapChainDescription chainDescription = new SwapChainDescription()
{
BufferCount = 1,
IsWindowed = true,
Usage = Usage.RenderTargetOutput,
ModeDescription = new ModeDescription(0, 0, new Rational(60, 1), Format.R8G8B8A8_UNorm),
SampleDescription = new SampleDescription(1, 0),
Flags = SwapChainFlags.None,
OutputHandle = inParms.Handle,
SwapEffect = SwapEffect.Discard
};
Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.None, chainDescription, out mDevice, out mSwapChain);
Texture2D texture = new Texture2D(Device, description, inShapes);
}
R32G32B32_Float (and pretty much every 3 channels format) is not supported for render target usage.
So you have different options:
Use R32G32B32A32_Float instead (means that you will need to change your Data Rectangles as you add an extra channel).
Remove the BindFlags.RenderTarget flag. If you only want to read this resource, this flag is not needed. As you provide initial data, you can also change Usage to ResourceUsage.Immutable as well.
Additionally, to check if a Format is supported for a specific resource usage, you can use the following snippet:
public bool IsFormatSupported(Device dev, FormatSupport usage, Format format)
{
FormatSupport support = dev.CheckFormatSupport(format);
return (support | usage) == support;
}
It seems Win 8 has a new user group "ALL APPLICATION PACKAGES". This group seems to have Read permissions on all folders by default. However my requirement is to set some specific ACLs on a folder created by me. This group has no permissions on my folder currently and I wrote some code to add Read permissions for "ALL APPLICATION PACKAGES". I'm using VS 2010 and below is the trimmed down code snippet.
The SID for "ALL APPLICATION PACKAGES" as listed at http://msdn.microsoft.com/en-us/library/cc980032.aspx is ALL_APP_PACKAGES (S-1-15-2-1).
But no matter how or what value I pass as trustee Name the code below does not work. For example in the code below SetNamedSecurityInfo() fails with ERROR_INVALID_ACL. However if I use "Administrators" or "Everyone" account then it works.
Exact permission I need to assign are “Read & Execute”, “List Folder Contents”, and “Read”
#include "stdafx.h"
#include "windows.h"
#include "sddl.h"
#include "Aclapi.h"
int _tmain(int argc, _TCHAR* argv[])
{
TCHAR pszObjName[MAX_PATH] = L"C:\\Program Files\\Common Files\\Test\\";
PACL pOldDACL = NULL, pNewDACL = NULL;
PSECURITY_DESCRIPTOR pSD = NULL;
EXPLICIT_ACCESS ea;
SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION;
// Get a pointer to the existing DACL (Conditionaly).
DWORD dwRes = GetNamedSecurityInfo(pszObjName, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pOldDACL, NULL, &pSD);
// Initialize an EXPLICIT_ACCESS structure for the new ACE.
ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
ea.grfAccessPermissions = STANDARD_RIGHTS_READ;
ea.grfAccessMode = SET_ACCESS;
ea.grfInheritance= SUB_CONTAINERS_AND_OBJECTS_INHERIT;
ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
// ea.Trustee.TrusteeType = TRUSTEE_IS_GROUP;
// Should I be using SID (S-1-15-2-1) (SetEntriesInAcl() fails) or "ALL_APP_PACKAGES" (SetEntriesInAcl() passes but SetNamedSecurityInfo() fails)
//If I use "Administrators" or "Everyone" as Trustee Name then it works fine but not with "ALL APPLICATION PACKAGES"
ea.Trustee.ptstrName = _T(" ALL_APP_PACKAGES");
// Create a new ACL that merges the new ACE into the existing DACL.
dwRes = SetEntriesInAcl(1, &ea, pOldDACL, &pNewDACL);
if(ERROR_SUCCESS != dwRes)
goto Cleanup;
// Attach the new ACL as the object's DACL.
dwRes = SetNamedSecurityInfo(pszObjName, SE_FILE_OBJECT, si, NULL, NULL, pNewDACL, NULL);
if(ERROR_SUCCESS != dwRes)
goto Cleanup;
Cleanup:
if(pSD != NULL)
LocalFree((HLOCAL) pSD);
if(pNewDACL != NULL)
LocalFree((HLOCAL) pNewDACL);
return dwRes;
}
Try to set the Trustee structure this way. It works for me.
ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
ea.Trustee.ptstrName = L"ALL APPLICATION PACKAGES";
Exact permission I need to assign are “Read & Execute”, “List Folder
Contents”, and “Read”
So you need
ea.grfAccessPermissions = GENERIC_READ | GENERIC_EXECUTE;
instead of
ea.grfAccessPermissions = STANDARD_RIGHTS_READ;
Also this is probably won't work if the group name is localized:
ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
ea.Trustee.ptstrName = L"ALL APPLICATION PACKAGES";
This piece will:
// Allocate enough memory for the largest possible SID.
PSID TheSID = NULL;
DWORD SidSize = SECURITY_MAX_SID_SIZE;
if (!(TheSID = LocalAlloc(LMEM_FIXED, SidSize)))
goto Cleanup;
// Create a SID for the Everyone group on the local computer.
if (!CreateWellKnownSid(WinBuiltinAnyPackageSid, NULL, TheSID, &SidSize))
goto Cleanup;
// Initialize an EXPLICIT_ACCESS structure for the new ACE.
ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
ea.grfAccessPermissions = GENERIC_READ | GENERIC_EXECUTE;
ea.grfAccessMode = SET_ACCESS;
ea.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
ea.Trustee.ptstrName = (LPWSTR)TheSID;
What does ERROR_BAD_INHERITANCE_ACL returned from SetNamedSecurityInfo imply? In this case I'm adding a user to a directory's ACL. I've looked at the directory in question and its rights seem reasonable before the call. But the calls fails.
Any thoughts?
Here is the code snippet doing the work (and as I paste it here, I'm wondering about the NO_MULTIPLE_TRUSTEE value):
pAAP is a pointer to a structure with the following members:
CString objName; // name of object
SE_OBJECT_TYPE ObjectType; // type of object
CString trustee; // trustee for new ACE (explicit user name)
CString targetComputer;
bool bNeedWrite;
DWORD dwRes = 0;
PACL pOldDACL = NULL, pNewDACL = NULL;
PSECURITY_DESCRIPTOR pSD = NULL;
EXPLICIT_ACCESS ea = {0};
CSID trusteeSID;
bool bGotSID = false;
if(0 == wcsncmp(pAAP->trustee, L"SID:", 4)) //4 = len of SID: //GLOK
bGotSID = CSID::FromString((LPWSTR)((LPCWSTR)pAAP->trustee + 4), trusteeSID);
else
bGotSID = CSID::FromAccount(pAAP->targetComputer, pAAP->trustee, trusteeSID);
if(false == bGotSID)
{
Log(logDEBUG, L"CSID::FromAccount failed for [%s] on [%s]. GLE=%s", pAAP->trustee, pAAP->targetComputer, GetSystemErrorMessage(GetLastError()));
_ASSERT(0);
goto Cleanup;
}
// Get a pointer to the existing DACL.
dwRes = GetNamedSecurityInfo(pAAP->objName.LockBuffer(), pAAP->ObjectType, DACL_SECURITY_INFORMATION,
NULL, NULL, &pOldDACL, NULL, &pSD);
pAAP->objName.UnlockBuffer();
if (ERROR_SUCCESS != dwRes)
{
Log(logDEBUG, L"GetNamedSecurityInfo failed on [%s] for [%s] on [%s]. GLE=%s", pAAP->objName, pAAP->trustee, pAAP->targetComputer, GetSystemErrorMessage(dwRes));
//_ASSERT(ERROR_FILE_NOT_FOUND == dwRes);
goto Cleanup;
}
// Initialize an EXPLICIT_ACCESS structure for the new ACE.
ea.grfAccessPermissions = pAAP->bNeedWrite ? GENERIC_ALL : GENERIC_READ;
ea.grfAccessMode = GRANT_ACCESS;
ea.grfInheritance= CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea.Trustee.TrusteeType = TRUSTEE_IS_USER;
ea.Trustee.ptstrName = (LPWSTR)(PSID)trusteeSID;
ea.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
// Create a new ACL that merges the new ACE into the existing DACL.
dwRes = SetEntriesInAcl(1, &ea, pOldDACL, &pNewDACL);
if (ERROR_SUCCESS != dwRes)
{
Log(logDEBUG, L"SetEntriesInAcl failed on [%s] for [%s] on [%s]. GLE=%s", pAAP->objName, pAAP->trustee, pAAP->targetComputer, GetSystemErrorMessage(dwRes));
//_ASSERT(0);
goto Cleanup;
}
// Attach the new ACL as the object's DACL.
dwRes = SetNamedSecurityInfo(pAAP->objName.LockBuffer(), pAAP->ObjectType, DACL_SECURITY_INFORMATION,
NULL, NULL, pNewDACL, NULL);
if (ERROR_SUCCESS != dwRes)
{
Log(logDEBUG, L"SetNamedSecurityInfo failed on [%s] for [%s] on [%s]. GLE=%s", pAAP->objName, pAAP->trustee, pAAP->targetComputer, GetSystemErrorMessage(dwRes));
//_ASSERT(dwRes == ERROR_BAD_INHERITANCE_ACL);
goto Cleanup;
}
Cleanup:
if(pSD != NULL)
LocalFree((HLOCAL) pSD);
if(pNewDACL != NULL)
LocalFree((HLOCAL) pNewDACL);
A code sample would definitely help. It's easy to get the logic to build and set the ACL subtly wrong.
I don't have the code in front of me, but the basic logic is:
acquire the process token with a sufficient access mask
GetNamedSecurityInfo
allocate a new ACL big enough for the new ACE, copy from the old to the new, and call AddAccessAllowedAceEx to add the user's SID
SetNamedSecurityInfo
I am refering the following document section "Windows Media API for Capturing the Screen" to capture screen and the original code works ok. When I am adding additional feature (I just added several lines to make it record from default audio device), it fails at thew following line (I debugged and looks like it fails at COM layer?), any hints? I posted both the original source codes and my modified source codes.
"if(FAILED(hr=pSrcGrp->put_Profile(variant_t(pProfile))))"
http://www.geocities.com/krishnapg/screencap.html
Original Source Code:
http://www.geocities.com/krishnapg/WMEncScrnCap.zip
My modified source code (I only modified function InitEncoder)
HRESULT InitEncoder(LPCTSTR szOutputFileName)
{
HRESULT hr = E_FAIL;
CComVariant varValue;
IWMEncSourceGroupCollection* pSrcGrpCollection=NULL;
IWMEncSourceGroup* pSrcGrp=NULL;
IWMEncSource* pSrc=NULL;
IWMEncSource* paSrc=NULL;
IPropertyBag* pPropertyBag=NULL;
IWMEncVideoSource2* pSrcVid=NULL;
IWMEncAudioSource* pSrcAud=NULL;
IWMEncFile* pOutFile=NULL;
IWMEncProfile* pProfile=NULL;
if(FAILED(CoCreateInstance(CLSID_WMEncoder,NULL,CLSCTX_INPROC_SERVER,IID_IWMEncoder2,(void**)&g_pEncoder)))
{
ErrorMessage("Unable to Create Encoder Object");
return E_FAIL;
}
if(FAILED(g_pEncoder->get_SourceGroupCollection(&pSrcGrpCollection))) //Retrieve the Source Group Collection - One Application can Have many Source Groups - We need to add as many as we want
{
ErrorMessage("Unable to Get Source Group Collection");
return E_FAIL;
}
do
{
if(FAILED(hr=pSrcGrpCollection->Add(CComBSTR("SourceGroup1"),&pSrcGrp)))//Add a Source Group to the Collection - Each Source can have one video one audio source input
{
ErrorMessage("Unable to Add A Source Group to the Collection");
break;
}
if(FAILED(hr=pSrcGrp->AddSource(WMENC_VIDEO,&pSrc))) //Add a Video Source to the Group
{
ErrorMessage("Unable to Add A Source to the Source Group");
break;
}
if(FAILED(hr=pSrcGrp->AddSource(WMENC_AUDIO,&paSrc))) //Add an Audio Source to the Group
{
ErrorMessage("Unable to Add A Source to the Source Group");
break;
}
if(FAILED(hr=pSrc->QueryInterface(IID_IWMEncVideoSource2,(void**)&pSrcVid)))
{
ErrorMessage("Unable to Query interface for Video Source");
break;
}
if(FAILED(hr=paSrc->QueryInterface(IID_IWMEncAudioSource,(void**)&pSrcAud)))
{
ErrorMessage("Unable to Query interface for Audio Source");
break;
}
if(FAILED(hr=pSrcVid->SetInput(CComBSTR("ScreenCap://ScreenCapture1"))))//The Video Input Source Device - Should be "ScreenCap" Device
{
ErrorMessage("Unable to Set Video Input Source");
break;
}
if(FAILED(hr=pSrcAud->SetInput(CComBSTR("Device://Default_Audio_Device"))))//The Video Input Source Device - Should be "Default_Audio_Device" Device
{
ErrorMessage("Unable to Set Audio Input Source");
break;
}
if(FAILED(hr=pSrcVid->QueryInterface(IID_IPropertyBag,(void**)&pPropertyBag)))
{
ErrorMessage("Unable to Query Interface for Propery bag");
break;
}
varValue = CAPTURE_FULLSCREEN;
if(FAILED(hr=pPropertyBag->Write(WMSCRNCAP_ENTIRESCREEN,&varValue))) //Set Full Screen Property true/false
{
ErrorMessage("Unable to Set Capture Screen Property");
break;
}
//int nLeft, nRight, nTop, nBottom; //Set Capture Area - when not in full screen mode
// // Initialize the capture area. The size must be even.
// varValue = false;
// if ( SUCCEEDED( hr ) )
// {
// hr = pPropertyBag->Write( WMSCRNCAP_ENTIRESCREEN, &varValue );
// }
// varValue = nLeft;
// if ( SUCCEEDED( hr ) )
// {
// hr = pPropertyBag->Write( WMSCRNCAP_WINDOWLEFT, &varValue );
// }
// varValue = nRight;
// if ( SUCCEEDED( hr ) )
// {
// hr = pPropertyBag->Write( WMSCRNCAP_WINDOWRIGHT, &varValue );
// }
// varValue = nTop;
// if ( SUCCEEDED( hr ) )
// {
// hr = pPropertyBag->Write( WMSCRNCAP_WINDOWTOP, &varValue );
// }
// varValue = nBottom;
// if ( SUCCEEDED( hr ) )
// {
// hr = pPropertyBag->Write( WMSCRNCAP_WINDOWBOTTOM, &varValue );
// }
// varValue = true;
// if ( SUCCEEDED( hr ) )
// {
// hr = pPropertyBag->Write( WMSCRNCAP_FLASHRECT, &varValue );
// }
if(FAILED(hr=SetupScreenCaptureProfile())) //Setup the Custom Profile
{
break;
}
if(FAILED(hr=g_pProfile->QueryInterface(IID_IWMEncProfile,(void**)&pProfile)))
{
ErrorMessage("Unable to Query Interface For Profile");
break;
}
if(FAILED(hr=pSrcGrp->put_Profile(variant_t(pProfile)))) //Select the Custom Profile into the Encoder
{
ErrorMessage("Unable to Set Profile For Source Group");
break;
}
if(FAILED(hr=g_pEncoder->get_File(&pOutFile)))
{
ErrorMessage("Unable to Get Encoder Output File Object");
break;
}
if(FAILED(hr=pOutFile->put_LocalFileName(CComBSTR(szOutputFileName)))) //Set the Target Output Filename
{
ErrorMessage("Unable to Set Output File Name");
break;
}
if(FAILED(hr=g_pEncoder->PrepareToEncode(VARIANT_TRUE))) //Using Prepare optimizes startig latency
{
ErrorMessage("Unable to Prepare for Encoding");
break;
}
}while(false);
if(pProfile)
{
pProfile->Release();
pProfile=NULL;
}
if(pOutFile)
{
pOutFile->Release();
pOutFile = NULL;
}
if(pPropertyBag)
{
pPropertyBag->Release();
pPropertyBag = NULL;
}
if(pSrcVid)
{
pSrcVid->Release();
pSrcVid = NULL;
}
if(pSrc)
{
pSrc->Release();
pSrc = NULL;
}
if(pSrcGrp)
{
pSrcGrp->Release();
pSrcGrp = NULL;
}
if(pSrcGrpCollection)
{
pSrcGrpCollection->Release();
pSrcGrpCollection = NULL;
}
return hr;
}
You may need to reset the audio:
Open Control Panel -> open Sound
In Playback, you'll see your speaker as default playback.
Right-click on it -> go to Properties -> go to the Advanced tab-> click on Restore Default
There is probably nothing wrong with your code. Windows Vista is notorious for not being able to programatically set the output / input.