Allow delivery to multiple messages in a single message.
Where multiple messages are required to be sent in order to perform a player reconfiguration, it will usually be desirable to process all messages in a single "transaction" (i.e. without any rendering happening when only some of the messages have been applied). ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=123228334
This commit is contained in:
parent
ff7819e86a
commit
10329eb111
@ -104,8 +104,9 @@ public class VpxPlaybackTest extends InstrumentationTestCase {
|
||||
false),
|
||||
new DefaultAllocator(BUFFER_SEGMENT_SIZE), BUFFER_SEGMENT_SIZE * BUFFER_SEGMENT_COUNT,
|
||||
new Extractor[] {new MatroskaExtractor()});
|
||||
player.sendMessage(videoRenderer, LibvpxVideoTrackRenderer.MSG_SET_OUTPUT_BUFFER_RENDERER,
|
||||
new VpxVideoSurfaceView(context));
|
||||
player.sendMessages(new ExoPlayer.ExoPlayerMessage(videoRenderer,
|
||||
LibvpxVideoTrackRenderer.MSG_SET_OUTPUT_BUFFER_RENDERER,
|
||||
new VpxVideoSurfaceView(context)));
|
||||
player.setSource(sampleSource);
|
||||
player.setPlayWhenReady(true);
|
||||
Looper.loop();
|
||||
|
@ -41,10 +41,10 @@ public final class LibvpxVideoTrackRenderer extends TrackRenderer {
|
||||
|
||||
/**
|
||||
* The type of a message that can be passed to an instance of this class via
|
||||
* {@link ExoPlayer#sendMessage} or {@link ExoPlayer#blockingSendMessage}. The message object
|
||||
* {@link ExoPlayer#sendMessages} or {@link ExoPlayer#blockingSendMessages}. The message object
|
||||
* should be the target {@link VpxOutputBufferRenderer}, or null.
|
||||
*/
|
||||
public static final int MSG_SET_OUTPUT_BUFFER_RENDERER = 2;
|
||||
public static final int MSG_SET_OUTPUT_BUFFER_RENDERER = C.MSG_CUSTOM_BASE;
|
||||
|
||||
/**
|
||||
* The number of input buffers and the number of output buffers. The track renderer may limit the
|
||||
|
@ -231,25 +231,30 @@ public interface C {
|
||||
|
||||
/**
|
||||
* The type of a message that can be passed to a video {@link TrackRenderer} via
|
||||
* {@link ExoPlayer#sendMessage} or {@link ExoPlayer#blockingSendMessage}. The message object
|
||||
* {@link ExoPlayer#sendMessages} or {@link ExoPlayer#blockingSendMessages}. The message object
|
||||
* should be the target {@link Surface}, or null.
|
||||
*/
|
||||
int MSG_SET_SURFACE = 1;
|
||||
|
||||
/**
|
||||
* The type of a message that can be passed to an audio {@link TrackRenderer} via
|
||||
* {@link ExoPlayer#sendMessage} or {@link ExoPlayer#blockingSendMessage}. The message object
|
||||
* {@link ExoPlayer#sendMessages} or {@link ExoPlayer#blockingSendMessages}. The message object
|
||||
* should be a {@link Float} with 0 being silence and 1 being unity gain.
|
||||
*/
|
||||
int MSG_SET_VOLUME = 2;
|
||||
|
||||
/**
|
||||
* The type of a message that can be passed to an audio {@link TrackRenderer} via
|
||||
* {@link ExoPlayer#sendMessage} or {@link ExoPlayer#blockingSendMessage}. The message object
|
||||
* {@link ExoPlayer#sendMessages} or {@link ExoPlayer#blockingSendMessages}. The message object
|
||||
* should be a {@link android.media.PlaybackParams}, which will be used to configure the
|
||||
* underlying {@link android.media.AudioTrack}. The message object should not be modified by the
|
||||
* caller after it has been passed
|
||||
*/
|
||||
int MSG_SET_PLAYBACK_PARAMS = 3;
|
||||
|
||||
/**
|
||||
* A minimum value for custom {@link TrackRenderer} message types.
|
||||
*/
|
||||
int MSG_CUSTOM_BASE = 10000;
|
||||
|
||||
}
|
||||
|
@ -132,8 +132,8 @@ public interface ExoPlayer {
|
||||
/**
|
||||
* A component of an {@link ExoPlayer} that can receive messages on the playback thread.
|
||||
* <p>
|
||||
* Messages can be delivered to a component via {@link ExoPlayer#sendMessage} and
|
||||
* {@link ExoPlayer#blockingSendMessage}.
|
||||
* Messages can be delivered to a component via {@link ExoPlayer#sendMessages} and
|
||||
* {@link ExoPlayer#blockingSendMessages}.
|
||||
*/
|
||||
interface ExoPlayerComponent {
|
||||
|
||||
@ -148,6 +148,28 @@ public interface ExoPlayer {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a message and a target {@link ExoPlayerComponent} to receive it.
|
||||
*/
|
||||
final class ExoPlayerMessage {
|
||||
|
||||
public final ExoPlayerComponent target;
|
||||
public final int messageType;
|
||||
public final Object message;
|
||||
|
||||
/**
|
||||
* @param target The target of the message.
|
||||
* @param messageType An integer identifying the type of message.
|
||||
* @param message The message object.
|
||||
*/
|
||||
public ExoPlayerMessage(ExoPlayerComponent target, int messageType, Object message) {
|
||||
this.target = target;
|
||||
this.messageType = messageType;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The player does not have a source to load, so it is neither buffering nor ready to play.
|
||||
*/
|
||||
@ -256,25 +278,21 @@ public interface ExoPlayer {
|
||||
void release();
|
||||
|
||||
/**
|
||||
* Sends a message to a specified component. The message is delivered to the component on the
|
||||
* playback thread. If the component throws a {@link ExoPlaybackException}, then it is
|
||||
* propagated out of the player as an error.
|
||||
* Sends messages to their target components. The messages are delivered on the playback thread.
|
||||
* If a component throws an {@link ExoPlaybackException} then it is propagated out of the player
|
||||
* as an error.
|
||||
*
|
||||
* @param target The target to which the message should be delivered.
|
||||
* @param messageType An integer that can be used to identify the type of the message.
|
||||
* @param message The message object.
|
||||
* @param messages The messages to be sent.
|
||||
*/
|
||||
void sendMessage(ExoPlayerComponent target, int messageType, Object message);
|
||||
void sendMessages(ExoPlayerMessage... messages);
|
||||
|
||||
/**
|
||||
* Blocking variant of {@link #sendMessage(ExoPlayerComponent, int, Object)} that does not return
|
||||
* until after the message has been delivered.
|
||||
* Variant of {@link #sendMessages(ExoPlayerMessage...)} that blocks until after the messages have
|
||||
* been delivered.
|
||||
*
|
||||
* @param target The target to which the message should be delivered.
|
||||
* @param messageType An integer that can be used to identify the type of the message.
|
||||
* @param message The message object.
|
||||
* @param messages The messages to be sent.
|
||||
*/
|
||||
void blockingSendMessage(ExoPlayerComponent target, int messageType, Object message);
|
||||
void blockingSendMessages(ExoPlayerMessage... messages);
|
||||
|
||||
/**
|
||||
* Gets the duration of the track in milliseconds.
|
||||
|
@ -129,13 +129,13 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(ExoPlayerComponent target, int messageType, Object message) {
|
||||
internalPlayer.sendMessage(target, messageType, message);
|
||||
public void sendMessages(ExoPlayerMessage... messages) {
|
||||
internalPlayer.sendMessages(messages);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void blockingSendMessage(ExoPlayerComponent target, int messageType, Object message) {
|
||||
internalPlayer.blockingSendMessage(target, messageType, message);
|
||||
public void blockingSendMessages(ExoPlayerMessage... messages) {
|
||||
internalPlayer.blockingSendMessages(messages);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -15,7 +15,7 @@
|
||||
*/
|
||||
package com.google.android.exoplayer;
|
||||
|
||||
import com.google.android.exoplayer.ExoPlayer.ExoPlayerComponent;
|
||||
import com.google.android.exoplayer.ExoPlayer.ExoPlayerMessage;
|
||||
import com.google.android.exoplayer.TrackSelector.InvalidationListener;
|
||||
import com.google.android.exoplayer.util.PriorityHandlerThread;
|
||||
import com.google.android.exoplayer.util.TraceUtil;
|
||||
@ -154,19 +154,22 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
handler.sendEmptyMessage(MSG_STOP);
|
||||
}
|
||||
|
||||
public void sendMessage(ExoPlayerComponent target, int messageType, Object message) {
|
||||
public void sendMessages(ExoPlayerMessage... messages) {
|
||||
if (released) {
|
||||
Log.w(TAG, "Ignoring messages sent after release.");
|
||||
return;
|
||||
}
|
||||
customMessagesSent++;
|
||||
handler.obtainMessage(MSG_CUSTOM, messageType, 0, Pair.create(target, message)).sendToTarget();
|
||||
handler.obtainMessage(MSG_CUSTOM, messages).sendToTarget();
|
||||
}
|
||||
|
||||
public synchronized void blockingSendMessage(ExoPlayerComponent target, int messageType,
|
||||
Object message) {
|
||||
public synchronized void blockingSendMessages(ExoPlayerMessage... messages) {
|
||||
if (released) {
|
||||
Log.w(TAG, "Sent message(" + messageType + ") after release. Message ignored.");
|
||||
Log.w(TAG, "Ignoring messages sent after release.");
|
||||
return;
|
||||
}
|
||||
int messageNumber = customMessagesSent++;
|
||||
handler.obtainMessage(MSG_CUSTOM, messageType, 0, Pair.create(target, message)).sendToTarget();
|
||||
handler.obtainMessage(MSG_CUSTOM, messages).sendToTarget();
|
||||
while (customMessagesProcessed <= messageNumber) {
|
||||
try {
|
||||
wait();
|
||||
@ -225,7 +228,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
return true;
|
||||
}
|
||||
case MSG_CUSTOM: {
|
||||
sendMessageInternal(msg.arg1, msg.obj);
|
||||
sendMessagesInternal((ExoPlayerMessage[]) msg.obj);
|
||||
return true;
|
||||
}
|
||||
case MSG_TRACK_SELECTION_INVALIDATED: {
|
||||
@ -517,12 +520,11 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
}
|
||||
}
|
||||
|
||||
private <T> void sendMessageInternal(int what, Object obj)
|
||||
throws ExoPlaybackException {
|
||||
private void sendMessagesInternal(ExoPlayerMessage[] messages) throws ExoPlaybackException {
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
Pair<ExoPlayerComponent, Object> targetAndMessage = (Pair<ExoPlayerComponent, Object>) obj;
|
||||
targetAndMessage.first.handleMessage(what, targetAndMessage.second);
|
||||
for (ExoPlayerMessage message : messages) {
|
||||
message.target.handleMessage(message.messageType, message.message);
|
||||
}
|
||||
if (preparedSource) {
|
||||
// The message may have caused something to change that now requires us to do work.
|
||||
handler.sendEmptyMessage(MSG_DO_SOME_WORK);
|
||||
|
@ -89,6 +89,8 @@ public final class SimpleExoPlayer implements ExoPlayer {
|
||||
private final TrackRenderer[] renderers;
|
||||
private final ComponentListener componentListener;
|
||||
private final Handler mainHandler;
|
||||
private final int videoRendererCount;
|
||||
private final int audioRendererCount;
|
||||
|
||||
private Format videoFormat;
|
||||
private Format audioFormat;
|
||||
@ -115,6 +117,22 @@ public final class SimpleExoPlayer implements ExoPlayer {
|
||||
buildRenderers(context, drmSessionManager, renderersList);
|
||||
renderers = renderersList.toArray(new TrackRenderer[renderersList.size()]);
|
||||
|
||||
// Obtain counts of video and audio renderers.
|
||||
int videoRendererCount = 0;
|
||||
int audioRendererCount = 0;
|
||||
for (TrackRenderer renderer : renderers) {
|
||||
switch (renderer.getTrackType()) {
|
||||
case C.TRACK_TYPE_VIDEO:
|
||||
videoRendererCount++;
|
||||
break;
|
||||
case C.TRACK_TYPE_AUDIO:
|
||||
audioRendererCount++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.videoRendererCount = videoRendererCount;
|
||||
this.audioRendererCount = audioRendererCount;
|
||||
|
||||
// Build the player and associated objects.
|
||||
player = new ExoPlayerImpl(renderers, trackSelector, minBufferMs, minRebufferMs);
|
||||
}
|
||||
@ -145,16 +163,19 @@ public final class SimpleExoPlayer implements ExoPlayer {
|
||||
* @param surface The {@link Surface}.
|
||||
*/
|
||||
public void setSurface(Surface surface) {
|
||||
ExoPlayerMessage[] messages = new ExoPlayerMessage[videoRendererCount];
|
||||
int count = 0;
|
||||
for (TrackRenderer renderer : renderers) {
|
||||
if (renderer.getTrackType() == C.TRACK_TYPE_VIDEO) {
|
||||
if (surface == null) {
|
||||
// Block to ensure that the surface is not accessed after the method returns.
|
||||
player.blockingSendMessage(renderer, C.MSG_SET_SURFACE, null);
|
||||
} else {
|
||||
player.sendMessage(renderer, C.MSG_SET_SURFACE, surface);
|
||||
}
|
||||
messages[count++] = new ExoPlayerMessage(renderer, C.MSG_SET_SURFACE, surface);
|
||||
}
|
||||
}
|
||||
if (surface == null) {
|
||||
// Block to ensure that the surface is not accessed after the method returns.
|
||||
player.blockingSendMessages(messages);
|
||||
} else {
|
||||
player.sendMessages(messages);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -163,11 +184,14 @@ public final class SimpleExoPlayer implements ExoPlayer {
|
||||
* @param volume The volume.
|
||||
*/
|
||||
public void setVolume(float volume) {
|
||||
ExoPlayerMessage[] messages = new ExoPlayerMessage[audioRendererCount];
|
||||
int count = 0;
|
||||
for (TrackRenderer renderer : renderers) {
|
||||
if (renderer.getTrackType() == C.TRACK_TYPE_AUDIO) {
|
||||
player.sendMessage(renderer, C.MSG_SET_VOLUME, volume);
|
||||
messages[count++] = new ExoPlayerMessage(renderer, C.MSG_SET_VOLUME, volume);
|
||||
}
|
||||
}
|
||||
player.sendMessages(messages);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -296,13 +320,13 @@ public final class SimpleExoPlayer implements ExoPlayer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(ExoPlayerComponent target, int messageType, Object message) {
|
||||
player.sendMessage(target, messageType, message);
|
||||
public void sendMessages(ExoPlayerMessage... messages) {
|
||||
player.sendMessages(messages);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void blockingSendMessage(ExoPlayerComponent target, int messageType, Object message) {
|
||||
player.blockingSendMessage(target, messageType, message);
|
||||
public void blockingSendMessages(ExoPlayerMessage... messages) {
|
||||
player.blockingSendMessages(messages);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
x
Reference in New Issue
Block a user