com.google.android.exoplayer2.source.BehindLiveWindowException Java Examples

The following examples show how to use com.google.android.exoplayer2.source.BehindLiveWindowException. 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: DefaultDashChunkSource.java    From MediaSDK with Apache License 2.0 6 votes vote down vote up
@Override
public void updateManifest(DashManifest newManifest, int newPeriodIndex) {
  try {
    manifest = newManifest;
    periodIndex = newPeriodIndex;
    long periodDurationUs = manifest.getPeriodDurationUs(periodIndex);
    List<Representation> representations = getRepresentations();
    for (int i = 0; i < representationHolders.length; i++) {
      Representation representation = representations.get(trackSelection.getIndexInTrackGroup(i));
      representationHolders[i] =
          representationHolders[i].copyWithNewRepresentation(periodDurationUs, representation);
    }
  } catch (BehindLiveWindowException e) {
    fatalError = e;
  }
}
 
Example #2
Source File: DefaultDashChunkSource.java    From TelePlus-Android with GNU General Public License v2.0 6 votes vote down vote up
@Override
public void updateManifest(DashManifest newManifest, int newPeriodIndex) {
  try {
    manifest = newManifest;
    periodIndex = newPeriodIndex;
    long periodDurationUs = manifest.getPeriodDurationUs(periodIndex);
    List<Representation> representations = getRepresentations();
    for (int i = 0; i < representationHolders.length; i++) {
      Representation representation = representations.get(trackSelection.getIndexInTrackGroup(i));
      representationHolders[i] =
          representationHolders[i].copyWithNewRepresentation(periodDurationUs, representation);
    }
  } catch (BehindLiveWindowException e) {
    fatalError = e;
  }
}
 
Example #3
Source File: DefaultDashChunkSource.java    From Telegram with GNU General Public License v2.0 6 votes vote down vote up
@Override
public void updateManifest(DashManifest newManifest, int newPeriodIndex) {
  try {
    manifest = newManifest;
    periodIndex = newPeriodIndex;
    long periodDurationUs = manifest.getPeriodDurationUs(periodIndex);
    List<Representation> representations = getRepresentations();
    for (int i = 0; i < representationHolders.length; i++) {
      Representation representation = representations.get(trackSelection.getIndexInTrackGroup(i));
      representationHolders[i] =
          representationHolders[i].copyWithNewRepresentation(periodDurationUs, representation);
    }
  } catch (BehindLiveWindowException e) {
    fatalError = e;
  }
}
 
Example #4
Source File: MediaPlayerFragment.java    From PowerFileExplorer with GNU General Public License v3.0 6 votes vote down vote up
private static boolean isBehindLiveWindow(ExoPlaybackException e) {
	if (e.type != ExoPlaybackException.TYPE_SOURCE) {
		return false;
	}
	Throwable cause = e.getSourceException();
	while (cause != null) {
		if (cause instanceof BehindLiveWindowException) {
			return true;
		}
		cause = cause.getCause();
	}
	return false;
}
 
Example #5
Source File: DefaultDashChunkSource.java    From TelePlus-Android with GNU General Public License v2.0 6 votes vote down vote up
@Override
public void updateManifest(DashManifest newManifest, int newPeriodIndex) {
  try {
    manifest = newManifest;
    periodIndex = newPeriodIndex;
    long periodDurationUs = manifest.getPeriodDurationUs(periodIndex);
    List<Representation> representations = getRepresentations();
    for (int i = 0; i < representationHolders.length; i++) {
      Representation representation = representations.get(trackSelection.getIndexInTrackGroup(i));
      representationHolders[i] =
          representationHolders[i].copyWithNewRepresentation(periodDurationUs, representation);
    }
  } catch (BehindLiveWindowException e) {
    fatalError = e;
  }
}
 
