mirror of
https://github.com/androidx/media.git
synced 2025-05-07 23:50:44 +08:00
Use Handler instead of ExoPlayer messages in ConcatenatingMediaSource
ExoPlayer methods must not be called from any thread besides the specified app thread. Therefore we shouldn't use them here. Using a regular Handler instead is fully equivalent. Issue:#5240 PiperOrigin-RevId: 227650489
This commit is contained in:
parent
f11abbda97
commit
fc16833903
@ -4,6 +4,9 @@
|
|||||||
|
|
||||||
* IMA extension: Clear ads loader listeners on release
|
* IMA extension: Clear ads loader listeners on release
|
||||||
([#4114](https://github.com/google/ExoPlayer/issues/4114)).
|
([#4114](https://github.com/google/ExoPlayer/issues/4114)).
|
||||||
|
* Fix issue where sending callbacks for playlist changes may cause problems
|
||||||
|
because of parallel player access
|
||||||
|
([#5240](https://github.com/google/ExoPlayer/issues/5240)).
|
||||||
|
|
||||||
### 2.9.3 ###
|
### 2.9.3 ###
|
||||||
|
|
||||||
|
@ -16,13 +16,12 @@
|
|||||||
package com.google.android.exoplayer2.source;
|
package com.google.android.exoplayer2.source;
|
||||||
|
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.os.Message;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.ExoPlaybackException;
|
|
||||||
import com.google.android.exoplayer2.ExoPlayer;
|
import com.google.android.exoplayer2.ExoPlayer;
|
||||||
import com.google.android.exoplayer2.PlayerMessage;
|
|
||||||
import com.google.android.exoplayer2.Timeline;
|
import com.google.android.exoplayer2.Timeline;
|
||||||
import com.google.android.exoplayer2.source.ConcatenatingMediaSource.MediaSourceHolder;
|
import com.google.android.exoplayer2.source.ConcatenatingMediaSource.MediaSourceHolder;
|
||||||
import com.google.android.exoplayer2.source.ShuffleOrder.DefaultShuffleOrder;
|
import com.google.android.exoplayer2.source.ShuffleOrder.DefaultShuffleOrder;
|
||||||
@ -45,8 +44,7 @@ import java.util.Map;
|
|||||||
* during playback. It is valid for the same {@link MediaSource} instance to be present more than
|
* during playback. It is valid for the same {@link MediaSource} instance to be present more than
|
||||||
* once in the concatenation. Access to this class is thread-safe.
|
* once in the concatenation. Access to this class is thread-safe.
|
||||||
*/
|
*/
|
||||||
public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHolder>
|
public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHolder> {
|
||||||
implements PlayerMessage.Target {
|
|
||||||
|
|
||||||
private static final int MSG_ADD = 0;
|
private static final int MSG_ADD = 0;
|
||||||
private static final int MSG_REMOVE = 1;
|
private static final int MSG_REMOVE = 1;
|
||||||
@ -68,8 +66,8 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
|
|||||||
private final Timeline.Window window;
|
private final Timeline.Window window;
|
||||||
private final Timeline.Period period;
|
private final Timeline.Period period;
|
||||||
|
|
||||||
private @Nullable ExoPlayer player;
|
@Nullable private Handler playbackThreadHandler;
|
||||||
private @Nullable Handler playerApplicationHandler;
|
@Nullable private Handler applicationThreadHandler;
|
||||||
private boolean listenerNotificationScheduled;
|
private boolean listenerNotificationScheduled;
|
||||||
private ShuffleOrder shuffleOrder;
|
private ShuffleOrder shuffleOrder;
|
||||||
private int windowCount;
|
private int windowCount;
|
||||||
@ -239,12 +237,10 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
|
|||||||
mediaSourceHolders.add(new MediaSourceHolder(mediaSource));
|
mediaSourceHolders.add(new MediaSourceHolder(mediaSource));
|
||||||
}
|
}
|
||||||
mediaSourcesPublic.addAll(index, mediaSourceHolders);
|
mediaSourcesPublic.addAll(index, mediaSourceHolders);
|
||||||
if (player != null && !mediaSources.isEmpty()) {
|
if (playbackThreadHandler != null && !mediaSources.isEmpty()) {
|
||||||
player
|
playbackThreadHandler
|
||||||
.createMessage(this)
|
.obtainMessage(MSG_ADD, new MessageData<>(index, mediaSourceHolders, actionOnCompletion))
|
||||||
.setType(MSG_ADD)
|
.sendToTarget();
|
||||||
.setPayload(new MessageData<>(index, mediaSourceHolders, actionOnCompletion))
|
|
||||||
.send();
|
|
||||||
} else if (actionOnCompletion != null) {
|
} else if (actionOnCompletion != null) {
|
||||||
actionOnCompletion.run();
|
actionOnCompletion.run();
|
||||||
}
|
}
|
||||||
@ -328,12 +324,10 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (player != null) {
|
if (playbackThreadHandler != null) {
|
||||||
player
|
playbackThreadHandler
|
||||||
.createMessage(this)
|
.obtainMessage(MSG_REMOVE, new MessageData<>(fromIndex, toIndex, actionOnCompletion))
|
||||||
.setType(MSG_REMOVE)
|
.sendToTarget();
|
||||||
.setPayload(new MessageData<>(fromIndex, toIndex, actionOnCompletion))
|
|
||||||
.send();
|
|
||||||
} else if (actionOnCompletion != null) {
|
} else if (actionOnCompletion != null) {
|
||||||
actionOnCompletion.run();
|
actionOnCompletion.run();
|
||||||
}
|
}
|
||||||
@ -371,12 +365,10 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mediaSourcesPublic.add(newIndex, mediaSourcesPublic.remove(currentIndex));
|
mediaSourcesPublic.add(newIndex, mediaSourcesPublic.remove(currentIndex));
|
||||||
if (player != null) {
|
if (playbackThreadHandler != null) {
|
||||||
player
|
playbackThreadHandler
|
||||||
.createMessage(this)
|
.obtainMessage(MSG_MOVE, new MessageData<>(currentIndex, newIndex, actionOnCompletion))
|
||||||
.setType(MSG_MOVE)
|
.sendToTarget();
|
||||||
.setPayload(new MessageData<>(currentIndex, newIndex, actionOnCompletion))
|
|
||||||
.send();
|
|
||||||
} else if (actionOnCompletion != null) {
|
} else if (actionOnCompletion != null) {
|
||||||
actionOnCompletion.run();
|
actionOnCompletion.run();
|
||||||
}
|
}
|
||||||
@ -430,8 +422,8 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
|
|||||||
*/
|
*/
|
||||||
public final synchronized void setShuffleOrder(
|
public final synchronized void setShuffleOrder(
|
||||||
ShuffleOrder shuffleOrder, @Nullable Runnable actionOnCompletion) {
|
ShuffleOrder shuffleOrder, @Nullable Runnable actionOnCompletion) {
|
||||||
ExoPlayer player = this.player;
|
Handler playbackThreadHandler = this.playbackThreadHandler;
|
||||||
if (player != null) {
|
if (playbackThreadHandler != null) {
|
||||||
int size = getSize();
|
int size = getSize();
|
||||||
if (shuffleOrder.getLength() != size) {
|
if (shuffleOrder.getLength() != size) {
|
||||||
shuffleOrder =
|
shuffleOrder =
|
||||||
@ -439,11 +431,11 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
|
|||||||
.cloneAndClear()
|
.cloneAndClear()
|
||||||
.cloneAndInsert(/* insertionIndex= */ 0, /* insertionCount= */ size);
|
.cloneAndInsert(/* insertionIndex= */ 0, /* insertionCount= */ size);
|
||||||
}
|
}
|
||||||
player
|
playbackThreadHandler
|
||||||
.createMessage(this)
|
.obtainMessage(
|
||||||
.setType(MSG_SET_SHUFFLE_ORDER)
|
MSG_SET_SHUFFLE_ORDER,
|
||||||
.setPayload(new MessageData<>(/* index= */ 0, shuffleOrder, actionOnCompletion))
|
new MessageData<>(/* index= */ 0, shuffleOrder, actionOnCompletion))
|
||||||
.send();
|
.sendToTarget();
|
||||||
} else {
|
} else {
|
||||||
this.shuffleOrder =
|
this.shuffleOrder =
|
||||||
shuffleOrder.getLength() > 0 ? shuffleOrder.cloneAndClear() : shuffleOrder;
|
shuffleOrder.getLength() > 0 ? shuffleOrder.cloneAndClear() : shuffleOrder;
|
||||||
@ -465,8 +457,8 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
|
|||||||
boolean isTopLevelSource,
|
boolean isTopLevelSource,
|
||||||
@Nullable TransferListener mediaTransferListener) {
|
@Nullable TransferListener mediaTransferListener) {
|
||||||
super.prepareSourceInternal(player, isTopLevelSource, mediaTransferListener);
|
super.prepareSourceInternal(player, isTopLevelSource, mediaTransferListener);
|
||||||
this.player = player;
|
playbackThreadHandler = new Handler(/* callback= */ this::handleMessage);
|
||||||
playerApplicationHandler = new Handler(player.getApplicationLooper());
|
applicationThreadHandler = new Handler(player.getApplicationLooper());
|
||||||
if (mediaSourcesPublic.isEmpty()) {
|
if (mediaSourcesPublic.isEmpty()) {
|
||||||
notifyListener();
|
notifyListener();
|
||||||
} else {
|
} else {
|
||||||
@ -519,8 +511,8 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
|
|||||||
super.releaseSourceInternal();
|
super.releaseSourceInternal();
|
||||||
mediaSourceHolders.clear();
|
mediaSourceHolders.clear();
|
||||||
mediaSourceByUid.clear();
|
mediaSourceByUid.clear();
|
||||||
player = null;
|
playbackThreadHandler = null;
|
||||||
playerApplicationHandler = null;
|
applicationThreadHandler = null;
|
||||||
shuffleOrder = shuffleOrder.cloneAndClear();
|
shuffleOrder = shuffleOrder.cloneAndClear();
|
||||||
windowCount = 0;
|
windowCount = 0;
|
||||||
periodCount = 0;
|
periodCount = 0;
|
||||||
@ -556,24 +548,22 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
|
|||||||
return windowIndex + mediaSourceHolder.firstWindowIndexInChild;
|
return windowIndex + mediaSourceHolder.firstWindowIndexInChild;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public final void handleMessage(int messageType, @Nullable Object message)
|
private boolean handleMessage(Message msg) {
|
||||||
throws ExoPlaybackException {
|
if (playbackThreadHandler == null) {
|
||||||
if (player == null) {
|
|
||||||
// Stale event.
|
// Stale event.
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
switch (messageType) {
|
switch (msg.what) {
|
||||||
case MSG_ADD:
|
case MSG_ADD:
|
||||||
MessageData<Collection<MediaSourceHolder>> addMessage =
|
MessageData<Collection<MediaSourceHolder>> addMessage =
|
||||||
(MessageData<Collection<MediaSourceHolder>>) Util.castNonNull(message);
|
(MessageData<Collection<MediaSourceHolder>>) Util.castNonNull(msg.obj);
|
||||||
shuffleOrder = shuffleOrder.cloneAndInsert(addMessage.index, addMessage.customData.size());
|
shuffleOrder = shuffleOrder.cloneAndInsert(addMessage.index, addMessage.customData.size());
|
||||||
addMediaSourcesInternal(addMessage.index, addMessage.customData);
|
addMediaSourcesInternal(addMessage.index, addMessage.customData);
|
||||||
scheduleListenerNotification(addMessage.actionOnCompletion);
|
scheduleListenerNotification(addMessage.actionOnCompletion);
|
||||||
break;
|
break;
|
||||||
case MSG_REMOVE:
|
case MSG_REMOVE:
|
||||||
MessageData<Integer> removeMessage = (MessageData<Integer>) Util.castNonNull(message);
|
MessageData<Integer> removeMessage = (MessageData<Integer>) Util.castNonNull(msg.obj);
|
||||||
int fromIndex = removeMessage.index;
|
int fromIndex = removeMessage.index;
|
||||||
int toIndex = removeMessage.customData;
|
int toIndex = removeMessage.customData;
|
||||||
if (fromIndex == 0 && toIndex == shuffleOrder.getLength()) {
|
if (fromIndex == 0 && toIndex == shuffleOrder.getLength()) {
|
||||||
@ -587,7 +577,7 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
|
|||||||
scheduleListenerNotification(removeMessage.actionOnCompletion);
|
scheduleListenerNotification(removeMessage.actionOnCompletion);
|
||||||
break;
|
break;
|
||||||
case MSG_MOVE:
|
case MSG_MOVE:
|
||||||
MessageData<Integer> moveMessage = (MessageData<Integer>) Util.castNonNull(message);
|
MessageData<Integer> moveMessage = (MessageData<Integer>) Util.castNonNull(msg.obj);
|
||||||
shuffleOrder = shuffleOrder.cloneAndRemove(moveMessage.index, moveMessage.index + 1);
|
shuffleOrder = shuffleOrder.cloneAndRemove(moveMessage.index, moveMessage.index + 1);
|
||||||
shuffleOrder = shuffleOrder.cloneAndInsert(moveMessage.customData, 1);
|
shuffleOrder = shuffleOrder.cloneAndInsert(moveMessage.customData, 1);
|
||||||
moveMediaSourceInternal(moveMessage.index, moveMessage.customData);
|
moveMediaSourceInternal(moveMessage.index, moveMessage.customData);
|
||||||
@ -595,7 +585,7 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
|
|||||||
break;
|
break;
|
||||||
case MSG_SET_SHUFFLE_ORDER:
|
case MSG_SET_SHUFFLE_ORDER:
|
||||||
MessageData<ShuffleOrder> shuffleOrderMessage =
|
MessageData<ShuffleOrder> shuffleOrderMessage =
|
||||||
(MessageData<ShuffleOrder>) Util.castNonNull(message);
|
(MessageData<ShuffleOrder>) Util.castNonNull(msg.obj);
|
||||||
shuffleOrder = shuffleOrderMessage.customData;
|
shuffleOrder = shuffleOrderMessage.customData;
|
||||||
scheduleListenerNotification(shuffleOrderMessage.actionOnCompletion);
|
scheduleListenerNotification(shuffleOrderMessage.actionOnCompletion);
|
||||||
break;
|
break;
|
||||||
@ -603,8 +593,8 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
|
|||||||
notifyListener();
|
notifyListener();
|
||||||
break;
|
break;
|
||||||
case MSG_ON_COMPLETION:
|
case MSG_ON_COMPLETION:
|
||||||
List<Runnable> actionsOnCompletion = (List<Runnable>) Util.castNonNull(message);
|
List<Runnable> actionsOnCompletion = (List<Runnable>) Util.castNonNull(msg.obj);
|
||||||
Handler handler = Assertions.checkNotNull(playerApplicationHandler);
|
Handler handler = Assertions.checkNotNull(applicationThreadHandler);
|
||||||
for (int i = 0; i < actionsOnCompletion.size(); i++) {
|
for (int i = 0; i < actionsOnCompletion.size(); i++) {
|
||||||
handler.post(actionsOnCompletion.get(i));
|
handler.post(actionsOnCompletion.get(i));
|
||||||
}
|
}
|
||||||
@ -612,11 +602,14 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
|
|||||||
default:
|
default:
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void scheduleListenerNotification(@Nullable Runnable actionOnCompletion) {
|
private void scheduleListenerNotification(@Nullable Runnable actionOnCompletion) {
|
||||||
if (!listenerNotificationScheduled) {
|
if (!listenerNotificationScheduled) {
|
||||||
Assertions.checkNotNull(player).createMessage(this).setType(MSG_NOTIFY_LISTENER).send();
|
Assertions.checkNotNull(playbackThreadHandler)
|
||||||
|
.obtainMessage(MSG_NOTIFY_LISTENER)
|
||||||
|
.sendToTarget();
|
||||||
listenerNotificationScheduled = true;
|
listenerNotificationScheduled = true;
|
||||||
}
|
}
|
||||||
if (actionOnCompletion != null) {
|
if (actionOnCompletion != null) {
|
||||||
@ -636,11 +629,9 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
|
|||||||
mediaSourceHolders, windowCount, periodCount, shuffleOrder, isAtomic),
|
mediaSourceHolders, windowCount, periodCount, shuffleOrder, isAtomic),
|
||||||
/* manifest= */ null);
|
/* manifest= */ null);
|
||||||
if (!actionsOnCompletion.isEmpty()) {
|
if (!actionsOnCompletion.isEmpty()) {
|
||||||
Assertions.checkNotNull(player)
|
Assertions.checkNotNull(playbackThreadHandler)
|
||||||
.createMessage(this)
|
.obtainMessage(MSG_ON_COMPLETION, actionsOnCompletion)
|
||||||
.setType(MSG_ON_COMPLETION)
|
.sendToTarget();
|
||||||
.setPayload(actionsOnCompletion)
|
|
||||||
.send();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user