Ejemplo n.º 1
0
        private async Task _fillVideoGabs(YoutubeMediaPacketType type)
        {
            // compute the broken ranges for both videos packets and audio packets
            List <Range> LostPacketsRanges = _computeBrokenRanges(type);

            // fill the missing packets
            await _fillBrokenRanges(LostPacketsRanges, type);
        }
Ejemplo n.º 2
0
 public YoutubeMediaPacket(YoutubeMediaPacketType videoPacketType, YoutubeRequestURL requestURL, string packetFilePath)
 {
     FilePath          = packetFilePath;
     VideoPacketType   = videoPacketType;
     YoutubeRequestURL = requestURL;
     VideoId           = requestURL.RequestPath.QueryString.HasValue(YoutubeChatterClientHandler.VIDEO_ID_FIELD_NAME) ?
                         requestURL.RequestPath.QueryString.GetValue(YoutubeChatterClientHandler.VIDEO_ID_FIELD_NAME)
      : null;
     _populateFromYoutubeRequestURL(requestURL);
 }
Ejemplo n.º 3
0
 public YoutubeMediaPacket(YoutubeMediaPacketType videoPacketType, YoutubeRequestURL requestURL, byte[] packetData)
 {
     FilePath          = _writePacketDataToDisk(packetData);
     VideoPacketType   = videoPacketType;
     YoutubeRequestURL = requestURL;
     _populateFromYoutubeRequestURL(requestURL);
     VideoId = requestURL.RequestPath.QueryString.HasValue(YoutubeChatterClientHandler.VIDEO_ID_FIELD_NAME) ?
               requestURL.RequestPath.QueryString.GetValue(YoutubeChatterClientHandler.VIDEO_ID_FIELD_NAME)
      : null;
 }
Ejemplo n.º 4
0
        private List <Range> _computeBrokenRanges(YoutubeMediaPacketType type)
        {
            YoutubeMediaPacket[] storedPackets;
            lock (this.Video.Packets)
            {
                storedPackets = this.Video.Packets.Where(x => x.VideoPacketType == type).OrderBy(x => x.Range.Start).ToArray();
            }

            var lostPacketsRanges = new List <Range>();

            // checking if there is a missing packets at start or end of media
            var firstPacket = storedPackets.FirstOrDefault();
            var lastPacket  = storedPackets.LastOrDefault();

            // at start
            if (firstPacket != null && firstPacket.Range.Start != 0)
            {
                lostPacketsRanges.Add(new Range(0, firstPacket.Range.Start - 1));
            }

            // at end
            if (lastPacket != null && lastPacket.Range.End + 1 != lastPacket.OverAllLength)
            {
                lostPacketsRanges.Add(new Range(lastPacket.Range.End + 1, lastPacket.OverAllLength - 1));
            }

            // checking if there is a missing packets at middle of the video packets
            for (int i = 0; i < storedPackets.Length; i++)
            {
                // to make sure the counter don't exceed the array bounds when declaring nextPacket
                if (i >= storedPackets.Length - 1)
                {
                    break;
                }


                var currentPacket = storedPackets[i];
                var nextPacket    = storedPackets[i + 1];

                // a gap will appear when two consecutive ranges are broken
                // i.e when the end of one packet range + 1 not equal to the next packet's range start
                if (currentPacket.Range.End + 1 != nextPacket.Range.Start)
                {
                    // two cases may happen here
                    // 1- a user seeking to unbuffer location so we have a gab
                    // 2- a buffered location faced an inturrupting ad
                    // case #2 is handled in AddPacket (newComingIntersectWithAlreadyStored flag) so it will not occure here
                    // i will add broken ranges to lostPacketsRanges to handle them later
                    var start = currentPacket.Range.End + 1;
                    var end   = nextPacket.Range.Start - 1;
                    lostPacketsRanges.Add(new Range(start, end));
                }
            }
            return(lostPacketsRanges);
        }