Example #6
Source File: PlayerActivity.java    From ExoPlayer-Offline with Apache License 2.0 6 votes vote down vote up
private static boolean isBehindLiveWindow(ExoPlaybackException e) {
    if (e.type != ExoPlaybackException.TYPE_SOURCE) {
        return false;
    }
    Throwable cause = e.getSourceException();
    while (cause != null) {
        if (cause instanceof BehindLiveWindowException) {
            return true;
        }
        cause = cause.getCause();
    }
    return false;
}
 
Example #7
Source File: ExoPlayerHelper.java    From ExoPlayer-Wrapper with Apache License 2.0 6 votes vote down vote up
private static boolean isBehindLiveWindow(ExoPlaybackException e) {
    if (e.type != ExoPlaybackException.TYPE_SOURCE) {
        return false;
    }
    Throwable cause = e.getSourceException();
    while (cause != null) {
        if (cause instanceof BehindLiveWindowException) {
            return true;
        }
        cause = cause.getCause();
    }
    return false;
}
 
Example #8
Source File: LiveVideoPlayerActivity.java    From LiveVideoBroadcaster with Apache License 2.0 6 votes vote down vote up
private static boolean isBehindLiveWindow(ExoPlaybackException e) {
  if (e.type != ExoPlaybackException.TYPE_SOURCE) {
    return false;
  }
  Throwable cause = e.getSourceException();
  while (cause != null) {
    if (cause instanceof BehindLiveWindowException) {
      return true;
    }
    cause = cause.getCause();
  }
  return false;
}
 
Example #9
Source File: VideoPlayerComponent.java    From android-arch-components-lifecycle with Apache License 2.0 6 votes vote down vote up
private static boolean isBehindLiveWindow(ExoPlaybackException e) {
    if (e.type != ExoPlaybackException.TYPE_SOURCE) {
        return false;
    }
    Throwable cause = e.getSourceException();
    while (cause != null) {
        if (cause instanceof BehindLiveWindowException) {
            return true;
        }
        cause = cause.getCause();
    }
    return false;
}
 
Example #10
Source File: DefaultDashChunkSource.java    From Telegram-FOSS with GNU General Public License v2.0 6 votes vote down vote up
@Override
public void updateManifest(DashManifest newManifest, int newPeriodIndex) {
  try {
    manifest = newManifest;
    periodIndex = newPeriodIndex;
    long periodDurationUs = manifest.getPeriodDurationUs(periodIndex);
    List<Representation> representations = getRepresentations();
    for (int i = 0; i < representationHolders.length; i++) {
      Representation representation = representations.get(trackSelection.getIndexInTrackGroup(i));
      representationHolders[i] =
          representationHolders[i].copyWithNewRepresentation(periodDurationUs, representation);
    }
  } catch (BehindLiveWindowException e) {
    fatalError = e;
  }
}
 
Example #11
Source File: ReactExoplayerView.java    From react-native-video with MIT License 6 votes vote down vote up
private static boolean isBehindLiveWindow(ExoPlaybackException e) {
    Log.e("ExoPlayer Exception", e.toString());
    if (e.type != ExoPlaybackException.TYPE_SOURCE) {
        return false;
    }
    Throwable cause = e.getSourceException();
    while (cause != null) {
        if (cause instanceof BehindLiveWindowException ||
                cause instanceof HttpDataSource.HttpDataSourceException) {
            return true;
        }
        cause = cause.getCause();
    }
    return false;
}
 
