Java Code Examples for com.google.android.exoplayer2.C#AUDIO_SESSION_ID_UNSET

The following examples show how to use com.google.android.exoplayer2.C#AUDIO_SESSION_ID_UNSET . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: DefaultTrackSelector.java    From MediaSDK with Apache License 2.0 6 votes vote down vote up
private void setInitialValuesWithoutContext(@UnderInitialization ParametersBuilder this) {
  // Video
  maxVideoWidth = Integer.MAX_VALUE;
  maxVideoHeight = Integer.MAX_VALUE;
  maxVideoFrameRate = Integer.MAX_VALUE;
  maxVideoBitrate = Integer.MAX_VALUE;
  exceedVideoConstraintsIfNecessary = true;
  allowVideoMixedMimeTypeAdaptiveness = false;
  allowVideoNonSeamlessAdaptiveness = true;
  viewportWidth = Integer.MAX_VALUE;
  viewportHeight = Integer.MAX_VALUE;
  viewportOrientationMayChange = true;
  // Audio
  maxAudioChannelCount = Integer.MAX_VALUE;
  maxAudioBitrate = Integer.MAX_VALUE;
  exceedAudioConstraintsIfNecessary = true;
  allowAudioMixedMimeTypeAdaptiveness = false;
  allowAudioMixedSampleRateAdaptiveness = false;
  allowAudioMixedChannelCountAdaptiveness = false;
  // General
  forceLowestBitrate = false;
  forceHighestSupportedBitrate = false;
  exceedRendererCapabilitiesIfNecessary = true;
  tunnelingAudioSessionId = C.AUDIO_SESSION_ID_UNSET;
}
 
Example 2
Source File: DefaultTrackSelector.java    From TelePlus-Android with GNU General Public License v2.0 6 votes vote down vote up
private Parameters() {
  this(
      /* selectionOverrides= */ new SparseArray<>(),
      /* rendererDisabledFlags= */ new SparseBooleanArray(),
      /* preferredAudioLanguage= */ null,
      /* preferredTextLanguage= */ null,
      /* selectUndeterminedTextLanguage= */ false,
      /* disabledTextTrackSelectionFlags= */ 0,
      /* forceLowestBitrate= */ false,
      /* allowMixedMimeAdaptiveness= */ false,
      /* allowNonSeamlessAdaptiveness= */ true,
      /* maxVideoWidth= */ Integer.MAX_VALUE,
      /* maxVideoHeight= */ Integer.MAX_VALUE,
      /* maxVideoBitrate= */ Integer.MAX_VALUE,
      /* exceedVideoConstraintsIfNecessary= */ true,
      /* exceedRendererCapabilitiesIfNecessary= */ true,
      /* viewportWidth= */ Integer.MAX_VALUE,
      /* viewportHeight= */ Integer.MAX_VALUE,
      /* viewportOrientationMayChange= */ true,
      /* tunnelingAudioSessionId= */ C.AUDIO_SESSION_ID_UNSET);
}
 
