diff --git a/core/build.gradle b/core/build.gradle index 7fd18a4c..325715b9 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -48,7 +48,7 @@ android { } dependencies { - implementation 'com.google.android.exoplayer:exoplayer:2.7.3' + implementation 'com.google.android.exoplayer:exoplayer:2.8.1' testImplementation 'junit:junit:4.12' testImplementation 'org.mockito:mockito-core:2.16.0' diff --git a/core/src/main/java/com/novoda/noplayer/OptionsBuilder.java b/core/src/main/java/com/novoda/noplayer/OptionsBuilder.java index 5daf8703..406d8965 100644 --- a/core/src/main/java/com/novoda/noplayer/OptionsBuilder.java +++ b/core/src/main/java/com/novoda/noplayer/OptionsBuilder.java @@ -59,5 +59,4 @@ public OptionsBuilder withMaxInitialBitrate(int maxInitialBitrate) { public Options build() { return new Options(contentType, minDurationBeforeQualityIncreaseInMillis, maxInitialBitrate); } - } diff --git a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/CompositeTrackSelectorCreator.java b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/CompositeTrackSelectorCreator.java index 42240a92..a0a18e12 100644 --- a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/CompositeTrackSelectorCreator.java +++ b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/CompositeTrackSelectorCreator.java @@ -2,7 +2,6 @@ import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; -import com.google.android.exoplayer2.trackselection.FixedTrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter; import com.google.android.exoplayer2.util.Clock; @@ -14,16 +13,9 @@ class CompositeTrackSelectorCreator { - private final DefaultBandwidthMeter bandwidthMeter; - - CompositeTrackSelectorCreator(DefaultBandwidthMeter bandwidthMeter) { - this.bandwidthMeter = bandwidthMeter; - } - - CompositeTrackSelector create(Options options) { + CompositeTrackSelector create(Options options, DefaultBandwidthMeter bandwidthMeter) { TrackSelection.Factory adaptiveTrackSelectionFactory = new AdaptiveTrackSelection.Factory( bandwidthMeter, - options.maxInitialBitrate(), options.minDurationBeforeQualityIncreaseInMillis(), AdaptiveTrackSelection.DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS, AdaptiveTrackSelection.DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS, @@ -35,13 +27,9 @@ CompositeTrackSelector create(Options options) { DefaultTrackSelector trackSelector = new DefaultTrackSelector(adaptiveTrackSelectionFactory); ExoPlayerTrackSelector exoPlayerTrackSelector = ExoPlayerTrackSelector.newInstance(trackSelector); - FixedTrackSelection.Factory trackSelectionFactory = new FixedTrackSelection.Factory(); - ExoPlayerAudioTrackSelector audioTrackSelector = new ExoPlayerAudioTrackSelector(exoPlayerTrackSelector, trackSelectionFactory); - ExoPlayerVideoTrackSelector videoTrackSelector = new ExoPlayerVideoTrackSelector(exoPlayerTrackSelector, trackSelectionFactory); - ExoPlayerSubtitleTrackSelector subtitleTrackSelector = new ExoPlayerSubtitleTrackSelector( - exoPlayerTrackSelector, - trackSelectionFactory - ); + ExoPlayerAudioTrackSelector audioTrackSelector = new ExoPlayerAudioTrackSelector(exoPlayerTrackSelector); + ExoPlayerVideoTrackSelector videoTrackSelector = new ExoPlayerVideoTrackSelector(exoPlayerTrackSelector); + ExoPlayerSubtitleTrackSelector subtitleTrackSelector = new ExoPlayerSubtitleTrackSelector(exoPlayerTrackSelector); return new CompositeTrackSelector(trackSelector, audioTrackSelector, videoTrackSelector, subtitleTrackSelector); } diff --git a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/ExoPlayerCreator.java b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/ExoPlayerCreator.java index a5005dec..6422538b 100644 --- a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/ExoPlayerCreator.java +++ b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/ExoPlayerCreator.java @@ -7,7 +7,7 @@ import com.google.android.exoplayer2.ExoPlayerFactory; import com.google.android.exoplayer2.RenderersFactory; import com.google.android.exoplayer2.SimpleExoPlayer; -import com.google.android.exoplayer2.drm.DefaultDrmSessionManager; +import com.google.android.exoplayer2.drm.DefaultDrmSessionEventListener; import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.FrameworkMediaCrypto; import com.google.android.exoplayer2.mediacodec.MediaCodecSelector; @@ -30,14 +30,13 @@ class ExoPlayerCreator { @NonNull public SimpleExoPlayer create(DrmSessionCreator drmSessionCreator, - DefaultDrmSessionManager.EventListener drmSessionEventListener, + DefaultDrmSessionEventListener drmSessionEventListener, MediaCodecSelector mediaCodecSelector, TrackSelector trackSelector) { DrmSessionManager drmSessionManager = drmSessionCreator.create(drmSessionEventListener); SubtitleDecoderFactory subtitleDecoderFactory = new NoPlayerSubtitleDecoderFactory(); RenderersFactory renderersFactory = new SimpleRenderersFactory( context, - drmSessionManager, EXTENSION_RENDERER_MODE_OFF, DEFAULT_ALLOWED_VIDEO_JOINING_TIME_MS, mediaCodecSelector, @@ -45,6 +44,6 @@ public SimpleExoPlayer create(DrmSessionCreator drmSessionCreator, ); DefaultLoadControl loadControl = new DefaultLoadControl(); - return ExoPlayerFactory.newSimpleInstance(renderersFactory, trackSelector, loadControl); + return ExoPlayerFactory.newSimpleInstance(renderersFactory, trackSelector, loadControl, drmSessionManager); } } diff --git a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/ExoPlayerFacade.java b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/ExoPlayerFacade.java index a1fdf18a..96f1be82 100644 --- a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/ExoPlayerFacade.java +++ b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/ExoPlayerFacade.java @@ -2,11 +2,13 @@ import android.net.Uri; import android.support.annotation.Nullable; + import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.audio.AudioAttributes; import com.google.android.exoplayer2.mediacodec.MediaCodecSelector; import com.google.android.exoplayer2.source.MediaSource; +import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter; import com.novoda.noplayer.Options; import com.novoda.noplayer.PlayerSurfaceHolder; import com.novoda.noplayer.internal.exoplayer.drm.DrmSessionCreator; @@ -106,7 +108,12 @@ void loadVideo(PlayerSurfaceHolder playerSurfaceHolder, ExoPlayerForwarder forwarder, MediaCodecSelector mediaCodecSelector) { this.options = options; - compositeTrackSelector = trackSelectorCreator.create(options); + + DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter.Builder() + .setInitialBitrateEstimate(options.maxInitialBitrate()) + .build(); + + compositeTrackSelector = trackSelectorCreator.create(options, bandwidthMeter); exoPlayer = exoPlayerCreator.create( drmSessionCreator, forwarder.drmSessionEventListener(), @@ -115,15 +122,15 @@ void loadVideo(PlayerSurfaceHolder playerSurfaceHolder, ); rendererTypeRequester = rendererTypeRequesterCreator.createfrom(exoPlayer); exoPlayer.addListener(forwarder.exoPlayerEventListener()); - exoPlayer.setVideoDebugListener(forwarder.videoRendererEventListener()); + exoPlayer.addAnalyticsListener(forwarder.analyticsListener()); setMovieAudioAttributes(exoPlayer); MediaSource mediaSource = mediaSourceFactory.create( - options.contentType(), + options, uri, - forwarder.extractorMediaSourceListener(), - forwarder.mediaSourceEventListener() + forwarder.mediaSourceEventListener(), + bandwidthMeter ); attachToSurface(playerSurfaceHolder); exoPlayer.prepare(mediaSource, RESET_POSITION, DO_NOT_RESET_STATE); diff --git a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/NoPlayerExoPlayerCreator.java b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/NoPlayerExoPlayerCreator.java index 613f3d42..f408b485 100644 --- a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/NoPlayerExoPlayerCreator.java +++ b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/NoPlayerExoPlayerCreator.java @@ -4,8 +4,6 @@ import android.os.Handler; import com.google.android.exoplayer2.mediacodec.MediaCodecSelector; -import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter; -import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; import com.novoda.noplayer.NoPlayer; import com.novoda.noplayer.internal.Heart; import com.novoda.noplayer.internal.SystemClock; @@ -44,15 +42,13 @@ static class InternalCreator { } ExoPlayerTwoImpl create(Context context, DrmSessionCreator drmSessionCreator, boolean downgradeSecureDecoder) { - DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter(); - DefaultDataSourceFactory defaultDataSourceFactory = new DefaultDataSourceFactory(context, "user-agent", bandwidthMeter); - MediaSourceFactory mediaSourceFactory = new MediaSourceFactory(defaultDataSourceFactory, handler); + MediaSourceFactory mediaSourceFactory = new MediaSourceFactory(context, handler); MediaCodecSelector mediaCodecSelector = downgradeSecureDecoder ? SecurityDowngradingCodecSelector.newInstance() : MediaCodecSelector.DEFAULT; - CompositeTrackSelectorCreator trackSelectorCreator = new CompositeTrackSelectorCreator(bandwidthMeter); + CompositeTrackSelectorCreator trackSelectorCreator = new CompositeTrackSelectorCreator(); ExoPlayerCreator exoPlayerCreator = new ExoPlayerCreator(context); RendererTypeRequesterCreator rendererTypeRequesterCreator = new RendererTypeRequesterCreator(); diff --git a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/SimpleRenderersFactory.java b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/SimpleRenderersFactory.java index 9db23e6b..9895b2fb 100644 --- a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/SimpleRenderersFactory.java +++ b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/SimpleRenderersFactory.java @@ -19,6 +19,7 @@ import android.os.Handler; import android.os.Looper; import android.support.annotation.IntDef; +import android.support.annotation.Nullable; import android.util.Log; import com.google.android.exoplayer2.Renderer; @@ -90,8 +91,6 @@ class SimpleRenderersFactory implements RenderersFactory { private final Context context; - private final DrmSessionManager drmSessionManager; - @ExtensionRendererMode private final int extensionRendererMode; @@ -101,8 +100,6 @@ class SimpleRenderersFactory implements RenderersFactory { /** * @param context A {@link Context}. - * @param drmSessionManager An optional {@link DrmSessionManager}. May be null if DRM protected - * playbacks are not required.. * @param extensionRendererMode The extension renderer mode, which determines if and how * available extension renderers are used. Note that extensions must be included in the * application build for them to be considered available. @@ -112,13 +109,11 @@ class SimpleRenderersFactory implements RenderersFactory { * @param subtitleDecoderFactory A factory from which to obtain {@link SubtitleDecoder} instances. */ SimpleRenderersFactory(Context context, - DrmSessionManager drmSessionManager, @ExtensionRendererMode int extensionRendererMode, long allowedVideoJoiningTimeMs, MediaCodecSelector mediaCodecSelector, SubtitleDecoderFactory subtitleDecoderFactory) { this.context = context; - this.drmSessionManager = drmSessionManager; this.extensionRendererMode = extensionRendererMode; this.allowedVideoJoiningTimeMs = allowedVideoJoiningTimeMs; this.mediaCodecSelector = mediaCodecSelector; @@ -130,7 +125,8 @@ public Renderer[] createRenderers(Handler eventHandler, VideoRendererEventListener videoRendererEventListener, AudioRendererEventListener audioRendererEventListener, TextOutput textRendererOutput, - MetadataOutput metadataRendererOutput) { + MetadataOutput metadataRendererOutput, + @Nullable DrmSessionManager drmSessionManager) { ArrayList renderersList = new ArrayList<>(); buildVideoRenderers(context, drmSessionManager, allowedVideoJoiningTimeMs, eventHandler, videoRendererEventListener, extensionRendererMode, renderersList); @@ -219,13 +215,18 @@ private void buildAudioRenderers(Context context, AudioRendererEventListener eventListener, @ExtensionRendererMode int extensionRendererMode, List outRenderers) { - outRenderers.add(new MediaCodecAudioRenderer(mediaCodecSelector, + MediaCodecAudioRenderer mediaCodecAudioRenderer = new MediaCodecAudioRenderer( + context, + mediaCodecSelector, drmSessionManager, PLAY_CLEAR_SAMPLES_WITHOUT_KEYS, eventHandler, eventListener, AudioCapabilities.getCapabilities(context), - audioProcessors)); + audioProcessors + ); + + outRenderers.add(mediaCodecAudioRenderer); if (extensionRendererMode == EXTENSION_RENDERER_MODE_OFF) { return; diff --git a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/drm/DownloadDrmSessionCreator.java b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/drm/DownloadDrmSessionCreator.java index f3056e8d..9b359720 100644 --- a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/drm/DownloadDrmSessionCreator.java +++ b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/drm/DownloadDrmSessionCreator.java @@ -2,7 +2,7 @@ import android.os.Handler; -import com.google.android.exoplayer2.drm.DefaultDrmSessionManager; +import com.google.android.exoplayer2.drm.DefaultDrmSessionEventListener; import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.FrameworkMediaCrypto; import com.novoda.noplayer.drm.DownloadedModularDrm; @@ -20,7 +20,7 @@ class DownloadDrmSessionCreator implements DrmSessionCreator { } @Override - public DrmSessionManager create(DefaultDrmSessionManager.EventListener eventListener) { + public DrmSessionManager create(DefaultDrmSessionEventListener eventListener) { return new LocalDrmSessionManager( downloadedModularDrm.getKeySetId(), mediaDrmCreator.create(WIDEVINE_MODULAR_UUID), diff --git a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/drm/DrmSessionCreator.java b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/drm/DrmSessionCreator.java index a9b9afd8..ad0b037f 100644 --- a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/drm/DrmSessionCreator.java +++ b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/drm/DrmSessionCreator.java @@ -2,7 +2,7 @@ import android.support.annotation.Nullable; -import com.google.android.exoplayer2.drm.DefaultDrmSessionManager; +import com.google.android.exoplayer2.drm.DefaultDrmSessionEventListener; import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.FrameworkMediaCrypto; @@ -13,5 +13,5 @@ public interface DrmSessionCreator { UUID WIDEVINE_MODULAR_UUID = new UUID(0xEDEF8BA979D64ACEL, 0xA3C827DCD51D21EDL); @Nullable - DrmSessionManager create(DefaultDrmSessionManager.EventListener eventListener); + DrmSessionManager create(DefaultDrmSessionEventListener eventListener); } diff --git a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/drm/LocalDrmSessionManager.java b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/drm/LocalDrmSessionManager.java index 8677c9cb..c3333a55 100644 --- a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/drm/LocalDrmSessionManager.java +++ b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/drm/LocalDrmSessionManager.java @@ -5,7 +5,7 @@ import android.os.Handler; import android.os.Looper; -import com.google.android.exoplayer2.drm.DefaultDrmSessionManager; +import com.google.android.exoplayer2.drm.DefaultDrmSessionEventListener; import com.google.android.exoplayer2.drm.DrmInitData; import com.google.android.exoplayer2.drm.DrmSession; import com.google.android.exoplayer2.drm.DrmSessionManager; @@ -19,7 +19,7 @@ class LocalDrmSessionManager implements DrmSessionManager private final KeySetId keySetIdToRestore; private final ExoMediaDrm mediaDrm; - private final DefaultDrmSessionManager.EventListener eventListener; + private final DefaultDrmSessionEventListener eventListener; private final UUID drmScheme; private final Handler handler; @@ -27,7 +27,7 @@ class LocalDrmSessionManager implements DrmSessionManager ExoMediaDrm mediaDrm, UUID drmScheme, Handler handler, - DefaultDrmSessionManager.EventListener eventListener) { + DefaultDrmSessionEventListener eventListener) { this.keySetIdToRestore = keySetIdToRestore; this.mediaDrm = mediaDrm; this.eventListener = eventListener; diff --git a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/drm/NoDrmSessionCreator.java b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/drm/NoDrmSessionCreator.java index 49ba518e..4db14731 100644 --- a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/drm/NoDrmSessionCreator.java +++ b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/drm/NoDrmSessionCreator.java @@ -2,7 +2,7 @@ import android.support.annotation.Nullable; -import com.google.android.exoplayer2.drm.DefaultDrmSessionManager; +import com.google.android.exoplayer2.drm.DefaultDrmSessionEventListener; import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.FrameworkMediaCrypto; @@ -12,7 +12,7 @@ class NoDrmSessionCreator implements DrmSessionCreator { @Nullable @Override - public DrmSessionManager create(DefaultDrmSessionManager.EventListener eventListener) { + public DrmSessionManager create(DefaultDrmSessionEventListener eventListener) { return NO_DRM_SESSION; } } diff --git a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/drm/StreamingDrmSessionCreator.java b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/drm/StreamingDrmSessionCreator.java index 30b83312..10e1157f 100644 --- a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/drm/StreamingDrmSessionCreator.java +++ b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/drm/StreamingDrmSessionCreator.java @@ -2,6 +2,7 @@ import android.os.Handler; +import com.google.android.exoplayer2.drm.DefaultDrmSessionEventListener; import com.google.android.exoplayer2.drm.DefaultDrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.FrameworkMediaCrypto; @@ -26,16 +27,18 @@ class StreamingDrmSessionCreator implements DrmSessionCreator { } @Override - public DrmSessionManager create(DefaultDrmSessionManager.EventListener eventListener) { + public DrmSessionManager create(DefaultDrmSessionEventListener eventListener) { FrameworkMediaDrm frameworkMediaDrm = frameworkMediaDrmCreator.create(WIDEVINE_MODULAR_UUID); - return new DefaultDrmSessionManager<>( + DefaultDrmSessionManager defaultDrmSessionManager = new DefaultDrmSessionManager<>( WIDEVINE_MODULAR_UUID, frameworkMediaDrm, mediaDrmCallback, - NO_OPTIONAL_PARAMETERS, - handler, - eventListener + NO_OPTIONAL_PARAMETERS ); + defaultDrmSessionManager.removeListener(eventListener); + defaultDrmSessionManager.addListener(handler, eventListener); + + return defaultDrmSessionManager; } } diff --git a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/AnalyticsListenerForwarder.java b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/AnalyticsListenerForwarder.java new file mode 100644 index 00000000..1f4e1910 --- /dev/null +++ b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/AnalyticsListenerForwarder.java @@ -0,0 +1,435 @@ +package com.novoda.noplayer.internal.exoplayer.forwarder; + +import android.net.NetworkInfo; +import android.support.annotation.Nullable; +import android.view.Surface; + +import com.google.android.exoplayer2.ExoPlaybackException; +import com.google.android.exoplayer2.Format; +import com.google.android.exoplayer2.PlaybackParameters; +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.source.MediaSourceEventListener; +import com.google.android.exoplayer2.source.TrackGroupArray; +import com.google.android.exoplayer2.trackselection.TrackSelectionArray; +import com.novoda.noplayer.NoPlayer; + +import java.io.IOException; +import java.util.HashMap; + +import static com.novoda.noplayer.internal.exoplayer.forwarder.ForwarderInformation.Methods; +import static com.novoda.noplayer.internal.exoplayer.forwarder.ForwarderInformation.Parameters; + +class AnalyticsListenerForwarder implements AnalyticsListener { + + private final NoPlayer.InfoListener infoListeners; + + AnalyticsListenerForwarder(NoPlayer.InfoListener infoListeners) { + this.infoListeners = infoListeners; + } + + @Override + public void onPlayerStateChanged(EventTime eventTime, boolean playWhenReady, int playbackState) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + callingMethodParameters.put(Parameters.PLAY_WHEN_READY, String.valueOf(playWhenReady)); + callingMethodParameters.put(Parameters.PLAYBACK_STATE, String.valueOf(playbackState)); + + infoListeners.onNewInfo(Methods.ON_PLAYER_STATE_CHANGED, callingMethodParameters); + } + + @Override + public void onTimelineChanged(EventTime eventTime, int reason) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + callingMethodParameters.put(Parameters.REASON, String.valueOf(reason)); + + infoListeners.onNewInfo(Methods.ON_TIMELINE_CHANGED, callingMethodParameters); + } + + @Override + public void onPositionDiscontinuity(EventTime eventTime, int reason) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + callingMethodParameters.put(Parameters.REASON, String.valueOf(reason)); + + infoListeners.onNewInfo(Methods.ON_POSITION_DISCONTINUITY, callingMethodParameters); + } + + @Override + public void onSeekStarted(EventTime eventTime) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + + infoListeners.onNewInfo(Methods.ON_SEEK_STARTED, callingMethodParameters); + } + + @Override + public void onSeekProcessed(EventTime eventTime) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + + infoListeners.onNewInfo(Methods.ON_SEEK_PROCESSED, callingMethodParameters); + } + + @Override + public void onPlaybackParametersChanged(EventTime eventTime, PlaybackParameters playbackParameters) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + callingMethodParameters.put(Parameters.PLAYBACK_PARAMETERS, playbackParameters.toString()); + + infoListeners.onNewInfo(Methods.ON_PLAYBACK_PARAMETERS_CHANGED, callingMethodParameters); + } + + @Override + public void onRepeatModeChanged(EventTime eventTime, int repeatMode) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + callingMethodParameters.put(Parameters.REPEAT_MODE, String.valueOf(repeatMode)); + + infoListeners.onNewInfo(Methods.ON_REPEAT_MODE_CHANGED, callingMethodParameters); + } + + @Override + public void onShuffleModeChanged(EventTime eventTime, boolean shuffleModeEnabled) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + callingMethodParameters.put(Parameters.SHUFFLE_MODE_ENABLED, String.valueOf(shuffleModeEnabled)); + + infoListeners.onNewInfo(Methods.ON_SHUFFLE_MODE_CHANGED, callingMethodParameters); + } + + @Override + public void onLoadingChanged(EventTime eventTime, boolean isLoading) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + callingMethodParameters.put(Parameters.IS_LOADING, String.valueOf(isLoading)); + + infoListeners.onNewInfo(Methods.ON_LOADING_CHANGED, callingMethodParameters); + } + + @Override + public void onPlayerError(EventTime eventTime, ExoPlaybackException error) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + callingMethodParameters.put(Parameters.ERROR, error.toString()); + + infoListeners.onNewInfo(Methods.ON_PLAYER_ERROR, callingMethodParameters); + } + + @Override + public void onTracksChanged(EventTime eventTime, TrackGroupArray trackGroups, TrackSelectionArray trackSelections) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + callingMethodParameters.put(Parameters.TRACK_GROUPS, trackGroups.toString()); + callingMethodParameters.put(Parameters.TRACK_SELECTIONS, trackSelections.toString()); + + infoListeners.onNewInfo(Methods.ON_TRACKS_CHANGED, callingMethodParameters); + } + + @Override + public void onLoadStarted(EventTime eventTime, + MediaSourceEventListener.LoadEventInfo loadEventInfo, + MediaSourceEventListener.MediaLoadData mediaLoadData) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + callingMethodParameters.put(Parameters.LOAD_EVENT_INFO, loadEventInfo.toString()); + callingMethodParameters.put(Parameters.MEDIA_LOAD_DATA, mediaLoadData.toString()); + + infoListeners.onNewInfo(Methods.ON_LOAD_STARTED, callingMethodParameters); + } + + @Override + public void onLoadCompleted(EventTime eventTime, + MediaSourceEventListener.LoadEventInfo loadEventInfo, + MediaSourceEventListener.MediaLoadData mediaLoadData) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + callingMethodParameters.put(Parameters.LOAD_EVENT_INFO, loadEventInfo.toString()); + callingMethodParameters.put(Parameters.MEDIA_LOAD_DATA, mediaLoadData.toString()); + + infoListeners.onNewInfo(Methods.ON_LOAD_COMPLETED, callingMethodParameters); + } + + @Override + public void onLoadCanceled(EventTime eventTime, + MediaSourceEventListener.LoadEventInfo loadEventInfo, + MediaSourceEventListener.MediaLoadData mediaLoadData) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + callingMethodParameters.put(Parameters.LOAD_EVENT_INFO, loadEventInfo.toString()); + callingMethodParameters.put(Parameters.MEDIA_LOAD_DATA, mediaLoadData.toString()); + + infoListeners.onNewInfo(Methods.ON_LOAD_CANCELED, callingMethodParameters); + } + + @Override + public void onLoadError(EventTime eventTime, + MediaSourceEventListener.LoadEventInfo loadEventInfo, + MediaSourceEventListener.MediaLoadData mediaLoadData, + IOException error, + boolean wasCanceled) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + callingMethodParameters.put(Parameters.LOAD_EVENT_INFO, loadEventInfo.toString()); + callingMethodParameters.put(Parameters.MEDIA_LOAD_DATA, mediaLoadData.toString()); + callingMethodParameters.put(Parameters.ERROR, error.toString()); + callingMethodParameters.put(Parameters.WAS_CANCELED, String.valueOf(wasCanceled)); + + infoListeners.onNewInfo(Methods.ON_LOAD_ERROR, callingMethodParameters); + } + + @Override + public void onDownstreamFormatChanged(EventTime eventTime, MediaSourceEventListener.MediaLoadData mediaLoadData) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + callingMethodParameters.put(Parameters.MEDIA_LOAD_DATA, mediaLoadData.toString()); + + infoListeners.onNewInfo(Methods.ON_DOWNSTREAM_FORMAT_CHANGED, callingMethodParameters); + } + + @Override + public void onUpstreamDiscarded(EventTime eventTime, MediaSourceEventListener.MediaLoadData mediaLoadData) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + callingMethodParameters.put(Parameters.MEDIA_LOAD_DATA, mediaLoadData.toString()); + + infoListeners.onNewInfo(Methods.ON_UPSTREAM_DISCARDED, callingMethodParameters); + } + + @Override + public void onMediaPeriodCreated(EventTime eventTime) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + + infoListeners.onNewInfo(Methods.ON_MEDIA_PERIOD_CREATED, callingMethodParameters); + } + + @Override + public void onMediaPeriodReleased(EventTime eventTime) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + + infoListeners.onNewInfo(Methods.ON_MEDIA_PERIOD_RELEASED, callingMethodParameters); + } + + @Override + public void onReadingStarted(EventTime eventTime) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + + infoListeners.onNewInfo(Methods.ON_READING_STARTED, callingMethodParameters); + } + + @Override + public void onBandwidthEstimate(EventTime eventTime, + int totalLoadTimeMs, + long totalBytesLoaded, + long bitrateEstimate) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + callingMethodParameters.put(Parameters.TOTAL_LOAD_TIME_MS, String.valueOf(totalLoadTimeMs)); + callingMethodParameters.put(Parameters.TOTAL_BYTES_LOADED, String.valueOf(totalBytesLoaded)); + callingMethodParameters.put(Parameters.BITRATE_ESTIMATE, String.valueOf(bitrateEstimate)); + + infoListeners.onNewInfo(Methods.ON_BANDWIDTH_ESTIMATE, callingMethodParameters); + } + + @Override + public void onViewportSizeChange(EventTime eventTime, int width, int height) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + callingMethodParameters.put(Parameters.WIDTH, String.valueOf(width)); + callingMethodParameters.put(Parameters.HEIGHT, String.valueOf(height)); + + infoListeners.onNewInfo(Methods.ON_VIEWPORT_SIZE_CHANGE, callingMethodParameters); + } + + @Override + public void onNetworkTypeChanged(EventTime eventTime, @Nullable NetworkInfo networkInfo) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + callingMethodParameters.put(Parameters.NETWORK_INFO, networkInfo == null ? Parameters.NO_NETWORK_INFO : networkInfo.toString()); + + infoListeners.onNewInfo(Methods.ON_NETWORK_TYPE_CHANGED, callingMethodParameters); + } + + @Override + public void onMetadata(EventTime eventTime, Metadata metadata) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + callingMethodParameters.put(Parameters.METADATA, metadata.toString()); + + infoListeners.onNewInfo(Methods.ON_METADATA, callingMethodParameters); + } + + @Override + public void onDecoderEnabled(EventTime eventTime, int trackType, DecoderCounters decoderCounters) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + callingMethodParameters.put(Parameters.TRACK_TYPE, String.valueOf(trackType)); + callingMethodParameters.put(Parameters.DECODER_COUNTERS, decoderCounters.toString()); + + infoListeners.onNewInfo(Methods.ON_DECODER_ENABLED, callingMethodParameters); + } + + @Override + public void onDecoderInitialized(EventTime eventTime, + int trackType, + String decoderName, + long initializationDurationMs) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + callingMethodParameters.put(Parameters.TRACK_TYPE, String.valueOf(trackType)); + callingMethodParameters.put(Parameters.DECODER_NAME, decoderName); + callingMethodParameters.put(Parameters.INITIALIZATION_DURATION_MS, String.valueOf(initializationDurationMs)); + + infoListeners.onNewInfo(Methods.ON_DECODER_INITIALIZED, callingMethodParameters); + } + + @Override + public void onDecoderInputFormatChanged(EventTime eventTime, int trackType, Format format) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + callingMethodParameters.put(Parameters.TRACK_TYPE, String.valueOf(trackType)); + callingMethodParameters.put(Parameters.FORMAT, format.toString()); + + infoListeners.onNewInfo(Methods.ON_DECODER_INPUT_FORMAT_CHANGED, callingMethodParameters); + } + + @Override + public void onDecoderDisabled(EventTime eventTime, int trackType, DecoderCounters decoderCounters) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + callingMethodParameters.put(Parameters.TRACK_TYPE, String.valueOf(trackType)); + callingMethodParameters.put(Parameters.DECODER_COUNTERS, decoderCounters.toString()); + + infoListeners.onNewInfo(Methods.ON_DECODER_DISABLED, callingMethodParameters); + } + + @Override + public void onAudioSessionId(EventTime eventTime, int audioSessionId) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + callingMethodParameters.put(Parameters.AUDIO_SESSION_ID, String.valueOf(audioSessionId)); + + infoListeners.onNewInfo(Methods.ON_AUDIO_SESSION_ID, callingMethodParameters); + } + + @Override + public void onAudioUnderrun(EventTime eventTime, int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + callingMethodParameters.put(Parameters.BUFFER_SIZE, String.valueOf(bufferSize)); + callingMethodParameters.put(Parameters.BUFFER_SIZE_MS, String.valueOf(bufferSizeMs)); + callingMethodParameters.put(Parameters.ELAPSED_SINCE_LAST_FEED_MS, String.valueOf(elapsedSinceLastFeedMs)); + + infoListeners.onNewInfo(Methods.ON_AUDIO_UNDERRUN, callingMethodParameters); + } + + @Override + public void onDroppedVideoFrames(EventTime eventTime, int droppedFrames, long elapsedMs) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + callingMethodParameters.put(Parameters.DROPPED_FRAMES, String.valueOf(droppedFrames)); + callingMethodParameters.put(Parameters.ELAPSED_MS, String.valueOf(elapsedMs)); + + infoListeners.onNewInfo(Methods.ON_DROPPED_VIDEO_FRAMES, callingMethodParameters); + } + + @Override + public void onVideoSizeChanged(EventTime eventTime, + int width, + int height, + int unappliedRotationDegrees, + float pixelWidthHeightRatio) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + callingMethodParameters.put(Parameters.WIDTH, String.valueOf(width)); + callingMethodParameters.put(Parameters.HEIGHT, String.valueOf(height)); + callingMethodParameters.put(Parameters.UNAPPLIED_ROTATION_DEGREES, String.valueOf(unappliedRotationDegrees)); + callingMethodParameters.put(Parameters.PIXEL_WIDTH_HEIGHT_RATIO, String.valueOf(pixelWidthHeightRatio)); + + infoListeners.onNewInfo(Methods.ON_VIDEO_SIZE_CHANGED, callingMethodParameters); + } + + @Override + public void onRenderedFirstFrame(EventTime eventTime, Surface surface) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + callingMethodParameters.put(Parameters.SURFACE, surface.toString()); + + infoListeners.onNewInfo(Methods.ON_RENDERED_FIRST_FRAME, callingMethodParameters); + } + + @Override + public void onDrmKeysLoaded(EventTime eventTime) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + + infoListeners.onNewInfo(Methods.ON_DRM_KEYS_LOADED, callingMethodParameters); + } + + @Override + public void onDrmSessionManagerError(EventTime eventTime, Exception error) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + callingMethodParameters.put(Parameters.ERROR, error.toString()); + + infoListeners.onNewInfo(Methods.ON_DRM_SESSION_MANAGER_ERROR, callingMethodParameters); + } + + @Override + public void onDrmKeysRestored(EventTime eventTime) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + + infoListeners.onNewInfo(Methods.ON_DRM_KEYS_RESTORED, callingMethodParameters); + } + + @Override + public void onDrmKeysRemoved(EventTime eventTime) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.EVENT_TIME, eventTime.toString()); + + infoListeners.onNewInfo(Methods.ON_DRM_KEYS_REMOVED, callingMethodParameters); + } +} diff --git a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/BitrateForwarder.java b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/BitrateForwarder.java index 20e91574..18d6f4b3 100644 --- a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/BitrateForwarder.java +++ b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/BitrateForwarder.java @@ -1,15 +1,16 @@ package com.novoda.noplayer.internal.exoplayer.forwarder; +import android.support.annotation.Nullable; + import com.google.android.exoplayer2.C; -import com.google.android.exoplayer2.Format; -import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener; -import com.google.android.exoplayer2.upstream.DataSpec; +import com.google.android.exoplayer2.source.MediaSource; +import com.google.android.exoplayer2.source.MediaSourceEventListener; import com.novoda.noplayer.NoPlayer; import com.novoda.noplayer.model.Bitrate; import java.io.IOException; -class BitrateForwarder implements AdaptiveMediaSourceEventListener { +class BitrateForwarder implements MediaSourceEventListener { private Bitrate videoBitrate = Bitrate.fromBitsPerSecond(0); private Bitrate audioBitrate = Bitrate.fromBitsPerSecond(0); @@ -21,82 +22,75 @@ class BitrateForwarder implements AdaptiveMediaSourceEventListener { } @Override - public void onDownstreamFormatChanged(int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaTimeMs) { - if (trackType == C.TRACK_TYPE_VIDEO) { - videoBitrate = Bitrate.fromBitsPerSecond(trackFormat.bitrate); - bitrateChangedListener.onBitrateChanged(audioBitrate, videoBitrate); - } else if (trackType == C.TRACK_TYPE_AUDIO) { - audioBitrate = Bitrate.fromBitsPerSecond(trackFormat.bitrate); - bitrateChangedListener.onBitrateChanged(audioBitrate, videoBitrate); - } + public void onMediaPeriodCreated(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId) { + // TODO: should we send? } - @SuppressWarnings({"checkstyle:ParameterNumber", "PMD.ExcessiveParameterList"}) // This implements an interface method defined by ExoPlayer @Override - public void onLoadStarted(DataSpec dataSpec, - int dataType, - int trackType, - Format trackFormat, - int trackSelectionReason, - Object trackSelectionData, - long mediaStartTimeMs, - long mediaEndTimeMs, - long elapsedRealtimeMs) { + public void onMediaPeriodReleased(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId) { // TODO: should we send? } - @SuppressWarnings({"checkstyle:ParameterNumber", "PMD.ExcessiveParameterList"}) // This implements an interface method defined by ExoPlayer @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) { + public void onLoadStarted(int windowIndex, + @Nullable MediaSource.MediaPeriodId mediaPeriodId, + LoadEventInfo loadEventInfo, + MediaLoadData mediaLoadData) { // TODO: should we send? } - @SuppressWarnings({"checkstyle:ParameterNumber", "PMD.ExcessiveParameterList"}) // This implements an interface method defined by ExoPlayer @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) { + public void onLoadCompleted(int windowIndex, + @Nullable MediaSource.MediaPeriodId mediaPeriodId, + LoadEventInfo loadEventInfo, + MediaLoadData mediaLoadData) { // TODO: should we send? } - @SuppressWarnings({"checkstyle:ParameterNumber", "PMD.ExcessiveParameterList"}) // This implements an interface method defined by ExoPlayer @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, + public void onLoadCanceled(int windowIndex, + @Nullable MediaSource.MediaPeriodId mediaPeriodId, + LoadEventInfo loadEventInfo, + MediaLoadData mediaLoadData) { + // TODO: should we send? + } + + @Override + public void onLoadError(int windowIndex, + @Nullable MediaSource.MediaPeriodId mediaPeriodId, + LoadEventInfo loadEventInfo, + MediaLoadData mediaLoadData, IOException error, boolean wasCanceled) { // TODO: should we send? } @Override - public void onUpstreamDiscarded(int trackType, long mediaStartTimeMs, long mediaEndTimeMs) { + public void onReadingStarted(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId) { // TODO: should we send? } + + @Override + public void onUpstreamDiscarded(int windowIndex, + MediaSource.MediaPeriodId mediaPeriodId, + MediaLoadData mediaLoadData) { + // TODO: should we send? + } + + @Override + public void onDownstreamFormatChanged(int windowIndex, + @Nullable MediaSource.MediaPeriodId mediaPeriodId, + MediaLoadData mediaLoadData) { + if (mediaLoadData.trackFormat == null) { + return; + } + + if (mediaLoadData.trackType == C.TRACK_TYPE_VIDEO) { + videoBitrate = Bitrate.fromBitsPerSecond(mediaLoadData.trackFormat.bitrate); + bitrateChangedListener.onBitrateChanged(audioBitrate, videoBitrate); + } else if (mediaLoadData.trackType == C.TRACK_TYPE_AUDIO) { + audioBitrate = Bitrate.fromBitsPerSecond(mediaLoadData.trackFormat.bitrate); + bitrateChangedListener.onBitrateChanged(audioBitrate, videoBitrate); + } + } } diff --git a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/DrmSessionInfoForwarder.java b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/DrmSessionInfoForwarder.java index c3e03e20..3abc524d 100644 --- a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/DrmSessionInfoForwarder.java +++ b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/DrmSessionInfoForwarder.java @@ -1,12 +1,15 @@ package com.novoda.noplayer.internal.exoplayer.forwarder; -import com.google.android.exoplayer2.drm.DefaultDrmSessionManager; +import com.google.android.exoplayer2.drm.DefaultDrmSessionEventListener; import com.novoda.noplayer.NoPlayer; import java.util.Collections; import java.util.HashMap; -class DrmSessionInfoForwarder implements DefaultDrmSessionManager.EventListener { +import static com.novoda.noplayer.internal.exoplayer.forwarder.ForwarderInformation.Methods; +import static com.novoda.noplayer.internal.exoplayer.forwarder.ForwarderInformation.Parameters; + +class DrmSessionInfoForwarder implements DefaultDrmSessionEventListener { private final NoPlayer.InfoListener infoListener; @@ -16,27 +19,26 @@ class DrmSessionInfoForwarder implements DefaultDrmSessionManager.EventListener @Override public void onDrmKeysLoaded() { - infoListener.onNewInfo("onDrmKeysLoaded", Collections.emptyMap()); - + infoListener.onNewInfo(Methods.ON_DRM_KEYS_LOADED, Collections.emptyMap()); } @Override public void onDrmSessionManagerError(Exception error) { HashMap callingMethodParameters = new HashMap<>(); - callingMethodParameters.put("error", String.valueOf(error)); + callingMethodParameters.put(Parameters.ERROR, String.valueOf(error)); - infoListener.onNewInfo("onDrmSessionManagerError", callingMethodParameters); + infoListener.onNewInfo(Methods.ON_DRM_SESSION_MANAGER_ERROR, callingMethodParameters); } @Override public void onDrmKeysRestored() { - infoListener.onNewInfo("onDrmKeysRestored", Collections.emptyMap()); + infoListener.onNewInfo(Methods.ON_DRM_KEYS_RESTORED, Collections.emptyMap()); } @Override public void onDrmKeysRemoved() { - infoListener.onNewInfo("onDrmKeysRemoved", Collections.emptyMap()); + infoListener.onNewInfo(Methods.ON_DRM_KEYS_REMOVED, Collections.emptyMap()); } } diff --git a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/EventInfoForwarder.java b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/EventInfoForwarder.java index d15aec1b..1e6c0da9 100644 --- a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/EventInfoForwarder.java +++ b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/EventInfoForwarder.java @@ -11,6 +11,9 @@ import java.util.Collections; import java.util.HashMap; +import static com.novoda.noplayer.internal.exoplayer.forwarder.ForwarderInformation.Methods; +import static com.novoda.noplayer.internal.exoplayer.forwarder.ForwarderInformation.Parameters; + class EventInfoForwarder implements Player.EventListener { private final NoPlayer.InfoListener infoListener; @@ -23,89 +26,89 @@ class EventInfoForwarder implements Player.EventListener { public void onTimelineChanged(Timeline timeline, Object manifest, @Player.TimelineChangeReason int reason) { HashMap callingMethodParameters = new HashMap<>(); - callingMethodParameters.put("timeline", String.valueOf(timeline)); - callingMethodParameters.put("manifest", String.valueOf(manifest)); - callingMethodParameters.put("reason", String.valueOf(reason)); + callingMethodParameters.put(Parameters.TIMELINE, String.valueOf(timeline)); + callingMethodParameters.put(Parameters.MANIFEST, String.valueOf(manifest)); + callingMethodParameters.put(Parameters.REASON, String.valueOf(reason)); - infoListener.onNewInfo("onTimelineChanged", callingMethodParameters); + infoListener.onNewInfo(Methods.ON_TIMELINE_CHANGED, callingMethodParameters); } @Override public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) { HashMap callingMethodParameters = new HashMap<>(); - callingMethodParameters.put("trackGroups", String.valueOf(trackGroups)); - callingMethodParameters.put("trackSelections", String.valueOf(trackSelections)); + callingMethodParameters.put(Parameters.TRACK_GROUPS, String.valueOf(trackGroups)); + callingMethodParameters.put(Parameters.TRACK_SELECTIONS, String.valueOf(trackSelections)); - infoListener.onNewInfo("onTracksChanged", callingMethodParameters); + infoListener.onNewInfo(Methods.ON_TRACKS_CHANGED, callingMethodParameters); } @Override public void onLoadingChanged(boolean isLoading) { HashMap callingMethodParameters = new HashMap<>(); - callingMethodParameters.put("isLoading", String.valueOf(isLoading)); + callingMethodParameters.put(Parameters.IS_LOADING, String.valueOf(isLoading)); - infoListener.onNewInfo("onLoadingChanged", callingMethodParameters); + infoListener.onNewInfo(Methods.ON_LOADING_CHANGED, callingMethodParameters); } @Override public void onPlayerStateChanged(boolean playWhenReady, int playbackState) { HashMap callingMethodParameters = new HashMap<>(); - callingMethodParameters.put("playWhenReady", String.valueOf(playWhenReady)); - callingMethodParameters.put("playbackState", String.valueOf(playbackState)); + callingMethodParameters.put(Parameters.PLAY_WHEN_READY, String.valueOf(playWhenReady)); + callingMethodParameters.put(Parameters.PLAYBACK_STATE, String.valueOf(playbackState)); - infoListener.onNewInfo("onPlayerStateChanged", callingMethodParameters); + infoListener.onNewInfo(Methods.ON_PLAYER_STATE_CHANGED, callingMethodParameters); } @Override public void onRepeatModeChanged(@Player.RepeatMode int repeatMode) { HashMap callingMethodParameters = new HashMap<>(); - callingMethodParameters.put("repeatMode", String.valueOf(repeatMode)); + callingMethodParameters.put(Parameters.REPEAT_MODE, String.valueOf(repeatMode)); - infoListener.onNewInfo("onRepeatModeChanged", callingMethodParameters); + infoListener.onNewInfo(Methods.ON_REPEAT_MODE_CHANGED, callingMethodParameters); } @Override public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) { HashMap callingMethodParameters = new HashMap<>(); - callingMethodParameters.put("shuffleModeEnabled", String.valueOf(shuffleModeEnabled)); + callingMethodParameters.put(Parameters.SHUFFLE_MODE_ENABLED, String.valueOf(shuffleModeEnabled)); - infoListener.onNewInfo("onShuffleModeEnabledChanged", callingMethodParameters); + infoListener.onNewInfo(Methods.ON_SHUFFLE_MODE_ENABLED_CHANGED, callingMethodParameters); } @Override public void onPlayerError(ExoPlaybackException error) { HashMap callingMethodParameters = new HashMap<>(); - callingMethodParameters.put("error", String.valueOf(error)); + callingMethodParameters.put(Parameters.ERROR, String.valueOf(error)); - infoListener.onNewInfo("onPlayerError", callingMethodParameters); + infoListener.onNewInfo(Methods.ON_PLAYER_ERROR, callingMethodParameters); } @Override public void onPositionDiscontinuity(int reason) { HashMap callingMethodParameters = new HashMap<>(); - callingMethodParameters.put("reason", String.valueOf(reason)); + callingMethodParameters.put(Parameters.REASON, String.valueOf(reason)); - infoListener.onNewInfo("onPositionDiscontinuity", callingMethodParameters); + infoListener.onNewInfo(Methods.ON_POSITION_DISCONTINUITY, callingMethodParameters); } @Override public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) { HashMap callingMethodParameters = new HashMap<>(); - callingMethodParameters.put("playbackParameters", String.valueOf(playbackParameters)); + callingMethodParameters.put(Parameters.PLAYBACK_PARAMETERS, String.valueOf(playbackParameters)); - infoListener.onNewInfo("onPlaybackParametersChanged", callingMethodParameters); + infoListener.onNewInfo(Methods.ON_PLAYBACK_PARAMETERS_CHANGED, callingMethodParameters); } @Override public void onSeekProcessed() { - infoListener.onNewInfo("onPositionDiscontinuity", Collections.emptyMap()); + infoListener.onNewInfo(Methods.ON_POSITION_DISCONTINUITY, Collections.emptyMap()); } } diff --git a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/ExoPlayerDrmSessionEventListener.java b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/ExoPlayerDrmSessionEventListener.java index dd5e2ef8..73db1a98 100644 --- a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/ExoPlayerDrmSessionEventListener.java +++ b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/ExoPlayerDrmSessionEventListener.java @@ -1,42 +1,42 @@ package com.novoda.noplayer.internal.exoplayer.forwarder; -import com.google.android.exoplayer2.drm.DefaultDrmSessionManager; +import com.google.android.exoplayer2.drm.DefaultDrmSessionEventListener; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; -class ExoPlayerDrmSessionEventListener implements DefaultDrmSessionManager.EventListener { +class ExoPlayerDrmSessionEventListener implements DefaultDrmSessionEventListener { - private final List listeners = new CopyOnWriteArrayList<>(); + private final List listeners = new CopyOnWriteArrayList<>(); - void add(DefaultDrmSessionManager.EventListener listener) { + void add(DefaultDrmSessionEventListener listener) { listeners.add(listener); } @Override public void onDrmKeysLoaded() { - for (DefaultDrmSessionManager.EventListener listener : listeners) { + for (DefaultDrmSessionEventListener listener : listeners) { listener.onDrmKeysLoaded(); } } @Override public void onDrmSessionManagerError(Exception e) { - for (DefaultDrmSessionManager.EventListener listener : listeners) { + for (DefaultDrmSessionEventListener listener : listeners) { listener.onDrmSessionManagerError(e); } } @Override public void onDrmKeysRestored() { - for (DefaultDrmSessionManager.EventListener listener : listeners) { + for (DefaultDrmSessionEventListener listener : listeners) { listener.onDrmKeysRestored(); } } @Override public void onDrmKeysRemoved() { - for (DefaultDrmSessionManager.EventListener listener : listeners) { + for (DefaultDrmSessionEventListener listener : listeners) { listener.onDrmKeysRemoved(); } } diff --git a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/ExoPlayerExtractorMediaSourceListener.java b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/ExoPlayerExtractorMediaSourceListener.java deleted file mode 100644 index d6f1d141..00000000 --- a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/ExoPlayerExtractorMediaSourceListener.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.novoda.noplayer.internal.exoplayer.forwarder; - -import com.google.android.exoplayer2.source.ExtractorMediaSource; - -import java.io.IOException; -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; - -class ExoPlayerExtractorMediaSourceListener implements ExtractorMediaSource.EventListener { - - private final List listeners = new CopyOnWriteArrayList<>(); - - public void add(ExtractorMediaSource.EventListener listener) { - listeners.add(listener); - } - - @Override - public void onLoadError(IOException error) { - for (ExtractorMediaSource.EventListener listener : listeners) { - listener.onLoadError(error); - } - } -} diff --git a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/ExoPlayerForwarder.java b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/ExoPlayerForwarder.java index 58d58d53..689c5478 100644 --- a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/ExoPlayerForwarder.java +++ b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/ExoPlayerForwarder.java @@ -1,8 +1,8 @@ package com.novoda.noplayer.internal.exoplayer.forwarder; -import com.google.android.exoplayer2.drm.DefaultDrmSessionManager; -import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener; -import com.google.android.exoplayer2.source.ExtractorMediaSource; +import com.google.android.exoplayer2.analytics.AnalyticsListener; +import com.google.android.exoplayer2.drm.DefaultDrmSessionEventListener; +import com.google.android.exoplayer2.source.MediaSourceEventListener; import com.google.android.exoplayer2.video.VideoRendererEventListener; import com.novoda.noplayer.NoPlayer; import com.novoda.noplayer.PlayerState; @@ -10,16 +10,16 @@ public class ExoPlayerForwarder { private final EventListener exoPlayerEventListener; - private final MediaSourceEventListener mediaSourceEventListener; + private final NoPlayerMediaSourceEventListener mediaSourceEventListener; + private final NoPlayerAnalyticsListener analyticsListener; private final ExoPlayerVideoRendererEventListener videoRendererEventListener; - private final ExoPlayerExtractorMediaSourceListener extractorMediaSourceListener; private final ExoPlayerDrmSessionEventListener drmSessionEventListener; public ExoPlayerForwarder() { exoPlayerEventListener = new EventListener(); - mediaSourceEventListener = new MediaSourceEventListener(); + mediaSourceEventListener = new NoPlayerMediaSourceEventListener(); videoRendererEventListener = new ExoPlayerVideoRendererEventListener(); - extractorMediaSourceListener = new ExoPlayerExtractorMediaSourceListener(); + analyticsListener = new NoPlayerAnalyticsListener(); drmSessionEventListener = new ExoPlayerDrmSessionEventListener(); } @@ -27,7 +27,7 @@ public EventListener exoPlayerEventListener() { return exoPlayerEventListener; } - public AdaptiveMediaSourceEventListener mediaSourceEventListener() { + public MediaSourceEventListener mediaSourceEventListener() { return mediaSourceEventListener; } @@ -35,11 +35,7 @@ public VideoRendererEventListener videoRendererEventListener() { return videoRendererEventListener; } - public ExtractorMediaSource.EventListener extractorMediaSourceListener() { - return extractorMediaSourceListener; - } - - public DefaultDrmSessionManager.EventListener drmSessionEventListener() { + public DefaultDrmSessionEventListener drmSessionEventListener() { return drmSessionEventListener; } @@ -70,9 +66,13 @@ public void bind(NoPlayer.BitrateChangedListener bitrateChangedListener) { public void bind(NoPlayer.InfoListener infoListeners) { exoPlayerEventListener.add(new EventInfoForwarder(infoListeners)); - mediaSourceEventListener.add(new MediaSourceInfoForwarder(infoListeners)); + mediaSourceEventListener.add(new MediaSourceEventForwarder(infoListeners)); videoRendererEventListener.add(new VideoRendererInfoForwarder(infoListeners)); - extractorMediaSourceListener.add(new ExtractorInfoForwarder(infoListeners)); drmSessionEventListener.add(new DrmSessionInfoForwarder(infoListeners)); + analyticsListener.add(new AnalyticsListenerForwarder(infoListeners)); + } + + public AnalyticsListener analyticsListener() { + return analyticsListener; } } diff --git a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/ExtractorInfoForwarder.java b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/ExtractorInfoForwarder.java deleted file mode 100644 index f4f26acd..00000000 --- a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/ExtractorInfoForwarder.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.novoda.noplayer.internal.exoplayer.forwarder; - -import com.google.android.exoplayer2.source.ExtractorMediaSource; -import com.novoda.noplayer.NoPlayer; - -import java.io.IOException; -import java.util.HashMap; - -class ExtractorInfoForwarder implements ExtractorMediaSource.EventListener { - - private final NoPlayer.InfoListener infoListener; - - ExtractorInfoForwarder(NoPlayer.InfoListener infoListener) { - this.infoListener = infoListener; - } - - @Override - public void onLoadError(IOException error) { - HashMap callingMethodParameters = new HashMap<>(); - - callingMethodParameters.put("error", String.valueOf(error)); - - infoListener.onNewInfo("onLoadError", callingMethodParameters); - } -} diff --git a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/ForwarderInformation.java b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/ForwarderInformation.java new file mode 100644 index 00000000..f0dea975 --- /dev/null +++ b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/ForwarderInformation.java @@ -0,0 +1,105 @@ +package com.novoda.noplayer.internal.exoplayer.forwarder; + +class ForwarderInformation { + + static final class Parameters { + + private Parameters() { + // non-instantiable + } + + static final String EVENT_TIME = "eventTime"; + static final String PLAY_WHEN_READY = "playWhenReady"; + static final String PLAYBACK_STATE = "playbackState"; + static final String REASON = "reason"; + static final String PLAYBACK_PARAMETERS = "playbackParameters"; + static final String REPEAT_MODE = "repeatMode"; + static final String SHUFFLE_MODE_ENABLED = "shuffleModeEnabled"; + static final String IS_LOADING = "isLoading"; + static final String ERROR = "error"; + static final String TRACK_GROUPS = "trackGroups"; + static final String TRACK_SELECTIONS = "trackSelections"; + static final String LOAD_EVENT_INFO = "loadEventInfo"; + static final String MEDIA_LOAD_DATA = "mediaLoadData"; + static final String WAS_CANCELED = "wasCanceled"; + static final String TOTAL_LOAD_TIME_MS = "totalLoadTimeMs"; + static final String TOTAL_BYTES_LOADED = "totalBytesLoaded"; + static final String BITRATE_ESTIMATE = "bitrateEstimate"; + static final String WIDTH = "width"; + static final String HEIGHT = "height"; + static final String NETWORK_INFO = "networkInfo"; + static final String NO_NETWORK_INFO = "null"; + static final String METADATA = "metadata"; + static final String TRACK_TYPE = "trackType"; + static final String DECODER_COUNTERS = "decoderCounters"; + static final String DECODER_NAME = "decoderName"; + static final String INITIALIZATION_DURATION_MS = "initializationDurationMs"; + static final String FORMAT = "format"; + static final String AUDIO_SESSION_ID = "audioSessionId"; + static final String BUFFER_SIZE = "bufferSize"; + static final String BUFFER_SIZE_MS = "bufferSizeMs"; + static final String ELAPSED_SINCE_LAST_FEED_MS = "elapsedSinceLastFeedMs"; + static final String DROPPED_FRAMES = "droppedFrames"; + static final String ELAPSED_MS = "elapsedMs"; + static final String PIXEL_WIDTH_HEIGHT_RATIO = "pixelWidthHeightRatio"; + static final String UNAPPLIED_ROTATION_DEGREES = "unappliedRotationDegrees"; + static final String SURFACE = "surface"; + static final String TIMELINE = "timeline"; + static final String MANIFEST = "manifest"; + static final String WINDOW_INDEX = "windowIndex"; + static final String MEDIA_PERIOD_ID = "mediaPeriodId"; + static final String COUNT = "count"; + static final String INITIALIZED_TIMESTAMP_MS = "initializedTimestampMs"; + + } + + static final class Methods { + + private Methods() { + // non-instantiable + } + + static final String ON_PLAYER_STATE_CHANGED = "onPlayerStateChanged"; + static final String ON_TIMELINE_CHANGED = "onTimelineChanged"; + static final String ON_POSITION_DISCONTINUITY = "onPositionDiscontinuity"; + static final String ON_SEEK_STARTED = "onSeekStarted"; + static final String ON_SEEK_PROCESSED = "onSeekProcessed"; + static final String ON_PLAYBACK_PARAMETERS_CHANGED = "onPlaybackParametersChanged"; + static final String ON_REPEAT_MODE_CHANGED = "onRepeatModeChanged"; + static final String ON_SHUFFLE_MODE_CHANGED = "onShuffleModeChanged"; + static final String ON_PLAYER_ERROR = "onPlayerError"; + static final String ON_TRACKS_CHANGED = "onTracksChanged"; + static final String ON_LOAD_STARTED = "onLoadStarted"; + static final String ON_LOAD_COMPLETED = "onLoadCompleted"; + static final String ON_LOAD_CANCELED = "onLoadCanceled"; + static final String ON_LOAD_ERROR = "onLoadError"; + static final String ON_DOWNSTREAM_FORMAT_CHANGED = "onDownstreamFormatChanged"; + static final String ON_UPSTREAM_DISCARDED = "onUpstreamDiscarded"; + static final String ON_MEDIA_PERIOD_CREATED = "onMediaPeriodCreated"; + static final String ON_MEDIA_PERIOD_RELEASED = "onMediaPeriodReleased"; + static final String ON_READING_STARTED = "onReadingStarted"; + static final String ON_BANDWIDTH_ESTIMATE = "onBandwidthEstimate"; + static final String ON_VIEWPORT_SIZE_CHANGE = "onViewportSizeChange"; + static final String ON_NETWORK_TYPE_CHANGED = "onNetworkTypeChanged"; + static final String ON_METADATA = "onMetadata"; + static final String ON_DECODER_ENABLED = "onDecoderEnabled"; + static final String ON_DECODER_INITIALIZED = "onDecoderInitialized"; + static final String ON_DECODER_INPUT_FORMAT_CHANGED = "onDecoderInputFormatChanged"; + static final String ON_DECODER_DISABLED = "onDecoderDisabled"; + static final String ON_AUDIO_SESSION_ID = "onAudioSessionId"; + static final String ON_AUDIO_UNDERRUN = "onAudioUnderrun"; + static final String ON_DROPPED_VIDEO_FRAMES = "onDroppedVideoFrames"; + static final String ON_VIDEO_SIZE_CHANGED = "onVideoSizeChanged"; + static final String ON_RENDERED_FIRST_FRAME = "onRenderedFirstFrame"; + static final String ON_DRM_KEYS_LOADED = "onDrmKeysLoaded"; + static final String ON_DRM_SESSION_MANAGER_ERROR = "onDrmSessionManagerError"; + static final String ON_DRM_KEYS_RESTORED = "onDrmKeysRestored"; + static final String ON_DRM_KEYS_REMOVED = "onDrmKeysRemoved"; + static final String ON_LOADING_CHANGED = "onLoadingChanged"; + static final String ON_SHUFFLE_MODE_ENABLED_CHANGED = "onShuffleModeEnabledChanged"; + static final String ON_VIDEO_ENABLED = "onVideoEnabled"; + static final String ON_VIDEO_DECODER_INITIALIZED = "onVideoDecoderInitialized"; + static final String ON_VIDEO_INPUT_FORMAT_CHANGED = "onVideoInputFormatChanged"; + static final String ON_VIDEO_DISABLED = "onVideoDisabled"; + } +} diff --git a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/MediaSourceEventForwarder.java b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/MediaSourceEventForwarder.java new file mode 100644 index 00000000..fa8d8994 --- /dev/null +++ b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/MediaSourceEventForwarder.java @@ -0,0 +1,144 @@ +package com.novoda.noplayer.internal.exoplayer.forwarder; + +import android.support.annotation.Nullable; + +import com.google.android.exoplayer2.source.MediaSource; +import com.google.android.exoplayer2.source.MediaSourceEventListener; +import com.novoda.noplayer.NoPlayer; + +import java.io.IOException; +import java.util.HashMap; + +import static com.novoda.noplayer.internal.exoplayer.forwarder.ForwarderInformation.Methods; +import static com.novoda.noplayer.internal.exoplayer.forwarder.ForwarderInformation.Parameters; + +// This implements an interface method defined by ExoPlayer +@SuppressWarnings({"PMD.UnusedImports", "checkstyle:ParameterNumber", "PMD.ExcessiveParameterList"}) +class MediaSourceEventForwarder implements MediaSourceEventListener { + + private static final String NO_MEDIA_PERIOD_ID = null; + + private final NoPlayer.InfoListener infoListener; + + MediaSourceEventForwarder(NoPlayer.InfoListener infoListener) { + this.infoListener = infoListener; + } + + @Override + public void onMediaPeriodCreated(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.WINDOW_INDEX, String.valueOf(windowIndex)); + callingMethodParameters.put(Parameters.MEDIA_PERIOD_ID, mediaPeriodId.toString()); + + infoListener.onNewInfo(Methods.ON_MEDIA_PERIOD_CREATED, callingMethodParameters); + } + + @Override + public void onMediaPeriodReleased(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.WINDOW_INDEX, String.valueOf(windowIndex)); + callingMethodParameters.put(Parameters.MEDIA_PERIOD_ID, mediaPeriodId.toString()); + + infoListener.onNewInfo(Methods.ON_MEDIA_PERIOD_RELEASED, callingMethodParameters); + } + + @Override + public void onLoadStarted(int windowIndex, + @Nullable MediaSource.MediaPeriodId mediaPeriodId, + LoadEventInfo loadEventInfo, + MediaLoadData mediaLoadData) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.WINDOW_INDEX, String.valueOf(windowIndex)); + callingMethodParameters.put(Parameters.MEDIA_PERIOD_ID, mediaPeriodId == null ? NO_MEDIA_PERIOD_ID : mediaPeriodId.toString()); + callingMethodParameters.put(Parameters.LOAD_EVENT_INFO, loadEventInfo.toString()); + callingMethodParameters.put(Parameters.MEDIA_LOAD_DATA, mediaLoadData.toString()); + + infoListener.onNewInfo(Methods.ON_LOAD_STARTED, callingMethodParameters); + } + + @Override + public void onLoadCompleted(int windowIndex, + @Nullable MediaSource.MediaPeriodId mediaPeriodId, + LoadEventInfo loadEventInfo, + MediaLoadData mediaLoadData) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.WINDOW_INDEX, String.valueOf(windowIndex)); + callingMethodParameters.put(Parameters.MEDIA_PERIOD_ID, mediaPeriodId == null ? NO_MEDIA_PERIOD_ID : mediaPeriodId.toString()); + callingMethodParameters.put(Parameters.LOAD_EVENT_INFO, loadEventInfo.toString()); + callingMethodParameters.put(Parameters.MEDIA_LOAD_DATA, mediaLoadData.toString()); + + infoListener.onNewInfo(Methods.ON_LOAD_COMPLETED, callingMethodParameters); + } + + @Override + public void onLoadCanceled(int windowIndex, + @Nullable MediaSource.MediaPeriodId mediaPeriodId, + LoadEventInfo loadEventInfo, + MediaLoadData mediaLoadData) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.WINDOW_INDEX, String.valueOf(windowIndex)); + callingMethodParameters.put(Parameters.MEDIA_PERIOD_ID, mediaPeriodId == null ? NO_MEDIA_PERIOD_ID : mediaPeriodId.toString()); + callingMethodParameters.put(Parameters.LOAD_EVENT_INFO, loadEventInfo.toString()); + callingMethodParameters.put(Parameters.MEDIA_LOAD_DATA, mediaLoadData.toString()); + + infoListener.onNewInfo(Methods.ON_LOAD_CANCELED, callingMethodParameters); + } + + @Override + public void onLoadError(int windowIndex, + @Nullable MediaSource.MediaPeriodId mediaPeriodId, + LoadEventInfo loadEventInfo, + MediaLoadData mediaLoadData, + IOException error, + boolean wasCanceled) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.WINDOW_INDEX, String.valueOf(windowIndex)); + callingMethodParameters.put(Parameters.MEDIA_PERIOD_ID, mediaPeriodId == null ? NO_MEDIA_PERIOD_ID : mediaPeriodId.toString()); + callingMethodParameters.put(Parameters.LOAD_EVENT_INFO, loadEventInfo.toString()); + callingMethodParameters.put(Parameters.MEDIA_LOAD_DATA, mediaLoadData.toString()); + + infoListener.onNewInfo(Methods.ON_LOAD_CANCELED, callingMethodParameters); + } + + @Override + public void onReadingStarted(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.WINDOW_INDEX, String.valueOf(windowIndex)); + callingMethodParameters.put(Parameters.MEDIA_PERIOD_ID, mediaPeriodId.toString()); + + infoListener.onNewInfo(Methods.ON_READING_STARTED, callingMethodParameters); + } + + @Override + public void onUpstreamDiscarded(int windowIndex, + MediaSource.MediaPeriodId mediaPeriodId, + MediaLoadData mediaLoadData) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.WINDOW_INDEX, String.valueOf(windowIndex)); + callingMethodParameters.put(Parameters.MEDIA_PERIOD_ID, mediaPeriodId.toString()); + callingMethodParameters.put(Parameters.MEDIA_LOAD_DATA, mediaLoadData.toString()); + + infoListener.onNewInfo(Methods.ON_UPSTREAM_DISCARDED, callingMethodParameters); + } + + @Override + public void onDownstreamFormatChanged(int windowIndex, + @Nullable MediaSource.MediaPeriodId mediaPeriodId, + MediaLoadData mediaLoadData) { + HashMap callingMethodParameters = new HashMap<>(); + + callingMethodParameters.put(Parameters.WINDOW_INDEX, String.valueOf(windowIndex)); + callingMethodParameters.put(Parameters.MEDIA_PERIOD_ID, mediaPeriodId == null ? NO_MEDIA_PERIOD_ID : mediaPeriodId.toString()); + callingMethodParameters.put(Parameters.MEDIA_LOAD_DATA, mediaLoadData.toString()); + + infoListener.onNewInfo(Methods.ON_DOWNSTREAM_FORMAT_CHANGED, callingMethodParameters); + } +} diff --git a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/MediaSourceEventListener.java b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/MediaSourceEventListener.java deleted file mode 100644 index 263ba2b8..00000000 --- a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/MediaSourceEventListener.java +++ /dev/null @@ -1,156 +0,0 @@ -package com.novoda.noplayer.internal.exoplayer.forwarder; - -import com.google.android.exoplayer2.Format; -import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener; -import com.google.android.exoplayer2.upstream.DataSpec; - -import java.io.IOException; -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; - -class MediaSourceEventListener implements AdaptiveMediaSourceEventListener { - - private final List listeners = new CopyOnWriteArrayList<>(); - - public void add(AdaptiveMediaSourceEventListener listener) { - listeners.add(listener); - } - - @SuppressWarnings({"checkstyle:ParameterNumber", "PMD.ExcessiveParameterList"}) // This implements an interface method defined by ExoPlayer - @Override - public void onLoadStarted(DataSpec dataSpec, - int dataType, - int trackType, - Format trackFormat, - int trackSelectionReason, - Object trackSelectionData, - long mediaStartTimeMs, - long mediaEndTimeMs, - long elapsedRealtimeMs) { - for (AdaptiveMediaSourceEventListener listener : listeners) { - listener.onLoadStarted( - dataSpec, - dataType, - trackType, - trackFormat, - trackSelectionReason, - trackSelectionData, - mediaStartTimeMs, - mediaEndTimeMs, - elapsedRealtimeMs - ); - } - } - - @SuppressWarnings({"checkstyle:ParameterNumber", "PMD.ExcessiveParameterList"}) // This implements an interface method defined by ExoPlayer - @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) { - for (AdaptiveMediaSourceEventListener listener : listeners) { - listener.onLoadCompleted( - dataSpec, - dataType, - trackType, - trackFormat, - trackSelectionReason, - trackSelectionData, - mediaStartTimeMs, - mediaEndTimeMs, - elapsedRealtimeMs, - loadDurationMs, - bytesLoaded - ); - } - } - - @SuppressWarnings({"checkstyle:ParameterNumber", "PMD.ExcessiveParameterList"}) // This implements an interface method defined by ExoPlayer - @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) { - for (AdaptiveMediaSourceEventListener listener : listeners) { - listener.onLoadCanceled( - dataSpec, - dataType, - trackType, - trackFormat, - trackSelectionReason, - trackSelectionData, - mediaStartTimeMs, - mediaEndTimeMs, - elapsedRealtimeMs, - loadDurationMs, - bytesLoaded - ); - } - } - - @SuppressWarnings({"checkstyle:ParameterNumber", "PMD.ExcessiveParameterList"}) // This implements an interface method defined by ExoPlayer - @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) { - for (AdaptiveMediaSourceEventListener listener : listeners) { - listener.onLoadError( - dataSpec, - dataType, - trackType, - trackFormat, - trackSelectionReason, - trackSelectionData, - mediaStartTimeMs, - mediaEndTimeMs, - elapsedRealtimeMs, - loadDurationMs, - bytesLoaded, - error, - wasCanceled - ); - } - } - - @Override - public void onUpstreamDiscarded(int trackType, long mediaStartTimeMs, long mediaEndTimeMs) { - for (AdaptiveMediaSourceEventListener listener : listeners) { - listener.onUpstreamDiscarded(trackType, mediaStartTimeMs, mediaEndTimeMs); - } - } - - @Override - public void onDownstreamFormatChanged(int trackType, - Format trackFormat, - int trackSelectionReason, - Object trackSelectionData, - long mediaTimeMs) { - for (AdaptiveMediaSourceEventListener listener : listeners) { - listener.onDownstreamFormatChanged(trackType, trackFormat, trackSelectionReason, trackSelectionData, mediaTimeMs); - } - } -} diff --git a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/MediaSourceInfoForwarder.java b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/MediaSourceInfoForwarder.java deleted file mode 100644 index cc1d7787..00000000 --- a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/MediaSourceInfoForwarder.java +++ /dev/null @@ -1,203 +0,0 @@ -package com.novoda.noplayer.internal.exoplayer.forwarder; - -import com.google.android.exoplayer2.Format; -import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener; -import com.google.android.exoplayer2.upstream.DataSpec; -import com.novoda.noplayer.NoPlayer; - -import java.io.IOException; -import java.util.HashMap; - -@SuppressWarnings("PMD.UnusedImports") // These two -class MediaSourceInfoForwarder implements AdaptiveMediaSourceEventListener { - - private final NoPlayer.InfoListener infoListener; - - MediaSourceInfoForwarder(NoPlayer.InfoListener infoListener) { - this.infoListener = infoListener; - } - - @SuppressWarnings({"checkstyle:ParameterNumber", "PMD.ExcessiveParameterList"}) // This implements an interface method defined by ExoPlayer - @Override - public void onLoadStarted(DataSpec dataSpec, - int dataType, - int trackType, - Format trackFormat, - int trackSelectionReason, - Object trackSelectionData, - long mediaStartTimeMs, - long mediaEndTimeMs, - long elapsedRealtimeMs) { - HashMap callingMethodParameters = new HashMap<>(); - - callingMethodParameters.put(Parameters.DATA_SPEC, String.valueOf(dataSpec)); - callingMethodParameters.put(Parameters.DATA_TYPE, String.valueOf(dataType)); - callingMethodParameters.put(Parameters.TRACK_TYPE, String.valueOf(trackType)); - callingMethodParameters.put(Parameters.TRACK_FORMAT, String.valueOf(trackFormat)); - callingMethodParameters.put(Parameters.TRACK_SELECTION_REASON, String.valueOf(trackSelectionReason)); - callingMethodParameters.put(Parameters.TRACK_SELECTION_DATA, String.valueOf(trackSelectionData)); - callingMethodParameters.put(Parameters.MEDIA_START_TIME_MS, String.valueOf(mediaStartTimeMs)); - callingMethodParameters.put(Parameters.MEDIA_END_TIME_MS, String.valueOf(mediaEndTimeMs)); - callingMethodParameters.put(Parameters.ELAPSED_REALTIME_MS, String.valueOf(elapsedRealtimeMs)); - - infoListener.onNewInfo(Methods.ON_LOAD_STARTED, callingMethodParameters); - } - - @SuppressWarnings({"checkstyle:ParameterNumber", "PMD.ExcessiveParameterList"}) // This implements an interface method defined by ExoPlayer - @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) { - HashMap callingMethodParameters = new HashMap<>(); - - callingMethodParameters.put(Parameters.DATA_SPEC, String.valueOf(dataSpec)); - callingMethodParameters.put(Parameters.DATA_TYPE, String.valueOf(dataType)); - callingMethodParameters.put(Parameters.TRACK_TYPE, String.valueOf(trackType)); - callingMethodParameters.put(Parameters.TRACK_FORMAT, String.valueOf(trackFormat)); - callingMethodParameters.put(Parameters.TRACK_SELECTION_REASON, String.valueOf(trackSelectionReason)); - callingMethodParameters.put(Parameters.TRACK_SELECTION_DATA, String.valueOf(trackSelectionData)); - callingMethodParameters.put(Parameters.MEDIA_START_TIME_MS, String.valueOf(mediaStartTimeMs)); - callingMethodParameters.put(Parameters.MEDIA_END_TIME_MS, String.valueOf(mediaEndTimeMs)); - callingMethodParameters.put(Parameters.ELAPSED_REALTIME_MS, String.valueOf(elapsedRealtimeMs)); - callingMethodParameters.put(Parameters.LOAD_DURATION_MS, String.valueOf(loadDurationMs)); - callingMethodParameters.put(Parameters.BYTES_LOADED, String.valueOf(bytesLoaded)); - - infoListener.onNewInfo(Methods.ON_LOAD_COMPLETED, callingMethodParameters); - } - - @SuppressWarnings({"checkstyle:ParameterNumber", "PMD.ExcessiveParameterList"}) // This implements an interface method defined by ExoPlayer - @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) { - HashMap callingMethodParameters = new HashMap<>(); - - callingMethodParameters.put(Parameters.DATA_SPEC, String.valueOf(dataSpec)); - callingMethodParameters.put(Parameters.DATA_TYPE, String.valueOf(dataType)); - callingMethodParameters.put(Parameters.TRACK_TYPE, String.valueOf(trackType)); - callingMethodParameters.put(Parameters.TRACK_FORMAT, String.valueOf(trackFormat)); - callingMethodParameters.put(Parameters.TRACK_SELECTION_REASON, String.valueOf(trackSelectionReason)); - callingMethodParameters.put(Parameters.TRACK_SELECTION_DATA, String.valueOf(trackSelectionData)); - callingMethodParameters.put(Parameters.MEDIA_START_TIME_MS, String.valueOf(mediaStartTimeMs)); - callingMethodParameters.put(Parameters.MEDIA_END_TIME_MS, String.valueOf(mediaEndTimeMs)); - callingMethodParameters.put(Parameters.ELAPSED_REALTIME_MS, String.valueOf(elapsedRealtimeMs)); - callingMethodParameters.put(Parameters.LOAD_DURATION_MS, String.valueOf(loadDurationMs)); - callingMethodParameters.put(Parameters.BYTES_LOADED, String.valueOf(bytesLoaded)); - - infoListener.onNewInfo(Methods.ON_LOAD_CANCELED, callingMethodParameters); - } - - @SuppressWarnings({"checkstyle:ParameterNumber", "PMD.ExcessiveParameterList"}) // This implements an interface method defined by ExoPlayer - @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) { - HashMap callingMethodParameters = new HashMap<>(); - - callingMethodParameters.put(Parameters.DATA_SPEC, String.valueOf(dataSpec)); - callingMethodParameters.put(Parameters.DATA_TYPE, String.valueOf(dataType)); - callingMethodParameters.put(Parameters.TRACK_TYPE, String.valueOf(trackType)); - callingMethodParameters.put(Parameters.TRACK_FORMAT, String.valueOf(trackFormat)); - callingMethodParameters.put(Parameters.TRACK_SELECTION_REASON, String.valueOf(trackSelectionReason)); - callingMethodParameters.put(Parameters.TRACK_SELECTION_DATA, String.valueOf(trackSelectionData)); - callingMethodParameters.put(Parameters.MEDIA_START_TIME_MS, String.valueOf(mediaStartTimeMs)); - callingMethodParameters.put(Parameters.MEDIA_END_TIME_MS, String.valueOf(mediaEndTimeMs)); - callingMethodParameters.put(Parameters.ELAPSED_REALTIME_MS, String.valueOf(elapsedRealtimeMs)); - callingMethodParameters.put(Parameters.LOAD_DURATION_MS, String.valueOf(loadDurationMs)); - callingMethodParameters.put(Parameters.BYTES_LOADED, String.valueOf(bytesLoaded)); - callingMethodParameters.put(Parameters.IO_EXCEPTION, String.valueOf(error)); - callingMethodParameters.put(Parameters.WAS_CANCELED, String.valueOf(wasCanceled)); - - infoListener.onNewInfo(Methods.ON_LOAD_ERROR, callingMethodParameters); - } - - @Override - public void onUpstreamDiscarded(int trackType, long mediaStartTimeMs, long mediaEndTimeMs) { - HashMap callingMethodParameters = new HashMap<>(); - - callingMethodParameters.put(Parameters.TRACK_TYPE, String.valueOf(trackType)); - callingMethodParameters.put(Parameters.MEDIA_START_TIME_MS, String.valueOf(mediaStartTimeMs)); - callingMethodParameters.put(Parameters.MEDIA_END_TIME_MS, String.valueOf(mediaEndTimeMs)); - - infoListener.onNewInfo(Methods.ON_UPSTREAM_DISCARDED, callingMethodParameters); - } - - @Override - public void onDownstreamFormatChanged(int trackType, - Format trackFormat, - int trackSelectionReason, - Object trackSelectionData, - long mediaTimeMs) { - HashMap callingMethodParameters = new HashMap<>(); - - callingMethodParameters.put(Parameters.TRACK_TYPE, String.valueOf(trackType)); - callingMethodParameters.put(Parameters.TRACK_FORMAT, String.valueOf(trackFormat)); - callingMethodParameters.put(Parameters.TRACK_SELECTION_REASON, String.valueOf(trackSelectionReason)); - callingMethodParameters.put(Parameters.TRACK_SELECTION_DATA, String.valueOf(trackSelectionData)); - callingMethodParameters.put(Parameters.MEDIA_TIME_MS, String.valueOf(mediaTimeMs)); - - infoListener.onNewInfo(Methods.ON_DOWNSTREAM_FORMAT_CHANGED, callingMethodParameters); - } - - static final class Parameters { - - private Parameters() { - // Not instantiable - } - - static final String DATA_SPEC = "dataSpec"; - static final String DATA_TYPE = "dataType"; - static final String TRACK_TYPE = "trackType"; - static final String TRACK_FORMAT = "trackFormat"; - static final String TRACK_SELECTION_REASON = "trackSelectionReason"; - static final String TRACK_SELECTION_DATA = "trackSelectionData"; - static final String MEDIA_START_TIME_MS = "mediaStartTimeMs"; - static final String MEDIA_END_TIME_MS = "mediaEndTimeMs"; - static final String ELAPSED_REALTIME_MS = "elapsedRealtimeMs"; - static final String LOAD_DURATION_MS = "loadDurationMs"; - static final String BYTES_LOADED = "bytesLoaded"; - static final String IO_EXCEPTION = "IOException"; - static final String WAS_CANCELED = "wasCanceled"; - static final String MEDIA_TIME_MS = "mediaTimeMs"; - } - - static final class Methods { - - private Methods() { - // Not instantiable - } - - static final String ON_LOAD_STARTED = "onLoadStarted"; - static final String ON_LOAD_COMPLETED = "onLoadCompleted"; - static final String ON_LOAD_CANCELED = "onLoadCanceled"; - static final String ON_LOAD_ERROR = "onLoadError"; - static final String ON_UPSTREAM_DISCARDED = "onUpstreamDiscarded"; - static final String ON_DOWNSTREAM_FORMAT_CHANGED = "onDownstreamFormatChanged"; - } -} diff --git a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/NoPlayerAnalyticsListener.java b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/NoPlayerAnalyticsListener.java new file mode 100644 index 00000000..9d29b1bb --- /dev/null +++ b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/NoPlayerAnalyticsListener.java @@ -0,0 +1,313 @@ +package com.novoda.noplayer.internal.exoplayer.forwarder; + +import android.net.NetworkInfo; +import android.support.annotation.Nullable; +import android.view.Surface; + +import com.google.android.exoplayer2.ExoPlaybackException; +import com.google.android.exoplayer2.Format; +import com.google.android.exoplayer2.PlaybackParameters; +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.source.MediaSourceEventListener; +import com.google.android.exoplayer2.source.TrackGroupArray; +import com.google.android.exoplayer2.trackselection.TrackSelectionArray; + +import java.io.IOException; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +class NoPlayerAnalyticsListener implements AnalyticsListener { + + private final List listeners = new CopyOnWriteArrayList<>(); + + public void add(AnalyticsListener listener) { + listeners.add(listener); + } + + @Override + public void onPlayerStateChanged(EventTime eventTime, boolean playWhenReady, int playbackState) { + for (AnalyticsListener listener : listeners) { + listener.onPlayerStateChanged(eventTime, playWhenReady, playbackState); + } + } + + @Override + public void onTimelineChanged(EventTime eventTime, int reason) { + for (AnalyticsListener listener : listeners) { + listener.onTimelineChanged(eventTime, reason); + } + } + + @Override + public void onPositionDiscontinuity(EventTime eventTime, int reason) { + for (AnalyticsListener listener : listeners) { + listener.onPositionDiscontinuity(eventTime, reason); + } + } + + @Override + public void onSeekStarted(EventTime eventTime) { + for (AnalyticsListener listener : listeners) { + listener.onSeekStarted(eventTime); + } + } + + @Override + public void onSeekProcessed(EventTime eventTime) { + for (AnalyticsListener listener : listeners) { + listener.onSeekProcessed(eventTime); + } + } + + @Override + public void onPlaybackParametersChanged(EventTime eventTime, PlaybackParameters playbackParameters) { + for (AnalyticsListener listener : listeners) { + listener.onPlaybackParametersChanged(eventTime, playbackParameters); + } + } + + @Override + public void onRepeatModeChanged(EventTime eventTime, int repeatMode) { + for (AnalyticsListener listener : listeners) { + listener.onRepeatModeChanged(eventTime, repeatMode); + } + } + + @Override + public void onShuffleModeChanged(EventTime eventTime, boolean shuffleModeEnabled) { + for (AnalyticsListener listener : listeners) { + listener.onShuffleModeChanged(eventTime, shuffleModeEnabled); + } + } + + @Override + public void onLoadingChanged(EventTime eventTime, boolean isLoading) { + for (AnalyticsListener listener : listeners) { + listener.onLoadingChanged(eventTime, isLoading); + } + } + + @Override + public void onPlayerError(EventTime eventTime, ExoPlaybackException error) { + for (AnalyticsListener listener : listeners) { + listener.onPlayerError(eventTime, error); + } + } + + @Override + public void onTracksChanged(EventTime eventTime, TrackGroupArray trackGroups, TrackSelectionArray trackSelections) { + for (AnalyticsListener listener : listeners) { + listener.onTracksChanged(eventTime, trackGroups, trackSelections); + } + } + + @Override + public void onLoadStarted(EventTime eventTime, + MediaSourceEventListener.LoadEventInfo loadEventInfo, + MediaSourceEventListener.MediaLoadData mediaLoadData) { + for (AnalyticsListener listener : listeners) { + listener.onLoadStarted(eventTime, loadEventInfo, mediaLoadData); + } + } + + @Override + public void onLoadCompleted(EventTime eventTime, + MediaSourceEventListener.LoadEventInfo loadEventInfo, + MediaSourceEventListener.MediaLoadData mediaLoadData) { + for (AnalyticsListener listener : listeners) { + listener.onLoadCompleted(eventTime, loadEventInfo, mediaLoadData); + } + } + + @Override + public void onLoadCanceled(EventTime eventTime, + MediaSourceEventListener.LoadEventInfo loadEventInfo, + MediaSourceEventListener.MediaLoadData mediaLoadData) { + for (AnalyticsListener listener : listeners) { + listener.onLoadCanceled(eventTime, loadEventInfo, mediaLoadData); + } + } + + @Override + public void onLoadError(EventTime eventTime, + MediaSourceEventListener.LoadEventInfo loadEventInfo, + MediaSourceEventListener.MediaLoadData mediaLoadData, + IOException error, + boolean wasCanceled) { + for (AnalyticsListener listener : listeners) { + listener.onLoadError(eventTime, loadEventInfo, mediaLoadData, error, wasCanceled); + } + } + + @Override + public void onDownstreamFormatChanged(EventTime eventTime, + MediaSourceEventListener.MediaLoadData mediaLoadData) { + for (AnalyticsListener listener : listeners) { + listener.onDownstreamFormatChanged(eventTime, mediaLoadData); + } + } + + @Override + public void onUpstreamDiscarded(EventTime eventTime, + MediaSourceEventListener.MediaLoadData mediaLoadData) { + for (AnalyticsListener listener : listeners) { + listener.onUpstreamDiscarded(eventTime, mediaLoadData); + } + } + + @Override + public void onMediaPeriodCreated(EventTime eventTime) { + for (AnalyticsListener listener : listeners) { + listener.onMediaPeriodCreated(eventTime); + } + } + + @Override + public void onMediaPeriodReleased(EventTime eventTime) { + for (AnalyticsListener listener : listeners) { + listener.onMediaPeriodReleased(eventTime); + } + } + + @Override + public void onReadingStarted(EventTime eventTime) { + for (AnalyticsListener listener : listeners) { + listener.onReadingStarted(eventTime); + } + } + + @Override + public void onBandwidthEstimate(EventTime eventTime, + int totalLoadTimeMs, + long totalBytesLoaded, + long bitrateEstimate) { + for (AnalyticsListener listener : listeners) { + listener.onBandwidthEstimate(eventTime, totalLoadTimeMs, totalBytesLoaded, bitrateEstimate); + } + } + + @Override + public void onViewportSizeChange(EventTime eventTime, + int width, + int height) { + for (AnalyticsListener listener : listeners) { + listener.onViewportSizeChange(eventTime, width, height); + } + } + + @Override + public void onNetworkTypeChanged(EventTime eventTime, @Nullable NetworkInfo networkInfo) { + for (AnalyticsListener listener : listeners) { + listener.onNetworkTypeChanged(eventTime, networkInfo); + } + } + + @Override + public void onMetadata(EventTime eventTime, Metadata metadata) { + for (AnalyticsListener listener : listeners) { + listener.onMetadata(eventTime, metadata); + } + } + + @Override + public void onDecoderEnabled(EventTime eventTime, int trackType, DecoderCounters decoderCounters) { + for (AnalyticsListener listener : listeners) { + listener.onDecoderEnabled(eventTime, trackType, decoderCounters); + } + } + + @Override + public void onDecoderInitialized(EventTime eventTime, + int trackType, + String decoderName, + long initializationDurationMs) { + for (AnalyticsListener listener : listeners) { + listener.onDecoderInitialized(eventTime, trackType, decoderName, initializationDurationMs); + } + } + + @Override + public void onDecoderInputFormatChanged(EventTime eventTime, + int trackType, + Format format) { + for (AnalyticsListener listener : listeners) { + listener.onDecoderInputFormatChanged(eventTime, trackType, format); + } + } + + @Override + public void onDecoderDisabled(EventTime eventTime, int trackType, DecoderCounters decoderCounters) { + for (AnalyticsListener listener : listeners) { + listener.onDecoderDisabled(eventTime, trackType, decoderCounters); + } + } + + @Override + public void onAudioSessionId(EventTime eventTime, int audioSessionId) { + for (AnalyticsListener listener : listeners) { + listener.onAudioSessionId(eventTime, audioSessionId); + } + } + + @Override + public void onAudioUnderrun(EventTime eventTime, int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs) { + for (AnalyticsListener listener : listeners) { + listener.onAudioUnderrun(eventTime, bufferSize, bufferSizeMs, elapsedSinceLastFeedMs); + } + } + + @Override + public void onDroppedVideoFrames(EventTime eventTime, int droppedFrames, long elapsedMs) { + for (AnalyticsListener listener : listeners) { + listener.onDroppedVideoFrames(eventTime, droppedFrames, elapsedMs); + } + } + + @Override + public void onVideoSizeChanged(EventTime eventTime, + int width, + int height, + int unappliedRotationDegrees, + float pixelWidthHeightRatio) { + for (AnalyticsListener listener : listeners) { + listener.onVideoSizeChanged(eventTime, width, height, unappliedRotationDegrees, pixelWidthHeightRatio); + } + } + + @Override + public void onRenderedFirstFrame(EventTime eventTime, Surface surface) { + for (AnalyticsListener listener : listeners) { + listener.onRenderedFirstFrame(eventTime, surface); + } + } + + @Override + public void onDrmKeysLoaded(EventTime eventTime) { + for (AnalyticsListener listener : listeners) { + listener.onDrmKeysLoaded(eventTime); + } + } + + @Override + public void onDrmSessionManagerError(EventTime eventTime, Exception error) { + for (AnalyticsListener listener : listeners) { + listener.onDrmSessionManagerError(eventTime, error); + } + } + + @Override + public void onDrmKeysRestored(EventTime eventTime) { + for (AnalyticsListener listener : listeners) { + listener.onDrmKeysRestored(eventTime); + } + } + + @Override + public void onDrmKeysRemoved(EventTime eventTime) { + for (AnalyticsListener listener : listeners) { + listener.onDrmKeysRemoved(eventTime); + } + } +} diff --git a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/NoPlayerMediaSourceEventListener.java b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/NoPlayerMediaSourceEventListener.java new file mode 100644 index 00000000..b1842ab5 --- /dev/null +++ b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/NoPlayerMediaSourceEventListener.java @@ -0,0 +1,100 @@ +package com.novoda.noplayer.internal.exoplayer.forwarder; + +import android.support.annotation.Nullable; + +import com.google.android.exoplayer2.source.MediaSource; +import com.google.android.exoplayer2.source.MediaSourceEventListener; + +import java.io.IOException; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +@SuppressWarnings({"checkstyle:ParameterNumber", "PMD.ExcessiveParameterList"}) // This implements an interface method defined by ExoPlayer +class NoPlayerMediaSourceEventListener implements MediaSourceEventListener { + + private final List listeners = new CopyOnWriteArrayList<>(); + + public void add(MediaSourceEventListener listener) { + listeners.add(listener); + } + + @Override + public void onMediaPeriodCreated(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId) { + for (MediaSourceEventListener listener : listeners) { + listener.onMediaPeriodCreated(windowIndex, mediaPeriodId); + } + } + + @Override + public void onMediaPeriodReleased(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId) { + for (MediaSourceEventListener listener : listeners) { + listener.onMediaPeriodReleased(windowIndex, mediaPeriodId); + } + } + + @Override + public void onLoadStarted(int windowIndex, + @Nullable MediaSource.MediaPeriodId mediaPeriodId, + LoadEventInfo loadEventInfo, + MediaLoadData mediaLoadData) { + for (MediaSourceEventListener listener : listeners) { + listener.onLoadStarted(windowIndex, mediaPeriodId, loadEventInfo, mediaLoadData); + } + } + + @Override + public void onLoadCompleted(int windowIndex, + @Nullable MediaSource.MediaPeriodId mediaPeriodId, + LoadEventInfo loadEventInfo, + MediaLoadData mediaLoadData) { + for (MediaSourceEventListener listener : listeners) { + listener.onLoadCompleted(windowIndex, mediaPeriodId, loadEventInfo, mediaLoadData); + } + } + + @Override + public void onLoadCanceled(int windowIndex, + @Nullable MediaSource.MediaPeriodId mediaPeriodId, + LoadEventInfo loadEventInfo, + MediaLoadData mediaLoadData) { + for (MediaSourceEventListener listener : listeners) { + listener.onLoadCanceled(windowIndex, mediaPeriodId, loadEventInfo, mediaLoadData); + } + } + + @Override + public void onLoadError(int windowIndex, + @Nullable MediaSource.MediaPeriodId mediaPeriodId, + LoadEventInfo loadEventInfo, + MediaLoadData mediaLoadData, + IOException error, boolean wasCanceled) { + for (MediaSourceEventListener listener : listeners) { + listener.onLoadError(windowIndex, mediaPeriodId, loadEventInfo, mediaLoadData, error, wasCanceled); + } + } + + @Override + public void onReadingStarted(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId) { + for (MediaSourceEventListener listener : listeners) { + listener.onReadingStarted(windowIndex, mediaPeriodId); + } + } + + @Override + public void onUpstreamDiscarded(int windowIndex, + MediaSource.MediaPeriodId mediaPeriodId, + MediaLoadData mediaLoadData) { + for (MediaSourceEventListener listener : listeners) { + listener.onUpstreamDiscarded(windowIndex, mediaPeriodId, mediaLoadData); + } + } + + @Override + public void onDownstreamFormatChanged(int windowIndex, + @Nullable MediaSource.MediaPeriodId mediaPeriodId, + MediaLoadData mediaLoadData) { + for (MediaSourceEventListener listener : listeners) { + listener.onDownstreamFormatChanged(windowIndex, mediaPeriodId, mediaLoadData); + } + } +} diff --git a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/VideoRendererInfoForwarder.java b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/VideoRendererInfoForwarder.java index 2b2baec7..6ef1d48c 100644 --- a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/VideoRendererInfoForwarder.java +++ b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/forwarder/VideoRendererInfoForwarder.java @@ -9,6 +9,9 @@ import java.util.HashMap; +import static com.novoda.noplayer.internal.exoplayer.forwarder.ForwarderInformation.Methods; +import static com.novoda.noplayer.internal.exoplayer.forwarder.ForwarderInformation.Parameters; + class VideoRendererInfoForwarder implements VideoRendererEventListener { private final NoPlayer.InfoListener infoListener; @@ -21,68 +24,68 @@ class VideoRendererInfoForwarder implements VideoRendererEventListener { public void onDroppedFrames(int count, long elapsedMs) { HashMap callingMethodParameters = new HashMap<>(); - callingMethodParameters.put("count", String.valueOf(count)); - callingMethodParameters.put("elapsedMs", String.valueOf(elapsedMs)); + callingMethodParameters.put(Parameters.COUNT, String.valueOf(count)); + callingMethodParameters.put(Parameters.ELAPSED_MS, String.valueOf(elapsedMs)); - infoListener.onNewInfo("onDroppedFrames", callingMethodParameters); + infoListener.onNewInfo(Methods.ON_DROPPED_VIDEO_FRAMES, callingMethodParameters); } @Override public void onVideoEnabled(DecoderCounters counters) { HashMap callingMethodParameters = new HashMap<>(); - callingMethodParameters.put("counters", String.valueOf(counters)); + callingMethodParameters.put(Parameters.DECODER_COUNTERS, String.valueOf(counters)); - infoListener.onNewInfo("onVideoEnabled", callingMethodParameters); + infoListener.onNewInfo(Methods.ON_VIDEO_ENABLED, callingMethodParameters); } @Override public void onVideoDecoderInitialized(String decoderName, long initializedTimestampMs, long initializationDurationMs) { HashMap callingMethodParameters = new HashMap<>(); - callingMethodParameters.put("decoderName", String.valueOf(decoderName)); - callingMethodParameters.put("initializedTimestampMs", String.valueOf(initializedTimestampMs)); - callingMethodParameters.put("initializationDurationMs", String.valueOf(initializationDurationMs)); + callingMethodParameters.put(Parameters.DECODER_NAME, String.valueOf(decoderName)); + callingMethodParameters.put(Parameters.INITIALIZED_TIMESTAMP_MS, String.valueOf(initializedTimestampMs)); + callingMethodParameters.put(Parameters.INITIALIZATION_DURATION_MS, String.valueOf(initializationDurationMs)); - infoListener.onNewInfo("onVideoDecoderInitialized", callingMethodParameters); + infoListener.onNewInfo(Methods.ON_VIDEO_DECODER_INITIALIZED, callingMethodParameters); } @Override public void onVideoInputFormatChanged(Format format) { HashMap callingMethodParameters = new HashMap<>(); - callingMethodParameters.put("format", String.valueOf(format)); + callingMethodParameters.put(Parameters.FORMAT, String.valueOf(format)); - infoListener.onNewInfo("onVideoInputFormatChanged", callingMethodParameters); + infoListener.onNewInfo(Methods.ON_VIDEO_INPUT_FORMAT_CHANGED, callingMethodParameters); } @Override public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) { HashMap callingMethodParameters = new HashMap<>(); - callingMethodParameters.put("width", String.valueOf(width)); - callingMethodParameters.put("height", String.valueOf(height)); - callingMethodParameters.put("unappliedRotationDegrees", String.valueOf(unappliedRotationDegrees)); - callingMethodParameters.put("pixelWidthHeightRatio", String.valueOf(pixelWidthHeightRatio)); + callingMethodParameters.put(Parameters.WIDTH, String.valueOf(width)); + callingMethodParameters.put(Parameters.HEIGHT, String.valueOf(height)); + callingMethodParameters.put(Parameters.UNAPPLIED_ROTATION_DEGREES, String.valueOf(unappliedRotationDegrees)); + callingMethodParameters.put(Parameters.PIXEL_WIDTH_HEIGHT_RATIO, String.valueOf(pixelWidthHeightRatio)); - infoListener.onNewInfo("onVideoSizeChanged", callingMethodParameters); + infoListener.onNewInfo(Methods.ON_VIDEO_SIZE_CHANGED, callingMethodParameters); } @Override public void onRenderedFirstFrame(Surface surface) { HashMap callingMethodParameters = new HashMap<>(); - callingMethodParameters.put("surface", String.valueOf(surface)); + callingMethodParameters.put(Parameters.SURFACE, String.valueOf(surface)); - infoListener.onNewInfo("onRenderedFirstFrame", callingMethodParameters); + infoListener.onNewInfo(Methods.ON_RENDERED_FIRST_FRAME, callingMethodParameters); } @Override public void onVideoDisabled(DecoderCounters counters) { HashMap callingMethodParameters = new HashMap<>(); - callingMethodParameters.put("counters", String.valueOf(counters)); + callingMethodParameters.put(Parameters.DECODER_COUNTERS, String.valueOf(counters)); - infoListener.onNewInfo("onVideoDisabled", callingMethodParameters); + infoListener.onNewInfo(Methods.ON_VIDEO_DISABLED, callingMethodParameters); } } diff --git a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/mediasource/ExoPlayerAudioTrackSelector.java b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/mediasource/ExoPlayerAudioTrackSelector.java index dead1d8c..91ce5cfc 100644 --- a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/mediasource/ExoPlayerAudioTrackSelector.java +++ b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/mediasource/ExoPlayerAudioTrackSelector.java @@ -3,8 +3,7 @@ import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.TrackGroupArray; -import com.google.android.exoplayer2.trackselection.MappingTrackSelector; -import com.google.android.exoplayer2.trackselection.TrackSelection; +import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; import com.novoda.noplayer.internal.exoplayer.RendererTypeRequester; import com.novoda.noplayer.model.AudioTracks; import com.novoda.noplayer.model.PlayerAudioTrack; @@ -17,18 +16,15 @@ public class ExoPlayerAudioTrackSelector { private final ExoPlayerTrackSelector trackSelector; - private final TrackSelection.Factory trackSelectionFactory; - public ExoPlayerAudioTrackSelector(ExoPlayerTrackSelector trackSelector, TrackSelection.Factory trackSelectionFactory) { + public ExoPlayerAudioTrackSelector(ExoPlayerTrackSelector trackSelector) { this.trackSelector = trackSelector; - this.trackSelectionFactory = trackSelectionFactory; } public boolean selectAudioTrack(PlayerAudioTrack audioTrack, RendererTypeRequester rendererTypeRequester) { TrackGroupArray trackGroups = trackSelector.trackGroups(AUDIO, rendererTypeRequester); - MappingTrackSelector.SelectionOverride selectionOverride = new MappingTrackSelector.SelectionOverride( - trackSelectionFactory, + DefaultTrackSelector.SelectionOverride selectionOverride = new DefaultTrackSelector.SelectionOverride( audioTrack.groupIndex(), audioTrack.formatIndex() ); diff --git a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/mediasource/ExoPlayerSubtitleTrackSelector.java b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/mediasource/ExoPlayerSubtitleTrackSelector.java index aad529a2..045563b1 100644 --- a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/mediasource/ExoPlayerSubtitleTrackSelector.java +++ b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/mediasource/ExoPlayerSubtitleTrackSelector.java @@ -3,8 +3,7 @@ import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.TrackGroupArray; -import com.google.android.exoplayer2.trackselection.MappingTrackSelector; -import com.google.android.exoplayer2.trackselection.TrackSelection; +import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; import com.novoda.noplayer.internal.exoplayer.RendererTypeRequester; import com.novoda.noplayer.model.PlayerSubtitleTrack; @@ -16,18 +15,15 @@ public class ExoPlayerSubtitleTrackSelector { private final ExoPlayerTrackSelector trackSelector; - private final TrackSelection.Factory trackSelectionFactory; - public ExoPlayerSubtitleTrackSelector(ExoPlayerTrackSelector trackSelector, TrackSelection.Factory trackSelectionFactory) { + public ExoPlayerSubtitleTrackSelector(ExoPlayerTrackSelector trackSelector) { this.trackSelector = trackSelector; - this.trackSelectionFactory = trackSelectionFactory; } public boolean selectTextTrack(PlayerSubtitleTrack subtitleTrack, RendererTypeRequester rendererTypeRequester) { TrackGroupArray trackGroups = trackSelector.trackGroups(TEXT, rendererTypeRequester); - MappingTrackSelector.SelectionOverride selectionOverride = new MappingTrackSelector.SelectionOverride( - trackSelectionFactory, + DefaultTrackSelector.SelectionOverride selectionOverride = new DefaultTrackSelector.SelectionOverride( subtitleTrack.groupIndex(), subtitleTrack.formatIndex() ); diff --git a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/mediasource/ExoPlayerTrackSelector.java b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/mediasource/ExoPlayerTrackSelector.java index 195902d1..b1b22d68 100644 --- a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/mediasource/ExoPlayerTrackSelector.java +++ b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/mediasource/ExoPlayerTrackSelector.java @@ -32,7 +32,10 @@ TrackGroupArray trackGroups(TrackType trackType, RendererTypeRequester rendererT boolean clearSelectionOverrideFor(TrackType trackType, RendererTypeRequester rendererTypeRequester) { Optional rendererIndex = rendererTrackIndexExtractor.extract(trackType, mappedTrackInfoLength(), rendererTypeRequester); if (rendererIndex.isPresent()) { - trackSelector.clearSelectionOverrides(rendererIndex.get()); + trackSelector.setParameters(trackSelector + .buildUponParameters() + .clearSelectionOverrides(rendererIndex.get()) + ); return true; } else { return false; @@ -55,10 +58,13 @@ private int mappedTrackInfoLength() { boolean setSelectionOverride(TrackType trackType, RendererTypeRequester rendererTypeRequester, TrackGroupArray trackGroups, - MappingTrackSelector.SelectionOverride selectionOverride) { + DefaultTrackSelector.SelectionOverride selectionOverride) { Optional rendererIndex = rendererTrackIndexExtractor.extract(trackType, mappedTrackInfoLength(), rendererTypeRequester); if (rendererIndex.isPresent()) { - trackSelector.setSelectionOverride(rendererIndex.get(), trackGroups, selectionOverride); + trackSelector.setParameters(trackSelector + .buildUponParameters() + .setSelectionOverride(rendererIndex.get(), trackGroups, selectionOverride) + ); return true; } else { return false; diff --git a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/mediasource/ExoPlayerVideoTrackSelector.java b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/mediasource/ExoPlayerVideoTrackSelector.java index 655cf64f..323c9c14 100644 --- a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/mediasource/ExoPlayerVideoTrackSelector.java +++ b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/mediasource/ExoPlayerVideoTrackSelector.java @@ -4,12 +4,11 @@ import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.TrackGroupArray; -import com.google.android.exoplayer2.trackselection.MappingTrackSelector; -import com.google.android.exoplayer2.trackselection.TrackSelection; +import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; import com.novoda.noplayer.ContentType; import com.novoda.noplayer.internal.exoplayer.RendererTypeRequester; -import com.novoda.noplayer.model.PlayerVideoTrack; import com.novoda.noplayer.internal.utils.Optional; +import com.novoda.noplayer.model.PlayerVideoTrack; import java.util.ArrayList; import java.util.List; @@ -19,18 +18,15 @@ public class ExoPlayerVideoTrackSelector { private final ExoPlayerTrackSelector trackSelector; - private final TrackSelection.Factory trackSelectionFactory; - public ExoPlayerVideoTrackSelector(ExoPlayerTrackSelector trackSelector, TrackSelection.Factory trackSelectionFactory) { + public ExoPlayerVideoTrackSelector(ExoPlayerTrackSelector trackSelector) { this.trackSelector = trackSelector; - this.trackSelectionFactory = trackSelectionFactory; } public boolean selectVideoTrack(PlayerVideoTrack videoTrack, RendererTypeRequester rendererTypeRequester) { TrackGroupArray trackGroups = trackSelector.trackGroups(VIDEO, rendererTypeRequester); - MappingTrackSelector.SelectionOverride selectionOverride = new MappingTrackSelector.SelectionOverride( - trackSelectionFactory, + DefaultTrackSelector.SelectionOverride selectionOverride = new DefaultTrackSelector.SelectionOverride( videoTrack.groupIndex(), videoTrack.formatIndex() ); diff --git a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/mediasource/MediaSourceFactory.java b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/mediasource/MediaSourceFactory.java index 846de59e..bf8b6af4 100644 --- a/core/src/main/java/com/novoda/noplayer/internal/exoplayer/mediasource/MediaSourceFactory.java +++ b/core/src/main/java/com/novoda/noplayer/internal/exoplayer/mediasource/MediaSourceFactory.java @@ -1,60 +1,72 @@ package com.novoda.noplayer.internal.exoplayer.mediasource; +import android.content.Context; import android.net.Uri; import android.os.Handler; import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory; -import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener; 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.dash.DashMediaSource; import com.google.android.exoplayer2.source.dash.DefaultDashChunkSource; import com.google.android.exoplayer2.source.hls.HlsMediaSource; -import com.google.android.exoplayer2.upstream.DataSource; -import com.novoda.noplayer.ContentType; +import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter; +import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; +import com.novoda.noplayer.Options; public class MediaSourceFactory { - private final DataSource.Factory mediaDataSourceFactory; + private final Context context; private final Handler handler; - public MediaSourceFactory(DataSource.Factory mediaDataSourceFactory, Handler handler) { - this.mediaDataSourceFactory = mediaDataSourceFactory; + public MediaSourceFactory(Context context, Handler handler) { + this.context = context; this.handler = handler; } - public MediaSource create(ContentType contentType, + public MediaSource create(Options options, Uri uri, - ExtractorMediaSource.EventListener eventListener, - AdaptiveMediaSourceEventListener mediaSourceEventListener) { - switch (contentType) { + MediaSourceEventListener mediaSourceEventListener, + DefaultBandwidthMeter bandwidthMeter) { + DefaultDataSourceFactory defaultDataSourceFactory = new DefaultDataSourceFactory(context, "user-agent", bandwidthMeter); + + switch (options.contentType()) { case HLS: - return new HlsMediaSource( - uri, - mediaDataSourceFactory, - handler, - mediaSourceEventListener - ); + return createHlsMediaSource(defaultDataSourceFactory, uri, mediaSourceEventListener); case H264: - DefaultExtractorsFactory extractorsFactory = new DefaultExtractorsFactory(); - return new ExtractorMediaSource( - uri, - mediaDataSourceFactory, - extractorsFactory, - handler, - eventListener - ); + return createH264MediaSource(defaultDataSourceFactory, uri, mediaSourceEventListener); case DASH: - DefaultDashChunkSource.Factory chunkSourceFactory = new DefaultDashChunkSource.Factory(mediaDataSourceFactory); - return new DashMediaSource( - uri, - mediaDataSourceFactory, - chunkSourceFactory, - handler, - mediaSourceEventListener - ); + return createDashMediaSource(defaultDataSourceFactory, uri); default: - throw new UnsupportedOperationException("Content type: " + contentType + " is not supported."); + throw new UnsupportedOperationException("Content type: " + options + " is not supported."); } } + + private MediaSource createHlsMediaSource(DefaultDataSourceFactory defaultDataSourceFactory, + Uri uri, + MediaSourceEventListener mediaSourceEventListener) { + HlsMediaSource.Factory factory = new HlsMediaSource.Factory(defaultDataSourceFactory); + HlsMediaSource hlsMediaSource = factory.createMediaSource(uri); + hlsMediaSource.addEventListener(handler, mediaSourceEventListener); + return hlsMediaSource; + } + + private MediaSource createH264MediaSource(DefaultDataSourceFactory defaultDataSourceFactory, + Uri uri, + MediaSourceEventListener mediaSourceEventListener) { + ExtractorMediaSource.Factory factory = new ExtractorMediaSource.Factory(defaultDataSourceFactory); + ExtractorMediaSource extractorMediaSource = factory + .setExtractorsFactory(new DefaultExtractorsFactory()) + .createMediaSource(uri); + extractorMediaSource.addEventListener(handler, mediaSourceEventListener); + return extractorMediaSource; + } + + private MediaSource createDashMediaSource(DefaultDataSourceFactory defaultDataSourceFactory, + Uri uri) { + DefaultDashChunkSource.Factory chunkSourceFactory = new DefaultDashChunkSource.Factory(defaultDataSourceFactory); + DashMediaSource.Factory factory = new DashMediaSource.Factory(chunkSourceFactory, defaultDataSourceFactory); + return factory.createMediaSource(uri); + } } diff --git a/core/src/test/java/com/novoda/noplayer/NoPlayerCreatorTest.java b/core/src/test/java/com/novoda/noplayer/NoPlayerCreatorTest.java index 2231c721..c8299486 100644 --- a/core/src/test/java/com/novoda/noplayer/NoPlayerCreatorTest.java +++ b/core/src/test/java/com/novoda/noplayer/NoPlayerCreatorTest.java @@ -25,14 +25,14 @@ import org.mockito.junit.MockitoRule; import static org.fest.assertions.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; -import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; @RunWith(Enclosed.class) public class NoPlayerCreatorTest { - public static abstract class Base { + public abstract static class Base { static final boolean USE_SECURE_CODEC = false; static final StreamingModularDrm STREAMING_MODULAR_DRM = mock(StreamingModularDrm.class); diff --git a/core/src/test/java/com/novoda/noplayer/internal/exoplayer/ExoPlayerFacadeTest.java b/core/src/test/java/com/novoda/noplayer/internal/exoplayer/ExoPlayerFacadeTest.java index 725cb08d..0b3c3395 100644 --- a/core/src/test/java/com/novoda/noplayer/internal/exoplayer/ExoPlayerFacadeTest.java +++ b/core/src/test/java/com/novoda/noplayer/internal/exoplayer/ExoPlayerFacadeTest.java @@ -4,13 +4,16 @@ import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.TextureView; + import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.audio.AudioAttributes; -import com.google.android.exoplayer2.drm.DefaultDrmSessionManager; +import com.google.android.exoplayer2.drm.DefaultDrmSessionEventListener; import com.google.android.exoplayer2.mediacodec.MediaCodecSelector; import com.google.android.exoplayer2.source.MediaSource; +import com.google.android.exoplayer2.source.MediaSourceEventListener; +import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter; import com.novoda.noplayer.ContentType; import com.novoda.noplayer.Options; import com.novoda.noplayer.OptionsBuilder; @@ -26,6 +29,10 @@ import com.novoda.noplayer.model.PlayerSubtitleTrack; import com.novoda.noplayer.model.PlayerVideoTrack; import com.novoda.noplayer.model.PlayerVideoTrackFixture; + +import java.util.Collections; +import java.util.List; + import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -35,10 +42,8 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; -import utils.ExceptionMatcher; -import java.util.Collections; -import java.util.List; +import utils.ExceptionMatcher; import static org.fest.assertions.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -92,11 +97,11 @@ public void whenLoadingVideo_thenAddsPlayerEventListener() { } @Test - public void whenLoadingVideo_thenSetsVideoDebugListener() { + public void whenLoadingVideo_thenSetsAnalyticsListener() { facade.loadVideo(surfaceViewHolder, drmSessionCreator, uri, OPTIONS, exoPlayerForwarder, mediaCodecSelector); - verify(exoPlayer).setVideoDebugListener(exoPlayerForwarder.videoRendererEventListener()); + verify(exoPlayer).addAnalyticsListener(exoPlayerForwarder.analyticsListener()); } @Test @@ -484,7 +489,9 @@ public abstract static class Base { @Mock DrmSessionCreator drmSessionCreator; @Mock - DefaultDrmSessionManager.EventListener drmSessionEventListener; + DefaultDrmSessionEventListener drmSessionEventListener; + @Mock + MediaSourceEventListener mediaSourceEventListener; @Mock MediaCodecSelector mediaCodecSelector; @Mock @@ -500,7 +507,8 @@ public abstract static class Base { public void setUp() { ExoPlayerCreator exoPlayerCreator = mock(ExoPlayerCreator.class); given(exoPlayerForwarder.drmSessionEventListener()).willReturn(drmSessionEventListener); - given(trackSelectorCreator.create(OPTIONS)).willReturn(trackSelector); + given(exoPlayerForwarder.mediaSourceEventListener()).willReturn(mediaSourceEventListener); + given(trackSelectorCreator.create(eq(OPTIONS), any(DefaultBandwidthMeter.class))).willReturn(trackSelector); given(exoPlayerCreator.create(drmSessionCreator, drmSessionEventListener, mediaCodecSelector, trackSelector.trackSelector())).willReturn(exoPlayer); given(rendererTypeRequesterCreator.createfrom(exoPlayer)).willReturn(rendererTypeRequester); facade = new ExoPlayerFacade( @@ -519,10 +527,10 @@ MediaSource givenMediaSource() { MediaSource mediaSource = mock(MediaSource.class); given( mediaSourceFactory.create( - OPTIONS.contentType(), - uri, - exoPlayerForwarder.extractorMediaSourceListener(), - exoPlayerForwarder.mediaSourceEventListener() + eq(OPTIONS), + eq(uri), + eq(mediaSourceEventListener), + any(DefaultBandwidthMeter.class) ) ).willReturn(mediaSource); diff --git a/core/src/test/java/com/novoda/noplayer/internal/exoplayer/mediasource/ExoPlayerAudioTrackSelectorTest.java b/core/src/test/java/com/novoda/noplayer/internal/exoplayer/mediasource/ExoPlayerAudioTrackSelectorTest.java index 8aaafb66..e80926f1 100644 --- a/core/src/test/java/com/novoda/noplayer/internal/exoplayer/mediasource/ExoPlayerAudioTrackSelectorTest.java +++ b/core/src/test/java/com/novoda/noplayer/internal/exoplayer/mediasource/ExoPlayerAudioTrackSelectorTest.java @@ -3,8 +3,7 @@ import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.TrackGroupArray; -import com.google.android.exoplayer2.trackselection.MappingTrackSelector; -import com.google.android.exoplayer2.trackselection.TrackSelection; +import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; import com.novoda.noplayer.internal.exoplayer.RendererTypeRequester; import com.novoda.noplayer.model.AudioTracks; import com.novoda.noplayer.model.PlayerAudioTrack; @@ -48,8 +47,6 @@ public class ExoPlayerAudioTrackSelectorTest { @Mock private ExoPlayerTrackSelector trackSelector; @Mock - private TrackSelection.Factory trackSelectionFactory; - @Mock private RendererTypeRequester rendererTypeRequester; private ExoPlayerAudioTrackSelector exoPlayerAudioTrackSelector; @@ -57,17 +54,16 @@ public class ExoPlayerAudioTrackSelectorTest { @Before public void setUp() { - exoPlayerAudioTrackSelector = new ExoPlayerAudioTrackSelector(trackSelector, trackSelectionFactory); + exoPlayerAudioTrackSelector = new ExoPlayerAudioTrackSelector(trackSelector); } @Test public void givenTrackSelectorContainsTracks_whenSelectingAudioTrack_thenSelectsTrack() { TrackGroupArray trackGroups = givenTrackSelectorContainsTracks(); - ArgumentCaptor argumentCaptor = whenSelectingAudioTrack(trackGroups); + ArgumentCaptor argumentCaptor = whenSelectingAudioTrack(trackGroups); - MappingTrackSelector.SelectionOverride selectionOverride = argumentCaptor.getValue(); - assertThat(selectionOverride.factory).isEqualTo(trackSelectionFactory); + DefaultTrackSelector.SelectionOverride selectionOverride = argumentCaptor.getValue(); assertThat(selectionOverride.groupIndex).isEqualTo(SECOND_GROUP); assertThat(selectionOverride.tracks).contains(THIRD_TRACK); } @@ -95,10 +91,10 @@ private TrackGroupArray givenTrackSelectorContainsTracks() { return trackGroups; } - private ArgumentCaptor whenSelectingAudioTrack(TrackGroupArray trackGroups) { + private ArgumentCaptor whenSelectingAudioTrack(TrackGroupArray trackGroups) { exoPlayerAudioTrackSelector.selectAudioTrack(AUDIO_TRACK, rendererTypeRequester); - ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(MappingTrackSelector.SelectionOverride.class); + ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(DefaultTrackSelector.SelectionOverride.class); verify(trackSelector).setSelectionOverride(eq(TrackType.AUDIO), any(RendererTypeRequester.class), eq(trackGroups), argumentCaptor.capture()); return argumentCaptor; } diff --git a/core/src/test/java/com/novoda/noplayer/internal/exoplayer/mediasource/ExoPlayerVideoTrackSelectorTest.java b/core/src/test/java/com/novoda/noplayer/internal/exoplayer/mediasource/ExoPlayerVideoTrackSelectorTest.java index 451ab014..ffbe5633 100644 --- a/core/src/test/java/com/novoda/noplayer/internal/exoplayer/mediasource/ExoPlayerVideoTrackSelectorTest.java +++ b/core/src/test/java/com/novoda/noplayer/internal/exoplayer/mediasource/ExoPlayerVideoTrackSelectorTest.java @@ -4,12 +4,12 @@ import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.TrackGroupArray; -import com.google.android.exoplayer2.trackselection.MappingTrackSelector; +import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; import com.google.android.exoplayer2.trackselection.TrackSelection; import com.novoda.noplayer.ContentType; import com.novoda.noplayer.internal.exoplayer.RendererTypeRequester; -import com.novoda.noplayer.model.PlayerVideoTrack; import com.novoda.noplayer.internal.utils.Optional; +import com.novoda.noplayer.model.PlayerVideoTrack; import java.util.Arrays; import java.util.List; @@ -75,17 +75,16 @@ public class ExoPlayerVideoTrackSelectorTest { @Before public void setUp() { - exoPlayerVideoTrackSelector = new ExoPlayerVideoTrackSelector(trackSelector, trackSelectionFactory); + exoPlayerVideoTrackSelector = new ExoPlayerVideoTrackSelector(trackSelector); } @Test public void givenTrackSelectorContainsTracks_whenSelectingVideoTrack_thenSelectsTrack() { givenTrackSelectorContainsTracks(); - ArgumentCaptor argumentCaptor = whenSelectingVideoTrack(ADDITIONAL_PLAYER_VIDEO_TRACK); + ArgumentCaptor argumentCaptor = whenSelectingVideoTrack(ADDITIONAL_PLAYER_VIDEO_TRACK); - MappingTrackSelector.SelectionOverride selectionOverride = argumentCaptor.getValue(); - assertThat(selectionOverride.factory).isEqualTo(trackSelectionFactory); + DefaultTrackSelector.SelectionOverride selectionOverride = argumentCaptor.getValue(); assertThat(selectionOverride.groupIndex).isEqualTo(FIRST_GROUP); assertThat(selectionOverride.tracks).contains(SECOND_TRACK); } @@ -126,10 +125,10 @@ private void givenTrackSelectorContainsTracks() { given(trackSelector.trackGroups(TrackType.VIDEO, rendererTypeRequester)).willReturn(trackGroups); } - private ArgumentCaptor whenSelectingVideoTrack(PlayerVideoTrack videoTrack) { + private ArgumentCaptor whenSelectingVideoTrack(PlayerVideoTrack videoTrack) { exoPlayerVideoTrackSelector.selectVideoTrack(videoTrack, rendererTypeRequester); - ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(MappingTrackSelector.SelectionOverride.class); + ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(DefaultTrackSelector.SelectionOverride.class); verify(trackSelector).setSelectionOverride(eq(TrackType.VIDEO), any(RendererTypeRequester.class), any(TrackGroupArray.class), argumentCaptor.capture()); return argumentCaptor; }