mirror of
https://github.com/samsonjs/media.git
synced 2026-04-05 11:15:46 +00:00
Rollback of ee8df7afcb
*** Original commit *** Ensure MediaSourceFactory instances can be re-used This fixes DefaultDrmSessionManager so it can be used by a new Player instance (by nulling out its reference to the playback thread, which is unique per-Player instance). This only works if the DefaultDrmSessionManager is 'fully released' before being used by the second Player instance, meaning that the reference count of the manager and all its sessions is zero. #exofixit Issue: #9099 *** PiperOrigin-RevId: 396861138
This commit is contained in:
parent
5f0395ee2d
commit
4433ac5a2a
4 changed files with 8 additions and 124 deletions
|
|
@ -20,10 +20,6 @@
|
|||
* Fix a bug when [depending on ExoPlayer locally](README.md#locally) with
|
||||
a relative path
|
||||
([#9403](https://github.com/google/ExoPlayer/issues/9403)).
|
||||
* Fix bug in `DefaultDrmSessionManager` which prevented
|
||||
`MediaSourceFactory` instances from being re-used by `ExoPlayer`
|
||||
instances with non-overlapping lifecycles
|
||||
([#9099](https://github.com/google/ExoPlayer/issues/9099)).
|
||||
* Better handle invalid seek requests. Seeks to positions that are before
|
||||
the start or after the end of the media are now handled as seeks to the
|
||||
start and end respectively
|
||||
|
|
|
|||
|
|
@ -1,99 +0,0 @@
|
|||
/*
|
||||
* Copyright 2021 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.source;
|
||||
|
||||
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.ExoPlayer;
|
||||
import com.google.android.exoplayer2.MediaItem;
|
||||
import com.google.android.exoplayer2.PlaybackException;
|
||||
import com.google.android.exoplayer2.Player;
|
||||
import com.google.android.exoplayer2.SimpleExoPlayer;
|
||||
import com.google.android.exoplayer2.util.ConditionVariable;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
/** Instrumentation tests for {@link DefaultMediaSourceFactory}. */
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public final class DefaultMediaSourceFactoryInstrumentationTest {
|
||||
|
||||
// https://github.com/google/ExoPlayer/issues/9099
|
||||
@Test
|
||||
public void reuseMediaSourceFactoryBetweenPlayerInstances() throws Exception {
|
||||
MediaItem mediaItem =
|
||||
new MediaItem.Builder()
|
||||
.setUri("asset:///media/mp4/sample.mp4")
|
||||
.setDrmUuid(C.WIDEVINE_UUID)
|
||||
.setDrmSessionForClearPeriods(true)
|
||||
.build();
|
||||
AtomicReference<SimpleExoPlayer> player = new AtomicReference<>();
|
||||
DefaultMediaSourceFactory defaultMediaSourceFactory =
|
||||
new DefaultMediaSourceFactory(getInstrumentation().getContext());
|
||||
getInstrumentation()
|
||||
.runOnMainSync(
|
||||
() ->
|
||||
player.set(
|
||||
new ExoPlayer.Builder(getInstrumentation().getContext())
|
||||
.setMediaSourceFactory(defaultMediaSourceFactory)
|
||||
.build()));
|
||||
playUntilEndAndRelease(player.get(), mediaItem);
|
||||
getInstrumentation()
|
||||
.runOnMainSync(
|
||||
() ->
|
||||
player.set(
|
||||
new ExoPlayer.Builder(getInstrumentation().getContext())
|
||||
.setMediaSourceFactory(defaultMediaSourceFactory)
|
||||
.build()));
|
||||
playUntilEndAndRelease(player.get(), mediaItem);
|
||||
}
|
||||
|
||||
private void playUntilEndAndRelease(Player player, MediaItem mediaItem)
|
||||
throws InterruptedException {
|
||||
ConditionVariable playbackComplete = new ConditionVariable();
|
||||
AtomicReference<PlaybackException> playbackException = new AtomicReference<>();
|
||||
getInstrumentation()
|
||||
.runOnMainSync(
|
||||
() -> {
|
||||
player.addListener(
|
||||
new Player.Listener() {
|
||||
@Override
|
||||
public void onPlaybackStateChanged(@Player.State int playbackState) {
|
||||
if (playbackState == Player.STATE_ENDED) {
|
||||
playbackComplete.open();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerError(PlaybackException error) {
|
||||
playbackException.set(error);
|
||||
playbackComplete.open();
|
||||
}
|
||||
});
|
||||
player.setMediaItem(mediaItem);
|
||||
player.prepare();
|
||||
player.play();
|
||||
});
|
||||
|
||||
playbackComplete.block();
|
||||
getInstrumentation().runOnMainSync(player::release);
|
||||
getInstrumentation().waitForIdleSync();
|
||||
assertThat(playbackException.get()).isNull();
|
||||
}
|
||||
}
|
||||
|
|
@ -53,6 +53,7 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import org.checkerframework.checker.nullness.qual.EnsuresNonNull;
|
||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
|
||||
/**
|
||||
* A {@link DrmSessionManager} that supports playbacks using {@link ExoMediaDrm}.
|
||||
|
|
@ -297,8 +298,8 @@ public class DefaultDrmSessionManager implements DrmSessionManager {
|
|||
@Nullable private ExoMediaDrm exoMediaDrm;
|
||||
@Nullable private DefaultDrmSession placeholderDrmSession;
|
||||
@Nullable private DefaultDrmSession noMultiSessionDrmSession;
|
||||
@Nullable private Looper playbackLooper;
|
||||
@Nullable private Handler playbackHandler;
|
||||
private @MonotonicNonNull Looper playbackLooper;
|
||||
private @MonotonicNonNull Handler playbackHandler;
|
||||
private int mode;
|
||||
@Nullable private byte[] offlineLicenseKeySetId;
|
||||
|
||||
|
|
@ -483,7 +484,7 @@ public class DefaultDrmSessionManager implements DrmSessionManager {
|
|||
}
|
||||
releaseAllPreacquiredSessions();
|
||||
|
||||
maybeFullyReleaseManager();
|
||||
maybeReleaseMediaDrm();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -662,7 +663,6 @@ public class DefaultDrmSessionManager implements DrmSessionManager {
|
|||
this.playbackLooper = playbackLooper;
|
||||
this.playbackHandler = new Handler(playbackLooper);
|
||||
} else {
|
||||
// Check this manager is only being used by a single player at a time.
|
||||
checkState(this.playbackLooper == playbackLooper);
|
||||
checkNotNull(playbackHandler);
|
||||
}
|
||||
|
|
@ -787,18 +787,12 @@ public class DefaultDrmSessionManager implements DrmSessionManager {
|
|||
return session;
|
||||
}
|
||||
|
||||
private void maybeFullyReleaseManager() {
|
||||
private void maybeReleaseMediaDrm() {
|
||||
if (exoMediaDrm != null
|
||||
&& prepareCallsCount == 0
|
||||
&& sessions.isEmpty()
|
||||
&& preacquiredSessionReferences.isEmpty()) {
|
||||
// This manager and all its sessions are fully released so we can null out the looper &
|
||||
// handler references and release exoMediaDrm.
|
||||
if (playbackLooper != null) {
|
||||
checkNotNull(playbackHandler).removeCallbacksAndMessages(/* token= */ null);
|
||||
playbackHandler = null;
|
||||
playbackLooper = null;
|
||||
}
|
||||
// This manager and all its sessions are fully released so we can release exoMediaDrm.
|
||||
checkNotNull(exoMediaDrm).release();
|
||||
exoMediaDrm = null;
|
||||
}
|
||||
|
|
@ -949,7 +943,7 @@ public class DefaultDrmSessionManager implements DrmSessionManager {
|
|||
keepaliveSessions.remove(session);
|
||||
}
|
||||
}
|
||||
maybeFullyReleaseManager();
|
||||
maybeReleaseMediaDrm();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ import android.net.Uri;
|
|||
import androidx.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.MediaItem;
|
||||
import com.google.android.exoplayer2.Player;
|
||||
import com.google.android.exoplayer2.drm.DefaultDrmSessionManager;
|
||||
import com.google.android.exoplayer2.drm.DefaultDrmSessionManagerProvider;
|
||||
import com.google.android.exoplayer2.drm.DrmSessionManager;
|
||||
|
|
@ -32,13 +31,7 @@ import com.google.android.exoplayer2.upstream.HttpDataSource;
|
|||
import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Factory for creating {@link MediaSource MediaSources} from {@link MediaItem MediaItems}.
|
||||
*
|
||||
* <p>A factory must only be used by a single {@link Player} at a time. A factory can only be
|
||||
* re-used by a second {@link Player} if the previous {@link Player} and all associated resources
|
||||
* are fully released.
|
||||
*/
|
||||
/** Factory for creating {@link MediaSource MediaSources} from {@link MediaItem MediaItems}. */
|
||||
public interface MediaSourceFactory {
|
||||
|
||||
/** @deprecated Use {@link MediaItem.PlaybackProperties#streamKeys} instead. */
|
||||
|
|
|
|||
Loading…
Reference in a new issue