Example #12
Source File: ProviderTvInputService.java    From xipl with Apache License 2.0 5 votes vote down vote up
@Override
public void onPlayerError(ExoPlaybackException error) {
    if (error.getCause() instanceof BehindLiveWindowException) {
        Toast.makeText(mContext, R.string.stream_failure_retry, Toast.LENGTH_SHORT).show();
        mProviderTvPlayer.restart(mContext);
        mProviderTvPlayer.play();
    } else if (error.getCause() instanceof UnrecognizedInputFormatException) {
        // Channel cannot be played in case of an error in parsing the ".m3u8" file.
        Toast.makeText(mContext, mContext.getString(R.string.channel_stream_failure), Toast.LENGTH_SHORT).show();
    } else if (error.getCause() instanceof HttpDataSource.InvalidResponseCodeException) {

         /*
          We might get errors different like 403 which indicate permission denied due to multiple
          connections at the same time or 502 meaning bad gateway.

          Restart the loading after 5 seconds.
          */

        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                if (mContext != null && mProviderTvPlayer != null) {
                    Toast.makeText(mContext, R.string.stream_failure_retry, Toast.LENGTH_SHORT).show();
                    mProviderTvPlayer.restart(mContext);
                    mProviderTvPlayer.play();
                }
            }
        }, 5000);
    } else if (error.getCause() instanceof HttpDataSource.HttpDataSourceException) {
        // Timeout, nothing we can do really...
        Toast.makeText(mContext, R.string.channel_stream_failure, Toast.LENGTH_SHORT).show();
    }
}
 
Example #13
Source File: DefaultDashChunkSource.java    From K-Sonic with MIT License 5 votes vote down vote up
@Override
public void updateManifest(DashManifest newManifest, int newPeriodIndex) {
  try {
    manifest = newManifest;
    periodIndex = newPeriodIndex;
    long periodDurationUs = manifest.getPeriodDurationUs(periodIndex);
    List<Representation> representations = getAdaptationSet().representations;
    for (int i = 0; i < representationHolders.length; i++) {
      Representation representation = representations.get(trackSelection.getIndexInTrackGroup(i));
      representationHolders[i].updateRepresentation(periodDurationUs, representation);
    }
  } catch (BehindLiveWindowException e) {
    fatalError = e;
  }
}
 
Example #14
Source File: VideoActivity.java    From evercam-android with GNU Affero General Public License v3.0 5 votes vote down vote up
private static boolean isBehindLiveWindow(ExoPlaybackException e) {
    if (e.type != ExoPlaybackException.TYPE_SOURCE) {
        return false;
    }
    Throwable cause = e.getSourceException();
    while (cause != null) {
        if (cause instanceof BehindLiveWindowException) {
            return true;
        }
        cause = cause.getCause();
    }
    return false;
}
 
Example #15
Source File: DefaultDashChunkSource.java    From Telegram with GNU General Public License v2.0 4 votes vote down vote up
@CheckResult
/* package */ RepresentationHolder copyWithNewRepresentation(
    long newPeriodDurationUs, Representation newRepresentation)
    throws BehindLiveWindowException {
  DashSegmentIndex oldIndex = representation.getIndex();
  DashSegmentIndex newIndex = newRepresentation.getIndex();

  if (oldIndex == null) {
    // Segment numbers cannot shift if the index isn't defined by the manifest.
    return new RepresentationHolder(
        newPeriodDurationUs, newRepresentation, extractorWrapper, segmentNumShift, oldIndex);
  }

  if (!oldIndex.isExplicit()) {
    // Segment numbers cannot shift if the index isn't explicit.
    return new RepresentationHolder(
        newPeriodDurationUs, newRepresentation, extractorWrapper, segmentNumShift, newIndex);
  }

  int oldIndexSegmentCount = oldIndex.getSegmentCount(newPeriodDurationUs);
  if (oldIndexSegmentCount == 0) {
    // Segment numbers cannot shift if the old index was empty.
    return new RepresentationHolder(
        newPeriodDurationUs, newRepresentation, extractorWrapper, segmentNumShift, newIndex);
  }

  long oldIndexFirstSegmentNum = oldIndex.getFirstSegmentNum();
  long oldIndexStartTimeUs = oldIndex.getTimeUs(oldIndexFirstSegmentNum);
  long oldIndexLastSegmentNum = oldIndexFirstSegmentNum + oldIndexSegmentCount - 1;
  long oldIndexEndTimeUs =
      oldIndex.getTimeUs(oldIndexLastSegmentNum)
          + oldIndex.getDurationUs(oldIndexLastSegmentNum, newPeriodDurationUs);
  long newIndexFirstSegmentNum = newIndex.getFirstSegmentNum();
  long newIndexStartTimeUs = newIndex.getTimeUs(newIndexFirstSegmentNum);
  long newSegmentNumShift = segmentNumShift;
  if (oldIndexEndTimeUs == newIndexStartTimeUs) {
    // The new index continues where the old one ended, with no overlap.
    newSegmentNumShift += oldIndexLastSegmentNum + 1 - newIndexFirstSegmentNum;
  } else if (oldIndexEndTimeUs < newIndexStartTimeUs) {
    // There's a gap between the old index and the new one which means we've slipped behind the
    // live window and can't proceed.
    throw new BehindLiveWindowException();
  } else if (newIndexStartTimeUs < oldIndexStartTimeUs) {
    // The new index overlaps with (but does not have a start position contained within) the old
    // index. This can only happen if extra segments have been added to the start of the index.
    newSegmentNumShift -=
        newIndex.getSegmentNum(oldIndexStartTimeUs, newPeriodDurationUs)
            - oldIndexFirstSegmentNum;
  } else {
    // The new index overlaps with (and has a start position contained within) the old index.
    newSegmentNumShift +=
        oldIndex.getSegmentNum(newIndexStartTimeUs, newPeriodDurationUs)
            - newIndexFirstSegmentNum;
  }
  return new RepresentationHolder(
      newPeriodDurationUs, newRepresentation, extractorWrapper, newSegmentNumShift, newIndex);
}
 
