/// <summary> /// Query whether a pin is connected to another pin. /// </summary> /// <param name="pPin">Specifies the pin to check.</param> /// <param name="bResult">Specifies the connection status.</param> /// <returns>An error value < 0 is returned or 0 for success.</returns> public static int IsPinConnected(IPin pPin, out bool bResult) { uint VFW_E_NOT_CONNECTED = 0x80040209; IPin pTmp = null; bResult = false; int hr = pPin.ConnectedTo(out pTmp); if (hr == 0) { bResult = true; } else if (hr == (int)VFW_E_NOT_CONNECTED) { // The pin is not connected. This is not an error for checking the connection status. bResult = false; hr = 0; } if (pTmp != null) { Marshal.ReleaseComObject(pTmp); } return(hr); }
/// <summary> /// Find all the filters connected downstream from the specified pin, /// following all branches. /// </summary> /// <param name="pin"></param> /// <returns></returns> private List <IBaseFilter> EnumerateDownstreamFromPin(IPin pin) { //Find the input pin that the target pin is connected to. IPin connectedToInput; try { pin.ConnectedTo(out connectedToInput); } catch (COMException) { //not connected return(new List <IBaseFilter>()); } // Map that pin to the next filter. _PinInfo pInfo; connectedToInput.QueryPinInfo(out pInfo); IBaseFilter connectedFilter = pInfo.pFilter; //Add the filter to the list. List <IBaseFilter> returnList = new List <IBaseFilter>(); returnList.Add(connectedFilter); //Enumerate output pins of the filter ArrayList outPins = Filter.GetPins(Filter.GetPins(connectedFilter), _PinDirection.PINDIR_OUTPUT); foreach (IPin p in outPins) { //recurse over each pin returnList.AddRange(EnumerateDownstreamFromPin(p)); } return(returnList); }
public static bool DisconnectPin(IGraphBuilder graphBuilder, IPin pin) { IPin other; int hr = pin.ConnectedTo(out other); bool allDisconnected = true; PinInfo info; pin.QueryPinInfo(out info); DsUtils.FreePinInfo(info); if (hr == 0 && other != null) { other.QueryPinInfo(out info); if (!DisconnectAllPins(graphBuilder, info.filter)) { allDisconnected = false; } hr = pin.Disconnect(); if (hr != 0) { allDisconnected = false; } hr = other.Disconnect(); if (hr != 0) { allDisconnected = false; } DsUtils.FreePinInfo(info); Marshal.ReleaseComObject(other); } else { } return(allDisconnected); }
protected override void BuildGraph(string path) { // Build partial graph IPin videoOutput = null, audioOutput = null; { VideoRendererDefault videoRenderer = new VideoRendererDefault(); DSoundRender audioRenderer = new DSoundRender(); try { GraphBuilder.AddFilter(videoRenderer as IBaseFilter, "Default Video Renderer"); GraphBuilder.AddFilter(audioRenderer as IBaseFilter, "Default Audio Renderer"); GraphBuilder.RenderFile(path, null); // Get Connected Pins { IPin videoInput = Util.FindInputPin(videoRenderer as IBaseFilter); videoInput.ConnectedTo(out videoOutput); Util.FreePin(videoInput); IPin audioInput = Util.FindInputPin(audioRenderer as IBaseFilter); audioInput.ConnectedTo(out audioOutput); Util.FreePin(audioInput); } GraphBuilder.RemoveFilter(videoRenderer as IBaseFilter); GraphBuilder.RemoveFilter(audioRenderer as IBaseFilter); } finally { Marshal.ReleaseComObject(videoRenderer); Marshal.ReleaseComObject(audioRenderer); } } // build video grabber if (videoOutput != null) { this.VideoGrabber = BuildGrabber("Video", videoOutput, MEDIATYPE_Video, MEDIASUBTYPE_RGB32, FORMAT_VideoInfo, OnVideoFrame) as ISampleGrabber; this.VideoInfo = GetMediaFormat <VideoInfoHeader>(VideoGrabber); Marshal.ReleaseComObject(videoOutput); } // build audio grabber if (audioOutput != null) { this.AudioGrabber = BuildGrabber("Audio", audioOutput, MEDIATYPE_Audio, MEDIASUBTYPE_PCM, FORMAT_WaveFormatEx, OnAudioFrame) as ISampleGrabber; this.AudioInfo = GetMediaFormat <WaveFormatEx>(AudioGrabber); Marshal.ReleaseComObject(audioOutput); } }
public static bool IsPinConnected(IPin pin) { IPin pinNext; int result = pin.ConnectedTo(out pinNext); if (pinNext != null) { Marshal.ReleaseComObject(pinNext); } return(result == 0); }
public static void Disconnect(IFilterGraph pFilterGraph, IPin pPin) { IPin pInputPin = null; if (pPin.ConnectedTo(out pInputPin) == DsHlp.S_OK) { pFilterGraph.Disconnect(pInputPin); Marshal.ReleaseComObject(pInputPin); } pFilterGraph.Disconnect(pPin); }
public static void Disconnect(IGraphBuilder pGraphBuilder, IPin pPin) { IPin pInputPin = null; if (pPin.ConnectedTo(out pInputPin) == DsHlp.S_OK) { pGraphBuilder.Disconnect(pInputPin); Marshal.ReleaseComObject(pInputPin); } pGraphBuilder.Disconnect(pPin); }
static IPin FindPinByDirection(IBaseFilter filter, PinDirection direction) { IPin destPin = null; IEnumPins iEnum; int hr; IPin[] pins = new IPin[1]; hr = filter.EnumPins(out iEnum); DsError.ThrowExceptionForHR(hr); if (iEnum == null) { throw new InvalidOperationException("iEnum is null"); } IntPtr fetched = Marshal.AllocCoTaskMem(4); hr = iEnum.Next(1, pins, fetched); DsError.ThrowExceptionForHR(hr); while (Marshal.ReadInt32(fetched) == 1) { PinDirection pinDir; IPin pPin; destPin = pins[0]; hr = destPin.QueryDirection(out pinDir); DsError.ThrowExceptionForHR(hr); destPin.ConnectedTo(out pPin); if (pPin == null && pinDir == direction) { break; } if (pPin != null) { Marshal.ReleaseComObject(pPin); } hr = iEnum.Next(1, pins, fetched); DsError.ThrowExceptionForHR(hr); } Marshal.FreeCoTaskMem(fetched); return(destPin); }
private bool IsMatchingPin(IPin pin, PinDirection direction, Guid mediaType) { PinDirection pinDirection; int hr = pin.QueryDirection(out pinDirection); DsError.ThrowExceptionForHR(hr); if (pinDirection != direction) { // The pin lacks direction return(false); } IPin connectedPin; hr = pin.ConnectedTo(out connectedPin); if ((uint)hr != 0x80040209 /* Pin is not connected */) { DsError.ThrowExceptionForHR(hr); } if (connectedPin != null) { // The pin is already connected Marshal.ReleaseComObject(connectedPin); return(false); } IEnumMediaTypes mediaTypesEnum; hr = pin.EnumMediaTypes(out mediaTypesEnum); DsError.ThrowExceptionForHR(hr); AMMediaType[] mediaTypes = new AMMediaType[1]; while (mediaTypesEnum.Next(1, mediaTypes, IntPtr.Zero) == 0) { Guid majorType = mediaTypes[0].majorType; DsUtils.FreeAMMediaType(mediaTypes[0]); if (majorType == mediaType) { // We have found the pin we were looking for return(true); } } return(false); }
public static void LogOutputPinsConnectionRecursive(IBaseFilter filter, string previous = "") { bool log = true; IEnumPins pinEnum = null; if (filter.EnumPins(out pinEnum) == 0) { FilterInfo sourceFilterInfo; filter.QueryFilterInfo(out sourceFilterInfo); int fetched = 0; IPin[] pins = new IPin[1]; while (pinEnum.Next(1, pins, out fetched) == 0 && fetched > 0) { IPin pin = pins[0]; PinDirection pinDirection; if (pin.QueryDirection(out pinDirection) == 0 && pinDirection == PinDirection.Output) { log = false; IPin connectedPin; if (pin.ConnectedTo(out connectedPin) == 0 && connectedPin != null) { PinInfo connectedPinInfo; connectedPin.QueryPinInfo(out connectedPinInfo); FilterInfo connectedFilterInfo; connectedPinInfo.filter.QueryFilterInfo(out connectedFilterInfo); if (previous == "") { previous = sourceFilterInfo.achName; } DirectShowUtil.ReleaseComObject(connectedPin, 2000); IBaseFilter connectedFilter; if (connectedFilterInfo.pGraph.FindFilterByName(connectedFilterInfo.achName, out connectedFilter) == 0 && connectedFilter != null) { LogOutputPinsConnectionRecursive(connectedFilter, previous + string.Format(" --> {0}", connectedFilterInfo.achName)); DirectShowUtil.ReleaseComObject(connectedFilter); } } DirectShowUtil.ReleaseComObject(pin, 2000); } } } DirectShowUtil.ReleaseComObject(pinEnum, 2000); if (log) { Log.Instance.Debug(previous); } }
/// <summary> /// Gets the first pin of the specified direction and connection status. You also specify /// how many matching pins should be skipped before a desired pin is returned. /// /// If this function finds a matching pin, it returns an IPin interface pointer /// with an outstanding reference count. The caller is responsible for releasing the interface. /// /// Leaving the last two parameters at their default /// values is like saying: "Gimme the first unconnected pin". /// </summary> /// <param name="pFilter">Filter</param> /// <param name="pinDir">Pin direction</param> /// <param name="bConnected">Whether the returned Pin should be connected to some other pin</param> /// <param name="nPinsToSkip">How many Pins that match the conditions should be skipped</param> /// <returns></returns> public static IPin GetPin(IBaseFilter pFilter, PinDirection pinDir, bool bConnected, int nPinsToSkip) { bool bFound = false; IEnumPins pEnum; IPin pPin = null; int cFetched; int nSkipped = 0; IPin pConnectedPin = null; int hr = pFilter.EnumPins(out pEnum); if (DsHlp.FAILED(hr) || pEnum == null) { return(null); } while ((pEnum.Next(1, out pPin, out cFetched) == DsHlp.S_OK) && pPin != null) { PinDirection PinDirThis; pPin.QueryDirection(out PinDirThis); if (pinDir == PinDirThis) { hr = pPin.ConnectedTo(out pConnectedPin); if (pConnectedPin != null) { Marshal.ReleaseComObject(pConnectedPin); pConnectedPin = null; } if ((hr == DsHlp.S_OK && bConnected) || ((uint)hr == DsHlp.VFW_E_NOT_CONNECTED && !bConnected)) { if (nSkipped == nPinsToSkip) { bFound = true; break; } else { nSkipped++; } } } Marshal.ReleaseComObject(pPin); pPin = null; } Marshal.ReleaseComObject(pEnum); return(bFound ? pPin : null); }
public static void tビデオレンダラをグラフから除去する(IGraphBuilder graphBuilder) { int hr = 0; IBaseFilter videoRenderer = null; IPin renderInputPin = null; IPin connectedOutputPin = null; try { // videoRenderer を探す。 CDirectShow.tビデオレンダラとその入力ピンを探して返す(graphBuilder, out videoRenderer, out renderInputPin); if (videoRenderer == null || renderInputPin == null) { return; // なかった } #region [ renderInputPin へ接続している前段の出力ピン connectedOutputPin を探す。 ] //----------------- renderInputPin.ConnectedTo(out connectedOutputPin); //----------------- #endregion if (connectedOutputPin == null) { return; // なかった } // 前段の出力ピンとビデオレンダラの入力ピンを切断する。双方向から切断しないとグラフから切り離されないので注意。 renderInputPin.Disconnect(); connectedOutputPin.Disconnect(); // ビデオレンダラをグラフから除去。 graphBuilder.RemoveFilter(videoRenderer); } finally { CCommon.tReleaseComObject(ref connectedOutputPin); CCommon.tReleaseComObject(ref renderInputPin); CCommon.tReleaseComObject(ref videoRenderer); } }
/// <summary> /// Disconnects a single Pin. /// </summary> /// <param name="graphBuilder">IGraphBuilder</param> /// <param name="pin">Pin to disconnect</param> /// <returns>True if successful</returns> bool DisconnectPin(IGraphBuilder graphBuilder, IPin pin) { IntPtr other_ptr; int hr = pin.ConnectedTo(out other_ptr); bool allDisconnected = true; if (hr == 0 && other_ptr != IntPtr.Zero) { IPin other = Marshal.GetObjectForIUnknown(other_ptr) as IPin; PinInfo info; pin.QueryPinInfo(out info); ServiceRegistration.Get <ILogger>().Info("Disconnecting pin {0}", info.name); FilterGraphTools.FreePinInfo(info); other.QueryPinInfo(out info); if (!DisconnectAllPins(graphBuilder, info.filter)) { allDisconnected = false; } FilterGraphTools.FreePinInfo(info); hr = pin.Disconnect(); if (hr != 0) { allDisconnected = false; ServiceRegistration.Get <ILogger>().Error("Error disconnecting: {0:x}", hr); } hr = other.Disconnect(); if (hr != 0) { allDisconnected = false; ServiceRegistration.Get <ILogger>().Error("Error disconnecting other: {0:x}", hr); } Marshal.ReleaseComObject(other); } else { ServiceRegistration.Get <ILogger>().Info(" Not connected"); } return(allDisconnected); }
private bool GetPins(out IPin rendererInputPin, out IPin decoderOutPin) { bool bRet = false; rendererInputPin = decoderOutPin = null; if (BaseFilter != null && (rendererInputPin = DsUtils.GetPin(BaseFilter, PinDirection.Input, true)) != null) { int hr = rendererInputPin.ConnectedTo(out decoderOutPin); if (hr == DsHlp.S_OK) { DsUtils.Disconnect(GraphBuilder, rendererInputPin); bRet = true; } else { Marshal.ReleaseComObject(rendererInputPin); rendererInputPin = null; } } return(bRet); }
protected IPin GetUnconnectedPin(IBaseFilter filter, PinDirection direction) { IPin destPin = null; IEnumPins iEnum; var pins = new IPin[1]; var hr = filter.EnumPins(out iEnum); Marshal.ThrowExceptionForHR(hr); var fetched = Marshal.AllocCoTaskMem(4); hr = iEnum.Next(1, pins, fetched); Marshal.ThrowExceptionForHR(hr); while (Marshal.ReadInt32(fetched) == 1) { PinDirection pinDir; IPin pPin; destPin = pins[0]; hr = destPin.QueryDirection(out pinDir); Marshal.ThrowExceptionForHR(hr); PinInfo info; destPin.QueryPinInfo(out info); //var name = info.name; destPin.ConnectedTo(out pPin); if (pPin == null && pinDir == direction) { break; } hr = iEnum.Next(1, pins, fetched); Marshal.ThrowExceptionForHR(hr); } Marshal.FreeCoTaskMem(fetched); return(destPin); }
public static void RemoveFromGraph(IGraphBuilder graphBuilder) { IBaseFilter vob = null; DirectShowUtil.FindFilterByClassID(graphBuilder, ClassId.DirectVobSubAutoload, out vob); if (vob == null) { //Try the "normal" filter then. DirectShowUtil.FindFilterByClassID(graphBuilder, ClassId.DirectVobSubNormal, out vob); if (vob == null) { return; } } Log.Info("VideoPlayerVMR9: DirectVobSub in graph, removing..."); // Check where video inputs are connected IPin pinVideoIn = DsFindPin.ByDirection(vob, PinDirection.Input, 0); IPin pinVideoOut = DsFindPin.ByDirection(vob, PinDirection.Output, 0); //find directvobsub's video output pin source input pin IPin pinVideoTo = null; pinVideoOut.ConnectedTo(out pinVideoTo); //find directvobsub's video input pin source output pin IPin pinVideoFrom = null; pinVideoIn.ConnectedTo(out pinVideoFrom); int hr; if (pinVideoFrom != null) { hr = pinVideoFrom.Disconnect(); if (hr != 0) { Log.Error("VideoPlayerVMR9: DirectVobSub failed disconnecting source pin"); } } if (pinVideoTo != null) { hr = pinVideoTo.Disconnect(); if (hr != 0) { Log.Error("VideoPlayerVMR9: DirectVobSub failed disconnecting destination pin"); } } //remove the DirectVobSub filter from the graph graphBuilder.RemoveFilter(vob); DirectShowUtil.ReleaseComObject(vob); vob = null; //reconnect the source output pin to the vmr9/evr filter hr = graphBuilder.Connect(pinVideoFrom, pinVideoTo); //hr = graphBuilder.Render(pinVideoFrom); DirectShowUtil.ReleaseComObject(pinVideoFrom); pinVideoFrom = null; DirectShowUtil.ReleaseComObject(pinVideoTo); pinVideoTo = null; DirectShowUtil.ReleaseComObject(pinVideoOut); pinVideoOut = null; DirectShowUtil.ReleaseComObject(pinVideoIn); pinVideoIn = null; if (hr != 0) { Log.Error("VideoPlayerVMR9: Could not connect video out to video renderer: {0}", hr); } else { Log.Debug("VideoPlayerVMR9: DirectVobSub graph rebuild finished"); } }
private void UnRender(IPin pinOutOrigin) { int hr; //hr = pinOutOrigin.Disconnect(); IPin pinOutEnd = null; hr = pinOutOrigin.ConnectedTo(out pinOutEnd); if (pinOutEnd != null) { try { PinInfo pInfo = new PinInfo(); hr = pinOutEnd.QueryPinInfo(out pInfo); if (hr >= 0) { if (pInfo.filter != null) { try { IEnumPins ppEnum; hr = pInfo.filter.EnumPins(out ppEnum); if (hr >= 0) { try { // Walk the pins looking for a match IPin[] pPins = new IPin[1]; //22 int lFetched; //22 while ((ppEnum.Next(1, pPins, out lFetched) >= 0) && (lFetched == 1)) while (ppEnum.Next(1, pPins, IntPtr.Zero) >= 0) { try { // Read the direction PinDirection ppindir; hr = pPins[0].QueryDirection(out ppindir); if (hr >= 0) { // Is it the right direction? if (ppindir == PinDirection.Output) { if (pPins[0] != null) { UnRender(pPins[0]); } } } } finally { Marshal.ReleaseComObject(pPins[0]); } } } finally { Marshal.ReleaseComObject(ppEnum); } } hr = graphBuilder.RemoveFilter(pInfo.filter); } finally { Marshal.ReleaseComObject(pInfo.filter); } } } } finally { Marshal.ReleaseComObject(pinOutEnd); } } }
/// <summary> /// helper function to connect 2 filters /// </summary> /// <param name="graphBuilder">graph builder interface</param> /// <param name="pinSource">souce pin</param> /// <param name="filterDest">destination filter</param> /// <param name="destPinIndex">input pin index</param> public static bool ConnectPin(IGraphBuilder graphBuilder, IPin pinSource, IBaseFilter filterDest, int destPinIndex) { IPin pin; pinSource.ConnectedTo(out pin); if (pin != null) { Release.ComObject("Connect Pin", pin); return false; } IPin pinDest = DsFindPin.ByDirection(filterDest, PinDirection.Input, destPinIndex); if (pinDest == null) return false; int hr = graphBuilder.Connect(pinSource, pinDest); if (hr != 0) { Release.ComObject("Connect Pin", pinDest); return false; } Release.ComObject("Connect Pin", pinDest); return true; }
private void UnRender(IPin pinOutOrigin) { int hr; //hr = pinOutOrigin.Disconnect(); IPin pinOutEnd = null; hr = pinOutOrigin.ConnectedTo(out pinOutEnd); if (pinOutEnd != null) { try { PinInfo pInfo = new PinInfo(); hr = pinOutEnd.QueryPinInfo(out pInfo); if (hr >= 0) { if (pInfo.filter != null) { try { IEnumPins ppEnum; hr = pInfo.filter.EnumPins(out ppEnum); if (hr >= 0) { try { // Walk the pins looking for a match IPin[] pPins = new IPin[1]; //22 int lFetched; //22 while ((ppEnum.Next(1, pPins, out lFetched) >= 0) && (lFetched == 1)) while (ppEnum.Next(1, pPins, IntPtr.Zero) >= 0) { try { // Read the direction PinDirection ppindir; hr = pPins[0].QueryDirection(out ppindir); if (hr >= 0) { // Is it the right direction? if (ppindir == PinDirection.Output) { if (pPins[0] != null) { UnRender(pPins[0]); } } } } finally { Marshal.ReleaseComObject(pPins[0]); } } } finally { Marshal.ReleaseComObject(ppEnum); } } hr = graphBuilder.RemoveFilter(pInfo.filter); } finally { Marshal.ReleaseComObject(pInfo.filter); } } } } finally { Marshal.ReleaseComObject(pinOutEnd); } } }
/// <summary> /// Logs the pin info. /// </summary> /// <param name="pin">The pin.</param> /// <returns></returns> public static string LogPinInfo(IPin pin) { if (pin == null) return " pin==null "; PinInfo pinInfo; IPin connectedToPin; if (pin.ConnectedTo(out connectedToPin) != 0) connectedToPin = null; bool connected = connectedToPin != null; if (connected) Release.ComObject(connectedToPin); int hr = pin.QueryPinInfo(out pinInfo); if (hr == 0) { if (pinInfo.filter != null) Release.ComObject(pinInfo.filter); } return String.Format("name:{0} [{3}/{4}] Direction:{1} Connected:{2}", pinInfo.name, pinInfo.dir, connected, getRefCount(pin), getRefCountCOM(pin)); }
private bool IsMatchingPin(IPin pin, PinDirection direction, Guid mediaType) { PinDirection pinDirection; int hr = pin.QueryDirection(out pinDirection); DsError.ThrowExceptionForHR(hr); if (pinDirection != direction) // The pin lacks direction return false; IPin connectedPin; hr = pin.ConnectedTo(out connectedPin); if ((uint)hr != 0x80040209 /* Pin is not connected */) DsError.ThrowExceptionForHR(hr); if (connectedPin != null) { // The pin is already connected Marshal.ReleaseComObject(connectedPin); return false; } IEnumMediaTypes mediaTypesEnum; hr = pin.EnumMediaTypes(out mediaTypesEnum); DsError.ThrowExceptionForHR(hr); AMMediaType[] mediaTypes = new AMMediaType[1]; while (mediaTypesEnum.Next(1, mediaTypes, IntPtr.Zero) == 0) { Guid majorType = mediaTypes[0].majorType; DsUtils.FreeAMMediaType(mediaTypes[0]); if (majorType == mediaType) { // We have found the pin we were looking for return true; } } return false; }
public static bool DisconnectPin(IGraphBuilder graphBuilder, IPin pin) { IPin other; int hr = pin.ConnectedTo(out other); bool allDisconnected = true; PinInfo info; pin.QueryPinInfo(out info); DsUtils.FreePinInfo(info); if (hr == 0 && other != null) { other.QueryPinInfo(out info); if (!DisconnectAllPins(graphBuilder, info.filter)) { allDisconnected = false; } hr = pin.Disconnect(); if (hr != 0) { allDisconnected = false; } hr = other.Disconnect(); if (hr != 0) { allDisconnected = false; } DsUtils.FreePinInfo(info); Marshal.ReleaseComObject(other); } else { } return allDisconnected; }
/// <summary> /// Disconnects a single Pin. /// </summary> /// <param name="graphBuilder">IGraphBuilder</param> /// <param name="pin">Pin to disconnect</param> /// <returns>True if successful</returns> bool DisconnectPin(IGraphBuilder graphBuilder, IPin pin) { IntPtr other_ptr; int hr = pin.ConnectedTo(out other_ptr); bool allDisconnected = true; if (hr == 0 && other_ptr != IntPtr.Zero) { IPin other = Marshal.GetObjectForIUnknown(other_ptr) as IPin; PinInfo info; pin.QueryPinInfo(out info); ServiceRegistration.Get<ILogger>().Info("Disconnecting pin {0}", info.name); FilterGraphTools.FreePinInfo(info); other.QueryPinInfo(out info); if (!DisconnectAllPins(graphBuilder, info.filter)) allDisconnected = false; FilterGraphTools.FreePinInfo(info); hr = pin.Disconnect(); if (hr != 0) { allDisconnected = false; ServiceRegistration.Get<ILogger>().Error("Error disconnecting: {0:x}", hr); } hr = other.Disconnect(); if (hr != 0) { allDisconnected = false; ServiceRegistration.Get<ILogger>().Error("Error disconnecting other: {0:x}", hr); } Marshal.ReleaseComObject(other); } else { ServiceRegistration.Get<ILogger>().Info(" Not connected"); } return allDisconnected; }
/// <summary> build the capture graph for grabber. </summary> private void SetupGraph(string FileName) { int hr; // Get the graphbuilder object this.graphBuilder = new FilterGraph() as IGraphBuilder; this.mediaControl = this.graphBuilder as IMediaControl; this.mediaSeeking = this.graphBuilder as IMediaSeeking; this.mediaEvent = this.graphBuilder as IMediaEvent; try { // Get the SampleGrabber interface this.sampleGrabber = new SampleGrabber() as ISampleGrabber; this.sampleGrabberFilter = sampleGrabber as IBaseFilter; ConfigureSampleGrabber(sampleGrabber); // Add the frame grabber to the graph hr = graphBuilder.AddFilter(sampleGrabberFilter, "Ds.NET Sample Grabber"); DsError.ThrowExceptionForHR(hr); IBaseFilter aviSplitter = new AviSplitter() as IBaseFilter; // Add the aviSplitter to the graph hr = graphBuilder.AddFilter(aviSplitter, "Splitter"); DsError.ThrowExceptionForHR(hr); // Have the graph builder construct its appropriate graph automatically hr = this.graphBuilder.RenderFile(FileName, null); DsError.ThrowExceptionForHR(hr); #if DEBUG m_rot = new DsROTEntry(graphBuilder); #endif // Remove the video renderer filter IBaseFilter defaultVideoRenderer = null; graphBuilder.FindFilterByName("Video Renderer", out defaultVideoRenderer); graphBuilder.RemoveFilter(defaultVideoRenderer); // Disconnect anything that is connected // to the output of the sample grabber IPin iPinSampleGrabberOut = DsFindPin.ByDirection(sampleGrabberFilter, PinDirection.Output, 0); IPin iPinVideoIn; hr = iPinSampleGrabberOut.ConnectedTo(out iPinVideoIn); if (hr == 0) { // Disconnect the sample grabber output from the attached filters hr = iPinVideoIn.Disconnect(); DsError.ThrowExceptionForHR(hr); hr = iPinSampleGrabberOut.Disconnect(); DsError.ThrowExceptionForHR(hr); } else { // Try other way round because automatic renderer could not build // graph including the sample grabber IPin iPinAVISplitterOut = DsFindPin.ByDirection(aviSplitter, PinDirection.Output, 0); IPin iPinAVISplitterIn; hr = iPinAVISplitterOut.ConnectedTo(out iPinAVISplitterIn); DsError.ThrowExceptionForHR(hr); hr = iPinAVISplitterOut.Disconnect(); DsError.ThrowExceptionForHR(hr); hr = iPinAVISplitterIn.Disconnect(); DsError.ThrowExceptionForHR(hr); // Connect the avi splitter output to sample grabber IPin iPinSampleGrabberIn = DsFindPin.ByDirection(sampleGrabberFilter, PinDirection.Input, 0); hr = graphBuilder.Connect(iPinAVISplitterOut, iPinSampleGrabberIn); DsError.ThrowExceptionForHR(hr); } // Add the null renderer to the graph nullrenderer = new NullRenderer() as IBaseFilter; hr = graphBuilder.AddFilter(nullrenderer, "Null renderer"); DsError.ThrowExceptionForHR(hr); // Get the input pin of the null renderer IPin iPinNullRendererIn = DsFindPin.ByDirection(nullrenderer, PinDirection.Input, 0); // Connect the sample grabber to the null renderer hr = graphBuilder.Connect(iPinSampleGrabberOut, iPinNullRendererIn); DsError.ThrowExceptionForHR(hr); // Read and cache the image sizes SaveSizeInfo(sampleGrabber); this.GetFrameStepInterface(); } finally { } }
public void ReloadFilters() { log("reload filters.."); IEnumFilters ef; ClearFiltersSelection(); ClearConnections(); filter_positions.Clear(); foreach (Filter f in filters) { filter_positions.Add(f.Name, f.Coords); } filters.Clear(); log("reload_filters 1"); try { int hr = graphBuilder.EnumFilters(out ef); DsError.ThrowExceptionForHR(hr); IBaseFilter[] fs = new IBaseFilter[1]; IntPtr fetched = Marshal.AllocHGlobal(4); while ((hr = ef.Next(1, fs, fetched)) == 0) { log("reload_filters 2"); FilterInfo fi; fs[0].QueryFilterInfo(out fi); log("reload_filters: " + fi.achName); Filter ff = FindFilterByName(fi.achName); if (ff == null) //not found { ff = new Filter(fs[0]); AddFilterHere(ff, false, null); history.AddFilterIfNew(ff.filterProps, ff.Name, ff.srcFileName, ff.dstFileName, ff); } else { ff.ReloadPins(); } log("reload_filters 3"); foreach (Pin pin in ff.Pins) { log("reload_filters 4: " + pin.Name); IPin ip = pin.IPin, connected_ipin; hr = ip.ConnectedTo(out connected_ipin); if (hr != 0) { continue; } PinInfo cpi; connected_ipin.QueryPinInfo(out cpi); FilterInfo cfi; cpi.filter.QueryFilterInfo(out cfi); Filter connected_filter = FindFilterByName(cfi.achName); if (connected_filter != null) { Pin cp = connected_filter.FindPinByName(connected_filter.Name + "." + cpi.name); if (cp != null) { string con_uniqname = (pin.Direction == PinDirection.Input) ? cp.UniqName + "-" + pin.UniqName : pin.UniqName + "-" + cp.UniqName; PinConnection con = FindConnectionByName(con_uniqname); if (con == null) { if (pin.Direction == PinDirection.Input) { Connect(cp, pin); } else { Connect(pin, cp); } } } } DsUtils.FreePinInfo(cpi); } } Marshal.FreeHGlobal(fetched); if (hr < 0) { DsError.ThrowExceptionForHR(hr); } } catch (COMException e) { ShowCOMException(e, "Error while enumerating filters in the graph"); return; } /*catch (Exception e) * { * MessageBox.Show(e.Message, "Error while enumerating filters in the graph"); * return; * }*/ log("reload_filters: almost done"); history.CommitAdded(); log("reload_filters: done"); }
/// <summary> /// Find all the filters connected downstream from the specified pin, /// following all branches. /// </summary> /// <param name="pin"></param> /// <returns></returns> private List<IBaseFilter> EnumerateDownstreamFromPin(IPin pin) { //Find the input pin that the target pin is connected to. IPin connectedToInput; try { pin.ConnectedTo(out connectedToInput); } catch (COMException) { //not connected return new List<IBaseFilter>(); } // Map that pin to the next filter. _PinInfo pInfo; connectedToInput.QueryPinInfo(out pInfo); IBaseFilter connectedFilter = pInfo.pFilter; //Add the filter to the list. List<IBaseFilter> returnList = new List<IBaseFilter>(); returnList.Add(connectedFilter); //Enumerate output pins of the filter ArrayList outPins = Filter.GetPins(Filter.GetPins(connectedFilter), _PinDirection.PINDIR_OUTPUT); foreach (IPin p in outPins) { //recurse over each pin returnList.AddRange(EnumerateDownstreamFromPin(p)); } return returnList; }
/* * protected void InitAudioSampleGrabber() * { * // Get the graph builder * IGraphBuilder graphBuilder = (mediaControl as IGraphBuilder); * if (graphBuilder == null) * return; * * try * { * // Build the sample grabber * sampleGrabber = Activator.CreateInstance(Type.GetTypeFromCLSID(Filters.SampleGrabber, true)) * as ISampleGrabber; * * if (sampleGrabber == null) * return; * * // Add it to the filter graph * int hr = graphBuilder.AddFilter(sampleGrabber as IBaseFilter, "ProTONE_SampleGrabber"); * DsError.ThrowExceptionForHR(hr); * * AMMediaType mtAudio = new AMMediaType(); * mtAudio.majorType = MediaType.Audio; * mtAudio.subType = MediaSubType.PCM; * mtAudio.formatPtr = IntPtr.Zero; * * _actualAudioFormat = null; * * hr = sampleGrabber.SetMediaType(mtAudio); * DsError.ThrowExceptionForHR(hr); * * hr = sampleGrabber.SetBufferSamples(true); * DsError.ThrowExceptionForHR(hr); * * hr = sampleGrabber.SetOneShot(false); * DsError.ThrowExceptionForHR(hr); * * hr = sampleGrabber.SetCallback(this, 1); * DsError.ThrowExceptionForHR(hr); * * sampleAnalyzerMustStop.Reset(); * sampleAnalyzerThread = new Thread(new ThreadStart(SampleAnalyzerLoop)); * sampleAnalyzerThread.Priority = ThreadPriority.Highest; * sampleAnalyzerThread.Start(); * } * catch(Exception ex) * { * Logger.LogException(ex); * } * * rotEntry = new DsROTEntry(graphBuilder as IFilterGraph); * }*/ protected void InitAudioSampleGrabber_v2() { // Get the graph builder IGraphBuilder graphBuilder = (mediaControl as IGraphBuilder); if (graphBuilder == null) { return; } try { // Build the sample grabber sampleGrabber = Activator.CreateInstance(Type.GetTypeFromCLSID(Filters.SampleGrabber, true)) as ISampleGrabber; if (sampleGrabber == null) { return; } // Add it to the filter graph int hr = graphBuilder.AddFilter(sampleGrabber as IBaseFilter, "ProTONE_SampleGrabber_v2"); DsError.ThrowExceptionForHR(hr); IBaseFilter ffdAudioDecoder = null; IPin ffdAudioDecoderOutput = null; IPin soundDeviceInput = null; IPin sampleGrabberInput = null; IPin sampleGrabberOutput = null; IntPtr pSoundDeviceInput = IntPtr.Zero; // When using FFDShow, typically we'll find // a ffdshow Audio Decoder connected to the sound device filter // // i.e. [ffdshow Audio Decoder] --> [DirectSound Device] // // Our audio sample grabber supports only PCM sample input and output. // Its entire processing is based on this assumption. // // Thus need to insert the audio sample grabber between the ffdshow Audio Decoder and the sound device // because this is the only place where we can find PCM samples. The sound device only accepts PCM. // // So we need to turn this graph: // // .. -->[ffdshow Audio Decoder]-->[DirectSound Device] // // into this: // // .. -->[ffdshow Audio Decoder]-->[Sample grabber]-->[DirectSound Device] // // Actions to do to achieve the graph change: // // 1. Locate the ffdshow Audio Decoder in the graph // 2. Find its output pin and the pin that it's connected to // 3. Locate the input and output pins of sample grabber // 4. Disconnect the ffdshow Audio Decoder and its correspondent (sound device input pin) // 5. Connect the ffdshow Audio Decoder to sample grabber input // 6. Connect the sample grabber output to sound device input // that's all. // -------------- // 1. Locate the ffdshow Audio Decoder in the graph hr = graphBuilder.FindFilterByName("ffdshow Audio Decoder", out ffdAudioDecoder); DsError.ThrowExceptionForHR(hr); // 2. Find its output pin and the pin that it's connected to hr = ffdAudioDecoder.FindPin("Out", out ffdAudioDecoderOutput); DsError.ThrowExceptionForHR(hr); hr = ffdAudioDecoderOutput.ConnectedTo(out pSoundDeviceInput); DsError.ThrowExceptionForHR(hr); soundDeviceInput = new DSPin(pSoundDeviceInput).Value; // 3. Locate the input and output pins of sample grabber hr = (sampleGrabber as IBaseFilter).FindPin("In", out sampleGrabberInput); DsError.ThrowExceptionForHR(hr); hr = (sampleGrabber as IBaseFilter).FindPin("Out", out sampleGrabberOutput); DsError.ThrowExceptionForHR(hr); // 4. Disconnect the ffdshow Audio Decoder and its correspondent (sound device input pin) hr = ffdAudioDecoderOutput.Disconnect(); DsError.ThrowExceptionForHR(hr); hr = soundDeviceInput.Disconnect(); DsError.ThrowExceptionForHR(hr); // 5. Connect the ffdshow Audio Decoder to sample grabber input hr = graphBuilder.Connect(ffdAudioDecoderOutput, sampleGrabberInput); DsError.ThrowExceptionForHR(hr); // 6. Connect the sample grabber output to sound device input hr = graphBuilder.Connect(sampleGrabberOutput, soundDeviceInput); DsError.ThrowExceptionForHR(hr); AMMediaType mtAudio = new AMMediaType(); mtAudio.majorType = MediaType.Audio; mtAudio.subType = MediaSubType.PCM; mtAudio.formatPtr = IntPtr.Zero; _actualAudioFormat = null; sampleGrabber.SetMediaType(mtAudio); sampleGrabber.SetBufferSamples(true); sampleGrabber.SetOneShot(false); sampleGrabber.SetCallback(this, 1); sampleAnalyzerMustStop.Reset(); sampleAnalyzerThread = new Thread(new ThreadStart(SampleAnalyzerLoop)); sampleAnalyzerThread.Priority = ThreadPriority.Highest; sampleAnalyzerThread.Start(); } catch (Exception ex) { Logger.LogException(ex); } rotEntry = new DsROTEntry(graphBuilder as IFilterGraph); }
public int RebuildPin(IFilterGraph pGraph, IPin pPin) { //Set codec bool to false ResetCodecBool(); IPin pinTo; if (pPin != null) { int hr = pPin.ConnectedTo(out pinTo); if (hr >= 0 && pinTo != null) { PinInfo pInfo; pinTo.QueryPinInfo(out pInfo); FilterInfo fInfo; pInfo.filter.QueryFilterInfo(out fInfo); if (pPin != null) { RebuildMediaType(pPin); Log.Debug("VideoPlayer9: Rebuild LAV Delegate Info filter Name - {0}", fInfo.achName); if (MediatypeVideo) { //Video Part if (h264Codec) { if (fInfo.achName == filterConfig.VideoH264) { RebuildRelease(pInfo, fInfo, pinTo, pPin); return 1; } } else if (vc1Codec) { if (fInfo.achName == filterConfig.VideoVC1) { RebuildRelease(pInfo, fInfo, pinTo, pPin); return 1; } } else if (vc1ICodec) { if (fInfo.achName == filterConfig.VideoVC1I) { RebuildRelease(pInfo, fInfo, pinTo, pPin); return 1; } } else if (xvidCodec) { if (fInfo.achName == filterConfig.VideoXVID) { RebuildRelease(pInfo, fInfo, pinTo, pPin); return 1; } } else if (fInfo.achName == filterConfig.Video) { RebuildRelease(pInfo, fInfo, pinTo, pPin); return 1; } iChangedMediaTypes = 2; DoGraphRebuild(); Log.Debug("VideoPlayer9: Rebuild LAV Delegate filter Video"); RebuildRelease(pInfo, fInfo, pinTo, pPin); return 1; } else if (MediatypeAudio) { //Audio Part if (aacCodec) { if (fInfo.achName == filterConfig.AudioAAC) { RebuildRelease(pInfo, fInfo, pinTo, pPin); return 1; } } if (aacCodecLav && fInfo.achName == LAV_AUDIO) { if (fInfo.achName == filterConfig.AudioAAC) { RebuildRelease(pInfo, fInfo, pinTo, pPin); return 1; } } else if ((!aacCodecLav || !aacCodec) && fInfo.achName == filterConfig.Audio) { RebuildRelease(pInfo, fInfo, pinTo, pPin); return 1; } iChangedMediaTypes = 1; DoGraphRebuild(); Log.Debug("VideoPlayer9: Rebuild LAV Delegate filter Audio"); RebuildRelease(pInfo, fInfo, pinTo, pPin); return 1; } else if (MediatypeSubtitle) { RebuildRelease(pInfo, fInfo, pinTo, pPin); return -1; } } DsUtils.FreePinInfo(pInfo); DirectShowUtil.ReleaseComObject(fInfo.pGraph); DirectShowUtil.ReleaseComObject(pinTo); pinTo = null; } DirectShowUtil.ReleaseComObject(pPin); pPin = null; } Log.Debug("VideoPlayer9: Rebuild LAV Delegate (No Rebuild from MP, LAV Will doing the job)"); return -1; }
public static IBaseFilter AddToGraph(IGraphBuilder graphBuilder) { IBaseFilter vob = null; using (Settings xmlreader = new MPSettings()) { string engineType = xmlreader.GetValueAsString("subtitles", "engine", "DirectVobSub"); XySubFilter = engineType.Equals("XySubFilter"); } if (!XySubFilter) { DirectShowUtil.FindFilterByClassID(graphBuilder, ClassId.DirectVobSubAutoload, out vob); if (vob == null) { //Try the "normal" filter then. DirectShowUtil.FindFilterByClassID(graphBuilder, ClassId.DirectVobSubNormal, out vob); } } else { //Try the XySubFilter "autoload" filter. DirectShowUtil.FindFilterByClassID(graphBuilder, ClassId.XySubFilterAutoload, out vob); if (vob != null) { return(vob); } //Try the XySubFilter "normal" filter then. DirectShowUtil.FindFilterByClassID(graphBuilder, ClassId.XySubFilterNormal, out vob); if (vob != null) { return(vob); } vob = DirectShowUtil.AddFilterToGraph(graphBuilder, "XySubFilter"); if (vob == null) { Log.Warn("VideoPlayerVMR9: DirectVobSub or XySubFilter filter not found! You need to install XySubFilter"); return(null); } Log.Debug("VideoPlayerVMR9: VobSub filter added to graph"); return(vob); } //if the directvobsub filter has not been added to the graph. (i.e. with evr) //we add a bit more intelligence to determine if subtitles are enabled. //and if subtitles are present for the video / movie then we add it if necessary to the graph. if (vob == null) { Log.Info("VideoPlayerVMR9: No VobSub filter in the current graph"); //the filter has not been added lets check if it should be added or not. //add the filter to the graph vob = DirectShowUtil.AddFilterToGraph(graphBuilder, "DirectVobSub"); if (vob == null) { Log.Warn("VideoPlayerVMR9: DirectVobSub or XySubFilter filter not found! You need to install VSFilter"); return(null); } Log.Debug("VideoPlayerVMR9: VobSub filter added to graph"); } else // VobSub already loaded { return(vob); } // Check if Haali Media Splitter is in the graph. IBaseFilter hms = null; DirectShowUtil.FindFilterByClassID(graphBuilder, ClassId.HaaliGuid, out hms); if (hms == null) { DirectShowUtil.FindFilterByClassID(graphBuilder, ClassId.MPCMatroska, out hms); } if (hms == null) { DirectShowUtil.FindFilterByClassID(graphBuilder, ClassId.MPCMatroskaSource, out hms); } if (hms == null) { DirectShowUtil.FindFilterByClassID(graphBuilder, ClassId.LAVFilter, out hms); } if (hms == null) { DirectShowUtil.FindFilterByClassID(graphBuilder, ClassId.LAVFilterSource, out hms); } if (hms != null) { IPin pinSubTo = null; // It is. Connect it' subtitle output pin (if any) to Vobsub's subtitle input. pinSubTo = DirectShowUtil.FindPin(hms, PinDirection.Output, "Subtitle"); if (pinSubTo == null) { while (true) { IPin freeSubtitle = DirectShowUtil.FindFirstFreePinSub(hms, PinDirection.Output, ""); IPin freeVobSub = DirectShowUtil.FindFirstFreePin(vob, PinDirection.Input, "Input"); if (freeSubtitle != null && freeVobSub != null) { Log.Debug("VideoPlayerVMR9: Connecting Matroska's subtitle output to VobSub's input."); graphBuilder.Connect(freeSubtitle, freeVobSub); DirectShowUtil.ReleaseComObject(freeSubtitle); freeSubtitle = null; DirectShowUtil.ReleaseComObject(freeVobSub); freeVobSub = null; } else { break; } } } DirectShowUtil.ReleaseComObject(hms); hms = null; if (pinSubTo != null) { Log.Debug("VideoPlayerVMR9: Connecting Haali's subtitle output to VobSub's input."); // Try to render pins IPin pinVobSubSub = DirectShowUtil.FindPin(vob, PinDirection.Input, "Input"); // If pinSubTo is already connected (disconnect it) graphBuilder.Disconnect(pinSubTo); graphBuilder.Connect(pinSubTo, pinVobSubSub); DirectShowUtil.ReleaseComObject(pinSubTo); pinSubTo = null; DirectShowUtil.ReleaseComObject(pinVobSubSub); pinVobSubSub = null; } } // Now check if vobsub's video input is not connected. // Check only if vmr9 is connected (render was successful). VMR9Util Vmr9 = VMR9Util.g_vmr9; if (Vmr9.IsVMR9Connected) { Log.Debug("VideoPlayerVMR9: Connect VobSub's video pins"); IPin pinVobSubVideoIn = DsFindPin.ByDirection(vob, PinDirection.Input, 0); IPin pinVobSubVideoOut = DsFindPin.ByDirection(vob, PinDirection.Output, 0); // This is the pin that we will connect to vobsub's input. IPin pinVideoTo = Vmr9.PinConnectedTo; IPin pinVideoFrom = null; pinVideoTo.ConnectedTo(out pinVideoFrom); pinVideoTo.Disconnect(); pinVideoFrom.Disconnect(); //Now make connection to VobSub int hr = graphBuilder.Connect(pinVideoTo, pinVobSubVideoIn); //hr = graphBuilder.Render(pinVideoFrom); if (hr != 0) { Log.Error("VideoPlayerVMR9: could not connect Vobsub's input video pin"); return(null); } hr = graphBuilder.Connect(pinVobSubVideoOut, pinVideoFrom); //hr = graphBuilder.Render(pinVobSubVideoOut); if (hr != 0) { Log.Error("VideoPlayerVMR9: could not connect Vobsub's output video pin"); return(null); } Log.Debug("VideoPlayerVMR9: Vobsub's video pins connected"); DirectShowUtil.ReleaseComObject(pinVideoTo); pinVideoTo = null; DirectShowUtil.ReleaseComObject(pinVobSubVideoIn); pinVobSubVideoIn = null; DirectShowUtil.ReleaseComObject(pinVobSubVideoOut); pinVobSubVideoOut = null; DirectShowUtil.ReleaseComObject(pinVideoFrom); pinVideoFrom = null; } Vmr9 = null; return(vob); }
private static bool HasConnection(IPin pin) { IPin pinInConnected; int hr = pin.ConnectedTo(out pinInConnected); if (hr != 0 || pinInConnected == null) { return false; } else { ReleaseComObject(pinInConnected); return true; } }
public static VideoInfoHeader2 GetSBEFrameSize(string pathToFile) { int hr = 0; IGraphBuilder graph = null; IBaseFilter capFilter = null; IBaseFilter nRender = null; try { graph = (IGraphBuilder) new FilterGraph(); hr = graph.AddSourceFilter(pathToFile, "Source", out capFilter); DsError.ThrowExceptionForHR(hr); #if DEBUG using (DsROTEntry rot = new DsROTEntry(graph)) { #endif IPin vPin = null; IBaseFilter dec = null; IPin sgIn = null; IBaseFilter mpegDec = null; try { dec = (IBaseFilter) new DTFilter(); hr = graph.AddFilter(dec, "Decrypt"); DsError.ThrowExceptionForHR(hr); nRender = (IBaseFilter) new NullRenderer(); hr = graph.AddFilter((IBaseFilter)nRender, "Video Null Renderer"); DsError.ThrowExceptionForHR(hr); IBaseFilter dec1 = FilterDefinition.AddToFilterGraph(FatAttitude.WTVTranscoder.FilterDefinitions.Decrypt.DTFilterPBDA, ref graph, "Decrypt1"); if (dec1 != null) { Marshal.ReleaseComObject(dec1); } dec1 = null; mpegDec = FilterDefinition.AddToFilterGraph(FatAttitude.WTVTranscoder.FilterDefinitions.Video.VideoDecoderMpeg, ref graph, "MS MPEG Decoder"); sgIn = DsFindPin.ByDirection(mpegDec, PinDirection.Input, 0); IEnumPins ppEnum; IPin[] pPins = new IPin[1]; hr = capFilter.EnumPins(out ppEnum); DsError.ThrowExceptionForHR(hr); try { while (ppEnum.Next(1, pPins, IntPtr.Zero) == 0) { IEnumMediaTypes emtDvr = null; AMMediaType[] amtDvr = new AMMediaType[1]; try { pPins[0].EnumMediaTypes(out emtDvr); hr = emtDvr.Next(1, amtDvr, IntPtr.Zero); DsError.ThrowExceptionForHR(hr); if (amtDvr[0].majorType == MediaType.Video) { if (graph.Connect(pPins[0], sgIn) >= 0) { vPin = pPins[0]; break; } } if (pPins[0] != null) { Marshal.ReleaseComObject(pPins[0]); } } finally { if (emtDvr != null) { Marshal.ReleaseComObject(emtDvr); } DsUtils.FreeAMMediaType(amtDvr[0]); } } } finally { if (ppEnum != null) { Marshal.ReleaseComObject(ppEnum); } } FilterGraphTools.RenderPin(graph, mpegDec, "Video Output 1"); } finally { if (vPin != null) { Marshal.ReleaseComObject(vPin); } if (dec != null) { Marshal.ReleaseComObject(dec); } if (sgIn != null) { Marshal.ReleaseComObject(sgIn); } if (mpegDec != null) { Marshal.ReleaseComObject(mpegDec); } } EventCode ec; IMediaControl mControl = graph as IMediaControl; IMediaEvent mEvent = graph as IMediaEvent; hr = mControl.Pause(); DsError.ThrowExceptionForHR(hr); hr = mControl.Run(); DsError.ThrowExceptionForHR(hr); hr = mEvent.WaitForCompletion(1000, out ec); //DsError.ThrowExceptionForHR(hr); hr = mControl.Pause(); DsError.ThrowExceptionForHR(hr); hr = mControl.Stop(); DsError.ThrowExceptionForHR(hr); IPin mpgOut = null; sgIn = null; AMMediaType mt = new AMMediaType(); try { sgIn = DsFindPin.ByDirection(nRender, PinDirection.Input, 0); if (sgIn != null) { hr = sgIn.ConnectedTo(out mpgOut); DsError.ThrowExceptionForHR(hr); hr = graph.RemoveFilter(nRender); DsError.ThrowExceptionForHR(hr); Marshal.ReleaseComObject(nRender); nRender = null; nRender = (IBaseFilter) new NullRenderer(); hr = graph.AddFilter((IBaseFilter)nRender, "Video Null Renderer"); DsError.ThrowExceptionForHR(hr); hr = graph.Render(mpgOut); DsError.ThrowExceptionForHR(hr); hr = mpgOut.ConnectionMediaType(mt); DsError.ThrowExceptionForHR(hr); if (mt.formatType == FormatType.VideoInfo2) { VideoInfoHeader2 vih = (VideoInfoHeader2)Marshal.PtrToStructure(mt.formatPtr, typeof(VideoInfoHeader2)); return(vih); } } } finally { DsUtils.FreeAMMediaType(mt); if (mpgOut != null) { Marshal.ReleaseComObject(mpgOut); } if (sgIn != null) { Marshal.ReleaseComObject(sgIn); } } #if DEBUG } #endif } finally { if (nRender != null) { Marshal.ReleaseComObject(nRender); } if (capFilter != null) { Marshal.ReleaseComObject(capFilter); } if (graph != null) { while (Marshal.ReleaseComObject(graph) > 0) { ; } } } return(null); }
public static void RemoveFromGraph(IGraphBuilder graphBuilder) { IBaseFilter vob = null; using (Settings xmlreader = new MPSettings()) { string engineType = xmlreader.GetValueAsString("subtitles", "engine", "DirectVobSub"); XySubFilter = engineType.Equals("XySubFilter"); } if (!XySubFilter) { DirectShowUtil.FindFilterByClassID(graphBuilder, ClassId.DirectVobSubAutoload, out vob); if (vob == null) { //Try the "normal" filter then. DirectShowUtil.FindFilterByClassID(graphBuilder, ClassId.DirectVobSubNormal, out vob); } } if (vob == null) { DirectShowUtil.FindFilterByClassID(graphBuilder, ClassId.XySubFilterAutoload, out vob); if (vob != null) { //remove the XySubFilter filter from the graph graphBuilder.RemoveFilter(vob); DirectShowUtil.ReleaseComObject(vob); vob = null; return; } //Try the XySubFilter "normal" filter then. DirectShowUtil.FindFilterByClassID(graphBuilder, ClassId.XySubFilterNormal, out vob); if (vob != null) { //remove the XySubFilter filter from the graph graphBuilder.RemoveFilter(vob); DirectShowUtil.ReleaseComObject(vob); vob = null; } return; } Log.Info("VideoPlayerVMR9: DirectVobSub in graph, removing..."); // Check where video inputs are connected IPin pinVideoIn = DsFindPin.ByDirection(vob, PinDirection.Input, 0); IPin pinVideoOut = DsFindPin.ByDirection(vob, PinDirection.Output, 0); //find directvobsub's video output pin source input pin IPin pinVideoTo = null; if (pinVideoOut != null) { pinVideoOut.ConnectedTo(out pinVideoTo); } //find directvobsub's video input pin source output pin IPin pinVideoFrom = null; if (pinVideoIn != null) { pinVideoIn.ConnectedTo(out pinVideoFrom); } int hr = 0; if (pinVideoFrom != null) { hr = pinVideoFrom.Disconnect(); if (hr != 0) { Log.Error("VideoPlayerVMR9: DirectVobSub failed disconnecting source pin"); } } if (pinVideoTo != null) { hr = pinVideoTo.Disconnect(); if (hr != 0) { Log.Error("VideoPlayerVMR9: DirectVobSub failed disconnecting destination pin"); } } //remove the DirectVobSub filter from the graph graphBuilder.RemoveFilter(vob); DirectShowUtil.ReleaseComObject(vob); vob = null; //reconnect the source output pin to the vmr9/evr filter if (pinVideoFrom != null) { if (pinVideoTo != null) { hr = graphBuilder.Connect(pinVideoFrom, pinVideoTo); } //hr = graphBuilder.Render(pinVideoFrom); DirectShowUtil.ReleaseComObject(pinVideoFrom); pinVideoFrom = null; } if (pinVideoTo != null) { DirectShowUtil.ReleaseComObject(pinVideoTo); pinVideoTo = null; } if (pinVideoOut != null) { DirectShowUtil.ReleaseComObject(pinVideoOut); pinVideoOut = null; } if (pinVideoIn != null) { DirectShowUtil.ReleaseComObject(pinVideoIn); pinVideoIn = null; } if (hr != 0) { Log.Error("VideoPlayerVMR9: Could not connect video out to video renderer: {0}", hr); } else { Log.Debug("VideoPlayerVMR9: DirectVobSub graph rebuild finished"); } }
private void SetupSampleGrabber() { if (_graph == null) { return; } int hr; //Get directsound filter IBaseFilter directSoundFilter; hr = _graph.FindFilterByName(DEFAULT_AUDIO_RENDERER_NAME, out directSoundFilter); DsError.ThrowExceptionForHR(hr); IPin rendererPinIn = DsFindPin.ByConnectionStatus(directSoundFilter, PinConnectedStatus.Connected, 0); if (rendererPinIn != null) { IPin audioPinOut; hr = rendererPinIn.ConnectedTo(out audioPinOut); DsError.ThrowExceptionForHR(hr); if (audioPinOut != null) { //Disconect audio decoder to directsound renderer hr = audioPinOut.Disconnect(); DsError.ThrowExceptionForHR(hr); hr = _graph.RemoveFilter(directSoundFilter); DsError.ThrowExceptionForHR(hr); //Add Sample Grabber ISampleGrabber sampleGrabber = new SampleGrabber() as ISampleGrabber; hr = sampleGrabber.SetCallback(this, 1); DsError.ThrowExceptionForHR(hr); AMMediaType media; media = new AMMediaType(); media.majorType = MediaType.Audio; media.subType = MediaSubType.PCM; media.formatType = FormatType.WaveEx; hr = sampleGrabber.SetMediaType(media); DsError.ThrowExceptionForHR(hr); IPin sampleGrabberPinIn = DsFindPin.ByDirection((IBaseFilter)sampleGrabber, PinDirection.Input, 0); IPin sampleGrabberPinOut = DsFindPin.ByDirection((IBaseFilter)sampleGrabber, PinDirection.Output, 0); hr = _graph.AddFilter((IBaseFilter)sampleGrabber, "SampleGrabber"); DsError.ThrowExceptionForHR(hr); PinInfo pinInfo; hr = audioPinOut.QueryPinInfo(out pinInfo); DsError.ThrowExceptionForHR(hr); FilterInfo filterInfo; hr = pinInfo.filter.QueryFilterInfo(out filterInfo); DsError.ThrowExceptionForHR(hr); hr = _graph.Connect(audioPinOut, sampleGrabberPinIn); DsError.ThrowExceptionForHR(hr); //Add null renderer NullRenderer nullRenderer = new NullRenderer(); hr = _graph.AddFilter((IBaseFilter)nullRenderer, "NullRenderer"); DsError.ThrowExceptionForHR(hr); IPin nullRendererPinIn = DsFindPin.ByDirection((IBaseFilter)nullRenderer, PinDirection.Input, 0); hr = _graph.Connect(sampleGrabberPinOut, nullRendererPinIn); DsError.ThrowExceptionForHR(hr); _audioEngine.Setup(this.GetSampleGrabberFormat(sampleGrabber)); } } }
public void TestConnectDisconnectConnectedToConnectionMediaType() { int hr; IBaseFilter aviSplitter = null; IBaseFilter ibfAVISource = null; IPin pinIn = null; IPin pinOut = null; IFilterGraph2 graphBuilder = new FilterGraph() as IFilterGraph2; try { ibfAVISource = new AsyncReader() as IBaseFilter; // Add it to the graph hr = graphBuilder.AddFilter(ibfAVISource, "Ds.NET AsyncReader"); Marshal.ThrowExceptionForHR(hr); // Set the file name IFileSourceFilter fsf = ibfAVISource as IFileSourceFilter; hr = fsf.Load(@"foo.avi", null); Marshal.ThrowExceptionForHR(hr); pinOut = DsFindPin.ByDirection(ibfAVISource, PinDirection.Output, 0); // Get the avi splitter aviSplitter = (IBaseFilter) new AviSplitter(); // Add it to the graph hr = graphBuilder.AddFilter(aviSplitter, "Ds.NET AviSplitter"); Marshal.ThrowExceptionForHR(hr); pinIn = DsFindPin.ByDirection(aviSplitter, PinDirection.Input, 0); Assert.IsNotNull(pinOut); Assert.IsNotNull(pinIn); // Test Connect hr = pinOut.Connect(pinIn, null); Marshal.ThrowExceptionForHR(hr); // Test ConnectedTo IPin pinConnect; hr = pinOut.ConnectedTo(out pinConnect); Marshal.ThrowExceptionForHR(hr); Assert.AreEqual(pinIn, pinConnect); // Test ConnectionMediaType AMMediaType mediaType = new AMMediaType(); hr = pinIn.ConnectionMediaType(mediaType); Marshal.ThrowExceptionForHR(hr); Assert.IsNotNull(mediaType); Assert.IsNotNull(mediaType.majorType); // Test Disconnect hr = pinOut.Disconnect(); Marshal.ThrowExceptionForHR(hr); } finally { Marshal.ReleaseComObject(graphBuilder); } }
public static bool DisconnectPin(IGraphBuilder graphBuilder, IPin pin) { IPin other; int hr = pin.ConnectedTo(out other); bool allDisconnected = true; PinInfo info; pin.QueryPinInfo(out info); DsUtils.FreePinInfo(info); Log.Info("Disconnecting pin {0}", info.name); if (hr == 0 && other != null) { other.QueryPinInfo(out info); if (!DisconnectAllPins(graphBuilder, info.filter)) { allDisconnected = false; } hr = pin.Disconnect(); if (hr != 0) { allDisconnected = false; Log.Error("Error disconnecting: {0:x}", hr); } hr = other.Disconnect(); if (hr != 0) { allDisconnected = false; Log.Error("Error disconnecting other: {0:x}", hr); } DsUtils.FreePinInfo(info); ReleaseComObject(other); } else { Log.Info(" Not connected"); } return allDisconnected; }
// This function is called recursively, every time a new crossbar is // entered as we search upstream. // // Return values: // // 0 - Returned on final exit after recursive search if at least // one routing is possible // 1 - Normal return indicating we've reached the end of a // recursive search, so save the current path // -1 - Unable to route anything private int BuildRoutingList(IPin startingInputPin, Routing routing, int depth) { if (startingInputPin == null || routing == null) { return(-1); // E_POINTER; } // If the pin isn't connected, then it's a terminal pin IPin startingOutputPin = null; int hr = startingInputPin.ConnectedTo(out startingOutputPin); if (hr != 0) { return((depth == 0) ? -1 : 1); } // It is connected, so now find out if the filter supports IAMCrossbar PinInfo pinInfo; if (startingOutputPin.QueryPinInfo(out pinInfo) == 0) { //ASSERT (pinInfo.dir == PINDIR_OUTPUT); IAMCrossbar crossbar = pinInfo.filter as IAMCrossbar; if (crossbar != null) { int inputs, outputs, inputIndex, outputIndex; int inputIndexRelated, outputIndexRelated; PhysicalConnectorType inputPhysicalType, outputPhysicalType; hr = crossbar.get_PinCounts(out outputs, out inputs); // for all output pins for (outputIndex = 0; outputIndex < outputs; outputIndex++) { hr = crossbar.get_CrossbarPinInfo(false, outputIndex, out outputIndexRelated, out outputPhysicalType); // for all input pins for (inputIndex = 0; inputIndex < inputs; inputIndex++) { hr = crossbar.get_CrossbarPinInfo(true, inputIndex, out inputIndexRelated, out inputPhysicalType); // Can we route it? if (crossbar.CanRoute(outputIndex, inputIndex) == 0) { IPin pPin = null; hr = GetCrossbarPinAtIndex(crossbar, inputIndex, true, out pPin); // We've found a route through this crossbar // so save our state before recusively searching // again. Routing routingNext = new Routing(); // doubly linked list routingNext.rightRouting = routing; routing.leftRouting = routingNext; routing.crossbar = crossbar; routing.inputIndex = inputIndex; routing.outputIndex = outputIndex; routing.inputIndexRelated = inputIndexRelated; routing.outputIndexRelated = outputIndexRelated; routing.inputPhysicalType = inputPhysicalType; routing.outputPhysicalType = outputPhysicalType; routing.depth = depth; routing.inputName = this.pinNameByPhysicalConnectorType[inputPhysicalType] as string; hr = BuildRoutingList(pPin, routingNext, depth + 1); if (hr == 1) { routing.leftRouting = null; SaveRouting(routing, inputPhysicalType >= PhysicalConnectorType.Audio_Tuner); } } // if we can route } // for all input pins } //pXbar.Release(); } else { // The filter doesn't support IAMCrossbar, so this // is a terminal pin DsUtils.FreePinInfo(pinInfo); Marshal.ReleaseComObject(startingOutputPin); return((depth == 0) ? -1 : 1); } DsUtils.FreePinInfo(pinInfo); } Marshal.ReleaseComObject(startingOutputPin); return(0); }
public static void RemoveDownStreamFilters(IGraphBuilder graphBuilder, IPin pin) { IPin pinConnected; pin.ConnectedTo(out pinConnected); if (pinConnected == null) { return; } PinInfo info; pinConnected.QueryPinInfo(out info); if (info.filter != null) { RemoveDownStreamFilters(graphBuilder, info.filter, true); } DsUtils.FreePinInfo(info); }
// This function is called recursively, every time a new crossbar is // entered as we search upstream. // // Return values: // // 0 - Returned on final exit after recursive search if at least // one routing is possible // 1 - Normal return indicating we've reached the end of a // recursive search, so save the current path // -1 - Unable to route anything private int BuildRoutingList(IPin startingInputPin, Routing routing, int depth) { if (startingInputPin == null || routing == null) return -1; // E_POINTER; // If the pin isn't connected, then it's a terminal pin IPin startingOutputPin = null; int hr = startingInputPin.ConnectedTo(out startingOutputPin); if (hr != 0) return ((depth == 0) ? -1 : 1); // It is connected, so now find out if the filter supports IAMCrossbar PinInfo pinInfo; if (startingOutputPin.QueryPinInfo(out pinInfo) == 0) { //ASSERT (pinInfo.dir == PINDIR_OUTPUT); IAMCrossbar crossbar = pinInfo.filter as IAMCrossbar; if (crossbar != null) { int inputs, outputs, inputIndex, outputIndex; int inputIndexRelated, outputIndexRelated; PhysicalConnectorType inputPhysicalType, outputPhysicalType; hr = crossbar.get_PinCounts(out outputs, out inputs); // for all output pins for (outputIndex = 0; outputIndex < outputs; outputIndex++) { hr = crossbar.get_CrossbarPinInfo(false, outputIndex, out outputIndexRelated, out outputPhysicalType); // for all input pins for (inputIndex = 0; inputIndex < inputs; inputIndex++) { hr = crossbar.get_CrossbarPinInfo(true, inputIndex, out inputIndexRelated, out inputPhysicalType); // Can we route it? if (crossbar.CanRoute(outputIndex, inputIndex) == 0) { IPin pPin = null; hr = GetCrossbarPinAtIndex(crossbar, inputIndex, true, out pPin); // We've found a route through this crossbar // so save our state before recusively searching // again. Routing routingNext = new Routing(); // doubly linked list routingNext.rightRouting = routing; routing.leftRouting = routingNext; routing.crossbar = crossbar; routing.inputIndex = inputIndex; routing.outputIndex = outputIndex; routing.inputIndexRelated = inputIndexRelated; routing.outputIndexRelated = outputIndexRelated; routing.inputPhysicalType = inputPhysicalType; routing.outputPhysicalType = outputPhysicalType; routing.depth = depth; routing.inputName = this.pinNameByPhysicalConnectorType[inputPhysicalType] as string; hr = BuildRoutingList(pPin, routingNext, depth + 1); if (hr == 1) { routing.leftRouting = null; SaveRouting(routing, inputPhysicalType >= PhysicalConnectorType.Audio_Tuner); } } // if we can route } // for all input pins } //pXbar.Release(); } else { // The filter doesn't support IAMCrossbar, so this // is a terminal pin DsUtils.FreePinInfo(pinInfo); Marshal.ReleaseComObject(startingOutputPin); return (depth == 0) ? -1 : 1; } DsUtils.FreePinInfo(pinInfo); } Marshal.ReleaseComObject(startingOutputPin); return 0; }
public static void tオーディオレンダラをNullレンダラに変えてフォーマットを取得する(IGraphBuilder graphBuilder, out WaveFormat wfx, out byte[] wfx拡張データ) { int hr = 0; IBaseFilter audioRenderer = null; IPin rendererInputPin = null; IPin rendererConnectedOutputPin = null; IBaseFilter nullRenderer = null; IPin nullRendererInputPin = null; wfx = null; wfx拡張データ = new byte[0]; try { // audioRenderer を探す。 audioRenderer = CDirectShow.tオーディオレンダラを探して返す(graphBuilder); if (audioRenderer == null) { return; // なかった } #region [ 音量ゼロで一度再生する。(オーディオレンダラの入力ピンMediaTypeが、接続時とは異なる「正しいもの」に変わる可能性があるため。)] //----------------- { // ここに来た時点で、グラフのビデオレンダラは無効化(NullRendererへの置換や除去など)しておくこと。 // さもないと、StopWhenReady() 時に一瞬だけ Activeウィンドウが表示されてしまう。 var mediaCtrl = (IMediaControl)graphBuilder; var basicAudio = (IBasicAudio)graphBuilder; basicAudio.put_Volume(-10000); // 最小音量 // グラフを再生してすぐ止める。(Paused → Stopped へ遷移する) mediaCtrl.StopWhenReady(); // グラフが Stopped に遷移完了するまで待つ。(StopWhenReady() はグラフが Stopped になるのを待たずに帰ってくる。) FilterState fs = FilterState.Paused; hr = CWin32.S_FALSE; while (fs != FilterState.Stopped || hr != CWin32.S_OK) { hr = mediaCtrl.GetState(10, out fs); } // 終了処理。 basicAudio.put_Volume(0); // 最大音量 basicAudio = null; mediaCtrl = null; } //----------------- #endregion // audioRenderer の入力ピンを探す。 rendererInputPin = t最初の入力ピンを探して返す(audioRenderer); if (rendererInputPin == null) { return; } // WAVEフォーマットを取得し、wfx 引数へ格納する。 var type = new AMMediaType(); hr = rendererInputPin.ConnectionMediaType(type); DsError.ThrowExceptionForHR(hr); try { wfx = new WaveFormat(); #region [ type.formatPtr から wfx に、拡張領域を除くデータをコピーする。] //----------------- var wfxTemp = new WaveFormatEx(); // SharpDX.Multimedia.WaveFormat は Marshal.PtrToStructure() で使えないので、それが使える DirectShowLib.WaveFormatEx を介して取得する。(面倒…) Marshal.PtrToStructure(type.formatPtr, (object)wfxTemp); wfx = WaveFormat.CreateCustomFormat((WaveFormatEncoding)wfxTemp.wFormatTag, wfxTemp.nSamplesPerSec, wfxTemp.nChannels, wfxTemp.nAvgBytesPerSec, wfxTemp.nBlockAlign, wfxTemp.wBitsPerSample); //----------------- #endregion #region [ 拡張領域が存在するならそれを wfx拡張データ に格納する。 ] //----------------- int nWaveFormatEx本体サイズ = 16 + 2; // sizeof( WAVEFORMAT ) + sizof( WAVEFORMATEX.cbSize ) int nはみ出しサイズbyte = type.formatSize - nWaveFormatEx本体サイズ; if (nはみ出しサイズbyte > 0) { wfx拡張データ = new byte[nはみ出しサイズbyte]; var hGC = GCHandle.Alloc(wfx拡張データ, GCHandleType.Pinned); // 動くなよー unsafe { byte *src = (byte *)type.formatPtr.ToPointer(); byte *dst = (byte *)hGC.AddrOfPinnedObject().ToPointer(); CWin32.CopyMemory(dst, src + nWaveFormatEx本体サイズ, (uint)nはみ出しサイズbyte); } hGC.Free(); } //----------------- #endregion } finally { if (type != null) { DsUtils.FreeAMMediaType(type); } } // audioRenderer につながる出力ピンを探す。 hr = rendererInputPin.ConnectedTo(out rendererConnectedOutputPin); DsError.ThrowExceptionForHR(hr); // audioRenderer をグラフから切断する。 rendererInputPin.Disconnect(); rendererConnectedOutputPin.Disconnect(); // audioRenderer をグラフから除去する。 hr = graphBuilder.RemoveFilter(audioRenderer); DsError.ThrowExceptionForHR(hr); // nullRenderer を作成し、グラフに追加する。 nullRenderer = (IBaseFilter) new NullRenderer(); hr = graphBuilder.AddFilter(nullRenderer, "Audio Null Renderer"); DsError.ThrowExceptionForHR(hr); // nullRenderer の入力ピンを探す。 hr = nullRenderer.FindPin("In", out nullRendererInputPin); DsError.ThrowExceptionForHR(hr); // nullRenderer をグラフに接続する。 hr = rendererConnectedOutputPin.Connect(nullRendererInputPin, null); DsError.ThrowExceptionForHR(hr); } finally { CCommon.tReleaseComObject(ref nullRendererInputPin); CCommon.tReleaseComObject(ref nullRenderer); CCommon.tReleaseComObject(ref rendererConnectedOutputPin); CCommon.tReleaseComObject(ref rendererInputPin); CCommon.tReleaseComObject(ref audioRenderer); } }