initSourceBuffer_(contentType, stream, codecs) {
    const ContentType = shaka.util.ManifestParserUtils.ContentType;

    if (contentType == ContentType.AUDIO && codecs) {
      codecs = shaka.util.StreamUtils.getCorrectAudioCodecs(
          codecs, stream.mimeType);
    }

    let mimeType = shaka.util.MimeUtils.getFullType(
        stream.mimeType, codecs);
    if (contentType == ContentType.TEXT) {
      this.reinitText(mimeType, this.sequenceMode_, stream.external);
    } else {
      let needTransmux = this.config_.forceTransmux;
      if (!shaka.media.Capabilities.isTypeSupported(mimeType) ||
          (!this.sequenceMode_ &&
          shaka.util.MimeUtils.RAW_FORMATS.includes(mimeType))) {
        needTransmux = true;
      }
      const mimeTypeWithAllCodecs =
          shaka.util.MimeUtils.getFullTypeWithAllCodecs(
              stream.mimeType, codecs);
      if (needTransmux) {
        const audioCodec = shaka.util.ManifestParserUtils.guessCodecsSafe(
            ContentType.AUDIO, (codecs || '').split(','));
        const videoCodec = shaka.util.ManifestParserUtils.guessCodecsSafe(
            ContentType.VIDEO, (codecs || '').split(','));
        if (audioCodec && videoCodec) {
          this.needSplitMuxedContent_ = true;
          this.initSourceBuffer_(ContentType.AUDIO, stream, audioCodec);
          this.initSourceBuffer_(ContentType.VIDEO, stream, videoCodec);
          return;
        }
        const transmuxerPlugin = shaka.transmuxer.TransmuxerEngine
            .findTransmuxer(mimeTypeWithAllCodecs);
        if (transmuxerPlugin) {
          const transmuxer = transmuxerPlugin();
          this.transmuxers_.set(contentType, transmuxer);
          mimeType =
              transmuxer.convertCodecs(contentType, mimeTypeWithAllCodecs);
        }
      }
      const type = this.addExtraFeaturesToMimeType_(mimeType);

      this.destroyer_.ensureNotDestroyed();

      let sourceBuffer;

      try {
        sourceBuffer = this.mediaSource_.addSourceBuffer(type);
      } catch (exception) {
        throw new shaka.util.Error(
            shaka.util.Error.Severity.CRITICAL,
            shaka.util.Error.Category.MEDIA,
            shaka.util.Error.Code.MEDIA_SOURCE_OPERATION_THREW,
            exception,
            'The mediaSource_ status was ' + this.mediaSource_.readyState +
            ' expected \'open\'',
            null);
      }

      if (this.sequenceMode_) {
        sourceBuffer.mode =
            shaka.media.MediaSourceEngine.SourceBufferMode_.SEQUENCE;
      }

      this.eventManager_.listen(
          sourceBuffer, 'error',
          () => this.onError_(contentType));
      this.eventManager_.listen(
          sourceBuffer, 'updateend',
          () => this.onUpdateEnd_(contentType));
      this.sourceBuffers_.set(contentType, sourceBuffer);
      this.sourceBufferTypes_.set(contentType, mimeType);
      this.expectedEncryption_.set(contentType, !!stream.drmInfos.length);
    }
  }
Initialize a specific SourceBuffer.

@param {shaka.util.ManifestParserUtils.ContentType} contentType
@param {shaka.extern.Stream} stream
@param {string} codecs
@private