Example #16
Source File: DefaultDashChunkSource.java    From Telegram-FOSS with GNU General Public License v2.0 4 votes vote down vote up
@CheckResult
/* package */ RepresentationHolder copyWithNewRepresentation(
    long newPeriodDurationUs, Representation newRepresentation)
    throws BehindLiveWindowException {
  DashSegmentIndex oldIndex = representation.getIndex();
  DashSegmentIndex newIndex = newRepresentation.getIndex();

  if (oldIndex == null) {
    // Segment numbers cannot shift if the index isn't defined by the manifest.
    return new RepresentationHolder(
        newPeriodDurationUs, newRepresentation, extractorWrapper, segmentNumShift, oldIndex);
  }

  if (!oldIndex.isExplicit()) {
    // Segment numbers cannot shift if the index isn't explicit.
    return new RepresentationHolder(
        newPeriodDurationUs, newRepresentation, extractorWrapper, segmentNumShift, newIndex);
  }

  int oldIndexSegmentCount = oldIndex.getSegmentCount(newPeriodDurationUs);
  if (oldIndexSegmentCount == 0) {
    // Segment numbers cannot shift if the old index was empty.
    return new RepresentationHolder(
        newPeriodDurationUs, newRepresentation, extractorWrapper, segmentNumShift, newIndex);
  }

  long oldIndexFirstSegmentNum = oldIndex.getFirstSegmentNum();
  long oldIndexStartTimeUs = oldIndex.getTimeUs(oldIndexFirstSegmentNum);
  long oldIndexLastSegmentNum = oldIndexFirstSegmentNum + oldIndexSegmentCount - 1;
  long oldIndexEndTimeUs =
      oldIndex.getTimeUs(oldIndexLastSegmentNum)
          + oldIndex.getDurationUs(oldIndexLastSegmentNum, newPeriodDurationUs);
  long newIndexFirstSegmentNum = newIndex.getFirstSegmentNum();
  long newIndexStartTimeUs = newIndex.getTimeUs(newIndexFirstSegmentNum);
  long newSegmentNumShift = segmentNumShift;
  if (oldIndexEndTimeUs == newIndexStartTimeUs) {
    // The new index continues where the old one ended, with no overlap.
    newSegmentNumShift += oldIndexLastSegmentNum + 1 - newIndexFirstSegmentNum;
  } else if (oldIndexEndTimeUs < newIndexStartTimeUs) {
    // There's a gap between the old index and the new one which means we've slipped behind the
    // live window and can't proceed.
    throw new BehindLiveWindowException();
  } else if (newIndexStartTimeUs < oldIndexStartTimeUs) {
    // The new index overlaps with (but does not have a start position contained within) the old
    // index. This can only happen if extra segments have been added to the start of the index.
    newSegmentNumShift -=
        newIndex.getSegmentNum(oldIndexStartTimeUs, newPeriodDurationUs)
            - oldIndexFirstSegmentNum;
  } else {
    // The new index overlaps with (and has a start position contained within) the old index.
    newSegmentNumShift +=
        oldIndex.getSegmentNum(newIndexStartTimeUs, newPeriodDurationUs)
            - newIndexFirstSegmentNum;
  }
  return new RepresentationHolder(
      newPeriodDurationUs, newRepresentation, extractorWrapper, newSegmentNumShift, newIndex);
}
 
