Commit 19d65a7a by olly Committed by Oliver Woodman

Report loading on/off changes via ExoPlayer.

Also attempt to clear up naming a little, using "buffering" to
mean the user visible buffering state, and "loading" to mean a
source being loaded.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=126693592
parent f4239eb5
......@@ -67,6 +67,11 @@ public class EventLogger implements ExoPlayer.EventListener, SimpleExoPlayer.Deb
// ExoPlayer.EventListener
@Override
public void onLoadingChanged(boolean isLoading) {
Log.d(TAG, "loading [" + isLoading + "]");
}
@Override
public void onPlayerStateChanged(boolean playWhenReady, int state) {
Log.d(TAG, "state [" + getSessionTimeString() + ", " + playWhenReady + ", "
+ getStateString(state) + "]");
......
......@@ -18,7 +18,7 @@ package com.google.android.exoplayer.demo;
import com.google.android.exoplayer.AspectRatioFrameLayout;
import com.google.android.exoplayer.C;
import com.google.android.exoplayer.ConcatenatingSampleSourceProvider;
import com.google.android.exoplayer.DefaultBufferingControl;
import com.google.android.exoplayer.DefaultLoadControl;
import com.google.android.exoplayer.DefaultTrackSelectionPolicy;
import com.google.android.exoplayer.DefaultTrackSelector;
import com.google.android.exoplayer.DefaultTrackSelector.TrackInfo;
......@@ -268,8 +268,8 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
trackSelector.addListener(this);
trackSelector.addListener(eventLogger);
trackSelectionHelper = new TrackSelectionHelper(trackSelector);
player = ExoPlayerFactory.newSimpleInstance(this, trackSelector,
new DefaultBufferingControl(), drmSessionManager, preferExtensionDecoders);
player = ExoPlayerFactory.newSimpleInstance(this, trackSelector, new DefaultLoadControl(),
drmSessionManager, preferExtensionDecoders);
player.addListener(this);
player.addListener(eventLogger);
player.setDebugListener(eventLogger);
......@@ -389,6 +389,11 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
// ExoPlayer.EventListener implementation
@Override
public void onLoadingChanged(boolean isLoading) {
// Do nothing.
}
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if (playbackState == ExoPlayer.STATE_ENDED) {
showControls();
......
......@@ -89,6 +89,11 @@ public class FlacPlaybackTest extends InstrumentationTestCase {
}
@Override
public void onLoadingChanged(boolean isLoading) {
// Do nothing.
}
@Override
public void onPlayWhenReadyCommitted () {
// Do nothing.
}
......
......@@ -89,6 +89,11 @@ public class OpusPlaybackTest extends InstrumentationTestCase {
}
@Override
public void onLoadingChanged(boolean isLoading) {
// Do nothing.
}
@Override
public void onPlayWhenReadyCommitted () {
// Do nothing.
}
......
......@@ -108,6 +108,11 @@ public class VpxPlaybackTest extends InstrumentationTestCase {
}
@Override
public void onLoadingChanged(boolean isLoading) {
// Do nothing.
}
@Override
public void onPlayWhenReadyCommitted () {
// Do nothing.
}
......
......@@ -19,26 +19,10 @@ import com.google.android.exoplayer.upstream.Allocator;
import com.google.android.exoplayer.upstream.DefaultAllocator;
import com.google.android.exoplayer.util.Util;
import android.os.Handler;
/**
* The default {@link BufferingControl} implementation.
* The default {@link LoadControl} implementation.
*/
public final class DefaultBufferingControl implements BufferingControl {
/**
* Interface definition for a callback to be notified of {@link DefaultBufferingControl} events.
*/
public interface EventListener {
/**
* Invoked when the control transitions from a buffering to a draining state or vice versa.
*
* @param buffering Whether the control is now in the buffering state.
*/
void onBufferingChanged(boolean buffering);
}
public final class DefaultLoadControl implements LoadControl {
/**
* The default minimum duration of media that the player will attempt to ensure is buffered at all
......@@ -69,8 +53,6 @@ public final class DefaultBufferingControl implements BufferingControl {
private static final int BELOW_LOW_WATERMARK = 2;
private final DefaultAllocator allocator;
private final Handler eventHandler;
private final EventListener eventListener;
private final long minBufferUs;
private final long maxBufferUs;
......@@ -83,7 +65,7 @@ public final class DefaultBufferingControl implements BufferingControl {
/**
* Constructs a new instance, using the {@code DEFAULT_*} constants defined in this class.
*/
public DefaultBufferingControl() {
public DefaultLoadControl() {
this(new DefaultAllocator(C.DEFAULT_BUFFER_SEGMENT_SIZE));
}
......@@ -92,22 +74,9 @@ public final class DefaultBufferingControl implements BufferingControl {
*
* @param allocator The {@link DefaultAllocator} used by the loader.
*/
public DefaultBufferingControl(DefaultAllocator allocator) {
this(allocator, null, null);
}
/**
* Constructs a new instance, using the {@code DEFAULT_*} constants defined in this class.
*
* @param allocator The {@link DefaultAllocator} used by the loader.
* @param eventHandler A handler to use when delivering events to {@code eventListener}. May be
* null if delivery of events is not required.
* @param eventListener A listener of events. May be null if delivery of events is not required.
*/
public DefaultBufferingControl(DefaultAllocator allocator, Handler eventHandler,
EventListener eventListener) {
public DefaultLoadControl(DefaultAllocator allocator) {
this(allocator, DEFAULT_MIN_BUFFER_MS, DEFAULT_MAX_BUFFER_MS, DEFAULT_BUFFER_FOR_PLAYBACK_MS,
DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS, eventHandler, eventListener);
DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS);
}
/**
......@@ -123,16 +92,10 @@ public final class DefaultBufferingControl implements BufferingControl {
* @param bufferForPlaybackAfterRebufferMs The default duration of media that must be buffered for
* playback to resume after a player-invoked rebuffer (i.e. a rebuffer that occurs due to
* buffer depletion rather than a user action), in milliseconds.
* @param eventHandler A handler to use when delivering events to {@code eventListener}. May be
* null if delivery of events is not required.
* @param eventListener A listener of events. May be null if delivery of events is not required.
*/
public DefaultBufferingControl(DefaultAllocator allocator, int minBufferMs, int maxBufferMs,
long bufferForPlaybackMs, long bufferForPlaybackAfterRebufferMs, Handler eventHandler,
EventListener eventListener) {
public DefaultLoadControl(DefaultAllocator allocator, int minBufferMs, int maxBufferMs,
long bufferForPlaybackMs, long bufferForPlaybackAfterRebufferMs) {
this.allocator = allocator;
this.eventHandler = eventHandler;
this.eventListener = eventListener;
minBufferUs = minBufferMs * 1000L;
maxBufferUs = maxBufferMs * 1000L;
bufferForPlaybackUs = bufferForPlaybackMs * 1000L;
......@@ -154,7 +117,7 @@ public final class DefaultBufferingControl implements BufferingControl {
@Override
public void reset() {
targetBufferSize = 0;
setBuffering(false);
isBuffering = false;
}
@Override
......@@ -169,20 +132,12 @@ public final class DefaultBufferingControl implements BufferingControl {
}
@Override
public boolean shouldContinueBuffering(long bufferedDurationUs) {
public boolean shouldContinueLoading(long bufferedDurationUs) {
int bufferTimeState = getBufferTimeState(bufferedDurationUs);
boolean targetBufferSizeReached = allocator.getTotalBytesAllocated() >= targetBufferSize;
boolean shouldBuffer = bufferTimeState == BELOW_LOW_WATERMARK
isBuffering = bufferTimeState == BELOW_LOW_WATERMARK
|| (bufferTimeState == BETWEEN_WATERMARKS && isBuffering && !targetBufferSizeReached);
setBuffering(shouldBuffer);
return shouldBuffer;
}
private void setBuffering(boolean isBuffering) {
if (this.isBuffering != isBuffering) {
this.isBuffering = isBuffering;
notifyBufferingChanged(isBuffering);
}
return isBuffering;
}
private int getBufferTimeState(long bufferedDurationUs) {
......@@ -190,15 +145,4 @@ public final class DefaultBufferingControl implements BufferingControl {
: (bufferedDurationUs < minBufferUs ? BELOW_LOW_WATERMARK : BETWEEN_WATERMARKS);
}
private void notifyBufferingChanged(final boolean buffering) {
if (eventHandler != null && eventListener != null) {
eventHandler.post(new Runnable() {
@Override
public void run() {
eventListener.onBufferingChanged(buffering);
}
});
}
}
}
......@@ -98,6 +98,13 @@ public interface ExoPlayer {
interface EventListener {
/**
* Invoked when the player starts or stops loading the source.
*
* @param isLoading Whether the source is currently being loaded.
*/
void onLoadingChanged(boolean isLoading);
/**
* Invoked when the value returned from either {@link ExoPlayer#getPlayWhenReady()} or
* {@link ExoPlayer#getPlaybackState()} changes.
*
......@@ -270,6 +277,13 @@ public interface ExoPlayer {
boolean isPlayWhenReadyCommitted();
/**
* Whether the player is currently loading the source.
*
* @return True if the player is currently loading the source. False otherwise.
*/
boolean isLoading();
/**
* Seeks to a position specified in milliseconds in the current source.
*
* @param positionMs The seek position.
......
......@@ -42,7 +42,7 @@ 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, new DefaultBufferingControl(), null);
return newSimpleInstance(context, trackSelector, new DefaultLoadControl(), null);
}
/**
......@@ -52,13 +52,13 @@ public final class ExoPlayerFactory {
*
* @param context A {@link Context}.
* @param trackSelector The {@link TrackSelector} that will be used by the instance.
* @param bufferingControl The {@link BufferingControl} that will be used by the instance.
* @param loadControl The {@link LoadControl} 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,
BufferingControl bufferingControl, DrmSessionManager drmSessionManager) {
return newSimpleInstance(context, trackSelector, bufferingControl, drmSessionManager, false);
LoadControl loadControl, DrmSessionManager drmSessionManager) {
return newSimpleInstance(context, trackSelector, loadControl, drmSessionManager, false);
}
/**
......@@ -68,7 +68,7 @@ public final class ExoPlayerFactory {
*
* @param context A {@link Context}.
* @param trackSelector The {@link TrackSelector} that will be used by the instance.
* @param bufferingControl The {@link BufferingControl} that will be used by the instance.
* @param loadControl The {@link LoadControl} 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.
* @param preferExtensionDecoders True to prefer {@link TrackRenderer} instances defined in
......@@ -76,9 +76,9 @@ public final class ExoPlayerFactory {
* included in the application build for setting this flag to have any effect.
*/
public static SimpleExoPlayer newSimpleInstance(Context context, TrackSelector trackSelector,
BufferingControl bufferingControl, DrmSessionManager drmSessionManager,
LoadControl loadControl, DrmSessionManager drmSessionManager,
boolean preferExtensionDecoders) {
return newSimpleInstance(context, trackSelector, bufferingControl, drmSessionManager,
return newSimpleInstance(context, trackSelector, loadControl, drmSessionManager,
preferExtensionDecoders, DEFAULT_ALLOWED_VIDEO_JOINING_TIME_MS);
}
......@@ -89,7 +89,7 @@ public final class ExoPlayerFactory {
*
* @param context A {@link Context}.
* @param trackSelector The {@link TrackSelector} that will be used by the instance.
* @param bufferingControl The {@link BufferingControl} that will be used by the instance.
* @param loadControl The {@link LoadControl} 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.
* @param preferExtensionDecoders True to prefer {@link TrackRenderer} instances defined in
......@@ -99,9 +99,9 @@ public final class ExoPlayerFactory {
* seamlessly join an ongoing playback.
*/
public static SimpleExoPlayer newSimpleInstance(Context context, TrackSelector trackSelector,
BufferingControl bufferingControl, DrmSessionManager drmSessionManager,
LoadControl loadControl, DrmSessionManager drmSessionManager,
boolean preferExtensionDecoders, long allowedVideoJoiningTimeMs) {
return new SimpleExoPlayer(context, trackSelector, bufferingControl, drmSessionManager,
return new SimpleExoPlayer(context, trackSelector, loadControl, drmSessionManager,
preferExtensionDecoders, allowedVideoJoiningTimeMs);
}
......@@ -114,7 +114,7 @@ public final class ExoPlayerFactory {
* @param trackSelector The {@link TrackSelector} that will be used by the instance.
*/
public static ExoPlayer newInstance(TrackRenderer[] renderers, TrackSelector trackSelector) {
return newInstance(renderers, trackSelector, new DefaultBufferingControl());
return newInstance(renderers, trackSelector, new DefaultLoadControl());
}
/**
......@@ -124,11 +124,11 @@ public final class ExoPlayerFactory {
*
* @param renderers The {@link TrackRenderer}s that will be used by the instance.
* @param trackSelector The {@link TrackSelector} that will be used by the instance.
* @param bufferingControl The {@link BufferingControl} that will be used by the instance.
* @param loadControl The {@link LoadControl} that will be used by the instance.
*/
public static ExoPlayer newInstance(TrackRenderer[] renderers, TrackSelector trackSelector,
BufferingControl bufferingControl) {
return new ExoPlayerImpl(renderers, trackSelector, bufferingControl);
LoadControl loadControl) {
return new ExoPlayerImpl(renderers, trackSelector, loadControl);
}
}
......@@ -41,6 +41,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
private int playbackState;
private int pendingPlayWhenReadyAcks;
private int pendingSetSourceProviderAndSeekAcks;
private boolean isLoading;
// Playback information when there is no pending seek/set source operation.
private PlaybackInfo playbackInfo;
......@@ -55,11 +56,11 @@ import java.util.concurrent.CopyOnWriteArraySet;
*
* @param renderers The {@link TrackRenderer}s that will be used by the instance.
* @param trackSelector The {@link TrackSelector} that will be used by the instance.
* @param bufferingControl The {@link BufferingControl} that will be used by the instance.
* @param loadControl The {@link LoadControl} that will be used by the instance.
*/
@SuppressLint("HandlerLeak")
public ExoPlayerImpl(TrackRenderer[] renderers, TrackSelector trackSelector,
BufferingControl bufferingControl) {
LoadControl loadControl) {
Log.i(TAG, "Init " + ExoPlayerLibraryInfo.VERSION);
Assertions.checkNotNull(renderers);
Assertions.checkState(renderers.length > 0);
......@@ -72,8 +73,8 @@ import java.util.concurrent.CopyOnWriteArraySet;
ExoPlayerImpl.this.handleEvent(msg);
}
};
internalPlayer = new ExoPlayerImplInternal(renderers, trackSelector, bufferingControl,
playWhenReady, eventHandler);
internalPlayer = new ExoPlayerImplInternal(renderers, trackSelector, loadControl, playWhenReady,
eventHandler);
playbackInfo = new ExoPlayerImplInternal.PlaybackInfo(0);
}
......@@ -133,6 +134,11 @@ import java.util.concurrent.CopyOnWriteArraySet;
}
@Override
public boolean isLoading() {
return isLoading;
}
@Override
public void seekTo(long positionMs) {
seekTo(getCurrentSourceIndex(), positionMs);
}
......@@ -221,6 +227,13 @@ import java.util.concurrent.CopyOnWriteArraySet;
}
break;
}
case ExoPlayerImplInternal.MSG_LOADING_CHANGED: {
isLoading = msg.arg1 != 0;
for (EventListener listener : listeners) {
listener.onLoadingChanged(isLoading);
}
break;
}
case ExoPlayerImplInternal.MSG_SET_PLAY_WHEN_READY_ACK: {
pendingPlayWhenReadyAcks--;
if (pendingPlayWhenReadyAcks == 0) {
......
......@@ -20,7 +20,7 @@ import com.google.android.exoplayer.upstream.Allocator;
/**
* Controls buffering of media.
*/
public interface BufferingControl {
public interface LoadControl {
/**
* Invoked by the player when a track selection occurs.
......@@ -55,11 +55,11 @@ public interface BufferingControl {
boolean shouldStartPlayback(long bufferedDurationUs, boolean rebuffering);
/**
* Invoked by the player to determine whether buffering should continue.
* Invoked by the player to determine whether it should continue to load the source.
*
* @param bufferedDurationUs The duration of media that's currently buffered.
* @return True if the buffering should continue. False otherwise.
* @return True if the loading should continue. False otherwise.
*/
boolean shouldContinueBuffering(long bufferedDurationUs);
boolean shouldContinueLoading(long bufferedDurationUs);
}
......@@ -111,7 +111,7 @@ public final class SimpleExoPlayer implements ExoPlayer {
private CodecCounters audioCodecCounters;
/* package */ SimpleExoPlayer(Context context, TrackSelector trackSelector,
BufferingControl bufferingControl, DrmSessionManager drmSessionManager,
LoadControl loadControl, DrmSessionManager drmSessionManager,
boolean preferExtensionDecoders, long allowedVideoJoiningTimeMs) {
mainHandler = new Handler();
bandwidthMeter = new DefaultBandwidthMeter();
......@@ -145,7 +145,7 @@ public final class SimpleExoPlayer implements ExoPlayer {
this.audioRendererCount = audioRendererCount;
// Build the player and associated objects.
player = new ExoPlayerImpl(renderers, trackSelector, bufferingControl);
player = new ExoPlayerImpl(renderers, trackSelector, loadControl);
}
/**
......@@ -339,6 +339,11 @@ public final class SimpleExoPlayer implements ExoPlayer {
}
@Override
public boolean isLoading() {
return player.isLoading();
}
@Override
public void seekTo(long positionMs) {
player.seekTo(positionMs);
}
......
......@@ -154,6 +154,11 @@ public final class DebugTextViewHelper implements Runnable, ExoPlayer.EventListe
// ExoPlayer.EventListener implementation
@Override
public void onLoadingChanged(boolean isLoading) {
// Do nothing.
}
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
updateTextView();
}
......
......@@ -174,7 +174,12 @@ public abstract class ExoHostedTest implements HostedTest, ExoPlayer.EventListen
assertPassed(audioCodecCounters, videoCodecCounters);
}
// ExoPlayer.Listener
// ExoPlayer.EventListener
@Override
public void onLoadingChanged(boolean isLoading) {
// Do nothing.
}
@Override
public final void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment