diff --git a/demo/src/main/java/com/google/android/exoplayer/demo/EventLogger.java b/demo/src/main/java/com/google/android/exoplayer/demo/EventLogger.java index 2b74602ce7..ffdf43a4d2 100644 --- a/demo/src/main/java/com/google/android/exoplayer/demo/EventLogger.java +++ b/demo/src/main/java/com/google/android/exoplayer/demo/EventLogger.java @@ -102,7 +102,8 @@ public class EventLogger implements DemoPlayer.Listener, DemoPlayer.InfoListener } @Override - public void onLoadCompleted(int sourceId, long bytesLoaded) { + public void onLoadCompleted(int sourceId, long bytesLoaded, int type, int trigger, Format format, + int mediaStartTimeMs, int mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs) { if (VerboseLogUtil.isTagEnabled(TAG)) { long downloadTime = SystemClock.elapsedRealtime() - loadStartTimeMs[sourceId]; Log.v(TAG, "loadEnd [" + getSessionTimeString() + ", " + sourceId + ", " + downloadTime diff --git a/demo/src/main/java/com/google/android/exoplayer/demo/player/DemoPlayer.java b/demo/src/main/java/com/google/android/exoplayer/demo/player/DemoPlayer.java index 8136cdc979..5427a41bcf 100644 --- a/demo/src/main/java/com/google/android/exoplayer/demo/player/DemoPlayer.java +++ b/demo/src/main/java/com/google/android/exoplayer/demo/player/DemoPlayer.java @@ -128,7 +128,8 @@ public class DemoPlayer implements ExoPlayer.Listener, ChunkSampleSource.EventLi void onBandwidthSample(int elapsedMs, long bytes, long bitrateEstimate); void onLoadStarted(int sourceId, long length, int type, int trigger, Format format, int mediaStartTimeMs, int mediaEndTimeMs); - void onLoadCompleted(int sourceId, long bytesLoaded); + void onLoadCompleted(int sourceId, long bytesLoaded, int type, int trigger, Format format, + int mediaStartTimeMs, int mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs); void onDecoderInitialized(String decoderName, long elapsedRealtimeMs, long initializationDurationMs); } @@ -539,9 +540,11 @@ public class DemoPlayer implements ExoPlayer.Listener, ChunkSampleSource.EventLi } @Override - public void onLoadCompleted(int sourceId, long bytesLoaded) { + public void onLoadCompleted(int sourceId, long bytesLoaded, int type, int trigger, Format format, + int mediaStartTimeMs, int mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs) { if (infoListener != null) { - infoListener.onLoadCompleted(sourceId, bytesLoaded); + infoListener.onLoadCompleted(sourceId, bytesLoaded, type, trigger, format, mediaStartTimeMs, + mediaEndTimeMs, elapsedRealtimeMs, loadDurationMs); } } diff --git a/library/src/main/java/com/google/android/exoplayer/chunk/BaseChunkSampleSourceEventListener.java b/library/src/main/java/com/google/android/exoplayer/chunk/BaseChunkSampleSourceEventListener.java index b8890bbb82..c155928020 100644 --- a/library/src/main/java/com/google/android/exoplayer/chunk/BaseChunkSampleSourceEventListener.java +++ b/library/src/main/java/com/google/android/exoplayer/chunk/BaseChunkSampleSourceEventListener.java @@ -48,8 +48,19 @@ public interface BaseChunkSampleSourceEventListener { * * @param sourceId The id of the reporting {@link SampleSource}. * @param bytesLoaded The number of bytes that were loaded. + * @param type The type of the loaded data. + * @param trigger The reason for the data being loaded. + * @param format The particular format to which this data corresponds, or null if the loaded data + * does not correspond to a format. + * @param mediaStartTimeMs The media time of the start of the loaded data, or -1 if this load was + * for initialization data. + * @param mediaEndTimeMs The media time of the end of the loaded data, or -1 if this load was for + * initialization data. + * @param elapsedRealtimeMs {@code elapsedRealtime} timestamp of when the load finished. + * @param loadDurationMs Amount of time taken to load the data. */ - void onLoadCompleted(int sourceId, long bytesLoaded); + void onLoadCompleted(int sourceId, long bytesLoaded, int type, int trigger, Format format, + int mediaStartTimeMs, int mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs); /** * Invoked when the current upstream load operation is canceled. diff --git a/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSampleSource.java b/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSampleSource.java index b45cfe4280..bf3f26e4b1 100644 --- a/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSampleSource.java @@ -84,6 +84,7 @@ public class ChunkSampleSource implements SampleSource, Loader.Callback { private boolean currentLoadableExceptionFatal; private int currentLoadableExceptionCount; private long currentLoadableExceptionTimestamp; + private long currentLoadStartTimeMs; private MediaFormat downstreamMediaFormat; private volatile Format downstreamFormat; @@ -329,11 +330,18 @@ public class ChunkSampleSource implements SampleSource, Loader.Callback { @Override public void onLoadCompleted(Loadable loadable) { + long now = SystemClock.elapsedRealtime(); + long loadDurationMs = now - currentLoadStartTimeMs; Chunk currentLoadable = currentLoadableHolder.chunk; chunkSource.onChunkLoadCompleted(currentLoadable); - notifyLoadCompleted(currentLoadable.bytesLoaded()); if (isMediaChunk(currentLoadable)) { + MediaChunk mediaChunk = (MediaChunk) currentLoadable; + notifyLoadCompleted(currentLoadable.bytesLoaded(), mediaChunk.type, mediaChunk.trigger, + mediaChunk.format, mediaChunk.startTimeUs, mediaChunk.endTimeUs, now, loadDurationMs); loadingFinished = ((BaseMediaChunk) currentLoadable).isLastChunk; + } else { + notifyLoadCompleted(currentLoadable.bytesLoaded(), currentLoadable.type, + currentLoadable.trigger, currentLoadable.format, -1, -1, now, loadDurationMs); } clearCurrentLoadable(); updateLoadControl(); @@ -525,6 +533,7 @@ public class ChunkSampleSource implements SampleSource, Loader.Callback { // Nothing to load. return; } + currentLoadStartTimeMs = SystemClock.elapsedRealtime(); if (isMediaChunk(currentLoadable)) { BaseMediaChunk mediaChunk = (BaseMediaChunk) currentLoadable; mediaChunk.init(sampleQueue); @@ -594,12 +603,15 @@ public class ChunkSampleSource implements SampleSource, Loader.Callback { } } - private void notifyLoadCompleted(final long bytesLoaded) { + private void notifyLoadCompleted(final long bytesLoaded, final int type, final int trigger, + final Format format, final long mediaStartTimeUs, final long mediaEndTimeUs, + final long elapsedRealtimeMs, final long loadDurationMs) { if (eventHandler != null && eventListener != null) { eventHandler.post(new Runnable() { @Override public void run() { - eventListener.onLoadCompleted(eventSourceId, bytesLoaded); + eventListener.onLoadCompleted(eventSourceId, bytesLoaded, type, trigger, format, + usToMs(mediaStartTimeUs), usToMs(mediaEndTimeUs), elapsedRealtimeMs, loadDurationMs); } }); } diff --git a/library/src/main/java/com/google/android/exoplayer/hls/HlsSampleSource.java b/library/src/main/java/com/google/android/exoplayer/hls/HlsSampleSource.java index 57d09a69a3..92f00ece75 100644 --- a/library/src/main/java/com/google/android/exoplayer/hls/HlsSampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/hls/HlsSampleSource.java @@ -84,6 +84,7 @@ public class HlsSampleSource implements SampleSource, Loader.Callback { private boolean currentLoadableExceptionFatal; private int currentLoadableExceptionCount; private long currentLoadableExceptionTimestamp; + private long currentLoadStartTimeMs; public HlsSampleSource(HlsChunkSource chunkSource, boolean frameAccurateSeeking, int downstreamRendererCount) { @@ -316,11 +317,17 @@ public class HlsSampleSource implements SampleSource, Loader.Callback { @Override public void onLoadCompleted(Loadable loadable) { + long now = SystemClock.elapsedRealtime(); + long loadDurationMs = now - currentLoadStartTimeMs; chunkSource.onChunkLoadCompleted(currentLoadable); - notifyLoadCompleted(currentLoadable.bytesLoaded()); if (isTsChunk(currentLoadable)) { TsChunk tsChunk = (TsChunk) loadable; loadingFinished = tsChunk.isLastChunk; + notifyLoadCompleted(currentLoadable.bytesLoaded(), tsChunk.type, tsChunk.trigger, + tsChunk.format, tsChunk.startTimeUs, tsChunk.endTimeUs, now, loadDurationMs); + } else { + notifyLoadCompleted(currentLoadable.bytesLoaded(), currentLoadable.type, + currentLoadable.trigger, currentLoadable.format, -1, -1, now, loadDurationMs); } if (!currentLoadableExceptionFatal) { clearCurrentLoadable(); @@ -450,6 +457,7 @@ public class HlsSampleSource implements SampleSource, Loader.Callback { return; } + currentLoadStartTimeMs = SystemClock.elapsedRealtime(); currentLoadable = nextLoadable; if (isTsChunk(currentLoadable)) { TsChunk tsChunk = (TsChunk) currentLoadable; @@ -498,12 +506,15 @@ public class HlsSampleSource implements SampleSource, Loader.Callback { } } - private void notifyLoadCompleted(final long bytesLoaded) { + private void notifyLoadCompleted(final long bytesLoaded, final int type, final int trigger, + final Format format, final long mediaStartTimeUs, final long mediaEndTimeUs, + final long elapsedRealtimeMs, final long loadDurationMs) { if (eventHandler != null && eventListener != null) { eventHandler.post(new Runnable() { @Override public void run() { - eventListener.onLoadCompleted(eventSourceId, bytesLoaded); + eventListener.onLoadCompleted(eventSourceId, bytesLoaded, type, trigger, format, + usToMs(mediaStartTimeUs), usToMs(mediaEndTimeUs), elapsedRealtimeMs, loadDurationMs); } }); }