コード例 #1
0
ファイル: MpdParser.cs プロジェクト: Xen0byte/xdm
        //@"\$(RepresentationID|Time|Time(%0([\d]+)([dx])?)?|Number|Number(%0([\d]+)([dx])?)?|Bandwidth)\$");
        public static IList <IList <(Representation Video, Representation Audio)> > Parse(
            string[] manifestLines,
            string playlistUrl)
        {
            using var memstream = new MemoryStream(Encoding.UTF8.GetBytes(string.Join("\n", manifestLines)));
            var xmldoc = new XmlDocument();

            xmldoc.Load(new XmlTextReader(memstream)
            {
                Namespaces = false
            });

            if (xmldoc.DocumentElement?.Name != "MPD")
            {
                throw new Exception("Missing MPD start tag: " + xmldoc.DocumentElement.Name);
            }
            if (xmldoc.DocumentElement.Attributes["type"]?.Value == "dynamic")
            {
                throw new Exception("Manifest type dynamic is not supported");
            }
            if (xmldoc.DocumentElement.SelectSingleNode("descendant::ContentProtection") != null)
            {
                throw new Exception("Encrypted manifest");
            }

            var mediaList = new List <IList <(Representation Video, Representation Audio)> >();

            var mediaPresentationDuration =
                DashUtil.ParseXsDuration(xmldoc.DocumentElement.Attributes["mediaPresentationDuration"]?.Value ?? "0");
            var baseUrl         = new Uri(playlistUrl);
            var baseUrlNodeRoot = xmldoc.DocumentElement.SelectSingleNode("child::BaseURL");

            if (baseUrlNodeRoot != null)
            {
                baseUrl = UrlResolver.Resolve(baseUrl, baseUrlNodeRoot.InnerText);
            }

            var periods = xmldoc.DocumentElement.SelectNodes("child::Period");

            if (periods == null || periods.Count < 1)
            {
                throw new Exception("No period found!");
            }
            if (periods.Count > 1)
            {
                var periodDurations = CalculatePeriodDurationsIfMissing(periods, mediaPresentationDuration);
                for (var i = 0; i < periods.Count; i++)
                {
                    var period = periods[i];
                    mediaList.Add(ParsePeriod(period, baseUrl, periodDurations[i]));
                }
            }
            else if (periods.Count == 1)
            {
                mediaList.Add(ParsePeriod(periods[0], baseUrl, mediaPresentationDuration));
            }

            return(mediaList);
        }
コード例 #2
0
ファイル: MpdParser.cs プロジェクト: Xen0byte/xdm
        public static IList <long> CalculatePeriodDurationsIfMissing(XmlNodeList periods, long mediaPresentationDuration)
        {
            var stack = new Stack <XmlNode>();

            foreach (XmlNode node in periods)
            {
                stack.Push(node);
            }
            var list  = new List <long>(periods.Count);
            var last  = mediaPresentationDuration;
            var count = stack.Count;

            for (int i = 0; i < count; i++)
            {
                var node      = stack.Pop();
                var sduration = node.Attributes["duration"]?.Value;
                var sstart    = node.Attributes["start"]?.Value;
                if (sstart == null && sduration == null)
                {
                    throw new Exception("Both period start and duration is missing");
                }
                if (sduration != null)
                {
                    var duration = DashUtil.ParseXsDuration(sduration);
                    list.Add(duration);
                    last = mediaPresentationDuration - duration;
                    continue;
                }
                if (sstart == null && i == stack.Count - 1)
                {
                    sstart = "PT0S";
                }
                var start = DashUtil.ParseXsDuration(sstart);
                list.Add(last - start);
                last = start;
            }
            list.Reverse();
            return(list);
        }