mardi 12 août 2014

c# - DirectShow - filtres mettez dans GraphEdit, mais pas dans mon application - Stack Overflow


I have a C# application that is supposed to build a DirectShow graph to render an H.264 encoded video stream. I'm using DirectShowLib as managed wrapper. I already got it working with different filters for RTSP Source and H.264 (Video Processing Project, DivX, Datastead, ...), but recently, I came across the MontiVision Filters mentioned here. I tried them in GraphStudio, and was very pleased with their performance, so I wanted to use them in my application.


Strange thing though, while the "MV Stream Source" and "MV Video Decoder" filters connect seamlessly in GraphStudio (after setting the RTSP URL), when I try the same thing in C#, I get an HRESULT of VFW_E_NO_ACCEPTABLE_TYPES when trying to connect the same filters. "MV Stream Source" outputs an AVC1 Mediatype, I don't know what mediatype the "MV Video Decoder" accepts, but when I connect the filters in GraphStudio, it seems to accept AVC1.


I am certain that the pin names and GUIDs are correct (same as in GraphStudio). I also tried waiting (Thread.Sleep) up to 10 seconds between filter creation and connection, to no avail.


Does anybody have an idea what I might be doing wrong? Thanks!


The code for connecting the filters looks like this:


int hr = 0;

//add Source Filter
hr = pGraph.AddFilter(pSourceFilter, "Source Filter");
DsHelper.checkHR(hr, "Can't add Source Filter to graph");


//set source filename
IFileSourceFilter pVideoSourceFilter_src = pSourceFilter as IFileSourceFilter;
if (pVideoSourceFilter_src == null)
DsHelper.checkHR(unchecked((int)0x80004002), "Can't get IFileSourceFilter");

hr = pVideoSourceFilter_src.Load(srcFile, null);

DsHelper.checkHR(hr, "Can't load file");

//add Video Decoder
hr = pGraph.AddFilter(pVideoDecoder, "Video Decoder");
DsHelper.checkHR(hr, "Can't add Video Decoder to graph");

//add Video Renderer
IBaseFilter pVideoRenderer = DsHelper.FilterFromGUID(DsHelper.CLSID_NullRenderer);
hr = pGraph.AddFilter(pVideoRenderer, "Video Renderer");
DsHelper.checkHR(hr, "Can't add Video Renderer to graph");

//connect Source Filter and Video Decoder
hr = pGraph.ConnectDirect(DsHelper.GetPin(pSourceFilter, srcFilterVideoOutName), DsHelper.GetPin(pVideoDecoder, vdVideoInName), null);
DsHelper.checkHR(hr, "Can't connect Source Filter and Video Decoder");

Creating the filters:


IBaseFilter pSourceFilter = (IBaseFilter)DsHelper.FilterFromGUID(DsHelper.CLSID_MVRTSPSourceFilter);
IBaseFilter pVideoDecoder = (IBaseFilter)DsHelper.FilterFromGUID(DsHelper.CLSID_MVDecoder);

Helpers:


public static Guid CLSID_MVDecoder = new Guid("{D8F0E4C9-38DB-40E7-93C3-248A22D587B8}");
public static Guid CLSID_MVRTSPSourceFilter = new Guid("{EDE234EC-157E-4516-9AC5-0F401384918B}");
public static IBaseFilter FilterFromGUID(Guid filterGuid)
{
return (IBaseFilter)Activator.CreateInstance(Type.GetTypeFromCLSID(filterGuid));
}

public static IPin GetPin(IBaseFilter filter, string pinname)
{
IEnumPins epins;
int hr = filter.EnumPins(out epins);
checkHR(hr, "Can't enumerate pins");
IntPtr fetched = Marshal.AllocCoTaskMem(4);
IPin[] pins = new IPin[1];
while (epins.Next(1, pins, fetched) == 0)
{
PinInfo pinfo;
pins[0].QueryPinInfo(out pinfo);
bool found = (pinfo.name == pinname);
DsUtils.FreePinInfo(pinfo);
if (found) return pins[0];
}
checkHR(-1, "Pin not found: " + pinname);
return null;
}


