Skip to content

Commit

Permalink
Enable SeekParameters functionality for ExtractorMediaSource
Browse files Browse the repository at this point in the history
Also fix ClippingMediaSource to consider the start position an
artificial key-frame, and to properly offset the value returned
by getAdjustedSeekPositionUs.

Issue: #2882

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=179032243
  • Loading branch information
ojw28 committed Dec 15, 2017
1 parent a17375b commit 37a275f
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 17 deletions.
6 changes: 6 additions & 0 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@
sub-streams, by allowing injection of custom `CompositeSequenceableLoader`
factories through `DashMediaSource.Factory`, `HlsMediaSource.Factory`,
`SsMediaSource.Factory`, and `MergingMediaSource`.
* Add `ExoPlayer.setSeekParameters` for controlling how seek operations are
performed. The `SeekParameters` class contains defaults for exact seeking and
seeking to the closest sync points before, either side or after specified seek
positions.
* Note: `SeekParameters` are only currently effective when playing
`ExtractorMediaSource`s (i.e. progressive streams).
* DASH: Support DASH manifest EventStream elements.
* HLS: Add opt-in support for chunkless preparation in HLS. This allows an
HLS source to finish preparation without downloading any chunks, which can
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -678,20 +678,20 @@ private void seekToInternal(SeekPosition seekPosition) throws ExoPlaybackExcepti
periodPositionUs = 0;
}
try {
long newPeriodPositionUs = periodPositionUs;
if (periodId.equals(playbackInfo.periodId)) {
long adjustedPeriodPositionUs = periodPositionUs;
if (playingPeriodHolder != null) {
adjustedPeriodPositionUs =
if (playingPeriodHolder != null && newPeriodPositionUs != 0) {
newPeriodPositionUs =
playingPeriodHolder.mediaPeriod.getAdjustedSeekPositionUs(
adjustedPeriodPositionUs, SeekParameters.DEFAULT);
newPeriodPositionUs, seekParameters);
}
if ((adjustedPeriodPositionUs / 1000) == (playbackInfo.positionUs / 1000)) {
if ((newPeriodPositionUs / 1000) == (playbackInfo.positionUs / 1000)) {
// Seek will be performed to the current position. Do nothing.
periodPositionUs = playbackInfo.positionUs;
return;
}
}
long newPeriodPositionUs = seekToPeriodPosition(periodId, periodPositionUs);
newPeriodPositionUs = seekToPeriodPosition(periodId, newPeriodPositionUs);
seekPositionAdjusted |= periodPositionUs != newPeriodPositionUs;
periodPositionUs = newPeriodPositionUs;
} finally {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,16 +165,23 @@ public long seekToUs(long positionUs) {
sampleStream.clearSentEos();
}
}
long seekUs = mediaPeriod.seekToUs(positionUs + startUs);
Assertions.checkState(seekUs == positionUs + startUs
|| (seekUs >= startUs && (endUs == C.TIME_END_OF_SOURCE || seekUs <= endUs)));
long offsetPositionUs = positionUs + startUs;
long seekUs = mediaPeriod.seekToUs(offsetPositionUs);
Assertions.checkState(
seekUs == offsetPositionUs
|| (seekUs >= startUs && (endUs == C.TIME_END_OF_SOURCE || seekUs <= endUs)));
return seekUs - startUs;
}

@Override
public long getAdjustedSeekPositionUs(long positionUs, SeekParameters seekParameters) {
return mediaPeriod.getAdjustedSeekPositionUs(
positionUs + startUs, adjustSeekParameters(positionUs + startUs, seekParameters));
if (positionUs == startUs) {
// Never adjust seeks to the start of the clipped view.
return 0;
}
long offsetPositionUs = positionUs + startUs;
SeekParameters clippedSeekParameters = clipSeekParameters(offsetPositionUs, seekParameters);
return mediaPeriod.getAdjustedSeekPositionUs(offsetPositionUs, clippedSeekParameters) - startUs;
}

@Override
Expand Down Expand Up @@ -209,12 +216,12 @@ public void onContinueLoadingRequested(MediaPeriod source) {
return pendingInitialDiscontinuityPositionUs != C.TIME_UNSET;
}

