protected override HRESULT LoadTracks() { // Check if required extradata is present, if not continue packet processing until they are filled if (_stream.VideoStream.StreamId == 0) { DecryptError = true; return(S_FALSE); } while (_stream.VideoStream.ExtraSize == 0) { DemuxPacketWrapper demuxPacket = _stream.Read(); // EOS if (demuxPacket.IsEOS) { return(S_FALSE); } } //Initialise the tracks, these create our output pins AMMediaType mediaType; if (MediaTypeBuilder.TryGetType(_stream.VideoStream, out mediaType)) { m_Tracks.Add(new MediaTypedDemuxTrack(this, DemuxTrack.TrackType.Video, mediaType)); } if (MediaTypeBuilder.TryGetType(_stream.AudioStream, out mediaType)) { m_Tracks.Add(new MediaTypedDemuxTrack(this, DemuxTrack.TrackType.Audio, mediaType) { LCID = _stream.AudioStream.Language.TryGetLCID() }); } m_rtDuration = _stream.Functions.GetTotalTime().ToDS(); return(S_OK); }
public override int Info(int lIndex, IntPtr ppmt, IntPtr pdwFlags, IntPtr plcid, IntPtr pdwGroup, IntPtr ppszName, IntPtr ppObject, IntPtr ppUnk) { if (lIndex >= _streamParser.SelectableTracks.Count) { return(S_FALSE); } var selected = _streamParser.SelectableTracks[lIndex]; if (ppmt != IntPtr.Zero) { AMMediaType mt; if (MediaTypeBuilder.TryGetType(selected, out mt)) { IntPtr pmt = Marshal.AllocCoTaskMem(Marshal.SizeOf(mt)); Marshal.StructureToPtr(mt, pmt, true); Marshal.WriteIntPtr(ppmt, pmt); } else { Marshal.WriteIntPtr(ppmt, IntPtr.Zero); } } if (pdwFlags != IntPtr.Zero) { var enabled = (int)(selected.StreamId == _streamParser.InputStream.AudioStream.StreamId ? AMStreamSelectInfoFlags.Enabled : AMStreamSelectInfoFlags.Disabled); Marshal.WriteInt32(pdwFlags, enabled); } if (plcid != IntPtr.Zero) { int lcid = selected.Language.TryGetLCID(); if (lcid == 0) { lcid = LOCALE_NEUTRAL; } Marshal.WriteInt32(plcid, lcid); } if (pdwGroup != IntPtr.Zero) { if (selected.StreamType == StreamType.Audio) { Marshal.WriteInt32(pdwGroup, 1); } else if (selected.StreamType == StreamType.Subtitle) { Marshal.WriteInt32(pdwGroup, 2); } else { Marshal.WriteInt32(pdwGroup, 0); } } if (ppszName != IntPtr.Zero) { var culture = selected.Language.FromISOName(); string name = culture != null ? culture.DisplayName : selected.Language; if (string.IsNullOrEmpty(name)) { name = "Audio #" + lIndex; } Marshal.WriteIntPtr(ppszName, Marshal.StringToCoTaskMemUni(name)); } if (ppObject != IntPtr.Zero) { Marshal.WriteIntPtr(ppObject, Marshal.GetIUnknownForObject(selected)); } if (ppUnk != IntPtr.Zero) { Marshal.WriteIntPtr(ppUnk, IntPtr.Zero); } return(NOERROR); }
private HRESULT RenameOutputPin(SplitterOutputPin pPin, uint oldStreamId, uint newStreamId) { // Output Pin was found // Stop the Graph, remove the old filter, render the graph again, start it up again // This only works on pins that were connected before, or the filter graph could .. well, break if (pPin != null && pPin.IsConnected) { Logger.Info("RenameOutputPin() - Switching {0} Stream {1} to {2}", pPin.Name, oldStreamId, newStreamId); IMediaControl pControl = (IMediaControl)FilterGraph; FilterState oldState; // Get the graph state // If the graph is in transition, we'll get the next state, not the previous var hr = (HRESULT)pControl.GetState(10, out oldState); // Stop the filter graph hr = (HRESULT)pControl.Stop(); // Audio Filters get their connected filter removed // This way we make sure we reconnect to the proper filter // Other filters just disconnect and try to reconnect later on PinInfo pInfo; IPinImpl connectedPin = pPin.Connected; hr = (HRESULT)connectedPin.QueryPinInfo(out pInfo); // Update Output Pin AMMediaType pmt; if (MediaTypeBuilder.TryGetType(_streamParser.InputStream.AudioStream, out pmt)) { pPin.SetMediaType(pmt); } int mtIdx = connectedPin.QueryAccept(pmt); bool bMediaTypeFound = (mtIdx >= 0); if (pInfo.filter != null) { bool bRemoveFilter = !bMediaTypeFound; if (bRemoveFilter) { hr = (HRESULT)FilterGraph.RemoveFilter(pInfo.filter); // Use IGraphBuilder to rebuild the graph IGraphBuilder pGraphBuilder = (IGraphBuilder)FilterGraph; // Instruct the GraphBuilder to connect us again hr = (HRESULT)pGraphBuilder.Render(pPin); } else { hr = (HRESULT)ReconnectPin(pPin, pmt); } pPin.SetMediaType(pmt); } // Re-start the graph if (oldState == FilterState.Paused) { hr = (HRESULT)pControl.Pause(); } else if (oldState == FilterState.Running) { hr = (HRESULT)pControl.Run(); } return(hr); } return(E_FAIL); }
public override int Enable(int lIndex, AMStreamSelectEnableFlags dwFlags) { bool changed = false; uint oldAudioStream = _streamParser.InputStream.AudioStream.StreamId; for (int index = 0; index < _streamParser.SelectableTracks.Count; index++) { var track = _streamParser.SelectableTracks[index]; bool isEnabled = ( index == lIndex && dwFlags == AMStreamSelectEnableFlags.Enable || // the current index should be enabled dwFlags == AMStreamSelectEnableFlags.EnableAll // all should be enabled ) && dwFlags != AMStreamSelectEnableFlags.DisableAll; // must not be "Disable All" changed |= _streamParser.InputStream.EnableStream((int)track.StreamId, isEnabled); } uint newAudioStream = _streamParser.InputStream.AudioStream.StreamId; if (!changed) { return(NOERROR); } // Update output pin var audioPin = Pins.OfType <SplitterOutputPin>().FirstOrDefault(p => p.Track.Type == DemuxTrack.TrackType.Audio); if (audioPin != null) { AMMediaType mt; if (MediaTypeBuilder.TryGetType(_streamParser.InputStream.AudioStream, out mt)) { _streamParser.Tracks[1].SetStreamMediaType(mt); } var res = RenameOutputPin(audioPin, oldAudioStream, newAudioStream); } if (IsActive && dwFlags != AMStreamSelectEnableFlags.DisableAll) { try { IMediaSeeking seeking = (IMediaSeeking)FilterGraph; if (seeking != null) { long current; seeking.GetCurrentPosition(out current); // Only seek during playback, not on initial selection if (current != 0) { current -= UNITS / 10; seeking.SetPositions(current, AMSeekingSeekingFlags.AbsolutePositioning, null, AMSeekingSeekingFlags.NoPositioning); current += UNITS / 10; seeking.SetPositions(current, AMSeekingSeekingFlags.AbsolutePositioning, null, AMSeekingSeekingFlags.NoPositioning); } } } catch { } } return(NOERROR); }