mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Add 'Player.getVideoSurfaceSize' that returns the size of the surface
on which the video is rendered. Design Doc: go/aaos-mu-media-dd PiperOrigin-RevId: 485884772
This commit is contained in:
parent
5ac4700c9a
commit
b780635c0b
@ -28,6 +28,8 @@ Release notes
|
||||
([#10667](https://github.com/google/ExoPlayer/issues/10667)).
|
||||
* Enforce minimum `compileSdkVersion` to avoid compilation errors
|
||||
([#10684](https://github.com/google/ExoPlayer/issues/10684)).
|
||||
* Add `Player.getVideoSurfaceSize` that returns the size of the surface on
|
||||
which the video is rendered.
|
||||
* Downloads:
|
||||
* Fix potential infinite loop in `ProgressiveDownloader` caused by
|
||||
simultaneous download and playback with the same `PriorityTaskManager`
|
||||
|
@ -47,6 +47,7 @@ import androidx.media3.common.util.Assertions;
|
||||
import androidx.media3.common.util.Clock;
|
||||
import androidx.media3.common.util.ListenerSet;
|
||||
import androidx.media3.common.util.Log;
|
||||
import androidx.media3.common.util.Size;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.common.util.Util;
|
||||
import com.google.android.gms.cast.CastStatusCodes;
|
||||
@ -727,6 +728,12 @@ public final class CastPlayer extends BasePlayer {
|
||||
return VideoSize.UNKNOWN;
|
||||
}
|
||||
|
||||
/** This method is not supported and returns {@link Size#UNKNOWN}. */
|
||||
@Override
|
||||
public Size getVideoSurfaceSize() {
|
||||
return Size.UNKNOWN;
|
||||
}
|
||||
|
||||
/** This method is not supported and returns an empty {@link CueGroup}. */
|
||||
@Override
|
||||
public CueGroup getCurrentCues() {
|
||||
|
@ -23,6 +23,7 @@ import android.view.TextureView;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.media3.common.text.Cue;
|
||||
import androidx.media3.common.text.CueGroup;
|
||||
import androidx.media3.common.util.Size;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import java.util.List;
|
||||
|
||||
@ -759,6 +760,12 @@ public class ForwardingPlayer implements Player {
|
||||
return player.getVideoSize();
|
||||
}
|
||||
|
||||
/** Calls {@link Player#getVideoSurfaceSize()} on the delegate and returns the result. */
|
||||
@Override
|
||||
public Size getVideoSurfaceSize() {
|
||||
return player.getVideoSurfaceSize();
|
||||
}
|
||||
|
||||
/** Calls {@link Player#clearVideoSurface()} on the delegate. */
|
||||
@Override
|
||||
public void clearVideoSurface() {
|
||||
|
@ -33,6 +33,7 @@ import androidx.annotation.IntRange;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.media3.common.text.Cue;
|
||||
import androidx.media3.common.text.CueGroup;
|
||||
import androidx.media3.common.util.Size;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.common.util.Util;
|
||||
import com.google.common.base.Objects;
|
||||
@ -2498,6 +2499,14 @@ public interface Player {
|
||||
*/
|
||||
VideoSize getVideoSize();
|
||||
|
||||
/**
|
||||
* Gets the size of the surface on which the video is rendered.
|
||||
*
|
||||
* @see Listener#onSurfaceSizeChanged(int, int)
|
||||
*/
|
||||
@UnstableApi
|
||||
Size getVideoSurfaceSize();
|
||||
|
||||
/** Returns the current {@link CueGroup}. */
|
||||
CueGroup getCurrentCues();
|
||||
|
||||
|
@ -28,6 +28,7 @@ import androidx.media3.common.text.CueGroup;
|
||||
import androidx.media3.common.util.Clock;
|
||||
import androidx.media3.common.util.HandlerWrapper;
|
||||
import androidx.media3.common.util.ListenerSet;
|
||||
import androidx.media3.common.util.Size;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.common.util.Util;
|
||||
import com.google.common.base.Supplier;
|
||||
@ -589,6 +590,12 @@ public abstract class SimpleBasePlayer extends BasePlayer {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Size getVideoSurfaceSize() {
|
||||
// TODO: implement.
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final CueGroup getCurrentCues() {
|
||||
// TODO: implement.
|
||||
|
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 androidx.media3.common.util;
|
||||
|
||||
import static androidx.media3.common.util.Assertions.checkArgument;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.media3.common.C;
|
||||
|
||||
/** Immutable class for describing width and height dimensions in pixels. */
|
||||
@UnstableApi
|
||||
public final class Size {
|
||||
|
||||
/** A static instance to represent an unknown size value. */
|
||||
public static final Size UNKNOWN =
|
||||
new Size(/* width= */ C.LENGTH_UNSET, /* height= */ C.LENGTH_UNSET);
|
||||
|
||||
private final int width;
|
||||
private final int height;
|
||||
|
||||
/**
|
||||
* Creates a new immutable Size instance.
|
||||
*
|
||||
* @param width The width of the size, in pixels, or {@link C#LENGTH_UNSET} if unknown.
|
||||
* @param height The height of the size, in pixels, or {@link C#LENGTH_UNSET} if unknown.
|
||||
* @throws IllegalArgumentException if an invalid {@code width} or {@code height} is specified.
|
||||
*/
|
||||
public Size(int width, int height) {
|
||||
checkArgument(
|
||||
(width == C.LENGTH_UNSET || width >= 0) && (height == C.LENGTH_UNSET || height >= 0));
|
||||
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
/** Returns the width of the size (in pixels), or {@link C#LENGTH_UNSET} if unknown. */
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
/** Returns the height of the size (in pixels), or {@link C#LENGTH_UNSET} if unknown. */
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof Size) {
|
||||
Size other = (Size) obj;
|
||||
return width == other.width && height == other.height;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return width + "x" + height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
// assuming most sizes are <2^16, doing a rotate will give us perfect hashing
|
||||
return height ^ ((width << (Integer.SIZE / 2)) | (width >>> (Integer.SIZE / 2)));
|
||||
}
|
||||
}
|
@ -82,6 +82,7 @@ import androidx.media3.common.util.ConditionVariable;
|
||||
import androidx.media3.common.util.HandlerWrapper;
|
||||
import androidx.media3.common.util.ListenerSet;
|
||||
import androidx.media3.common.util.Log;
|
||||
import androidx.media3.common.util.Size;
|
||||
import androidx.media3.common.util.Util;
|
||||
import androidx.media3.exoplayer.PlayerMessage.Target;
|
||||
import androidx.media3.exoplayer.Renderer.MessageType;
|
||||
@ -192,8 +193,7 @@ import java.util.concurrent.TimeoutException;
|
||||
@Nullable private TextureView textureView;
|
||||
private @C.VideoScalingMode int videoScalingMode;
|
||||
private @C.VideoChangeFrameRateStrategy int videoChangeFrameRateStrategy;
|
||||
private int surfaceWidth;
|
||||
private int surfaceHeight;
|
||||
private Size surfaceSize;
|
||||
@Nullable private DecoderCounters videoDecoderCounters;
|
||||
@Nullable private DecoderCounters audioDecoderCounters;
|
||||
private int audioSessionId;
|
||||
@ -382,6 +382,7 @@ import java.util.concurrent.TimeoutException;
|
||||
wifiLockManager.setEnabled(builder.wakeMode == C.WAKE_MODE_NETWORK);
|
||||
deviceInfo = createDeviceInfo(streamVolumeManager);
|
||||
videoSize = VideoSize.UNKNOWN;
|
||||
surfaceSize = Size.UNKNOWN;
|
||||
|
||||
trackSelector.setAudioAttributes(audioAttributes);
|
||||
sendRendererMessage(TRACK_TYPE_AUDIO, MSG_SET_AUDIO_SESSION_ID, audioSessionId);
|
||||
@ -1229,6 +1230,12 @@ import java.util.concurrent.TimeoutException;
|
||||
return videoSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Size getVideoSurfaceSize() {
|
||||
verifyApplicationThread();
|
||||
return surfaceSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearVideoSurface() {
|
||||
verifyApplicationThread();
|
||||
@ -2545,9 +2552,8 @@ import java.util.concurrent.TimeoutException;
|
||||
}
|
||||
|
||||
private void maybeNotifySurfaceSizeChanged(int width, int height) {
|
||||
if (width != surfaceWidth || height != surfaceHeight) {
|
||||
surfaceWidth = width;
|
||||
surfaceHeight = height;
|
||||
if (width != surfaceSize.getWidth() || height != surfaceSize.getHeight()) {
|
||||
surfaceSize = new Size(width, height);
|
||||
listeners.sendEvent(
|
||||
EVENT_SURFACE_SIZE_CHANGED, listener -> listener.onSurfaceSizeChanged(width, height));
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ import androidx.media3.common.VideoSize;
|
||||
import androidx.media3.common.text.CueGroup;
|
||||
import androidx.media3.common.util.Clock;
|
||||
import androidx.media3.common.util.ConditionVariable;
|
||||
import androidx.media3.common.util.Size;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.exoplayer.analytics.AnalyticsCollector;
|
||||
import androidx.media3.exoplayer.analytics.AnalyticsListener;
|
||||
@ -528,6 +529,12 @@ public class SimpleExoPlayer extends BasePlayer
|
||||
return player.getVideoSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Size getVideoSurfaceSize() {
|
||||
blockUntilConstructorFinished();
|
||||
return player.getVideoSurfaceSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearVideoSurface() {
|
||||
blockUntilConstructorFinished();
|
||||
|
@ -54,6 +54,7 @@ import androidx.media3.common.VideoSize;
|
||||
import androidx.media3.common.text.CueGroup;
|
||||
import androidx.media3.common.util.Consumer;
|
||||
import androidx.media3.common.util.Log;
|
||||
import androidx.media3.common.util.Size;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.common.util.Util;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
@ -1498,6 +1499,13 @@ public class MediaController implements Player {
|
||||
return isConnected() ? impl.getVideoSize() : VideoSize.UNKNOWN;
|
||||
}
|
||||
|
||||
@UnstableApi
|
||||
@Override
|
||||
public Size getVideoSurfaceSize() {
|
||||
verifyApplicationThread();
|
||||
return isConnected() ? impl.getVideoSurfaceSize() : Size.UNKNOWN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearVideoSurface() {
|
||||
verifyApplicationThread();
|
||||
@ -1968,6 +1976,8 @@ public class MediaController implements Player {
|
||||
|
||||
VideoSize getVideoSize();
|
||||
|
||||
Size getVideoSurfaceSize();
|
||||
|
||||
void clearVideoSurface();
|
||||
|
||||
void clearVideoSurface(@Nullable Surface surface);
|
||||
|
@ -75,6 +75,7 @@ import androidx.media3.common.util.BundleableUtil;
|
||||
import androidx.media3.common.util.Clock;
|
||||
import androidx.media3.common.util.ListenerSet;
|
||||
import androidx.media3.common.util.Log;
|
||||
import androidx.media3.common.util.Size;
|
||||
import androidx.media3.common.util.Util;
|
||||
import androidx.media3.session.MediaController.MediaControllerImpl;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
@ -122,8 +123,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
@Nullable private Surface videoSurface;
|
||||
@Nullable private SurfaceHolder videoSurfaceHolder;
|
||||
@Nullable private TextureView videoTextureView;
|
||||
private int surfaceWidth;
|
||||
private int surfaceHeight;
|
||||
private Size surfaceSize;
|
||||
@Nullable private IMediaSession iSession;
|
||||
private long lastReturnedContentPositionMs;
|
||||
private long lastSetPlayWhenReadyCalledTimeMs;
|
||||
@ -136,6 +136,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
Looper applicationLooper) {
|
||||
// Initialize default values.
|
||||
playerInfo = PlayerInfo.DEFAULT;
|
||||
surfaceSize = Size.UNKNOWN;
|
||||
sessionCommands = SessionCommands.EMPTY;
|
||||
playerCommandsFromSession = Commands.EMPTY;
|
||||
playerCommandsFromPlayer = Commands.EMPTY;
|
||||
@ -1566,6 +1567,11 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
return playerInfo.videoSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Size getVideoSurfaceSize() {
|
||||
return surfaceSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearVideoSurface() {
|
||||
if (!isPlayerCommandAvailable(Player.COMMAND_SET_VIDEO_SURFACE)) {
|
||||
@ -2189,9 +2195,8 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
}
|
||||
|
||||
private void maybeNotifySurfaceSizeChanged(int width, int height) {
|
||||
if (surfaceWidth != width || surfaceHeight != height) {
|
||||
surfaceWidth = width;
|
||||
surfaceHeight = height;
|
||||
if (surfaceSize.getWidth() != width || surfaceSize.getHeight() != height) {
|
||||
surfaceSize = new Size(width, height);
|
||||
listeners.sendEvent(
|
||||
/* eventFlag= */ Player.EVENT_SURFACE_SIZE_CHANGED,
|
||||
listener -> listener.onSurfaceSizeChanged(width, height));
|
||||
|
@ -67,6 +67,7 @@ import androidx.media3.common.text.CueGroup;
|
||||
import androidx.media3.common.util.Clock;
|
||||
import androidx.media3.common.util.ListenerSet;
|
||||
import androidx.media3.common.util.Log;
|
||||
import androidx.media3.common.util.Size;
|
||||
import androidx.media3.common.util.Util;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
@ -961,6 +962,12 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
|
||||
return VideoSize.UNKNOWN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Size getVideoSurfaceSize() {
|
||||
Log.w(TAG, "Session doesn't support getting VideoSurfaceSize");
|
||||
return Size.UNKNOWN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearVideoSurface() {
|
||||
Log.w(TAG, "Session doesn't support clearing Surface");
|
||||
|
@ -18,6 +18,7 @@ package androidx.media3.session;
|
||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.os.Looper;
|
||||
import android.view.Surface;
|
||||
import android.view.SurfaceHolder;
|
||||
@ -40,6 +41,7 @@ import androidx.media3.common.Tracks;
|
||||
import androidx.media3.common.VideoSize;
|
||||
import androidx.media3.common.text.CueGroup;
|
||||
import androidx.media3.common.util.ConditionVariable;
|
||||
import androidx.media3.common.util.Size;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.common.util.Util;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
@ -230,6 +232,7 @@ public class MockPlayer implements Player {
|
||||
public @RepeatMode int repeatMode;
|
||||
public boolean shuffleModeEnabled;
|
||||
public VideoSize videoSize;
|
||||
public Size surfaceSize;
|
||||
@Nullable public Surface surface;
|
||||
@Nullable public SurfaceHolder surfaceHolder;
|
||||
@Nullable public SurfaceView surfaceView;
|
||||
@ -277,6 +280,7 @@ public class MockPlayer implements Player {
|
||||
currentMediaItemIndex = 0;
|
||||
repeatMode = Player.REPEAT_MODE_OFF;
|
||||
videoSize = VideoSize.UNKNOWN;
|
||||
surfaceSize = Size.UNKNOWN;
|
||||
volume = 1.0f;
|
||||
cueGroup = CueGroup.EMPTY_TIME_ZERO;
|
||||
deviceInfo = DeviceInfo.UNKNOWN;
|
||||
@ -1121,6 +1125,11 @@ public class MockPlayer implements Player {
|
||||
return videoSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Size getVideoSurfaceSize() {
|
||||
return surfaceSize;
|
||||
}
|
||||
|
||||
public void notifyVideoSizeChanged(VideoSize videoSize) {
|
||||
for (Listener listener : listeners) {
|
||||
listener.onVideoSizeChanged(videoSize);
|
||||
@ -1136,47 +1145,70 @@ public class MockPlayer implements Player {
|
||||
public void clearVideoSurface(@Nullable Surface surface) {
|
||||
if (surface != null && surface == this.surface) {
|
||||
this.surface = null;
|
||||
maybeUpdateSurfaceSize(/* width= */ 0, /* height= */ 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVideoSurface(@Nullable Surface surface) {
|
||||
this.surface = surface;
|
||||
int newSurfaceSize = surface == null ? 0 : C.LENGTH_UNSET;
|
||||
maybeUpdateSurfaceSize(/* width= */ newSurfaceSize, /* height= */ newSurfaceSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVideoSurfaceHolder(@Nullable SurfaceHolder surfaceHolder) {
|
||||
this.surfaceHolder = surfaceHolder;
|
||||
if (surfaceHolder == null || surfaceHolder.getSurfaceFrame() == null) {
|
||||
maybeUpdateSurfaceSize(/* width= */ 0, /* height= */ 0);
|
||||
} else {
|
||||
Rect rect = surfaceHolder.getSurfaceFrame();
|
||||
maybeUpdateSurfaceSize(rect.width(), rect.height());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearVideoSurfaceHolder(@Nullable SurfaceHolder surfaceHolder) {
|
||||
if (surfaceHolder != null && surfaceHolder == this.surfaceHolder) {
|
||||
this.surfaceHolder = null;
|
||||
maybeUpdateSurfaceSize(/* width= */ 0, /* height= */ 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVideoSurfaceView(@Nullable SurfaceView surfaceView) {
|
||||
this.surfaceView = surfaceView;
|
||||
if (surfaceView == null
|
||||
|| surfaceView.getHolder() == null
|
||||
|| surfaceView.getHolder().getSurfaceFrame() == null) {
|
||||
maybeUpdateSurfaceSize(/* width= */ 0, /* height= */ 0);
|
||||
} else {
|
||||
Rect rect = surfaceView.getHolder().getSurfaceFrame();
|
||||
maybeUpdateSurfaceSize(rect.width(), rect.height());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearVideoSurfaceView(@Nullable SurfaceView surfaceView) {
|
||||
if (surfaceView != null && surfaceView == this.surfaceView) {
|
||||
this.surfaceView = null;
|
||||
maybeUpdateSurfaceSize(/* width= */ 0, /* height= */ 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVideoTextureView(@Nullable TextureView textureView) {
|
||||
this.textureView = textureView;
|
||||
if (textureView != null) {
|
||||
maybeUpdateSurfaceSize(textureView.getWidth(), textureView.getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearVideoTextureView(@Nullable TextureView textureView) {
|
||||
if (textureView != null && textureView == this.textureView) {
|
||||
this.textureView = null;
|
||||
maybeUpdateSurfaceSize(/* width= */ 0, /* height= */ 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1278,6 +1310,12 @@ public class MockPlayer implements Player {
|
||||
}
|
||||
}
|
||||
|
||||
private void maybeUpdateSurfaceSize(int width, int height) {
|
||||
if (width != surfaceSize.getWidth() || height != surfaceSize.getHeight()) {
|
||||
surfaceSize = new Size(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
private static ImmutableMap<@Method Integer, ConditionVariable> createMethodConditionVariables() {
|
||||
return new ImmutableMap.Builder<@Method Integer, ConditionVariable>()
|
||||
.put(METHOD_ADD_MEDIA_ITEM, new ConditionVariable())
|
||||
|
@ -34,6 +34,7 @@ import androidx.media3.common.TrackSelectionParameters;
|
||||
import androidx.media3.common.Tracks;
|
||||
import androidx.media3.common.VideoSize;
|
||||
import androidx.media3.common.text.CueGroup;
|
||||
import androidx.media3.common.util.Size;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import java.util.List;
|
||||
|
||||
@ -351,6 +352,11 @@ public class StubPlayer extends BasePlayer {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Size getVideoSurfaceSize() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CueGroup getCurrentCues() {
|
||||
throw new UnsupportedOperationException();
|
||||
|
Loading…
x
Reference in New Issue
Block a user