private SeekParameters adjustSeekParameters(long positionUs, SeekParameters seekParameters) {
long toleranceBeforeMs = Math.min(positionUs - startUs, seekParameters.toleranceBeforeUs);
private SeekParameters clipSeekParameters(long offsetPositionUs, SeekParameters seekParameters) {
long toleranceBeforeMs = Math.min(offsetPositionUs - startUs, seekParameters.toleranceBeforeUs);
long toleranceAfterMs =
endUs == C.TIME_END_OF_SOURCE
? seekParameters.toleranceAfterUs
: Math.min(endUs - positionUs, seekParameters.toleranceAfterUs);
: Math.min(endUs - offsetPositionUs, seekParameters.toleranceAfterUs);
if (toleranceBeforeMs == seekParameters.toleranceBeforeUs
&& toleranceAfterMs == seekParameters.toleranceAfterUs) {
return seekParameters;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import com.google.android.exoplayer2.extractor.ExtractorOutput;
import com.google.android.exoplayer2.extractor.PositionHolder;
import com.google.android.exoplayer2.extractor.SeekMap;
import com.google.android.exoplayer2.extractor.SeekMap.SeekPoints;
import com.google.android.exoplayer2.extractor.TrackOutput;
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
import com.google.android.exoplayer2.source.SampleQueue.UpstreamFormatChangedListener;
Expand Down Expand Up @@ -372,8 +373,33 @@ public long seekToUs(long positionUs) {

@Override
public long getAdjustedSeekPositionUs(long positionUs, SeekParameters seekParameters) {
// Treat all seeks into non-seekable media as being to t=0.
return seekMap.isSeekable() ? positionUs : 0;
if (!seekMap.isSeekable()) {
// Treat all seeks into non-seekable media as being to t=0.
return 0;
}
SeekPoints seekPoints = seekMap.getSeekPoints(positionUs);
long minPositionUs =
Util.subtractWithOverflowDefault(
positionUs, seekParameters.toleranceBeforeUs, Long.MIN_VALUE);
long maxPositionUs =
Util.addWithOverflowDefault(positionUs, seekParameters.toleranceAfterUs, Long.MAX_VALUE);
long firstPointUs = seekPoints.first.timeUs;
boolean firstPointValid = minPositionUs <= firstPointUs && firstPointUs <= maxPositionUs;
long secondPointUs = seekPoints.second.timeUs;
boolean secondPointValid = minPositionUs <= secondPointUs && secondPointUs <= maxPositionUs;
if (firstPointValid && secondPointValid) {
if (Math.abs(firstPointUs - positionUs) <= Math.abs(secondPointUs - positionUs)) {
return firstPointUs;
} else {
return secondPointUs;
}
} else if (firstPointValid) {
return firstPointUs;
} else if (secondPointValid) {
return secondPointUs;
} else {
return minPositionUs;
}
}

// SampleStream methods.
Expand Down Expand Up @@ -657,7 +683,7 @@ private boolean isPendingReset() {
return pendingResetPositionUs != C.TIME_UNSET;
}

private boolean isLoadableExceptionFatal(IOException e) {
private static boolean isLoadableExceptionFatal(IOException e) {
return e instanceof UnrecognizedInputFormatException;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,40 @@ public static float constrainValue(float value, float min, float max) {
return Math.max(min, Math.min(value, max));
}

/**
* Returns the sum of two arguments, or a third argument if the result overflows.
*
* @param x The first value.
* @param y The second value.
* @param overflowResult The return value if {@code x + y} overflows.
* @return {@code x + y}, or {@code overflowResult} if the result overflows.
*/
public static long addWithOverflowDefault(long x, long y, long overflowResult) {
long result = x + y;
// See Hacker's Delight 2-13 (H. Warren Jr).
if (((x ^ result) & (y ^ result)) < 0) {
return overflowResult;
}
return result;
}

/**
* Returns the difference between two arguments, or a third argument if the result overflows.
*
* @param x The first value.
* @param y The second value.
* @param overflowResult The return value if {@code x - y} overflows.
* @return {@code x - y}, or {@code overflowResult} if the result overflows.
*/
public static long subtractWithOverflowDefault(long x, long y, long overflowResult) {
long result = x - y;
// See Hacker's Delight 2-13 (H. Warren Jr).
if (((x ^ y) & (x ^ result)) < 0) {
return overflowResult;
}
return result;
}

/**
* Returns the index of the largest element in {@code array} that is less than (or optionally
* equal to) a specified {@code value}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,42 @@
@Config(sdk = Config.TARGET_SDK, manifest = Config.NONE)
public class UtilTest {

@Test
public void testAddWithOverflowDefault() {
long res = Util.addWithOverflowDefault(5, 10, /* overflowResult= */ 0);
assertThat(res).isEqualTo(15);

res = Util.addWithOverflowDefault(Long.MAX_VALUE - 1, 1, /* overflowResult= */ 12345);
assertThat(res).isEqualTo(Long.MAX_VALUE);

res = Util.addWithOverflowDefault(Long.MIN_VALUE + 1, -1, /* overflowResult= */ 12345);
assertThat(res).isEqualTo(Long.MIN_VALUE);

res = Util.addWithOverflowDefault(Long.MAX_VALUE, 1, /* overflowResult= */ 12345);
assertThat(res).isEqualTo(12345);

res = Util.addWithOverflowDefault(Long.MIN_VALUE, -1, /* overflowResult= */ 12345);
assertThat(res).isEqualTo(12345);
}

@Test
public void testSubtrackWithOverflowDefault() {
long res = Util.subtractWithOverflowDefault(5, 10, /* overflowResult= */ 0);
assertThat(res).isEqualTo(-5);

res = Util.subtractWithOverflowDefault(Long.MIN_VALUE + 1, 1, /* overflowResult= */ 12345);
assertThat(res).isEqualTo(Long.MIN_VALUE);

res = Util.subtractWithOverflowDefault(Long.MAX_VALUE - 1, -1, /* overflowResult= */ 12345);
assertThat(res).isEqualTo(Long.MAX_VALUE);

res = Util.subtractWithOverflowDefault(Long.MIN_VALUE, 1, /* overflowResult= */ 12345);
assertThat(res).isEqualTo(12345);

res = Util.subtractWithOverflowDefault(Long.MAX_VALUE, -1, /* overflowResult= */ 12345);
assertThat(res).isEqualTo(12345);
}

@Test
public void testInferContentType() {
assertThat(Util.inferContentType("http://a.b/c.ism")).isEqualTo(C.TYPE_SS);
Expand Down

0 comments on commit 37a275f

Please sign in to comment.