I am new with DirectShow.Net. I am implementing an C# application to record
video and audio from a webcam to a file (the webcam has a micro). Recording
video is fine but when I add a filter to record audio then it occurs exception
"One or more arguments are invalid". I do not know how to put valid arguments
since I put arguments similarly to rednering the video. Following is my code
and exception occurs at the second last line. Does anyone know how to put
correct arguments?
//Create the Graph
graphBuilder = (IGraphBuilder)new FilterGraph();
//Create the media control for controlling the graph
mediaControlList = (IMediaControl)this.graphBuilder;
// Attach the filter graph to the capture graph
int hr = captureGraphBuilder.SetFiltergraph(this.graphBuilder);
DsError.ThrowExceptionForHR(hr);
//Add the Video input device to the graph
IBaseFilter sourceFilter = (IBaseFilter)devices;
hr = graphBuilder.AddFilter(sourceFilter, "The webcam " + (indexOfCamera +
1).ToString());
DsError.ThrowExceptionForHR(hr);
//Add the Video compressor filter to the graph
IBaseFilter videoCompressor = getVideoCompressor();
if (videoCompressor != null)
{
hr = graphBuilder.AddFilter(videoCompressor, "video compressor filter");
DsError.ThrowExceptionForHR(hr);
}
//Add the Video compressor filter to the graph
IBaseFilter audioCompressor = getAudioCompressor();
if (audioCompressor != null)
{
hr = graphBuilder.AddFilter(audioCompressor, "audio compressor filter");
DsError.ThrowExceptionForHR(hr);
}
//Create the file writer part of the graph. SetOutputFileName does this for
us, and returns the mux and sink
IBaseFilter mux = null;
IFileSinkFilter sink = null;
hr = captureGraphBuilder.SetOutputFileName(MediaSubType.Avi, fileName, out
mux, out sink);
DsError.ThrowExceptionForHR(hr);
//Render any preview pin of the device
hr = captureGraphBuilder.RenderStream(PinCategory.Preview, MediaType.Video,
sourceFilter, null, null);
DsError.ThrowExceptionForHR(hr);
//Connect the device and compressor to the mux to render the capture part of
the graph
hr = captureGraphBuilder.RenderStream(PinCategory.Capture, MediaType.Video,
sourceFilter, null, mux);
DsError.ThrowExceptionForHR(hr);
// Find all cameras
private void findAllCaptureDevices()
{
System.Collections.ArrayList availableDevices = new
System.Collections.ArrayList();
devices = new System.Collections.ArrayList();
// Get all video input devices
availableDevices.AddRange(DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDe
vice));
foreach (object obj in availableDevices)
{
DsDevice device = (DsDevice)obj;
// Bind Moniker to a filter object
Guid iid = typeof(IBaseFilter).GUID;
object source;
device.Mon.BindToObject(null, null, ref iid, out source);
devices.Add((IBaseFilter)source);
}
}
It seems DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice) does not
include audio. if yes, could you help me to get webcams including both video
and audio since I need to save both video and audio into a file.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Your first question help me to figure the problem. I now figured out how to
get video and audio devices separately and successfully recorded audio and
video into a file. But with this solution, the audio devices could not be the
micro of webcams. Is there any way to get both video and audio of webcam into
a device object?
// Find all cameras
private void findAllCaptureDevices()
{
System.Collections.ArrayList availableDevices = new
System.Collections.ArrayList();
videoDevices = new System.Collections.ArrayList();
// Get all video input devices
availableDevices.AddRange(DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDe
vice));
foreach (object obj in availableDevices)
{
DsDevice device = (DsDevice)obj;
// Bind Moniker to a filter object
Guid iid = typeof(IBaseFilter).GUID;
object source;
device.Mon.BindToObject(null, null, ref iid, out source);
videoDevices.Add((IBaseFilter)source);
}
audioDevices = new System.Collections.ArrayList();
// Get usb audio input devices
availableDevices.RemoveRange(0, videoDevices.Count);
availableDevices.AddRange(DsDevice.GetDevicesOfCat(FilterCategory.AudioInputDe
vice));
foreach (object obj in availableDevices)
{
DsDevice device = (DsDevice)obj;
if(device.Name.Contains("USB Audio Device"))
{
// Bind Moniker to a filter object
Guid iid = typeof(IBaseFilter).GUID;
object source;
device.Mon.BindToObject(null, null, ref iid, out source);
audioDevices.Add((IBaseFilter)source);
}
}
}
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I am new with DirectShow.Net. I am implementing an C# application to record
video and audio from a webcam to a file (the webcam has a micro). Recording
video is fine but when I add a filter to record audio then it occurs exception
"One or more arguments are invalid". I do not know how to put valid arguments
since I put arguments similarly to rednering the video. Following is my code
and exception occurs at the second last line. Does anyone know how to put
correct arguments?
//Create the Graph
graphBuilder = (IGraphBuilder)new FilterGraph();
//Create the Capture Graph Builder
ICaptureGraphBuilder2 captureGraphBuilder = null;
captureGraphBuilder = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();
//Create the media control for controlling the graph
mediaControlList = (IMediaControl)this.graphBuilder;
// Attach the filter graph to the capture graph
int hr = captureGraphBuilder.SetFiltergraph(this.graphBuilder);
DsError.ThrowExceptionForHR(hr);
//Add the Video input device to the graph
IBaseFilter sourceFilter = (IBaseFilter)devices;
hr = graphBuilder.AddFilter(sourceFilter, "The webcam " + (indexOfCamera +
1).ToString());
DsError.ThrowExceptionForHR(hr);
//Add the Video compressor filter to the graph
IBaseFilter videoCompressor = getVideoCompressor();
if (videoCompressor != null)
{
hr = graphBuilder.AddFilter(videoCompressor, "video compressor filter");
DsError.ThrowExceptionForHR(hr);
}
//Add the Video compressor filter to the graph
IBaseFilter audioCompressor = getAudioCompressor();
if (audioCompressor != null)
{
hr = graphBuilder.AddFilter(audioCompressor, "audio compressor filter");
DsError.ThrowExceptionForHR(hr);
}
//Create the file writer part of the graph. SetOutputFileName does this for
us, and returns the mux and sink
IBaseFilter mux = null;
IFileSinkFilter sink = null;
hr = captureGraphBuilder.SetOutputFileName(MediaSubType.Avi, fileName, out
mux, out sink);
DsError.ThrowExceptionForHR(hr);
//Render any preview pin of the device
hr = captureGraphBuilder.RenderStream(PinCategory.Preview, MediaType.Video,
sourceFilter, null, null);
DsError.ThrowExceptionForHR(hr);
//Connect the device and compressor to the mux to render the capture part of
the graph
hr = captureGraphBuilder.RenderStream(PinCategory.Capture, MediaType.Video,
sourceFilter, null, mux);
DsError.ThrowExceptionForHR(hr);
//Render with audio
hr = captureGraphBuilder.RenderStream(PinCategory.Capture, MediaType.Audio,
sourceFilter, null, mux);
DsError.ThrowExceptionForHR(hr);
Thanks,
Let's take a look at what you are doing to connect the audio:
Now, where do you get the value for sourceFilter?
You don't show where you get "devices", but presumably from using DsDevice? If
so, then the solution here should be obvious.
Here is how I get the webcams.
// Find all cameras
private void findAllCaptureDevices()
{
System.Collections.ArrayList availableDevices = new
System.Collections.ArrayList();
devices = new System.Collections.ArrayList();
// Get all video input devices
availableDevices.AddRange(DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDe
vice));
foreach (object obj in availableDevices)
{
DsDevice device = (DsDevice)obj;
// Bind Moniker to a filter object
Guid iid = typeof(IBaseFilter).GUID;
object source;
device.Mon.BindToObject(null, null, ref iid, out source);
devices.Add((IBaseFilter)source);
}
}
It seems DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice) does not
include audio. if yes, could you help me to get webcams including both video
and audio since I need to save both video and audio into a file.
C'mon man. You've got a statement that reads:
DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice)
And you can't figure out what you have to change to get audio devices? You're
kidding, right?
Your first question help me to figure the problem. I now figured out how to
get video and audio devices separately and successfully recorded audio and
video into a file. But with this solution, the audio devices could not be the
micro of webcams. Is there any way to get both video and audio of webcam into
a device object?
// Find all cameras
private void findAllCaptureDevices()
{
System.Collections.ArrayList availableDevices = new
System.Collections.ArrayList();
videoDevices = new System.Collections.ArrayList();
// Get all video input devices
availableDevices.AddRange(DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDe
vice));
foreach (object obj in availableDevices)
{
DsDevice device = (DsDevice)obj;
// Bind Moniker to a filter object
Guid iid = typeof(IBaseFilter).GUID;
object source;
device.Mon.BindToObject(null, null, ref iid, out source);
videoDevices.Add((IBaseFilter)source);
}
audioDevices = new System.Collections.ArrayList();
// Get usb audio input devices
availableDevices.RemoveRange(0, videoDevices.Count);
availableDevices.AddRange(DsDevice.GetDevicesOfCat(FilterCategory.AudioInputDe
vice));
foreach (object obj in availableDevices)
{
DsDevice device = (DsDevice)obj;
if(device.Name.Contains("USB Audio Device"))
{
// Bind Moniker to a filter object
Guid iid = typeof(IBaseFilter).GUID;
object source;
device.Mon.BindToObject(null, null, ref iid, out source);
audioDevices.Add((IBaseFilter)source);
}
}
}