public void AddVideoTrack(LocalVideoTrack track, string deviceName) { ThreadHelper.EnsureIsMainThread(); VideoTracks.Add(new VideoTrackViewModel(track, deviceName)); LocalTracks.Add(new LocalTrackViewModel(Symbol.Video) { DisplayName = deviceName }); }
/// <summary> /// Callback on remote videa track added. /// /// For simplicity this grabs the first remote video track found and uses it to render its /// content on the right pane of the Tracks window. /// </summary> /// <param name="track">The video track added.</param> /// <seealso cref="RemoteVideoTrack_I420AFrameReady"/> private void OnRemoteVideoTrackAdded(RemoteVideoTrack track) { Logger.Log($"Added remote video track {track.Name} of transceiver {track.Transceiver.Name}."); ThreadHelper.RunOnMainThread(() => { var trvm = Transceivers.SingleOrDefault(tr => tr.Transceiver == track.Transceiver); Debug.Assert(trvm.Transceiver.RemoteVideoTrack == track); trvm.NotifyReceiverChanged(); // this is thread-aware // This raises property changed events in current thread, needs to be main one VideoTracks.Add(new VideoTrackViewModel(track)); }); }
/// <summary> /// Callback on remote video track removed. /// </summary> /// <param name="track">The video track removed.</param> private void OnRemoteVideoTrackRemoved(Transceiver transceiver, RemoteVideoTrack track) { Logger.Log($"Removed remote video track {track.Name} from transceiver {transceiver.Name}."); var vtvm = VideoTracks.Single(vm => vm.TrackImpl == track); VideoTracks.Remove(vtvm); //IVideoTrack newPlaybackVideoTrack = null; //if (LocalVideoTracks.Count > 0) //{ // newPlaybackVideoTrack = LocalVideoTracks[0].Track; //} //else //{ // videoTrackComboBox.IsEnabled = false; // _videoStatsTimer.Stop(); //} //SwitchMediaPlayerSource(_playbackAudioTrack, newPlaybackVideoTrack); }
private SessionModel() { _peerConnection.Connected += OnPeerConnected; _peerConnection.LocalSdpReadytoSend += OnLocalSdpReadyToSend; _peerConnection.IceCandidateReadytoSend += OnIceCandidateReadyToSend; _peerConnection.IceStateChanged += OnIceStateChanged; _peerConnection.IceGatheringStateChanged += OnIceGatheringStateChanged; _peerConnection.RenegotiationNeeded += OnRenegotiationNeeded; _peerConnection.TransceiverAdded += OnTransceiverAdded; _peerConnection.AudioTrackAdded += OnRemoteAudioTrackAdded; _peerConnection.AudioTrackRemoved += OnRemoteAudioTrackRemoved; _peerConnection.VideoTrackAdded += OnRemoteVideoTrackAdded; _peerConnection.VideoTrackRemoved += OnRemoteVideoTrackRemoved; _peerConnection.DataChannelAdded += OnDataChannelAdded; _peerConnection.DataChannelRemoved += OnDataChannelRemoved; NodeDssSignaler.OnConnect += DssSignaler_OnConnected; NodeDssSignaler.OnDisconnect += DssSignaler_OnDisconnected; NodeDssSignaler.OnMessage += DssSignaler_OnMessage; NodeDssSignaler.OnFailure += DssSignaler_OnFailure; NodeDssSignaler.OnPollingDone += DssSignaler_OnPollingDone; AudioTracks.Add(NullAudioTrack); VideoTracks.Add(NullVideoTrack); AudioTracks.CollectionChanged += LocalAudioTrackCollectionChanged; VideoTracks.CollectionChanged += LocalVideoTrackCollectionChanged; LocalTracks.Add(new AddNewTrackViewModel() { DisplayName = "Add audio track", PageType = typeof(AddAudioTrackPage) }); LocalTracks.Add(new AddNewTrackViewModel() { DisplayName = "Add video track", PageType = typeof(AddVideoTrackPage) }); }
private void OnInspectorGUI_MediaInfo() { MediaPlayer media = (this.target) as MediaPlayer; IMediaInfo info = media.Info; IMediaControl control = media.Control; ITextTracks textTracks = media.TextTracks; IAudioTracks audioTracks = media.AudioTracks; IVideoTracks videoTracks = media.VideoTracks; if (info != null) { if (!info.HasVideo() && !info.HasAudio()) // && !info.HasText()) { GUILayout.Label("No media loaded"); } else { if (info.HasVideo()) { GUILayout.BeginHorizontal(); { string dimensionText = string.Format("{0}x{1}@{2:0.##}", info.GetVideoWidth(), info.GetVideoHeight(), info.GetVideoFrameRate()); GUILayout.Label(dimensionText); GUILayout.FlexibleSpace(); string rateText = "0.00"; if (media.Info != null) { rateText = media.Info.GetVideoDisplayRate().ToString("F2"); } GUILayout.Label(rateText + "FPS"); } GUILayout.EndHorizontal(); EditorGUILayout.Space(); } if (info.HasVideo()) { VideoTracks tracks = videoTracks.GetVideoTracks(); if (tracks.Count > 0) { GUILayout.Label("Video Tracks: " + tracks.Count); foreach (VideoTrack track in tracks) { bool isActiveTrack = (track == videoTracks.GetActiveVideoTrack()); GUI.color = isActiveTrack?Color.green:Color.white; { if (GUILayout.Button(track.DisplayName)) { if (isActiveTrack) { videoTracks.SetActiveVideoTrack(null); } else { videoTracks.SetActiveVideoTrack(track); } } } } GUI.color = Color.white; EditorGUILayout.Space(); } } if (info.HasAudio()) { AudioTracks tracks = audioTracks.GetAudioTracks(); if (tracks.Count > 0) { GUILayout.Label("Audio Tracks: " + tracks.Count); foreach (AudioTrack track in tracks) { bool isActiveTrack = (track == audioTracks.GetActiveAudioTrack()); GUI.color = isActiveTrack?Color.green:Color.white; { if (GUILayout.Button(track.DisplayName)) { if (isActiveTrack) { audioTracks.SetActiveAudioTrack(null); } else { audioTracks.SetActiveAudioTrack(track); } } } } GUI.color = Color.white; /*int channelCount = control.GetAudioChannelCount(); * if (channelCount > 0) * { * GUILayout.Label("Audio Channels: " + channelCount); * AudioChannelMaskFlags audioChannels = control.GetAudioChannelMask(); * GUILayout.Label("(" + audioChannels + ")", EditorHelper.IMGUI.GetWordWrappedTextAreaStyle()); * }*/ EditorGUILayout.Space(); } } { TextTracks tracks = textTracks.GetTextTracks(); if (tracks.Count > 0) { GUILayout.Label("Text Tracks: " + tracks.Count); foreach (TextTrack track in tracks) { bool isActiveTrack = (track == textTracks.GetActiveTextTrack()); GUI.color = isActiveTrack?Color.green:Color.white; { if (GUILayout.Button(track.DisplayName)) { if (isActiveTrack) { textTracks.SetActiveTextTrack(null); } else { textTracks.SetActiveTextTrack(track); } } } } GUI.color = Color.white; if (textTracks.GetActiveTextTrack() != null) { string text = string.Empty; if (textTracks.GetCurrentTextCue() != null) { text = textTracks.GetCurrentTextCue().Text; // Clip the text if it is too long if (text.Length >= 96) { text = string.Format("{0}...({1} chars)", text.Substring(0, 96), text.Length); } } GUILayout.Label(text, EditorHelper.IMGUI.GetWordWrappedTextAreaStyle(), GUILayout.Height(48f)); } EditorGUILayout.Space(); } } } } else { GUILayout.Label("No media loaded"); } }
/// <summary> /// Null-safe method for testing if the first video track meets certain criteria. /// </summary> /// <param name="delegate">Does NOT need to check if the video track is null. It will not be invoked if there are no video tracks.</param> /// <returns>The delegate's return value if this playlist has a video track; otherwise false.</returns> bool TestFirstVideoTrack(FirstVideoTrackDelegate @delegate) { var video = VideoTracks.FirstOrDefault(); return(video != null && @delegate(video)); }
public virtual void SelectTracks(int resolution, string codec, bool engOnly) { VideoTracks = VideoTracks.GroupBy(x => x.Id).Select(x => x.First()).OrderBy(x => x.Bitrate).OrderBy(x => x.Height).ToList(); AudioTracks = AudioTracks.GroupBy(x => x.Id).Select(x => x.First()).OrderByDescending(x => x.Codec.Contains("dd")).OrderByDescending(x => x.Codec.Contains("ddp")).OrderByDescending(x => x.Codec.Contains("atmos")).OrderBy(x => x.Bitrate).ToList(); SelectedSubtitleTracks = SelectedSubtitleTracks.GroupBy(x => x.Id).Select(x => x.First()).OrderBy(x => x.Name).ThenByDescending(x => x.LanguageCode.Contains("en")).ToList(); List <VideoTrack> videoTrackPool = VideoTracks; List <AudioTrack> audioTrackPool = AudioTracks; /*if (DeviceConfig.L1Available) * { * videoTrackPool = VideoTracks.Where(x => x.SecurityLevel != ITrack.SecurityLevel.Hardware).ToList(); * audioTrackPool = AudioTracks.Where(x => x.SecurityLevel != ITrack.SecurityLevel.Hardware).ToList(); * }*/ if (codec != null) { if (codec == "H264") { videoTrackPool = videoTrackPool.Where(x => x.Codec.Contains("avc")).ToList(); } else if (codec == "H265") { videoTrackPool = videoTrackPool.Where(x => x.Codec.Contains("hvc") || x.Codec.Contains("hev")).ToList(); } } if (resolution == 0) { SelectedVideoTracks.Add(videoTrackPool.Last()); } else { try { SelectedVideoTracks.Add(videoTrackPool.Where(x => x.Height == resolution).Last()); } catch { SelectedVideoTracks.Add(videoTrackPool.Last()); } } string origLang = "en"; foreach (var track in AudioTracks) { if (track.Name.Contains("Original")) { origLang = track.Language; break; } } SelectedAudioTracks = audioTrackPool.GroupBy(x => x.Language + x.Name.Contains("Description").ToString()).Select(x => x.OrderByDescending(y => y.Name.Contains("Description")).OrderByDescending(y => y.Bitrate).FirstOrDefault()).ToList(); SelectedAudioTracks.AddRange(audioTrackPool.Where(x => x.Name.Contains("Description")).GroupBy(x => x.Language).Select(x => x.OrderByDescending(y => y.Name.Contains("Description")).OrderByDescending(y => y.Bitrate).FirstOrDefault())); SelectedAudioTracks = SelectedAudioTracks.OrderByDescending(y => y.Channels).OrderByDescending(y => y.Bitrate).OrderBy(x => x.Language).OrderByDescending(x => x.Language.Contains("en")).OrderByDescending(x => x.Language.Contains("en-us")).OrderByDescending(x => x.Language == origLang).ToList(); SelectedSubtitleTracks = SelectedSubtitleTracks.OrderBy(x => x.LanguageCode).OrderByDescending(x => x.LanguageCode == origLang).OrderByDescending(x => x.LanguageCode.Contains("en")).Where(x => !x.Name.Contains("Forced")).ToList(); if (engOnly) { SelectedAudioTracks = SelectedAudioTracks.Where(x => (x.Language.Contains("en") || x.Language == origLang) && !x.Name.Contains("Description")).ToList(); } if (engOnly) { SelectedSubtitleTracks = new List <SubtitleTrack>() { SelectedSubtitleTracks.Where(x => x.LanguageCode.Contains("en") || x.LanguageCode == origLang).FirstOrDefault() } } ; SelectedAudioTracks = SelectedAudioTracks.Distinct().ToList(); SelectedSubtitleTracks = SelectedSubtitleTracks.Distinct().ToList(); /* * foreach (var subtitleTrack in SelectedSubtitleTracks) * { * if (subtitleTrack.LanguageCode == origLang) * { * subtitleTrack.Default = true; * break; * } * } */ }
public DASHPlaylist(string[] playlistUrls, bool[] playlistsAudioOnly, List <AudioTrackMetadata> audioMetadata = null) { foreach ((string playlistUrl, bool audioOnly) in playlistUrls.Zip(playlistsAudioOnly)) { string originalPlaylist = Requests.Request(playlistUrl, null); XmlDocument xmlDoc = new XmlDocument(); try { xmlDoc.LoadXml(originalPlaylist); OriginalPlaylists.Add(originalPlaylist); } catch { continue; } string baseUrl = playlistUrl.Substring(0, playlistUrl.LastIndexOf("/") + 1); Dictionary <string, string> initDataPairs = new Dictionary <string, string>(); foreach (XmlElement adaptationSet in xmlDoc["MPD"]["Period"].GetElementsByTagName("AdaptationSet")) { try { string keyId; try { keyId = adaptationSet.GetElementsByTagName("ContentProtection").Cast <XmlElement>().Where(x => x.HasAttribute("cenc:default_KID")).FirstOrDefault().GetAttribute("cenc:default_KID"); } catch { keyId = adaptationSet.GetElementsByTagName("ContentProtection").Cast <XmlElement>().Where(x => x.HasAttribute("_:default_KID")).FirstOrDefault().GetAttribute("_:default_KID"); } string initData = adaptationSet.GetElementsByTagName("ContentProtection").Cast <XmlElement>().Where(x => x.GetAttribute("schemeIdUri").ToLower().Contains("edef8ba9-79d6-4ace-a3c8-27dcd51d21ed")).FirstOrDefault().FirstChild.InnerText; if (!initDataPairs.ContainsKey(keyId)) { initDataPairs.Add(keyId, initData); } } catch { } } foreach (XmlElement adaptationSet in xmlDoc["MPD"]["Period"].GetElementsByTagName("AdaptationSet")) { bool isEncrypted = false; string initDataB64 = null; XmlNodeList contentProtectionElements = adaptationSet.GetElementsByTagName("ContentProtection"); if (contentProtectionElements.Count > 0) { isEncrypted = true; string keyId; try { keyId = contentProtectionElements.Cast <XmlElement>().Where(x => x.HasAttribute("cenc:default_KID")).FirstOrDefault().GetAttribute("cenc:default_KID"); } catch { keyId = contentProtectionElements.Cast <XmlElement>().Where(x => x.HasAttribute("_:default_KID")).FirstOrDefault().GetAttribute("_:default_KID"); } initDataB64 = initDataPairs[keyId]; } foreach (XmlElement representation in adaptationSet.GetElementsByTagName("Representation")) { string url = representation.GetElementsByTagName("BaseURL")[0].InnerText; if (!url.Contains("https://") && !url.Contains("http://")) { url = baseUrl + url; } if (url.StartsWith("http:")) { url = url.Replace("http:", "https:"); } if (adaptationSet.GetAttribute("contentType").ToLower() == "audio" || adaptationSet.GetAttribute("mimeType").ToLower().Contains("audio")) { string name = null; if (adaptationSet.HasAttribute("label")) { name = adaptationSet.GetAttribute("label"); } string codec = null; if (representation.HasAttribute("codecs")) { codec = representation.GetAttribute("codecs"); } else { codec = adaptationSet.GetAttribute("codecs"); } int channels = 2; try { XmlElement audioChannelConfiguration = null; try { audioChannelConfiguration = representation.GetElementsByTagName("AudioChannelConfiguration").Cast <XmlElement>().FirstOrDefault(); } catch { audioChannelConfiguration = adaptationSet.GetElementsByTagName("AudioChannelConfiguration").Cast <XmlElement>().FirstOrDefault(); } if (audioChannelConfiguration == null) { audioChannelConfiguration = adaptationSet.GetElementsByTagName("AudioChannelConfiguration").Cast <XmlElement>().FirstOrDefault(); } string channelValue = audioChannelConfiguration.GetAttribute("value"); if (channelValue == "2") { channels = 2; } else if (channelValue == "A000") { channels = 2; } else if (channelValue == "F801" || channelValue == "6") { channels = 6; } else if (channelValue == "FA01" || channelValue == "8") { channels = 8; } } catch { channels = 2; } int bandwidth = int.Parse(representation.GetAttribute("bandwidth")); string id = representation.GetAttribute("id"); if (adaptationSet.HasAttribute("audioTrackId")) { id = adaptationSet.GetAttribute("audioTrackId") + "_" + id; } string lang; try { //amzn lang = id.Split("_")[0]; } catch { lang = adaptationSet.GetAttribute("lang"); } if (lang == null || lang == "") { lang = "en"; } if (audioMetadata != null && audioMetadata.Count > 1 && adaptationSet.HasAttribute("audioTrackId")) { string trackId = adaptationSet.GetAttribute("audioTrackId"); name = audioMetadata.FirstOrDefault(x => x.AudioTrackId == trackId).DisplayName; } else if (audioMetadata != null && audioMetadata.Count == 1) { name = audioMetadata[0].DisplayName; } if (name == null) { name = lang; } var audioTrack = new AudioTrack { Encrypted = isEncrypted, Id = id, Name = name, InitDataB64 = initDataB64, Urls = new string[] { url }, Segments = 1, Codec = codec, Bitrate = bandwidth, Channels = channels, Language = lang, SecurityLevel = ITrack.SecurityLevel.Unknown }; AudioTracks.Add(audioTrack); } else if ((adaptationSet.GetAttribute("contentType").ToLower() == "video" || adaptationSet.GetAttribute("mimeType").ToLower().Contains("video")) && !audioOnly) { string frameRate = "24000/1001"; if (representation.HasAttribute("frameRate")) { frameRate = representation.GetAttribute("frameRate"); } else { frameRate = adaptationSet.GetAttribute("frameRate"); } var frameRateValue = 0.0; if (frameRate.Contains("/")) { frameRateValue = Utils.EvaluateEquation(frameRate); } else { frameRateValue = float.Parse(frameRate); } int bandwidth = int.Parse(representation.GetAttribute("bandwidth")); try { bandwidth = int.Parse(representation.GetAttribute("id").Split("=")[1]); } catch { } var videoTrack = new VideoTrack { Encrypted = isEncrypted, Id = representation.GetAttribute("id"), InitDataB64 = initDataB64, Urls = new string[] { url }, Segments = 1, Codec = representation.GetAttribute("codecs"), Bitrate = bandwidth, Width = int.Parse(representation.GetAttribute("width")), Height = int.Parse(representation.GetAttribute("height")), FrameRate = frameRateValue, SecurityLevel = ITrack.SecurityLevel.Unknown }; VideoTracks.Add(videoTrack); } } } } }