Example #17
Source File: DefaultDashChunkSource.java    From K-Sonic with MIT License 4 votes vote down vote up
public void updateRepresentation(long newPeriodDurationUs, Representation newRepresentation)
    throws BehindLiveWindowException{
  DashSegmentIndex oldIndex = representation.getIndex();
  DashSegmentIndex newIndex = newRepresentation.getIndex();

  periodDurationUs = newPeriodDurationUs;
  representation = newRepresentation;
  if (oldIndex == null) {
    // Segment numbers cannot shift if the index isn't defined by the manifest.
    return;
  }

  segmentIndex = newIndex;
  if (!oldIndex.isExplicit()) {
    // Segment numbers cannot shift if the index isn't explicit.
    return;
  }

  int oldIndexSegmentCount = oldIndex.getSegmentCount(periodDurationUs);
  if (oldIndexSegmentCount == 0) {
    // Segment numbers cannot shift if the old index was empty.
    return;
  }

  int oldIndexLastSegmentNum = oldIndex.getFirstSegmentNum() + oldIndexSegmentCount - 1;
  long oldIndexEndTimeUs = oldIndex.getTimeUs(oldIndexLastSegmentNum)
      + oldIndex.getDurationUs(oldIndexLastSegmentNum, periodDurationUs);
  int newIndexFirstSegmentNum = newIndex.getFirstSegmentNum();
  long newIndexStartTimeUs = newIndex.getTimeUs(newIndexFirstSegmentNum);
  if (oldIndexEndTimeUs == newIndexStartTimeUs) {
    // The new index continues where the old one ended, with no overlap.
    segmentNumShift += oldIndexLastSegmentNum + 1 - newIndexFirstSegmentNum;
  } else if (oldIndexEndTimeUs < newIndexStartTimeUs) {
    // There's a gap between the old index and the new one which means we've slipped behind the
    // live window and can't proceed.
    throw new BehindLiveWindowException();
  } else {
    // The new index overlaps with the old one.
    segmentNumShift += oldIndex.getSegmentNum(newIndexStartTimeUs, periodDurationUs)
        - newIndexFirstSegmentNum;
  }
}
 
