diff --git a/library/src/main/java/com/google/android/exoplayer/ExoPlayerFactory.java b/library/src/main/java/com/google/android/exoplayer/ExoPlayerFactory.java index 3fbc314bf2..6251622f63 100644 --- a/library/src/main/java/com/google/android/exoplayer/ExoPlayerFactory.java +++ b/library/src/main/java/com/google/android/exoplayer/ExoPlayerFactory.java @@ -38,6 +38,12 @@ public final class ExoPlayerFactory { */ public static final int DEFAULT_MIN_REBUFFER_MS = 5000; + /** + * The default maximum duration for which a video renderer can attempt to seamlessly join an + * ongoing playback. + */ + public static final long DEFAULT_ALLOWED_VIDEO_JOINING_TIME_MS = 5000; + private ExoPlayerFactory() {} /** @@ -49,7 +55,22 @@ public final class ExoPlayerFactory { * @param trackSelector The {@link TrackSelector} that will be used by the instance. */ public static SimpleExoPlayer newSimpleInstance(Context context, TrackSelector trackSelector) { - return newSimpleInstance(context, trackSelector, null, false); + return newSimpleInstance(context, trackSelector, null); + } + + /** + * Obtains a {@link SimpleExoPlayer} instance. + *
+ * Must be called from a thread that has an associated {@link Looper}.
+ *
+ * @param context A {@link Context}.
+ * @param trackSelector The {@link TrackSelector} that will be used by the instance.
+ * @param drmSessionManager An optional {@link DrmSessionManager}. May be null if the instance
+ * will not be used for DRM protected playbacks.
+ */
+ public static SimpleExoPlayer newSimpleInstance(Context context, TrackSelector trackSelector,
+ DrmSessionManager drmSessionManager) {
+ return newSimpleInstance(context, trackSelector, drmSessionManager, false);
}
/**
@@ -68,7 +89,7 @@ public final class ExoPlayerFactory {
public static SimpleExoPlayer newSimpleInstance(Context context, TrackSelector trackSelector,
DrmSessionManager drmSessionManager, boolean preferExtensionDecoders) {
return newSimpleInstance(context, trackSelector, drmSessionManager, preferExtensionDecoders,
- DEFAULT_MIN_BUFFER_MS, DEFAULT_MIN_REBUFFER_MS);
+ DEFAULT_MIN_BUFFER_MS, DEFAULT_MIN_REBUFFER_MS, DEFAULT_ALLOWED_VIDEO_JOINING_TIME_MS);
}
/**
@@ -88,12 +109,14 @@ public final class ExoPlayerFactory {
* @param minRebufferMs A minimum duration of data that must be buffered for playback to resume
* after a player-invoked rebuffer (i.e. a rebuffer that occurs due to buffer depletion, and
* not due to a user action such as starting playback or seeking).
+ * @param allowedVideoJoiningTimeMs The maximum duration for which a video renderer can attempt to
+ * seamlessly join an ongoing playback.
*/
public static SimpleExoPlayer newSimpleInstance(Context context, TrackSelector trackSelector,
DrmSessionManager drmSessionManager, boolean preferExtensionDecoders, int minBufferMs,
- int minRebufferMs) {
+ int minRebufferMs, long allowedVideoJoiningTimeMs) {
return new SimpleExoPlayer(context, trackSelector, drmSessionManager, preferExtensionDecoders,
- minBufferMs, minRebufferMs);
+ minBufferMs, minRebufferMs, allowedVideoJoiningTimeMs);
}
/**
diff --git a/library/src/main/java/com/google/android/exoplayer/SimpleExoPlayer.java b/library/src/main/java/com/google/android/exoplayer/SimpleExoPlayer.java
index 5d31e83b8c..7cc68074e1 100644
--- a/library/src/main/java/com/google/android/exoplayer/SimpleExoPlayer.java
+++ b/library/src/main/java/com/google/android/exoplayer/SimpleExoPlayer.java
@@ -90,7 +90,6 @@ public final class SimpleExoPlayer implements ExoPlayer {
}
private static final String TAG = "SimpleExoPlayer";
- private static final long ALLOWED_VIDEO_JOINING_TIME_MS = 5000;
private static final int MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY = 50;
private final ExoPlayer player;
@@ -113,7 +112,7 @@ public final class SimpleExoPlayer implements ExoPlayer {
/* package */ SimpleExoPlayer(Context context, TrackSelector trackSelector,
DrmSessionManager drmSessionManager, boolean preferExtensionDecoders, int minBufferMs,
- int minRebufferMs) {
+ int minRebufferMs, long allowedVideoJoiningTimeMs) {
mainHandler = new Handler();
bandwidthMeter = new DefaultBandwidthMeter();
componentListener = new ComponentListener();
@@ -121,11 +120,11 @@ public final class SimpleExoPlayer implements ExoPlayer {
// Build the renderers.
ArrayList
- * The test will be stopped if it has finished, if the {@link HostActivity} has been paused, or
- * if the {@link HostActivity}'s {@link Surface} has been destroyed.
+ * The test will be stopped if {@link #canStop()} returns true, if the {@link HostActivity} has
+ * been paused, or if the {@link HostActivity}'s {@link Surface} has been destroyed.
*/
void onStop();
/**
- * Called on the main thread to check whether the test has finished.
- *
- * @return True if the test has finished. False otherwise.
- */
- boolean isFinished();
-
- /**
- * Called on the main thread after the test has finished and been stopped.
+ * Called on the test thread after the test has finished and been stopped.
*
* Implementations may use this method to assert that test criteria were met.
*/
@@ -88,7 +88,7 @@ public final class HostActivity extends Activity implements SurfaceHolder.Callba
private WifiLock wifiLock;
private SurfaceView surfaceView;
private Handler mainHandler;
- private CheckFinishedRunnable checkFinishedRunnable;
+ private CheckCanStopRunnable checkCanStopRunnable;
private HostedTest hostedTest;
private ConditionVariable hostedTestStoppedCondition;
@@ -147,7 +147,7 @@ public final class HostActivity extends Activity implements SurfaceHolder.Callba
surfaceView = (SurfaceView) findViewById(R.id.surface_view);
surfaceView.getHolder().addCallback(this);
mainHandler = new Handler();
- checkFinishedRunnable = new CheckFinishedRunnable();
+ checkCanStopRunnable = new CheckCanStopRunnable();
}
@Override
@@ -211,7 +211,7 @@ public final class HostActivity extends Activity implements SurfaceHolder.Callba
hostedTestStarted = true;
Log.d(TAG, "Starting test.");
hostedTest.onStart(this, surface);
- checkFinishedRunnable.startChecking();
+ checkCanStopRunnable.startChecking();
}
}
@@ -219,8 +219,16 @@ public final class HostActivity extends Activity implements SurfaceHolder.Callba
if (hostedTest != null && hostedTestStarted) {
hostedTest.onStop();
hostedTest = null;
- mainHandler.removeCallbacks(checkFinishedRunnable);
- hostedTestStoppedCondition.open();
+ mainHandler.removeCallbacks(checkCanStopRunnable);
+ // We post opening of the stopped condition so that any events posted to the main thread as a
+ // result of hostedTest.onStop() are guaranteed to be handled before hostedTest.onFinished()
+ // is invoked from runTest.
+ mainHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ hostedTestStoppedCondition.open();
+ }
+ });
}
}
@@ -229,7 +237,7 @@ public final class HostActivity extends Activity implements SurfaceHolder.Callba
return Util.SDK_INT < 12 ? WifiManager.WIFI_MODE_FULL : WifiManager.WIFI_MODE_FULL_HIGH_PERF;
}
- private final class CheckFinishedRunnable implements Runnable {
+ private final class CheckCanStopRunnable implements Runnable {
private static final long CHECK_INTERVAL_MS = 1000;
@@ -239,7 +247,7 @@ public final class HostActivity extends Activity implements SurfaceHolder.Callba
@Override
public void run() {
- if (hostedTest.isFinished()) {
+ if (hostedTest.canStop()) {
hostedTestFinished = true;
maybeStopHostedTest();
} else {