loadVideo(
        source,
        textureOptions = {},
        successCallback,
        errorCallback
    ) {
        const video = this._createVideo(source);

        video.preload = true;
        video.muted = true;
        video.loop = true;
        video.setAttribute("playsinline", "");

        video.crossOrigin = this.crossOrigin;

        let options = Object.assign({}, textureOptions);
        // merge texture options with its parent textures options if needed
        if(this._parent) {
            options = Object.assign(textureOptions, this._parent._texturesOptions);
        }

        options.loader = this;
        options.sampler = video.hasAttribute("data-sampler") ? video.getAttribute("data-sampler") : options.sampler;

        // create a new texture that will use our video later
        const texture = new Texture(this.renderer, options);

        // add a new entry in our elements array
        const el = this._addElement(video, texture, successCallback, errorCallback);

        // handle our loaded data event inside the texture and tell our plane when the video is ready to play
        video.addEventListener('canplaythrough', el.load, false);
        video.addEventListener('error', el.error, false);

        // If the video is in the cache of the browser,
        // the 'canplaythrough' event might have been triggered
        // before we registered the event handler.
        if(video.readyState >= video.HAVE_FUTURE_DATA && successCallback) {
            this._sourceLoaded(video, texture, successCallback);
        }

        // start loading our video
        video.load();

        // if there's a parent (PlaneTextureLoader) add texture and source to it
        this._addToParent && this._addToParent(texture, video, "video");

        // if requestVideoFrameCallback exist, use it to update our video texture
        if('requestVideoFrameCallback' in HTMLVideoElement.prototype) {
            el.videoFrameCallback = texture._videoFrameCallback.bind(texture);
            texture._videoFrameCallbackID = video.requestVideoFrameCallback(el.videoFrameCallback);
        }
    }
This method loads a video
     Creates a new texture object right away and once the video has enough data it uses it as our WebGL texture

     params:
     @source (video): html video element
     @textureOptions (object): parameters to apply to the textures, such as sampler name, repeat wrapping, filters, anisotropy...
     @successCallback (function): function to execute when the source has been loaded
     @errorCallback (function): function to execute if the source fails to load
*