Commit fa594489 by ibaker Committed by kim-vde

Completely separate MediaSource & DrmSession EventDispatchers

PiperOrigin-RevId: 319989989
parent 4c75339e
Showing with 697 additions and 811 deletions
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.util;
/**
* Represents an operation that accepts a single input argument and returns no result. Unlike most
* other functional interfaces, Consumer is expected to operate via side-effects.
*/
public interface Consumer<T> {
/** Performs this operation on the given argument. */
void accept(T t);
}
...@@ -70,7 +70,8 @@ import java.util.Set; ...@@ -70,7 +70,8 @@ import java.util.Set;
private final IdentityHashMap<MediaPeriod, MediaSourceHolder> mediaSourceByMediaPeriod; private final IdentityHashMap<MediaPeriod, MediaSourceHolder> mediaSourceByMediaPeriod;
private final Map<Object, MediaSourceHolder> mediaSourceByUid; private final Map<Object, MediaSourceHolder> mediaSourceByUid;
private final MediaSourceListInfoRefreshListener mediaSourceListInfoListener; private final MediaSourceListInfoRefreshListener mediaSourceListInfoListener;
private final MediaSourceEventListener.EventDispatcher eventDispatcher; private final MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher;
private final DrmSessionEventListener.EventDispatcher drmEventDispatcher;
private final HashMap<MediaSourceList.MediaSourceHolder, MediaSourceAndListener> childSources; private final HashMap<MediaSourceList.MediaSourceHolder, MediaSourceAndListener> childSources;
private final Set<MediaSourceHolder> enabledMediaSourceHolders; private final Set<MediaSourceHolder> enabledMediaSourceHolders;
...@@ -98,14 +99,13 @@ import java.util.Set; ...@@ -98,14 +99,13 @@ import java.util.Set;
mediaSourceByMediaPeriod = new IdentityHashMap<>(); mediaSourceByMediaPeriod = new IdentityHashMap<>();
mediaSourceByUid = new HashMap<>(); mediaSourceByUid = new HashMap<>();
mediaSourceHolders = new ArrayList<>(); mediaSourceHolders = new ArrayList<>();
eventDispatcher = new MediaSourceEventListener.EventDispatcher(); mediaSourceEventDispatcher = new MediaSourceEventListener.EventDispatcher();
drmEventDispatcher = new DrmSessionEventListener.EventDispatcher();
childSources = new HashMap<>(); childSources = new HashMap<>();
enabledMediaSourceHolders = new HashSet<>(); enabledMediaSourceHolders = new HashSet<>();
if (analyticsCollector != null) { if (analyticsCollector != null) {
eventDispatcher.addEventListener( mediaSourceEventDispatcher.addEventListener(analyticsCollectorHandler, analyticsCollector);
analyticsCollectorHandler, analyticsCollector, MediaSourceEventListener.class); drmEventDispatcher.addEventListener(analyticsCollectorHandler, analyticsCollector);
eventDispatcher.addEventListener(
analyticsCollectorHandler, analyticsCollector, DrmSessionEventListener.class);
} }
} }
...@@ -523,10 +523,12 @@ import java.util.Set; ...@@ -523,10 +523,12 @@ import java.util.Set;
implements MediaSourceEventListener, DrmSessionEventListener { implements MediaSourceEventListener, DrmSessionEventListener {
private final MediaSourceList.MediaSourceHolder id; private final MediaSourceList.MediaSourceHolder id;
private EventDispatcher eventDispatcher; private MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher;
private DrmSessionEventListener.EventDispatcher drmEventDispatcher;
public ForwardingEventListener(MediaSourceList.MediaSourceHolder id) { public ForwardingEventListener(MediaSourceList.MediaSourceHolder id) {
eventDispatcher = MediaSourceList.this.eventDispatcher; mediaSourceEventDispatcher = MediaSourceList.this.mediaSourceEventDispatcher;
drmEventDispatcher = MediaSourceList.this.drmEventDispatcher;
this.id = id; this.id = id;
} }
...@@ -535,14 +537,14 @@ import java.util.Set; ...@@ -535,14 +537,14 @@ import java.util.Set;
@Override @Override
public void onMediaPeriodCreated(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId) { public void onMediaPeriodCreated(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId) {
if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) {
eventDispatcher.mediaPeriodCreated(); mediaSourceEventDispatcher.mediaPeriodCreated();
} }
} }
@Override @Override
public void onMediaPeriodReleased(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId) { public void onMediaPeriodReleased(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId) {
if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) {
eventDispatcher.mediaPeriodReleased(); mediaSourceEventDispatcher.mediaPeriodReleased();
} }
} }
...@@ -553,7 +555,7 @@ import java.util.Set; ...@@ -553,7 +555,7 @@ import java.util.Set;
LoadEventInfo loadEventData, LoadEventInfo loadEventData,
MediaLoadData mediaLoadData) { MediaLoadData mediaLoadData) {
if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) {
eventDispatcher.loadStarted(loadEventData, mediaLoadData); mediaSourceEventDispatcher.loadStarted(loadEventData, mediaLoadData);
} }
} }
...@@ -564,7 +566,7 @@ import java.util.Set; ...@@ -564,7 +566,7 @@ import java.util.Set;
LoadEventInfo loadEventData, LoadEventInfo loadEventData,
MediaLoadData mediaLoadData) { MediaLoadData mediaLoadData) {
if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) {
eventDispatcher.loadCompleted(loadEventData, mediaLoadData); mediaSourceEventDispatcher.loadCompleted(loadEventData, mediaLoadData);
} }
} }
...@@ -575,7 +577,7 @@ import java.util.Set; ...@@ -575,7 +577,7 @@ import java.util.Set;
LoadEventInfo loadEventData, LoadEventInfo loadEventData,
MediaLoadData mediaLoadData) { MediaLoadData mediaLoadData) {
if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) {
eventDispatcher.loadCanceled(loadEventData, mediaLoadData); mediaSourceEventDispatcher.loadCanceled(loadEventData, mediaLoadData);
} }
} }
...@@ -588,14 +590,14 @@ import java.util.Set; ...@@ -588,14 +590,14 @@ import java.util.Set;
IOException error, IOException error,
boolean wasCanceled) { boolean wasCanceled) {
if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) {
eventDispatcher.loadError(loadEventData, mediaLoadData, error, wasCanceled); mediaSourceEventDispatcher.loadError(loadEventData, mediaLoadData, error, wasCanceled);
} }
} }
@Override @Override
public void onReadingStarted(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId) { public void onReadingStarted(int windowIndex, MediaSource.MediaPeriodId mediaPeriodId) {
if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) {
eventDispatcher.readingStarted(); mediaSourceEventDispatcher.readingStarted();
} }
} }
...@@ -605,7 +607,7 @@ import java.util.Set; ...@@ -605,7 +607,7 @@ import java.util.Set;
@Nullable MediaSource.MediaPeriodId mediaPeriodId, @Nullable MediaSource.MediaPeriodId mediaPeriodId,
MediaLoadData mediaLoadData) { MediaLoadData mediaLoadData) {
if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) {
eventDispatcher.upstreamDiscarded(mediaLoadData); mediaSourceEventDispatcher.upstreamDiscarded(mediaLoadData);
} }
} }
...@@ -615,7 +617,7 @@ import java.util.Set; ...@@ -615,7 +617,7 @@ import java.util.Set;
@Nullable MediaSource.MediaPeriodId mediaPeriodId, @Nullable MediaSource.MediaPeriodId mediaPeriodId,
MediaLoadData mediaLoadData) { MediaLoadData mediaLoadData) {
if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) {
eventDispatcher.downstreamFormatChanged(mediaLoadData); mediaSourceEventDispatcher.downstreamFormatChanged(mediaLoadData);
} }
} }
...@@ -625,8 +627,7 @@ import java.util.Set; ...@@ -625,8 +627,7 @@ import java.util.Set;
public void onDrmSessionAcquired( public void onDrmSessionAcquired(
int windowIndex, @Nullable MediaSource.MediaPeriodId mediaPeriodId) { int windowIndex, @Nullable MediaSource.MediaPeriodId mediaPeriodId) {
if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) {
eventDispatcher.dispatch( drmEventDispatcher.drmSessionAcquired();
DrmSessionEventListener::onDrmSessionAcquired, DrmSessionEventListener.class);
} }
} }
...@@ -634,8 +635,7 @@ import java.util.Set; ...@@ -634,8 +635,7 @@ import java.util.Set;
public void onDrmKeysLoaded( public void onDrmKeysLoaded(
int windowIndex, @Nullable MediaSource.MediaPeriodId mediaPeriodId) { int windowIndex, @Nullable MediaSource.MediaPeriodId mediaPeriodId) {
if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) {
eventDispatcher.dispatch( drmEventDispatcher.drmKeysLoaded();
DrmSessionEventListener::onDrmKeysLoaded, DrmSessionEventListener.class);
} }
} }
...@@ -643,10 +643,7 @@ import java.util.Set; ...@@ -643,10 +643,7 @@ import java.util.Set;
public void onDrmSessionManagerError( public void onDrmSessionManagerError(
int windowIndex, @Nullable MediaSource.MediaPeriodId mediaPeriodId, Exception error) { int windowIndex, @Nullable MediaSource.MediaPeriodId mediaPeriodId, Exception error) {
if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) {
eventDispatcher.dispatch( drmEventDispatcher.drmSessionManagerError(error);
(listener, innerWindowIndex, innerMediaPeriodId) ->
listener.onDrmSessionManagerError(innerWindowIndex, innerMediaPeriodId, error),
DrmSessionEventListener.class);
} }
} }
...@@ -654,8 +651,7 @@ import java.util.Set; ...@@ -654,8 +651,7 @@ import java.util.Set;
public void onDrmKeysRestored( public void onDrmKeysRestored(
int windowIndex, @Nullable MediaSource.MediaPeriodId mediaPeriodId) { int windowIndex, @Nullable MediaSource.MediaPeriodId mediaPeriodId) {
if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) {
eventDispatcher.dispatch( drmEventDispatcher.drmKeysRestored();
DrmSessionEventListener::onDrmKeysRestored, DrmSessionEventListener.class);
} }
} }
...@@ -663,8 +659,7 @@ import java.util.Set; ...@@ -663,8 +659,7 @@ import java.util.Set;
public void onDrmKeysRemoved( public void onDrmKeysRemoved(
int windowIndex, @Nullable MediaSource.MediaPeriodId mediaPeriodId) { int windowIndex, @Nullable MediaSource.MediaPeriodId mediaPeriodId) {
if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) {
eventDispatcher.dispatch( drmEventDispatcher.drmKeysRemoved();
DrmSessionEventListener::onDrmKeysRemoved, DrmSessionEventListener.class);
} }
} }
...@@ -672,8 +667,7 @@ import java.util.Set; ...@@ -672,8 +667,7 @@ import java.util.Set;
public void onDrmSessionReleased( public void onDrmSessionReleased(
int windowIndex, @Nullable MediaSource.MediaPeriodId mediaPeriodId) { int windowIndex, @Nullable MediaSource.MediaPeriodId mediaPeriodId) {
if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) {
eventDispatcher.dispatch( drmEventDispatcher.drmSessionReleased();
DrmSessionEventListener::onDrmSessionReleased, DrmSessionEventListener.class);
} }
} }
...@@ -689,12 +683,17 @@ import java.util.Set; ...@@ -689,12 +683,17 @@ import java.util.Set;
} }
} }
int windowIndex = getWindowIndexForChildWindowIndex(id, childWindowIndex); int windowIndex = getWindowIndexForChildWindowIndex(id, childWindowIndex);
if (eventDispatcher.windowIndex != windowIndex if (mediaSourceEventDispatcher.windowIndex != windowIndex
|| !Util.areEqual(eventDispatcher.mediaPeriodId, mediaPeriodId)) { || !Util.areEqual(mediaSourceEventDispatcher.mediaPeriodId, mediaPeriodId)) {
eventDispatcher = mediaSourceEventDispatcher =
MediaSourceList.this.eventDispatcher.withParameters( MediaSourceList.this.mediaSourceEventDispatcher.withParameters(
windowIndex, mediaPeriodId, /* mediaTimeOffsetMs= */ 0L); windowIndex, mediaPeriodId, /* mediaTimeOffsetMs= */ 0L);
} }
if (drmEventDispatcher.windowIndex != windowIndex
|| !Util.areEqual(drmEventDispatcher.mediaPeriodId, mediaPeriodId)) {
drmEventDispatcher =
MediaSourceList.this.drmEventDispatcher.withParameters(windowIndex, mediaPeriodId);
}
return true; return true;
} }
} }
......
...@@ -34,9 +34,9 @@ import com.google.android.exoplayer2.source.MediaLoadData; ...@@ -34,9 +34,9 @@ import com.google.android.exoplayer2.source.MediaLoadData;
import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy; import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy;
import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.LoadErrorInfo; import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy.LoadErrorInfo;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Consumer;
import com.google.android.exoplayer2.util.CopyOnWriteMultiset; import com.google.android.exoplayer2.util.CopyOnWriteMultiset;
import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.MediaSourceEventDispatcher;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
...@@ -123,7 +123,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -123,7 +123,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
private final boolean playClearSamplesWithoutKeys; private final boolean playClearSamplesWithoutKeys;
private final boolean isPlaceholderSession; private final boolean isPlaceholderSession;
private final HashMap<String, String> keyRequestParameters; private final HashMap<String, String> keyRequestParameters;
private final CopyOnWriteMultiset<MediaSourceEventDispatcher> eventDispatchers; private final CopyOnWriteMultiset<DrmSessionEventListener.EventDispatcher> eventDispatchers;
private final LoadErrorHandlingPolicy loadErrorHandlingPolicy; private final LoadErrorHandlingPolicy loadErrorHandlingPolicy;
/* package */ final MediaDrmCallback callback; /* package */ final MediaDrmCallback callback;
...@@ -271,7 +271,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -271,7 +271,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
} }
@Override @Override
public void acquire(@Nullable MediaSourceEventDispatcher eventDispatcher) { public void acquire(@Nullable DrmSessionEventListener.EventDispatcher eventDispatcher) {
Assertions.checkState(referenceCount >= 0); Assertions.checkState(referenceCount >= 0);
if (eventDispatcher != null) { if (eventDispatcher != null) {
eventDispatchers.add(eventDispatcher); eventDispatchers.add(eventDispatcher);
...@@ -288,14 +288,13 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -288,14 +288,13 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
// If the session is already open then send the acquire event only to the provided dispatcher. // If the session is already open then send the acquire event only to the provided dispatcher.
// TODO: Add a parameter to onDrmSessionAcquired to indicate whether the session is being // TODO: Add a parameter to onDrmSessionAcquired to indicate whether the session is being
// re-used or not. // re-used or not.
eventDispatcher.dispatch( eventDispatcher.drmSessionAcquired();
DrmSessionEventListener::onDrmSessionAcquired, DrmSessionEventListener.class);
} }
referenceCountListener.onReferenceCountIncremented(this, referenceCount); referenceCountListener.onReferenceCountIncremented(this, referenceCount);
} }
@Override @Override
public void release(@Nullable MediaSourceEventDispatcher eventDispatcher) { public void release(@Nullable DrmSessionEventListener.EventDispatcher eventDispatcher) {
if (--referenceCount == 0) { if (--referenceCount == 0) {
// Assigning null to various non-null variables for clean-up. // Assigning null to various non-null variables for clean-up.
state = STATE_RELEASED; state = STATE_RELEASED;
...@@ -312,14 +311,13 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -312,14 +311,13 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
mediaDrm.closeSession(sessionId); mediaDrm.closeSession(sessionId);
sessionId = null; sessionId = null;
} }
dispatchEvent(DrmSessionEventListener::onDrmSessionReleased); dispatchEvent(DrmSessionEventListener.EventDispatcher::drmSessionReleased);
} }
if (eventDispatcher != null) { if (eventDispatcher != null) {
if (isOpen()) { if (isOpen()) {
// If the session is still open then send the release event only to the provided dispatcher // If the session is still open then send the release event only to the provided dispatcher
// before removing it. // before removing it.
eventDispatcher.dispatch( eventDispatcher.drmSessionReleased();
DrmSessionEventListener::onDrmSessionReleased, DrmSessionEventListener.class);
} }
eventDispatchers.remove(eventDispatcher); eventDispatchers.remove(eventDispatcher);
} }
...@@ -345,7 +343,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -345,7 +343,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
try { try {
sessionId = mediaDrm.openSession(); sessionId = mediaDrm.openSession();
mediaCrypto = mediaDrm.createMediaCrypto(sessionId); mediaCrypto = mediaDrm.createMediaCrypto(sessionId);
dispatchEvent(DrmSessionEventListener::onDrmSessionAcquired); dispatchEvent(DrmSessionEventListener.EventDispatcher::drmSessionAcquired);
state = STATE_OPENED; state = STATE_OPENED;
Assertions.checkNotNull(sessionId); Assertions.checkNotNull(sessionId);
return true; return true;
...@@ -409,7 +407,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -409,7 +407,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
onError(new KeysExpiredException()); onError(new KeysExpiredException());
} else { } else {
state = STATE_OPENED_WITH_KEYS; state = STATE_OPENED_WITH_KEYS;
dispatchEvent(DrmSessionEventListener::onDrmKeysRestored); dispatchEvent(DrmSessionEventListener.EventDispatcher::drmKeysRestored);
} }
} }
break; break;
...@@ -479,7 +477,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -479,7 +477,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
byte[] responseData = (byte[]) response; byte[] responseData = (byte[]) response;
if (mode == DefaultDrmSessionManager.MODE_RELEASE) { if (mode == DefaultDrmSessionManager.MODE_RELEASE) {
mediaDrm.provideKeyResponse(Util.castNonNull(offlineLicenseKeySetId), responseData); mediaDrm.provideKeyResponse(Util.castNonNull(offlineLicenseKeySetId), responseData);
dispatchEvent(DrmSessionEventListener::onDrmKeysRemoved); dispatchEvent(DrmSessionEventListener.EventDispatcher::drmKeysRemoved);
} else { } else {
byte[] keySetId = mediaDrm.provideKeyResponse(sessionId, responseData); byte[] keySetId = mediaDrm.provideKeyResponse(sessionId, responseData);
if ((mode == DefaultDrmSessionManager.MODE_DOWNLOAD if ((mode == DefaultDrmSessionManager.MODE_DOWNLOAD
...@@ -490,7 +488,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -490,7 +488,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
offlineLicenseKeySetId = keySetId; offlineLicenseKeySetId = keySetId;
} }
state = STATE_OPENED_WITH_KEYS; state = STATE_OPENED_WITH_KEYS;
dispatchEvent(DrmSessionEventListener::onDrmKeysLoaded); dispatchEvent(DrmSessionEventListener.EventDispatcher::drmKeysLoaded);
} }
} catch (Exception e) { } catch (Exception e) {
onKeysError(e); onKeysError(e);
...@@ -514,9 +512,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -514,9 +512,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
private void onError(final Exception e) { private void onError(final Exception e) {
lastException = new DrmSessionException(e); lastException = new DrmSessionException(e);
dispatchEvent( dispatchEvent(eventDispatcher -> eventDispatcher.drmSessionManagerError(e));
(listener, windowIndex, mediaPeriodId) ->
listener.onDrmSessionManagerError(windowIndex, mediaPeriodId, e));
if (state != STATE_OPENED_WITH_KEYS) { if (state != STATE_OPENED_WITH_KEYS) {
state = STATE_ERROR; state = STATE_ERROR;
} }
...@@ -528,10 +524,9 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -528,10 +524,9 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
return state == STATE_OPENED || state == STATE_OPENED_WITH_KEYS; return state == STATE_OPENED || state == STATE_OPENED_WITH_KEYS;
} }
private void dispatchEvent( private void dispatchEvent(Consumer<DrmSessionEventListener.EventDispatcher> event) {
MediaSourceEventDispatcher.EventWithPeriodId<DrmSessionEventListener> event) { for (DrmSessionEventListener.EventDispatcher eventDispatcher : eventDispatchers.elementSet()) {
for (MediaSourceEventDispatcher eventDispatcher : eventDispatchers.elementSet()) { event.accept(eventDispatcher);
eventDispatcher.dispatch(event, DrmSessionEventListener.class);
} }
} }
......
...@@ -32,7 +32,6 @@ import com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy; ...@@ -32,7 +32,6 @@ import com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy;
import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy; import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.MediaSourceEventDispatcher;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
...@@ -406,8 +405,8 @@ public class DefaultDrmSessionManager implements DrmSessionManager { ...@@ -406,8 +405,8 @@ public class DefaultDrmSessionManager implements DrmSessionManager {
/** /**
* Sets the mode, which determines the role of sessions acquired from the instance. This must be * Sets the mode, which determines the role of sessions acquired from the instance. This must be
* called before {@link #acquireSession(Looper, MediaSourceEventDispatcher, DrmInitData)} or * called before {@link #acquireSession(Looper, DrmSessionEventListener.EventDispatcher,
* {@link #acquirePlaceholderSession} is called. * DrmInitData)} or {@link #acquirePlaceholderSession} is called.
* *
* <p>By default, the mode is {@link #MODE_PLAYBACK} and a streaming license is requested when * <p>By default, the mode is {@link #MODE_PLAYBACK} and a streaming license is requested when
* required. * required.
...@@ -527,7 +526,7 @@ public class DefaultDrmSessionManager implements DrmSessionManager { ...@@ -527,7 +526,7 @@ public class DefaultDrmSessionManager implements DrmSessionManager {
@Override @Override
public DrmSession acquireSession( public DrmSession acquireSession(
Looper playbackLooper, Looper playbackLooper,
@Nullable MediaSourceEventDispatcher eventDispatcher, @Nullable DrmSessionEventListener.EventDispatcher eventDispatcher,
DrmInitData drmInitData) { DrmInitData drmInitData) {
initPlaybackLooper(playbackLooper); initPlaybackLooper(playbackLooper);
maybeCreateMediaDrmHandler(playbackLooper); maybeCreateMediaDrmHandler(playbackLooper);
...@@ -538,10 +537,7 @@ public class DefaultDrmSessionManager implements DrmSessionManager { ...@@ -538,10 +537,7 @@ public class DefaultDrmSessionManager implements DrmSessionManager {
if (schemeDatas.isEmpty()) { if (schemeDatas.isEmpty()) {
final MissingSchemeDataException error = new MissingSchemeDataException(uuid); final MissingSchemeDataException error = new MissingSchemeDataException(uuid);
if (eventDispatcher != null) { if (eventDispatcher != null) {
eventDispatcher.dispatch( eventDispatcher.drmSessionManagerError(error);
(listener, windowIndex, mediaPeriodId) ->
listener.onDrmSessionManagerError(windowIndex, mediaPeriodId, error),
DrmSessionEventListener.class);
} }
return new ErrorStateDrmSession(new DrmSessionException(error)); return new ErrorStateDrmSession(new DrmSessionException(error));
} }
...@@ -605,7 +601,7 @@ public class DefaultDrmSessionManager implements DrmSessionManager { ...@@ -605,7 +601,7 @@ public class DefaultDrmSessionManager implements DrmSessionManager {
private DefaultDrmSession createAndAcquireSessionWithRetry( private DefaultDrmSession createAndAcquireSessionWithRetry(
@Nullable List<SchemeData> schemeDatas, @Nullable List<SchemeData> schemeDatas,
boolean isPlaceholderSession, boolean isPlaceholderSession,
@Nullable MediaSourceEventDispatcher eventDispatcher) { @Nullable DrmSessionEventListener.EventDispatcher eventDispatcher) {
DefaultDrmSession session = DefaultDrmSession session =
createAndAcquireSession(schemeDatas, isPlaceholderSession, eventDispatcher); createAndAcquireSession(schemeDatas, isPlaceholderSession, eventDispatcher);
if (session.getState() == DrmSession.STATE_ERROR if (session.getState() == DrmSession.STATE_ERROR
...@@ -644,7 +640,7 @@ public class DefaultDrmSessionManager implements DrmSessionManager { ...@@ -644,7 +640,7 @@ public class DefaultDrmSessionManager implements DrmSessionManager {
private DefaultDrmSession createAndAcquireSession( private DefaultDrmSession createAndAcquireSession(
@Nullable List<SchemeData> schemeDatas, @Nullable List<SchemeData> schemeDatas,
boolean isPlaceholderSession, boolean isPlaceholderSession,
@Nullable MediaSourceEventDispatcher eventDispatcher) { @Nullable DrmSessionEventListener.EventDispatcher eventDispatcher) {
Assertions.checkNotNull(exoMediaDrm); Assertions.checkNotNull(exoMediaDrm);
// Placeholder sessions should always play clear samples without keys. // Placeholder sessions should always play clear samples without keys.
boolean playClearSamplesWithoutKeys = this.playClearSamplesWithoutKeys | isPlaceholderSession; boolean playClearSamplesWithoutKeys = this.playClearSamplesWithoutKeys | isPlaceholderSession;
......
...@@ -18,7 +18,6 @@ package com.google.android.exoplayer2.drm; ...@@ -18,7 +18,6 @@ package com.google.android.exoplayer2.drm;
import android.media.MediaDrm; import android.media.MediaDrm;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.util.MediaSourceEventDispatcher;
import java.io.IOException; import java.io.IOException;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
...@@ -31,10 +30,10 @@ public interface DrmSession { ...@@ -31,10 +30,10 @@ public interface DrmSession {
/** /**
* Acquires {@code newSession} then releases {@code previousSession}. * Acquires {@code newSession} then releases {@code previousSession}.
* *
* <p>Invokes {@code newSession's} {@link #acquire(MediaSourceEventDispatcher)} and {@code * <p>Invokes {@code newSession's} {@link #acquire(DrmSessionEventListener.EventDispatcher)} and
* previousSession's} {@link #release(MediaSourceEventDispatcher)} in that order (passing {@code * {@code previousSession's} {@link #release(DrmSessionEventListener.EventDispatcher)} in that
* eventDispatcher = null}). Null arguments are ignored. Does nothing if {@code previousSession} * order (passing {@code eventDispatcher = null}). Null arguments are ignored. Does nothing if
* and {@code newSession} are the same session. * {@code previousSession} and {@code newSession} are the same session.
*/ */
static void replaceSession( static void replaceSession(
@Nullable DrmSession previousSession, @Nullable DrmSession newSession) { @Nullable DrmSession previousSession, @Nullable DrmSession newSession) {
...@@ -134,20 +133,21 @@ public interface DrmSession { ...@@ -134,20 +133,21 @@ public interface DrmSession {
/** /**
* Increments the reference count. When the caller no longer needs to use the instance, it must * Increments the reference count. When the caller no longer needs to use the instance, it must
* call {@link #release(MediaSourceEventDispatcher)} to decrement the reference count. * call {@link #release(DrmSessionEventListener.EventDispatcher)} to decrement the reference
* count.
* *
* @param eventDispatcher The {@link MediaSourceEventDispatcher} used to route DRM-related events * @param eventDispatcher The {@link DrmSessionEventListener.EventDispatcher} used to route
* dispatched from this session, or null if no event handling is needed. * DRM-related events dispatched from this session, or null if no event handling is needed.
*/ */
void acquire(@Nullable MediaSourceEventDispatcher eventDispatcher); void acquire(@Nullable DrmSessionEventListener.EventDispatcher eventDispatcher);
/** /**
* Decrements the reference count. If the reference count drops to 0 underlying resources are * Decrements the reference count. If the reference count drops to 0 underlying resources are
* released, and the instance cannot be re-used. * released, and the instance cannot be re-used.
* *
* @param eventDispatcher The {@link MediaSourceEventDispatcher} to disconnect when the session is * @param eventDispatcher The {@link DrmSessionEventListener.EventDispatcher} to disconnect when
* released (the same instance (possibly null) that was passed by the caller to {@link * the session is released (the same instance (possibly null) that was passed by the caller to
* #acquire(MediaSourceEventDispatcher)}). * {@link #acquire(DrmSessionEventListener.EventDispatcher)}).
*/ */
void release(@Nullable MediaSourceEventDispatcher eventDispatcher); void release(@Nullable DrmSessionEventListener.EventDispatcher eventDispatcher);
} }
...@@ -15,9 +15,14 @@ ...@@ -15,9 +15,14 @@
*/ */
package com.google.android.exoplayer2.drm; package com.google.android.exoplayer2.drm;
import android.os.Handler;
import android.os.Looper;
import androidx.annotation.CheckResult;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.util.Assertions;
import java.util.concurrent.CopyOnWriteArrayList;
/** Listener of {@link DrmSessionManager} events. */ /** Listener of {@link DrmSessionManager} events. */
public interface DrmSessionEventListener { public interface DrmSessionEventListener {
...@@ -78,4 +83,148 @@ public interface DrmSessionEventListener { ...@@ -78,4 +83,148 @@ public interface DrmSessionEventListener {
* @param mediaPeriodId The {@link MediaPeriodId} associated with the drm session. * @param mediaPeriodId The {@link MediaPeriodId} associated with the drm session.
*/ */
default void onDrmSessionReleased(int windowIndex, @Nullable MediaPeriodId mediaPeriodId) {} default void onDrmSessionReleased(int windowIndex, @Nullable MediaPeriodId mediaPeriodId) {}
/** Dispatches events to {@link DrmSessionEventListener DrmSessionEventListeners}. */
class EventDispatcher {
/** The timeline window index reported with the events. */
public final int windowIndex;
/** The {@link MediaPeriodId} reported with the events. */
@Nullable public final MediaPeriodId mediaPeriodId;
private final CopyOnWriteArrayList<EventDispatcher.ListenerAndHandler> listenerAndHandlers;
/** Creates an event dispatcher. */
public EventDispatcher() {
this(
/* listenerAndHandlers= */ new CopyOnWriteArrayList<>(),
/* windowIndex= */ 0,
/* mediaPeriodId= */ null);
}
private EventDispatcher(
CopyOnWriteArrayList<EventDispatcher.ListenerAndHandler> listenerAndHandlers,
int windowIndex,
@Nullable MediaPeriodId mediaPeriodId) {
this.listenerAndHandlers = listenerAndHandlers;
this.windowIndex = windowIndex;
this.mediaPeriodId = mediaPeriodId;
}
/**
* Creates a view of the event dispatcher with the provided window index and media period id.
*
* @param windowIndex The timeline window index to be reported with the events.
* @param mediaPeriodId The {@link MediaPeriodId} to be reported with the events.
* @return A view of the event dispatcher with the pre-configured parameters.
*/
@CheckResult
public EventDispatcher withParameters(int windowIndex, @Nullable MediaPeriodId mediaPeriodId) {
return new EventDispatcher(listenerAndHandlers, windowIndex, mediaPeriodId);
}
/**
* Adds a listener to the event dispatcher.
*
* @param handler A handler on the which listener events will be posted.
* @param eventListener The listener to be added.
*/
public void addEventListener(Handler handler, DrmSessionEventListener eventListener) {
Assertions.checkNotNull(handler);
Assertions.checkNotNull(eventListener);
listenerAndHandlers.add(new ListenerAndHandler(handler, eventListener));
}
/**
* Removes a listener from the event dispatcher.
*
* @param eventListener The listener to be removed.
*/
public void removeEventListener(DrmSessionEventListener eventListener) {
for (ListenerAndHandler listenerAndHandler : listenerAndHandlers) {
if (listenerAndHandler.listener == eventListener) {
listenerAndHandlers.remove(listenerAndHandler);
}
}
}
/** Dispatches {@link #onDrmSessionAcquired(int, MediaPeriodId)}. */
public void drmSessionAcquired() {
for (ListenerAndHandler listenerAndHandler : listenerAndHandlers) {
DrmSessionEventListener listener = listenerAndHandler.listener;
postOrRun(
listenerAndHandler.handler,
() -> listener.onDrmSessionAcquired(windowIndex, mediaPeriodId));
}
}
/** Dispatches {@link #onDrmKeysLoaded(int, MediaPeriodId)}. */
public void drmKeysLoaded() {
for (ListenerAndHandler listenerAndHandler : listenerAndHandlers) {
DrmSessionEventListener listener = listenerAndHandler.listener;
postOrRun(
listenerAndHandler.handler, () -> listener.onDrmKeysLoaded(windowIndex, mediaPeriodId));
}
}
/** Dispatches {@link #onDrmSessionManagerError(int, MediaPeriodId, Exception)}. */
public void drmSessionManagerError(Exception error) {
for (ListenerAndHandler listenerAndHandler : listenerAndHandlers) {
DrmSessionEventListener listener = listenerAndHandler.listener;
postOrRun(
listenerAndHandler.handler,
() -> listener.onDrmSessionManagerError(windowIndex, mediaPeriodId, error));
}
}
/** Dispatches {@link #onDrmKeysRestored(int, MediaPeriodId)}. */
public void drmKeysRestored() {
for (ListenerAndHandler listenerAndHandler : listenerAndHandlers) {
DrmSessionEventListener listener = listenerAndHandler.listener;
postOrRun(
listenerAndHandler.handler,
() -> listener.onDrmKeysRestored(windowIndex, mediaPeriodId));
}
}
/** Dispatches {@link #onDrmKeysRemoved(int, MediaPeriodId)}. */
public void drmKeysRemoved() {
for (ListenerAndHandler listenerAndHandler : listenerAndHandlers) {
DrmSessionEventListener listener = listenerAndHandler.listener;
postOrRun(
listenerAndHandler.handler,
() -> listener.onDrmKeysRemoved(windowIndex, mediaPeriodId));
}
}
/** Dispatches {@link #onDrmSessionReleased(int, MediaPeriodId)}. */
public void drmSessionReleased() {
for (ListenerAndHandler listenerAndHandler : listenerAndHandlers) {
DrmSessionEventListener listener = listenerAndHandler.listener;
postOrRun(
listenerAndHandler.handler,
() -> listener.onDrmSessionReleased(windowIndex, mediaPeriodId));
}
}
/** Dispatches {@link #onDrmSessionAcquired(int, MediaPeriodId)}. */
private static void postOrRun(Handler handler, Runnable runnable) {
if (handler.getLooper() == Looper.myLooper()) {
runnable.run();
} else {
handler.post(runnable);
}
}
private static final class ListenerAndHandler {
public Handler handler;
public DrmSessionEventListener listener;
public ListenerAndHandler(Handler handler, DrmSessionEventListener listener) {
this.handler = handler;
this.listener = listener;
}
}
}
} }
...@@ -19,7 +19,6 @@ import android.os.Looper; ...@@ -19,7 +19,6 @@ import android.os.Looper;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.drm.DrmInitData.SchemeData; import com.google.android.exoplayer2.drm.DrmInitData.SchemeData;
import com.google.android.exoplayer2.util.MediaSourceEventDispatcher;
/** Manages a DRM session. */ /** Manages a DRM session. */
public interface DrmSessionManager { public interface DrmSessionManager {
...@@ -41,7 +40,7 @@ public interface DrmSessionManager { ...@@ -41,7 +40,7 @@ public interface DrmSessionManager {
@Override @Override
public DrmSession acquireSession( public DrmSession acquireSession(
Looper playbackLooper, Looper playbackLooper,
@Nullable MediaSourceEventDispatcher eventDispatcher, @Nullable DrmSessionEventListener.EventDispatcher eventDispatcher,
DrmInitData drmInitData) { DrmInitData drmInitData) {
return new ErrorStateDrmSession( return new ErrorStateDrmSession(
new DrmSession.DrmSessionException( new DrmSession.DrmSessionException(
...@@ -83,7 +82,7 @@ public interface DrmSessionManager { ...@@ -83,7 +82,7 @@ public interface DrmSessionManager {
/** /**
* Returns a {@link DrmSession} that does not execute key requests, with an incremented reference * Returns a {@link DrmSession} that does not execute key requests, with an incremented reference
* count. When the caller no longer needs to use the instance, it must call {@link * count. When the caller no longer needs to use the instance, it must call {@link
* DrmSession#release(MediaSourceEventDispatcher)} to decrement the reference count. * DrmSession#release(DrmSessionEventListener.EventDispatcher)} to decrement the reference count.
* *
* <p>Placeholder {@link DrmSession DrmSessions} may be used to configure secure decoders for * <p>Placeholder {@link DrmSession DrmSessions} may be used to configure secure decoders for
* playback of clear content periods. This can reduce the cost of transitioning between clear and * playback of clear content periods. This can reduce the cost of transitioning between clear and
...@@ -103,18 +102,19 @@ public interface DrmSessionManager { ...@@ -103,18 +102,19 @@ public interface DrmSessionManager {
/** /**
* Returns a {@link DrmSession} for the specified {@link DrmInitData}, with an incremented * Returns a {@link DrmSession} for the specified {@link DrmInitData}, with an incremented
* reference count. When the caller no longer needs to use the instance, it must call {@link * reference count. When the caller no longer needs to use the instance, it must call {@link
* DrmSession#release(MediaSourceEventDispatcher)} to decrement the reference count. * DrmSession#release(DrmSessionEventListener.EventDispatcher)} to decrement the reference count.
* *
* @param playbackLooper The looper associated with the media playback thread. * @param playbackLooper The looper associated with the media playback thread.
* @param eventDispatcher The {@link MediaSourceEventDispatcher} used to distribute events, and * @param eventDispatcher The {@link DrmSessionEventListener.EventDispatcher} used to distribute
* passed on to {@link DrmSession#acquire(MediaSourceEventDispatcher)}. * events, and passed on to {@link
* DrmSession#acquire(DrmSessionEventListener.EventDispatcher)}.
* @param drmInitData DRM initialization data. All contained {@link SchemeData}s must contain * @param drmInitData DRM initialization data. All contained {@link SchemeData}s must contain
* non-null {@link SchemeData#data}. * non-null {@link SchemeData#data}.
* @return The DRM session. * @return The DRM session.
*/ */
DrmSession acquireSession( DrmSession acquireSession(
Looper playbackLooper, Looper playbackLooper,
@Nullable MediaSourceEventDispatcher eventDispatcher, @Nullable DrmSessionEventListener.EventDispatcher eventDispatcher,
DrmInitData drmInitData); DrmInitData drmInitData);
/** /**
......
...@@ -17,7 +17,6 @@ package com.google.android.exoplayer2.drm; ...@@ -17,7 +17,6 @@ package com.google.android.exoplayer2.drm;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.MediaSourceEventDispatcher;
import java.util.Map; import java.util.Map;
/** A {@link DrmSession} that's in a terminal error state. */ /** A {@link DrmSession} that's in a terminal error state. */
...@@ -64,12 +63,12 @@ public final class ErrorStateDrmSession implements DrmSession { ...@@ -64,12 +63,12 @@ public final class ErrorStateDrmSession implements DrmSession {
} }
@Override @Override
public void acquire(@Nullable MediaSourceEventDispatcher eventDispatcher) { public void acquire(@Nullable DrmSessionEventListener.EventDispatcher eventDispatcher) {
// Do nothing. // Do nothing.
} }
@Override @Override
public void release(@Nullable MediaSourceEventDispatcher eventDispatcher) { public void release(@Nullable DrmSessionEventListener.EventDispatcher eventDispatcher) {
// Do nothing. // Do nothing.
} }
} }
...@@ -27,7 +27,6 @@ import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException; ...@@ -27,7 +27,6 @@ import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.upstream.HttpDataSource; import com.google.android.exoplayer2.upstream.HttpDataSource;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.MediaSourceEventDispatcher;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
...@@ -40,7 +39,7 @@ public final class OfflineLicenseHelper { ...@@ -40,7 +39,7 @@ public final class OfflineLicenseHelper {
private final ConditionVariable conditionVariable; private final ConditionVariable conditionVariable;
private final DefaultDrmSessionManager drmSessionManager; private final DefaultDrmSessionManager drmSessionManager;
private final HandlerThread handlerThread; private final HandlerThread handlerThread;
private final MediaSourceEventDispatcher eventDispatcher; private final DrmSessionEventListener.EventDispatcher eventDispatcher;
/** /**
* Instantiates a new instance which uses Widevine CDM. Call {@link #release()} when the instance * Instantiates a new instance which uses Widevine CDM. Call {@link #release()} when the instance
...@@ -49,14 +48,14 @@ public final class OfflineLicenseHelper { ...@@ -49,14 +48,14 @@ public final class OfflineLicenseHelper {
* @param defaultLicenseUrl The default license URL. Used for key requests that do not specify * @param defaultLicenseUrl The default license URL. Used for key requests that do not specify
* their own license URL. * their own license URL.
* @param httpDataSourceFactory A factory from which to obtain {@link HttpDataSource} instances. * @param httpDataSourceFactory A factory from which to obtain {@link HttpDataSource} instances.
* @param eventDispatcher A {@link MediaSourceEventDispatcher} used to distribute DRM-related * @param eventDispatcher A {@link DrmSessionEventListener.EventDispatcher} used to distribute
* events. * DRM-related events.
* @return A new instance which uses Widevine CDM. * @return A new instance which uses Widevine CDM.
*/ */
public static OfflineLicenseHelper newWidevineInstance( public static OfflineLicenseHelper newWidevineInstance(
String defaultLicenseUrl, String defaultLicenseUrl,
HttpDataSource.Factory httpDataSourceFactory, HttpDataSource.Factory httpDataSourceFactory,
MediaSourceEventDispatcher eventDispatcher) { DrmSessionEventListener.EventDispatcher eventDispatcher) {
return newWidevineInstance( return newWidevineInstance(
defaultLicenseUrl, defaultLicenseUrl,
/* forceDefaultLicenseUrl= */ false, /* forceDefaultLicenseUrl= */ false,
...@@ -73,15 +72,15 @@ public final class OfflineLicenseHelper { ...@@ -73,15 +72,15 @@ public final class OfflineLicenseHelper {
* @param forceDefaultLicenseUrl Whether to use {@code defaultLicenseUrl} for key requests that * @param forceDefaultLicenseUrl Whether to use {@code defaultLicenseUrl} for key requests that
* include their own license URL. * include their own license URL.
* @param httpDataSourceFactory A factory from which to obtain {@link HttpDataSource} instances. * @param httpDataSourceFactory A factory from which to obtain {@link HttpDataSource} instances.
* @param eventDispatcher A {@link MediaSourceEventDispatcher} used to distribute DRM-related * @param eventDispatcher A {@link DrmSessionEventListener.EventDispatcher} used to distribute
* events. * DRM-related events.
* @return A new instance which uses Widevine CDM. * @return A new instance which uses Widevine CDM.
*/ */
public static OfflineLicenseHelper newWidevineInstance( public static OfflineLicenseHelper newWidevineInstance(
String defaultLicenseUrl, String defaultLicenseUrl,
boolean forceDefaultLicenseUrl, boolean forceDefaultLicenseUrl,
HttpDataSource.Factory httpDataSourceFactory, HttpDataSource.Factory httpDataSourceFactory,
MediaSourceEventDispatcher eventDispatcher) { DrmSessionEventListener.EventDispatcher eventDispatcher) {
return newWidevineInstance( return newWidevineInstance(
defaultLicenseUrl, defaultLicenseUrl,
forceDefaultLicenseUrl, forceDefaultLicenseUrl,
...@@ -100,8 +99,8 @@ public final class OfflineLicenseHelper { ...@@ -100,8 +99,8 @@ public final class OfflineLicenseHelper {
* include their own license URL. * include their own license URL.
* @param optionalKeyRequestParameters An optional map of parameters to pass as the last argument * @param optionalKeyRequestParameters An optional map of parameters to pass as the last argument
* to {@link MediaDrm#getKeyRequest}. May be null. * to {@link MediaDrm#getKeyRequest}. May be null.
* @param eventDispatcher A {@link MediaSourceEventDispatcher} used to distribute DRM-related * @param eventDispatcher A {@link DrmSessionEventListener.EventDispatcher} used to distribute
* events. * DRM-related events.
* @return A new instance which uses Widevine CDM. * @return A new instance which uses Widevine CDM.
* @see DefaultDrmSessionManager.Builder * @see DefaultDrmSessionManager.Builder
*/ */
...@@ -110,7 +109,7 @@ public final class OfflineLicenseHelper { ...@@ -110,7 +109,7 @@ public final class OfflineLicenseHelper {
boolean forceDefaultLicenseUrl, boolean forceDefaultLicenseUrl,
HttpDataSource.Factory httpDataSourceFactory, HttpDataSource.Factory httpDataSourceFactory,
@Nullable Map<String, String> optionalKeyRequestParameters, @Nullable Map<String, String> optionalKeyRequestParameters,
MediaSourceEventDispatcher eventDispatcher) { DrmSessionEventListener.EventDispatcher eventDispatcher) {
return new OfflineLicenseHelper( return new OfflineLicenseHelper(
new DefaultDrmSessionManager.Builder() new DefaultDrmSessionManager.Builder()
.setKeyRequestParameters(optionalKeyRequestParameters) .setKeyRequestParameters(optionalKeyRequestParameters)
...@@ -122,7 +121,7 @@ public final class OfflineLicenseHelper { ...@@ -122,7 +121,7 @@ public final class OfflineLicenseHelper {
/** /**
* @deprecated Use {@link #OfflineLicenseHelper(DefaultDrmSessionManager, * @deprecated Use {@link #OfflineLicenseHelper(DefaultDrmSessionManager,
* MediaSourceEventDispatcher)} instead. * DrmSessionEventListener.EventDispatcher)} instead.
*/ */
@Deprecated @Deprecated
public OfflineLicenseHelper( public OfflineLicenseHelper(
...@@ -130,7 +129,7 @@ public final class OfflineLicenseHelper { ...@@ -130,7 +129,7 @@ public final class OfflineLicenseHelper {
ExoMediaDrm.Provider mediaDrmProvider, ExoMediaDrm.Provider mediaDrmProvider,
MediaDrmCallback callback, MediaDrmCallback callback,
@Nullable Map<String, String> optionalKeyRequestParameters, @Nullable Map<String, String> optionalKeyRequestParameters,
MediaSourceEventDispatcher eventDispatcher) { DrmSessionEventListener.EventDispatcher eventDispatcher) {
this( this(
new DefaultDrmSessionManager.Builder() new DefaultDrmSessionManager.Builder()
.setUuidAndExoMediaDrmProvider(uuid, mediaDrmProvider) .setUuidAndExoMediaDrmProvider(uuid, mediaDrmProvider)
...@@ -143,12 +142,12 @@ public final class OfflineLicenseHelper { ...@@ -143,12 +142,12 @@ public final class OfflineLicenseHelper {
* Constructs an instance. Call {@link #release()} when the instance is no longer required. * Constructs an instance. Call {@link #release()} when the instance is no longer required.
* *
* @param defaultDrmSessionManager The {@link DefaultDrmSessionManager} used to download licenses. * @param defaultDrmSessionManager The {@link DefaultDrmSessionManager} used to download licenses.
* @param eventDispatcher A {@link MediaSourceEventDispatcher} used to distribute DRM-related * @param eventDispatcher A {@link DrmSessionEventListener.EventDispatcher} used to distribute
* events. * DRM-related events.
*/ */
public OfflineLicenseHelper( public OfflineLicenseHelper(
DefaultDrmSessionManager defaultDrmSessionManager, DefaultDrmSessionManager defaultDrmSessionManager,
MediaSourceEventDispatcher eventDispatcher) { DrmSessionEventListener.EventDispatcher eventDispatcher) {
this.drmSessionManager = defaultDrmSessionManager; this.drmSessionManager = defaultDrmSessionManager;
this.eventDispatcher = eventDispatcher; this.eventDispatcher = eventDispatcher;
handlerThread = new HandlerThread("ExoPlayer:OfflineLicenseHelper"); handlerThread = new HandlerThread("ExoPlayer:OfflineLicenseHelper");
...@@ -177,8 +176,7 @@ public final class OfflineLicenseHelper { ...@@ -177,8 +176,7 @@ public final class OfflineLicenseHelper {
conditionVariable.open(); conditionVariable.open();
} }
}; };
eventDispatcher.addEventListener( eventDispatcher.addEventListener(new Handler(handlerThread.getLooper()), eventListener);
new Handler(handlerThread.getLooper()), eventListener, DrmSessionEventListener.class);
} }
/** /**
......
...@@ -22,7 +22,6 @@ import com.google.android.exoplayer2.Timeline; ...@@ -22,7 +22,6 @@ import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.drm.DrmSessionEventListener; import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.upstream.TransferListener; import com.google.android.exoplayer2.upstream.TransferListener;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.MediaSourceEventDispatcher;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
...@@ -38,6 +37,7 @@ public abstract class BaseMediaSource implements MediaSource { ...@@ -38,6 +37,7 @@ public abstract class BaseMediaSource implements MediaSource {
private final ArrayList<MediaSourceCaller> mediaSourceCallers; private final ArrayList<MediaSourceCaller> mediaSourceCallers;
private final HashSet<MediaSourceCaller> enabledMediaSourceCallers; private final HashSet<MediaSourceCaller> enabledMediaSourceCallers;
private final MediaSourceEventListener.EventDispatcher eventDispatcher; private final MediaSourceEventListener.EventDispatcher eventDispatcher;
private final DrmSessionEventListener.EventDispatcher drmEventDispatcher;
@Nullable private Looper looper; @Nullable private Looper looper;
@Nullable private Timeline timeline; @Nullable private Timeline timeline;
...@@ -46,6 +46,7 @@ public abstract class BaseMediaSource implements MediaSource { ...@@ -46,6 +46,7 @@ public abstract class BaseMediaSource implements MediaSource {
mediaSourceCallers = new ArrayList<>(/* initialCapacity= */ 1); mediaSourceCallers = new ArrayList<>(/* initialCapacity= */ 1);
enabledMediaSourceCallers = new HashSet<>(/* initialCapacity= */ 1); enabledMediaSourceCallers = new HashSet<>(/* initialCapacity= */ 1);
eventDispatcher = new MediaSourceEventListener.EventDispatcher(); eventDispatcher = new MediaSourceEventListener.EventDispatcher();
drmEventDispatcher = new DrmSessionEventListener.EventDispatcher();
} }
/** /**
...@@ -127,6 +128,33 @@ public abstract class BaseMediaSource implements MediaSource { ...@@ -127,6 +128,33 @@ public abstract class BaseMediaSource implements MediaSource {
return eventDispatcher.withParameters(windowIndex, mediaPeriodId, mediaTimeOffsetMs); return eventDispatcher.withParameters(windowIndex, mediaPeriodId, mediaTimeOffsetMs);
} }
/**
* Returns a {@link DrmSessionEventListener.EventDispatcher} which dispatches all events to the
* registered listeners with the specified media period id.
*
* @param mediaPeriodId The {@link MediaPeriodId} to be reported with the events. May be null, if
* the events do not belong to a specific media period.
* @return An event dispatcher with pre-configured media period id.
*/
protected final DrmSessionEventListener.EventDispatcher createDrmEventDispatcher(
@Nullable MediaPeriodId mediaPeriodId) {
return drmEventDispatcher.withParameters(/* windowIndex= */ 0, mediaPeriodId);
}
/**
* Returns a {@link DrmSessionEventListener.EventDispatcher} which dispatches all events to the
* registered listeners with the specified window index and media period id.
*
* @param windowIndex The timeline window index to be reported with the events.
* @param mediaPeriodId The {@link MediaPeriodId} to be reported with the events. May be null, if
* the events do not belong to a specific media period.
* @return An event dispatcher with pre-configured media period id and time offset.
*/
protected final DrmSessionEventListener.EventDispatcher createDrmEventDispatcher(
int windowIndex, @Nullable MediaPeriodId mediaPeriodId) {
return drmEventDispatcher.withParameters(windowIndex, mediaPeriodId);
}
/** Returns whether the source is enabled. */ /** Returns whether the source is enabled. */
protected final boolean isEnabled() { protected final boolean isEnabled() {
return !enabledMediaSourceCallers.isEmpty(); return !enabledMediaSourceCallers.isEmpty();
...@@ -134,44 +162,22 @@ public abstract class BaseMediaSource implements MediaSource { ...@@ -134,44 +162,22 @@ public abstract class BaseMediaSource implements MediaSource {
@Override @Override
public final void addEventListener(Handler handler, MediaSourceEventListener eventListener) { public final void addEventListener(Handler handler, MediaSourceEventListener eventListener) {
addEventListenerInternal(handler, eventListener, MediaSourceEventListener.class); eventDispatcher.addEventListener(handler, eventListener);
} }
@Override @Override
public final void removeEventListener(MediaSourceEventListener eventListener) { public final void removeEventListener(MediaSourceEventListener eventListener) {
removeEventListenerInternal(eventListener, MediaSourceEventListener.class); eventDispatcher.removeEventListener(eventListener);
} }
@Override @Override
public final void addDrmEventListener(Handler handler, DrmSessionEventListener eventListener) { public final void addDrmEventListener(Handler handler, DrmSessionEventListener eventListener) {
addEventListenerInternal(handler, eventListener, DrmSessionEventListener.class); drmEventDispatcher.addEventListener(handler, eventListener);
} }
@Override @Override
public final void removeDrmEventListener(DrmSessionEventListener eventListener) { public final void removeDrmEventListener(DrmSessionEventListener eventListener) {
removeEventListenerInternal(eventListener, DrmSessionEventListener.class); drmEventDispatcher.removeEventListener(eventListener);
}
/**
* Adds a listener to the internal {@link MediaSourceEventDispatcher} with the provided type.
*
* <p>NOTE: Read the caveats on {@link MediaSourceEventDispatcher#addEventListener(Handler,
* Object, Class)} when deciding what value to pass for {@code listenerClass}.
*
* @see MediaSourceEventDispatcher#addEventListener(Handler, Object, Class)
*/
protected final <T> void addEventListenerInternal(
Handler handler, T eventListener, Class<T> listenerClass) {
eventDispatcher.addEventListener(handler, eventListener, listenerClass);
}
/**
* Removes a listener from the internal {@link MediaSourceEventDispatcher}.
*
* @see MediaSourceEventDispatcher#removeEventListener(Object, Class)
*/
protected final <T> void removeEventListenerInternal(T eventListener, Class<T> listenerClass) {
eventDispatcher.removeEventListener(eventListener, listenerClass);
} }
@Override @Override
......
...@@ -222,10 +222,12 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource { ...@@ -222,10 +222,12 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource {
implements MediaSourceEventListener, DrmSessionEventListener { implements MediaSourceEventListener, DrmSessionEventListener {
@UnknownNull private final T id; @UnknownNull private final T id;
private EventDispatcher eventDispatcher; private MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher;
private DrmSessionEventListener.EventDispatcher drmEventDispatcher;
public ForwardingEventListener(@UnknownNull T id) { public ForwardingEventListener(@UnknownNull T id) {
this.eventDispatcher = createEventDispatcher(/* mediaPeriodId= */ null); this.mediaSourceEventDispatcher = createEventDispatcher(/* mediaPeriodId= */ null);
this.drmEventDispatcher = createDrmEventDispatcher(/* mediaPeriodId= */ null);
this.id = id; this.id = id;
} }
...@@ -235,8 +237,8 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource { ...@@ -235,8 +237,8 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource {
public void onMediaPeriodCreated(int windowIndex, MediaPeriodId mediaPeriodId) { public void onMediaPeriodCreated(int windowIndex, MediaPeriodId mediaPeriodId) {
if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) {
if (shouldDispatchCreateOrReleaseEvent( if (shouldDispatchCreateOrReleaseEvent(
Assertions.checkNotNull(eventDispatcher.mediaPeriodId))) { Assertions.checkNotNull(mediaSourceEventDispatcher.mediaPeriodId))) {
eventDispatcher.mediaPeriodCreated(); mediaSourceEventDispatcher.mediaPeriodCreated();
} }
} }
} }
...@@ -245,8 +247,8 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource { ...@@ -245,8 +247,8 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource {
public void onMediaPeriodReleased(int windowIndex, MediaPeriodId mediaPeriodId) { public void onMediaPeriodReleased(int windowIndex, MediaPeriodId mediaPeriodId) {
if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) {
if (shouldDispatchCreateOrReleaseEvent( if (shouldDispatchCreateOrReleaseEvent(
Assertions.checkNotNull(eventDispatcher.mediaPeriodId))) { Assertions.checkNotNull(mediaSourceEventDispatcher.mediaPeriodId))) {
eventDispatcher.mediaPeriodReleased(); mediaSourceEventDispatcher.mediaPeriodReleased();
} }
} }
} }
...@@ -258,7 +260,8 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource { ...@@ -258,7 +260,8 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource {
LoadEventInfo loadEventData, LoadEventInfo loadEventData,
MediaLoadData mediaLoadData) { MediaLoadData mediaLoadData) {
if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) {
eventDispatcher.loadStarted(loadEventData, maybeUpdateMediaLoadData(mediaLoadData)); mediaSourceEventDispatcher.loadStarted(
loadEventData, maybeUpdateMediaLoadData(mediaLoadData));
} }
} }
...@@ -269,7 +272,8 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource { ...@@ -269,7 +272,8 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource {
LoadEventInfo loadEventData, LoadEventInfo loadEventData,
MediaLoadData mediaLoadData) { MediaLoadData mediaLoadData) {
if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) {
eventDispatcher.loadCompleted(loadEventData, maybeUpdateMediaLoadData(mediaLoadData)); mediaSourceEventDispatcher.loadCompleted(
loadEventData, maybeUpdateMediaLoadData(mediaLoadData));
} }
} }
...@@ -280,7 +284,8 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource { ...@@ -280,7 +284,8 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource {
LoadEventInfo loadEventData, LoadEventInfo loadEventData,
MediaLoadData mediaLoadData) { MediaLoadData mediaLoadData) {
if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) {
eventDispatcher.loadCanceled(loadEventData, maybeUpdateMediaLoadData(mediaLoadData)); mediaSourceEventDispatcher.loadCanceled(
loadEventData, maybeUpdateMediaLoadData(mediaLoadData));
} }
} }
...@@ -293,7 +298,7 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource { ...@@ -293,7 +298,7 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource {
IOException error, IOException error,
boolean wasCanceled) { boolean wasCanceled) {
if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) {
eventDispatcher.loadError( mediaSourceEventDispatcher.loadError(
loadEventData, maybeUpdateMediaLoadData(mediaLoadData), error, wasCanceled); loadEventData, maybeUpdateMediaLoadData(mediaLoadData), error, wasCanceled);
} }
} }
...@@ -301,7 +306,7 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource { ...@@ -301,7 +306,7 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource {
@Override @Override
public void onReadingStarted(int windowIndex, MediaPeriodId mediaPeriodId) { public void onReadingStarted(int windowIndex, MediaPeriodId mediaPeriodId) {
if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) {
eventDispatcher.readingStarted(); mediaSourceEventDispatcher.readingStarted();
} }
} }
...@@ -309,7 +314,7 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource { ...@@ -309,7 +314,7 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource {
public void onUpstreamDiscarded( public void onUpstreamDiscarded(
int windowIndex, @Nullable MediaPeriodId mediaPeriodId, MediaLoadData mediaLoadData) { int windowIndex, @Nullable MediaPeriodId mediaPeriodId, MediaLoadData mediaLoadData) {
if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) {
eventDispatcher.upstreamDiscarded(maybeUpdateMediaLoadData(mediaLoadData)); mediaSourceEventDispatcher.upstreamDiscarded(maybeUpdateMediaLoadData(mediaLoadData));
} }
} }
...@@ -317,7 +322,7 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource { ...@@ -317,7 +322,7 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource {
public void onDownstreamFormatChanged( public void onDownstreamFormatChanged(
int windowIndex, @Nullable MediaPeriodId mediaPeriodId, MediaLoadData mediaLoadData) { int windowIndex, @Nullable MediaPeriodId mediaPeriodId, MediaLoadData mediaLoadData) {
if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) {
eventDispatcher.downstreamFormatChanged(maybeUpdateMediaLoadData(mediaLoadData)); mediaSourceEventDispatcher.downstreamFormatChanged(maybeUpdateMediaLoadData(mediaLoadData));
} }
} }
...@@ -326,16 +331,14 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource { ...@@ -326,16 +331,14 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource {
@Override @Override
public void onDrmSessionAcquired(int windowIndex, @Nullable MediaPeriodId mediaPeriodId) { public void onDrmSessionAcquired(int windowIndex, @Nullable MediaPeriodId mediaPeriodId) {
if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) {
eventDispatcher.dispatch( drmEventDispatcher.drmSessionAcquired();
DrmSessionEventListener::onDrmSessionAcquired, DrmSessionEventListener.class);
} }
} }
@Override @Override
public void onDrmKeysLoaded(int windowIndex, @Nullable MediaPeriodId mediaPeriodId) { public void onDrmKeysLoaded(int windowIndex, @Nullable MediaPeriodId mediaPeriodId) {
if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) {
eventDispatcher.dispatch( drmEventDispatcher.drmKeysLoaded();
DrmSessionEventListener::onDrmKeysLoaded, DrmSessionEventListener.class);
} }
} }
...@@ -343,34 +346,28 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource { ...@@ -343,34 +346,28 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource {
public void onDrmSessionManagerError( public void onDrmSessionManagerError(
int windowIndex, @Nullable MediaPeriodId mediaPeriodId, Exception error) { int windowIndex, @Nullable MediaPeriodId mediaPeriodId, Exception error) {
if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) {
eventDispatcher.dispatch( drmEventDispatcher.drmSessionManagerError(error);
(listener, innerWindowIndex, innerMediaPeriodId) ->
listener.onDrmSessionManagerError(innerWindowIndex, innerMediaPeriodId, error),
DrmSessionEventListener.class);
} }
} }
@Override @Override
public void onDrmKeysRestored(int windowIndex, @Nullable MediaPeriodId mediaPeriodId) { public void onDrmKeysRestored(int windowIndex, @Nullable MediaPeriodId mediaPeriodId) {
if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) {
eventDispatcher.dispatch( drmEventDispatcher.drmKeysRestored();
DrmSessionEventListener::onDrmKeysRestored, DrmSessionEventListener.class);
} }
} }
@Override @Override
public void onDrmKeysRemoved(int windowIndex, @Nullable MediaPeriodId mediaPeriodId) { public void onDrmKeysRemoved(int windowIndex, @Nullable MediaPeriodId mediaPeriodId) {
if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) {
eventDispatcher.dispatch( drmEventDispatcher.drmKeysRemoved();
DrmSessionEventListener::onDrmKeysRemoved, DrmSessionEventListener.class);
} }
} }
@Override @Override
public void onDrmSessionReleased(int windowIndex, @Nullable MediaPeriodId mediaPeriodId) { public void onDrmSessionReleased(int windowIndex, @Nullable MediaPeriodId mediaPeriodId) {
if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) {
eventDispatcher.dispatch( drmEventDispatcher.drmSessionReleased();
DrmSessionEventListener::onDrmSessionReleased, DrmSessionEventListener.class);
} }
} }
...@@ -386,11 +383,15 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource { ...@@ -386,11 +383,15 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource {
} }
} }
int windowIndex = getWindowIndexForChildWindowIndex(id, childWindowIndex); int windowIndex = getWindowIndexForChildWindowIndex(id, childWindowIndex);
if (eventDispatcher.windowIndex != windowIndex if (mediaSourceEventDispatcher.windowIndex != windowIndex
|| !Util.areEqual(eventDispatcher.mediaPeriodId, mediaPeriodId)) { || !Util.areEqual(mediaSourceEventDispatcher.mediaPeriodId, mediaPeriodId)) {
eventDispatcher = mediaSourceEventDispatcher =
createEventDispatcher(windowIndex, mediaPeriodId, /* mediaTimeOffsetMs= */ 0); createEventDispatcher(windowIndex, mediaPeriodId, /* mediaTimeOffsetMs= */ 0);
} }
if (drmEventDispatcher.windowIndex != windowIndex
|| !Util.areEqual(drmEventDispatcher.mediaPeriodId, mediaPeriodId)) {
drmEventDispatcher = createDrmEventDispatcher(windowIndex, mediaPeriodId);
}
return true; return true;
} }
......
...@@ -24,6 +24,7 @@ import com.google.android.exoplayer2.FormatHolder; ...@@ -24,6 +24,7 @@ import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.ParserException; import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.SeekParameters; import com.google.android.exoplayer2.SeekParameters;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.extractor.Extractor; import com.google.android.exoplayer2.extractor.Extractor;
import com.google.android.exoplayer2.extractor.ExtractorOutput; import com.google.android.exoplayer2.extractor.ExtractorOutput;
...@@ -35,7 +36,6 @@ import com.google.android.exoplayer2.extractor.SeekMap.Unseekable; ...@@ -35,7 +36,6 @@ import com.google.android.exoplayer2.extractor.SeekMap.Unseekable;
import com.google.android.exoplayer2.extractor.TrackOutput; import com.google.android.exoplayer2.extractor.TrackOutput;
import com.google.android.exoplayer2.metadata.Metadata; import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.metadata.icy.IcyHeaders; import com.google.android.exoplayer2.metadata.icy.IcyHeaders;
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
import com.google.android.exoplayer2.source.SampleQueue.UpstreamFormatChangedListener; import com.google.android.exoplayer2.source.SampleQueue.UpstreamFormatChangedListener;
import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
...@@ -101,7 +101,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -101,7 +101,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
private final DataSource dataSource; private final DataSource dataSource;
private final DrmSessionManager drmSessionManager; private final DrmSessionManager drmSessionManager;
private final LoadErrorHandlingPolicy loadErrorHandlingPolicy; private final LoadErrorHandlingPolicy loadErrorHandlingPolicy;
private final EventDispatcher eventDispatcher; private final MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher;
private final DrmSessionEventListener.EventDispatcher drmEventDispatcher;
private final Listener listener; private final Listener listener;
private final Allocator allocator; private final Allocator allocator;
@Nullable private final String customCacheKey; @Nullable private final String customCacheKey;
...@@ -145,8 +146,11 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -145,8 +146,11 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
* @param uri The {@link Uri} of the media stream. * @param uri The {@link Uri} of the media stream.
* @param dataSource The data source to read the media. * @param dataSource The data source to read the media.
* @param extractorsFactory The {@link ExtractorsFactory} to use to read the data source. * @param extractorsFactory The {@link ExtractorsFactory} to use to read the data source.
* @param drmSessionManager A {@link DrmSessionManager} to allow DRM interactions.
* @param drmEventDispatcher A dispatcher to notify of {@link DrmSessionEventListener} events.
* @param loadErrorHandlingPolicy The {@link LoadErrorHandlingPolicy}. * @param loadErrorHandlingPolicy The {@link LoadErrorHandlingPolicy}.
* @param eventDispatcher A dispatcher to notify of events. * @param mediaSourceEventDispatcher A dispatcher to notify of {@link MediaSourceEventListener}
* events.
* @param listener A listener to notify when information about the period changes. * @param listener A listener to notify when information about the period changes.
* @param allocator An {@link Allocator} from which to obtain media buffer allocations. * @param allocator An {@link Allocator} from which to obtain media buffer allocations.
* @param customCacheKey A custom key that uniquely identifies the original stream. Used for cache * @param customCacheKey A custom key that uniquely identifies the original stream. Used for cache
...@@ -164,8 +168,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -164,8 +168,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
DataSource dataSource, DataSource dataSource,
ExtractorsFactory extractorsFactory, ExtractorsFactory extractorsFactory,
DrmSessionManager drmSessionManager, DrmSessionManager drmSessionManager,
DrmSessionEventListener.EventDispatcher drmEventDispatcher,
LoadErrorHandlingPolicy loadErrorHandlingPolicy, LoadErrorHandlingPolicy loadErrorHandlingPolicy,
EventDispatcher eventDispatcher, MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher,
Listener listener, Listener listener,
Allocator allocator, Allocator allocator,
@Nullable String customCacheKey, @Nullable String customCacheKey,
...@@ -173,8 +178,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -173,8 +178,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
this.uri = uri; this.uri = uri;
this.dataSource = dataSource; this.dataSource = dataSource;
this.drmSessionManager = drmSessionManager; this.drmSessionManager = drmSessionManager;
this.drmEventDispatcher = drmEventDispatcher;
this.loadErrorHandlingPolicy = loadErrorHandlingPolicy; this.loadErrorHandlingPolicy = loadErrorHandlingPolicy;
this.eventDispatcher = eventDispatcher; this.mediaSourceEventDispatcher = mediaSourceEventDispatcher;
this.listener = listener; this.listener = listener;
this.allocator = allocator; this.allocator = allocator;
this.customCacheKey = customCacheKey; this.customCacheKey = customCacheKey;
...@@ -199,7 +205,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -199,7 +205,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
length = C.LENGTH_UNSET; length = C.LENGTH_UNSET;
durationUs = C.TIME_UNSET; durationUs = C.TIME_UNSET;
dataType = C.DATA_TYPE_MEDIA; dataType = C.DATA_TYPE_MEDIA;
eventDispatcher.mediaPeriodCreated(); mediaSourceEventDispatcher.mediaPeriodCreated();
} }
public void release() { public void release() {
...@@ -214,7 +220,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -214,7 +220,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
handler.removeCallbacksAndMessages(null); handler.removeCallbacksAndMessages(null);
callback = null; callback = null;
released = true; released = true;
eventDispatcher.mediaPeriodReleased(); mediaSourceEventDispatcher.mediaPeriodReleased();
} }
@Override @Override
...@@ -369,7 +375,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -369,7 +375,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
@Override @Override
public long readDiscontinuity() { public long readDiscontinuity() {
if (!notifiedReadingStarted) { if (!notifiedReadingStarted) {
eventDispatcher.readingStarted(); mediaSourceEventDispatcher.readingStarted();
notifiedReadingStarted = true; notifiedReadingStarted = true;
} }
if (notifyDiscontinuity if (notifyDiscontinuity
...@@ -510,7 +516,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -510,7 +516,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
boolean[] trackNotifiedDownstreamFormats = trackState.trackNotifiedDownstreamFormats; boolean[] trackNotifiedDownstreamFormats = trackState.trackNotifiedDownstreamFormats;
if (!trackNotifiedDownstreamFormats[track]) { if (!trackNotifiedDownstreamFormats[track]) {
Format trackFormat = trackState.tracks.get(track).getFormat(/* index= */ 0); Format trackFormat = trackState.tracks.get(track).getFormat(/* index= */ 0);
eventDispatcher.downstreamFormatChanged( mediaSourceEventDispatcher.downstreamFormatChanged(
MimeTypes.getTrackType(trackFormat.sampleMimeType), MimeTypes.getTrackType(trackFormat.sampleMimeType),
trackFormat, trackFormat,
C.SELECTION_REASON_UNKNOWN, C.SELECTION_REASON_UNKNOWN,
...@@ -566,7 +572,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -566,7 +572,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
loadDurationMs, loadDurationMs,
dataSource.getBytesRead()); dataSource.getBytesRead());
loadErrorHandlingPolicy.onLoadTaskConcluded(loadable.loadTaskId); loadErrorHandlingPolicy.onLoadTaskConcluded(loadable.loadTaskId);
eventDispatcher.loadCompleted( mediaSourceEventDispatcher.loadCompleted(
loadEventInfo, loadEventInfo,
C.DATA_TYPE_MEDIA, C.DATA_TYPE_MEDIA,
C.TRACK_TYPE_UNKNOWN, C.TRACK_TYPE_UNKNOWN,
...@@ -594,7 +600,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -594,7 +600,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
loadDurationMs, loadDurationMs,
dataSource.getBytesRead()); dataSource.getBytesRead());
loadErrorHandlingPolicy.onLoadTaskConcluded(loadable.loadTaskId); loadErrorHandlingPolicy.onLoadTaskConcluded(loadable.loadTaskId);
eventDispatcher.loadCanceled( mediaSourceEventDispatcher.loadCanceled(
loadEventInfo, loadEventInfo,
C.DATA_TYPE_MEDIA, C.DATA_TYPE_MEDIA,
C.TRACK_TYPE_UNKNOWN, C.TRACK_TYPE_UNKNOWN,
...@@ -657,7 +663,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -657,7 +663,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
} }
boolean wasCanceled = !loadErrorAction.isRetry(); boolean wasCanceled = !loadErrorAction.isRetry();
eventDispatcher.loadError( mediaSourceEventDispatcher.loadError(
loadEventInfo, loadEventInfo,
C.DATA_TYPE_MEDIA, C.DATA_TYPE_MEDIA,
C.TRACK_TYPE_UNKNOWN, C.TRACK_TYPE_UNKNOWN,
...@@ -719,7 +725,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -719,7 +725,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
allocator, allocator,
/* playbackLooper= */ handler.getLooper(), /* playbackLooper= */ handler.getLooper(),
drmSessionManager, drmSessionManager,
eventDispatcher); drmEventDispatcher);
trackOutput.setUpstreamFormatChangeListener(this); trackOutput.setUpstreamFormatChangeListener(this);
@NullableType @NullableType
TrackId[] sampleQueueTrackIds = Arrays.copyOf(this.sampleQueueTrackIds, trackCount + 1); TrackId[] sampleQueueTrackIds = Arrays.copyOf(this.sampleQueueTrackIds, trackCount + 1);
...@@ -824,7 +830,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -824,7 +830,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
loader.startLoading( loader.startLoading(
loadable, this, loadErrorHandlingPolicy.getMinimumLoadableRetryCount(dataType)); loadable, this, loadErrorHandlingPolicy.getMinimumLoadableRetryCount(dataType));
DataSpec dataSpec = loadable.dataSpec; DataSpec dataSpec = loadable.dataSpec;
eventDispatcher.loadStarted( mediaSourceEventDispatcher.loadStarted(
new LoadEventInfo(loadable.loadTaskId, dataSpec, elapsedRealtimeMs), new LoadEventInfo(loadable.loadTaskId, dataSpec, elapsedRealtimeMs),
C.DATA_TYPE_MEDIA, C.DATA_TYPE_MEDIA,
C.TRACK_TYPE_UNKNOWN, C.TRACK_TYPE_UNKNOWN,
......
...@@ -283,6 +283,7 @@ public final class ProgressiveMediaSource extends BaseMediaSource ...@@ -283,6 +283,7 @@ public final class ProgressiveMediaSource extends BaseMediaSource
dataSource, dataSource,
extractorsFactory, extractorsFactory,
drmSessionManager, drmSessionManager,
createDrmEventDispatcher(id),
loadableLoadErrorHandlingPolicy, loadableLoadErrorHandlingPolicy,
createEventDispatcher(id), createEventDispatcher(id),
this, this,
......
...@@ -26,12 +26,12 @@ import com.google.android.exoplayer2.FormatHolder; ...@@ -26,12 +26,12 @@ import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.drm.DrmInitData; import com.google.android.exoplayer2.drm.DrmInitData;
import com.google.android.exoplayer2.drm.DrmSession; import com.google.android.exoplayer2.drm.DrmSession;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.extractor.TrackOutput; import com.google.android.exoplayer2.extractor.TrackOutput;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DataReader; import com.google.android.exoplayer2.upstream.DataReader;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.MediaSourceEventDispatcher;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.ParsableByteArray;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
...@@ -59,7 +59,7 @@ public class SampleQueue implements TrackOutput { ...@@ -59,7 +59,7 @@ public class SampleQueue implements TrackOutput {
private final SampleExtrasHolder extrasHolder; private final SampleExtrasHolder extrasHolder;
private final Looper playbackLooper; private final Looper playbackLooper;
private final DrmSessionManager drmSessionManager; private final DrmSessionManager drmSessionManager;
private final MediaSourceEventDispatcher eventDispatcher; private final DrmSessionEventListener.EventDispatcher drmEventDispatcher;
@Nullable private UpstreamFormatChangedListener upstreamFormatChangeListener; @Nullable private UpstreamFormatChangedListener upstreamFormatChangeListener;
@Nullable private Format downstreamFormat; @Nullable private Format downstreamFormat;
...@@ -103,17 +103,17 @@ public class SampleQueue implements TrackOutput { ...@@ -103,17 +103,17 @@ public class SampleQueue implements TrackOutput {
* @param playbackLooper The looper associated with the media playback thread. * @param playbackLooper The looper associated with the media playback thread.
* @param drmSessionManager The {@link DrmSessionManager} to obtain {@link DrmSession DrmSessions} * @param drmSessionManager The {@link DrmSessionManager} to obtain {@link DrmSession DrmSessions}
* from. The created instance does not take ownership of this {@link DrmSessionManager}. * from. The created instance does not take ownership of this {@link DrmSessionManager}.
* @param eventDispatcher A {@link MediaSourceEventDispatcher} to notify of events related to this * @param drmEventDispatcher A {@link DrmSessionEventListener.EventDispatcher} to notify of events
* SampleQueue. * related to this SampleQueue.
*/ */
public SampleQueue( public SampleQueue(
Allocator allocator, Allocator allocator,
Looper playbackLooper, Looper playbackLooper,
DrmSessionManager drmSessionManager, DrmSessionManager drmSessionManager,
MediaSourceEventDispatcher eventDispatcher) { DrmSessionEventListener.EventDispatcher drmEventDispatcher) {
this.playbackLooper = playbackLooper; this.playbackLooper = playbackLooper;
this.drmSessionManager = drmSessionManager; this.drmSessionManager = drmSessionManager;
this.eventDispatcher = eventDispatcher; this.drmEventDispatcher = drmEventDispatcher;
sampleDataQueue = new SampleDataQueue(allocator); sampleDataQueue = new SampleDataQueue(allocator);
extrasHolder = new SampleExtrasHolder(); extrasHolder = new SampleExtrasHolder();
capacity = SAMPLE_CAPACITY_INCREMENT; capacity = SAMPLE_CAPACITY_INCREMENT;
...@@ -691,7 +691,7 @@ public class SampleQueue implements TrackOutput { ...@@ -691,7 +691,7 @@ public class SampleQueue implements TrackOutput {
private void releaseDrmSessionReferences() { private void releaseDrmSessionReferences() {
if (currentDrmSession != null) { if (currentDrmSession != null) {
currentDrmSession.release(eventDispatcher); currentDrmSession.release(drmEventDispatcher);
currentDrmSession = null; currentDrmSession = null;
// Clear downstream format to avoid violating the assumption that downstreamFormat.drmInitData // Clear downstream format to avoid violating the assumption that downstreamFormat.drmInitData
// != null implies currentSession != null // != null implies currentSession != null
...@@ -826,13 +826,13 @@ public class SampleQueue implements TrackOutput { ...@@ -826,13 +826,13 @@ public class SampleQueue implements TrackOutput {
@Nullable DrmSession previousSession = currentDrmSession; @Nullable DrmSession previousSession = currentDrmSession;
currentDrmSession = currentDrmSession =
newDrmInitData != null newDrmInitData != null
? drmSessionManager.acquireSession(playbackLooper, eventDispatcher, newDrmInitData) ? drmSessionManager.acquireSession(playbackLooper, drmEventDispatcher, newDrmInitData)
: drmSessionManager.acquirePlaceholderSession( : drmSessionManager.acquirePlaceholderSession(
playbackLooper, MimeTypes.getTrackType(newFormat.sampleMimeType)); playbackLooper, MimeTypes.getTrackType(newFormat.sampleMimeType));
outputFormatHolder.drmSession = currentDrmSession; outputFormatHolder.drmSession = currentDrmSession;
if (previousSession != null) { if (previousSession != null) {
previousSession.release(eventDispatcher); previousSession.release(drmEventDispatcher);
} }
} }
......
...@@ -23,10 +23,11 @@ import com.google.android.exoplayer2.FormatHolder; ...@@ -23,10 +23,11 @@ import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.SeekParameters; import com.google.android.exoplayer2.SeekParameters;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.drm.DrmSession; import com.google.android.exoplayer2.drm.DrmSession;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.source.LoadEventInfo; import com.google.android.exoplayer2.source.LoadEventInfo;
import com.google.android.exoplayer2.source.MediaLoadData; import com.google.android.exoplayer2.source.MediaLoadData;
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher; import com.google.android.exoplayer2.source.MediaSourceEventListener;
import com.google.android.exoplayer2.source.SampleQueue; import com.google.android.exoplayer2.source.SampleQueue;
import com.google.android.exoplayer2.source.SampleStream; import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.source.SequenceableLoader; import com.google.android.exoplayer2.source.SequenceableLoader;
...@@ -71,7 +72,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -71,7 +72,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
private final boolean[] embeddedTracksSelected; private final boolean[] embeddedTracksSelected;
private final T chunkSource; private final T chunkSource;
private final SequenceableLoader.Callback<ChunkSampleStream<T>> callback; private final SequenceableLoader.Callback<ChunkSampleStream<T>> callback;
private final EventDispatcher eventDispatcher; private final MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher;
private final LoadErrorHandlingPolicy loadErrorHandlingPolicy; private final LoadErrorHandlingPolicy loadErrorHandlingPolicy;
private final Loader loader; private final Loader loader;
private final ChunkHolder nextChunkHolder; private final ChunkHolder nextChunkHolder;
...@@ -102,8 +103,10 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -102,8 +103,10 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
* @param positionUs The position from which to start loading media. * @param positionUs The position from which to start loading media.
* @param drmSessionManager The {@link DrmSessionManager} to obtain {@link DrmSession DrmSessions} * @param drmSessionManager The {@link DrmSessionManager} to obtain {@link DrmSession DrmSessions}
* from. * from.
* @param drmEventDispatcher A dispatcher to notify of {@link DrmSessionEventListener} events.
* @param loadErrorHandlingPolicy The {@link LoadErrorHandlingPolicy}. * @param loadErrorHandlingPolicy The {@link LoadErrorHandlingPolicy}.
* @param eventDispatcher A dispatcher to notify of events. * @param mediaSourceEventDispatcher A dispatcher to notify of {@link MediaSourceEventListener}
* events.
*/ */
public ChunkSampleStream( public ChunkSampleStream(
int primaryTrackType, int primaryTrackType,
...@@ -114,14 +117,15 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -114,14 +117,15 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
Allocator allocator, Allocator allocator,
long positionUs, long positionUs,
DrmSessionManager drmSessionManager, DrmSessionManager drmSessionManager,
DrmSessionEventListener.EventDispatcher drmEventDispatcher,
LoadErrorHandlingPolicy loadErrorHandlingPolicy, LoadErrorHandlingPolicy loadErrorHandlingPolicy,
EventDispatcher eventDispatcher) { MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher) {
this.primaryTrackType = primaryTrackType; this.primaryTrackType = primaryTrackType;
this.embeddedTrackTypes = embeddedTrackTypes == null ? new int[0] : embeddedTrackTypes; this.embeddedTrackTypes = embeddedTrackTypes == null ? new int[0] : embeddedTrackTypes;
this.embeddedTrackFormats = embeddedTrackFormats == null ? new Format[0] : embeddedTrackFormats; this.embeddedTrackFormats = embeddedTrackFormats == null ? new Format[0] : embeddedTrackFormats;
this.chunkSource = chunkSource; this.chunkSource = chunkSource;
this.callback = callback; this.callback = callback;
this.eventDispatcher = eventDispatcher; this.mediaSourceEventDispatcher = mediaSourceEventDispatcher;
this.loadErrorHandlingPolicy = loadErrorHandlingPolicy; this.loadErrorHandlingPolicy = loadErrorHandlingPolicy;
loader = new Loader("Loader:ChunkSampleStream"); loader = new Loader("Loader:ChunkSampleStream");
nextChunkHolder = new ChunkHolder(); nextChunkHolder = new ChunkHolder();
...@@ -139,7 +143,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -139,7 +143,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
allocator, allocator,
/* playbackLooper= */ Assertions.checkNotNull(Looper.myLooper()), /* playbackLooper= */ Assertions.checkNotNull(Looper.myLooper()),
drmSessionManager, drmSessionManager,
eventDispatcher); drmEventDispatcher);
trackTypes[0] = primaryTrackType; trackTypes[0] = primaryTrackType;
sampleQueues[0] = primarySampleQueue; sampleQueues[0] = primarySampleQueue;
...@@ -149,7 +153,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -149,7 +153,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
allocator, allocator,
/* playbackLooper= */ Assertions.checkNotNull(Looper.myLooper()), /* playbackLooper= */ Assertions.checkNotNull(Looper.myLooper()),
DrmSessionManager.getDummyDrmSessionManager(), DrmSessionManager.getDummyDrmSessionManager(),
eventDispatcher); drmEventDispatcher);
embeddedSampleQueues[i] = sampleQueue; embeddedSampleQueues[i] = sampleQueue;
sampleQueues[i + 1] = sampleQueue; sampleQueues[i + 1] = sampleQueue;
trackTypes[i + 1] = this.embeddedTrackTypes[i]; trackTypes[i + 1] = this.embeddedTrackTypes[i];
...@@ -413,7 +417,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -413,7 +417,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
loadDurationMs, loadDurationMs,
loadable.bytesLoaded()); loadable.bytesLoaded());
loadErrorHandlingPolicy.onLoadTaskConcluded(loadable.loadTaskId); loadErrorHandlingPolicy.onLoadTaskConcluded(loadable.loadTaskId);
eventDispatcher.loadCompleted( mediaSourceEventDispatcher.loadCompleted(
loadEventInfo, loadEventInfo,
loadable.type, loadable.type,
primaryTrackType, primaryTrackType,
...@@ -438,7 +442,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -438,7 +442,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
loadDurationMs, loadDurationMs,
loadable.bytesLoaded()); loadable.bytesLoaded());
loadErrorHandlingPolicy.onLoadTaskConcluded(loadable.loadTaskId); loadErrorHandlingPolicy.onLoadTaskConcluded(loadable.loadTaskId);
eventDispatcher.loadCanceled( mediaSourceEventDispatcher.loadCanceled(
loadEventInfo, loadEventInfo,
loadable.type, loadable.type,
primaryTrackType, primaryTrackType,
...@@ -519,7 +523,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -519,7 +523,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
} }
boolean canceled = !loadErrorAction.isRetry(); boolean canceled = !loadErrorAction.isRetry();
eventDispatcher.loadError( mediaSourceEventDispatcher.loadError(
loadEventInfo, loadEventInfo,
loadable.type, loadable.type,
primaryTrackType, primaryTrackType,
...@@ -593,7 +597,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -593,7 +597,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
long elapsedRealtimeMs = long elapsedRealtimeMs =
loader.startLoading( loader.startLoading(
loadable, this, loadErrorHandlingPolicy.getMinimumLoadableRetryCount(loadable.type)); loadable, this, loadErrorHandlingPolicy.getMinimumLoadableRetryCount(loadable.type));
eventDispatcher.loadStarted( mediaSourceEventDispatcher.loadStarted(
new LoadEventInfo(loadable.loadTaskId, loadable.dataSpec, elapsedRealtimeMs), new LoadEventInfo(loadable.loadTaskId, loadable.dataSpec, elapsedRealtimeMs),
loadable.type, loadable.type,
primaryTrackType, primaryTrackType,
...@@ -648,7 +652,8 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -648,7 +652,8 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
pendingResetPositionUs = lastSeekPositionUs; pendingResetPositionUs = lastSeekPositionUs;
} }
loadingFinished = false; loadingFinished = false;
eventDispatcher.upstreamDiscarded(primaryTrackType, firstRemovedChunk.startTimeUs, endTimeUs); mediaSourceEventDispatcher.upstreamDiscarded(
primaryTrackType, firstRemovedChunk.startTimeUs, endTimeUs);
} }
// Internal methods // Internal methods
...@@ -701,8 +706,11 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -701,8 +706,11 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
BaseMediaChunk currentChunk = mediaChunks.get(mediaChunkReadIndex); BaseMediaChunk currentChunk = mediaChunks.get(mediaChunkReadIndex);
Format trackFormat = currentChunk.trackFormat; Format trackFormat = currentChunk.trackFormat;
if (!trackFormat.equals(primaryDownstreamTrackFormat)) { if (!trackFormat.equals(primaryDownstreamTrackFormat)) {
eventDispatcher.downstreamFormatChanged(primaryTrackType, trackFormat, mediaSourceEventDispatcher.downstreamFormatChanged(
currentChunk.trackSelectionReason, currentChunk.trackSelectionData, primaryTrackType,
trackFormat,
currentChunk.trackSelectionReason,
currentChunk.trackSelectionData,
currentChunk.startTimeUs); currentChunk.startTimeUs);
} }
primaryDownstreamTrackFormat = trackFormat; primaryDownstreamTrackFormat = trackFormat;
...@@ -812,7 +820,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -812,7 +820,7 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
private void maybeNotifyDownstreamFormat() { private void maybeNotifyDownstreamFormat() {
if (!notifiedDownstreamFormat) { if (!notifiedDownstreamFormat) {
eventDispatcher.downstreamFormatChanged( mediaSourceEventDispatcher.downstreamFormatChanged(
embeddedTrackTypes[index], embeddedTrackTypes[index],
embeddedTrackFormats[index], embeddedTrackFormats[index],
C.SELECTION_REASON_UNKNOWN, C.SELECTION_REASON_UNKNOWN,
......
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.util;
import android.os.Handler;
import android.os.Looper;
import androidx.annotation.CheckResult;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
/**
* Event dispatcher which forwards events to a list of registered listeners.
*
* <p>Adds the correct {@code windowIndex} and {@code mediaPeriodId} values (and {@code
* mediaTimeOffsetMs} if needed).
*
* <p>Allows listeners of any type to be registered, calls to {@link #dispatch} then provide the
* type of listener to forward to, which is used to filter the registered listeners.
*/
// TODO: Make this final when MediaSourceEventListener.EventDispatcher is deleted.
public class MediaSourceEventDispatcher {
/**
* Functional interface to send an event with {@code windowIndex} and {@code mediaPeriodId}
* attached.
*/
public interface EventWithPeriodId<T> {
/** Sends the event to a listener. */
void sendTo(T listener, int windowIndex, @Nullable MediaPeriodId mediaPeriodId);
}
/** The timeline window index reported with the events. */
public final int windowIndex;
/** The {@link MediaPeriodId} reported with the events. */
@Nullable public final MediaPeriodId mediaPeriodId;
// TODO: Make these private when MediaSourceEventListener.EventDispatcher is deleted.
protected final CopyOnWriteMultiset<ListenerInfo> listenerInfos;
// TODO: Define exactly what this means, and check it's always set correctly.
protected final long mediaTimeOffsetMs;
/** Creates an event dispatcher. */
public MediaSourceEventDispatcher() {
this(
/* listenerInfos= */ new CopyOnWriteMultiset<>(),
/* windowIndex= */ 0,
/* mediaPeriodId= */ null,
/* mediaTimeOffsetMs= */ 0);
}
protected MediaSourceEventDispatcher(
CopyOnWriteMultiset<ListenerInfo> listenerInfos,
int windowIndex,
@Nullable MediaPeriodId mediaPeriodId,
long mediaTimeOffsetMs) {
this.listenerInfos = listenerInfos;
this.windowIndex = windowIndex;
this.mediaPeriodId = mediaPeriodId;
this.mediaTimeOffsetMs = mediaTimeOffsetMs;
}
/**
* Creates a view of the event dispatcher with pre-configured window index, media period id, and
* media time offset.
*
* @param windowIndex The timeline window index to be reported with the events.
* @param mediaPeriodId The {@link MediaPeriodId} to be reported with the events.
* @param mediaTimeOffsetMs The offset to be added to all media times, in milliseconds.
* @return A view of the event dispatcher with the pre-configured parameters.
*/
@CheckResult
public MediaSourceEventDispatcher withParameters(
int windowIndex, @Nullable MediaPeriodId mediaPeriodId, long mediaTimeOffsetMs) {
return new MediaSourceEventDispatcher(
listenerInfos, windowIndex, mediaPeriodId, mediaTimeOffsetMs);
}
/**
* Adds a listener to the event dispatcher.
*
* <p>Calls to {@link #dispatch(EventWithPeriodId, Class)} will propagate to {@code eventListener}
* if the {@code listenerClass} types are equal.
*
* <p>The same listener instance can be added multiple times with different {@code listenerClass}
* values (i.e. if the instance implements multiple listener interfaces).
*
* <p>Duplicate {@code {eventListener, listenerClass}} pairs are also permitted. In this case an
* event dispatched to {@code listenerClass} will only be passed to the {@code eventListener}
* once.
*
* <p><b>NOTE</b>: This doesn't interact well with hierarchies of listener interfaces. If a
* listener is registered with a super-class type then it will only receive events dispatched
* directly to that super-class type. Similarly, if a listener is registered with a sub-class type
* then it will only receive events dispatched directly to that sub-class.
*
* @param handler A handler on the which listener events will be posted.
* @param eventListener The listener to be added.
* @param listenerClass The type used to register the listener. Can be a superclass of {@code
* eventListener}.
*/
public <T> void addEventListener(Handler handler, T eventListener, Class<T> listenerClass) {
Assertions.checkNotNull(handler);
Assertions.checkNotNull(eventListener);
listenerInfos.add(new ListenerInfo(handler, eventListener, listenerClass));
}
/**
* Removes a listener from the event dispatcher.
*
* <p>If there are duplicate registrations of {@code {eventListener, listenerClass}} this will
* only remove one (so events dispatched to {@code listenerClass} will still be passed to {@code
* eventListener}).
*
* @param eventListener The listener to be removed.
* @param listenerClass The listener type passed to {@link #addEventListener(Handler, Object,
* Class)}.
*/
public <T> void removeEventListener(T eventListener, Class<T> listenerClass) {
for (ListenerInfo listenerInfo : listenerInfos) {
if (listenerInfo.listener == eventListener
&& listenerInfo.listenerClass.equals(listenerClass)) {
listenerInfos.remove(listenerInfo);
return;
}
}
}
/** Dispatches {@code event} to all registered listeners of type {@code listenerClass}. */
@SuppressWarnings("unchecked") // The cast is gated with listenerClass.isInstance()
public <T> void dispatch(EventWithPeriodId<T> event, Class<T> listenerClass) {
for (ListenerInfo listenerInfo : listenerInfos.elementSet()) {
if (listenerInfo.listenerClass.equals(listenerClass)) {
postOrRun(
listenerInfo.handler,
() -> event.sendTo((T) listenerInfo.listener, windowIndex, mediaPeriodId));
}
}
}
private static void postOrRun(Handler handler, Runnable runnable) {
if (handler.getLooper() == Looper.myLooper()) {
runnable.run();
} else {
handler.post(runnable);
}
}
public static long adjustMediaTime(long mediaTimeUs, long mediaTimeOffsetMs) {
long mediaTimeMs = C.usToMs(mediaTimeUs);
return mediaTimeMs == C.TIME_UNSET ? C.TIME_UNSET : mediaTimeOffsetMs + mediaTimeMs;
}
/** Container class for a {@link Handler}, {@code listener} and {@code listenerClass}. */
protected static final class ListenerInfo {
public final Handler handler;
public final Object listener;
public final Class<?> listenerClass;
public ListenerInfo(Handler handler, Object listener, Class<?> listenerClass) {
this.handler = handler;
this.listener = listener;
this.listenerClass = listenerClass;
}
@Override
public boolean equals(@Nullable Object o) {
if (this == o) {
return true;
}
if (!(o instanceof ListenerInfo)) {
return false;
}
ListenerInfo that = (ListenerInfo) o;
// We deliberately only consider listener and listenerClass (and not handler) in equals() and
// hashcode() because the handler used to process the callbacks is an implementation detail.
return listener.equals(that.listener) && listenerClass.equals(that.listenerClass);
}
@Override
public int hashCode() {
int result = 31 * listener.hashCode();
return result + 31 * listenerClass.hashCode();
}
}
}
...@@ -44,6 +44,7 @@ import com.google.android.exoplayer2.Player.EventListener; ...@@ -44,6 +44,7 @@ import com.google.android.exoplayer2.Player.EventListener;
import com.google.android.exoplayer2.Timeline.Window; import com.google.android.exoplayer2.Timeline.Window;
import com.google.android.exoplayer2.analytics.AnalyticsListener; import com.google.android.exoplayer2.analytics.AnalyticsListener;
import com.google.android.exoplayer2.audio.AudioAttributes; import com.google.android.exoplayer2.audio.AudioAttributes;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.source.ClippingMediaSource; import com.google.android.exoplayer2.source.ClippingMediaSource;
import com.google.android.exoplayer2.source.CompositeMediaSource; import com.google.android.exoplayer2.source.CompositeMediaSource;
...@@ -53,7 +54,7 @@ import com.google.android.exoplayer2.source.MaskingMediaSource; ...@@ -53,7 +54,7 @@ import com.google.android.exoplayer2.source.MaskingMediaSource;
import com.google.android.exoplayer2.source.MediaPeriod; import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher; import com.google.android.exoplayer2.source.MediaSourceEventListener;
import com.google.android.exoplayer2.source.SampleStream; import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.source.SilenceMediaSource; import com.google.android.exoplayer2.source.SilenceMediaSource;
import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.TrackGroup;
...@@ -616,15 +617,17 @@ public final class ExoPlayerTest { ...@@ -616,15 +617,17 @@ public final class ExoPlayerTest {
MediaPeriodId id, MediaPeriodId id,
TrackGroupArray trackGroupArray, TrackGroupArray trackGroupArray,
Allocator allocator, Allocator allocator,
MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher,
DrmSessionManager drmSessionManager, DrmSessionManager drmSessionManager,
EventDispatcher eventDispatcher, DrmSessionEventListener.EventDispatcher drmEventDispatcher,
@Nullable TransferListener transferListener) { @Nullable TransferListener transferListener) {
FakeMediaPeriod mediaPeriod = FakeMediaPeriod mediaPeriod =
new FakeMediaPeriod( new FakeMediaPeriod(
trackGroupArray, trackGroupArray,
TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US, TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US,
eventDispatcher, mediaSourceEventDispatcher,
drmSessionManager, drmSessionManager,
drmEventDispatcher,
/* deferOnPrepared= */ false); /* deferOnPrepared= */ false);
mediaPeriod.setSeekToUsOffset(10); mediaPeriod.setSeekToUsOffset(10);
return mediaPeriod; return mediaPeriod;
...@@ -658,14 +661,15 @@ public final class ExoPlayerTest { ...@@ -658,14 +661,15 @@ public final class ExoPlayerTest {
MediaPeriodId id, MediaPeriodId id,
TrackGroupArray trackGroupArray, TrackGroupArray trackGroupArray,
Allocator allocator, Allocator allocator,
MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher,
DrmSessionManager drmSessionManager, DrmSessionManager drmSessionManager,
EventDispatcher eventDispatcher, DrmSessionEventListener.EventDispatcher drmEventDispatcher,
@Nullable TransferListener transferListener) { @Nullable TransferListener transferListener) {
FakeMediaPeriod mediaPeriod = FakeMediaPeriod mediaPeriod =
new FakeMediaPeriod( new FakeMediaPeriod(
trackGroupArray, trackGroupArray,
TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US, TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US,
eventDispatcher); mediaSourceEventDispatcher);
mediaPeriod.setDiscontinuityPositionUs(10); mediaPeriod.setDiscontinuityPositionUs(10);
return mediaPeriod; return mediaPeriod;
} }
...@@ -689,14 +693,15 @@ public final class ExoPlayerTest { ...@@ -689,14 +693,15 @@ public final class ExoPlayerTest {
MediaPeriodId id, MediaPeriodId id,
TrackGroupArray trackGroupArray, TrackGroupArray trackGroupArray,
Allocator allocator, Allocator allocator,
MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher,
DrmSessionManager drmSessionManager, DrmSessionManager drmSessionManager,
EventDispatcher eventDispatcher, DrmSessionEventListener.EventDispatcher drmEventDispatcher,
@Nullable TransferListener transferListener) { @Nullable TransferListener transferListener) {
FakeMediaPeriod mediaPeriod = FakeMediaPeriod mediaPeriod =
new FakeMediaPeriod( new FakeMediaPeriod(
trackGroupArray, trackGroupArray,
TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US, TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US,
eventDispatcher); mediaSourceEventDispatcher);
// Set a discontinuity at the position this period is supposed to start at anyway. // Set a discontinuity at the position this period is supposed to start at anyway.
mediaPeriod.setDiscontinuityPositionUs( mediaPeriod.setDiscontinuityPositionUs(
timeline.getWindow(/* windowIndex= */ 0, new Window()).positionInFirstPeriodUs); timeline.getWindow(/* windowIndex= */ 0, new Window()).positionInFirstPeriodUs);
...@@ -938,16 +943,18 @@ public final class ExoPlayerTest { ...@@ -938,16 +943,18 @@ public final class ExoPlayerTest {
MediaPeriodId id, MediaPeriodId id,
TrackGroupArray trackGroupArray, TrackGroupArray trackGroupArray,
Allocator allocator, Allocator allocator,
MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher,
DrmSessionManager drmSessionManager, DrmSessionManager drmSessionManager,
EventDispatcher eventDispatcher, DrmSessionEventListener.EventDispatcher drmEventDispatcher,
@Nullable TransferListener transferListener) { @Nullable TransferListener transferListener) {
// Defer completing preparation of the period until playback parameters have been set. // Defer completing preparation of the period until playback parameters have been set.
fakeMediaPeriodHolder[0] = fakeMediaPeriodHolder[0] =
new FakeMediaPeriod( new FakeMediaPeriod(
trackGroupArray, trackGroupArray,
TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US, TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US,
eventDispatcher, mediaSourceEventDispatcher,
drmSessionManager, drmSessionManager,
drmEventDispatcher,
/* deferOnPrepared= */ true); /* deferOnPrepared= */ true);
createPeriodCalledCountDownLatch.countDown(); createPeriodCalledCountDownLatch.countDown();
return fakeMediaPeriodHolder[0]; return fakeMediaPeriodHolder[0];
...@@ -990,16 +997,18 @@ public final class ExoPlayerTest { ...@@ -990,16 +997,18 @@ public final class ExoPlayerTest {
MediaPeriodId id, MediaPeriodId id,
TrackGroupArray trackGroupArray, TrackGroupArray trackGroupArray,
Allocator allocator, Allocator allocator,
MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher,
DrmSessionManager drmSessionManager, DrmSessionManager drmSessionManager,
EventDispatcher eventDispatcher, DrmSessionEventListener.EventDispatcher drmEventDispatcher,
@Nullable TransferListener transferListener) { @Nullable TransferListener transferListener) {
// Defer completing preparation of the period until seek has been sent. // Defer completing preparation of the period until seek has been sent.
fakeMediaPeriodHolder[0] = fakeMediaPeriodHolder[0] =
new FakeMediaPeriod( new FakeMediaPeriod(
trackGroupArray, trackGroupArray,
TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US, TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US,
eventDispatcher, mediaSourceEventDispatcher,
drmSessionManager, drmSessionManager,
drmEventDispatcher,
/* deferOnPrepared= */ true); /* deferOnPrepared= */ true);
createPeriodCalledCountDownLatch.countDown(); createPeriodCalledCountDownLatch.countDown();
return fakeMediaPeriodHolder[0]; return fakeMediaPeriodHolder[0];
...@@ -3723,13 +3732,14 @@ public final class ExoPlayerTest { ...@@ -3723,13 +3732,14 @@ public final class ExoPlayerTest {
MediaPeriodId id, MediaPeriodId id,
TrackGroupArray trackGroupArray, TrackGroupArray trackGroupArray,
Allocator allocator, Allocator allocator,
MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher,
DrmSessionManager drmSessionManager, DrmSessionManager drmSessionManager,
EventDispatcher eventDispatcher, DrmSessionEventListener.EventDispatcher drmEventDispatcher,
@Nullable TransferListener transferListener) { @Nullable TransferListener transferListener) {
return new FakeMediaPeriod( return new FakeMediaPeriod(
trackGroupArray, trackGroupArray,
TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US, TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US,
eventDispatcher) { mediaSourceEventDispatcher) {
@Override @Override
public long getBufferedPositionUs() { public long getBufferedPositionUs() {
// Pretend not to have buffered data yet. // Pretend not to have buffered data yet.
...@@ -6365,13 +6375,14 @@ public final class ExoPlayerTest { ...@@ -6365,13 +6375,14 @@ public final class ExoPlayerTest {
MediaPeriodId id, MediaPeriodId id,
TrackGroupArray trackGroupArray, TrackGroupArray trackGroupArray,
Allocator allocator, Allocator allocator,
MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher,
DrmSessionManager drmSessionManager, DrmSessionManager drmSessionManager,
EventDispatcher eventDispatcher, DrmSessionEventListener.EventDispatcher drmEventDispatcher,
@Nullable TransferListener transferListener) { @Nullable TransferListener transferListener) {
return new FakeMediaPeriod( return new FakeMediaPeriod(
trackGroupArray, trackGroupArray,
TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US, TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US,
eventDispatcher) { mediaSourceEventDispatcher) {
private final List<Allocation> allocations = new ArrayList<>(); private final List<Allocation> allocations = new ArrayList<>();
...@@ -6444,14 +6455,16 @@ public final class ExoPlayerTest { ...@@ -6444,14 +6455,16 @@ public final class ExoPlayerTest {
MediaPeriodId id, MediaPeriodId id,
TrackGroupArray trackGroupArray, TrackGroupArray trackGroupArray,
Allocator allocator, Allocator allocator,
MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher,
DrmSessionManager drmSessionManager, DrmSessionManager drmSessionManager,
EventDispatcher eventDispatcher, DrmSessionEventListener.EventDispatcher drmEventDispatcher,
@Nullable TransferListener transferListener) { @Nullable TransferListener transferListener) {
return new FakeMediaPeriod( return new FakeMediaPeriod(
trackGroupArray, trackGroupArray,
TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US, TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US,
eventDispatcher, mediaSourceEventDispatcher,
drmSessionManager, drmSessionManager,
drmEventDispatcher,
/* deferOnPrepared= */ false) { /* deferOnPrepared= */ false) {
private Loader loader = new Loader("oomLoader"); private Loader loader = new Loader("oomLoader");
...@@ -6466,13 +6479,15 @@ public final class ExoPlayerTest { ...@@ -6466,13 +6479,15 @@ public final class ExoPlayerTest {
protected SampleStream createSampleStream( protected SampleStream createSampleStream(
long positionUs, long positionUs,
TrackSelection selection, TrackSelection selection,
MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher,
DrmSessionManager drmSessionManager, DrmSessionManager drmSessionManager,
EventDispatcher eventDispatcher) { DrmSessionEventListener.EventDispatcher drmEventDispatcher) {
// Create 3 samples without end of stream signal to test that all 3 samples are // Create 3 samples without end of stream signal to test that all 3 samples are
// still played before the exception is thrown. // still played before the exception is thrown.
return new FakeSampleStream( return new FakeSampleStream(
mediaSourceEventDispatcher,
drmSessionManager, drmSessionManager,
eventDispatcher, drmEventDispatcher,
selection.getSelectedFormat(), selection.getSelectedFormat(),
ImmutableList.of( ImmutableList.of(
oneByteSample(positionUs), oneByteSample(positionUs),
......
...@@ -34,6 +34,7 @@ import com.google.android.exoplayer2.decoder.DecoderException; ...@@ -34,6 +34,7 @@ import com.google.android.exoplayer2.decoder.DecoderException;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.decoder.SimpleDecoder; import com.google.android.exoplayer2.decoder.SimpleDecoder;
import com.google.android.exoplayer2.decoder.SimpleOutputBuffer; import com.google.android.exoplayer2.decoder.SimpleOutputBuffer;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.drm.ExoMediaCrypto; import com.google.android.exoplayer2.drm.ExoMediaCrypto;
import com.google.android.exoplayer2.testutil.FakeSampleStream; import com.google.android.exoplayer2.testutil.FakeSampleStream;
...@@ -107,8 +108,9 @@ public class DecoderAudioRendererTest { ...@@ -107,8 +108,9 @@ public class DecoderAudioRendererTest {
RendererConfiguration.DEFAULT, RendererConfiguration.DEFAULT,
new Format[] {FORMAT}, new Format[] {FORMAT},
new FakeSampleStream( new FakeSampleStream(
/* mediaSourceEventDispatcher= */ null,
DrmSessionManager.DUMMY, DrmSessionManager.DUMMY,
/* eventDispatcher= */ null, new DrmSessionEventListener.EventDispatcher(),
FORMAT, FORMAT,
ImmutableList.of(END_OF_STREAM_ITEM)), ImmutableList.of(END_OF_STREAM_ITEM)),
/* positionUs= */ 0, /* positionUs= */ 0,
......
...@@ -32,6 +32,7 @@ import com.google.android.exoplayer2.C; ...@@ -32,6 +32,7 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.RendererConfiguration; import com.google.android.exoplayer2.RendererConfiguration;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.mediacodec.MediaCodecInfo; import com.google.android.exoplayer2.mediacodec.MediaCodecInfo;
import com.google.android.exoplayer2.mediacodec.MediaCodecSelector; import com.google.android.exoplayer2.mediacodec.MediaCodecSelector;
...@@ -111,8 +112,9 @@ public class MediaCodecAudioRendererTest { ...@@ -111,8 +112,9 @@ public class MediaCodecAudioRendererTest {
FakeSampleStream fakeSampleStream = FakeSampleStream fakeSampleStream =
new FakeSampleStream( new FakeSampleStream(
/* mediaSourceEventDispatcher= */ null,
DrmSessionManager.DUMMY, DrmSessionManager.DUMMY,
/* eventDispatcher= */ null, new DrmSessionEventListener.EventDispatcher(),
/* initialFormat= */ AUDIO_AAC, /* initialFormat= */ AUDIO_AAC,
ImmutableList.of( ImmutableList.of(
oneByteSample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME), oneByteSample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME),
...@@ -158,8 +160,9 @@ public class MediaCodecAudioRendererTest { ...@@ -158,8 +160,9 @@ public class MediaCodecAudioRendererTest {
FakeSampleStream fakeSampleStream = FakeSampleStream fakeSampleStream =
new FakeSampleStream( new FakeSampleStream(
/* mediaSourceEventDispatcher= */ null,
DrmSessionManager.DUMMY, DrmSessionManager.DUMMY,
/* eventDispatcher= */ null, new DrmSessionEventListener.EventDispatcher(),
/* initialFormat= */ AUDIO_AAC, /* initialFormat= */ AUDIO_AAC,
ImmutableList.of( ImmutableList.of(
oneByteSample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME), oneByteSample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME),
...@@ -225,8 +228,9 @@ public class MediaCodecAudioRendererTest { ...@@ -225,8 +228,9 @@ public class MediaCodecAudioRendererTest {
FakeSampleStream fakeSampleStream = FakeSampleStream fakeSampleStream =
new FakeSampleStream( new FakeSampleStream(
/* mediaSourceEventDispatcher= */ null,
DrmSessionManager.DUMMY, DrmSessionManager.DUMMY,
/* eventDispatcher= */ null, new DrmSessionEventListener.EventDispatcher(),
/* initialFormat= */ AUDIO_AAC, /* initialFormat= */ AUDIO_AAC,
ImmutableList.of( ImmutableList.of(
oneByteSample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME), END_OF_STREAM_ITEM)); oneByteSample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME), END_OF_STREAM_ITEM));
......
...@@ -25,7 +25,6 @@ import android.util.Pair; ...@@ -25,7 +25,6 @@ import android.util.Pair;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.drm.DrmInitData.SchemeData; import com.google.android.exoplayer2.drm.DrmInitData.SchemeData;
import com.google.android.exoplayer2.util.MediaSourceEventDispatcher;
import java.util.HashMap; import java.util.HashMap;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
...@@ -57,7 +56,7 @@ public class OfflineLicenseHelperTest { ...@@ -57,7 +56,7 @@ public class OfflineLicenseHelperTest {
new ExoMediaDrm.AppManagedProvider(mediaDrm), new ExoMediaDrm.AppManagedProvider(mediaDrm),
mediaDrmCallback, mediaDrmCallback,
/* optionalKeyRequestParameters= */ null, /* optionalKeyRequestParameters= */ null,
new MediaSourceEventDispatcher()); new DrmSessionEventListener.EventDispatcher());
} }
@After @After
......
...@@ -22,6 +22,7 @@ import static java.nio.charset.StandardCharsets.UTF_8; ...@@ -22,6 +22,7 @@ import static java.nio.charset.StandardCharsets.UTF_8;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.metadata.emsg.EventMessage; import com.google.android.exoplayer2.metadata.emsg.EventMessage;
import com.google.android.exoplayer2.metadata.emsg.EventMessageEncoder; import com.google.android.exoplayer2.metadata.emsg.EventMessageEncoder;
...@@ -146,8 +147,9 @@ public class MetadataRendererTest { ...@@ -146,8 +147,9 @@ public class MetadataRendererTest {
renderer.replaceStream( renderer.replaceStream(
new Format[] {EMSG_FORMAT}, new Format[] {EMSG_FORMAT},
new FakeSampleStream( new FakeSampleStream(
/* mediaSourceEventDispatcher= */ null,
DrmSessionManager.DUMMY, DrmSessionManager.DUMMY,
/* eventDispatcher= */ null, new DrmSessionEventListener.EventDispatcher(),
EMSG_FORMAT, EMSG_FORMAT,
ImmutableList.of( ImmutableList.of(
FakeSampleStreamItem.sample(/* timeUs= */ 0, /* flags= */ 0, input), FakeSampleStreamItem.sample(/* timeUs= */ 0, /* flags= */ 0, input),
......
...@@ -27,11 +27,11 @@ import com.google.android.exoplayer2.Player; ...@@ -27,11 +27,11 @@ import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.Timeline.Period; import com.google.android.exoplayer2.Timeline.Period;
import com.google.android.exoplayer2.Timeline.Window; import com.google.android.exoplayer2.Timeline.Window;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.source.ClippingMediaSource.IllegalClippingException; import com.google.android.exoplayer2.source.ClippingMediaSource.IllegalClippingException;
import com.google.android.exoplayer2.source.MaskingMediaSource.DummyTimeline; import com.google.android.exoplayer2.source.MaskingMediaSource.DummyTimeline;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
import com.google.android.exoplayer2.testutil.FakeMediaPeriod; import com.google.android.exoplayer2.testutil.FakeMediaPeriod;
import com.google.android.exoplayer2.testutil.FakeMediaSource; import com.google.android.exoplayer2.testutil.FakeMediaSource;
import com.google.android.exoplayer2.testutil.FakeTimeline; import com.google.android.exoplayer2.testutil.FakeTimeline;
...@@ -569,10 +569,11 @@ public final class ClippingMediaSourceTest { ...@@ -569,10 +569,11 @@ public final class ClippingMediaSourceTest {
MediaPeriodId id, MediaPeriodId id,
TrackGroupArray trackGroupArray, TrackGroupArray trackGroupArray,
Allocator allocator, Allocator allocator,
MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher,
DrmSessionManager drmSessionManager, DrmSessionManager drmSessionManager,
EventDispatcher eventDispatcher, DrmSessionEventListener.EventDispatcher drmEventDispatcher,
@Nullable TransferListener transferListener) { @Nullable TransferListener transferListener) {
eventDispatcher.downstreamFormatChanged( mediaSourceEventDispatcher.downstreamFormatChanged(
new MediaLoadData( new MediaLoadData(
C.DATA_TYPE_MEDIA, C.DATA_TYPE_MEDIA,
C.TRACK_TYPE_UNKNOWN, C.TRACK_TYPE_UNKNOWN,
...@@ -585,8 +586,9 @@ public final class ClippingMediaSourceTest { ...@@ -585,8 +586,9 @@ public final class ClippingMediaSourceTest {
id, id,
trackGroupArray, trackGroupArray,
allocator, allocator,
mediaSourceEventDispatcher,
drmSessionManager, drmSessionManager,
eventDispatcher, drmEventDispatcher,
transferListener); transferListener);
} }
}; };
......
...@@ -24,6 +24,7 @@ import com.google.android.exoplayer2.C; ...@@ -24,6 +24,7 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.FormatHolder; import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher; import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
...@@ -200,13 +201,14 @@ public final class MergingMediaPeriodTest { ...@@ -200,13 +201,14 @@ public final class MergingMediaPeriodTest {
public FakeMediaPeriodWithSelectTracksPosition( public FakeMediaPeriodWithSelectTracksPosition(
TrackGroupArray trackGroupArray, TrackGroupArray trackGroupArray,
EventDispatcher eventDispatcher, EventDispatcher mediaSourceEventDispatcher,
TrackDataFactory trackDataFactory) { TrackDataFactory trackDataFactory) {
super( super(
trackGroupArray, trackGroupArray,
trackDataFactory, trackDataFactory,
eventDispatcher, mediaSourceEventDispatcher,
DrmSessionManager.DUMMY, DrmSessionManager.DUMMY,
new DrmSessionEventListener.EventDispatcher(),
/* deferOnPrepared= */ false); /* deferOnPrepared= */ false);
selectTracksPositionUs = C.TIME_UNSET; selectTracksPositionUs = C.TIME_UNSET;
} }
......
...@@ -22,6 +22,7 @@ import android.net.Uri; ...@@ -22,6 +22,7 @@ import android.net.Uri;
import androidx.test.core.app.ApplicationProvider; import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.extractor.Extractor; import com.google.android.exoplayer2.extractor.Extractor;
import com.google.android.exoplayer2.extractor.mp4.Mp4Extractor; import com.google.android.exoplayer2.extractor.mp4.Mp4Extractor;
...@@ -44,18 +45,18 @@ public final class ProgressiveMediaPeriodTest { ...@@ -44,18 +45,18 @@ public final class ProgressiveMediaPeriodTest {
AtomicBoolean sourceInfoRefreshCalled = new AtomicBoolean(false); AtomicBoolean sourceInfoRefreshCalled = new AtomicBoolean(false);
ProgressiveMediaPeriod.Listener sourceInfoRefreshListener = ProgressiveMediaPeriod.Listener sourceInfoRefreshListener =
(durationUs, isSeekable, isLive) -> sourceInfoRefreshCalled.set(true); (durationUs, isSeekable, isLive) -> sourceInfoRefreshCalled.set(true);
MediaPeriodId mediaPeriodId = new MediaPeriodId(/* periodUid= */ new Object());
ProgressiveMediaPeriod mediaPeriod = ProgressiveMediaPeriod mediaPeriod =
new ProgressiveMediaPeriod( new ProgressiveMediaPeriod(
Uri.parse("asset://android_asset/mp4/sample.mp4"), Uri.parse("asset://android_asset/mp4/sample.mp4"),
new AssetDataSource(ApplicationProvider.getApplicationContext()), new AssetDataSource(ApplicationProvider.getApplicationContext()),
() -> new Extractor[] {new Mp4Extractor()}, () -> new Extractor[] {new Mp4Extractor()},
DrmSessionManager.DUMMY, DrmSessionManager.DUMMY,
new DrmSessionEventListener.EventDispatcher()
.withParameters(/* windowIndex= */ 0, mediaPeriodId),
new DefaultLoadErrorHandlingPolicy(), new DefaultLoadErrorHandlingPolicy(),
new MediaSourceEventListener.EventDispatcher() new MediaSourceEventListener.EventDispatcher()
.withParameters( .withParameters(/* windowIndex= */ 0, mediaPeriodId, /* mediaTimeOffsetMs= */ 0),
/* windowIndex= */ 0,
new MediaPeriodId(/* periodUid= */ new Object()),
/* mediaTimeOffsetMs= */ 0),
sourceInfoRefreshListener, sourceInfoRefreshListener,
new DefaultAllocator(/* trimOnReset= */ true, C.DEFAULT_BUFFER_SEGMENT_SIZE), new DefaultAllocator(/* trimOnReset= */ true, C.DEFAULT_BUFFER_SEGMENT_SIZE),
/* customCacheKey= */ null, /* customCacheKey= */ null,
......
...@@ -35,13 +35,13 @@ import com.google.android.exoplayer2.FormatHolder; ...@@ -35,13 +35,13 @@ import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.drm.DrmInitData; import com.google.android.exoplayer2.drm.DrmInitData;
import com.google.android.exoplayer2.drm.DrmSession; import com.google.android.exoplayer2.drm.DrmSession;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.extractor.TrackOutput; import com.google.android.exoplayer2.extractor.TrackOutput;
import com.google.android.exoplayer2.testutil.TestUtil; import com.google.android.exoplayer2.testutil.TestUtil;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DefaultAllocator; import com.google.android.exoplayer2.upstream.DefaultAllocator;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.MediaSourceEventDispatcher;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.ParsableByteArray;
import com.google.common.primitives.Bytes; import com.google.common.primitives.Bytes;
...@@ -129,7 +129,7 @@ public final class SampleQueueTest { ...@@ -129,7 +129,7 @@ public final class SampleQueueTest {
private Allocator allocator; private Allocator allocator;
private DrmSessionManager mockDrmSessionManager; private DrmSessionManager mockDrmSessionManager;
private DrmSession mockDrmSession; private DrmSession mockDrmSession;
private MediaSourceEventDispatcher eventDispatcher; private DrmSessionEventListener.EventDispatcher eventDispatcher;
private SampleQueue sampleQueue; private SampleQueue sampleQueue;
private FormatHolder formatHolder; private FormatHolder formatHolder;
private DecoderInputBuffer inputBuffer; private DecoderInputBuffer inputBuffer;
...@@ -142,7 +142,7 @@ public final class SampleQueueTest { ...@@ -142,7 +142,7 @@ public final class SampleQueueTest {
when(mockDrmSessionManager.acquireSession( when(mockDrmSessionManager.acquireSession(
ArgumentMatchers.any(), ArgumentMatchers.any(), ArgumentMatchers.any())) ArgumentMatchers.any(), ArgumentMatchers.any(), ArgumentMatchers.any()))
.thenReturn(mockDrmSession); .thenReturn(mockDrmSession);
eventDispatcher = new MediaSourceEventDispatcher(); eventDispatcher = new DrmSessionEventListener.EventDispatcher();
sampleQueue = sampleQueue =
new SampleQueue( new SampleQueue(
allocator, allocator,
......
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.google.android.exoplayer2.util;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import android.os.Handler;
import android.os.Looper;
import androidx.annotation.Nullable;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.MediaSourceEventListener;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
/** Tests for {@link MediaSourceEventDispatcher}. */
@RunWith(AndroidJUnit4.class)
public class MediaSourceEventDispatcherTest {
private static final MediaSource.MediaPeriodId MEDIA_PERIOD_ID =
new MediaSource.MediaPeriodId("test uid");
private static final int WINDOW_INDEX = 200;
private static final int MEDIA_TIME_OFFSET_MS = 1_000;
@Rule public final MockitoRule mockito = MockitoJUnit.rule();
@Mock private MediaSourceEventListener mediaSourceEventListener;
@Mock private MediaAndDrmEventListener mediaAndDrmEventListener;
private MediaSourceEventDispatcher eventDispatcher;
@Before
public void setupEventDispatcher() {
eventDispatcher = new MediaSourceEventDispatcher();
eventDispatcher =
eventDispatcher.withParameters(WINDOW_INDEX, MEDIA_PERIOD_ID, MEDIA_TIME_OFFSET_MS);
}
@Test
public void listenerReceivesEventPopulatedWithMediaPeriodInfo() {
eventDispatcher.addEventListener(
Util.createHandlerForCurrentOrMainLooper(),
mediaSourceEventListener,
MediaSourceEventListener.class);
eventDispatcher.dispatch(
MediaSourceEventListener::onMediaPeriodCreated, MediaSourceEventListener.class);
verify(mediaSourceEventListener).onMediaPeriodCreated(WINDOW_INDEX, MEDIA_PERIOD_ID);
}
@Test
public void sameListenerObjectRegisteredTwiceOnlyReceivesEventsOnce() {
eventDispatcher.addEventListener(
Util.createHandlerForCurrentOrMainLooper(),
mediaSourceEventListener,
MediaSourceEventListener.class);
eventDispatcher.addEventListener(
Util.createHandlerForCurrentOrMainLooper(),
mediaSourceEventListener,
MediaSourceEventListener.class);
eventDispatcher.dispatch(
MediaSourceEventListener::onMediaPeriodCreated, MediaSourceEventListener.class);
verify(mediaSourceEventListener).onMediaPeriodCreated(WINDOW_INDEX, MEDIA_PERIOD_ID);
}
@Test
public void sameListenerInstanceCanBeRegisteredWithTwoTypes() {
eventDispatcher.addEventListener(
new Handler(Looper.getMainLooper()),
mediaAndDrmEventListener,
MediaSourceEventListener.class);
eventDispatcher.addEventListener(
new Handler(Looper.getMainLooper()),
mediaAndDrmEventListener,
DrmSessionEventListener.class);
eventDispatcher.dispatch(
MediaSourceEventListener::onMediaPeriodCreated, MediaSourceEventListener.class);
eventDispatcher.dispatch(
DrmSessionEventListener::onDrmKeysLoaded, DrmSessionEventListener.class);
verify(mediaAndDrmEventListener).onMediaPeriodCreated(WINDOW_INDEX, MEDIA_PERIOD_ID);
verify(mediaAndDrmEventListener).onDrmKeysLoaded(WINDOW_INDEX, MEDIA_PERIOD_ID);
}
// If a listener is added that implements multiple types, it should only receive events for the
// type specified at registration time.
@Test
public void listenerOnlyReceivesEventsForRegisteredType() {
eventDispatcher.addEventListener(
new Handler(Looper.getMainLooper()),
mediaAndDrmEventListener,
MediaSourceEventListener.class);
eventDispatcher.dispatch(
MediaSourceEventListener::onMediaPeriodCreated, MediaSourceEventListener.class);
eventDispatcher.dispatch(
DrmSessionEventListener::onDrmKeysLoaded, DrmSessionEventListener.class);
verify(mediaAndDrmEventListener).onMediaPeriodCreated(WINDOW_INDEX, MEDIA_PERIOD_ID);
verify(mediaAndDrmEventListener, never()).onDrmKeysLoaded(WINDOW_INDEX, MEDIA_PERIOD_ID);
}
@Test
public void listenerDoesntReceiveEventsDispatchedToSubclass() {
SubclassListener subclassListener = mock(SubclassListener.class);
eventDispatcher.addEventListener(
new Handler(Looper.getMainLooper()), subclassListener, MediaSourceEventListener.class);
eventDispatcher.dispatch(SubclassListener::subclassMethod, SubclassListener.class);
// subclassListener can handle the call to subclassMethod, but it isn't called because
// it was registered 'as-a' MediaSourceEventListener, not SubclassListener.
verify(subclassListener, never()).subclassMethod(anyInt(), any());
}
@Test
public void listenerDoesntReceiveEventsDispatchedToSuperclass() {
SubclassListener subclassListener = mock(SubclassListener.class);
eventDispatcher.addEventListener(
new Handler(Looper.getMainLooper()), subclassListener, SubclassListener.class);
eventDispatcher.dispatch(
MediaSourceEventListener::onMediaPeriodCreated, MediaSourceEventListener.class);
// subclassListener 'is-a' a MediaSourceEventListener, but it isn't called because the event
// is dispatched specifically to listeners registered as MediaSourceEventListener.
verify(subclassListener, never()).onMediaPeriodCreated(anyInt(), any());
}
@Test
public void listenersAreCopiedToNewDispatcher() {
eventDispatcher.addEventListener(
Util.createHandlerForCurrentOrMainLooper(),
mediaSourceEventListener,
MediaSourceEventListener.class);
MediaSource.MediaPeriodId newPeriodId = new MediaSource.MediaPeriodId("different uid");
MediaSourceEventDispatcher newEventDispatcher =
this.eventDispatcher.withParameters(
/* windowIndex= */ 250, newPeriodId, /* mediaTimeOffsetMs= */ 500);
newEventDispatcher.dispatch(
MediaSourceEventListener::onMediaPeriodCreated, MediaSourceEventListener.class);
verify(mediaSourceEventListener).onMediaPeriodCreated(250, newPeriodId);
}
@Test
public void removingListenerStopsEventDispatch() {
eventDispatcher.addEventListener(
Util.createHandlerForCurrentOrMainLooper(),
mediaSourceEventListener,
MediaSourceEventListener.class);
eventDispatcher.removeEventListener(mediaSourceEventListener, MediaSourceEventListener.class);
eventDispatcher.dispatch(
MediaSourceEventListener::onMediaPeriodCreated, MediaSourceEventListener.class);
verify(mediaSourceEventListener, never()).onMediaPeriodCreated(anyInt(), any());
}
@Test
public void removingListenerWithDifferentTypeToRegistrationDoesntRemove() {
eventDispatcher.addEventListener(
Util.createHandlerForCurrentOrMainLooper(),
mediaAndDrmEventListener,
MediaSourceEventListener.class);
eventDispatcher.removeEventListener(mediaAndDrmEventListener, DrmSessionEventListener.class);
eventDispatcher.dispatch(
MediaSourceEventListener::onMediaPeriodCreated, MediaSourceEventListener.class);
verify(mediaAndDrmEventListener).onMediaPeriodCreated(WINDOW_INDEX, MEDIA_PERIOD_ID);
}
@Test
public void listenersAreCountedBasedOnListenerAndType() {
// Add the listener twice and remove it once.
eventDispatcher.addEventListener(
Util.createHandlerForCurrentOrMainLooper(),
mediaSourceEventListener,
MediaSourceEventListener.class);
eventDispatcher.addEventListener(
Util.createHandlerForCurrentOrMainLooper(),
mediaSourceEventListener,
MediaSourceEventListener.class);
eventDispatcher.removeEventListener(mediaSourceEventListener, MediaSourceEventListener.class);
eventDispatcher.dispatch(
MediaSourceEventListener::onMediaPeriodCreated, MediaSourceEventListener.class);
verify(mediaSourceEventListener).onMediaPeriodCreated(WINDOW_INDEX, MEDIA_PERIOD_ID);
// Remove it a second time and confirm the events stop being propagated.
eventDispatcher.removeEventListener(mediaSourceEventListener, MediaSourceEventListener.class);
verifyNoMoreInteractions(mediaSourceEventListener);
}
private interface MediaAndDrmEventListener
extends MediaSourceEventListener, DrmSessionEventListener {}
private interface SubclassListener extends MediaSourceEventListener {
void subclassMethod(int windowIndex, @Nullable MediaPeriodId mediaPeriodId);
}
}
...@@ -35,6 +35,7 @@ import com.google.android.exoplayer2.RendererConfiguration; ...@@ -35,6 +35,7 @@ import com.google.android.exoplayer2.RendererConfiguration;
import com.google.android.exoplayer2.decoder.DecoderException; import com.google.android.exoplayer2.decoder.DecoderException;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.decoder.SimpleDecoder; import com.google.android.exoplayer2.decoder.SimpleDecoder;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.drm.ExoMediaCrypto; import com.google.android.exoplayer2.drm.ExoMediaCrypto;
import com.google.android.exoplayer2.testutil.FakeSampleStream; import com.google.android.exoplayer2.testutil.FakeSampleStream;
...@@ -185,8 +186,9 @@ public final class DecoderVideoRendererTest { ...@@ -185,8 +186,9 @@ public final class DecoderVideoRendererTest {
public void enable_withMayRenderStartOfStream_rendersFirstFrameBeforeStart() throws Exception { public void enable_withMayRenderStartOfStream_rendersFirstFrameBeforeStart() throws Exception {
FakeSampleStream fakeSampleStream = FakeSampleStream fakeSampleStream =
new FakeSampleStream( new FakeSampleStream(
/* mediaSourceEventDispatcher= */ null,
DrmSessionManager.DUMMY, DrmSessionManager.DUMMY,
/* eventDispatcher= */ null, new DrmSessionEventListener.EventDispatcher(),
/* initialFormat= */ H264_FORMAT, /* initialFormat= */ H264_FORMAT,
ImmutableList.of(oneByteSample(/* timeUs= */ 0))); ImmutableList.of(oneByteSample(/* timeUs= */ 0)));
...@@ -212,8 +214,9 @@ public final class DecoderVideoRendererTest { ...@@ -212,8 +214,9 @@ public final class DecoderVideoRendererTest {
throws Exception { throws Exception {
FakeSampleStream fakeSampleStream = FakeSampleStream fakeSampleStream =
new FakeSampleStream( new FakeSampleStream(
/* mediaSourceEventDispatcher= */ null,
DrmSessionManager.DUMMY, DrmSessionManager.DUMMY,
/* eventDispatcher= */ null, new DrmSessionEventListener.EventDispatcher(),
/* initialFormat= */ H264_FORMAT, /* initialFormat= */ H264_FORMAT,
ImmutableList.of(oneByteSample(/* timeUs= */ 0))); ImmutableList.of(oneByteSample(/* timeUs= */ 0)));
...@@ -238,8 +241,9 @@ public final class DecoderVideoRendererTest { ...@@ -238,8 +241,9 @@ public final class DecoderVideoRendererTest {
public void enable_withoutMayRenderStartOfStream_rendersFirstFrameAfterStart() throws Exception { public void enable_withoutMayRenderStartOfStream_rendersFirstFrameAfterStart() throws Exception {
FakeSampleStream fakeSampleStream = FakeSampleStream fakeSampleStream =
new FakeSampleStream( new FakeSampleStream(
/* mediaSourceEventDispatcher= */ null,
DrmSessionManager.DUMMY, DrmSessionManager.DUMMY,
/* eventDispatcher= */ null, new DrmSessionEventListener.EventDispatcher(),
/* initialFormat= */ H264_FORMAT, /* initialFormat= */ H264_FORMAT,
ImmutableList.of(oneByteSample(/* timeUs= */ 0))); ImmutableList.of(oneByteSample(/* timeUs= */ 0)));
...@@ -267,15 +271,17 @@ public final class DecoderVideoRendererTest { ...@@ -267,15 +271,17 @@ public final class DecoderVideoRendererTest {
public void replaceStream_whenStarted_rendersFirstFrameOfNewStream() throws Exception { public void replaceStream_whenStarted_rendersFirstFrameOfNewStream() throws Exception {
FakeSampleStream fakeSampleStream1 = FakeSampleStream fakeSampleStream1 =
new FakeSampleStream( new FakeSampleStream(
/* mediaSourceEventDispatcher= */ null,
DrmSessionManager.DUMMY, DrmSessionManager.DUMMY,
/* eventDispatcher= */ null, new DrmSessionEventListener.EventDispatcher(),
/* initialFormat= */ H264_FORMAT, /* initialFormat= */ H264_FORMAT,
ImmutableList.of( ImmutableList.of(
oneByteSample(/* timeUs= */ 0), FakeSampleStreamItem.END_OF_STREAM_ITEM)); oneByteSample(/* timeUs= */ 0), FakeSampleStreamItem.END_OF_STREAM_ITEM));
FakeSampleStream fakeSampleStream2 = FakeSampleStream fakeSampleStream2 =
new FakeSampleStream( new FakeSampleStream(
/* mediaSourceEventDispatcher= */ null,
DrmSessionManager.DUMMY, DrmSessionManager.DUMMY,
/* eventDispatcher= */ null, new DrmSessionEventListener.EventDispatcher(),
/* initialFormat= */ H264_FORMAT, /* initialFormat= */ H264_FORMAT,
ImmutableList.of( ImmutableList.of(
oneByteSample(/* timeUs= */ 0), FakeSampleStreamItem.END_OF_STREAM_ITEM)); oneByteSample(/* timeUs= */ 0), FakeSampleStreamItem.END_OF_STREAM_ITEM));
...@@ -309,15 +315,17 @@ public final class DecoderVideoRendererTest { ...@@ -309,15 +315,17 @@ public final class DecoderVideoRendererTest {
public void replaceStream_whenNotStarted_doesNotRenderFirstFrameOfNewStream() throws Exception { public void replaceStream_whenNotStarted_doesNotRenderFirstFrameOfNewStream() throws Exception {
FakeSampleStream fakeSampleStream1 = FakeSampleStream fakeSampleStream1 =
new FakeSampleStream( new FakeSampleStream(
/* mediaSourceEventDispatcher= */ null,
DrmSessionManager.DUMMY, DrmSessionManager.DUMMY,
/* eventDispatcher= */ null, new DrmSessionEventListener.EventDispatcher(),
/* initialFormat= */ H264_FORMAT, /* initialFormat= */ H264_FORMAT,
ImmutableList.of( ImmutableList.of(
oneByteSample(/* timeUs= */ 0), FakeSampleStreamItem.END_OF_STREAM_ITEM)); oneByteSample(/* timeUs= */ 0), FakeSampleStreamItem.END_OF_STREAM_ITEM));
FakeSampleStream fakeSampleStream2 = FakeSampleStream fakeSampleStream2 =
new FakeSampleStream( new FakeSampleStream(
/* mediaSourceEventDispatcher= */ null,
DrmSessionManager.DUMMY, DrmSessionManager.DUMMY,
/* eventDispatcher= */ null, new DrmSessionEventListener.EventDispatcher(),
/* initialFormat= */ H264_FORMAT, /* initialFormat= */ H264_FORMAT,
ImmutableList.of( ImmutableList.of(
oneByteSample(/* timeUs= */ 0), FakeSampleStreamItem.END_OF_STREAM_ITEM)); oneByteSample(/* timeUs= */ 0), FakeSampleStreamItem.END_OF_STREAM_ITEM));
......
...@@ -40,6 +40,7 @@ import com.google.android.exoplayer2.Format; ...@@ -40,6 +40,7 @@ import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.Renderer; import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.RendererCapabilities; import com.google.android.exoplayer2.RendererCapabilities;
import com.google.android.exoplayer2.RendererConfiguration; import com.google.android.exoplayer2.RendererConfiguration;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.mediacodec.MediaCodecInfo; import com.google.android.exoplayer2.mediacodec.MediaCodecInfo;
import com.google.android.exoplayer2.mediacodec.MediaCodecSelector; import com.google.android.exoplayer2.mediacodec.MediaCodecSelector;
...@@ -129,8 +130,9 @@ public class MediaCodecVideoRendererTest { ...@@ -129,8 +130,9 @@ public class MediaCodecVideoRendererTest {
public void render_dropsLateBuffer() throws Exception { public void render_dropsLateBuffer() throws Exception {
FakeSampleStream fakeSampleStream = FakeSampleStream fakeSampleStream =
new FakeSampleStream( new FakeSampleStream(
/* mediaSourceEventDispatcher= */ null,
DrmSessionManager.DUMMY, DrmSessionManager.DUMMY,
/* eventDispatcher= */ null, new DrmSessionEventListener.EventDispatcher(),
/* initialFormat= */ VIDEO_H264, /* initialFormat= */ VIDEO_H264,
ImmutableList.of( ImmutableList.of(
oneByteSample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME), // First buffer. oneByteSample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME), // First buffer.
...@@ -165,8 +167,9 @@ public class MediaCodecVideoRendererTest { ...@@ -165,8 +167,9 @@ public class MediaCodecVideoRendererTest {
RendererConfiguration.DEFAULT, RendererConfiguration.DEFAULT,
new Format[] {VIDEO_H264}, new Format[] {VIDEO_H264},
new FakeSampleStream( new FakeSampleStream(
/* mediaSourceEventDispatcher= */ null,
DrmSessionManager.DUMMY, DrmSessionManager.DUMMY,
/* eventDispatcher= */ null, new DrmSessionEventListener.EventDispatcher(),
/* initialFormat= */ VIDEO_H264, /* initialFormat= */ VIDEO_H264,
ImmutableList.of( ImmutableList.of(
oneByteSample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME), oneByteSample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME),
...@@ -202,8 +205,9 @@ public class MediaCodecVideoRendererTest { ...@@ -202,8 +205,9 @@ public class MediaCodecVideoRendererTest {
FakeSampleStream fakeSampleStream = FakeSampleStream fakeSampleStream =
new FakeSampleStream( new FakeSampleStream(
/* mediaSourceEventDispatcher= */ null,
DrmSessionManager.DUMMY, DrmSessionManager.DUMMY,
/* eventDispatcher= */ null, new DrmSessionEventListener.EventDispatcher(),
/* initialFormat= */ pAsp1, /* initialFormat= */ pAsp1,
ImmutableList.of(oneByteSample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME))); ImmutableList.of(oneByteSample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME)));
...@@ -246,8 +250,9 @@ public class MediaCodecVideoRendererTest { ...@@ -246,8 +250,9 @@ public class MediaCodecVideoRendererTest {
throws Exception { throws Exception {
FakeSampleStream fakeSampleStream = FakeSampleStream fakeSampleStream =
new FakeSampleStream( new FakeSampleStream(
/* mediaSourceEventDispatcher= */ null,
DrmSessionManager.DUMMY, DrmSessionManager.DUMMY,
/* eventDispatcher= */ null, new DrmSessionEventListener.EventDispatcher(),
/* initialFormat= */ VIDEO_H264, /* initialFormat= */ VIDEO_H264,
ImmutableList.of(oneByteSample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME))); ImmutableList.of(oneByteSample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME)));
mediaCodecVideoRenderer.enable( mediaCodecVideoRenderer.enable(
...@@ -279,8 +284,9 @@ public class MediaCodecVideoRendererTest { ...@@ -279,8 +284,9 @@ public class MediaCodecVideoRendererTest {
public void enable_withMayRenderStartOfStream_rendersFirstFrameBeforeStart() throws Exception { public void enable_withMayRenderStartOfStream_rendersFirstFrameBeforeStart() throws Exception {
FakeSampleStream fakeSampleStream = FakeSampleStream fakeSampleStream =
new FakeSampleStream( new FakeSampleStream(
/* mediaSourceEventDispatcher= */ null,
DrmSessionManager.DUMMY, DrmSessionManager.DUMMY,
/* eventDispatcher= */ null, new DrmSessionEventListener.EventDispatcher(),
/* initialFormat= */ VIDEO_H264, /* initialFormat= */ VIDEO_H264,
ImmutableList.of(oneByteSample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME))); ImmutableList.of(oneByteSample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME)));
...@@ -304,8 +310,9 @@ public class MediaCodecVideoRendererTest { ...@@ -304,8 +310,9 @@ public class MediaCodecVideoRendererTest {
throws Exception { throws Exception {
FakeSampleStream fakeSampleStream = FakeSampleStream fakeSampleStream =
new FakeSampleStream( new FakeSampleStream(
/* mediaSourceEventDispatcher= */ null,
DrmSessionManager.DUMMY, DrmSessionManager.DUMMY,
/* eventDispatcher= */ null, new DrmSessionEventListener.EventDispatcher(),
/* initialFormat= */ VIDEO_H264, /* initialFormat= */ VIDEO_H264,
ImmutableList.of(oneByteSample(/* timeUs= */ 0))); ImmutableList.of(oneByteSample(/* timeUs= */ 0)));
...@@ -328,8 +335,9 @@ public class MediaCodecVideoRendererTest { ...@@ -328,8 +335,9 @@ public class MediaCodecVideoRendererTest {
public void enable_withoutMayRenderStartOfStream_rendersFirstFrameAfterStart() throws Exception { public void enable_withoutMayRenderStartOfStream_rendersFirstFrameAfterStart() throws Exception {
FakeSampleStream fakeSampleStream = FakeSampleStream fakeSampleStream =
new FakeSampleStream( new FakeSampleStream(
/* mediaSourceEventDispatcher= */ null,
DrmSessionManager.DUMMY, DrmSessionManager.DUMMY,
/* eventDispatcher= */ null, new DrmSessionEventListener.EventDispatcher(),
/* initialFormat= */ VIDEO_H264, /* initialFormat= */ VIDEO_H264,
ImmutableList.of(oneByteSample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME))); ImmutableList.of(oneByteSample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME)));
...@@ -353,16 +361,18 @@ public class MediaCodecVideoRendererTest { ...@@ -353,16 +361,18 @@ public class MediaCodecVideoRendererTest {
public void replaceStream_whenStarted_rendersFirstFrameOfNewStream() throws Exception { public void replaceStream_whenStarted_rendersFirstFrameOfNewStream() throws Exception {
FakeSampleStream fakeSampleStream1 = FakeSampleStream fakeSampleStream1 =
new FakeSampleStream( new FakeSampleStream(
/* mediaSourceEventDispatcher= */ null,
DrmSessionManager.DUMMY, DrmSessionManager.DUMMY,
/* eventDispatcher= */ null, new DrmSessionEventListener.EventDispatcher(),
/* initialFormat= */ VIDEO_H264, /* initialFormat= */ VIDEO_H264,
ImmutableList.of( ImmutableList.of(
oneByteSample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME), oneByteSample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME),
FakeSampleStreamItem.END_OF_STREAM_ITEM)); FakeSampleStreamItem.END_OF_STREAM_ITEM));
FakeSampleStream fakeSampleStream2 = FakeSampleStream fakeSampleStream2 =
new FakeSampleStream( new FakeSampleStream(
/* mediaSourceEventDispatcher= */ null,
DrmSessionManager.DUMMY, DrmSessionManager.DUMMY,
/* eventDispatcher= */ null, new DrmSessionEventListener.EventDispatcher(),
/* initialFormat= */ VIDEO_H264, /* initialFormat= */ VIDEO_H264,
ImmutableList.of( ImmutableList.of(
oneByteSample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME), oneByteSample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME),
...@@ -395,16 +405,18 @@ public class MediaCodecVideoRendererTest { ...@@ -395,16 +405,18 @@ public class MediaCodecVideoRendererTest {
public void replaceStream_whenNotStarted_doesNotRenderFirstFrameOfNewStream() throws Exception { public void replaceStream_whenNotStarted_doesNotRenderFirstFrameOfNewStream() throws Exception {
FakeSampleStream fakeSampleStream1 = FakeSampleStream fakeSampleStream1 =
new FakeSampleStream( new FakeSampleStream(
/* mediaSourceEventDispatcher= */ null,
DrmSessionManager.DUMMY, DrmSessionManager.DUMMY,
/* eventDispatcher= */ null, new DrmSessionEventListener.EventDispatcher(),
/* initialFormat= */ VIDEO_H264, /* initialFormat= */ VIDEO_H264,
ImmutableList.of( ImmutableList.of(
oneByteSample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME), oneByteSample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME),
FakeSampleStreamItem.END_OF_STREAM_ITEM)); FakeSampleStreamItem.END_OF_STREAM_ITEM));
FakeSampleStream fakeSampleStream2 = FakeSampleStream fakeSampleStream2 =
new FakeSampleStream( new FakeSampleStream(
/* mediaSourceEventDispatcher= */ null,
DrmSessionManager.DUMMY, DrmSessionManager.DUMMY,
/* eventDispatcher= */ null, new DrmSessionEventListener.EventDispatcher(),
/* initialFormat= */ VIDEO_H264, /* initialFormat= */ VIDEO_H264,
ImmutableList.of( ImmutableList.of(
oneByteSample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME), oneByteSample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME),
...@@ -443,8 +455,9 @@ public class MediaCodecVideoRendererTest { ...@@ -443,8 +455,9 @@ public class MediaCodecVideoRendererTest {
Format mp4Uhd = VIDEO_H264.buildUpon().setWidth(3840).setHeight(2160).build(); Format mp4Uhd = VIDEO_H264.buildUpon().setWidth(3840).setHeight(2160).build();
FakeSampleStream fakeSampleStream = FakeSampleStream fakeSampleStream =
new FakeSampleStream( new FakeSampleStream(
/* mediaSourceEventDispatcher= */ null,
DrmSessionManager.DUMMY, DrmSessionManager.DUMMY,
/* eventDispatcher= */ null, new DrmSessionEventListener.EventDispatcher(),
/* initialFormat= */ mp4Uhd, /* initialFormat= */ mp4Uhd,
ImmutableList.of( ImmutableList.of(
oneByteSample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME), oneByteSample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME),
......
...@@ -24,11 +24,13 @@ import com.google.android.exoplayer2.C; ...@@ -24,11 +24,13 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.SeekParameters; import com.google.android.exoplayer2.SeekParameters;
import com.google.android.exoplayer2.drm.DrmInitData; import com.google.android.exoplayer2.drm.DrmInitData;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.offline.StreamKey; import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.source.CompositeSequenceableLoaderFactory; import com.google.android.exoplayer2.source.CompositeSequenceableLoaderFactory;
import com.google.android.exoplayer2.source.EmptySampleStream; import com.google.android.exoplayer2.source.EmptySampleStream;
import com.google.android.exoplayer2.source.MediaPeriod; import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.MediaSourceEventListener;
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher; import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
import com.google.android.exoplayer2.source.SampleStream; import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.source.SequenceableLoader; import com.google.android.exoplayer2.source.SequenceableLoader;
...@@ -90,7 +92,8 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -90,7 +92,8 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
private final PlayerEmsgHandler playerEmsgHandler; private final PlayerEmsgHandler playerEmsgHandler;
private final IdentityHashMap<ChunkSampleStream<DashChunkSource>, PlayerTrackEmsgHandler> private final IdentityHashMap<ChunkSampleStream<DashChunkSource>, PlayerTrackEmsgHandler>
trackEmsgHandlerBySampleStream; trackEmsgHandlerBySampleStream;
private final EventDispatcher eventDispatcher; private final MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher;
private final DrmSessionEventListener.EventDispatcher drmEventDispatcher;
@Nullable private Callback callback; @Nullable private Callback callback;
private ChunkSampleStream<DashChunkSource>[] sampleStreams; private ChunkSampleStream<DashChunkSource>[] sampleStreams;
...@@ -108,8 +111,9 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -108,8 +111,9 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
DashChunkSource.Factory chunkSourceFactory, DashChunkSource.Factory chunkSourceFactory,
@Nullable TransferListener transferListener, @Nullable TransferListener transferListener,
DrmSessionManager drmSessionManager, DrmSessionManager drmSessionManager,
DrmSessionEventListener.EventDispatcher drmEventDispatcher,
LoadErrorHandlingPolicy loadErrorHandlingPolicy, LoadErrorHandlingPolicy loadErrorHandlingPolicy,
EventDispatcher eventDispatcher, EventDispatcher mediaSourceEventDispatcher,
long elapsedRealtimeOffsetMs, long elapsedRealtimeOffsetMs,
LoaderErrorThrower manifestLoaderErrorThrower, LoaderErrorThrower manifestLoaderErrorThrower,
Allocator allocator, Allocator allocator,
...@@ -121,8 +125,9 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -121,8 +125,9 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
this.chunkSourceFactory = chunkSourceFactory; this.chunkSourceFactory = chunkSourceFactory;
this.transferListener = transferListener; this.transferListener = transferListener;
this.drmSessionManager = drmSessionManager; this.drmSessionManager = drmSessionManager;
this.drmEventDispatcher = drmEventDispatcher;
this.loadErrorHandlingPolicy = loadErrorHandlingPolicy; this.loadErrorHandlingPolicy = loadErrorHandlingPolicy;
this.eventDispatcher = eventDispatcher; this.mediaSourceEventDispatcher = mediaSourceEventDispatcher;
this.elapsedRealtimeOffsetMs = elapsedRealtimeOffsetMs; this.elapsedRealtimeOffsetMs = elapsedRealtimeOffsetMs;
this.manifestLoaderErrorThrower = manifestLoaderErrorThrower; this.manifestLoaderErrorThrower = manifestLoaderErrorThrower;
this.allocator = allocator; this.allocator = allocator;
...@@ -139,7 +144,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -139,7 +144,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
buildTrackGroups(drmSessionManager, period.adaptationSets, eventStreams); buildTrackGroups(drmSessionManager, period.adaptationSets, eventStreams);
trackGroups = result.first; trackGroups = result.first;
trackGroupInfos = result.second; trackGroupInfos = result.second;
eventDispatcher.mediaPeriodCreated(); mediaSourceEventDispatcher.mediaPeriodCreated();
} }
/** /**
...@@ -178,7 +183,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -178,7 +183,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
sampleStream.release(this); sampleStream.release(this);
} }
callback = null; callback = null;
eventDispatcher.mediaPeriodReleased(); mediaSourceEventDispatcher.mediaPeriodReleased();
} }
// ChunkSampleStream.ReleaseCallback implementation. // ChunkSampleStream.ReleaseCallback implementation.
...@@ -316,7 +321,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -316,7 +321,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
@Override @Override
public long readDiscontinuity() { public long readDiscontinuity() {
if (!notifiedReadingStarted) { if (!notifiedReadingStarted) {
eventDispatcher.readingStarted(); mediaSourceEventDispatcher.readingStarted();
notifiedReadingStarted = true; notifiedReadingStarted = true;
} }
return C.TIME_UNSET; return C.TIME_UNSET;
...@@ -788,8 +793,9 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -788,8 +793,9 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
allocator, allocator,
positionUs, positionUs,
drmSessionManager, drmSessionManager,
drmEventDispatcher,
loadErrorHandlingPolicy, loadErrorHandlingPolicy,
eventDispatcher); mediaSourceEventDispatcher);
synchronized (this) { synchronized (this) {
// The map is also accessed on the loading thread so synchronize access. // The map is also accessed on the loading thread so synchronize access.
trackEmsgHandlerBySampleStream.put(stream, trackPlayerEmsgHandler); trackEmsgHandlerBySampleStream.put(stream, trackPlayerEmsgHandler);
......
...@@ -29,6 +29,7 @@ import com.google.android.exoplayer2.MediaItem; ...@@ -29,6 +29,7 @@ import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.ParserException; import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.drm.DrmSession; import com.google.android.exoplayer2.drm.DrmSession;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.offline.FilteringManifestParser; import com.google.android.exoplayer2.offline.FilteringManifestParser;
import com.google.android.exoplayer2.offline.StreamKey; import com.google.android.exoplayer2.offline.StreamKey;
...@@ -694,8 +695,9 @@ public final class DashMediaSource extends BaseMediaSource { ...@@ -694,8 +695,9 @@ public final class DashMediaSource extends BaseMediaSource {
public MediaPeriod createPeriod( public MediaPeriod createPeriod(
MediaPeriodId periodId, Allocator allocator, long startPositionUs) { MediaPeriodId periodId, Allocator allocator, long startPositionUs) {
int periodIndex = (Integer) periodId.periodUid - firstPeriodId; int periodIndex = (Integer) periodId.periodUid - firstPeriodId;
EventDispatcher periodEventDispatcher = MediaSourceEventListener.EventDispatcher periodEventDispatcher =
createEventDispatcher(periodId, manifest.getPeriod(periodIndex).startMs); createEventDispatcher(periodId, manifest.getPeriod(periodIndex).startMs);
DrmSessionEventListener.EventDispatcher drmEventDispatcher = createDrmEventDispatcher(periodId);
DashMediaPeriod mediaPeriod = DashMediaPeriod mediaPeriod =
new DashMediaPeriod( new DashMediaPeriod(
firstPeriodId + periodIndex, firstPeriodId + periodIndex,
...@@ -704,6 +706,7 @@ public final class DashMediaSource extends BaseMediaSource { ...@@ -704,6 +706,7 @@ public final class DashMediaSource extends BaseMediaSource {
chunkSourceFactory, chunkSourceFactory,
mediaTransferListener, mediaTransferListener,
drmSessionManager, drmSessionManager,
drmEventDispatcher,
loadErrorHandlingPolicy, loadErrorHandlingPolicy,
periodEventDispatcher, periodEventDispatcher,
elapsedRealtimeOffsetMs, elapsedRealtimeOffsetMs,
......
...@@ -24,6 +24,7 @@ import com.google.android.exoplayer2.C; ...@@ -24,6 +24,7 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.FormatHolder; import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.ParserException; import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.extractor.TrackOutput; import com.google.android.exoplayer2.extractor.TrackOutput;
import com.google.android.exoplayer2.metadata.Metadata; import com.google.android.exoplayer2.metadata.Metadata;
...@@ -35,7 +36,6 @@ import com.google.android.exoplayer2.source.chunk.Chunk; ...@@ -35,7 +36,6 @@ import com.google.android.exoplayer2.source.chunk.Chunk;
import com.google.android.exoplayer2.source.dash.manifest.DashManifest; import com.google.android.exoplayer2.source.dash.manifest.DashManifest;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DataReader; import com.google.android.exoplayer2.upstream.DataReader;
import com.google.android.exoplayer2.util.MediaSourceEventDispatcher;
import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.ParsableByteArray;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import java.io.IOException; import java.io.IOException;
...@@ -290,7 +290,7 @@ public final class PlayerEmsgHandler implements Handler.Callback { ...@@ -290,7 +290,7 @@ public final class PlayerEmsgHandler implements Handler.Callback {
allocator, allocator,
/* playbackLooper= */ handler.getLooper(), /* playbackLooper= */ handler.getLooper(),
DrmSessionManager.getDummyDrmSessionManager(), DrmSessionManager.getDummyDrmSessionManager(),
new MediaSourceEventDispatcher()); new DrmSessionEventListener.EventDispatcher());
formatHolder = new FormatHolder(); formatHolder = new FormatHolder();
buffer = new MetadataInputBuffer(); buffer = new MetadataInputBuffer();
} }
......
...@@ -22,10 +22,11 @@ import androidx.annotation.Nullable; ...@@ -22,10 +22,11 @@ import androidx.annotation.Nullable;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.source.CompositeSequenceableLoaderFactory; import com.google.android.exoplayer2.source.CompositeSequenceableLoaderFactory;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher; import com.google.android.exoplayer2.source.MediaSourceEventListener;
import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.source.dash.PlayerEmsgHandler.PlayerEmsgCallback; import com.google.android.exoplayer2.source.dash.PlayerEmsgHandler.PlayerEmsgCallback;
...@@ -344,6 +345,7 @@ public final class DashMediaPeriodTest { ...@@ -344,6 +345,7 @@ public final class DashMediaPeriodTest {
} }
private static DashMediaPeriod createDashMediaPeriod(DashManifest manifest, int periodIndex) { private static DashMediaPeriod createDashMediaPeriod(DashManifest manifest, int periodIndex) {
MediaPeriodId mediaPeriodId = new MediaPeriodId(/* periodUid= */ new Object());
return new DashMediaPeriod( return new DashMediaPeriod(
/* id= */ periodIndex, /* id= */ periodIndex,
manifest, manifest,
...@@ -351,12 +353,11 @@ public final class DashMediaPeriodTest { ...@@ -351,12 +353,11 @@ public final class DashMediaPeriodTest {
mock(DashChunkSource.Factory.class), mock(DashChunkSource.Factory.class),
mock(TransferListener.class), mock(TransferListener.class),
DrmSessionManager.getDummyDrmSessionManager(), DrmSessionManager.getDummyDrmSessionManager(),
new DrmSessionEventListener.EventDispatcher()
.withParameters(/* windowIndex= */ 0, mediaPeriodId),
mock(LoadErrorHandlingPolicy.class), mock(LoadErrorHandlingPolicy.class),
new EventDispatcher() new MediaSourceEventListener.EventDispatcher()
.withParameters( .withParameters(/* windowIndex= */ 0, mediaPeriodId, /* mediaTimeOffsetMs= */ 0),
/* windowIndex= */ 0,
/* mediaPeriodId= */ new MediaPeriodId(/* periodUid= */ new Object()),
/* mediaTimeOffsetMs= */ 0),
/* elapsedRealtimeOffsetMs= */ 0, /* elapsedRealtimeOffsetMs= */ 0,
mock(LoaderErrorThrower.class), mock(LoaderErrorThrower.class),
mock(Allocator.class), mock(Allocator.class),
......
...@@ -23,6 +23,7 @@ import com.google.android.exoplayer2.Format; ...@@ -23,6 +23,7 @@ import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.SeekParameters; import com.google.android.exoplayer2.SeekParameters;
import com.google.android.exoplayer2.drm.DrmInitData; import com.google.android.exoplayer2.drm.DrmInitData;
import com.google.android.exoplayer2.drm.DrmSession; import com.google.android.exoplayer2.drm.DrmSession;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.extractor.Extractor; import com.google.android.exoplayer2.extractor.Extractor;
import com.google.android.exoplayer2.metadata.Metadata; import com.google.android.exoplayer2.metadata.Metadata;
...@@ -69,6 +70,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper ...@@ -69,6 +70,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
private final HlsDataSourceFactory dataSourceFactory; private final HlsDataSourceFactory dataSourceFactory;
@Nullable private final TransferListener mediaTransferListener; @Nullable private final TransferListener mediaTransferListener;
private final DrmSessionManager drmSessionManager; private final DrmSessionManager drmSessionManager;
private final DrmSessionEventListener.EventDispatcher drmEventDispatcher;
private final LoadErrorHandlingPolicy loadErrorHandlingPolicy; private final LoadErrorHandlingPolicy loadErrorHandlingPolicy;
private final EventDispatcher eventDispatcher; private final EventDispatcher eventDispatcher;
private final Allocator allocator; private final Allocator allocator;
...@@ -114,6 +116,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper ...@@ -114,6 +116,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
HlsDataSourceFactory dataSourceFactory, HlsDataSourceFactory dataSourceFactory,
@Nullable TransferListener mediaTransferListener, @Nullable TransferListener mediaTransferListener,
DrmSessionManager drmSessionManager, DrmSessionManager drmSessionManager,
DrmSessionEventListener.EventDispatcher drmEventDispatcher,
LoadErrorHandlingPolicy loadErrorHandlingPolicy, LoadErrorHandlingPolicy loadErrorHandlingPolicy,
EventDispatcher eventDispatcher, EventDispatcher eventDispatcher,
Allocator allocator, Allocator allocator,
...@@ -126,6 +129,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper ...@@ -126,6 +129,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
this.dataSourceFactory = dataSourceFactory; this.dataSourceFactory = dataSourceFactory;
this.mediaTransferListener = mediaTransferListener; this.mediaTransferListener = mediaTransferListener;
this.drmSessionManager = drmSessionManager; this.drmSessionManager = drmSessionManager;
this.drmEventDispatcher = drmEventDispatcher;
this.loadErrorHandlingPolicy = loadErrorHandlingPolicy; this.loadErrorHandlingPolicy = loadErrorHandlingPolicy;
this.eventDispatcher = eventDispatcher; this.eventDispatcher = eventDispatcher;
this.allocator = allocator; this.allocator = allocator;
...@@ -758,6 +762,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper ...@@ -758,6 +762,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
positionUs, positionUs,
muxedAudioFormat, muxedAudioFormat,
drmSessionManager, drmSessionManager,
drmEventDispatcher,
loadErrorHandlingPolicy, loadErrorHandlingPolicy,
eventDispatcher, eventDispatcher,
metadataType); metadataType);
......
...@@ -26,6 +26,7 @@ import com.google.android.exoplayer2.C; ...@@ -26,6 +26,7 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlayerLibraryInfo; import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.drm.DrmSession; import com.google.android.exoplayer2.drm.DrmSession;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.extractor.Extractor; import com.google.android.exoplayer2.extractor.Extractor;
import com.google.android.exoplayer2.offline.StreamKey; import com.google.android.exoplayer2.offline.StreamKey;
...@@ -35,7 +36,6 @@ import com.google.android.exoplayer2.source.DefaultCompositeSequenceableLoaderFa ...@@ -35,7 +36,6 @@ import com.google.android.exoplayer2.source.DefaultCompositeSequenceableLoaderFa
import com.google.android.exoplayer2.source.MediaPeriod; import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.MediaSourceEventListener; import com.google.android.exoplayer2.source.MediaSourceEventListener;
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
import com.google.android.exoplayer2.source.MediaSourceFactory; import com.google.android.exoplayer2.source.MediaSourceFactory;
import com.google.android.exoplayer2.source.SequenceableLoader; import com.google.android.exoplayer2.source.SequenceableLoader;
import com.google.android.exoplayer2.source.SinglePeriodTimeline; import com.google.android.exoplayer2.source.SinglePeriodTimeline;
...@@ -446,7 +446,8 @@ public final class HlsMediaSource extends BaseMediaSource ...@@ -446,7 +446,8 @@ public final class HlsMediaSource extends BaseMediaSource
protected void prepareSourceInternal(@Nullable TransferListener mediaTransferListener) { protected void prepareSourceInternal(@Nullable TransferListener mediaTransferListener) {
this.mediaTransferListener = mediaTransferListener; this.mediaTransferListener = mediaTransferListener;
drmSessionManager.prepare(); drmSessionManager.prepare();
EventDispatcher eventDispatcher = createEventDispatcher(/* mediaPeriodId= */ null); MediaSourceEventListener.EventDispatcher eventDispatcher =
createEventDispatcher(/* mediaPeriodId= */ null);
playlistTracker.start(playbackProperties.uri, eventDispatcher, /* listener= */ this); playlistTracker.start(playbackProperties.uri, eventDispatcher, /* listener= */ this);
} }
...@@ -457,15 +458,17 @@ public final class HlsMediaSource extends BaseMediaSource ...@@ -457,15 +458,17 @@ public final class HlsMediaSource extends BaseMediaSource
@Override @Override
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) { public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) {
EventDispatcher eventDispatcher = createEventDispatcher(id); MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher = createEventDispatcher(id);
DrmSessionEventListener.EventDispatcher drmEventDispatcher = createDrmEventDispatcher(id);
return new HlsMediaPeriod( return new HlsMediaPeriod(
extractorFactory, extractorFactory,
playlistTracker, playlistTracker,
dataSourceFactory, dataSourceFactory,
mediaTransferListener, mediaTransferListener,
drmSessionManager, drmSessionManager,
drmEventDispatcher,
loadErrorHandlingPolicy, loadErrorHandlingPolicy,
eventDispatcher, mediaSourceEventDispatcher,
allocator, allocator,
compositeSequenceableLoaderFactory, compositeSequenceableLoaderFactory,
allowChunklessPreparation, allowChunklessPreparation,
......
...@@ -27,6 +27,7 @@ import com.google.android.exoplayer2.ParserException; ...@@ -27,6 +27,7 @@ import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.drm.DrmInitData; import com.google.android.exoplayer2.drm.DrmInitData;
import com.google.android.exoplayer2.drm.DrmSession; import com.google.android.exoplayer2.drm.DrmSession;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.extractor.DummyTrackOutput; import com.google.android.exoplayer2.extractor.DummyTrackOutput;
import com.google.android.exoplayer2.extractor.Extractor; import com.google.android.exoplayer2.extractor.Extractor;
...@@ -39,7 +40,7 @@ import com.google.android.exoplayer2.metadata.emsg.EventMessageDecoder; ...@@ -39,7 +40,7 @@ import com.google.android.exoplayer2.metadata.emsg.EventMessageDecoder;
import com.google.android.exoplayer2.metadata.id3.PrivFrame; import com.google.android.exoplayer2.metadata.id3.PrivFrame;
import com.google.android.exoplayer2.source.LoadEventInfo; import com.google.android.exoplayer2.source.LoadEventInfo;
import com.google.android.exoplayer2.source.MediaLoadData; import com.google.android.exoplayer2.source.MediaLoadData;
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher; import com.google.android.exoplayer2.source.MediaSourceEventListener;
import com.google.android.exoplayer2.source.SampleQueue; import com.google.android.exoplayer2.source.SampleQueue;
import com.google.android.exoplayer2.source.SampleQueue.UpstreamFormatChangedListener; import com.google.android.exoplayer2.source.SampleQueue.UpstreamFormatChangedListener;
import com.google.android.exoplayer2.source.SampleStream; import com.google.android.exoplayer2.source.SampleStream;
...@@ -57,7 +58,6 @@ import com.google.android.exoplayer2.upstream.Loader; ...@@ -57,7 +58,6 @@ import com.google.android.exoplayer2.upstream.Loader;
import com.google.android.exoplayer2.upstream.Loader.LoadErrorAction; import com.google.android.exoplayer2.upstream.Loader.LoadErrorAction;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.MediaSourceEventDispatcher;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.ParsableByteArray;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
...@@ -120,9 +120,10 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -120,9 +120,10 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
private final Allocator allocator; private final Allocator allocator;
@Nullable private final Format muxedAudioFormat; @Nullable private final Format muxedAudioFormat;
private final DrmSessionManager drmSessionManager; private final DrmSessionManager drmSessionManager;
private final DrmSessionEventListener.EventDispatcher drmEventDispatcher;
private final LoadErrorHandlingPolicy loadErrorHandlingPolicy; private final LoadErrorHandlingPolicy loadErrorHandlingPolicy;
private final Loader loader; private final Loader loader;
private final EventDispatcher eventDispatcher; private final MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher;
private final @HlsMediaSource.MetadataType int metadataType; private final @HlsMediaSource.MetadataType int metadataType;
private final HlsChunkSource.HlsChunkHolder nextChunkHolder; private final HlsChunkSource.HlsChunkHolder nextChunkHolder;
private final ArrayList<HlsMediaChunk> mediaChunks; private final ArrayList<HlsMediaChunk> mediaChunks;
...@@ -185,8 +186,10 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -185,8 +186,10 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
* @param muxedAudioFormat Optional muxed audio {@link Format} as defined by the master playlist. * @param muxedAudioFormat Optional muxed audio {@link Format} as defined by the master playlist.
* @param drmSessionManager The {@link DrmSessionManager} to acquire {@link DrmSession * @param drmSessionManager The {@link DrmSessionManager} to acquire {@link DrmSession
* DrmSessions} with. * DrmSessions} with.
* @param drmEventDispatcher A dispatcher to notify of {@link DrmSessionEventListener} events.
* @param loadErrorHandlingPolicy A {@link LoadErrorHandlingPolicy}. * @param loadErrorHandlingPolicy A {@link LoadErrorHandlingPolicy}.
* @param eventDispatcher A dispatcher to notify of events. * @param mediaSourceEventDispatcher A dispatcher to notify of {@link MediaSourceEventListener}
* events.
*/ */
public HlsSampleStreamWrapper( public HlsSampleStreamWrapper(
int trackType, int trackType,
...@@ -197,8 +200,9 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -197,8 +200,9 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
long positionUs, long positionUs,
@Nullable Format muxedAudioFormat, @Nullable Format muxedAudioFormat,
DrmSessionManager drmSessionManager, DrmSessionManager drmSessionManager,
DrmSessionEventListener.EventDispatcher drmEventDispatcher,
LoadErrorHandlingPolicy loadErrorHandlingPolicy, LoadErrorHandlingPolicy loadErrorHandlingPolicy,
EventDispatcher eventDispatcher, MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher,
@HlsMediaSource.MetadataType int metadataType) { @HlsMediaSource.MetadataType int metadataType) {
this.trackType = trackType; this.trackType = trackType;
this.callback = callback; this.callback = callback;
...@@ -207,8 +211,9 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -207,8 +211,9 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
this.allocator = allocator; this.allocator = allocator;
this.muxedAudioFormat = muxedAudioFormat; this.muxedAudioFormat = muxedAudioFormat;
this.drmSessionManager = drmSessionManager; this.drmSessionManager = drmSessionManager;
this.drmEventDispatcher = drmEventDispatcher;
this.loadErrorHandlingPolicy = loadErrorHandlingPolicy; this.loadErrorHandlingPolicy = loadErrorHandlingPolicy;
this.eventDispatcher = eventDispatcher; this.mediaSourceEventDispatcher = mediaSourceEventDispatcher;
this.metadataType = metadataType; this.metadataType = metadataType;
loader = new Loader("Loader:HlsSampleStreamWrapper"); loader = new Loader("Loader:HlsSampleStreamWrapper");
nextChunkHolder = new HlsChunkSource.HlsChunkHolder(); nextChunkHolder = new HlsChunkSource.HlsChunkHolder();
...@@ -552,8 +557,11 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -552,8 +557,11 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
HlsMediaChunk currentChunk = mediaChunks.get(0); HlsMediaChunk currentChunk = mediaChunks.get(0);
Format trackFormat = currentChunk.trackFormat; Format trackFormat = currentChunk.trackFormat;
if (!trackFormat.equals(downstreamTrackFormat)) { if (!trackFormat.equals(downstreamTrackFormat)) {
eventDispatcher.downstreamFormatChanged(trackType, trackFormat, mediaSourceEventDispatcher.downstreamFormatChanged(
currentChunk.trackSelectionReason, currentChunk.trackSelectionData, trackType,
trackFormat,
currentChunk.trackSelectionReason,
currentChunk.trackSelectionData,
currentChunk.startTimeUs); currentChunk.startTimeUs);
} }
downstreamTrackFormat = trackFormat; downstreamTrackFormat = trackFormat;
...@@ -682,7 +690,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -682,7 +690,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
long elapsedRealtimeMs = long elapsedRealtimeMs =
loader.startLoading( loader.startLoading(
loadable, this, loadErrorHandlingPolicy.getMinimumLoadableRetryCount(loadable.type)); loadable, this, loadErrorHandlingPolicy.getMinimumLoadableRetryCount(loadable.type));
eventDispatcher.loadStarted( mediaSourceEventDispatcher.loadStarted(
new LoadEventInfo(loadable.loadTaskId, loadable.dataSpec, elapsedRealtimeMs), new LoadEventInfo(loadable.loadTaskId, loadable.dataSpec, elapsedRealtimeMs),
loadable.type, loadable.type,
trackType, trackType,
...@@ -735,7 +743,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -735,7 +743,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
loadDurationMs, loadDurationMs,
loadable.bytesLoaded()); loadable.bytesLoaded());
loadErrorHandlingPolicy.onLoadTaskConcluded(loadable.loadTaskId); loadErrorHandlingPolicy.onLoadTaskConcluded(loadable.loadTaskId);
eventDispatcher.loadCompleted( mediaSourceEventDispatcher.loadCompleted(
loadEventInfo, loadEventInfo,
loadable.type, loadable.type,
trackType, trackType,
...@@ -765,7 +773,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -765,7 +773,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
loadDurationMs, loadDurationMs,
loadable.bytesLoaded()); loadable.bytesLoaded());
loadErrorHandlingPolicy.onLoadTaskConcluded(loadable.loadTaskId); loadErrorHandlingPolicy.onLoadTaskConcluded(loadable.loadTaskId);
eventDispatcher.loadCanceled( mediaSourceEventDispatcher.loadCanceled(
loadEventInfo, loadEventInfo,
loadable.type, loadable.type,
trackType, trackType,
...@@ -838,7 +846,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -838,7 +846,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
} }
boolean wasCanceled = !loadErrorAction.isRetry(); boolean wasCanceled = !loadErrorAction.isRetry();
eventDispatcher.loadError( mediaSourceEventDispatcher.loadError(
loadEventInfo, loadEventInfo,
loadable.type, loadable.type,
trackType, trackType,
...@@ -910,7 +918,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -910,7 +918,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
} }
loadingFinished = false; loadingFinished = false;
eventDispatcher.upstreamDiscarded( mediaSourceEventDispatcher.upstreamDiscarded(
primarySampleQueueType, firstRemovedChunk.startTimeUs, endTimeUs); primarySampleQueueType, firstRemovedChunk.startTimeUs, endTimeUs);
} }
...@@ -989,7 +997,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -989,7 +997,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
allocator, allocator,
/* playbackLooper= */ handler.getLooper(), /* playbackLooper= */ handler.getLooper(),
drmSessionManager, drmSessionManager,
eventDispatcher, drmEventDispatcher,
overridingDrmInitData); overridingDrmInitData);
if (isAudioVideo) { if (isAudioVideo) {
sampleQueue.setDrmInitData(drmInitData); sampleQueue.setDrmInitData(drmInitData);
...@@ -1496,7 +1504,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; ...@@ -1496,7 +1504,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
Allocator allocator, Allocator allocator,
Looper playbackLooper, Looper playbackLooper,
DrmSessionManager drmSessionManager, DrmSessionManager drmSessionManager,
MediaSourceEventDispatcher eventDispatcher, DrmSessionEventListener.EventDispatcher eventDispatcher,
Map<String, DrmInitData> overridingDrmInitData) { Map<String, DrmInitData> overridingDrmInitData) {
super(allocator, playbackLooper, drmSessionManager, eventDispatcher); super(allocator, playbackLooper, drmSessionManager, eventDispatcher);
this.overridingDrmInitData = overridingDrmInitData; this.overridingDrmInitData = overridingDrmInitData;
......
...@@ -22,10 +22,11 @@ import static org.mockito.Mockito.when; ...@@ -22,10 +22,11 @@ import static org.mockito.Mockito.when;
import android.net.Uri; import android.net.Uri;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.source.CompositeSequenceableLoaderFactory; import com.google.android.exoplayer2.source.CompositeSequenceableLoaderFactory;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher; import com.google.android.exoplayer2.source.MediaSourceEventListener;
import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist; import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist;
import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist.Rendition; import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist.Rendition;
import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist.Variant; import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist.Variant;
...@@ -77,18 +78,18 @@ public final class HlsMediaPeriodTest { ...@@ -77,18 +78,18 @@ public final class HlsMediaPeriodTest {
when(mockDataSourceFactory.createDataSource(anyInt())).thenReturn(mock(DataSource.class)); when(mockDataSourceFactory.createDataSource(anyInt())).thenReturn(mock(DataSource.class));
HlsPlaylistTracker mockPlaylistTracker = mock(HlsPlaylistTracker.class); HlsPlaylistTracker mockPlaylistTracker = mock(HlsPlaylistTracker.class);
when(mockPlaylistTracker.getMasterPlaylist()).thenReturn((HlsMasterPlaylist) playlist); when(mockPlaylistTracker.getMasterPlaylist()).thenReturn((HlsMasterPlaylist) playlist);
MediaPeriodId mediaPeriodId = new MediaPeriodId(/* periodUid= */ new Object());
return new HlsMediaPeriod( return new HlsMediaPeriod(
mock(HlsExtractorFactory.class), mock(HlsExtractorFactory.class),
mockPlaylistTracker, mockPlaylistTracker,
mockDataSourceFactory, mockDataSourceFactory,
mock(TransferListener.class), mock(TransferListener.class),
mock(DrmSessionManager.class), mock(DrmSessionManager.class),
new DrmSessionEventListener.EventDispatcher()
.withParameters(/* windowIndex= */ 0, mediaPeriodId),
mock(LoadErrorHandlingPolicy.class), mock(LoadErrorHandlingPolicy.class),
new EventDispatcher() new MediaSourceEventListener.EventDispatcher()
.withParameters( .withParameters(/* windowIndex= */ 0, mediaPeriodId, /* mediaTimeOffsetMs= */ 0),
/* windowIndex= */ 0,
/* mediaPeriodId= */ new MediaPeriodId(/* periodUid= */ new Object()),
/* mediaTimeOffsetMs= */ 0),
mock(Allocator.class), mock(Allocator.class),
mock(CompositeSequenceableLoaderFactory.class), mock(CompositeSequenceableLoaderFactory.class),
/* allowChunklessPreparation =*/ true, /* allowChunklessPreparation =*/ true,
......
...@@ -19,11 +19,12 @@ import androidx.annotation.Nullable; ...@@ -19,11 +19,12 @@ import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.SeekParameters; import com.google.android.exoplayer2.SeekParameters;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.offline.StreamKey; import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.source.CompositeSequenceableLoaderFactory; import com.google.android.exoplayer2.source.CompositeSequenceableLoaderFactory;
import com.google.android.exoplayer2.source.MediaPeriod; import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher; import com.google.android.exoplayer2.source.MediaSourceEventListener;
import com.google.android.exoplayer2.source.SampleStream; import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.source.SequenceableLoader; import com.google.android.exoplayer2.source.SequenceableLoader;
import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.TrackGroup;
...@@ -48,8 +49,9 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -48,8 +49,9 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
@Nullable private final TransferListener transferListener; @Nullable private final TransferListener transferListener;
private final LoaderErrorThrower manifestLoaderErrorThrower; private final LoaderErrorThrower manifestLoaderErrorThrower;
private final DrmSessionManager drmSessionManager; private final DrmSessionManager drmSessionManager;
private final DrmSessionEventListener.EventDispatcher drmEventDispatcher;
private final LoadErrorHandlingPolicy loadErrorHandlingPolicy; private final LoadErrorHandlingPolicy loadErrorHandlingPolicy;
private final EventDispatcher eventDispatcher; private final MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher;
private final Allocator allocator; private final Allocator allocator;
private final TrackGroupArray trackGroups; private final TrackGroupArray trackGroups;
private final CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory; private final CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory;
...@@ -66,8 +68,9 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -66,8 +68,9 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
@Nullable TransferListener transferListener, @Nullable TransferListener transferListener,
CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory, CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory,
DrmSessionManager drmSessionManager, DrmSessionManager drmSessionManager,
DrmSessionEventListener.EventDispatcher drmEventDispatcher,
LoadErrorHandlingPolicy loadErrorHandlingPolicy, LoadErrorHandlingPolicy loadErrorHandlingPolicy,
EventDispatcher eventDispatcher, MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher,
LoaderErrorThrower manifestLoaderErrorThrower, LoaderErrorThrower manifestLoaderErrorThrower,
Allocator allocator) { Allocator allocator) {
this.manifest = manifest; this.manifest = manifest;
...@@ -75,15 +78,16 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -75,15 +78,16 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
this.transferListener = transferListener; this.transferListener = transferListener;
this.manifestLoaderErrorThrower = manifestLoaderErrorThrower; this.manifestLoaderErrorThrower = manifestLoaderErrorThrower;
this.drmSessionManager = drmSessionManager; this.drmSessionManager = drmSessionManager;
this.drmEventDispatcher = drmEventDispatcher;
this.loadErrorHandlingPolicy = loadErrorHandlingPolicy; this.loadErrorHandlingPolicy = loadErrorHandlingPolicy;
this.eventDispatcher = eventDispatcher; this.mediaSourceEventDispatcher = mediaSourceEventDispatcher;
this.allocator = allocator; this.allocator = allocator;
this.compositeSequenceableLoaderFactory = compositeSequenceableLoaderFactory; this.compositeSequenceableLoaderFactory = compositeSequenceableLoaderFactory;
trackGroups = buildTrackGroups(manifest, drmSessionManager); trackGroups = buildTrackGroups(manifest, drmSessionManager);
sampleStreams = newSampleStreamArray(0); sampleStreams = newSampleStreamArray(0);
compositeSequenceableLoader = compositeSequenceableLoader =
compositeSequenceableLoaderFactory.createCompositeSequenceableLoader(sampleStreams); compositeSequenceableLoaderFactory.createCompositeSequenceableLoader(sampleStreams);
eventDispatcher.mediaPeriodCreated(); mediaSourceEventDispatcher.mediaPeriodCreated();
} }
public void updateManifest(SsManifest manifest) { public void updateManifest(SsManifest manifest) {
...@@ -99,7 +103,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -99,7 +103,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
sampleStream.release(); sampleStream.release();
} }
callback = null; callback = null;
eventDispatcher.mediaPeriodReleased(); mediaSourceEventDispatcher.mediaPeriodReleased();
} }
// MediaPeriod implementation. // MediaPeriod implementation.
...@@ -197,7 +201,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -197,7 +201,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
@Override @Override
public long readDiscontinuity() { public long readDiscontinuity() {
if (!notifiedReadingStarted) { if (!notifiedReadingStarted) {
eventDispatcher.readingStarted(); mediaSourceEventDispatcher.readingStarted();
notifiedReadingStarted = true; notifiedReadingStarted = true;
} }
return C.TIME_UNSET; return C.TIME_UNSET;
...@@ -254,8 +258,9 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -254,8 +258,9 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
allocator, allocator,
positionUs, positionUs,
drmSessionManager, drmSessionManager,
drmEventDispatcher,
loadErrorHandlingPolicy, loadErrorHandlingPolicy,
eventDispatcher); mediaSourceEventDispatcher);
} }
private static TrackGroupArray buildTrackGroups( private static TrackGroupArray buildTrackGroups(
......
...@@ -26,6 +26,7 @@ import com.google.android.exoplayer2.ExoPlayerLibraryInfo; ...@@ -26,6 +26,7 @@ import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.drm.DrmSession; import com.google.android.exoplayer2.drm.DrmSession;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.offline.FilteringManifestParser; import com.google.android.exoplayer2.offline.FilteringManifestParser;
import com.google.android.exoplayer2.offline.StreamKey; import com.google.android.exoplayer2.offline.StreamKey;
...@@ -632,7 +633,8 @@ public final class SsMediaSource extends BaseMediaSource ...@@ -632,7 +633,8 @@ public final class SsMediaSource extends BaseMediaSource
@Override @Override
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) { public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) {
EventDispatcher eventDispatcher = createEventDispatcher(id); MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher = createEventDispatcher(id);
DrmSessionEventListener.EventDispatcher drmEventDispatcher = createDrmEventDispatcher(id);
SsMediaPeriod period = SsMediaPeriod period =
new SsMediaPeriod( new SsMediaPeriod(
manifest, manifest,
...@@ -640,8 +642,9 @@ public final class SsMediaSource extends BaseMediaSource ...@@ -640,8 +642,9 @@ public final class SsMediaSource extends BaseMediaSource
mediaTransferListener, mediaTransferListener,
compositeSequenceableLoaderFactory, compositeSequenceableLoaderFactory,
drmSessionManager, drmSessionManager,
drmEventDispatcher,
loadErrorHandlingPolicy, loadErrorHandlingPolicy,
eventDispatcher, mediaSourceEventDispatcher,
manifestLoaderErrorThrower, manifestLoaderErrorThrower,
allocator); allocator);
mediaPeriods.add(period); mediaPeriods.add(period);
......
...@@ -22,10 +22,11 @@ import static org.mockito.Mockito.mock; ...@@ -22,10 +22,11 @@ import static org.mockito.Mockito.mock;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.source.CompositeSequenceableLoaderFactory; import com.google.android.exoplayer2.source.CompositeSequenceableLoaderFactory;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher; import com.google.android.exoplayer2.source.MediaSourceEventListener;
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest; import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest;
import com.google.android.exoplayer2.testutil.MediaPeriodAsserts; import com.google.android.exoplayer2.testutil.MediaPeriodAsserts;
import com.google.android.exoplayer2.testutil.MediaPeriodAsserts.FilterableManifestMediaPeriodFactory; import com.google.android.exoplayer2.testutil.MediaPeriodAsserts.FilterableManifestMediaPeriodFactory;
...@@ -61,21 +62,22 @@ public class SsMediaPeriodTest { ...@@ -61,21 +62,22 @@ public class SsMediaPeriodTest {
createStreamElement( createStreamElement(
/* name= */ "text", C.TRACK_TYPE_TEXT, createTextFormat(/* language= */ "eng"))); /* name= */ "text", C.TRACK_TYPE_TEXT, createTextFormat(/* language= */ "eng")));
FilterableManifestMediaPeriodFactory<SsManifest> mediaPeriodFactory = FilterableManifestMediaPeriodFactory<SsManifest> mediaPeriodFactory =
(manifest, periodIndex) -> (manifest, periodIndex) -> {
new SsMediaPeriod( MediaPeriodId mediaPeriodId = new MediaPeriodId(/* periodUid= */ new Object());
return new SsMediaPeriod(
manifest, manifest,
mock(SsChunkSource.Factory.class), mock(SsChunkSource.Factory.class),
mock(TransferListener.class), mock(TransferListener.class),
mock(CompositeSequenceableLoaderFactory.class), mock(CompositeSequenceableLoaderFactory.class),
mock(DrmSessionManager.class), mock(DrmSessionManager.class),
new DrmSessionEventListener.EventDispatcher()
.withParameters(/* windowIndex= */ 0, mediaPeriodId),
mock(LoadErrorHandlingPolicy.class), mock(LoadErrorHandlingPolicy.class),
new EventDispatcher() new MediaSourceEventListener.EventDispatcher()
.withParameters( .withParameters(/* windowIndex= */ 0, mediaPeriodId, /* mediaTimeOffsetMs= */ 0),
/* windowIndex= */ 0,
/* mediaPeriodId= */ new MediaPeriodId(/* periodUid= */ new Object()),
/* mediaTimeOffsetMs= */ 0),
mock(LoaderErrorThrower.class), mock(LoaderErrorThrower.class),
mock(Allocator.class)); mock(Allocator.class));
};
MediaPeriodAsserts.assertGetStreamKeysAndManifestFilterIntegration( MediaPeriodAsserts.assertGetStreamKeysAndManifestFilterIntegration(
mediaPeriodFactory, testManifest); mediaPeriodFactory, testManifest);
......
...@@ -27,6 +27,7 @@ import androidx.test.rule.ActivityTestRule; ...@@ -27,6 +27,7 @@ import androidx.test.rule.ActivityTestRule;
import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.drm.DrmInitData; import com.google.android.exoplayer2.drm.DrmInitData;
import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException; import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.OfflineLicenseHelper; import com.google.android.exoplayer2.drm.OfflineLicenseHelper;
import com.google.android.exoplayer2.source.dash.DashUtil; import com.google.android.exoplayer2.source.dash.DashUtil;
import com.google.android.exoplayer2.source.dash.manifest.DashManifest; import com.google.android.exoplayer2.source.dash.manifest.DashManifest;
...@@ -34,7 +35,6 @@ import com.google.android.exoplayer2.testutil.ActionSchedule; ...@@ -34,7 +35,6 @@ import com.google.android.exoplayer2.testutil.ActionSchedule;
import com.google.android.exoplayer2.testutil.HostActivity; import com.google.android.exoplayer2.testutil.HostActivity;
import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory; import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory;
import com.google.android.exoplayer2.util.MediaSourceEventDispatcher;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import java.io.IOException; import java.io.IOException;
...@@ -77,7 +77,9 @@ public final class DashWidevineOfflineTest { ...@@ -77,7 +77,9 @@ public final class DashWidevineOfflineTest {
if (Util.SDK_INT >= 18) { if (Util.SDK_INT >= 18) {
offlineLicenseHelper = offlineLicenseHelper =
OfflineLicenseHelper.newWidevineInstance( OfflineLicenseHelper.newWidevineInstance(
widevineLicenseUrl, httpDataSourceFactory, new MediaSourceEventDispatcher()); widevineLicenseUrl,
httpDataSourceFactory,
new DrmSessionEventListener.EventDispatcher());
} }
} }
......
...@@ -16,10 +16,11 @@ ...@@ -16,10 +16,11 @@
package com.google.android.exoplayer2.testutil; package com.google.android.exoplayer2.testutil;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.source.CompositeSequenceableLoader; import com.google.android.exoplayer2.source.CompositeSequenceableLoader;
import com.google.android.exoplayer2.source.MediaPeriod; import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher; import com.google.android.exoplayer2.source.MediaSourceEventListener;
import com.google.android.exoplayer2.source.SampleStream; import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.source.SequenceableLoader; import com.google.android.exoplayer2.source.SequenceableLoader;
import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.source.TrackGroupArray;
...@@ -53,7 +54,7 @@ public class FakeAdaptiveMediaPeriod extends FakeMediaPeriod ...@@ -53,7 +54,7 @@ public class FakeAdaptiveMediaPeriod extends FakeMediaPeriod
public FakeAdaptiveMediaPeriod( public FakeAdaptiveMediaPeriod(
TrackGroupArray trackGroupArray, TrackGroupArray trackGroupArray,
EventDispatcher eventDispatcher, MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher,
Allocator allocator, Allocator allocator,
FakeChunkSource.Factory chunkSourceFactory, FakeChunkSource.Factory chunkSourceFactory,
long durationUs, long durationUs,
...@@ -63,8 +64,9 @@ public class FakeAdaptiveMediaPeriod extends FakeMediaPeriod ...@@ -63,8 +64,9 @@ public class FakeAdaptiveMediaPeriod extends FakeMediaPeriod
/* trackDataFactory= */ (unusedFormat, unusedMediaPeriodId) -> { /* trackDataFactory= */ (unusedFormat, unusedMediaPeriodId) -> {
throw new RuntimeException("unused track data"); throw new RuntimeException("unused track data");
}, },
eventDispatcher, mediaSourceEventDispatcher,
DrmSessionManager.DUMMY, DrmSessionManager.DUMMY,
new DrmSessionEventListener.EventDispatcher(),
/* deferOnPrepared= */ false); /* deferOnPrepared= */ false);
this.allocator = allocator; this.allocator = allocator;
this.chunkSourceFactory = chunkSourceFactory; this.chunkSourceFactory = chunkSourceFactory;
...@@ -143,8 +145,9 @@ public class FakeAdaptiveMediaPeriod extends FakeMediaPeriod ...@@ -143,8 +145,9 @@ public class FakeAdaptiveMediaPeriod extends FakeMediaPeriod
protected final SampleStream createSampleStream( protected final SampleStream createSampleStream(
long positionUs, long positionUs,
TrackSelection trackSelection, TrackSelection trackSelection,
MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher,
DrmSessionManager drmSessionManager, DrmSessionManager drmSessionManager,
EventDispatcher eventDispatcher) { DrmSessionEventListener.EventDispatcher drmEventDispatcher) {
FakeChunkSource chunkSource = FakeChunkSource chunkSource =
chunkSourceFactory.createChunkSource(trackSelection, durationUs, transferListener); chunkSourceFactory.createChunkSource(trackSelection, durationUs, transferListener);
return new ChunkSampleStream<>( return new ChunkSampleStream<>(
...@@ -156,8 +159,9 @@ public class FakeAdaptiveMediaPeriod extends FakeMediaPeriod ...@@ -156,8 +159,9 @@ public class FakeAdaptiveMediaPeriod extends FakeMediaPeriod
allocator, allocator,
positionUs, positionUs,
/* drmSessionManager= */ DrmSessionManager.getDummyDrmSessionManager(), /* drmSessionManager= */ DrmSessionManager.getDummyDrmSessionManager(),
drmEventDispatcher,
new DefaultLoadErrorHandlingPolicy(/* minimumLoadableRetryCount= */ 3), new DefaultLoadErrorHandlingPolicy(/* minimumLoadableRetryCount= */ 3),
eventDispatcher); mediaSourceEventDispatcher);
} }
@Override @Override
......
...@@ -18,9 +18,10 @@ package com.google.android.exoplayer2.testutil; ...@@ -18,9 +18,10 @@ package com.google.android.exoplayer2.testutil;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.Timeline.Period; import com.google.android.exoplayer2.Timeline.Period;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher; import com.google.android.exoplayer2.source.MediaSourceEventListener;
import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.TransferListener; import com.google.android.exoplayer2.upstream.TransferListener;
...@@ -53,13 +54,14 @@ public class FakeAdaptiveMediaSource extends FakeMediaSource { ...@@ -53,13 +54,14 @@ public class FakeAdaptiveMediaSource extends FakeMediaSource {
MediaPeriodId id, MediaPeriodId id,
TrackGroupArray trackGroupArray, TrackGroupArray trackGroupArray,
Allocator allocator, Allocator allocator,
MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher,
DrmSessionManager drmSessionManager, DrmSessionManager drmSessionManager,
EventDispatcher eventDispatcher, DrmSessionEventListener.EventDispatcher drmEventDispatcher,
@Nullable TransferListener transferListener) { @Nullable TransferListener transferListener) {
Period period = Util.castNonNull(getTimeline()).getPeriodByUid(id.periodUid, new Period()); Period period = Util.castNonNull(getTimeline()).getPeriodByUid(id.periodUid, new Period());
return new FakeAdaptiveMediaPeriod( return new FakeAdaptiveMediaPeriod(
trackGroupArray, trackGroupArray,
eventDispatcher, mediaSourceEventDispatcher,
allocator, allocator,
chunkSourceFactory, chunkSourceFactory,
period.durationUs, period.durationUs,
......
...@@ -26,6 +26,7 @@ import com.google.android.exoplayer2.Format; ...@@ -26,6 +26,7 @@ import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.Timeline.Period; import com.google.android.exoplayer2.Timeline.Period;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.source.BaseMediaSource; import com.google.android.exoplayer2.source.BaseMediaSource;
import com.google.android.exoplayer2.source.ForwardingTimeline; import com.google.android.exoplayer2.source.ForwardingTimeline;
...@@ -33,7 +34,7 @@ import com.google.android.exoplayer2.source.LoadEventInfo; ...@@ -33,7 +34,7 @@ import com.google.android.exoplayer2.source.LoadEventInfo;
import com.google.android.exoplayer2.source.MediaLoadData; import com.google.android.exoplayer2.source.MediaLoadData;
import com.google.android.exoplayer2.source.MediaPeriod; import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher; import com.google.android.exoplayer2.source.MediaSourceEventListener;
import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.testutil.FakeMediaPeriod.TrackDataFactory; import com.google.android.exoplayer2.testutil.FakeMediaPeriod.TrackDataFactory;
...@@ -215,11 +216,19 @@ public class FakeMediaSource extends BaseMediaSource { ...@@ -215,11 +216,19 @@ public class FakeMediaSource extends BaseMediaSource {
int periodIndex = castNonNull(timeline).getIndexOfPeriod(id.periodUid); int periodIndex = castNonNull(timeline).getIndexOfPeriod(id.periodUid);
Assertions.checkArgument(periodIndex != C.INDEX_UNSET); Assertions.checkArgument(periodIndex != C.INDEX_UNSET);
Period period = timeline.getPeriod(periodIndex, new Period()); Period period = timeline.getPeriod(periodIndex, new Period());
EventDispatcher eventDispatcher = MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher =
createEventDispatcher(period.windowIndex, id, period.getPositionInWindowMs()); createEventDispatcher(period.windowIndex, id, period.getPositionInWindowMs());
DrmSessionEventListener.EventDispatcher drmEventDispatcher =
createDrmEventDispatcher(period.windowIndex, id);
FakeMediaPeriod mediaPeriod = FakeMediaPeriod mediaPeriod =
createFakeMediaPeriod( createFakeMediaPeriod(
id, trackGroupArray, allocator, drmSessionManager, eventDispatcher, transferListener); id,
trackGroupArray,
allocator,
mediaSourceEventDispatcher,
drmSessionManager,
drmEventDispatcher,
transferListener);
activeMediaPeriods.add(mediaPeriod); activeMediaPeriods.add(mediaPeriod);
createdMediaPeriods.add(id); createdMediaPeriods.add(id);
return mediaPeriod; return mediaPeriod;
...@@ -308,7 +317,10 @@ public class FakeMediaSource extends BaseMediaSource { ...@@ -308,7 +317,10 @@ public class FakeMediaSource extends BaseMediaSource {
* @param id The identifier of the period. * @param id The identifier of the period.
* @param trackGroupArray The {@link TrackGroupArray} supported by the media period. * @param trackGroupArray The {@link TrackGroupArray} supported by the media period.
* @param allocator An {@link Allocator} from which to obtain media buffer allocations. * @param allocator An {@link Allocator} from which to obtain media buffer allocations.
* @param eventDispatcher An {@link EventDispatcher} to dispatch media source events. * @param mediaSourceEventDispatcher An {@link MediaSourceEventListener.EventDispatcher} to
* dispatch media source events.
* @param drmEventDispatcher An {@link MediaSourceEventListener.EventDispatcher} to dispatch DRM
* events.
* @param transferListener The transfer listener which should be informed of any data transfers. * @param transferListener The transfer listener which should be informed of any data transfers.
* May be null if no listener is available. * May be null if no listener is available.
* @return A new {@link FakeMediaPeriod}. * @return A new {@link FakeMediaPeriod}.
...@@ -318,8 +330,9 @@ public class FakeMediaSource extends BaseMediaSource { ...@@ -318,8 +330,9 @@ public class FakeMediaSource extends BaseMediaSource {
MediaPeriodId id, MediaPeriodId id,
TrackGroupArray trackGroupArray, TrackGroupArray trackGroupArray,
Allocator allocator, Allocator allocator,
MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher,
DrmSessionManager drmSessionManager, DrmSessionManager drmSessionManager,
EventDispatcher eventDispatcher, DrmSessionEventListener.EventDispatcher drmEventDispatcher,
@Nullable TransferListener transferListener) { @Nullable TransferListener transferListener) {
long positionInWindowUs = long positionInWindowUs =
timeline.getPeriodByUid(id.periodUid, new Period()).getPositionInWindowUs(); timeline.getPeriodByUid(id.periodUid, new Period()).getPositionInWindowUs();
...@@ -329,8 +342,9 @@ public class FakeMediaSource extends BaseMediaSource { ...@@ -329,8 +342,9 @@ public class FakeMediaSource extends BaseMediaSource {
trackDataFactory != null trackDataFactory != null
? trackDataFactory ? trackDataFactory
: TrackDataFactory.singleSampleWithTimeUs(defaultFirstSampleTimeUs), : TrackDataFactory.singleSampleWithTimeUs(defaultFirstSampleTimeUs),
eventDispatcher, mediaSourceEventDispatcher,
drmSessionManager, drmSessionManager,
drmEventDispatcher,
/* deferOnPrepared= */ false); /* deferOnPrepared= */ false);
} }
...@@ -347,7 +361,8 @@ public class FakeMediaSource extends BaseMediaSource { ...@@ -347,7 +361,8 @@ public class FakeMediaSource extends BaseMediaSource {
/* mediaStartTimeMs= */ C.TIME_UNSET, /* mediaStartTimeMs= */ C.TIME_UNSET,
/* mediaEndTimeMs = */ C.TIME_UNSET); /* mediaEndTimeMs = */ C.TIME_UNSET);
long elapsedRealTimeMs = SystemClock.elapsedRealtime(); long elapsedRealTimeMs = SystemClock.elapsedRealtime();
EventDispatcher eventDispatcher = createEventDispatcher(/* mediaPeriodId= */ null); MediaSourceEventListener.EventDispatcher eventDispatcher =
createEventDispatcher(/* mediaPeriodId= */ null);
long loadTaskId = LoadEventInfo.getNewId(); long loadTaskId = LoadEventInfo.getNewId();
eventDispatcher.loadStarted( eventDispatcher.loadStarted(
new LoadEventInfo( new LoadEventInfo(
......
...@@ -25,8 +25,9 @@ import com.google.android.exoplayer2.FormatHolder; ...@@ -25,8 +25,9 @@ import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.drm.DrmInitData; import com.google.android.exoplayer2.drm.DrmInitData;
import com.google.android.exoplayer2.drm.DrmSession; import com.google.android.exoplayer2.drm.DrmSession;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher; import com.google.android.exoplayer2.source.MediaSourceEventListener;
import com.google.android.exoplayer2.source.SampleStream; import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
...@@ -126,10 +127,11 @@ public class FakeSampleStream implements SampleStream { ...@@ -126,10 +127,11 @@ public class FakeSampleStream implements SampleStream {
} }
} }
@Nullable private final MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher;
private final Format initialFormat; private final Format initialFormat;
private final List<FakeSampleStreamItem> fakeSampleStreamItems; private final List<FakeSampleStreamItem> fakeSampleStreamItems;
private final DrmSessionManager drmSessionManager; private final DrmSessionManager drmSessionManager;
@Nullable private final EventDispatcher eventDispatcher; private final DrmSessionEventListener.EventDispatcher drmEventDispatcher;
private int sampleItemIndex; private int sampleItemIndex;
private @MonotonicNonNull Format downstreamFormat; private @MonotonicNonNull Format downstreamFormat;
...@@ -140,8 +142,11 @@ public class FakeSampleStream implements SampleStream { ...@@ -140,8 +142,11 @@ public class FakeSampleStream implements SampleStream {
* Creates a fake sample stream which outputs the given {@link Format} followed by the provided * Creates a fake sample stream which outputs the given {@link Format} followed by the provided
* {@link FakeSampleStreamItem items}. * {@link FakeSampleStreamItem items}.
* *
* @param mediaSourceEventDispatcher A {@link MediaSourceEventListener.EventDispatcher} to notify
* of media events.
* @param drmSessionManager A {@link DrmSessionManager} for DRM interactions. * @param drmSessionManager A {@link DrmSessionManager} for DRM interactions.
* @param eventDispatcher An {@link EventDispatcher} to notify of read events. * @param drmEventDispatcher A {@link DrmSessionEventListener.EventDispatcher} to notify of DRM
* events.
* @param initialFormat The first {@link Format} to output. * @param initialFormat The first {@link Format} to output.
* @param fakeSampleStreamItems The {@link FakeSampleStreamItem items} to customize the return * @param fakeSampleStreamItems The {@link FakeSampleStreamItem items} to customize the return
* values of {@link #readData(FormatHolder, DecoderInputBuffer, boolean)}. This is assumed to * values of {@link #readData(FormatHolder, DecoderInputBuffer, boolean)}. This is assumed to
...@@ -150,12 +155,14 @@ public class FakeSampleStream implements SampleStream { ...@@ -150,12 +155,14 @@ public class FakeSampleStream implements SampleStream {
* FakeSampleStreamItem#END_OF_STREAM_ITEM}. * FakeSampleStreamItem#END_OF_STREAM_ITEM}.
*/ */
public FakeSampleStream( public FakeSampleStream(
@Nullable MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher,
DrmSessionManager drmSessionManager, DrmSessionManager drmSessionManager,
@Nullable EventDispatcher eventDispatcher, DrmSessionEventListener.EventDispatcher drmEventDispatcher,
Format initialFormat, Format initialFormat,
List<FakeSampleStreamItem> fakeSampleStreamItems) { List<FakeSampleStreamItem> fakeSampleStreamItems) {
this.mediaSourceEventDispatcher = mediaSourceEventDispatcher;
this.drmSessionManager = drmSessionManager; this.drmSessionManager = drmSessionManager;
this.eventDispatcher = eventDispatcher; this.drmEventDispatcher = drmEventDispatcher;
this.initialFormat = initialFormat; this.initialFormat = initialFormat;
this.fakeSampleStreamItems = new ArrayList<>(fakeSampleStreamItems); this.fakeSampleStreamItems = new ArrayList<>(fakeSampleStreamItems);
} }
...@@ -268,13 +275,13 @@ public class FakeSampleStream implements SampleStream { ...@@ -268,13 +275,13 @@ public class FakeSampleStream implements SampleStream {
Looper playbackLooper = Assertions.checkNotNull(Looper.myLooper()); Looper playbackLooper = Assertions.checkNotNull(Looper.myLooper());
currentDrmSession = currentDrmSession =
newDrmInitData != null newDrmInitData != null
? drmSessionManager.acquireSession(playbackLooper, eventDispatcher, newDrmInitData) ? drmSessionManager.acquireSession(playbackLooper, drmEventDispatcher, newDrmInitData)
: drmSessionManager.acquirePlaceholderSession( : drmSessionManager.acquirePlaceholderSession(
playbackLooper, MimeTypes.getTrackType(newFormat.sampleMimeType)); playbackLooper, MimeTypes.getTrackType(newFormat.sampleMimeType));
outputFormatHolder.drmSession = currentDrmSession; outputFormatHolder.drmSession = currentDrmSession;
if (previousSession != null) { if (previousSession != null) {
previousSession.release(eventDispatcher); previousSession.release(drmEventDispatcher);
} }
} }
...@@ -308,13 +315,13 @@ public class FakeSampleStream implements SampleStream { ...@@ -308,13 +315,13 @@ public class FakeSampleStream implements SampleStream {
/** Release this SampleStream and all underlying resources. */ /** Release this SampleStream and all underlying resources. */
public void release() { public void release() {
if (currentDrmSession != null) { if (currentDrmSession != null) {
currentDrmSession.release(eventDispatcher); currentDrmSession.release(drmEventDispatcher);
currentDrmSession = null; currentDrmSession = null;
} }
} }
private void notifyEventDispatcher(Format format) { private void notifyEventDispatcher(Format format) {
if (eventDispatcher != null) { if (mediaSourceEventDispatcher != null) {
@Nullable SampleInfo sampleInfo = null; @Nullable SampleInfo sampleInfo = null;
for (int i = sampleItemIndex; i < fakeSampleStreamItems.size(); i++) { for (int i = sampleItemIndex; i < fakeSampleStreamItems.size(); i++) {
sampleInfo = fakeSampleStreamItems.get(i).sampleInfo; sampleInfo = fakeSampleStreamItems.get(i).sampleInfo;
...@@ -323,7 +330,7 @@ public class FakeSampleStream implements SampleStream { ...@@ -323,7 +330,7 @@ public class FakeSampleStream implements SampleStream {
} }
} }
long nextSampleTimeUs = sampleInfo != null ? sampleInfo.timeUs : C.TIME_END_OF_SOURCE; long nextSampleTimeUs = sampleInfo != null ? sampleInfo.timeUs : C.TIME_END_OF_SOURCE;
eventDispatcher.downstreamFormatChanged( mediaSourceEventDispatcher.downstreamFormatChanged(
C.TRACK_TYPE_UNKNOWN, C.TRACK_TYPE_UNKNOWN,
format, format,
C.SELECTION_REASON_UNKNOWN, C.SELECTION_REASON_UNKNOWN,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment