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),
|
false),
|
||||||
new DefaultAllocator(BUFFER_SEGMENT_SIZE), BUFFER_SEGMENT_SIZE * BUFFER_SEGMENT_COUNT,
|
new DefaultAllocator(BUFFER_SEGMENT_SIZE), BUFFER_SEGMENT_SIZE * BUFFER_SEGMENT_COUNT,
|
||||||
new Extractor[] {new MatroskaExtractor()});
|
new Extractor[] {new MatroskaExtractor()});
|
||||||
player.sendMessage(videoRenderer, LibvpxVideoTrackRenderer.MSG_SET_OUTPUT_BUFFER_RENDERER,
|
player.sendMessages(new ExoPlayer.ExoPlayerMessage(videoRenderer,
|
||||||
new VpxVideoSurfaceView(context));
|
LibvpxVideoTrackRenderer.MSG_SET_OUTPUT_BUFFER_RENDERER,
|
||||||
|
new VpxVideoSurfaceView(context)));
|
||||||
player.setSource(sampleSource);
|
player.setSource(sampleSource);
|
||||||
player.setPlayWhenReady(true);
|
player.setPlayWhenReady(true);
|
||||||
Looper.loop();
|
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
|
* 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.
|
* 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
|
* 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
|
* 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.
|
* should be the target {@link Surface}, or null.
|
||||||
*/
|
*/
|
||||||
int MSG_SET_SURFACE = 1;
|
int MSG_SET_SURFACE = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of a message that can be passed to an audio {@link TrackRenderer} via
|
* 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.
|
* should be a {@link Float} with 0 being silence and 1 being unity gain.
|
||||||
*/
|
*/
|
||||||
int MSG_SET_VOLUME = 2;
|
int MSG_SET_VOLUME = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of a message that can be passed to an audio {@link TrackRenderer} via
|
* 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
|
* 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
|
* underlying {@link android.media.AudioTrack}. The message object should not be modified by the
|
||||||
* caller after it has been passed
|
* caller after it has been passed
|
||||||
*/
|
*/
|
||||||
int MSG_SET_PLAYBACK_PARAMS = 3;
|
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.
|
* A component of an {@link ExoPlayer} that can receive messages on the playback thread.
|
||||||
* <p>
|
* <p>
|
||||||
* Messages can be delivered to a component via {@link ExoPlayer#sendMessage} and
|
* Messages can be delivered to a component via {@link ExoPlayer#sendMessages} and
|
||||||
* {@link ExoPlayer#blockingSendMessage}.
|
* {@link ExoPlayer#blockingSendMessages}.
|
||||||
*/
|
*/
|
||||||
interface ExoPlayerComponent {
|
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.
|
* 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();
|
void release();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a message to a specified component. The message is delivered to the component on the
|
* Sends messages to their target components. The messages are delivered on the playback thread.
|
||||||
* playback thread. If the component throws a {@link ExoPlaybackException}, then it is
|
* If a component throws an {@link ExoPlaybackException} then it is propagated out of the player
|
||||||
* propagated out of the player as an error.
|
* as an error.
|
||||||
*
|
*
|
||||||
* @param target The target to which the message should be delivered.
|
* @param messages The messages to be sent.
|
||||||
* @param messageType An integer that can be used to identify the type of the message.
|
|
||||||
* @param message The message object.
|
|
||||||
*/
|
*/
|
||||||
void sendMessage(ExoPlayerComponent target, int messageType, Object message);
|
void sendMessages(ExoPlayerMessage... messages);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Blocking variant of {@link #sendMessage(ExoPlayerComponent, int, Object)} that does not return
|
* Variant of {@link #sendMessages(ExoPlayerMessage...)} that blocks until after the messages have
|
||||||
* until after the message has been delivered.
|
* been delivered.
|
||||||
*
|
*
|
||||||
* @param target The target to which the message should be delivered.
|
* @param messages The messages to be sent.
|
||||||
* @param messageType An integer that can be used to identify the type of the message.
|
|
||||||
* @param message The message object.
|
|
||||||
*/
|
*/
|
||||||
void blockingSendMessage(ExoPlayerComponent target, int messageType, Object message);
|
void blockingSendMessages(ExoPlayerMessage... messages);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the duration of the track in milliseconds.
|
* Gets the duration of the track in milliseconds.
|
||||||
|
@ -129,13 +129,13 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendMessage(ExoPlayerComponent target, int messageType, Object message) {
|
public void sendMessages(ExoPlayerMessage... messages) {
|
||||||
internalPlayer.sendMessage(target, messageType, message);
|
internalPlayer.sendMessages(messages);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void blockingSendMessage(ExoPlayerComponent target, int messageType, Object message) {
|
public void blockingSendMessages(ExoPlayerMessage... messages) {
|
||||||
internalPlayer.blockingSendMessage(target, messageType, message);
|
internalPlayer.blockingSendMessages(messages);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer;
|
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.TrackSelector.InvalidationListener;
|
||||||
import com.google.android.exoplayer.util.PriorityHandlerThread;
|
import com.google.android.exoplayer.util.PriorityHandlerThread;
|
||||||
import com.google.android.exoplayer.util.TraceUtil;
|
import com.google.android.exoplayer.util.TraceUtil;
|
||||||
@ -154,19 +154,22 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
handler.sendEmptyMessage(MSG_STOP);
|
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++;
|
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,
|
public synchronized void blockingSendMessages(ExoPlayerMessage... messages) {
|
||||||
Object message) {
|
|
||||||
if (released) {
|
if (released) {
|
||||||
Log.w(TAG, "Sent message(" + messageType + ") after release. Message ignored.");
|
Log.w(TAG, "Ignoring messages sent after release.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int messageNumber = customMessagesSent++;
|
int messageNumber = customMessagesSent++;
|
||||||
handler.obtainMessage(MSG_CUSTOM, messageType, 0, Pair.create(target, message)).sendToTarget();
|
handler.obtainMessage(MSG_CUSTOM, messages).sendToTarget();
|
||||||
while (customMessagesProcessed <= messageNumber) {
|
while (customMessagesProcessed <= messageNumber) {
|
||||||
try {
|
try {
|
||||||
wait();
|
wait();
|
||||||
@ -225,7 +228,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case MSG_CUSTOM: {
|
case MSG_CUSTOM: {
|
||||||
sendMessageInternal(msg.arg1, msg.obj);
|
sendMessagesInternal((ExoPlayerMessage[]) msg.obj);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case MSG_TRACK_SELECTION_INVALIDATED: {
|
case MSG_TRACK_SELECTION_INVALIDATED: {
|
||||||
@ -517,12 +520,11 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> void sendMessageInternal(int what, Object obj)
|
private void sendMessagesInternal(ExoPlayerMessage[] messages) throws ExoPlaybackException {
|
||||||
throws ExoPlaybackException {
|
|
||||||
try {
|
try {
|
||||||
@SuppressWarnings("unchecked")
|
for (ExoPlayerMessage message : messages) {
|
||||||
Pair<ExoPlayerComponent, Object> targetAndMessage = (Pair<ExoPlayerComponent, Object>) obj;
|
message.target.handleMessage(message.messageType, message.message);
|
||||||
targetAndMessage.first.handleMessage(what, targetAndMessage.second);
|
}
|
||||||
if (preparedSource) {
|
if (preparedSource) {
|
||||||
// The message may have caused something to change that now requires us to do work.
|
// The message may have caused something to change that now requires us to do work.
|
||||||
handler.sendEmptyMessage(MSG_DO_SOME_WORK);
|
handler.sendEmptyMessage(MSG_DO_SOME_WORK);
|
||||||
|
@ -89,6 +89,8 @@ public final class SimpleExoPlayer implements ExoPlayer {
|
|||||||
private final TrackRenderer[] renderers;
|
private final TrackRenderer[] renderers;
|
||||||
private final ComponentListener componentListener;
|
private final ComponentListener componentListener;
|
||||||
private final Handler mainHandler;
|
private final Handler mainHandler;
|
||||||
|
private final int videoRendererCount;
|
||||||
|
private final int audioRendererCount;
|
||||||
|
|
||||||
private Format videoFormat;
|
private Format videoFormat;
|
||||||
private Format audioFormat;
|
private Format audioFormat;
|
||||||
@ -115,6 +117,22 @@ public final class SimpleExoPlayer implements ExoPlayer {
|
|||||||
buildRenderers(context, drmSessionManager, renderersList);
|
buildRenderers(context, drmSessionManager, renderersList);
|
||||||
renderers = renderersList.toArray(new TrackRenderer[renderersList.size()]);
|
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.
|
// Build the player and associated objects.
|
||||||
player = new ExoPlayerImpl(renderers, trackSelector, minBufferMs, minRebufferMs);
|
player = new ExoPlayerImpl(renderers, trackSelector, minBufferMs, minRebufferMs);
|
||||||
}
|
}
|
||||||
@ -145,15 +163,18 @@ public final class SimpleExoPlayer implements ExoPlayer {
|
|||||||
* @param surface The {@link Surface}.
|
* @param surface The {@link Surface}.
|
||||||
*/
|
*/
|
||||||
public void setSurface(Surface surface) {
|
public void setSurface(Surface surface) {
|
||||||
|
ExoPlayerMessage[] messages = new ExoPlayerMessage[videoRendererCount];
|
||||||
|
int count = 0;
|
||||||
for (TrackRenderer renderer : renderers) {
|
for (TrackRenderer renderer : renderers) {
|
||||||
if (renderer.getTrackType() == C.TRACK_TYPE_VIDEO) {
|
if (renderer.getTrackType() == C.TRACK_TYPE_VIDEO) {
|
||||||
|
messages[count++] = new ExoPlayerMessage(renderer, C.MSG_SET_SURFACE, surface);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (surface == null) {
|
if (surface == null) {
|
||||||
// Block to ensure that the surface is not accessed after the method returns.
|
// Block to ensure that the surface is not accessed after the method returns.
|
||||||
player.blockingSendMessage(renderer, C.MSG_SET_SURFACE, null);
|
player.blockingSendMessages(messages);
|
||||||
} else {
|
} else {
|
||||||
player.sendMessage(renderer, C.MSG_SET_SURFACE, surface);
|
player.sendMessages(messages);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,11 +184,14 @@ public final class SimpleExoPlayer implements ExoPlayer {
|
|||||||
* @param volume The volume.
|
* @param volume The volume.
|
||||||
*/
|
*/
|
||||||
public void setVolume(float volume) {
|
public void setVolume(float volume) {
|
||||||
|
ExoPlayerMessage[] messages = new ExoPlayerMessage[audioRendererCount];
|
||||||
|
int count = 0;
|
||||||
for (TrackRenderer renderer : renderers) {
|
for (TrackRenderer renderer : renderers) {
|
||||||
if (renderer.getTrackType() == C.TRACK_TYPE_AUDIO) {
|
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
|
@Override
|
||||||
public void sendMessage(ExoPlayerComponent target, int messageType, Object message) {
|
public void sendMessages(ExoPlayerMessage... messages) {
|
||||||
player.sendMessage(target, messageType, message);
|
player.sendMessages(messages);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void blockingSendMessage(ExoPlayerComponent target, int messageType, Object message) {
|
public void blockingSendMessages(ExoPlayerMessage... messages) {
|
||||||
player.blockingSendMessage(target, messageType, message);
|
player.blockingSendMessages(messages);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
x
Reference in New Issue
Block a user