Ejemplo n.º 5
0
        private YoutubeMediaPacket _getTheLastAddedMediaPacket(YoutubeMediaPacketType typeToSearchFor)
        {
            // lock is for "Exception thrown: 'System.ArgumentException' in mscorlib.dll
            // An exception of type 'System.ArgumentException' occurred in mscorlib.dll but was not handled in user code
            // Destination array was not long enough. Check destIndex and length, and the array's lower bounds."

            lock (this.Video)
            {
                return(this.Video.Packets.ToList() // ToList to avoid (Collection was modified; enumeration operation may not execute) Exception .. see https://stackoverflow.com/questions/604831/collection-was-modified-enumeration-operation-may-not-execute
                       .Where(x => x.VideoPacketType == typeToSearchFor)
                       .OrderByDescending(x => x.Range.End).FirstOrDefault());
            }
        }
Ejemplo n.º 6
0
        private async Task <bool> _populate(YoutubeMediaPacketType type, string filePath)
        {
            return(await Task.Run(() =>
            {
                Debug.WriteLine(type + " packets clen : " + this.Video.Packets.Where(x => x.VideoPacketType == type).First().OverAllLength);
                var sorted = this.Video.Packets.Where(x => x.VideoPacketType == type).OrderBy(x => x.Range.Start).ToList();
                sorted.ForEach(item =>
                {
                    Debug.WriteLine("Appending Packet : " + item.VideoPacketType.ToString() + " " + item.Range.Start + "-" + item.Range.End + " :: " + item.FilePath);

                    Helpers.Misc.AppendAllBytes(filePath, File.ReadAllBytes(item.FilePath));
                });
                return true;
            }));
        }
Ejemplo n.º 7
0
        private YoutubeMediaPacketType _parseMediaPacketType(string sessionContentType)
        {
            // returns the videoMediaType from a contentType header
            YoutubeMediaPacketType PacketType = YoutubeMediaPacketType.Unknown;

            if (sessionContentType.StartsWith("video"))
            {
                PacketType = YoutubeMediaPacketType.Video;
            }

            if (sessionContentType.StartsWith("audio"))
            {
                PacketType = YoutubeMediaPacketType.Audio;
            }

            return(PacketType);
        }
Ejemplo n.º 8
0
        private async Task _handleYoutubePacket(SessionEventArgs session)
        {
            // check if the packet in session is Audio or Video
            YoutubeMediaPacketType PacketType = _parseMediaPacketType(session.HttpClient.Response.Headers.Headers["Content-Type"].Value);

            // if content type is not video nor audio cancel it
            if (PacketType == YoutubeMediaPacketType.Unknown)
            {
                return;
            }

            var requestURL = requestURLFromSession(session);

            // making sure that the packet is valid to parse
            if (!YoutubeMediaPacket.IsValidYoutubeRequestURL(requestURL))
            {
                return;
            }

            byte[] bodyBytes = await session.GetResponseBody();

            var newPacket = new YoutubeMediaPacket(PacketType, requestURL, bodyBytes);

            // if videos list contains a video with the same fingerprint append the packet to it
            // otherwise create another video and add new packet to
            bool isVideoAddedBefore = this.VideosManagers.Any(x => x.Video.VideoFingerPrint == newPacket.VideoFingerPrint);

            if (!isVideoAddedBefore)
            {
                var newVideo        = new YoutubeVideo(newPacket.VideoFingerPrint);
                var newVideoManager = new YoutubeVideoManager(newVideo, _client);
                VideosManagers.Add(newVideoManager);
                newVideoManager.OnYoutubeLastPacketRecieved += videoLastPacketRecieved;
                newVideoManager.OnYoutubeStored             += NewVideoManager_OnYoutubeStored;
                newVideoManager.AddPacketFile(newPacket);
            }
            else
            {
                var packetVideo = VideosManagers.Where(x => x.Video.VideoFingerPrint == newPacket.VideoFingerPrint).FirstOrDefault();
                packetVideo.AddPacketFile(newPacket);
            }
        }
Ejemplo n.º 9
0
        private double?_computePacketsSum(YoutubeMediaPacketType type)
        {
            var higherQualityPacket = _getHigherQualityPacket();

            if (higherQualityPacket == null)
            {
                return(null);
            }

            int?higherQuality = higherQualityPacket.PacketMediaFileDataInfo.VerticalResolution;

            if (!higherQuality.HasValue)
            {
                return(null);
            }

            return(this.Packets
                   .Where(x => x.VideoPacketType == type)
                   .Sum(x => x.Range.Length));
        }