Example #18
Source File: DefaultDashChunkSource.java    From TelePlus-Android with GNU General Public License v2.0 4 votes vote down vote up
@CheckResult
/* package */ RepresentationHolder copyWithNewRepresentation(
    long newPeriodDurationUs, Representation newRepresentation)
    throws BehindLiveWindowException {
  DashSegmentIndex oldIndex = representation.getIndex();
  DashSegmentIndex newIndex = newRepresentation.getIndex();

  if (oldIndex == null) {
    // Segment numbers cannot shift if the index isn't defined by the manifest.
    return new RepresentationHolder(
        newPeriodDurationUs, newRepresentation, extractorWrapper, segmentNumShift, oldIndex);
  }

  if (!oldIndex.isExplicit()) {
    // Segment numbers cannot shift if the index isn't explicit.
    return new RepresentationHolder(
        newPeriodDurationUs, newRepresentation, extractorWrapper, segmentNumShift, newIndex);
  }

  int oldIndexSegmentCount = oldIndex.getSegmentCount(newPeriodDurationUs);
  if (oldIndexSegmentCount == 0) {
    // Segment numbers cannot shift if the old index was empty.
    return new RepresentationHolder(
        newPeriodDurationUs, newRepresentation, extractorWrapper, segmentNumShift, newIndex);
  }

  long oldIndexLastSegmentNum = oldIndex.getFirstSegmentNum() + oldIndexSegmentCount - 1;
  long oldIndexEndTimeUs =
      oldIndex.getTimeUs(oldIndexLastSegmentNum)
          + oldIndex.getDurationUs(oldIndexLastSegmentNum, newPeriodDurationUs);
  long newIndexFirstSegmentNum = newIndex.getFirstSegmentNum();
  long newIndexStartTimeUs = newIndex.getTimeUs(newIndexFirstSegmentNum);
  long newSegmentNumShift = segmentNumShift;
  if (oldIndexEndTimeUs == newIndexStartTimeUs) {
    // The new index continues where the old one ended, with no overlap.
    newSegmentNumShift += oldIndexLastSegmentNum + 1 - newIndexFirstSegmentNum;
  } else if (oldIndexEndTimeUs < newIndexStartTimeUs) {
    // There's a gap between the old index and the new one which means we've slipped behind the
    // live window and can't proceed.
    throw new BehindLiveWindowException();
  } else {
    // The new index overlaps with the old one.
    newSegmentNumShift +=
        oldIndex.getSegmentNum(newIndexStartTimeUs, newPeriodDurationUs)
            - newIndexFirstSegmentNum;
  }
  return new RepresentationHolder(
      newPeriodDurationUs, newRepresentation, extractorWrapper, newSegmentNumShift, newIndex);
}
 
Example #19
Source File: DefaultDashChunkSource.java    From TelePlus-Android with GNU General Public License v2.0 4 votes vote down vote up
@CheckResult
/* package */ RepresentationHolder copyWithNewRepresentation(
    long newPeriodDurationUs, Representation newRepresentation)
    throws BehindLiveWindowException {
  DashSegmentIndex oldIndex = representation.getIndex();
  DashSegmentIndex newIndex = newRepresentation.getIndex();

  if (oldIndex == null) {
    // Segment numbers cannot shift if the index isn't defined by the manifest.
    return new RepresentationHolder(
        newPeriodDurationUs, newRepresentation, extractorWrapper, segmentNumShift, oldIndex);
  }

  if (!oldIndex.isExplicit()) {
    // Segment numbers cannot shift if the index isn't explicit.
    return new RepresentationHolder(
        newPeriodDurationUs, newRepresentation, extractorWrapper, segmentNumShift, newIndex);
  }

  int oldIndexSegmentCount = oldIndex.getSegmentCount(newPeriodDurationUs);
  if (oldIndexSegmentCount == 0) {
    // Segment numbers cannot shift if the old index was empty.
    return new RepresentationHolder(
        newPeriodDurationUs, newRepresentation, extractorWrapper, segmentNumShift, newIndex);
  }

  long oldIndexLastSegmentNum = oldIndex.getFirstSegmentNum() + oldIndexSegmentCount - 1;
  long oldIndexEndTimeUs =
      oldIndex.getTimeUs(oldIndexLastSegmentNum)
          + oldIndex.getDurationUs(oldIndexLastSegmentNum, newPeriodDurationUs);
  long newIndexFirstSegmentNum = newIndex.getFirstSegmentNum();
  long newIndexStartTimeUs = newIndex.getTimeUs(newIndexFirstSegmentNum);
  long newSegmentNumShift = segmentNumShift;
  if (oldIndexEndTimeUs == newIndexStartTimeUs) {
    // The new index continues where the old one ended, with no overlap.
    newSegmentNumShift += oldIndexLastSegmentNum + 1 - newIndexFirstSegmentNum;
  } else if (oldIndexEndTimeUs < newIndexStartTimeUs) {
    // There's a gap between the old index and the new one which means we've slipped behind the
    // live window and can't proceed.
    throw new BehindLiveWindowException();
  } else {
    // The new index overlaps with the old one.
    newSegmentNumShift +=
        oldIndex.getSegmentNum(newIndexStartTimeUs, newPeriodDurationUs)
            - newIndexFirstSegmentNum;
  }
  return new RepresentationHolder(
      newPeriodDurationUs, newRepresentation, extractorWrapper, newSegmentNumShift, newIndex);
}
 
