godot icon indicating copy to clipboard operation
godot copied to clipboard

SceneTreeTimer breaks when playing a video in loop

Open caioraphael1 opened this issue 1 year ago • 4 comments

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)

demo_timer.zip

caioraphael1 avatar Oct 18 '24 17:10 caioraphael1

I can't reproduce the problem using the MRP. Also tried various combinations.

timothyqiu avatar Oct 18 '24 17:10 timothyqiu

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?

caioraphael1 avatar Oct 18 '24 17:10 caioraphael1

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

Loff3 avatar Oct 18 '24 18:10 Loff3

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.

matheusmdx avatar Oct 19 '24 00:10 matheusmdx

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.

caioraphael1 avatar Oct 19 '24 00:10 caioraphael1

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!

matheusmdx avatar Oct 19 '24 09:10 matheusmdx

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?

matheusmdx avatar Oct 30 '24 00:10 matheusmdx

This is probably the same as #103106. Can someone please test the proposed fix?

berarma avatar Feb 22 '25 11:02 berarma

@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

matheusmdx avatar Feb 22 '25 23:02 matheusmdx

Fixed by #101958.

akien-mga avatar Feb 23 '25 00:02 akien-mga