From 662e10ec3ed39ae3f3f37ae69220de975218dd78 Mon Sep 17 00:00:00 2001 From: "A.Akira" Date: Thu, 31 May 2018 13:54:18 +0900 Subject: [PATCH 1/3] Update ExoPlayer 2.8.1. --- .../playermanager/sample/PlayerActivity.kt | 14 +- build.gradle | 4 +- .../playermanager/ima/AdPlayerController.kt | 4 +- .../aakira/playermanager/EventLogger.java | 499 ++++++++++-------- .../playermanager/LimitBandwidthMeter.java | 141 ++++- .../aakira/playermanager/CallBackTypeAlias.kt | 23 +- .../github/aakira/playermanager/EventProxy.kt | 319 ++++++++--- .../aakira/playermanager/ExoPlayerManager.kt | 73 ++- 8 files changed, 697 insertions(+), 380 deletions(-) diff --git a/app/src/main/kotlin/com/github/aakira/playermanager/sample/PlayerActivity.kt b/app/src/main/kotlin/com/github/aakira/playermanager/sample/PlayerActivity.kt index 074dedf..2f16bc5 100644 --- a/app/src/main/kotlin/com/github/aakira/playermanager/sample/PlayerActivity.kt +++ b/app/src/main/kotlin/com/github/aakira/playermanager/sample/PlayerActivity.kt @@ -5,14 +5,11 @@ import android.os.Bundle import android.widget.Button import com.github.aakira.playermanager.DataSourceCreator import com.github.aakira.playermanager.ExoPlayerManager -import com.google.android.exoplayer2.Format import com.google.android.exoplayer2.SimpleExoPlayer import com.google.android.exoplayer2.ui.PlayerView -import com.google.android.exoplayer2.upstream.DataSpec import com.google.android.exoplayer2.util.Util import kotterknife.bindView import timber.log.Timber -import java.io.IOException /** * An activity that plays media using [SimpleExoPlayer]. @@ -67,13 +64,12 @@ class PlayerActivity : Activity() { playerManager.addOnAudioCapabilitiesChangedListener { } - playerManager.addOnVideoSizeChangedListener { width, height, unappliedRotationDegrees, pixelWidthHeightRatio -> + playerManager.addOnVideoSizeChangedListener { eventTime, width, height, unappliedRotationDegrees, + pixelWidthHeightRatio -> } - playerManager.addOnMediaSourceLoadErrorListener { dataSpec: DataSpec?, dataType: Int, trackType: Int, - trackFormat: Format?, trackSelectionReason: Int, trackSelectionData: Any?, - mediaStartTimeMs: Long, mediaEndTimeMs: Long, elapsedRealtimeMs: Long, - loadDurationMs: Long, bytesLoaded: Long, error: IOException?, wasCanceled: Boolean -> + playerManager.addOnMediaSourceLoadErrorListener { eventTime, loadEventInfo, mediaLoadData, + error, wasCanceled -> } playerManager.addOnStateChangedListener { playWhenReady: Boolean, playbackState: Int -> @@ -124,4 +120,4 @@ class PlayerActivity : Activity() { private fun updatePlayBackSpeedString(speed: Float) { playBackSpeedButton.text = String.format("x %.1f", speed) } -} \ No newline at end of file +} diff --git a/build.gradle b/build.gradle index 3852694..15957e0 100644 --- a/build.gradle +++ b/build.gradle @@ -16,7 +16,7 @@ buildscript { // Base libraries ext.KOTLIN_VERSION = "1.2.30" - ext.EXO_PLAYER_VERSION = "2.7.3" + ext.EXO_PLAYER_VERSION = "2.8.1" ext.IMA_VERSION = "3.7.2" // Others @@ -50,4 +50,4 @@ allprojects { task clean(type: Delete) { delete rootProject.buildDir -} \ No newline at end of file +} diff --git a/ima/src/main/kotlin/com/github/aakira/playermanager/ima/AdPlayerController.kt b/ima/src/main/kotlin/com/github/aakira/playermanager/ima/AdPlayerController.kt index e801209..38c0766 100644 --- a/ima/src/main/kotlin/com/github/aakira/playermanager/ima/AdPlayerController.kt +++ b/ima/src/main/kotlin/com/github/aakira/playermanager/ima/AdPlayerController.kt @@ -105,7 +105,7 @@ class AdPlayerController private constructor( callback.onError() } } - playerManager.addOnMediaSourceLoadErrorListener { _, _, _, _, _, _, _, _, _, _, _, _, _ -> + playerManager.addOnMediaSourceLoadErrorListener { _, _, _, _, _ -> if (!isAdDisplayed) return@addOnMediaSourceLoadErrorListener for (callback in adCallbacks) { @@ -309,4 +309,4 @@ class AdPlayerController private constructor( isAdPlaying = true pauseContentListener?.onPauseContentRequested() } -} \ No newline at end of file +} diff --git a/playermanager/src/main/java/com/github/aakira/playermanager/EventLogger.java b/playermanager/src/main/java/com/github/aakira/playermanager/EventLogger.java index 61a73be..2869b0b 100644 --- a/playermanager/src/main/java/com/github/aakira/playermanager/EventLogger.java +++ b/playermanager/src/main/java/com/github/aakira/playermanager/EventLogger.java @@ -15,9 +15,12 @@ */ package com.github.aakira.playermanager; +import android.net.NetworkInfo; import android.os.SystemClock; +import android.support.annotation.Nullable; import android.util.Log; import android.view.Surface; + import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.Format; @@ -25,43 +28,25 @@ import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.RendererCapabilities; import com.google.android.exoplayer2.Timeline; -import com.google.android.exoplayer2.audio.AudioRendererEventListener; +import com.google.android.exoplayer2.analytics.AnalyticsListener; import com.google.android.exoplayer2.decoder.DecoderCounters; -import com.google.android.exoplayer2.drm.DefaultDrmSessionManager; import com.google.android.exoplayer2.metadata.Metadata; -import com.google.android.exoplayer2.metadata.MetadataOutput; -import com.google.android.exoplayer2.metadata.emsg.EventMessage; -import com.google.android.exoplayer2.metadata.id3.ApicFrame; -import com.google.android.exoplayer2.metadata.id3.CommentFrame; -import com.google.android.exoplayer2.metadata.id3.GeobFrame; -import com.google.android.exoplayer2.metadata.id3.Id3Frame; -import com.google.android.exoplayer2.metadata.id3.PrivFrame; -import com.google.android.exoplayer2.metadata.id3.TextInformationFrame; -import com.google.android.exoplayer2.metadata.id3.UrlLinkFrame; -import com.google.android.exoplayer2.metadata.scte35.SpliceCommand; -import com.google.android.exoplayer2.source.MediaSourceEventListener; +import com.google.android.exoplayer2.source.MediaSourceEventListener.LoadEventInfo; +import com.google.android.exoplayer2.source.MediaSourceEventListener.MediaLoadData; import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.TrackGroupArray; -import com.google.android.exoplayer2.source.ads.AdsMediaSource; import com.google.android.exoplayer2.trackselection.MappingTrackSelector; import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo; import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelectionArray; -import com.google.android.exoplayer2.upstream.DataSpec; -import com.google.android.exoplayer2.video.VideoRendererEventListener; +import com.google.android.exoplayer2.util.Util; + import java.io.IOException; import java.text.NumberFormat; import java.util.Locale; /** Logs events from {@link Player} and other core components using {@link Log}. */ -public class EventLogger - implements Player.EventListener, - MetadataOutput, - AudioRendererEventListener, - VideoRendererEventListener, - MediaSourceEventListener, - AdsMediaSource.EventListener, - DefaultDrmSessionManager.EventListener { +public class EventLogger implements AnalyticsListener { private static final String TAG = "EventLogger"; private static final int MAX_TIMELINE_ITEM_LINES = 3; @@ -73,378 +58,424 @@ public class EventLogger TIME_FORMAT.setGroupingUsed(false); } - private final MappingTrackSelector trackSelector; + private final @Nullable MappingTrackSelector trackSelector; private final Timeline.Window window; private final Timeline.Period period; private final long startTimeMs; - public EventLogger(MappingTrackSelector trackSelector) { + /** + * Creates event logger. + * + * @param trackSelector The mapping track selector used by the player. May be null if detailed + * logging of track mapping is not required. + */ + public EventLogger(@Nullable MappingTrackSelector trackSelector) { this.trackSelector = trackSelector; window = new Timeline.Window(); period = new Timeline.Period(); startTimeMs = SystemClock.elapsedRealtime(); } - // Player.EventListener + // AnalyticsListener + + @Override + public void onLoadingChanged(EventTime eventTime, boolean isLoading) { + logd(eventTime, "loading", Boolean.toString(isLoading)); + } @Override - public void onLoadingChanged(boolean isLoading) { - Log.d(TAG, "loading [" + isLoading + "]"); + public void onPlayerStateChanged(EventTime eventTime, boolean playWhenReady, int state) { + logd(eventTime, "state", playWhenReady + ", " + getStateString(state)); } @Override - public void onPlayerStateChanged(boolean playWhenReady, int state) { - Log.d(TAG, "state [" + getSessionTimeString() + ", " + playWhenReady + ", " - + getStateString(state) + "]"); + public void onRepeatModeChanged(EventTime eventTime, @Player.RepeatMode int repeatMode) { + logd(eventTime, "repeatMode", getRepeatModeString(repeatMode)); } @Override - public void onRepeatModeChanged(@Player.RepeatMode int repeatMode) { - Log.d(TAG, "repeatMode [" + getRepeatModeString(repeatMode) + "]"); + public void onShuffleModeChanged(EventTime eventTime, boolean shuffleModeEnabled) { + logd(eventTime, "shuffleModeEnabled", Boolean.toString(shuffleModeEnabled)); } @Override - public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) { - Log.d(TAG, "shuffleModeEnabled [" + shuffleModeEnabled + "]"); + public void onPositionDiscontinuity(EventTime eventTime, @Player.DiscontinuityReason int reason) { + logd(eventTime, "positionDiscontinuity", getDiscontinuityReasonString(reason)); } @Override - public void onPositionDiscontinuity(@Player.DiscontinuityReason int reason) { - Log.d(TAG, "positionDiscontinuity [" + getDiscontinuityReasonString(reason) + "]"); + public void onSeekStarted(EventTime eventTime) { + logd(eventTime, "seekStarted"); } @Override - public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) { - Log.d(TAG, "playbackParameters " + String.format( - "[speed=%.2f, pitch=%.2f]", playbackParameters.speed, playbackParameters.pitch)); + public void onPlaybackParametersChanged( + EventTime eventTime, PlaybackParameters playbackParameters) { + logd( + eventTime, + "playbackParameters", + Util.formatInvariant( + "speed=%.2f, pitch=%.2f, skipSilence=%s", + playbackParameters.speed, playbackParameters.pitch, playbackParameters.skipSilence)); } @Override - public void onTimelineChanged(Timeline timeline, Object manifest, - @Player.TimelineChangeReason int reason) { - int periodCount = timeline.getPeriodCount(); - int windowCount = timeline.getWindowCount(); - Log.d(TAG, "timelineChanged [periodCount=" + periodCount + ", windowCount=" + windowCount - + ", reason=" + getTimelineChangeReasonString(reason)); + public void onTimelineChanged(EventTime eventTime, @Player.TimelineChangeReason int reason) { + int periodCount = eventTime.timeline.getPeriodCount(); + int windowCount = eventTime.timeline.getWindowCount(); + logd( + "timelineChanged [" + + getEventTimeString(eventTime) + + ", periodCount=" + + periodCount + + ", windowCount=" + + windowCount + + ", reason=" + + getTimelineChangeReasonString(reason)); for (int i = 0; i < Math.min(periodCount, MAX_TIMELINE_ITEM_LINES); i++) { - timeline.getPeriod(i, period); - Log.d(TAG, " " + "period [" + getTimeString(period.getDurationMs()) + "]"); + eventTime.timeline.getPeriod(i, period); + logd(" " + "period [" + getTimeString(period.getDurationMs()) + "]"); } if (periodCount > MAX_TIMELINE_ITEM_LINES) { - Log.d(TAG, " ..."); + logd(" ..."); } for (int i = 0; i < Math.min(windowCount, MAX_TIMELINE_ITEM_LINES); i++) { - timeline.getWindow(i, window); - Log.d(TAG, " " + "window [" + getTimeString(window.getDurationMs()) + ", " - + window.isSeekable + ", " + window.isDynamic + "]"); + eventTime.timeline.getWindow(i, window); + logd( + " " + + "window [" + + getTimeString(window.getDurationMs()) + + ", " + + window.isSeekable + + ", " + + window.isDynamic + + "]"); } if (windowCount > MAX_TIMELINE_ITEM_LINES) { - Log.d(TAG, " ..."); + logd(" ..."); } - Log.d(TAG, "]"); + logd("]"); } @Override - public void onPlayerError(ExoPlaybackException e) { - Log.e(TAG, "playerFailed [" + getSessionTimeString() + "]", e); + public void onPlayerError(EventTime eventTime, ExoPlaybackException e) { + loge(eventTime, "playerFailed", e); } @Override - public void onTracksChanged(TrackGroupArray ignored, TrackSelectionArray trackSelections) { - MappedTrackInfo mappedTrackInfo = trackSelector.getCurrentMappedTrackInfo(); + public void onTracksChanged( + EventTime eventTime, TrackGroupArray ignored, TrackSelectionArray trackSelections) { + MappedTrackInfo mappedTrackInfo = + trackSelector != null ? trackSelector.getCurrentMappedTrackInfo() : null; if (mappedTrackInfo == null) { - Log.d(TAG, "Tracks []"); + logd(eventTime, "tracksChanged", "[]"); return; } - Log.d(TAG, "Tracks ["); + logd("tracksChanged [" + getEventTimeString(eventTime) + ", "); // Log tracks associated to renderers. - for (int rendererIndex = 0; rendererIndex < mappedTrackInfo.length; rendererIndex++) { + int rendererCount = mappedTrackInfo.getRendererCount(); + for (int rendererIndex = 0; rendererIndex < rendererCount; rendererIndex++) { TrackGroupArray rendererTrackGroups = mappedTrackInfo.getTrackGroups(rendererIndex); TrackSelection trackSelection = trackSelections.get(rendererIndex); if (rendererTrackGroups.length > 0) { - Log.d(TAG, " Renderer:" + rendererIndex + " ["); + logd(" Renderer:" + rendererIndex + " ["); for (int groupIndex = 0; groupIndex < rendererTrackGroups.length; groupIndex++) { TrackGroup trackGroup = rendererTrackGroups.get(groupIndex); - String adaptiveSupport = getAdaptiveSupportString(trackGroup.length, - mappedTrackInfo.getAdaptiveSupport(rendererIndex, groupIndex, false)); - Log.d(TAG, " Group:" + groupIndex + ", adaptive_supported=" + adaptiveSupport + " ["); + String adaptiveSupport = + getAdaptiveSupportString( + trackGroup.length, + mappedTrackInfo.getAdaptiveSupport(rendererIndex, groupIndex, false)); + logd(" Group:" + groupIndex + ", adaptive_supported=" + adaptiveSupport + " ["); for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) { String status = getTrackStatusString(trackSelection, trackGroup, trackIndex); - String formatSupport = getFormatSupportString( - mappedTrackInfo.getTrackFormatSupport(rendererIndex, groupIndex, trackIndex)); - Log.d(TAG, " " + status + " Track:" + trackIndex + ", " - + Format.toLogString(trackGroup.getFormat(trackIndex)) - + ", supported=" + formatSupport); + String formatSupport = + getFormatSupportString( + mappedTrackInfo.getTrackSupport(rendererIndex, groupIndex, trackIndex)); + logd( + " " + + status + + " Track:" + + trackIndex + + ", " + + Format.toLogString(trackGroup.getFormat(trackIndex)) + + ", supported=" + + formatSupport); } - Log.d(TAG, " ]"); + logd(" ]"); } // Log metadata for at most one of the tracks selected for the renderer. if (trackSelection != null) { for (int selectionIndex = 0; selectionIndex < trackSelection.length(); selectionIndex++) { Metadata metadata = trackSelection.getFormat(selectionIndex).metadata; if (metadata != null) { - Log.d(TAG, " Metadata ["); + logd(" Metadata ["); printMetadata(metadata, " "); - Log.d(TAG, " ]"); + logd(" ]"); break; } } } - Log.d(TAG, " ]"); + logd(" ]"); } } // Log tracks not associated with a renderer. - TrackGroupArray unassociatedTrackGroups = mappedTrackInfo.getUnassociatedTrackGroups(); + TrackGroupArray unassociatedTrackGroups = mappedTrackInfo.getUnmappedTrackGroups(); if (unassociatedTrackGroups.length > 0) { - Log.d(TAG, " Renderer:None ["); + logd(" Renderer:None ["); for (int groupIndex = 0; groupIndex < unassociatedTrackGroups.length; groupIndex++) { - Log.d(TAG, " Group:" + groupIndex + " ["); + logd(" Group:" + groupIndex + " ["); TrackGroup trackGroup = unassociatedTrackGroups.get(groupIndex); for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) { String status = getTrackStatusString(false); - String formatSupport = getFormatSupportString( - RendererCapabilities.FORMAT_UNSUPPORTED_TYPE); - Log.d(TAG, " " + status + " Track:" + trackIndex + ", " - + Format.toLogString(trackGroup.getFormat(trackIndex)) - + ", supported=" + formatSupport); + String formatSupport = + getFormatSupportString(RendererCapabilities.FORMAT_UNSUPPORTED_TYPE); + logd( + " " + + status + + " Track:" + + trackIndex + + ", " + + Format.toLogString(trackGroup.getFormat(trackIndex)) + + ", supported=" + + formatSupport); } - Log.d(TAG, " ]"); + logd(" ]"); } - Log.d(TAG, " ]"); + logd(" ]"); } - Log.d(TAG, "]"); + logd("]"); } @Override - public void onSeekProcessed() { - Log.d(TAG, "seekProcessed"); + public void onSeekProcessed(EventTime eventTime) { + logd(eventTime, "seekProcessed"); } - // MetadataOutput - @Override - public void onMetadata(Metadata metadata) { - Log.d(TAG, "onMetadata ["); + public void onMetadata(EventTime eventTime, Metadata metadata) { + logd("metadata [" + getEventTimeString(eventTime) + ", "); printMetadata(metadata, " "); - Log.d(TAG, "]"); + logd("]"); } - // AudioRendererEventListener - @Override - public void onAudioEnabled(DecoderCounters counters) { - Log.d(TAG, "audioEnabled [" + getSessionTimeString() + "]"); + public void onDecoderEnabled(EventTime eventTime, int trackType, DecoderCounters counters) { + logd(eventTime, "decoderEnabled", getTrackTypeString(trackType)); } @Override - public void onAudioSessionId(int audioSessionId) { - Log.d(TAG, "audioSessionId [" + audioSessionId + "]"); + public void onAudioSessionId(EventTime eventTime, int audioSessionId) { + logd(eventTime, "audioSessionId", Integer.toString(audioSessionId)); } @Override - public void onAudioDecoderInitialized(String decoderName, long elapsedRealtimeMs, - long initializationDurationMs) { - Log.d(TAG, "audioDecoderInitialized [" + getSessionTimeString() + ", " + decoderName + "]"); + public void onDecoderInitialized( + EventTime eventTime, int trackType, String decoderName, long initializationDurationMs) { + logd(eventTime, "decoderInitialized", getTrackTypeString(trackType) + ", " + decoderName); } @Override - public void onAudioInputFormatChanged(Format format) { - Log.d(TAG, "audioFormatChanged [" + getSessionTimeString() + ", " + Format.toLogString(format) - + "]"); + public void onDecoderInputFormatChanged(EventTime eventTime, int trackType, Format format) { + logd( + eventTime, + "decoderInputFormatChanged", + getTrackTypeString(trackType) + ", " + Format.toLogString(format)); } @Override - public void onAudioDisabled(DecoderCounters counters) { - Log.d(TAG, "audioDisabled [" + getSessionTimeString() + "]"); + public void onDecoderDisabled(EventTime eventTime, int trackType, DecoderCounters counters) { + logd(eventTime, "decoderDisabled", getTrackTypeString(trackType)); } @Override - public void onAudioSinkUnderrun(int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs) { - printInternalError("audioTrackUnderrun [" + bufferSize + ", " + bufferSizeMs + ", " - + elapsedSinceLastFeedMs + "]", null); + public void onAudioUnderrun( + EventTime eventTime, int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs) { + loge( + eventTime, + "audioTrackUnderrun", + bufferSize + ", " + bufferSizeMs + ", " + elapsedSinceLastFeedMs + "]", + null); } - // VideoRendererEventListener - @Override - public void onVideoEnabled(DecoderCounters counters) { - Log.d(TAG, "videoEnabled [" + getSessionTimeString() + "]"); + public void onDroppedVideoFrames(EventTime eventTime, int count, long elapsedMs) { + logd(eventTime, "droppedFrames", Integer.toString(count)); } @Override - public void onVideoDecoderInitialized(String decoderName, long elapsedRealtimeMs, - long initializationDurationMs) { - Log.d(TAG, "videoDecoderInitialized [" + getSessionTimeString() + ", " + decoderName + "]"); + public void onVideoSizeChanged( + EventTime eventTime, + int width, + int height, + int unappliedRotationDegrees, + float pixelWidthHeightRatio) { + logd(eventTime, "videoSizeChanged", width + ", " + height); } @Override - public void onVideoInputFormatChanged(Format format) { - Log.d(TAG, "videoFormatChanged [" + getSessionTimeString() + ", " + Format.toLogString(format) - + "]"); + public void onRenderedFirstFrame(EventTime eventTime, Surface surface) { + logd(eventTime, "renderedFirstFrame", surface.toString()); } @Override - public void onVideoDisabled(DecoderCounters counters) { - Log.d(TAG, "videoDisabled [" + getSessionTimeString() + "]"); + public void onMediaPeriodCreated(EventTime eventTime) { + logd(eventTime, "mediaPeriodCreated"); } @Override - public void onDroppedFrames(int count, long elapsed) { - Log.d(TAG, "droppedFrames [" + getSessionTimeString() + ", " + count + "]"); + public void onMediaPeriodReleased(EventTime eventTime) { + logd(eventTime, "mediaPeriodReleased"); } @Override - public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, - float pixelWidthHeightRatio) { - Log.d(TAG, "videoSizeChanged [" + width + ", " + height + "]"); + public void onLoadStarted( + EventTime eventTime, LoadEventInfo loadEventInfo, MediaLoadData mediaLoadData) { + // Do nothing. } @Override - public void onRenderedFirstFrame(Surface surface) { - Log.d(TAG, "renderedFirstFrame [" + surface + "]"); + public void onLoadError( + EventTime eventTime, + LoadEventInfo loadEventInfo, + MediaLoadData mediaLoadData, + IOException error, + boolean wasCanceled) { + printInternalError(eventTime, "loadError", error); } - // DefaultDrmSessionManager.EventListener - @Override - public void onDrmSessionManagerError(Exception e) { - printInternalError("drmSessionManagerError", e); + public void onLoadCanceled( + EventTime eventTime, LoadEventInfo loadEventInfo, MediaLoadData mediaLoadData) { + // Do nothing. } @Override - public void onDrmKeysRestored() { - Log.d(TAG, "drmKeysRestored [" + getSessionTimeString() + "]"); + public void onLoadCompleted( + EventTime eventTime, LoadEventInfo loadEventInfo, MediaLoadData mediaLoadData) { + // Do nothing. } @Override - public void onDrmKeysRemoved() { - Log.d(TAG, "drmKeysRemoved [" + getSessionTimeString() + "]"); + public void onReadingStarted(EventTime eventTime) { + logd(eventTime, "mediaPeriodReadingStarted"); } @Override - public void onDrmKeysLoaded() { - Log.d(TAG, "drmKeysLoaded [" + getSessionTimeString() + "]"); + public void onBandwidthEstimate( + EventTime eventTime, int totalLoadTimeMs, long totalBytesLoaded, long bitrateEstimate) { + // Do nothing. } - // MediaSourceEventListener - @Override - public void onLoadStarted( - DataSpec dataSpec, - int dataType, - int trackType, - Format trackFormat, - int trackSelectionReason, - Object trackSelectionData, - long mediaStartTimeMs, - long mediaEndTimeMs, - long elapsedRealtimeMs) { - // Do nothing. + public void onViewportSizeChange(EventTime eventTime, int width, int height) { + logd(eventTime, "viewportSizeChanged", width + ", " + height); } @Override - public void onLoadError(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, - int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, - long mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs, long bytesLoaded, - IOException error, boolean wasCanceled) { - printInternalError("loadError", error); + public void onNetworkTypeChanged(EventTime eventTime, @Nullable NetworkInfo networkInfo) { + logd(eventTime, "networkTypeChanged", networkInfo == null ? "none" : networkInfo.toString()); } @Override - public void onLoadCanceled(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, - int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, - long mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs, long bytesLoaded) { - // Do nothing. + public void onUpstreamDiscarded(EventTime eventTime, MediaLoadData mediaLoadData) { + logd(eventTime, "upstreamDiscarded", Format.toLogString(mediaLoadData.trackFormat)); } @Override - public void onLoadCompleted(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, - int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, - long mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs, long bytesLoaded) { - // Do nothing. + public void onDownstreamFormatChanged(EventTime eventTime, MediaLoadData mediaLoadData) { + logd(eventTime, "downstreamFormatChanged", Format.toLogString(mediaLoadData.trackFormat)); } @Override - public void onUpstreamDiscarded(int trackType, long mediaStartTimeMs, long mediaEndTimeMs) { - // Do nothing. + public void onDrmSessionManagerError(EventTime eventTime, Exception e) { + printInternalError(eventTime, "drmSessionManagerError", e); } @Override - public void onDownstreamFormatChanged(int trackType, Format trackFormat, int trackSelectionReason, - Object trackSelectionData, long mediaTimeMs) { - // Do nothing. + public void onDrmKeysRestored(EventTime eventTime) { + logd(eventTime, "drmKeysRestored"); } - // AdsMediaSource.EventListener - @Override - public void onAdLoadError(IOException error) { - printInternalError("adLoadError", error); + public void onDrmKeysRemoved(EventTime eventTime) { + logd(eventTime, "drmKeysRemoved"); } @Override - public void onInternalAdLoadError(RuntimeException error) { - printInternalError("internalAdLoadError", error); + public void onDrmKeysLoaded(EventTime eventTime) { + logd(eventTime, "drmKeysLoaded"); } - @Override - public void onAdClicked() { - // Do nothing. + /** + * Logs a debug message. + * + * @param msg The message to log. + */ + protected void logd(String msg) { + Log.d(TAG, msg); } - @Override - public void onAdTapped() { - // Do nothing. + /** + * Logs an error message and exception. + * + * @param msg The message to log. + * @param tr The exception to log. + */ + protected void loge(String msg, Throwable tr) { + Log.e(TAG, msg, tr); } // Internal methods - private void printInternalError(String type, Exception e) { - Log.e(TAG, "internalError [" + getSessionTimeString() + ", " + type + "]", e); + private void logd(EventTime eventTime, String eventName) { + logd(getEventString(eventTime, eventName)); + } + + private void logd(EventTime eventTime, String eventName, String eventDescription) { + logd(getEventString(eventTime, eventName, eventDescription)); + } + + private void loge(EventTime eventTime, String eventName, Throwable throwable) { + loge(getEventString(eventTime, eventName), throwable); + } + + private void loge( + EventTime eventTime, String eventName, String eventDescription, Throwable throwable) { + loge(getEventString(eventTime, eventName, eventDescription), throwable); + } + + private void printInternalError(EventTime eventTime, String type, Exception e) { + loge(eventTime, "internalError", type, e); } private void printMetadata(Metadata metadata, String prefix) { for (int i = 0; i < metadata.length(); i++) { - Metadata.Entry entry = metadata.get(i); - if (entry instanceof TextInformationFrame) { - TextInformationFrame textInformationFrame = (TextInformationFrame) entry; - Log.d(TAG, prefix + String.format("%s: value=%s", textInformationFrame.id, - textInformationFrame.value)); - } else if (entry instanceof UrlLinkFrame) { - UrlLinkFrame urlLinkFrame = (UrlLinkFrame) entry; - Log.d(TAG, prefix + String.format("%s: url=%s", urlLinkFrame.id, urlLinkFrame.url)); - } else if (entry instanceof PrivFrame) { - PrivFrame privFrame = (PrivFrame) entry; - Log.d(TAG, prefix + String.format("%s: owner=%s", privFrame.id, privFrame.owner)); - } else if (entry instanceof GeobFrame) { - GeobFrame geobFrame = (GeobFrame) entry; - Log.d(TAG, prefix + String.format("%s: mimeType=%s, filename=%s, description=%s", - geobFrame.id, geobFrame.mimeType, geobFrame.filename, geobFrame.description)); - } else if (entry instanceof ApicFrame) { - ApicFrame apicFrame = (ApicFrame) entry; - Log.d(TAG, prefix + String.format("%s: mimeType=%s, description=%s", - apicFrame.id, apicFrame.mimeType, apicFrame.description)); - } else if (entry instanceof CommentFrame) { - CommentFrame commentFrame = (CommentFrame) entry; - Log.d(TAG, prefix + String.format("%s: language=%s, description=%s", commentFrame.id, - commentFrame.language, commentFrame.description)); - } else if (entry instanceof Id3Frame) { - Id3Frame id3Frame = (Id3Frame) entry; - Log.d(TAG, prefix + String.format("%s", id3Frame.id)); - } else if (entry instanceof EventMessage) { - EventMessage eventMessage = (EventMessage) entry; - Log.d(TAG, prefix + String.format("EMSG: scheme=%s, id=%d, value=%s", - eventMessage.schemeIdUri, eventMessage.id, eventMessage.value)); - } else if (entry instanceof SpliceCommand) { - String description = - String.format("SCTE-35 splice command: type=%s.", entry.getClass().getSimpleName()); - Log.d(TAG, prefix + description); - } + logd(prefix + metadata.get(i)); } } - private String getSessionTimeString() { - return getTimeString(SystemClock.elapsedRealtime() - startTimeMs); + private String getEventString(EventTime eventTime, String eventName) { + return eventName + " [" + getEventTimeString(eventTime) + "]"; + } + + private String getEventString(EventTime eventTime, String eventName, String eventDescription) { + return eventName + " [" + getEventTimeString(eventTime) + ", " + eventDescription + "]"; + } + + private String getEventTimeString(EventTime eventTime) { + String windowPeriodString = "window=" + eventTime.windowIndex; + if (eventTime.mediaPeriodId != null) { + windowPeriodString += ", period=" + eventTime.mediaPeriodId.periodIndex; + if (eventTime.mediaPeriodId.isAd()) { + windowPeriodString += ", adGroup=" + eventTime.mediaPeriodId.adGroupIndex; + windowPeriodString += ", ad=" + eventTime.mediaPeriodId.adIndexInAdGroup; + } + } + return getTimeString(eventTime.realtimeMs - startTimeMs) + + ", " + + getTimeString(eventTime.currentPlaybackPositionMs) + + ", " + + windowPeriodString; } private static String getTimeString(long timeMs) { @@ -454,13 +485,13 @@ private static String getTimeString(long timeMs) { private static String getStateString(int state) { switch (state) { case Player.STATE_BUFFERING: - return "B"; + return "BUFFERING"; case Player.STATE_ENDED: - return "E"; + return "ENDED"; case Player.STATE_IDLE: - return "I"; + return "IDLE"; case Player.STATE_READY: - return "R"; + return "READY"; default: return "?"; } @@ -555,4 +586,22 @@ private static String getTimelineChangeReasonString(@Player.TimelineChangeReason } } + private static String getTrackTypeString(int trackType) { + switch (trackType) { + case C.TRACK_TYPE_AUDIO: + return "audio"; + case C.TRACK_TYPE_DEFAULT: + return "default"; + case C.TRACK_TYPE_METADATA: + return "metadata"; + case C.TRACK_TYPE_NONE: + return "none"; + case C.TRACK_TYPE_TEXT: + return "text"; + case C.TRACK_TYPE_VIDEO: + return "video"; + default: + return trackType >= C.TRACK_TYPE_CUSTOM_BASE ? "custom (" + trackType + ")" : "?"; + } + } } diff --git a/playermanager/src/main/java/com/github/aakira/playermanager/LimitBandwidthMeter.java b/playermanager/src/main/java/com/github/aakira/playermanager/LimitBandwidthMeter.java index da483fe..f27acc8 100644 --- a/playermanager/src/main/java/com/github/aakira/playermanager/LimitBandwidthMeter.java +++ b/playermanager/src/main/java/com/github/aakira/playermanager/LimitBandwidthMeter.java @@ -16,12 +16,13 @@ package com.github.aakira.playermanager; import android.os.Handler; -import android.os.SystemClock; +import android.support.annotation.Nullable; import com.google.android.exoplayer2.upstream.BandwidthMeter; import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.upstream.TransferListener; import com.google.android.exoplayer2.util.Assertions; +import com.google.android.exoplayer2.util.Clock; import com.google.android.exoplayer2.util.SlidingPercentile; /** @@ -30,17 +31,98 @@ */ public final class LimitBandwidthMeter implements BandwidthMeter, TransferListener { - /** - * The default maximum weight for the sliding window. - */ - public static final int DEFAULT_MAX_WEIGHT = 2000; + /** Default initial bitrate estimate in bits per second. */ + public static final long DEFAULT_INITIAL_BITRATE_ESTIMATE = 1_000_000; + + /** Default maximum weight for the sliding window. */ + public static final int DEFAULT_SLIDING_WINDOW_MAX_WEIGHT = 2000; + + /** Builder for a bandwidth meter. */ + public static final class Builder { + + private @Nullable Handler eventHandler; + private @Nullable EventListener eventListener; + private long initialBitrateEstimate; + private int slidingWindowMaxWeight; + private Clock clock; + + /** Creates a builder with default parameters and without listener. */ + public Builder() { + initialBitrateEstimate = DEFAULT_INITIAL_BITRATE_ESTIMATE; + slidingWindowMaxWeight = DEFAULT_SLIDING_WINDOW_MAX_WEIGHT; + clock = Clock.DEFAULT; + } + + /** + * Sets an event listener for new bandwidth estimates. + * + * @param eventHandler A handler for events. + * @param eventListener A listener of events. + * @return This builder. + * @throws IllegalArgumentException If the event handler or listener are null. + */ + public Builder setEventListener(Handler eventHandler, EventListener eventListener) { + Assertions.checkArgument(eventHandler != null && eventListener != null); + this.eventHandler = eventHandler; + this.eventListener = eventListener; + return this; + } + + /** + * Sets the maximum weight for the sliding window. + * + * @param slidingWindowMaxWeight The maximum weight for the sliding window. + * @return This builder. + */ + public Builder setSlidingWindowMaxWeight(int slidingWindowMaxWeight) { + this.slidingWindowMaxWeight = slidingWindowMaxWeight; + return this; + } + + /** + * Sets the initial bitrate estimate in bits per second that should be assumed when a bandwidth + * estimate is unavailable. + * + * @param initialBitrateEstimate The initial bitrate estimate in bits per second. + * @return This builder. + */ + public Builder setInitialBitrateEstimate(long initialBitrateEstimate) { + this.initialBitrateEstimate = initialBitrateEstimate; + return this; + } + + /** + * Sets the clock used to estimate bandwidth from data transfers. Should only be set for testing + * purposes. + * + * @param clock The clock used to estimate bandwidth from data transfers. + * @return This builder. + */ + public Builder setClock(Clock clock) { + this.clock = clock; + return this; + } + + /** + * Builds the bandwidth meter. + * + * @return A bandwidth meter with the configured properties. + */ + public LimitBandwidthMeter build() { + return new LimitBandwidthMeter( + eventHandler, eventListener, initialBitrateEstimate, slidingWindowMaxWeight, clock); + } + } + + private long limitBitrate = Long.MAX_VALUE; private static final int ELAPSED_MILLIS_FOR_ESTIMATE = 2000; private static final int BYTES_TRANSFERRED_FOR_ESTIMATE = 512 * 1024; - private final Handler eventHandler; - private final EventListener eventListener; + private final @Nullable Handler eventHandler; + private final @Nullable EventListener eventListener; private final SlidingPercentile slidingPercentile; + private final Clock clock; private int streamCount; private long sampleStartTimeMs; @@ -50,21 +132,44 @@ public final class LimitBandwidthMeter implements BandwidthMeter, TransferListen private long totalBytesTransferred; private long bitrateEstimate; - private long limitBitrate = Long.MAX_VALUE; - + /** Creates a bandwidth meter with default parameters. */ public LimitBandwidthMeter() { - this(null, null); + this( + /* eventHandler= */ null, + /* eventListener= */ null, + DEFAULT_INITIAL_BITRATE_ESTIMATE, + DEFAULT_SLIDING_WINDOW_MAX_WEIGHT, + Clock.DEFAULT); } + /** @deprecated Use {@link Builder} instead. */ + @Deprecated public LimitBandwidthMeter(Handler eventHandler, EventListener eventListener) { - this(eventHandler, eventListener, DEFAULT_MAX_WEIGHT); + this( + eventHandler, + eventListener, + DEFAULT_INITIAL_BITRATE_ESTIMATE, + DEFAULT_SLIDING_WINDOW_MAX_WEIGHT, + Clock.DEFAULT); } + /** @deprecated Use {@link Builder} instead. */ + @Deprecated public LimitBandwidthMeter(Handler eventHandler, EventListener eventListener, int maxWeight) { + this(eventHandler, eventListener, DEFAULT_INITIAL_BITRATE_ESTIMATE, maxWeight, Clock.DEFAULT); + } + + private LimitBandwidthMeter( + @Nullable Handler eventHandler, + @Nullable EventListener eventListener, + long initialBitrateEstimate, + int maxWeight, + Clock clock) { this.eventHandler = eventHandler; this.eventListener = eventListener; this.slidingPercentile = new SlidingPercentile(maxWeight); - bitrateEstimate = NO_ESTIMATE; + this.clock = clock; + bitrateEstimate = initialBitrateEstimate; } @Override @@ -75,7 +180,7 @@ public synchronized long getBitrateEstimate() { @Override public synchronized void onTransferStart(Object source, DataSpec dataSpec) { if (streamCount == 0) { - sampleStartTimeMs = SystemClock.elapsedRealtime(); + sampleStartTimeMs = clock.elapsedRealtime(); } streamCount++; } @@ -88,7 +193,7 @@ public synchronized void onBytesTransferred(Object source, int bytes) { @Override public synchronized void onTransferEnd(Object source) { Assertions.checkState(streamCount > 0); - long nowMs = SystemClock.elapsedRealtime(); + long nowMs = clock.elapsedRealtime(); int sampleElapsedTimeMs = (int) (nowMs - sampleStartTimeMs); totalElapsedTimeMs += sampleElapsedTimeMs; totalBytesTransferred += sampleBytesTransferred; @@ -97,9 +202,7 @@ public synchronized void onTransferEnd(Object source) { slidingPercentile.addSample((int) Math.sqrt(sampleBytesTransferred), bitsPerSecond); if (totalElapsedTimeMs >= ELAPSED_MILLIS_FOR_ESTIMATE || totalBytesTransferred >= BYTES_TRANSFERRED_FOR_ESTIMATE) { - float bitrateEstimateFloat = slidingPercentile.getPercentile(0.5f); - bitrateEstimate = Float.isNaN(bitrateEstimateFloat) ? NO_ESTIMATE - : (long) bitrateEstimateFloat; + bitrateEstimate = (long) slidingPercentile.getPercentile(0.5f); } } notifyBandwidthSample(sampleElapsedTimeMs, sampleBytesTransferred, bitrateEstimate); @@ -111,7 +214,7 @@ public synchronized void onTransferEnd(Object source) { private void notifyBandwidthSample(final int elapsedMs, final long bytes, final long bitrate) { if (eventHandler != null && eventListener != null) { - eventHandler.post(new Runnable() { + eventHandler.post(new Runnable() { @Override public void run() { eventListener.onBandwidthSample(elapsedMs, bytes, bitrate); @@ -123,4 +226,4 @@ public void run() { public void setLimitBitrate(Long bitrate) { this.limitBitrate = bitrate; } -} \ No newline at end of file +} diff --git a/playermanager/src/main/kotlin/com/github/aakira/playermanager/CallBackTypeAlias.kt b/playermanager/src/main/kotlin/com/github/aakira/playermanager/CallBackTypeAlias.kt index 42205b5..12b170d 100644 --- a/playermanager/src/main/kotlin/com/github/aakira/playermanager/CallBackTypeAlias.kt +++ b/playermanager/src/main/kotlin/com/github/aakira/playermanager/CallBackTypeAlias.kt @@ -1,12 +1,11 @@ package com.github.aakira.playermanager -import com.google.android.exoplayer2.Format import com.google.android.exoplayer2.PlaybackParameters +import com.google.android.exoplayer2.analytics.AnalyticsListener import com.google.android.exoplayer2.audio.AudioCapabilities import com.google.android.exoplayer2.metadata.Metadata -import com.google.android.exoplayer2.metadata.MetadataRenderer +import com.google.android.exoplayer2.source.MediaSourceEventListener import com.google.android.exoplayer2.trackselection.TrackSelectionArray -import com.google.android.exoplayer2.upstream.DataSpec import java.io.IOException /** @@ -35,15 +34,17 @@ typealias PlaybackParametersChangedListener = (playbackParameters: PlaybackParam typealias RepeatModeChangedListener = (repeatMode: Int) -> Unit /** - * See [MetadataRenderer.Output] + * See [com.google.android.exoplayer2.metadata.MetadataOutput] */ -typealias MetadataListener = (metadata: Metadata) -> Unit +typealias MetadataListener = (eventTime: AnalyticsListener.EventTime?, metadata: Metadata?) -> Unit /** * See [com.google.android.exoplayer2.video.VideoRendererEventListener.onVideoSizeChanged] */ -typealias VideoSizeChangedListener = (width: Int, height: Int, unappliedRotationDegrees: Int, +typealias VideoSizeChangedListener = (eventTime: AnalyticsListener.EventTime?, width: Int, + height: Int, unappliedRotationDegrees: Int, pixelWidthHeightRatio: Float) -> Unit + /** * See [com.google.android.exoplayer2.audio.AudioCapabilitiesReceiver.Listener.onAudioCapabilitiesChanged] */ @@ -52,11 +53,9 @@ typealias AudioCapabilitiesChangedListener = (AudioCapabilities) -> Unit /** * See [com.google.android.exoplayer2.source.MediaSourceEventListener.onLoadError] */ -typealias MediaSourceLoadErrorListener = (dataSpec: DataSpec?, dataType: Int, trackType: Int, - trackFormat: Format?, trackSelectionReason: Int, - trackSelectionData: Any?, mediaStartTimeMs: Long, - mediaEndTimeMs: Long, elapsedRealtimeMs: Long, - loadDurationMs: Long, bytesLoaded: Long, +typealias MediaSourceLoadErrorListener = (eventTime: AnalyticsListener.EventTime?, + loadEventInfo: MediaSourceEventListener.LoadEventInfo?, + mediaLoadData: MediaSourceEventListener.MediaLoadData?, error: IOException?, wasCanceled: Boolean) -> Unit /** @@ -68,4 +67,4 @@ typealias ExtractorMediaSourceLoadErrorListener = (error: IOException) -> Unit * See [com.google.android.exoplayer2.video.VideoRendererEventListener.onVideoEnabled] * See [com.google.android.exoplayer2.video.VideoRendererEventListener.onVideoDisabled] */ -typealias VideoRenderedListener = (enable: Boolean) -> Unit \ No newline at end of file +typealias VideoRenderedListener = (enable: Boolean) -> Unit diff --git a/playermanager/src/main/kotlin/com/github/aakira/playermanager/EventProxy.kt b/playermanager/src/main/kotlin/com/github/aakira/playermanager/EventProxy.kt index 6bcf42e..dbd9c47 100644 --- a/playermanager/src/main/kotlin/com/github/aakira/playermanager/EventProxy.kt +++ b/playermanager/src/main/kotlin/com/github/aakira/playermanager/EventProxy.kt @@ -1,30 +1,23 @@ package com.github.aakira.playermanager +import android.net.NetworkInfo import android.view.Surface +import com.google.android.exoplayer2.C import com.google.android.exoplayer2.ExoPlaybackException import com.google.android.exoplayer2.Format import com.google.android.exoplayer2.PlaybackParameters import com.google.android.exoplayer2.Player import com.google.android.exoplayer2.Timeline -import com.google.android.exoplayer2.audio.AudioCapabilities -import com.google.android.exoplayer2.audio.AudioCapabilitiesReceiver +import com.google.android.exoplayer2.analytics.AnalyticsListener import com.google.android.exoplayer2.decoder.DecoderCounters import com.google.android.exoplayer2.metadata.Metadata -import com.google.android.exoplayer2.metadata.MetadataOutput import com.google.android.exoplayer2.source.MediaSourceEventListener import com.google.android.exoplayer2.source.TrackGroupArray import com.google.android.exoplayer2.trackselection.TrackSelectionArray -import com.google.android.exoplayer2.upstream.DataSpec -import com.google.android.exoplayer2.video.VideoListener -import com.google.android.exoplayer2.video.VideoRendererEventListener import java.io.IOException +import java.lang.Exception -class EventProxy : Player.EventListener, - MetadataOutput, - VideoListener, - AudioCapabilitiesReceiver.Listener, - VideoRendererEventListener, - MediaSourceEventListener { +class EventProxy : Player.DefaultEventListener(), AnalyticsListener { var onTracksChangedListener: TracksChangedListener? = null var onPlayerStateChangedListener: PlayerStateChangedListener? = null @@ -33,7 +26,6 @@ class EventProxy : Player.EventListener, var onRepeatModeChangedListener: RepeatModeChangedListener? = null var onMetadataListener: MetadataListener? = null var onVideoSizeChangedListener: VideoSizeChangedListener? = null - var onAudioCapabilitiesChangedListener: AudioCapabilitiesChangedListener? = null var onMediaSourceLoadErrorListener: MediaSourceLoadErrorListener? = null var onVideoRenderedListener: VideoRenderedListener? = null @@ -43,7 +35,8 @@ class EventProxy : Player.EventListener, } // Player.EventListener - override fun onTracksChanged(trackGroups: TrackGroupArray, trackSelections: TrackSelectionArray) { + override fun onTracksChanged(trackGroups: TrackGroupArray, + trackSelections: TrackSelectionArray) { this.onTracksChangedListener?.invoke(trackSelections) } @@ -87,97 +80,285 @@ class EventProxy : Player.EventListener, // Do nothing. } - // MetadataRenderer.Output - override fun onMetadata(metadata: Metadata) { - onMetadataListener?.invoke(metadata) + /** + * AnalyticsListener + * repeated [onTimelineChanged] + */ + override fun onTimelineChanged(eventTime: AnalyticsListener.EventTime?, reason: Int) { + // Repeated the Player.EventListener } - // SimpleExoPlayer.VideoListener - override fun onVideoSizeChanged(width: Int, height: Int, unappliedRotationDegrees: Int, - pixelWidthHeightRatio: Float) { - onVideoSizeChangedListener?.invoke(width, height, unappliedRotationDegrees, pixelWidthHeightRatio) + /** + * AnalyticsListener + * repeated [onTracksChanged] + */ + override fun onTracksChanged(eventTime: AnalyticsListener.EventTime?, + trackGroups: TrackGroupArray?, + trackSelections: TrackSelectionArray?) { + // Repeated the Player.EventListener } - // SimpleExoPlayer.VideoListener - override fun onRenderedFirstFrame() { - // Do nothing. + /** + * AnalyticsListener + * repeated [onPlayerStateChanged] + */ + override fun onLoadingChanged(eventTime: AnalyticsListener.EventTime?, isLoading: Boolean) { + // Repeated the Player.EventListener + } + + /** + * AnalyticsListener + * repeated [onPlayerStateChanged] + */ + override fun onPlayerStateChanged(eventTime: AnalyticsListener.EventTime?, + playWhenReady: Boolean, playbackState: Int) { + // Repeated the Player.EventListener + } + + /** + * AnalyticsListener + * repeated [onRepeatModeChanged] + */ + override fun onRepeatModeChanged(eventTime: AnalyticsListener.EventTime?, repeatMode: Int) { + // Repeated the Player.EventListener + } + + /** + * AnalyticsListener + * repeated [onPlayerError] + */ + override fun onPlayerError(eventTime: AnalyticsListener.EventTime?, + error: ExoPlaybackException?) { + // Repeated the Player.EventListener + } + + /** + * AnalyticsListener + * repeated [onPositionDiscontinuity] + */ + override fun onPositionDiscontinuity(eventTime: AnalyticsListener.EventTime?, reason: Int) { + // Repeated the Player.EventListener + } + + /** + * AnalyticsListener + * repeated [onPlaybackParametersChanged] + */ + override fun onPlaybackParametersChanged(eventTime: AnalyticsListener.EventTime?, + playbackParameters: PlaybackParameters?) { + // Repeated the Player.EventListener } - // AudioCapabilitiesReceiver.Listener - override fun onAudioCapabilitiesChanged(audioCapabilities: AudioCapabilities) { - onAudioCapabilitiesChangedListener?.invoke(audioCapabilities) + /** + * AnalyticsListener + * repeated [onSeekProcessed] + */ + override fun onSeekProcessed(eventTime: AnalyticsListener.EventTime?) { + // Repeated the Player.EventListener } - // MediaSourceEventListener - override fun onLoadStarted(dataSpec: DataSpec?, dataType: Int, trackType: Int, trackFormat: Format?, - trackSelectionReason: Int, trackSelectionData: Any?, mediaStartTimeMs: Long, - mediaEndTimeMs: Long, elapsedRealtimeMs: Long) { + /** + * AnalyticsListener + * [com.google.android.exoplayer2.metadata.MetadataOutput.onMetadata] + **/ + override fun onMetadata(eventTime: AnalyticsListener.EventTime?, metadata: Metadata?) { + onMetadataListener?.invoke(eventTime, metadata) + } + + // AnalyticsListener + /** + * AnalyticsListener + * [com.google.android.exoplayer2.video.VideoListener.onVideoSizeChanged] + * [com.google.android.exoplayer2.video.VideoRendererEventListener.onVideoSizeChanged] + **/ + override fun onVideoSizeChanged(eventTime: AnalyticsListener.EventTime?, width: Int, + height: Int, unappliedRotationDegrees: Int, + pixelWidthHeightRatio: Float) { + onVideoSizeChangedListener?.invoke(eventTime, width, height, unappliedRotationDegrees, + pixelWidthHeightRatio) + } + + /** + * AnalyticsListener + * [com.google.android.exoplayer2.video.VideoRendererEventListener.onRenderedFirstFrame] + **/ + override fun onRenderedFirstFrame(eventTime: AnalyticsListener.EventTime?, surface: Surface?) { + // Do nothing. + } + + /** + * AnalyticsListener + * [com.google.android.exoplayer2.source.MediaSourceEventListener.onLoadStarted] + **/ + override fun onLoadStarted(eventTime: AnalyticsListener.EventTime?, + loadEventInfo: MediaSourceEventListener.LoadEventInfo?, + mediaLoadData: MediaSourceEventListener.MediaLoadData?) { // Do nothing. } - // MediaSourceEventListener - override fun onDownstreamFormatChanged(trackType: Int, trackFormat: Format?, trackSelectionReason: Int, - trackSelectionData: Any?, mediaTimeMs: Long) { + /** + * AnalyticsListener + * [com.google.android.exoplayer2.source.MediaSourceEventListener.onDownstreamFormatChanged] + **/ + override fun onDownstreamFormatChanged(eventTime: AnalyticsListener.EventTime?, + mediaLoadData: MediaSourceEventListener.MediaLoadData?) { // Do nothing. } - // MediaSourceEventListener - override fun onUpstreamDiscarded(trackType: Int, mediaStartTimeMs: Long, mediaEndTimeMs: Long) { + /** + * AnalyticsListener + * [com.google.android.exoplayer2.source.MediaSourceEventListener.onUpstreamDiscarded] + **/ + override fun onUpstreamDiscarded(eventTime: AnalyticsListener.EventTime?, + mediaLoadData: MediaSourceEventListener.MediaLoadData?) { // Do nothing. } - // MediaSourceEventListener - override fun onLoadCanceled(dataSpec: DataSpec?, dataType: Int, trackType: Int, trackFormat: Format?, - trackSelectionReason: Int, trackSelectionData: Any?, mediaStartTimeMs: Long, - mediaEndTimeMs: Long, elapsedRealtimeMs: Long, loadDurationMs: Long, bytesLoaded: Long) { + /** + * AnalyticsListener + * [com.google.android.exoplayer2.source.MediaSourceEventListener.onLoadCanceled] + **/ + override fun onLoadCanceled(eventTime: AnalyticsListener.EventTime?, + loadEventInfo: MediaSourceEventListener.LoadEventInfo?, + mediaLoadData: MediaSourceEventListener.MediaLoadData?) { // Do nothing. } - // MediaSourceEventListener - override fun onLoadCompleted(dataSpec: DataSpec?, dataType: Int, trackType: Int, trackFormat: Format?, - trackSelectionReason: Int, trackSelectionData: Any?, mediaStartTimeMs: Long, - mediaEndTimeMs: Long, elapsedRealtimeMs: Long, loadDurationMs: Long, bytesLoaded: Long) { + /** + * AnalyticsListener + * [com.google.android.exoplayer2.source.MediaSourceEventListener.onLoadCompleted] + **/ + override fun onLoadCompleted(eventTime: AnalyticsListener.EventTime?, + loadEventInfo: MediaSourceEventListener.LoadEventInfo?, + mediaLoadData: MediaSourceEventListener.MediaLoadData?) { // Do nothing. } - // MediaSourceEventListener - override fun onLoadError(dataSpec: DataSpec?, dataType: Int, trackType: Int, trackFormat: Format?, - trackSelectionReason: Int, trackSelectionData: Any?, mediaStartTimeMs: Long, - mediaEndTimeMs: Long, elapsedRealtimeMs: Long, loadDurationMs: Long, - bytesLoaded: Long, error: IOException?, wasCanceled: Boolean) { - onMediaSourceLoadErrorListener?.invoke(dataSpec, dataType, trackType, trackFormat, - trackSelectionReason, trackSelectionData, mediaStartTimeMs, - mediaEndTimeMs, elapsedRealtimeMs, loadDurationMs, - bytesLoaded, error, wasCanceled) + /** + * AnalyticsListener + * [com.google.android.exoplayer2.source.MediaSourceEventListener.onLoadError] + **/ + override fun onLoadError(eventTime: AnalyticsListener.EventTime?, + loadEventInfo: MediaSourceEventListener.LoadEventInfo?, + mediaLoadData: MediaSourceEventListener.MediaLoadData?, + error: IOException?, wasCanceled: Boolean) { + onMediaSourceLoadErrorListener?.invoke(eventTime, loadEventInfo, mediaLoadData, error, + wasCanceled) } - // VideoRendererEventListener - override fun onRenderedFirstFrame(surface: Surface?) { + /** + * AnalyticsListener + * [com.google.android.exoplayer2.source.MediaSourceEventListener.onMediaPeriodCreated] + **/ + override fun onMediaPeriodCreated(eventTime: AnalyticsListener.EventTime?) { // Do nothing. } - // VideoRendererEventListener - override fun onDroppedFrames(count: Int, elapsedMs: Long) { + /** + * AnalyticsListener + * [com.google.android.exoplayer2.source.MediaSourceEventListener.onMediaPeriodReleased] + **/ + override fun onMediaPeriodReleased(eventTime: AnalyticsListener.EventTime?) { // Do nothing. } - // VideoRendererEventListener - override fun onVideoDecoderInitialized(decoderName: String?, initializedTimestampMs: Long, initializationDurationMs: Long) { + /** + * AnalyticsListener + * [com.google.android.exoplayer2.source.MediaSourceEventListener.onReadingStarted] + **/ + override fun onReadingStarted(eventTime: AnalyticsListener.EventTime?) { // Do nothing. } - // VideoRendererEventListener - override fun onVideoEnabled(counters: DecoderCounters?) { - onVideoRenderedListener?.invoke(true) + // AnalyticsListener + override fun onSeekStarted(eventTime: AnalyticsListener.EventTime?) { } - // VideoRendererEventListener - override fun onVideoDisabled(counters: DecoderCounters?) { - onVideoRenderedListener?.invoke(false) + // AnalyticsListener + override fun onDrmKeysLoaded(eventTime: AnalyticsListener.EventTime?) { } - // VideoRendererEventListener - override fun onVideoInputFormatChanged(format: Format?) { - // Do nothing. + // AnalyticsListener + override fun onBandwidthEstimate(eventTime: AnalyticsListener.EventTime?, totalLoadTimeMs: Int, + totalBytesLoaded: Long, bitrateEstimate: Long) { + } + + // AnalyticsListener + override fun onNetworkTypeChanged(eventTime: AnalyticsListener.EventTime?, + networkInfo: NetworkInfo?) { + } + + // AnalyticsListener + override fun onViewportSizeChange(eventTime: AnalyticsListener.EventTime?, width: Int, + height: Int) { + } + + // AnalyticsListener + override fun onDrmKeysRestored(eventTime: AnalyticsListener.EventTime?) { + } + + /** + * AnalyticsListener + * [com.google.android.exoplayer2.video.VideoRendererEventListener.onVideoDisabled] + **/ + override fun onDecoderDisabled(eventTime: AnalyticsListener.EventTime?, trackType: Int, + decoderCounters: DecoderCounters?) { + if (trackType == C.TRACK_TYPE_VIDEO) onVideoRenderedListener?.invoke(false) + } + + // AnalyticsListener + override fun onShuffleModeChanged(eventTime: AnalyticsListener.EventTime?, + shuffleModeEnabled: Boolean) { + } + + /** + * AnalyticsListener + * [com.google.android.exoplayer2.video.VideoRendererEventListener.onVideoInputFormatChanged] + **/ + override fun onDecoderInputFormatChanged(eventTime: AnalyticsListener.EventTime?, + trackType: Int, format: Format?) { + } + + // AnalyticsListener + override fun onAudioSessionId(eventTime: AnalyticsListener.EventTime?, audioSessionId: Int) { + } + + // AnalyticsListener + override fun onDrmSessionManagerError(eventTime: AnalyticsListener.EventTime?, + error: Exception?) { + } + + /** + * AnalyticsListener + * [com.google.android.exoplayer2.video.VideoRendererEventListener.onVideoDecoderInitialized] + **/ + override fun onDecoderInitialized(eventTime: AnalyticsListener.EventTime?, trackType: Int, + decoderName: String?, initializationDurationMs: Long) { + } + + /** + * AnalyticsListener + * [com.google.android.exoplayer2.video.VideoRendererEventListener.onDroppedFrames] + **/ + override fun onDroppedVideoFrames(eventTime: AnalyticsListener.EventTime?, droppedFrames: Int, + elapsedMs: Long) { + } + + /** + * AnalyticsListener + * [com.google.android.exoplayer2.video.VideoRendererEventListener.onVideoEnabled] + **/ + override fun onDecoderEnabled(eventTime: AnalyticsListener.EventTime?, trackType: Int, + decoderCounters: DecoderCounters?) { + if (trackType == C.TRACK_TYPE_VIDEO) onVideoRenderedListener?.invoke(true) + } + + // AnalyticsListener + override fun onAudioUnderrun(eventTime: AnalyticsListener.EventTime?, bufferSize: Int, + bufferSizeMs: Long, elapsedSinceLastFeedMs: Long) { + } + + // AnalyticsListener + override fun onDrmKeysRemoved(eventTime: AnalyticsListener.EventTime?) { } -} \ No newline at end of file +} diff --git a/playermanager/src/main/kotlin/com/github/aakira/playermanager/ExoPlayerManager.kt b/playermanager/src/main/kotlin/com/github/aakira/playermanager/ExoPlayerManager.kt index 747d5fb..ffdbf89 100644 --- a/playermanager/src/main/kotlin/com/github/aakira/playermanager/ExoPlayerManager.kt +++ b/playermanager/src/main/kotlin/com/github/aakira/playermanager/ExoPlayerManager.kt @@ -1,30 +1,31 @@ package com.github.aakira.playermanager import android.content.Context -import android.os.Handler import com.google.android.exoplayer2.BuildConfig import com.google.android.exoplayer2.ExoPlayerFactory -import com.google.android.exoplayer2.Format import com.google.android.exoplayer2.PlaybackParameters import com.google.android.exoplayer2.Player import com.google.android.exoplayer2.SimpleExoPlayer +import com.google.android.exoplayer2.analytics.AnalyticsCollector +import com.google.android.exoplayer2.analytics.AnalyticsListener import com.google.android.exoplayer2.ext.okhttp.OkHttpDataSourceFactory import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory import com.google.android.exoplayer2.source.ExtractorMediaSource import com.google.android.exoplayer2.source.MediaSource +import com.google.android.exoplayer2.source.MediaSourceEventListener import com.google.android.exoplayer2.source.hls.HlsMediaSource import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection import com.google.android.exoplayer2.trackselection.DefaultTrackSelector import com.google.android.exoplayer2.ui.PlayerView import com.google.android.exoplayer2.upstream.DataSource -import com.google.android.exoplayer2.upstream.DataSpec import com.google.android.exoplayer2.upstream.DefaultHttpDataSource import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory import com.google.android.exoplayer2.upstream.TransferListener import okhttp3.OkHttpClient import java.io.IOException -class ExoPlayerManager(private val context: Context, private val debugLogger: Boolean = BuildConfig.DEBUG) { +class ExoPlayerManager(private val context: Context, + private val debugLogger: Boolean = BuildConfig.DEBUG) { var player: SimpleExoPlayer? = null private set @@ -40,7 +41,6 @@ class ExoPlayerManager(private val context: Context, private val debugLogger: Bo private val bandwidthMeter = LimitBandwidthMeter() private var eventLogger: EventLogger? = null private var eventProxy = EventProxy() - private val mainHandler = Handler() private var mediaSource: MediaSource? = null private var playerNeedsPrepare = false private var playerView: PlayerView? = null @@ -58,24 +58,16 @@ class ExoPlayerManager(private val context: Context, private val debugLogger: Bo private val onVideoRenderedListeners = ArrayList() init { - eventProxy.onMediaSourceLoadErrorListener = { dataSpec: DataSpec?, dataType: Int, trackType: Int, trackFormat: Format?, - trackSelectionReason: Int, trackSelectionData: Any?, - mediaStartTimeMs: Long, mediaEndTimeMs: Long, elapsedRealtimeMs: Long, - loadDurationMs: Long, bytesLoaded: Long, error: IOException?, wasCanceled: Boolean -> - + eventProxy.onMediaSourceLoadErrorListener = { eventTime: AnalyticsListener.EventTime?, + loadEventInfo: MediaSourceEventListener.LoadEventInfo?, + mediaLoadData: MediaSourceEventListener.MediaLoadData?, + error: IOException?, wasCanceled: Boolean -> onMediaSourceLoadErrorListeners.forEach { - it.invoke(dataSpec, dataType, trackType, trackFormat, trackSelectionReason, - trackSelectionData, mediaStartTimeMs, mediaEndTimeMs, elapsedRealtimeMs, - loadDurationMs, bytesLoaded, error, wasCanceled) - } - } - eventProxy.onAudioCapabilitiesChangedListener = { - onAudioCapabilitiesChangedListeners.forEach { listener -> - listener.invoke(it) + it.invoke(eventTime, loadEventInfo, mediaLoadData, error, wasCanceled) } } - eventProxy.onMetadataListener = { - onMetadataListeners.forEach { listener -> listener.invoke(it) } + eventProxy.onMetadataListener = {eventTime, metadata -> + onMetadataListeners.forEach { listener -> listener.invoke(eventTime, metadata) } } eventProxy.onPlaybackParametersChangedListener = { onPlaybackParametersListeners.forEach { listener -> listener.invoke(it) } @@ -93,9 +85,9 @@ class ExoPlayerManager(private val context: Context, private val debugLogger: Bo eventProxy.onTracksChangedListener = { onTracksChangedListeners.forEach { listener -> listener.invoke(it) } } - eventProxy.onVideoSizeChangedListener = { width, height, unappliedRotationDegrees, pixelWidthHeightRatio -> + eventProxy.onVideoSizeChangedListener = { eventTime ,width, height, unappliedRotationDegrees, pixelWidthHeightRatio -> onVideoSizeChangedListeners.forEach { - it.invoke(width, height, unappliedRotationDegrees, pixelWidthHeightRatio) + it.invoke(eventTime, width, height, unappliedRotationDegrees, pixelWidthHeightRatio) } } eventProxy.onVideoRenderedListener = { @@ -135,7 +127,7 @@ class ExoPlayerManager(private val context: Context, private val debugLogger: Bo dataSourceCreator.dataSourceCreatorInterface.create(context, bandwidthMeter, dataSource) } ?: dataSource ) - .createMediaSource(dataSourceCreator.uri, mainHandler, eventProxy) + .createMediaSource(dataSourceCreator.uri) playerNeedsPrepare = true } @@ -164,7 +156,7 @@ class ExoPlayerManager(private val context: Context, private val debugLogger: Bo } ?: dataSource ) .setExtractorsFactory(DefaultExtractorsFactory()) - .createMediaSource(dataSourceCreator.uri, mainHandler, eventProxy) + .createMediaSource(dataSourceCreator.uri) playerNeedsPrepare = true } @@ -371,14 +363,16 @@ class ExoPlayerManager(private val context: Context, private val debugLogger: Bo * @see [addOnMediaSourceLoadErrorListener] */ @Deprecated("Merge MediaSourceLoadErrorListener") - fun addOnExtractorMediaSourceLoadErrorListener(listener: ExtractorMediaSourceLoadErrorListener) { + fun addOnExtractorMediaSourceLoadErrorListener( + listener: ExtractorMediaSourceLoadErrorListener) { } /** * @see [removeMediaSourceErrorListener] */ @Deprecated("Merge MediaSourceLoadErrorListener") - fun removeExtractorMediaSourceLoadErrorListener(listener: ExtractorMediaSourceLoadErrorListener) { + fun removeExtractorMediaSourceLoadErrorListener( + listener: ExtractorMediaSourceLoadErrorListener) { } /** @@ -401,36 +395,29 @@ class ExoPlayerManager(private val context: Context, private val debugLogger: Bo } private fun initializePlayer() { + AnalyticsCollector.Factory() player = ExoPlayerFactory.newSimpleInstance(context, trackSelector).apply { addListener(eventProxy) - addVideoListener(eventProxy) - addMetadataOutput(eventProxy) - addVideoDebugListener(eventProxy) + addAnalyticsListener(eventProxy) if (debugLogger) { eventLogger = EventLogger(trackSelector).also { - addListener(it) - addAudioDebugListener(it) - addVideoDebugListener(it) - addMetadataOutput(it) + addAnalyticsListener(it) } } } playerNeedsPrepare = true + + player?.analyticsCollector } private fun clearExoPlayerListeners() { player?.run { removeListener(eventProxy) - removeVideoListener(eventProxy) - removeMetadataOutput(eventProxy) - removeVideoDebugListener(eventProxy) + removeAnalyticsListener(eventProxy) eventLogger?.let { - removeListener(it) - removeAudioDebugListener(it) - addVideoDebugListener(it) - addMetadataOutput(it) + removeAnalyticsListener(it) } } } @@ -441,13 +428,15 @@ class ExoPlayerManager(private val context: Context, private val debugLogger: Bo buildOkHttpDataSourceFactory(userAgent, bandwidthMeter, okHttpClient) } ?: buildDefaultHttpDataSourceFactory(userAgent, bandwidthMeter) - private fun buildDefaultHttpDataSourceFactory(userAgent: String, listener: TransferListener, + private fun buildDefaultHttpDataSourceFactory(userAgent: String, + listener: TransferListener, allowCrossProtocolRedirects: Boolean = false) = DefaultHttpDataSourceFactory(userAgent, listener, DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS, DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS, allowCrossProtocolRedirects) - private fun buildOkHttpDataSourceFactory(userAgent: String, listener: TransferListener, + private fun buildOkHttpDataSourceFactory(userAgent: String, + listener: TransferListener, okHttpClient: OkHttpClient) = OkHttpDataSourceFactory(okHttpClient, userAgent, listener) } From 2ec55babb8e2b0b1cb07706e794f833ef9fe1ea1 Mon Sep 17 00:00:00 2001 From: "A.Akira" Date: Thu, 31 May 2018 13:55:29 +0900 Subject: [PATCH 2/3] Bump up the version code and name. --- README.md | 6 +++--- build.gradle | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index c365ead..865c0cc 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ This is written in Kotlin. ## Requirements * Kotlin 1.1.0 or above -* ExoPlayer 2.6 or above +* ExoPlayer 2.8 or above * Android SDK version 4.1 or above (ExoPlayer requirements) ## Usage @@ -145,8 +145,8 @@ buildscript { } dependencies { - implementation 'com.github.aakira:exoplayer-manager:0.11.0@aar' - implementation 'com.github.aakira:exoplayer-manager-ima:0.11.0@aar' // if you use an IMA SDK + implementation 'com.github.aakira:exoplayer-manager:0.12.0@aar' + implementation 'com.github.aakira:exoplayer-manager-ima:0.12.0@aar' // if you use an IMA SDK } ``` ## Using libraries diff --git a/build.gradle b/build.gradle index 15957e0..e2d67ac 100644 --- a/build.gradle +++ b/build.gradle @@ -3,8 +3,8 @@ buildscript { // This library version - ext.LIBRARY_VERSION_CODE = 11 - ext.LIBRARY_VERSION_NAME = "0.11.0" + ext.LIBRARY_VERSION_CODE = 12 + ext.LIBRARY_VERSION_NAME = "0.12.0" // App information ext.COMPILE_SDK_VERSION = 27 From 480f444ba0fa4b193511ebe5304251bdae5410bf Mon Sep 17 00:00:00 2001 From: "A.Akira" Date: Thu, 31 May 2018 14:43:38 +0900 Subject: [PATCH 3/3] Remove audio capabilities changed listener. --- .../aakira/playermanager/sample/PlayerActivity.kt | 3 --- .../aakira/playermanager/CallBackTypeAlias.kt | 6 ------ .../github/aakira/playermanager/ExoPlayerManager.kt | 13 ------------- 3 files changed, 22 deletions(-) diff --git a/app/src/main/kotlin/com/github/aakira/playermanager/sample/PlayerActivity.kt b/app/src/main/kotlin/com/github/aakira/playermanager/sample/PlayerActivity.kt index 2f16bc5..0c9827e 100644 --- a/app/src/main/kotlin/com/github/aakira/playermanager/sample/PlayerActivity.kt +++ b/app/src/main/kotlin/com/github/aakira/playermanager/sample/PlayerActivity.kt @@ -60,9 +60,6 @@ class PlayerActivity : Activity() { (if (currentSpeed > 2f) 0.4f else currentSpeed + 0.2f).let { playerManager.setPlaybackParameters(it, 1f) } - } - playerManager.addOnAudioCapabilitiesChangedListener { - } playerManager.addOnVideoSizeChangedListener { eventTime, width, height, unappliedRotationDegrees, pixelWidthHeightRatio -> diff --git a/playermanager/src/main/kotlin/com/github/aakira/playermanager/CallBackTypeAlias.kt b/playermanager/src/main/kotlin/com/github/aakira/playermanager/CallBackTypeAlias.kt index 12b170d..68ff776 100644 --- a/playermanager/src/main/kotlin/com/github/aakira/playermanager/CallBackTypeAlias.kt +++ b/playermanager/src/main/kotlin/com/github/aakira/playermanager/CallBackTypeAlias.kt @@ -2,7 +2,6 @@ package com.github.aakira.playermanager import com.google.android.exoplayer2.PlaybackParameters import com.google.android.exoplayer2.analytics.AnalyticsListener -import com.google.android.exoplayer2.audio.AudioCapabilities import com.google.android.exoplayer2.metadata.Metadata import com.google.android.exoplayer2.source.MediaSourceEventListener import com.google.android.exoplayer2.trackselection.TrackSelectionArray @@ -45,11 +44,6 @@ typealias VideoSizeChangedListener = (eventTime: AnalyticsListener.EventTime?, w height: Int, unappliedRotationDegrees: Int, pixelWidthHeightRatio: Float) -> Unit -/** - * See [com.google.android.exoplayer2.audio.AudioCapabilitiesReceiver.Listener.onAudioCapabilitiesChanged] - */ -typealias AudioCapabilitiesChangedListener = (AudioCapabilities) -> Unit - /** * See [com.google.android.exoplayer2.source.MediaSourceEventListener.onLoadError] */ diff --git a/playermanager/src/main/kotlin/com/github/aakira/playermanager/ExoPlayerManager.kt b/playermanager/src/main/kotlin/com/github/aakira/playermanager/ExoPlayerManager.kt index ffdbf89..6e7640c 100644 --- a/playermanager/src/main/kotlin/com/github/aakira/playermanager/ExoPlayerManager.kt +++ b/playermanager/src/main/kotlin/com/github/aakira/playermanager/ExoPlayerManager.kt @@ -47,7 +47,6 @@ class ExoPlayerManager(private val context: Context, private var trackSelector: DefaultTrackSelector? = null private val onMediaSourceLoadErrorListeners = ArrayList() - private var onAudioCapabilitiesChangedListeners = ArrayList() private val onMetadataListeners = ArrayList() private val onPlaybackParametersListeners = ArrayList() private val onPlayerErrorListeners = ArrayList() @@ -263,18 +262,6 @@ class ExoPlayerManager(private val context: Context, onMediaSourceLoadErrorListeners.clear() } - fun addOnAudioCapabilitiesChangedListener(listener: AudioCapabilitiesChangedListener) { - onAudioCapabilitiesChangedListeners.add(listener) - } - - fun removeAudioCapabilitiesReceiverListener(listener: AudioCapabilitiesChangedListener) { - onAudioCapabilitiesChangedListeners.remove(listener) - } - - fun clearAudioCapabilitiesReceiverListeners() { - onAudioCapabilitiesChangedListeners.clear() - } - fun addOnMetadataListener(listener: MetadataListener) { onMetadataListeners.add(listener) }