void InitResolution(ICaptureGraphBuilder2 capGraph, IBaseFilter capFilter, int targetWidth, int targetHeight)
{
object o;
capGraph.FindInterface(PinCategory.Capture, MediaType.Video, capFilter, typeof(IAMStreamConfig).GUID, out o);
AMMediaType media = null;
IAMStreamConfig videoStreamConfig = o as IAMStreamConfig;
IntPtr ptr;
int iC = 0, iS = 0;
videoStreamConfig.GetNumberOfCapabilities(out iC, out iS);
ptr = Marshal.AllocCoTaskMem(iS);
int bestDWidth = 999999;
int bestDHeight = 999999;
int streamID = 0;
for (int i = 0; i < iC; i++)
{
videoStreamConfig.GetStreamCaps(i, out media, ptr);
VideoInfoHeader v;
v = new VideoInfoHeader();
Marshal.PtrToStructure(media.formatPtr, v);
int dW = Math.Abs(targetWidth - v.BmiHeader.Width);
int dH = Math.Abs(targetHeight - v.BmiHeader.Height);
if (dW < bestDWidth && dH < bestDHeight)
{
streamID = i;
bestDWidth = dW;
bestDHeight = dH;
}
}
videoStreamConfig.GetStreamCaps(streamID, out media, ptr);
int hr = videoStreamConfig.SetFormat(media);
Marshal.FreeCoTaskMem(ptr);
DsError.ThrowExceptionForHR(hr);
DsUtils.FreeAMMediaType(media);
media = null;
}
// Set the Framerate, and video size
private void SetConfigParms(ICaptureGraphBuilder2 capGraph, IBaseFilter capFilter, int iFrameRate, int iWidth, int iHeight)
{
int hr;
object o;
AMMediaType media;
// Find the stream config interface
hr = capGraph.FindInterface(
PinCategory.Capture, MediaType.Video, capFilter, typeof(IAMStreamConfig).GUID, out o );
IAMStreamConfig videoStreamConfig = o as IAMStreamConfig;
if (videoStreamConfig == null)
{
throw new Exception("Failed to get IAMStreamConfig");
}
// Get the existing format block
hr = videoStreamConfig.GetFormat( out media);
DsError.ThrowExceptionForHR( hr );
// copy out the videoinfoheader
VideoInfoHeader v = new VideoInfoHeader();
Marshal.PtrToStructure( media.formatPtr, v );
// if overriding the framerate, set the frame rate
if (iFrameRate > 0)
{
v.AvgTimePerFrame = 10000000 / iFrameRate;
}
// if overriding the width, set the width
if (iWidth > 0)
{
v.BmiHeader.Width = iWidth;
}
// if overriding the Height, set the Height
if (iHeight > 0)
{
v.BmiHeader.Height = iHeight;
}
// Copy the media structure back
Marshal.StructureToPtr( v, media.formatPtr, false );
// Set the new format
hr = videoStreamConfig.SetFormat( media );
DsError.ThrowExceptionForHR( hr );
DsUtils.FreeAMMediaType(media);
media = null;
}
/// <summary>
/// Retrieve a list of crossbar filters in the graph.
/// Most hardware devices should have a maximum of 2 crossbars,
/// one for video and another for audio.
/// </summary>
protected ArrayList findCrossbars(ICaptureGraphBuilder2 graphBuilder, IBaseFilter deviceFilter)
{
ArrayList crossbars = new ArrayList();
Guid category = FindDirection.UpstreamOnly;
Guid type = new Guid();
Guid riid = typeof(IAMCrossbar).GUID;
int hr;
object comObj = null;
object comObjNext = null;
// Find the first interface, look upstream from the selected device
hr = graphBuilder.FindInterface( ref category, ref type, deviceFilter, ref riid, out comObj );
while ( (hr == 0) && (comObj != null) )
{
// If found, add to the list
if ( comObj is IAMCrossbar )
{
crossbars.Add( comObj as IAMCrossbar );
// Find the second interface, look upstream from the next found crossbar
hr = graphBuilder.FindInterface( ref category, ref type, comObj as IBaseFilter, ref riid, out comObjNext );
comObj = comObjNext;
}
else
comObj = null;
}
return( crossbars );
}
// Set the Framerate, and video size
private void SetConfigParms(ICaptureGraphBuilder2 capGraph, IBaseFilter capFilter, int iSampleRate, int iChannels)
{
int hr;
object o;
AMMediaType media;
// Find the stream config interface
hr = capGraph.FindInterface(
PinCategory.Capture, MediaType.Audio, capFilter, typeof(IAMStreamConfig).GUID, out o);
IAMStreamConfig audioStreamConfig = o as IAMStreamConfig;
if (audioStreamConfig == null) {
throw new Exception("Failed to get IAMStreamConfig");
}
// Get the existing format block
hr = audioStreamConfig.GetFormat(out media);
DsError.ThrowExceptionForHR(hr);
// copy out the videoinfoheader
WaveFormatEx i = new WaveFormatEx();
Marshal.PtrToStructure(media.formatPtr, i);
i.wFormatTag = 0x0001; // WAVE_FORMAT_PCM
i.wBitsPerSample = 16;
i.nSamplesPerSec = 44100;
i.nChannels = m_Channels;
i.nBlockAlign = 2;
i.nAvgBytesPerSec = (i.nSamplesPerSec * i.nBlockAlign);
i.cbSize = 0;
// if overriding the framerate, set the frame rate
if (iSampleRate > 0) {
i.nSamplesPerSec = iSampleRate;
}
// if overriding the width, set the width
if (iChannels > 0) {
i.nChannels = (short)iChannels;
}
// Copy the media structure back
Marshal.StructureToPtr(i, media.formatPtr, false);
// Set the new format
hr = audioStreamConfig.SetFormat(media);
DsError.ThrowExceptionForHR(hr);
DsUtils.FreeAMMediaType(media);
media = null;
}
/// <summary>
/// Sets the capture parameters for the video capture device
/// </summary>
private bool SetVideoCaptureParameters(ICaptureGraphBuilder2 capGraph, IBaseFilter captureFilter, Guid mediaSubType)
{
/* The stream config interface */
object streamConfig;
/* Get the stream's configuration interface */
int hr = capGraph.FindInterface(PinCategory.Capture,
MediaType.Video,
captureFilter,
typeof(IAMStreamConfig).GUID,
out streamConfig);
DsError.ThrowExceptionForHR(hr);
var videoStreamConfig = streamConfig as IAMStreamConfig;
/* If QueryInterface fails... */
if (videoStreamConfig == null)
{
throw new Exception("Failed to get IAMStreamConfig");
}
/* The media type of the video */
AMMediaType media;
/* Get the AMMediaType for the video out pin */
hr = videoStreamConfig.GetFormat(out media);
DsError.ThrowExceptionForHR(hr);
/* Make the VIDEOINFOHEADER 'readable' */
var videoInfo = new VideoInfoHeader();
Marshal.PtrToStructure(media.formatPtr, videoInfo);
/* Setup the VIDEOINFOHEADER with the parameters we want */
videoInfo.AvgTimePerFrame = DSHOW_ONE_SECOND_UNIT / FPS;
videoInfo.BmiHeader.Width = DesiredWidth;
videoInfo.BmiHeader.Height = DesiredHeight;
if (mediaSubType != Guid.Empty)
{
int fourCC = 0;
byte[] b = mediaSubType.ToByteArray();
fourCC = b[0];
fourCC |= b[1] << 8;
fourCC |= b[2] << 16;
fourCC |= b[3] << 24;
videoInfo.BmiHeader.Compression = fourCC;
media.subType = mediaSubType;
}
/* Copy the data back to unmanaged memory */
Marshal.StructureToPtr(videoInfo, media.formatPtr, false);
/* Set the format */
hr = videoStreamConfig.SetFormat(media);
/* We don't want any memory leaks, do we? */
DsUtils.FreeAMMediaType(media);
if (hr < 0)
return false;
return true;
}
protected ArrayList findAudioSources(ICaptureGraphBuilder2 graphBuilder, IBaseFilter deviceFilter)
{
ArrayList sources = new ArrayList();
IAMAudioInputMixer audioInputMixer = deviceFilter as IAMAudioInputMixer;
if ( audioInputMixer != null )
{
// Get a pin enumerator off the filter
IEnumPins pinEnum;
int hr = deviceFilter.EnumPins( out pinEnum );
pinEnum.Reset();
if( (hr == 0) && (pinEnum != null) )
{
// Loop through each pin
IPin[] pins = new IPin[1];
int f;
do
{
// Get the next pin
hr = pinEnum.Next( 1, pins, out f );
if( (hr == 0) && (pins[0] != null) )
{
// Is this an input pin?
PinDirection dir = PinDirection.Output;
hr = pins[0].QueryDirection( out dir );
if( (hr == 0) && (dir == (PinDirection.Input)) )
{
// Add the input pin to the sources list
AudioSource source = new AudioSource( pins[0] );
sources.Add( source );
}
pins[0] = null;
}
}
while( hr == 0 );
Marshal.ReleaseComObject( pinEnum ); pinEnum = null;
}
}
// If there is only one source, don't return it
// because there is nothing for the user to choose.
// (Hopefully that single source is already enabled).
if ( sources.Count == 1 )
sources.Clear();
return( sources );
}
/// <summary>
/// Populate the internal InnerList with sources/physical connectors
/// found on the crossbars. Each instance of this class is limited
/// to video only or audio only sources ( specified by the isVideoDevice
/// parameter on the constructor) so we check each source before adding
/// it to the list.
/// </summary>
protected ArrayList findCrossbarSources(ICaptureGraphBuilder2 graphBuilder, IAMCrossbar crossbar, bool isVideoDevice)
{
ArrayList sources = new ArrayList();
int hr;
int numOutPins;
int numInPins;
hr = crossbar.get_PinCounts( out numOutPins, out numInPins );
if ( hr < 0 )
Marshal.ThrowExceptionForHR( hr );
// We loop through every combination of output and input pin
// to see which combinations match.
// Loop through output pins
for ( int cOut = 0; cOut < numOutPins; cOut++ )
{
// Loop through input pins
for ( int cIn = 0; cIn < numInPins; cIn++ )
{
// Can this combination be routed?
hr = crossbar.CanRoute( cOut, cIn );
if ( hr == 0 )
{
// Yes, this can be routed
int relatedPin;
PhysicalConnectorType connectorType;
hr = crossbar.get_CrossbarPinInfo( true, cIn, out relatedPin, out connectorType );
if ( hr < 0 )
Marshal.ThrowExceptionForHR( hr );
// Is this the correct type?, If so add to the InnerList
CrossbarSource source = new CrossbarSource( crossbar, cOut, cIn, connectorType );
if ( connectorType < PhysicalConnectorType.Audio_Tuner )
if ( isVideoDevice )
sources.Add( source );
else
if ( !isVideoDevice )
sources.Add( source );
}
}
}
// Some silly drivers (*cough* Nvidia *cough*) add crossbars
// with no real choices. Every input can only be routed to
// one output. Loop through every Source and see if there
// at least one other Source with the same output pin.
int refIndex = 0;
while ( refIndex < sources.Count )
{
bool found = false;
CrossbarSource refSource = (CrossbarSource) sources[refIndex];
for ( int c = 0; c < sources.Count; c++ )
{
CrossbarSource s = (CrossbarSource) sources[c];
if ( ( refSource.OutputPin == s.OutputPin ) && ( refIndex != c ) )
{
found = true;
break;
}
}
if ( found )
refIndex++;
else
sources.RemoveAt( refIndex );
}
return( sources );
}
请发表评论