Ejemplo n.º 10
0
        private async Task _fillBrokenRanges(List <Range> lostPacketsRanges, YoutubeMediaPacketType lostPacketsType)
        {
            // debugging purposes
            if (lostPacketsRanges.Count > 0)
            {
                YTrackLogger.Log("\nBroken Ranges for type " + lostPacketsType + " : \n");
                lostPacketsRanges.ForEach(x =>
                {
                    YTrackLogger.Log(x.ToString());
                });
                YTrackLogger.Log("\n\n");
            }


            // constructing the lost packates new requests and fetch them
            // firstly i will get clone from  first packet url
            // no need for higher quality checks because lower ones are already removed
            var lostPacketRequestURL = this.Video.Packets.FirstOrDefault(x => x.VideoPacketType == lostPacketsType)?.YoutubeRequestURL?.DeepClone();


            // Youtube Contains M4A containers .... the video may contain only media with Audio content type
            // if no video packets are present return
            if (lostPacketRequestURL == null)
            {
                return;
            }


            // now loop throught all lost packets and fill them
            foreach (var lostRange in lostPacketsRanges)
            {
                var newPacket = await _fillGab(lostPacketRequestURL, lostRange, lostPacketsType);

                _insertGabPacket(newPacket);
            }
        }
Ejemplo n.º 11
0
        private async Task <YoutubeMediaPacket> _fillGab(YoutubeRequestURL packetRequestURL, Range lostRange, YoutubeMediaPacketType type)
        {
            packetRequestURL.RequestPath.QueryString.SetValue("range", $"{lostRange.Start}-{lostRange.End}");
            var requestableURL = packetRequestURL.ToRequestableURL();

            // debugging
            YTrackLogger.Log("\nfilling broken range  for type " + type + " : " + lostRange.ToString() + " from : " + requestableURL);

            long httpSegmentSize = packetRequestURL.RequestPath.QueryString.HasValue("ratebypass") && packetRequestURL.RequestPath.QueryString.GetValue("ratebypass") == "yes"
                ? (long)lostRange.Length
                : 9_898_989;
            YoutubeMediaPacket packet;


            using (SegmentedHttpStream segmentedHttpStream = new SegmentedHttpStream(_client, requestableURL, (long)lostRange.Length, httpSegmentSize))
            {
                try
                {
                    string tmpFileName = Path.GetTempFileName();
                    using (Stream outputStream = new FileStream(tmpFileName, FileMode.Append))
                    {
                        IProgress <double> progressPercentage = new Progress <double>(b => packetDownloadProgressChanged(b));
                        await segmentedHttpStream.CopyToStreamAsync(outputStream, progressPercentage);
                    }
                    // no need to check whether the packetRequestURL is a valid requist URL
                    // because we requested it anyway
                    packet = new YoutubeMediaPacket(type, packetRequestURL, tmpFileName);
                    OnPacketDownloadCompleted?.Invoke(this, packet);
                }
                catch (Exception e)
                {
                    // two exception may be thrown
                    // WebException if something went wrong when fetch the new packets
                    // IOException if something went wrong when writing the packet file to disk
                    // I'll raise PacketDownloadExceptionThrown and re-throw exception
                    if (e is WebException)
                    {
                        _onGabPacketDownloadExceptionThrown?.Invoke(this, new PacketDownloadExceptionEventArgumanets()
                        {
                            Exception = e as WebException,
                            FailedPacketRequestURL = packetRequestURL,
                            Range = lostRange
                        });
                    }

                    // re-throw the error to the caller
                    Helpers.YTrackLogger.Log("Failed to download Packet : " + e.Message + "\n\n" + e.StackTrace);
                    throw;
                }
            }
            return(packet);
        }
Ejemplo n.º 12
0
 private void _truncateVideoPackets(YoutubeMediaPacketType type = YoutubeMediaPacketType.Video)
 {
     this.Video.Packets.RemoveAll(x => x.VideoPacketType == type);
 }