Example 3
Source File: MediaCodecVideoRenderer.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Returns the framework {@link MediaFormat} that should be used to configure the decoder.
 *
 * @param format The format of media.
 * @param codecMaxValues Codec max values that should be used when configuring the decoder.
 * @param codecOperatingRate The codec operating rate, or {@link #CODEC_OPERATING_RATE_UNSET} if
 *     no codec operating rate should be set.
 * @param deviceNeedsAutoFrcWorkaround Whether the device is known to enable frame-rate conversion
 *     logic that negatively impacts ExoPlayer.
 * @param tunnelingAudioSessionId The audio session id to use for tunneling, or {@link
 *     C#AUDIO_SESSION_ID_UNSET} if tunneling should not be enabled.
 * @return The framework {@link MediaFormat} that should be used to configure the decoder.
 */
@SuppressLint("InlinedApi")
protected MediaFormat getMediaFormat(
    Format format,
    CodecMaxValues codecMaxValues,
    float codecOperatingRate,
    boolean deviceNeedsAutoFrcWorkaround,
    int tunnelingAudioSessionId) {
  MediaFormat mediaFormat = new MediaFormat();
  // Set format parameters that should always be set.
  mediaFormat.setString(MediaFormat.KEY_MIME, format.sampleMimeType);
  mediaFormat.setInteger(MediaFormat.KEY_WIDTH, format.width);
  mediaFormat.setInteger(MediaFormat.KEY_HEIGHT, format.height);
  MediaFormatUtil.setCsdBuffers(mediaFormat, format.initializationData);
  // Set format parameters that may be unset.
  MediaFormatUtil.maybeSetFloat(mediaFormat, MediaFormat.KEY_FRAME_RATE, format.frameRate);
  MediaFormatUtil.maybeSetInteger(mediaFormat, MediaFormat.KEY_ROTATION, format.rotationDegrees);
  MediaFormatUtil.maybeSetColorInfo(mediaFormat, format.colorInfo);
  // Set codec max values.
  mediaFormat.setInteger(MediaFormat.KEY_MAX_WIDTH, codecMaxValues.width);
  mediaFormat.setInteger(MediaFormat.KEY_MAX_HEIGHT, codecMaxValues.height);
  MediaFormatUtil.maybeSetInteger(
      mediaFormat, MediaFormat.KEY_MAX_INPUT_SIZE, codecMaxValues.inputSize);
  // Set codec configuration values.
  if (Util.SDK_INT >= 23) {
    mediaFormat.setInteger(MediaFormat.KEY_PRIORITY, 0 /* realtime priority */);
    if (codecOperatingRate != CODEC_OPERATING_RATE_UNSET) {
      mediaFormat.setFloat(MediaFormat.KEY_OPERATING_RATE, codecOperatingRate);
    }
  }
  if (deviceNeedsAutoFrcWorkaround) {
    mediaFormat.setInteger("auto-frc", 0);
  }
  if (tunnelingAudioSessionId != C.AUDIO_SESSION_ID_UNSET) {
    configureTunnelingV21(mediaFormat, tunnelingAudioSessionId);
  }
  return mediaFormat;
}
 
Example 4
Source File: DefaultAudioSink.java    From Telegram-FOSS with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Creates a new default audio sink, optionally using float output for high resolution PCM and
 * with the specified {@code audioProcessorChain}.
 *
 * @param audioCapabilities The audio capabilities for playback on this device. May be null if the
 *     default capabilities (no encoded audio passthrough support) should be assumed.
 * @param audioProcessorChain An {@link AudioProcessorChain} which is used to apply playback
 *     parameters adjustments. The instance passed in must not be reused in other sinks.
 * @param enableConvertHighResIntPcmToFloat Whether to enable conversion of high resolution
 *     integer PCM to 32-bit float for output, if possible. Functionality that uses 16-bit integer
 *     audio processing (for example, speed and pitch adjustment) will not be available when float
 *     output is in use.
 */
public DefaultAudioSink(
    @Nullable AudioCapabilities audioCapabilities,
    AudioProcessorChain audioProcessorChain,
    boolean enableConvertHighResIntPcmToFloat) {
  this.audioCapabilities = audioCapabilities;
  this.audioProcessorChain = Assertions.checkNotNull(audioProcessorChain);
  this.enableConvertHighResIntPcmToFloat = enableConvertHighResIntPcmToFloat;
  releasingConditionVariable = new ConditionVariable(true);
  audioTrackPositionTracker = new AudioTrackPositionTracker(new PositionTrackerListener());
  channelMappingAudioProcessor = new ChannelMappingAudioProcessor();
  trimmingAudioProcessor = new TrimmingAudioProcessor();
  ArrayList<AudioProcessor> toIntPcmAudioProcessors = new ArrayList<>();
  Collections.addAll(
      toIntPcmAudioProcessors,
      new ResamplingAudioProcessor(),
      channelMappingAudioProcessor,
      trimmingAudioProcessor);
  Collections.addAll(toIntPcmAudioProcessors, audioProcessorChain.getAudioProcessors());
  toIntPcmAvailableAudioProcessors = toIntPcmAudioProcessors.toArray(new AudioProcessor[0]);
  toFloatPcmAvailableAudioProcessors = new AudioProcessor[] {new FloatResamplingAudioProcessor()};
  volume = 1.0f;
  startMediaTimeState = START_NOT_SET;
  audioAttributes = AudioAttributes.DEFAULT;
  audioSessionId = C.AUDIO_SESSION_ID_UNSET;
  auxEffectInfo = new AuxEffectInfo(AuxEffectInfo.NO_AUX_EFFECT_ID, 0f);
  playbackParameters = PlaybackParameters.DEFAULT;
  drainingAudioProcessorIndex = C.INDEX_UNSET;
  activeAudioProcessors = new AudioProcessor[0];
  outputBuffers = new ByteBuffer[0];
  playbackParametersCheckpoints = new ArrayDeque<>();
}
 
Example 5
Source File: SimpleDecoderAudioRenderer.java    From Telegram with GNU General Public License v2.0 5 votes vote down vote up
@Override
protected void onEnabled(boolean joining) throws ExoPlaybackException {
  decoderCounters = new DecoderCounters();
  eventDispatcher.enabled(decoderCounters);
  int tunnelingAudioSessionId = getConfiguration().tunnelingAudioSessionId;
  if (tunnelingAudioSessionId != C.AUDIO_SESSION_ID_UNSET) {
    audioSink.enableTunnelingV21(tunnelingAudioSessionId);
  } else {
    audioSink.disableTunneling();
  }
}
 
Example 6
Source File: SimpleDecoderAudioRenderer.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
@Override
protected void onEnabled(boolean joining) throws ExoPlaybackException {
  decoderCounters = new DecoderCounters();
  eventDispatcher.enabled(decoderCounters);
  int tunnelingAudioSessionId = getConfiguration().tunnelingAudioSessionId;
  if (tunnelingAudioSessionId != C.AUDIO_SESSION_ID_UNSET) {
    audioSink.enableTunnelingV21(tunnelingAudioSessionId);
  } else {
    audioSink.disableTunneling();
  }
}
 
Example 7
Source File: AudioTrack.java    From K-Sonic with MIT License 5 votes vote down vote up
/**
 * Sets the stream type for audio track. If the stream type has changed and if the audio track
 * is not configured for use with tunneling, then the audio track is reset and the audio session
 * id is cleared.
 * <p>
 * If the audio track is configured for use with tunneling then the stream type is ignored, the
 * audio track is not reset and the audio session id is not cleared. The passed stream type will
 * be used if the audio track is later re-configured into non-tunneled mode.
 *
 * @param streamType The {@link C.StreamType} to use for audio output.
 */
public void setStreamType(@C.StreamType int streamType) {
  if (this.streamType == streamType) {
    return;
  }
  this.streamType = streamType;
  if (tunneling) {
    // The stream type is ignored in tunneling mode, so no need to reset.
    return;
  }
  reset();
  audioSessionId = C.AUDIO_SESSION_ID_UNSET;
}
 
Example 8
Source File: MediaCodecAudioRenderer.java    From K-Sonic with MIT License 5 votes vote down vote up
@Override
protected void onEnabled(boolean joining) throws ExoPlaybackException {
  super.onEnabled(joining);
  eventDispatcher.enabled(decoderCounters);
  int tunnelingAudioSessionId = getConfiguration().tunnelingAudioSessionId;
  if (tunnelingAudioSessionId != C.AUDIO_SESSION_ID_UNSET) {
    audioTrack.enableTunnelingV21(tunnelingAudioSessionId);
  } else {
    audioTrack.disableTunneling();
  }
}
 
Example 9
Source File: SimpleDecoderAudioRenderer.java    From K-Sonic with MIT License 5 votes vote down vote up
@Override
protected void onEnabled(boolean joining) throws ExoPlaybackException {
  decoderCounters = new DecoderCounters();
  eventDispatcher.enabled(decoderCounters);
  int tunnelingAudioSessionId = getConfiguration().tunnelingAudioSessionId;
  if (tunnelingAudioSessionId != C.AUDIO_SESSION_ID_UNSET) {
    audioTrack.enableTunnelingV21(tunnelingAudioSessionId);
  } else {
    audioTrack.disableTunneling();
  }
}
 
Example 10
Source File: MediaCodecVideoRenderer.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
@Override
protected void onEnabled(boolean joining) throws ExoPlaybackException {
  super.onEnabled(joining);
  int oldTunnelingAudioSessionId = tunnelingAudioSessionId;
  tunnelingAudioSessionId = getConfiguration().tunnelingAudioSessionId;
  tunneling = tunnelingAudioSessionId != C.AUDIO_SESSION_ID_UNSET;
  if (tunnelingAudioSessionId != oldTunnelingAudioSessionId) {
    releaseCodec();
  }
  eventDispatcher.enabled(decoderCounters);
  frameReleaseTimeHelper.enable();
}
 
Example 11
Source File: DefaultAudioSink.java    From Telegram-FOSS with GNU General Public License v2.0 5 votes vote down vote up
@Override
public void setAudioAttributes(AudioAttributes audioAttributes) {
  if (this.audioAttributes.equals(audioAttributes)) {
    return;
  }
  this.audioAttributes = audioAttributes;
  if (tunneling) {
    // The audio attributes are ignored in tunneling mode, so no need to reset.
    return;
  }
  flush();
  audioSessionId = C.AUDIO_SESSION_ID_UNSET;
}
 
Example 12
Source File: MediaCodecVideoRenderer.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
@Override
protected void onEnabled(boolean joining) throws ExoPlaybackException {
  super.onEnabled(joining);
  tunnelingAudioSessionId = getConfiguration().tunnelingAudioSessionId;
  tunneling = tunnelingAudioSessionId != C.AUDIO_SESSION_ID_UNSET;
  eventDispatcher.enabled(decoderCounters);
  frameReleaseTimeHelper.enable();
}
 
Example 13
Source File: DefaultAudioSink.java    From Telegram with GNU General Public License v2.0 5 votes vote down vote up
@TargetApi(21)
private AudioTrack createAudioTrackV21(
    boolean tunneling, AudioAttributes audioAttributes, int audioSessionId) {
  android.media.AudioAttributes attributes;
  if (tunneling) {
    attributes =
        new android.media.AudioAttributes.Builder()
            .setContentType(android.media.AudioAttributes.CONTENT_TYPE_MOVIE)
            .setFlags(android.media.AudioAttributes.FLAG_HW_AV_SYNC)
            .setUsage(android.media.AudioAttributes.USAGE_MEDIA)
            .build();
  } else {
    attributes = audioAttributes.getAudioAttributesV21();
  }
  AudioFormat format =
      new AudioFormat.Builder()
          .setChannelMask(outputChannelConfig)
          .setEncoding(outputEncoding)
          .setSampleRate(outputSampleRate)
          .build();
  return new AudioTrack(
      attributes,
      format,
      bufferSize,
      MODE_STREAM,
      audioSessionId != C.AUDIO_SESSION_ID_UNSET
          ? audioSessionId
          : AudioManager.AUDIO_SESSION_ID_GENERATE);
}
 
Example 14
Source File: MediaCodecAudioRenderer.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
@Override
protected void onEnabled(boolean joining) throws ExoPlaybackException {
  super.onEnabled(joining);
  eventDispatcher.enabled(decoderCounters);
  int tunnelingAudioSessionId = getConfiguration().tunnelingAudioSessionId;
  if (tunnelingAudioSessionId != C.AUDIO_SESSION_ID_UNSET) {
    audioSink.enableTunnelingV21(tunnelingAudioSessionId);
  } else {
    audioSink.disableTunneling();
  }
}
 
Example 15
Source File: SimpleDecoderAudioRenderer.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
@Override
protected void onEnabled(boolean joining) throws ExoPlaybackException {
  decoderCounters = new DecoderCounters();
  eventDispatcher.enabled(decoderCounters);
  int tunnelingAudioSessionId = getConfiguration().tunnelingAudioSessionId;
  if (tunnelingAudioSessionId != C.AUDIO_SESSION_ID_UNSET) {
    audioSink.enableTunnelingV21(tunnelingAudioSessionId);
  } else {
    audioSink.disableTunneling();
  }
}
 
Example 16
Source File: MediaCodecVideoRenderer.java    From K-Sonic with MIT License 5 votes vote down vote up
@Override
protected void onEnabled(boolean joining) throws ExoPlaybackException {
  super.onEnabled(joining);
  tunnelingAudioSessionId = getConfiguration().tunnelingAudioSessionId;
  tunneling = tunnelingAudioSessionId != C.AUDIO_SESSION_ID_UNSET;
  eventDispatcher.enabled(decoderCounters);
  frameReleaseTimeHelper.enable();
}
 
Example 17
Source File: MediaCodecVideoRenderer.java    From MediaSDK with Apache License 2.0 4 votes vote down vote up
/**
 * Returns the framework {@link MediaFormat} that should be used to configure the decoder.
 *
 * @param format The {@link Format} of media.
 * @param codecMimeType The MIME type handled by the codec.
 * @param codecMaxValues Codec max values that should be used when configuring the decoder.
 * @param codecOperatingRate The codec operating rate, or {@link #CODEC_OPERATING_RATE_UNSET} if
 *     no codec operating rate should be set.
 * @param deviceNeedsNoPostProcessWorkaround Whether the device is known to do post processing by
 *     default that isn't compatible with ExoPlayer.
 * @param tunnelingAudioSessionId The audio session id to use for tunneling, or {@link
 *     C#AUDIO_SESSION_ID_UNSET} if tunneling should not be enabled.
 * @return The framework {@link MediaFormat} that should be used to configure the decoder.
 */
@SuppressLint("InlinedApi")
protected MediaFormat getMediaFormat(
    Format format,
    String codecMimeType,
    CodecMaxValues codecMaxValues,
    float codecOperatingRate,
    boolean deviceNeedsNoPostProcessWorkaround,
    int tunnelingAudioSessionId) {
  MediaFormat mediaFormat = new MediaFormat();
  // Set format parameters that should always be set.
  mediaFormat.setString(MediaFormat.KEY_MIME, codecMimeType);
  mediaFormat.setInteger(MediaFormat.KEY_WIDTH, format.width);
  mediaFormat.setInteger(MediaFormat.KEY_HEIGHT, format.height);
  MediaFormatUtil.setCsdBuffers(mediaFormat, format.initializationData);
  // Set format parameters that may be unset.
  MediaFormatUtil.maybeSetFloat(mediaFormat, MediaFormat.KEY_FRAME_RATE, format.frameRate);
  MediaFormatUtil.maybeSetInteger(mediaFormat, MediaFormat.KEY_ROTATION, format.rotationDegrees);
  MediaFormatUtil.maybeSetColorInfo(mediaFormat, format.colorInfo);
  if (MimeTypes.VIDEO_DOLBY_VISION.equals(format.sampleMimeType)) {
    // Some phones require the profile to be set on the codec.
    // See https://github.com/google/ExoPlayer/pull/5438.
    Pair<Integer, Integer> codecProfileAndLevel = MediaCodecUtil.getCodecProfileAndLevel(format);
    if (codecProfileAndLevel != null) {
      MediaFormatUtil.maybeSetInteger(
          mediaFormat, MediaFormat.KEY_PROFILE, codecProfileAndLevel.first);
    }
  }
  // Set codec max values.
  mediaFormat.setInteger(MediaFormat.KEY_MAX_WIDTH, codecMaxValues.width);
  mediaFormat.setInteger(MediaFormat.KEY_MAX_HEIGHT, codecMaxValues.height);
  MediaFormatUtil.maybeSetInteger(
      mediaFormat, MediaFormat.KEY_MAX_INPUT_SIZE, codecMaxValues.inputSize);
  // Set codec configuration values.
  if (Util.SDK_INT >= 23) {
    mediaFormat.setInteger(MediaFormat.KEY_PRIORITY, 0 /* realtime priority */);
    if (codecOperatingRate != CODEC_OPERATING_RATE_UNSET) {
      mediaFormat.setFloat(MediaFormat.KEY_OPERATING_RATE, codecOperatingRate);
    }
  }
  if (deviceNeedsNoPostProcessWorkaround) {
    mediaFormat.setInteger("no-post-process", 1);
    mediaFormat.setInteger("auto-frc", 0);
  }
  if (tunnelingAudioSessionId != C.AUDIO_SESSION_ID_UNSET) {
    configureTunnelingV21(mediaFormat, tunnelingAudioSessionId);
  }
  return mediaFormat;
}
 
Example 18
Source File: ExoMediaPlayer.java    From ExoMedia with Apache License 2.0 4 votes vote down vote up
@Override
public void onAudioDisabled(DecoderCounters counters) {
    audioSessionId = C.AUDIO_SESSION_ID_UNSET;
    analyticsCollector.onAudioDisabled(counters);
}
 
Example 19
Source File: DefaultTrackSelector.java    From Telegram-FOSS with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Determines whether tunneling should be enabled, replacing {@link RendererConfiguration}s in
 * {@code rendererConfigurations} with configurations that enable tunneling on the appropriate
 * renderers if so.
 *
 * @param mappedTrackInfo Mapped track information.
 * @param rendererConfigurations The renderer configurations. Configurations may be replaced with
 *     ones that enable tunneling as a result of this call.
 * @param trackSelections The renderer track selections.
 * @param tunnelingAudioSessionId The audio session id to use when tunneling, or {@link
 *     C#AUDIO_SESSION_ID_UNSET} if tunneling should not be enabled.
 */
private static void maybeConfigureRenderersForTunneling(
    MappedTrackInfo mappedTrackInfo,
    int[][][] renderererFormatSupports,
    @NullableType RendererConfiguration[] rendererConfigurations,
    @NullableType TrackSelection[] trackSelections,
    int tunnelingAudioSessionId) {
  if (tunnelingAudioSessionId == C.AUDIO_SESSION_ID_UNSET) {
    return;
  }
  // Check whether we can enable tunneling. To enable tunneling we require exactly one audio and
  // one video renderer to support tunneling and have a selection.
  int tunnelingAudioRendererIndex = -1;
  int tunnelingVideoRendererIndex = -1;
  boolean enableTunneling = true;
  for (int i = 0; i < mappedTrackInfo.getRendererCount(); i++) {
    int rendererType = mappedTrackInfo.getRendererType(i);
    TrackSelection trackSelection = trackSelections[i];
    if ((rendererType == C.TRACK_TYPE_AUDIO || rendererType == C.TRACK_TYPE_VIDEO)
        && trackSelection != null) {
      if (rendererSupportsTunneling(
          renderererFormatSupports[i], mappedTrackInfo.getTrackGroups(i), trackSelection)) {
        if (rendererType == C.TRACK_TYPE_AUDIO) {
          if (tunnelingAudioRendererIndex != -1) {
            enableTunneling = false;
            break;
          } else {
            tunnelingAudioRendererIndex = i;
          }
        } else {
          if (tunnelingVideoRendererIndex != -1) {
            enableTunneling = false;
            break;
          } else {
            tunnelingVideoRendererIndex = i;
          }
        }
      }
    }
  }
  enableTunneling &= tunnelingAudioRendererIndex != -1 && tunnelingVideoRendererIndex != -1;
  if (enableTunneling) {
    RendererConfiguration tunnelingRendererConfiguration =
        new RendererConfiguration(tunnelingAudioSessionId);
    rendererConfigurations[tunnelingAudioRendererIndex] = tunnelingRendererConfiguration;
    rendererConfigurations[tunnelingVideoRendererIndex] = tunnelingRendererConfiguration;
  }
}
 
Example 20
Source File: DefaultTrackSelector.java    From Telegram with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Determines whether tunneling should be enabled, replacing {@link RendererConfiguration}s in
 * {@code rendererConfigurations} with configurations that enable tunneling on the appropriate
 * renderers if so.
 *
 * @param mappedTrackInfo Mapped track information.
 * @param rendererConfigurations The renderer configurations. Configurations may be replaced with
 *     ones that enable tunneling as a result of this call.
 * @param trackSelections The renderer track selections.
 * @param tunnelingAudioSessionId The audio session id to use when tunneling, or {@link
 *     C#AUDIO_SESSION_ID_UNSET} if tunneling should not be enabled.
 */
private static void maybeConfigureRenderersForTunneling(
    MappedTrackInfo mappedTrackInfo,
    int[][][] renderererFormatSupports,
    @NullableType RendererConfiguration[] rendererConfigurations,
    @NullableType TrackSelection[] trackSelections,
    int tunnelingAudioSessionId) {
  if (tunnelingAudioSessionId == C.AUDIO_SESSION_ID_UNSET) {
    return;
  }
  // Check whether we can enable tunneling. To enable tunneling we require exactly one audio and
  // one video renderer to support tunneling and have a selection.
  int tunnelingAudioRendererIndex = -1;
  int tunnelingVideoRendererIndex = -1;
  boolean enableTunneling = true;
  for (int i = 0; i < mappedTrackInfo.getRendererCount(); i++) {
    int rendererType = mappedTrackInfo.getRendererType(i);
    TrackSelection trackSelection = trackSelections[i];
    if ((rendererType == C.TRACK_TYPE_AUDIO || rendererType == C.TRACK_TYPE_VIDEO)
        && trackSelection != null) {
      if (rendererSupportsTunneling(
          renderererFormatSupports[i], mappedTrackInfo.getTrackGroups(i), trackSelection)) {
        if (rendererType == C.TRACK_TYPE_AUDIO) {
          if (tunnelingAudioRendererIndex != -1) {
            enableTunneling = false;
            break;
          } else {
            tunnelingAudioRendererIndex = i;
          }
        } else {
          if (tunnelingVideoRendererIndex != -1) {
            enableTunneling = false;
            break;
          } else {
            tunnelingVideoRendererIndex = i;
          }
        }
      }
    }
  }
  enableTunneling &= tunnelingAudioRendererIndex != -1 && tunnelingVideoRendererIndex != -1;
  if (enableTunneling) {
    RendererConfiguration tunnelingRendererConfiguration =
        new RendererConfiguration(tunnelingAudioSessionId);
    rendererConfigurations[tunnelingAudioRendererIndex] = tunnelingRendererConfiguration;
    rendererConfigurations[tunnelingVideoRendererIndex] = tunnelingRendererConfiguration;
  }
}