godot
godot copied to clipboard
SceneTreeTimer breaks when playing a video in loop
Tested versions
v4.3 stable
System information
Windows 10, Ryzen 3 3300x, 16gb RAM 2666mhz, GTX 1660 6gb.
Issue description
If the video is looping, for whatever reason, the timer breaks and never returns the timeout signal.
@onready var _video: VideoStreamPlayer = $video
var timer : SceneTreeTimer
func _ready() -> void:
print('Starting')
await _execute_and_stop()
print('\n\nFinished!\n\n')
func _execute_and_stop() -> void:
_video.play()
timer = get_tree().create_timer(10, true) # Error.
#timer = get_tree().create_timer(10, true, true) # ok.
await timer.timeout
_video.stop()
Playing a video with 6.9166667 sec (166 frames at 24fps), using a timer with 10 sec, that's the log I get when printing the 'time_left' in the SceneTreeTimer.
3.30371609090929
3.29765548484868
3.29159487878808
3.28553427272747
3.27947366666686
3.27341306060626
3.26735245454565
3.26129184848505
3.25523124242444
3.24917063636383
3.24311003030323
3.23704942424262
3.23098881818202
3.22492821212141
3.2188676060608
3.2128070000002
3.20674639393959
3.20068578787899
3.19462518181838
3.18856457575778
3.18250396969717
3.17644336363656
3.17038275757596
3.16432215151535
3.15826154545475
3.15220093939414
3.14614033333353
3.14007972727293
3.13401912121232
3.12795851515172
3.12189790909111
3.1158373030305
3.1097766969699
3.10371609090929
3.09765548484869
3.09159487878808
3.08553427272748
3.07947366666687
3.07341306060626
3.06735245454566
3.06129184848505
3.05523124242445
14745887137786335000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
14745887137786335000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
14745887137786335000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
14745887137786335000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
14745887137786335000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
In the MRP, there are 2 videos. For reasons I don't understand, the timer works ok when updating in the physics frame, but not in the process frame. Also, the first video1 works ok, but the video2 breaks the timer...
Steps to reproduce
As shown in the script above.
Minimal reproduction project (MRP)
I can't reproduce the problem using the MRP. Also tried various combinations.
I can't reproduce the problem using the MRP. Also tried various combinations.
that's odd. The timer breaks exactly when the video2 loops, at ~3.05 sec remaining. How can this be system-specific?
that's odd. The timer breaks exactly when the video2 loops, at ~3.05 sec remaining. How can this be system-specific?
I could reproduce it using MRP
Seems that MinGW is doing some strange stuff with the code (again), i tested the mrp and in a build made with MSVC and the code works as expected, but compiled with MinGW has a strange behavior:
Godot v4.4.dev.custom_build [4631a617e], MSVC with production=yes:
https://github.com/user-attachments/assets/ad1d046d-be91-4078-84a1-07a4107d57a8
Godot v4.4.dev.custom_build [4631a617e], MinGW with production=yes lto=none
https://github.com/user-attachments/assets/789e4dfd-bf9e-49af-b817-97eab73a0f16
Godot v4.4.dev3.official [f4af8201b]
https://github.com/user-attachments/assets/accae297-a0ef-4026-857e-3858420e077a
Godot v4.4.dev3.official [f4af8201b] with loop = false
https://github.com/user-attachments/assets/be75b3d2-e977-43c0-9a5d-04d57c60c3f5
Maybe my compiled version with MinGW doesn't reproduce the bug in the same way like the official builds because the lto=none or maybe because the MinGW version (14.1.0 in my case) but using the official builds i reproduce the bug in the same way the issue shows. Also commenting the code that starts the video seems to make the timer work as expected in my self compiled build with MinGW.
I'm not able to see any of the videos you've sent. I suppose you encoded the videos with H.265 (HEVC)? I tried that once and had the same issue.
I suppose you encoded the videos with H.265 (HEVC)?
Yes, strange that i can see normally in my pc and phone.
But anyways, here what happens in my compiled build with MinGW:
Starting
10
9.96600733333333
9.94934066666667
9.94019966666667
9.94007104166223
9.93882166666667
9.93333333333333
9.92777777777778
9.92777777777778
9.91096377777778
9.89463577777778
9.89463577777778
9.87717377777778
9.87717377777778
9.85964777777778
9.84334977777777
9.84334977777777
9.82669577777777
0
Finished!
I took a look on the code related to SceneTreeTimer today and found something
https://github.com/godotengine/godot/blob/08f9cba0fbf27f171dea55de6f8274928b9f0d84/scene/main/scene_tree.cpp#L568-L602
Here p_time is used to process the timers and tweens, and for some reason between _process(false) and _flush_ugc() p_time can receive a strange number (which make SceneTreeTimer.time_left become that big number) or become a NaN (which makes SceneTreeTimer.time_left imediatly go to zero). Here a video that shows the bug hapenning, notice that process_time always keep normal (Youtube link for anyone that can't see the video here):
https://github.com/user-attachments/assets/8ac41c01-2fae-4a48-8ae3-75c56c64461c
Now if instead pass p_time for process_timers and process_tweens we pass process_time the bug simply dissapear, even p_time keep the normal value (Youtube link):
https://github.com/user-attachments/assets/2c090269-4c27-4c4b-9212-e8de1ce0d4b8
Another test i did was create a double variable in SceneTree.h and create a const double inside SceneTree::process to check if they also would break and that's what happens (Youtube link):
https://github.com/user-attachments/assets/701e7df4-c6c7-416c-8e44-3781087f2c74
All the tests was made using Godot 08f9cba0f and compiling using MinGW with production=yes lto=none debug_symbols=yes (as said in my first commentary MSVC don't have this issue)
Use process_time as parameter to call process_timers and process_tweens works but seems like hiding another bug so i wanted some insight before do anything else. @timothyqiu any idea why this is happening?
This is probably the same as #103106. Can someone please test the proposed fix?
@berarma Actually i tested the 4.4 rc 1 and this bug was fixed, so i did some tests and seems your pr #101958 (more specificly the commit f2475326a42bbdf20dab614db9ac32bc105c8a84) fixed this issue
Fixed by #101958.