/// <summary> /// validate the new packet and add it the video packets /// </summary> /// <param name="newPacketToAdd"></param> public void AddPacketFile(YoutubeMediaPacket newPacketToAdd) { // if the video is stored or being stored don't add any packets if (this.VideoBeingStored || VideoStored) { return; } Debug.WriteLine("adding " + newPacketToAdd.VideoPacketType.ToString() + " Packet : " + newPacketToAdd.Range.Start + "-" + newPacketToAdd.Range.End); // check if the new coming packets are having a different video quality than exiting packets // if so .. remove them and consider all of them as a gabs to fill in the final step if (newPacketToAdd.VideoPacketType == YoutubeMediaPacketType.Video && newPacketToAdd.PacketMediaFileDataInfo.VerticalResolution.HasValue && newPacketToAdd.PacketMediaFileDataInfo.VerticalResolution != this.Video.CurrentVideoVerticalRosolution) // to make sure not considering the first packet as a gab ... because _currentHigherVideoVerticalRosolution starts by 0 { this.Video.CurrentVideoVerticalRosolution = newPacketToAdd.PacketMediaFileDataInfo.VerticalResolution.Value; // truncating all previous packets _truncateVideoPackets(newPacketToAdd.VideoPacketType); } // this prevent packets from being intersecting // intersecting packets are packets that has it range intersect with the previous packets // main cause of these packets is the inturrupting video ads that rebuffer a part of stream suddenly bool newComingIntersectingPacketAlreadyStored = this.Video.Packets.ToList().Any(x => x.Range.End + 1 > newPacketToAdd.Range.Start && x.VideoPacketType == newPacketToAdd.VideoPacketType); if (!newComingIntersectingPacketAlreadyStored) { // i will add the new packet if it's range start is greater than all stored packets range's end this.Video.Packets.Add(newPacketToAdd); } _checkIfLastPacket(newPacketToAdd); }
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); }
private void _checkIfLastPacket(YoutubeMediaPacket packet) { // Get the last packet added to videos packets and the audios packets var lastVideoPacketAdded = _getTheLastAddedMediaPacket(YoutubeMediaPacketType.Video); var lastAudioPacketAdded = _getTheLastAddedMediaPacket(YoutubeMediaPacketType.Audio); // if the video does not recieve audio or video packet then don't proceed if (lastVideoPacketAdded == null || lastAudioPacketAdded == null) { return; } // if the packet is the last packet from the video stream proceed if (_doesLastAudioAndVideoPacketsRecieved()) { // now I'll raise OnYoutubeLastPacketRecieved OnYoutubeLastPacketRecieved?.Invoke(this, packet); } }
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); } }
private void _insertGabPacket(YoutubeMediaPacket packetToInsert) { lock (this.Video.Packets) { // gab is the first packet if (packetToInsert.Range.Start == 0) { this.Video.Packets.Insert(0, packetToInsert); } // gab is the last packet else if (packetToInsert.Range.End + 1 == packetToInsert.OverAllLength) { this.Video.Packets.Insert(this.Video.Packets.Count - 1, packetToInsert); } // gab is in the middle of the video packets else { // see where the previous packet is and add it after int previousPacketIndex = this.Video.Packets.FindIndex(x => (x.Range.End + 1) == packetToInsert.Range.Start); this.Video.Packets.Insert(++previousPacketIndex, packetToInsert); } } }
private void videoLastPacketRecieved(object sender, YoutubeMediaPacket lastPacket) { YoutubeVideoManager videoManager = sender as YoutubeVideoManager; OnNewVideoLastPacketRecieved?.Invoke(videoManager); }