kidrigger / godot-videodecoder

GDNative Video Decoder libraries for Godot Game Engine, using FFmpeg library for codecs. A Google Summer of Code Project, 2018
MIT License
84 stars 22 forks source link

set_stream_position setting the position right after setting the stream results in a black screen #16

Open arsen-ch opened 4 years ago

arsen-ch commented 4 years ago

Hi, Is set_stream_position method supported? It seems that nothing happens when the method is called from Godot.

kidrigger commented 4 years ago

It's not supported. At least yet. I had troubles working with seek.

jamie-pate commented 4 years ago

Should work now

EIREXE commented 4 years ago

@jamie-pate setting stream position seems to not be working for me, it reverts it to the first second, also setting the position right after setting the stream results in a black screen for me (running godot 3.2.1 stable on linux).

Interestingly, until I set the stream position manually the playback has terrible performance.

EIREXE commented 4 years ago

It seems like it only happens to certain webms, this webm for example presents the issue, in case you need something for testing:

https://files.catbox.moe/f1l26s.webm

jamie-pate commented 4 years ago

It seems to work fine for me: https://streamable.com/ofjpau There is some special handling required to make it work though: https://github.com/kidrigger/godot-videodecoder/blob/master/src/gdnative_videodecoder.c#L841

FIG1: how to seek while paused...
var _paused_seeking = 0
func seek_player(value):
    var was_playing = _playing
    if _playing:
        stop()
    _player.stream_position = value
    if was_playing:
        play(value)
        if _player.paused || _paused_seeking > 0:
            _player.paused = false
            _paused_seeking = _paused_seeking + 1
            # yes, it seems like 5 idle frames _is_ the magic number.
            # VideoPlayer gets notified to do NOTIFICATION_INTERNAL_PROCESS on idle frames
            # so this should always work?
            for i in range(5):
                yield(get_tree(), 'idle_frame')
            # WARNING: -= double decrements here somehow?
            _paused_seeking = _paused_seeking - 1
            assert(_paused_seeking >= 0)
            if _paused_seeking == 0:
                _player.paused = true

Basically you need to let it play for a frame because the VideoStreamGDNative class won't ask for any frames unless it's playing. This is something that will have to be fixed in godot itself.

jamie-pate commented 4 years ago

Not sure on the performance bit, one day I'll add this workaround and a proper benchmark into the test project...

EIREXE commented 4 years ago

Not sure on the performance bit, one day I'll add this workaround and a proper benchmark into the test project...

I cannot replicate the performance bit anymore, but doing the seek fixed it, thanks for the code, i'll test it!

EIREXE commented 4 years ago

Interestingly, the issue seems to happen regardless if I don't set the stream_position to -1 and then to 0 before initialization. All I get is a black screen, this is my code (using the demo):

imagen