-
-
Notifications
You must be signed in to change notification settings - Fork 6.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[VideoPlayer] Fixed: Infinite video halt when cache is full & valid #23760
[VideoPlayer] Fixed: Infinite video halt when cache is full & valid #23760
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cannot say anything about functional correctness of the change. Just some stylistic comments from my end.
All suggestions have been duly noted and respective changes made to the code. Thanks! @ksooo |
@FernetMenta do you have any thoughts on this fix? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not saying that the fix is not necessary but I see several things that are wrong:
I never liked the dependency of VP to FileCache. So far this was only for displaying some cache related info for what reason ever. I would not make behaviour of VP dependent on FileCache. |
@thexai @FernetMenta thanks for your very informational input, guys! I will be further working on this to improve the relationship between VideoPlayer & Caching modules. Hopefully, good things will come out of this! Humbly request to whomever is responsible to not close this as such. |
@thexai @FernetMenta I believe the latest commit should be it. The actual fault was in Fixing the above meant the user being shown Thus, the line CGUIDialogKaiToast::QueueNotification(g_localizeStrings.Get(21454), g_localizeStrings.Get(21455)); The ideal situation for this toast to be appropriate would be when |
I think the actual problem that's triggering your issue is the fact that the level is set to -1 in GetCachingTimes() when low-speed conditions are hit. Perhaps introduce an additional bool in CacheInfo to allow passing proper level, even with low-speed conditions (and use the bool where appropriate)? @FernetMenta probably has a better understanding of the logic low-speed logic and how it should "work"? |
@arnova As per your suggestions, the fix has been re-introduced by adding relevant bool flags in some of the video/file cache-status structs. |
@honest-mule have you tried just to remove the existing logic that depends on FileCache from VP? I don't think the state of FileCache should have any impact on behaviour of VideoPlayer. |
@FernetMenta Might as well, soon as I get some free time in my hands. Would be a nice & fun experiment, tbh! |
Cache level calculation is wrong and in some cases is 0 when cache level is 100%. This is similar to #22881 (the root cause is the same, but I don't full understand how this level is calculated) As now exist @honest-mule test this change: diff --git a/xbmc/cores/VideoPlayer/VideoPlayer.cpp b/xbmc/cores/VideoPlayer/VideoPlayer.cpp
index 72419823d8..64fea25605 100644
--- a/xbmc/cores/VideoPlayer/VideoPlayer.cpp
+++ b/xbmc/cores/VideoPlayer/VideoPlayer.cpp
@@ -1871,7 +1871,7 @@ void CVideoPlayer::HandlePlaySpeed()
CGUIDialogKaiToast::QueueNotification(g_localizeStrings.Get(21454), g_localizeStrings.Get(21455));
SetCaching(CACHESTATE_INIT);
}
- if (cache.level >= 1.0)
+ if (cache.time > 8.0)
SetCaching(CACHESTATE_INIT);
}
else
|
@thexai I agree wholeheartedly. In my opinion the cache level should always be between Thus, the calculation in line 1850 this is wrong: 1850 info.level = (cached + queued) / (cache_need + queued); -- The change you suggested, of course, gets rid of video halting issue but introduces another predicament where the cache is never allowed to fill to a 100%. Meaning, the video playback stops every 8 seconds and then waits until the next 8 seconds of playback is available. |
This is not true: I tested proposed change and cache still used same as before: As commented VideoPlayer queue allows 8 seconds of playback and the rest from 8 to 14s is due FileCache. In the capture cache has 7.44 MB that is the default without advanced settings, then is used 100% (same as before). You a confused with "cache level required to start playback after cache dry" That doesn't have to be 100% and in fact it usually isn't. The logical strategy is to fill the cache to 100% only when start playback, but if due to an (unusual) event it is accidentally emptied during playback, you want to resume playback as soon as possible and therefore not wait to fill the cache to 100%. A usual percentage could be 20 or 30%. Since VideoPlayer queue already has 8s of data is fine even start playback with 0% of cache. It is assumed that the bandwidth of the connection on average is higher than the bit rate of the stream and therefore the cache will recover slowly (and there is also 8 seconds of margin for it to do so). If the bandwidth of the connection is less than the bit rate of the stream it will never work well, neither with cache nor without cache. The cache only covers very temporary events and high latency issues. Current trigger condition is If the condition was cache at 100% then it would be Conclusion: proposed change fixes the issue without changing the current operating mode. |
Also reproduced and confirmed original issue limiting NAS bandwidth to ~80 Mbit/s and playing high bitrate 4K video files Confirmed two things:
|
@thexai Your explanation makes it transparent that indeed, VideoPlayer should have to wait only 8 seconds before it starts playing from cache again and I concur my logic was flawed thinking the cache isn't filling up to a 100%. Most likely this should be the fix. I just have apprehensions if the logic is calculating the seconds of footage in cache correctly. Did you ran any tests for that? |
No. You still not understand this :) VideoPlayer should have to wait queue filled 100% and this allows 8 seconds of play. But is not need necessarily 8 s. to fill queue: this time depends on bandwidth of connection. But you are run in extreme case in which bandwidth is extremely limited and then read rate is only 1x or even 0.9x stream bit rate then in this special case (only) YES, you need 8 s. to read data of 8 s. of playback. This is not due code change but insufficient bandwidth to play this video. For same reason cache never is filled. |
Yes, forgive me for the poor phrasing. What I meant was VideoPlayer should only have to wait for 8 seconds of footage in cache before it starts playing from cache again. I suppose we can close this and I believe you'll be pushing the fix from your endpoint! Cheers 🍻 |
You can do it in this PR, simply remove all other changes and left only: diff --git a/xbmc/cores/VideoPlayer/VideoPlayer.cpp b/xbmc/cores/VideoPlayer/VideoPlayer.cpp
index 72419823d8..64fea25605 100644
--- a/xbmc/cores/VideoPlayer/VideoPlayer.cpp
+++ b/xbmc/cores/VideoPlayer/VideoPlayer.cpp
@@ -1871,7 +1871,7 @@ void CVideoPlayer::HandlePlaySpeed()
CGUIDialogKaiToast::QueueNotification(g_localizeStrings.Get(21454), g_localizeStrings.Get(21455));
SetCaching(CACHESTATE_INIT);
}
- if (cache.level >= 1.0)
+ if (cache.time > 8.0)
SetCaching(CACHESTATE_INIT);
}
else |
@thexai Done! |
Please rebase and squash: https://medium.com/@slamflipstrom/a-beginners-guide-to-squashing-commits-with-git-rebase-8185cf6e62ec <- like presented here as a howto. What I can already tell you is, that there is a behaviour change. For people using very large caches, that want to wait for playback start until this is full, it will now start after VideoPlayer has 8 seconds and first byte landed into the additional cache. Just saying - from my local tests - with wifi, this change works great and is most likely better than the original implementation that - as documented in this thread - no one understands anymore. |
For commit name is fine use some like PR name:
and please add a comment in second line like: The reason is 'cache.level' variable some times is 0 when cache is full due the way is calculated. Replaced with 'cache.time' that not has these problems. |
@fritsch I've done it, hope it's correct. |
Sadly not. As long as you see more than one commit in this web view, 66 now for your PR, it did not work. |
What do you suggest, another rebase attempt or a new PR? |
From your source folder:
To start from scratch |
Here is a small howto: Doing every time, when rebasing, being on the branch, you want to rebase: Here now select all the commits, you want to "put" on top. In your case, it's exactly one. Now - force push to yourself: Good luck with that. But it's important to learn it now, as some changes will follow, e.g. 8.0 being a constant falling from heaving, which we make constexpr later on. |
3410405
to
a4f6692
Compare
@fritsch Is this correct? |
Yes - you did it correctly. |
I think it would also still be an improved if we would add an additional (bool) member to CacheInfo to flag low-speed conditions instead of setting level to -1.0. That way CVideoPlayer::GetCachingTimes() can always return proper level AND flag low-speed conditions at the same time. This has always felt a bit akward. |
Current issue is when level is not -1 precisely. The level calculation bug is for positive values so changing this would not solve this problem. Anyway, is supposed that when is produced "low speed condition" cache is not filled because connection bandwidth is less than required stream bitrate, then level is ~0 and is not need calculate (seems fine use -1 to signal this condition). |
@fritsch made a great point which no one has picked on yet:
This can only be resolved by adding new user-flags to |
Maybe or based if user has a cache related advanced setting or not. My point is: the usecase to load 200 or 300 MB into a cache so that consequent Playback of the 600M file would work with an ISDN 56kbit/s Connection is most likely a usecase from the past anyways. If not, it should not break ordinary Joe's playback cause we have forgotten how to properly calculate level internally ;-) From my pov: cache handling needs huge overhaul in general, the change here makes it at least understandable by using time based judgement. Curious though if it breaks other things that worked by luck. We will find out. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As this fixes a real issue let's merge it and leave others changes/improvements for future
Ah thanks for explaining that. I finally understand that piece of the puzzle (=why the level gets set to -1 with low-speed conditions). |
Edit: this PR is not the issue. The linked one is. Hey, I'm currently developing PlexMod4Kodi and have added a "Slow connection" feature recently. It pauses the video and waits for I'm currently using an unreasonable cache size of 2000 MB and a readfactor of 20. After this PR, it seems like the buffer doesn't fill anymore (when the video is paused) - which it did before. Right now Kodi only buffers a certain percentage even while playing back, even though the buffer is huge and the readfactor is 20. This is unexpected, as it was possible before to fill up the buffer as much as possible (even loading the full file into the buffer, then resuming, worked flawlessly). Edit: Oh wait, this seems to be the issue. |
20 readfactor also is unreasonable. Reason: 120 Mbps BluRay file * 20 = 2400 Mbps this means saturate 1000 Mbps (1 Gbps Ethernet) unnecessarily and creating CPU spikes to fill the cache.
Then correct way is fix this internally while use 2000 MB cache size, 20 read factor and hack advancersettings is the wrong way. |
+ added SCacheStatus parameters to GetGeneralInfo()
Description
HandlePlaySpeed()
inCVideoPlayer
class has been added with a multi-conditional clause to account for resuming playback when cache is at it's appropriate level.If the user the has set
cache->memorysize
in theiradvancedsettings.xml
then it will be used for basic gauging purposes.GetGeneralInfo()
has been modified to keep track ofSCacheStatus
parameters for debug purposes.Motivation and context
In the quest to enhance Kodi's performance and reliability, I've identified and addressed a specific bug that affects users with low-speed network connections. This issue is quite intricate and impacts the initial caching process during video playback.
Here's the crux of the problem: When the cache initially reaches its full capacity and Kodi notifies the user that the
rate is too slow for continuous playback
, the video stutters momentarily but then plays back normally utilizing the cache as it should. Once the cache gets depleted, it unexpectedly results in video playback stalling, even after the cache returns to its 100% capacity, the VideoPlayer fails to resume the video.The motivation behind this pull request is to highlight Kodi's commitment to providing a seamless streaming experience for all Kodi users, irrespective of their network speed. By resolving this bug, I aim to ensure that video playback remains uninterrupted as long as cache reserve is at its appropriate level, offering a smoother and more enjoyable viewing experience, even under challenging network conditions.
I look forward to your feedback and collaboration.
How has this been tested?
The fix has been tested in emulated & real-time environment.
Low-speed internet connection doesn't lead to an infinite halt of video playback anymore.
What is the effect on users?
Cache-oriented smooth playback as per either user's cache memory settings or Kodi's default settings.
Screenshots (if appropriate):
Types of change
Checklist: