Saturday, 24 August 2013

DirectShow .NET MediaControl.Stop() fails

DirectShow .NET MediaControl.Stop() fails

I'm using DirectShow .NET in my applicatiot, but I've got a problem
causing 2 problems: calling IMediaControl.Stop() doesn't stop my graph, it
keeps running. Therefore I can't neither restart the graph to change the
resolution, nor record video, because the headers are written when the
MediaControl is stopped. If I connect to the graph through GraphStudio and
stop it there, the .avi-File I'm recording is valid.
Here's my code building the graph:
public bool InitGraph(String sDevice,int iWidth,int iHeight,int fps,bool
useffd, Control hWindow) { try {
object o = null;
int hr = 0;
//fill up member vars
m_bUseFFDRaw = useffd;
m_Device = sDevice;
m_Control = hWindow;
m_filterGraph = (IGraphBuilder)new FilterGraph();
m_captureGraphBuilder = (ICaptureGraphBuilder2)new
CaptureGraphBuilder2();
m_mediaControl = (IMediaControl)m_filterGraph;
m_mediaEventEx = m_filterGraph as IMediaEventEx;
m_sampGrabber = (ISampleGrabber)new SampleGrabber();
if (m_sampGrabber == null)
{
MessageBox.Show("Error initializing grabber.\nErrorcode:
0x0003", "Capture Engine", MessageBoxButtons.OK,
MessageBoxIcon.Error);
return false;
}
//Get the filter for the capture device
//and set up the needed filters
m_deviceFilter = CreateFilter(FilterCategory.VideoInputDevice,
sDevice);
if (m_deviceFilter == null)
{
MessageBox.Show("Error initializing filters.\nErrorcode:
0x0004", "Capture Engine", MessageBoxButtons.OK,
MessageBoxIcon.Error);
return false;
}
m_sDeviceName = sDevice;
if (hWindow.Parent.Parent.Handle != null)
hr =
m_mediaEventEx.SetNotifyWindow(hWindow.Parent.Parent.Handle,
WM_GRAPHNOTIFY, IntPtr.Zero);
DsError.ThrowExceptionForHR(hr);
ConfigureSampleGrabber(m_sampGrabber);
//get the interfaces
m_grabFilter = (IBaseFilter)m_sampGrabber;
m_SmartTee = (IBaseFilter)new SmartTee();
m_videoRenderer = new VideoMixingRenderer9();
m_videoRendererFilter = (IBaseFilter)new VideoMixingRenderer9();
m_videoRendererFilter = (IBaseFilter)m_videoRenderer;
if (m_bUseFFDRaw)
{
try
{
m_ffdraw =
CreateFilter(FilterCategory.LegacyAmFilterCategory,
"ffdshow raw video filter");
if (m_ffdraw == null)
{
MessageBox.Show("Cant find the ffdshow
filter-interface. Make sure ffdshow filters are
installed correctly.\nErrorcode: 0x0005", "Capture
Engine", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
}
catch (Exception e)
{
MessageBox.Show(e.ToString() + "\nErrorcode: 0x0005",
"Capture Engine", MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}
m_filterGraph.AddFilter(m_deviceFilter, "Source");
m_filterGraph.AddFilter(m_grabFilter, "Grabber");
m_filterGraph.AddFilter(m_SmartTee, "Smart Tee");
if (m_bUseFFDRaw)
m_filterGraph.AddFilter(m_ffdraw, "FFDShow-Postprocessor");
m_filterGraph.AddFilter(m_videoRendererFilter, "VMR9");
String[] s;
this.GetAvailableVideoModes(out s);
//check if resolution is available
if (this.IsResolutionAvailable(iWidth, iHeight))
SetConfigParms(m_captureGraphBuilder, m_deviceFilter, fps,
iWidth, iHeight);
else MessageBox.Show("Your desired resolution is not available on
this device. Default parameters are set.\nPlease go to 'Settings'
and change the input resolution.", "Capture Engine",
MessageBoxButtons.OK, MessageBoxIcon.Information);
//get the pins
m_deviceOutCapture = DsFindPin.ByDirection(m_deviceFilter,
PinDirection.Output, 0);
m_deviceOutPreview = DsFindPin.ByDirection(m_deviceFilter,
PinDirection.Output, 1);
SmartIn = DsFindPin.ByDirection(m_SmartTee, PinDirection.Input, 0);
GrabberIn = DsFindPin.ByDirection(m_grabFilter,
PinDirection.Input, 0);
SmartOutCapt = DsFindPin.ByName(m_SmartTee, "Capture");
SmartOutPreview = DsFindPin.ByName(m_SmartTee, "Preview");
m_RendererIn = DsFindPin.ByName(m_videoRendererFilter, "VMR Input0");
if (m_bUseFFDRaw)
{
ffdrawIn = DsFindPin.ByDirection(m_ffdraw, PinDirection.Input,
0);
ffdrawOut = DsFindPin.ByDirection(m_ffdraw,
PinDirection.Output, 0);
}
hr = m_captureGraphBuilder.FindInterface(PinCategory.Capture,
MediaType.Video, m_deviceFilter, typeof(IAMStreamConfig).GUID, out
o);
if (hr >= 0)
{
m_stream = o as IAMStreamConfig;
o = null;
}
DsError.ThrowExceptionForHR(hr);
//connect the filters
hr = m_filterGraph.Connect(m_deviceOutCapture, SmartIn);
DsError.ThrowExceptionForHR(hr);
hr = m_filterGraph.Connect(SmartOutCapt, GrabberIn);
DsError.ThrowExceptionForHR(hr);
if (m_bUseFFDRaw)
{
if (SmartOutPreview != null && ffdrawIn != null)
{
hr = m_filterGraph.Connect(SmartOutPreview, ffdrawIn);
DsError.ThrowExceptionForHR(hr);
}
}
hr = m_captureGraphBuilder.SetFiltergraph(m_filterGraph);
DsError.ThrowExceptionForHR(hr);
//render all together
if (m_bUseFFDRaw)
{
hr = m_captureGraphBuilder.RenderStream(null, MediaType.Video,
m_ffdraw, null, m_videoRendererFilter);
//hr = m_filterGraph.Render(ffdrawOut);
DsError.ThrowExceptionForHR(hr);
}
else
{
hr = m_captureGraphBuilder.RenderStream(null, MediaType.Video,
m_SmartTee, null, m_videoRendererFilter);
//hr = m_filterGraph.Render(SmartOutPreview);
DsError.ThrowExceptionForHR(hr);
}
//get the interfaces
m_crossbarFilter = null;
hr = m_captureGraphBuilder.FindInterface(PinCategory.Capture,
MediaType.Video, m_deviceFilter, typeof(IAMCrossbar).GUID,
out o);
if (hr >= 0)
{
m_crossbarFilter = (IBaseFilter)o;
m_crossbarInterface = (IAMCrossbar)o;
o = null;
}
if (m_crossbarFilter == null || m_crossbarInterface == null)
m_console.Text += ("Capture Engine: Can't find a
crossbar-interface."
+ System.Environment.NewLine);
hr = m_captureGraphBuilder.FindInterface(null, null, m_deviceFilter,
typeof(IAMAnalogVideoDecoder).GUID, out o);
if (hr >= 0)
{
m_decoder = (IAMAnalogVideoDecoder)o;
m_decoderFilter = (IBaseFilter)o;
o = null;
}
if (m_decoder == null || m_decoderFilter == null)
m_console.Text += ("Capture Engine: Can't find a
decoder-interface." +
System.Environment.NewLine);
//get video properties
AMMediaType media;
VideoInfoHeader v;
hr = m_stream.GetFormat(out media);
DsError.ThrowExceptionForHR(hr);
try
{
v = new VideoInfoHeader();
Marshal.PtrToStructure(media.formatPtr, v);
m_iWidth = v.BmiHeader.Width;
m_iHeight = v.BmiHeader.Height;
m_iBitsPerPixel = v.BmiHeader.BitCount;
m_iFPS = 1000000 / (int)v.AvgTimePerFrame;
m_stride = m_iWidth * (v.BmiHeader.BitCount / 8);
}
finally
{
DsUtils.FreeAMMediaType(media);
media = null;
}
//set video window
m_videoWindow = null;
m_videoWindow = (IVideoWindow)m_filterGraph;
m_wndHandle = hWindow;
hr = m_videoWindow.put_Owner(hWindow.Handle);
DsError.ThrowExceptionForHR(hr);
hr = m_videoWindow.put_MessageDrain(hWindow.Parent.Handle);
DsError.ThrowExceptionForHR(hr);
hr = m_videoWindow.put_WindowStyle(WindowStyle.Child |
WindowStyle.ClipChildren | WindowStyle.ClipSiblings);
DsError.ThrowExceptionForHR(hr);
hr = m_videoWindow.put_Visible(OABool.True);
DsError.ThrowExceptionForHR(hr);
Rectangle rc = hWindow.ClientRectangle;
hr = m_videoWindow.SetWindowPosition(0, 0, rc.Right, rc.Bottom);
DsError.ThrowExceptionForHR(hr);
m_console.Text += "Capture Engine: Components initialized." +
System.Environment.NewLine + System.Environment.NewLine;
#if ROT
rot = new DsROTEntry(this.m_filterGraph);

No comments:

Post a Comment