polybiusproxy / hxCodec

Haxe library for native video playback on HaxeFlixel and OpenFL.
https://lib.haxe.org/p/hxCodec
Mozilla Public License 2.0
108 stars 70 forks source link

Performance dips every time a VideoSprite is created #246

Closed ActualMandM closed 1 year ago

ActualMandM commented 1 year ago

Every time a VideoSprite is created, it ends up causing the performance to lower just by a little bit. Depending on the computer, this can very quickly add up and cause performance to plummet.

This can be replicated in DDTO+ versions 3.0.0 and 3.0.1 with Encore week, and any version with Love n' Funkin and Libitina. All you need to do is constantly restart the song.

https://user-images.githubusercontent.com/15317421/224878523-0da2bc80-141f-4295-bbcf-9a7b38ad3001.mp4

I was not able to replicate the issue with the intro cutscene to Sayori's week, which uses VideoHandler instead.

TheRealJake12 commented 1 year ago

Every time a VideoSprite is created, it ends up causing the performance to lower just by a little bit. Depending on the computer, this can very quickly add up and cause performance to plummet.

This can be replicated in DDTO+ versions 3.0.0 and 3.0.1 with Encore week, and any version with Love n' Funkin and Libitina. All you need to do is constantly restart the song.

I was not able to replicate the issue with the intro cutscene to Sayori's week, which uses VideoHandler instead.

3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3

lol but still. Weird issue. I don't use VideoSprite. Perhaps its an issue with it destroying or something.

polybiusproxy commented 1 year ago

Creating a VideoSprite means also creating a full sprite with bitmap data. The sequential performance dip could also be caused by improper cleaning.

Are the VideoSprites being cleaned from memory every song restart?

ActualMandM commented 1 year ago

I tried cleaning the VideoSprites in the destroy function but it didn't fix the issue.

TheRealJake12 commented 1 year ago

I tried cleaning the VideoSprites in the destroy function but it didn't fix the issue.

perhaps try setting the graphic to null. Like video.graphic = null; or something along those lines.

ActualMandM commented 1 year ago

Edit: Apparently this code causes a crash on Linux according to https://github.com/Jorge-SunSpirit/Doki-Doki-Takeover/issues/30. Hmn.

Weird, must've been the way I did it before but this time around it's working...

    override function destroy()
    {
        // Clean up VideoSprite.
        for (video in members)
        {
            var video:Dynamic = video;
            var video:VideoSprite = video;

            if (video != null && video is VideoSprite)
            {
                video.bitmap.dispose();
                video.destroy();
                video = null;
            }
        }

        super.destroy();
    }

Not sure if I should close the issue since VideoSprite should be disposing of the bitmap automatically.

ActualMandM commented 1 year ago

Oh wait, this might be an issue due to the fact that this is looping in-game, so it doesn't get cleaned up due to that.

I would look into fixing it but given that there's the 3.0 rewrite, I'm unsure about looking into it if that doesn't have this issue,

EliteMasterEric commented 1 year ago

@ActualMandM The behavior of VideoBitmap above the C++ code hasn't changed too much so the issue probably still exists.

I'd leave this open until it's resolved, VideoBitmap.destroy() should definitely dispose the contained bitmap automatically. If you want to retain the bitmap, don't call destroy().

BoloVEVO commented 1 year ago

@ActualMandM @EliteMasterEric

Using :@privateAccess to execute onVLCEndReached in VideoSprite.bitmap actually solves the problem.

videoGroup is irrelevant is just the way how I handle background videos in fnf songs [:

    override function destroy()
    {
        for (vid in daVideoGroup)
        {
            if (vid != null)
            {
                if (vid.bitmap != null)
                {
                    @:privateAccess
                    vid.bitmap.onVLCEndReached();
                }
            }
        }
                super.destroy();
         }

The reason of this is because the videoSprite bitmap is disposed and removed from displayContainer when video ends but it doesn't if you change the state before the video ends and it's not removed from the display container so basically you're adding a new vid to the display container every time you reset the state until your game explodes.

I didn't use FlxG.removeChild(vid.bitmap) because the event listeners are not removed so instead of that I forced the vidsprite to execute the end callback when I destroy my state.

Flixel automatically calls destroy in vidsprite if it's added (used add() and never called remove() on vidSprite), if not you need to manually do it. But speaking of destroy, destroy is never overriden in VideoSprite.hx so is basically calling the usual FlxSprite destroy method.

https://user-images.githubusercontent.com/88955176/227708532-8985c53c-3fc4-4a7c-bd31-38cae49909bb.mp4

polybiusproxy commented 1 year ago

Nice! Would you be able to make a pull request?

BoloVEVO commented 1 year ago

Sure

polybiusproxy commented 1 year ago

Fixed in commit 0fe5009.