예제 #1
0
        string populateUrlsFromXml(VideoInfo video, XmlDocument streamPlaylist, bool live)
        {
            if (streamPlaylist == null)
            {
                Log.Warn("ITVPlayer: Stream playlist is null");
                return("");
            }

            XmlNode videoEntry = streamPlaylist.SelectSingleNode("//VideoEntries/Video");

            if (videoEntry == null)
            {
                Log.Warn("ITVPlayer: Could not find video entry");
                return("");
            }

            XmlNode node;

            node = videoEntry.SelectSingleNode("./MediaFiles");
            if (node == null || node.Attributes["base"] == null)
            {
                Log.Warn("ITVPlayer: Could not find base url");
                return("");
            }

            string rtmpUrl = node.Attributes["base"].Value;
            SortedList <string, string> options = new SortedList <string, string>(new StreamComparer());

            foreach (XmlNode mediaFile in node.SelectNodes("./MediaFile"))
            {
                if (mediaFile.Attributes["delivery"] == null || mediaFile.Attributes["delivery"].Value != "Streaming")
                {
                    continue;
                }

                string title = "";
                if (mediaFile.Attributes["bitrate"] != null)
                {
                    title = mediaFile.Attributes["bitrate"].Value;
                    int bitrate;
                    if (int.TryParse(title, out bitrate))
                    {
                        title = string.Format("{0} kbps", bitrate / 1000);
                    }
                }

                if (!options.ContainsKey(title))
                {
                    string url = new MPUrlSourceFilter.RtmpUrl(rtmpUrl)
                    {
                        PlayPath  = mediaFile.InnerText,
                        SwfUrl    = "http://mediaplayer.itv.com/2.18.5%2Bbuild.ad408a9c67/ITVMediaPlayer.swf",
                        SwfVerify = true,
                        Live      = live
                    }.ToString();
                    options.Add(title, url);
                }
            }

            if (RetrieveSubtitles)
            {
                node = videoEntry.SelectSingleNode("./ClosedCaptioningURIs");
                if (node != null && Helpers.UriUtils.IsValidUri(node.InnerText))
                {
                    video.SubtitleText = SubtitleReader.TimedText2SRT(GetWebData(node.InnerText));
                }
            }

            video.PlaybackOptions = new Dictionary <string, string>();
            if (options.Count == 0)
            {
                return(null);
            }

            if (AutoSelectStream)
            {
                var last = options.Last();
                video.PlaybackOptions.Add(last.Key, last.Value);
            }
            else
            {
                foreach (KeyValuePair <string, string> key in options)
                {
                    video.PlaybackOptions.Add(key.Key, key.Value);
                }
            }
            return(options.Last().Value);
        }
예제 #2
0
        public override string GetVideoUrl(VideoInfo video)
        {
            Log.Debug(@"video: {0}", video.Title);
            string result = string.Empty;

            video.PlaybackOptions = new Dictionary <string, string>();
            // keep track of bitrates and URLs
            Dictionary <int, string> urlsDictionary = new Dictionary <int, string>();

            string pid = string.Empty;

            // must find pid before proceeding
            if (video.VideoUrl.Contains(@"pid="))
            {
                pid = HttpUtility.ParseQueryString(new Uri(video.VideoUrl).Query)["pid"];
            }
            else
            {
                string data = GetWebData(video.VideoUrl);

                Match pidMatch = pidRegex.Match(data);
                if (pidMatch.Success)
                {
                    pid = pidMatch.Groups["pid"].Value;
                }
            }

            if (!string.IsNullOrEmpty(pid))
            {
                XmlDocument xml = GetWebData <XmlDocument>(string.Format(thePlatformUrlFormat, pid));
                Log.Debug(@"SMIL loaded from {0}", string.Format(thePlatformUrlFormat, pid));

                XmlNamespaceManager nsmRequest = new XmlNamespaceManager(xml.NameTable);
                nsmRequest.AddNamespace("a", @"http://www.w3.org/2005/SMIL21/Language");

                XmlNode metaBase = xml.SelectSingleNode(@"//a:meta", nsmRequest);
                // base URL may be stored in the base attribute of <meta> tag
                string url = metaBase != null ? metaBase.Attributes["base"].Value : string.Empty;

                foreach (XmlNode node in xml.SelectNodes("//a:body/a:switch/a:video", nsmRequest))
                {
                    int bitrate = int.Parse(node.Attributes["system-bitrate"].Value);
                    // do not bother unless bitrate is non-zero
                    if (bitrate == 0)
                    {
                        continue;
                    }

                    if (url.StartsWith("rtmp") && !urlsDictionary.ContainsKey(bitrate / 1000))
                    {
                        string playPath = node.Attributes["src"].Value;
                        if (playPath.EndsWith(@".mp4") && !playPath.StartsWith(@"mp4:"))
                        {
                            // prepend with mp4:
                            playPath = @"mp4:" + playPath;
                        }
                        else if (playPath.EndsWith(@".flv"))
                        {
                            // strip extension
                            playPath = playPath.Replace(@".flv", string.Empty);
                        }
                        Log.Debug(@"bitrate: {0}, url: {1}, PlayPath: {2}", bitrate / 1000, url, playPath);
                        urlsDictionary.Add(bitrate / 1000, new MPUrlSourceFilter.RtmpUrl(url)
                        {
                            PlayPath = playPath
                        }.ToString());
                    }
                }

                // closed captions
                string subtitleText = string.Empty;
                if (retrieveSubtitles)
                {
                    XmlNode ccUrl = xml.SelectSingleNode("//a:body/a:switch/a:ref/a:param[@name='ClosedCaptionURL']", nsmRequest);
                    if (ccUrl != null)
                    {
                        subtitleText = SubtitleReader.TimedText2SRT(GetWebData(ccUrl.Attributes["value"].Value));
                    }
                }

                // sort the URLs ascending by bitrate
                foreach (var item in urlsDictionary.OrderBy(u => u.Key))
                {
                    video.PlaybackOptions.Add(string.Format("{0} kbps", item.Key), item.Value);
                    if (!string.IsNullOrEmpty(subtitleText))
                    {
                        video.SubtitleText = subtitleText;
                    }
                    // return last URL as the default (will be the highest bitrate)
                    result = item.Value;
                }

                // if result is still empty then perhaps we are geo-locked
                if (string.IsNullOrEmpty(result))
                {
                    XmlNode geolockReference = xml.SelectSingleNode(@"//a:seq/a:ref", nsmRequest);
                    if (geolockReference != null)
                    {
                        string message = geolockReference.Attributes["abstract"] != null ?
                                         geolockReference.Attributes["abstract"].Value :
                                         @"This content is not available in your location.";
                        Log.Error(message);
                        throw new OnlineVideosException(message, true);
                    }
                }
            }
            return(result);
        }