Skip to content

Commit

Permalink
Unit test for MaskingMediaSource of initial seek
Browse files Browse the repository at this point in the history
Unit test equivalent of the functional test in ExoPlayerTest
depending on the scope of the fix either this test or the ExoPlayerTest
should be kept.

This test shows flaw in the assumption that only a non-zero initial seek value
is a valid override for the window default position.

Value for `startPositionUs` in this chmmit is non-zero, so the test passes.
If the value is 0 it will fail.
  • Loading branch information
stevemayhew committed Jul 20, 2021
1 parent b9d959c commit ac044ae
Show file tree
Hide file tree
Showing 2 changed files with 151 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.source;

import android.net.Uri;
import androidx.test.ext.junit.runners.AndroidJUnit4;

import java.io.IOException;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;

import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.testutil.FakeMediaPeriod;
import com.google.android.exoplayer2.testutil.MediaSourceTestRunner;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.TransferListener;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;

/** Unit tests for {@link MaskingMediaSource}. */
@RunWith(AndroidJUnit4.class)
public class MaskingMediaSourceTest {
private static final MediaItem EMPTY_MEDIA_ITEM =
new MediaItem.Builder().setUri(Uri.EMPTY).build();
@Rule
public final MockitoRule mockito = MockitoJUnit.rule();

@Mock
private MediaPeriod mockMediaPeriod;


class FakeDynamicTimelineMediaSource extends BaseMediaSource {

@Override
protected void prepareSourceInternal(TransferListener mediaTransferListener) {
}

@Override
protected void releaseSourceInternal() {
}

@Override
public MediaItem getMediaItem() {
return EMPTY_MEDIA_ITEM;
}

@Override
public void maybeThrowSourceInfoRefreshError() {
}

@Override
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) {
return mockMediaPeriod;
}

@Override
public void releasePeriod(MediaPeriod mediaPeriod) {

}

public void setNewSourceInfo(Timeline liveTimeline) {
refreshSourceInfo(liveTimeline);
}
}

@Before
public void setupMocks() {

}

@Test
public void onChildSourceInfoRefreshed_withLiveTimeline_initialSeek() throws IOException {
MediaItem mediaItem =
new MediaItem.Builder().setUri(Uri.EMPTY).build();
Timeline liveTimeline =
new SinglePeriodTimeline(
/* presentationStartTimeMs= */ 0,
/* windowStartTimeMs= */ 0,
/* elapsedRealtimeEpochOffsetMs= */ C.TIME_UNSET,
/* periodDurationUs= */ 1000 * C.MICROS_PER_SECOND,
/* windowDurationUs= */ 1000 * C.MICROS_PER_SECOND,
/* windowPositionInPeriodUs= */ 0,
/* windowDefaultStartPositionUs= */ 20 * C.MICROS_PER_SECOND,
/* isSeekable= */ true,
/* isDynamic= */ true,
/* manifest= */ null,
mediaItem,
mediaItem.liveConfiguration);
Object periodId = liveTimeline.getUidOfPeriod(0);
FakeDynamicTimelineMediaSource mediaSource = new FakeDynamicTimelineMediaSource();
MaskingMediaSource testedMediaSource = new MaskingMediaSource(mediaSource, true);
MediaSourceTestRunner testRunner = new MediaSourceTestRunner(mediaSource, null);
try {
testRunner.runOnPlaybackThread(() -> {
testedMediaSource.prepareSourceInternal(null);
});

// This is the sequence of calls when EPII:
// - lazy prepares the initial masked media source
// - updatePeriods() creates the first period
// - the Timeline update occurs with a live timeline with start position and duration

testRunner.prepareSourceLazy();

testRunner.runOnPlaybackThread(() -> {
int startPositionUs = 20; // TODO - if this value is 0, the test will fail, of course it should not.
MaskingMediaPeriod period = testedMediaSource.createPeriod(new MediaSource.MediaPeriodId(periodId), null, startPositionUs);
mediaSource.setNewSourceInfo(liveTimeline);
assertThat(period.getPreparePositionOverrideUs()).isEqualTo(startPositionUs);
});


testRunner.releaseSource();
} finally {
testRunner.release();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.source.LoadEventInfo;
import com.google.android.exoplayer2.source.MaskingMediaSource;
import com.google.android.exoplayer2.source.MediaLoadData;
import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.MediaSource;
Expand Down Expand Up @@ -131,6 +132,17 @@ public Timeline prepareSource() throws IOException {
return assertTimelineChangeBlocking();
}

/**
* Prepares source on playback thread without expecting a timeline change. Use for "lazy" prepare
* MediaSource, e.g. {@link MaskingMediaSource}
*/
public void prepareSourceLazy() {
runOnPlaybackThread(
() -> {
mediaSource.prepareSource(mediaSourceListener, /* mediaTransferListener= */ null);
});
}

/**
* Calls {@link MediaSource#createPeriod(MediaSource.MediaPeriodId, Allocator, long)} with a zero
* start position on the playback thread, asserting that a non-null {@link MediaPeriod} is
Expand Down

0 comments on commit ac044ae

Please sign in to comment.