I have a C# application that is supposed to build a DirectShow graph to render an H.264 encoded video stream. I'm using DirectShowLib as managed wrapper. I already got it working with different filters for RTSP Source and H.264 (Video Processing Project, DivX, Datastead, ...), but recently, I came across the MontiVision Filters mentioned here. I tried them in GraphStudio, and was very pleased with their performance, so I wanted to use them in my application.


Strange thing though, while the "MV Stream Source" and "MV Video Decoder" filters connect seamlessly in GraphStudio (after setting the RTSP URL), when I try the same thing in C#, I get an HRESULT of VFW_E_NO_ACCEPTABLE_TYPES when trying to connect the same filters. "MV Stream Source" outputs an AVC1 Mediatype, I don't know what mediatype the "MV Video Decoder" accepts, but when I connect the filters in GraphStudio, it seems to accept AVC1.


I am certain that the pin names and GUIDs are correct (same as in GraphStudio). I also tried waiting (Thread.Sleep) up to 10 seconds between filter creation and connection, to no avail.


Does anybody have an idea what I might be doing wrong? Thanks!


The code for connecting the filters looks like this:


int hr = 0;

//add Source Filter
hr = pGraph.AddFilter(pSourceFilter, "Source Filter");
DsHelper.checkHR(hr, "Can't add Source Filter to graph");


//set source filename
IFileSourceFilter pVideoSourceFilter_src = pSourceFilter as IFileSourceFilter;
if (pVideoSourceFilter_src == null)
DsHelper.checkHR(unchecked((int)0x80004002), "Can't get IFileSourceFilter");

hr = pVideoSourceFilter_src.Load(srcFile, null);

DsHelper.checkHR(hr, "Can't load file");

//add Video Decoder
hr = pGraph.AddFilter(pVideoDecoder, "Video Decoder");
DsHelper.checkHR(hr, "Can't add Video Decoder to graph");

//add Video Renderer
IBaseFilter pVideoRenderer = DsHelper.FilterFromGUID(DsHelper.CLSID_NullRenderer);
hr = pGraph.AddFilter(pVideoRenderer, "Video Renderer");
DsHelper.checkHR(hr, "Can't add Video Renderer to graph");

//connect Source Filter and Video Decoder
hr = pGraph.ConnectDirect(DsHelper.GetPin(pSourceFilter, srcFilterVideoOutName), DsHelper.GetPin(pVideoDecoder, vdVideoInName), null);
DsHelper.checkHR(hr, "Can't connect Source Filter and Video Decoder");

Creating the filters:


IBaseFilter pSourceFilter = (IBaseFilter)DsHelper.FilterFromGUID(DsHelper.CLSID_MVRTSPSourceFilter);
IBaseFilter pVideoDecoder = (IBaseFilter)DsHelper.FilterFromGUID(DsHelper.CLSID_MVDecoder);

Helpers:


public static Guid CLSID_MVDecoder = new Guid("{D8F0E4C9-38DB-40E7-93C3-248A22D587B8}");
public static Guid CLSID_MVRTSPSourceFilter = new Guid("{EDE234EC-157E-4516-9AC5-0F401384918B}");
public static IBaseFilter FilterFromGUID(Guid filterGuid)
{
return (IBaseFilter)Activator.CreateInstance(Type.GetTypeFromCLSID(filterGuid));
}

public static IPin GetPin(IBaseFilter filter, string pinname)
{
IEnumPins epins;
int hr = filter.EnumPins(out epins);
checkHR(hr, "Can't enumerate pins");
IntPtr fetched = Marshal.AllocCoTaskMem(4);
IPin[] pins = new IPin[1];
while (epins.Next(1, pins, fetched) == 0)
{
PinInfo pinfo;
pins[0].QueryPinInfo(out pinfo);
bool found = (pinfo.name == pinname);
DsUtils.FreePinInfo(pinfo);
if (found) return pins[0];
}
checkHR(-1, "Pin not found: " + pinname);
return null;
}

0 commentaires:

Enregistrer un commentaire