Example #20
Source File: DefaultDashChunkSource.java    From MediaSDK with Apache License 2.0 4 votes vote down vote up
@CheckResult
/* package */ RepresentationHolder copyWithNewRepresentation(
    long newPeriodDurationUs, Representation newRepresentation)
    throws BehindLiveWindowException {
  DashSegmentIndex oldIndex = representation.getIndex();
  DashSegmentIndex newIndex = newRepresentation.getIndex();

  if (oldIndex == null) {
    // Segment numbers cannot shift if the index isn't defined by the manifest.
    return new RepresentationHolder(
        newPeriodDurationUs, newRepresentation, extractorWrapper, segmentNumShift, oldIndex);
  }

  if (!oldIndex.isExplicit()) {
    // Segment numbers cannot shift if the index isn't explicit.
    return new RepresentationHolder(
        newPeriodDurationUs, newRepresentation, extractorWrapper, segmentNumShift, newIndex);
  }

  int oldIndexSegmentCount = oldIndex.getSegmentCount(newPeriodDurationUs);
  if (oldIndexSegmentCount == 0) {
    // Segment numbers cannot shift if the old index was empty.
    return new RepresentationHolder(
        newPeriodDurationUs, newRepresentation, extractorWrapper, segmentNumShift, newIndex);
  }

  long oldIndexFirstSegmentNum = oldIndex.getFirstSegmentNum();
  long oldIndexStartTimeUs = oldIndex.getTimeUs(oldIndexFirstSegmentNum);
  long oldIndexLastSegmentNum = oldIndexFirstSegmentNum + oldIndexSegmentCount - 1;
  long oldIndexEndTimeUs =
      oldIndex.getTimeUs(oldIndexLastSegmentNum)
          + oldIndex.getDurationUs(oldIndexLastSegmentNum, newPeriodDurationUs);
  long newIndexFirstSegmentNum = newIndex.getFirstSegmentNum();
  long newIndexStartTimeUs = newIndex.getTimeUs(newIndexFirstSegmentNum);
  long newSegmentNumShift = segmentNumShift;
  if (oldIndexEndTimeUs == newIndexStartTimeUs) {
    // The new index continues where the old one ended, with no overlap.
    newSegmentNumShift += oldIndexLastSegmentNum + 1 - newIndexFirstSegmentNum;
  } else if (oldIndexEndTimeUs < newIndexStartTimeUs) {
    // There's a gap between the old index and the new one which means we've slipped behind the
    // live window and can't proceed.
    throw new BehindLiveWindowException();
  } else if (newIndexStartTimeUs < oldIndexStartTimeUs) {
    // The new index overlaps with (but does not have a start position contained within) the old
    // index. This can only happen if extra segments have been added to the start of the index.
    newSegmentNumShift -=
        newIndex.getSegmentNum(oldIndexStartTimeUs, newPeriodDurationUs)
            - oldIndexFirstSegmentNum;
  } else {
    // The new index overlaps with (and has a start position contained within) the old index.
    newSegmentNumShift +=
        oldIndex.getSegmentNum(newIndexStartTimeUs, newPeriodDurationUs)
            - newIndexFirstSegmentNum;
  }
  return new RepresentationHolder(
      newPeriodDurationUs, newRepresentation, extractorWrapper, newSegmentNumShift, newIndex);
}