register (player, plugin, options = {}) {
    if (!player || !plugin || typeof plugin !== 'function' || plugin.prototype === undefined) {
      return
    }
    const cgid = player._pluginInfoId
    if (!cgid || !this.pluginGroup[cgid]) {
      return
    }
    if (!this.pluginGroup[cgid]._plugins) {
      this.pluginGroup[cgid]._plugins = {}
    }
    const plugins = this.pluginGroup[cgid]._plugins
    const originalOptions = this.pluginGroup[cgid]._originalOptions
    options.player = player

    const pluginName = options.pluginName || plugin.pluginName
    if (!pluginName) {
      throw new Error('The property pluginName is necessary')
    }

    if (plugin.isSupported && !plugin.isSupported(player.config.mediaType, player.config.codecType)) {
      console.warn(`not supported plugin [${pluginName}]`)
      return
    }

    if (!options.config) {
      options.config = {}
    }

    // get config items from player.config
    const keys = Object.keys(originalOptions)
    for (let i = 0; i < keys.length; i++) {
      if (pluginName.toLowerCase() === keys[i].toLowerCase()) {
        const config = originalOptions[keys[i]]
        if (Util.typeOf(config) === 'Object') {
          options.config = Object.assign({}, options.config, originalOptions[keys[i]])
        } else if (Util.typeOf(config) === 'Boolean') {
          options.config.disable = !config
        }
        break
      }
    }

    // copy the default configuration items of the plugin
    if (plugin.defaultConfig) {
      Object.keys(plugin.defaultConfig).forEach(key => {
        if (typeof options.config[key] === 'undefined') {
          options.config[key] = plugin.defaultConfig[key]
        }
      })
    }

    // get the parent dom which added the plugin will be mounted
    if (!options.root) {
      options.root = player.root
    } else if (typeof options.root === 'string') {
      options.root = player[options.root]
    }

    options.index = options.config.index || 0
    try {
      // if there is already a plugin instance with the same pluginName, destroy it
      if (plugins[pluginName.toLowerCase()]) {
        this.unRegister(cgid, pluginName.toLowerCase())
        console.warn(`the is one plugin with same pluginName [${pluginName}] exist, destroy the old instance`)
      }
      // eslint-disable-next-line new-cap
      const _instance = new plugin(options)
      plugins[pluginName.toLowerCase()] = _instance
      plugins[pluginName.toLowerCase()].func = plugin
      if (_instance && typeof _instance.afterCreate === 'function') {
        _instance.afterCreate()
      }
      return _instance
    } catch (err) {
      console.error(err)
      throw (err)
    }
  }
register a Plugin
@param { any } player the plugins register
@param { any } plugin the plugin contructor
@param { any } options the plugin configuration
@return { any } Plugin the plugin instance