Skip to content
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

Player.Destroy() and then Player.New() with websocket gives error with WebSocket URL #407

Closed
GenGol opened this issue Sep 19, 2022 · 2 comments

Comments

@GenGol
Copy link

GenGol commented Sep 19, 2022

I'm using JSMpeg using websockets. Player works fine the first time using a webSocket URL. I then I call player.destroy() which works fine.

BUT when I try to call JSMpeg.Player(webSocketURL, options) again I get the following error:

host-report-errors.js?44de:6 Unhandled promise rejection TypeError: Cannot read properties of null (reading 'restoreContext')
    at new WebGLRenderer (jsmpeg.js?bbb2:4180:1)
    at new Player (jsmpeg.js?bbb2:325:1)
    at SourceView.setupNewPlayer (source-view.js?0110:260:1)
    at eval (source-view.js?0110:326:1)
    at eval (es.promise.js?e6cf:107:1)

I've gone into the code and commented out the renderer.destroy() and it works fine:

Player.prototype.destroy = function() {
	this.pause();
	this.source.destroy();
	this.video && this.video.destroy();
	// this.renderer && this.renderer.destroy();
	this.audio && this.audio.destroy();
	this.audioOut && this.audioOut.destroy();
};

This is what my instantiation of the player looks like:

    setupNewPlayer(playerCanvas) {
        this.player = new JSMpeg.Player(this.webSocketUrl, {
            canvas: playerCanvas,
            audio: true,
            source: MetadataWrapper,
            onmeta: data => {
                function pad(value) {
                    return `0${value}`.slice(-2);
                }

                this.leftChan = 0;
                this.rightChan = 0;

                const hour = data[3];
                const minute = data[2];
                const second = data[1];
                const frame = data[0];

                if (frame !== 255) {
                    // Seems that the slicer may not have time data
                    this.slicerTime = `${hour}:${pad(minute)}:${pad(second)};${pad(frame)}`;
                }
                this.leftChan = Math.floor(data[9] * 0.18);
                this.rightChan = Math.floor(data[10] * 0.18);
            },
            protocols: [],
        });
    }

Is there some other way I should be doing this?

@phoboslab
Copy link
Owner

phoboslab commented Sep 20, 2022

The above commit should fix this.

Turns out, explicitly calling gl.getExtension('WEBGL_lose_context').loseContext() to destroy the WebGL context is not a good idea. loseContext() should only be used to "simulate" the glcontextlost event. So I have removed this functionality from the WebGL .destroy() method.

Furthermore, the canvas element is only removed from the document when calling .destroy() if it was created by the renderer. If the canvas element was handed over to the renderer (through the options.canvas in the Player constructor), it is left alone.

So, with this you can destroy() and re-create a JSMpeg.Player with the same canvas element, provided that it uses the same rendering method (2d or WebGL) as before.

@GenGol
Copy link
Author

GenGol commented Sep 20, 2022

I figured there was probably more to it. I've been testing these changes and so far so good. I haven't noticed any issues. Thank you for your help and efforts!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants