/// <summary> /// Creation of the fgm and the adding / removing of filters needs to happen on the /// same thread. So make sure it all happens on the UI thread. /// </summary> private void _RtpStream_FirstFrameReceived() { lock (fgmLock) { DisposeFgm(); Debug.Assert(fgm == null); // Create the DirectShow filter graph manager fgm = new FilgraphManagerClass(); IGraphBuilder iGB = (IGraphBuilder)fgm; rotID = FilterGraph.AddToRot((IGraphBuilder)fgm); IBaseFilter bfSource = RtpSourceClass.CreateInstance(); ((MSR.LST.MDShow.Filters.IRtpSource)bfSource).Initialize(rtpStream); iGB.AddFilter(bfSource, "RtpSource"); iGB.Render(Filter.GetPin(bfSource, _PinDirection.PINDIR_OUTPUT, Guid.Empty, Guid.Empty, false, 0)); DisableDXVA(fgm); // Render the video inside of the form iVW = (IVideoWindow)fgm; // Get the correct ratio to use for the video stretching // I would expect the fgm to always be castable to this, but I simply don't trust DShow IBasicVideo iBV = fgm as IBasicVideo; if (iBV != null) { int vidWidth, vidHeight; iBV.GetVideoSize(out vidWidth, out vidHeight); vidSrcRatio = (double)vidHeight / (double)vidWidth; } // Remove the border from the default DShow renderer UI int ws = WindowStyle; ws = ws & ~(0x00800000); // Remove WS_BORDER ws = ws & ~(0x00400000); // Remove WS_DLGFRAME WindowStyle = ws; iVW = null; uiState &= ~(int)FAudioVideo.UIState.RemoteVideoStopped; if (form != null) { ((FAudioVideo)form).UpdateVideoUI(uiState); } // FirstFrameReceived interprets fgmState as the *desired* state for the fgm // Because ResumePlayingVideo won't actually start if the state is already // Running, we change it to Stopped so that it will start if (IsPlaying && fgmState == FilterGraph.State.Running) { fgmState = FilterGraph.State.Stopped; ResumePlayingVideo(); } } }
/// <summary> /// Creation of the fgm and the adding / removing of filters needs to happen on the /// same thread. So make sure it all happens on the UI thread. /// </summary> private void _RtpStream_FirstFrameReceived() { lock (fgmLock) { DisposeFgm(); Debug.Assert(fgm == null); fgm = new FilgraphManagerClass(); IGraphBuilder iGB = (IGraphBuilder)fgm; rotID = FilterGraph.AddToRot(iGB); IBaseFilter rtpSource = RtpSourceClass.CreateInstance(); ((MSR.LST.MDShow.Filters.IRtpSource)rtpSource).Initialize(rtpStream); iGB.AddFilter(rtpSource, "RtpSource"); // Add the chosen audio renderer FilterInfo fi = SelectedSpeaker(); iGB.AddFilter(Filter.CreateBaseFilter(fi), fi.Name); iGB.Render(Filter.GetPin(rtpSource, _PinDirection.PINDIR_OUTPUT, Guid.Empty, Guid.Empty, false, 0)); iBA = (IBasicAudio)fgm; currentVolume = (int)Math.Round(Math.Pow(10.0, (2.0 * (double)(iBA.Volume + 10000)) / 10000.0)); iBA = null; uiState &= ~(int)FAudioVideo.UIState.RemoteAudioStopped; if (form != null) { ((FAudioVideo)form).UpdateAudioUI(uiState); } // FirstFrameReceived interprets fgmState as the *desired* state for the fgm // Because ResumePlayingAudio won't actually start if the state is already // Running, we change it to Stopped so that it will start if (IsPlaying && fgmState == FilterGraph.State.Running) { fgmState = FilterGraph.State.Stopped; ResumePlayingAudio(); } } }
private void CreateReceivingGraph() { // Tell the stream we will poll it for data with our own (DShow) thread // Instead of receiving data through the FrameReceived event rtpStream.IsUsingNextFrame = true; // Create receiving filtergraph fgm = new FilgraphManagerClass(); IGraphBuilder iGB = (IGraphBuilder)fgm; IBaseFilter rtpSource = RtpSourceClass.CreateInstance(); ((MSR.LST.MDShow.Filters.IRtpSource)rtpSource).Initialize(rtpStream); iGB.AddFilter(rtpSource, "RtpSource"); iGB.Render(Filter.GetPin(rtpSource, _PinDirection.PINDIR_OUTPUT, Guid.Empty, Guid.Empty, false, 0)); VideoWindow(); fgm.Run(); }