From ccc41f1adf106f38d57985e465e86afca5315119 Mon Sep 17 00:00:00 2001 From: tonihei Date: Thu, 7 Jun 2018 02:42:10 -0700 Subject: [PATCH] Add surface size change callback to VideoListener. This allows to detect changes in the surface size. SimpleExoPlayer already has the necessary listeners to report size changes for all surfaces whose lifecycle are managed by SimpleExoPlayer. In a subsequent change, AnalyticsCollector can be registered as a VideoListener to automatically notify of surface size changes. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=199605434 --- RELEASENOTES.md | 1 + .../android/exoplayer2/SimpleExoPlayer.java | 42 ++++++++++++++++--- .../exoplayer2/video/VideoListener.java | 13 ++++++ 3 files changed, 51 insertions(+), 5 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 51c47c439b..3e276345aa 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -17,6 +17,7 @@ * Allow injection of custom playlist trackers. * Add method to `BandwidthMeter` to return the `TransferListener` used to gather bandwidth information. +* Add callback to `VideoListener` to notify of surface size changes. ### 2.8.2 ### diff --git a/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java b/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java index 0a0df03053..5829b09431 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java @@ -16,6 +16,7 @@ package com.google.android.exoplayer2; import android.annotation.TargetApi; +import android.graphics.Rect; import android.graphics.SurfaceTexture; import android.media.MediaCodec; import android.media.PlaybackParams; @@ -86,6 +87,8 @@ public class SimpleExoPlayer implements ExoPlayer, Player.VideoComponent, Player private int videoScalingMode; private SurfaceHolder surfaceHolder; private TextureView textureView; + private int surfaceWidth; + private int surfaceHeight; private DecoderCounters videoDecoderCounters; private DecoderCounters audioDecoderCounters; private int audioSessionId; @@ -238,6 +241,8 @@ public class SimpleExoPlayer implements ExoPlayer, Player.VideoComponent, Player public void setVideoSurface(Surface surface) { removeSurfaceCallbacks(); setVideoSurfaceInternal(surface, false); + int newSurfaceSize = surface == null ? 0 : C.LENGTH_UNSET; + maybeNotifySurfaceSizeChanged(/* width= */ newSurfaceSize, /* height= */ newSurfaceSize); } @Override @@ -253,10 +258,18 @@ public class SimpleExoPlayer implements ExoPlayer, Player.VideoComponent, Player this.surfaceHolder = surfaceHolder; if (surfaceHolder == null) { setVideoSurfaceInternal(null, false); + maybeNotifySurfaceSizeChanged(/* width= */ 0, /* height= */ 0); } else { surfaceHolder.addCallback(componentListener); Surface surface = surfaceHolder.getSurface(); - setVideoSurfaceInternal(surface != null && surface.isValid() ? surface : null, false); + if (surface != null && surface.isValid()) { + setVideoSurfaceInternal(surface, /* ownsSurface= */ false); + Rect surfaceSize = surfaceHolder.getSurfaceFrame(); + maybeNotifySurfaceSizeChanged(surfaceSize.width(), surfaceSize.height()); + } else { + setVideoSurfaceInternal(/* surface= */ null, /* ownsSurface= */ false); + maybeNotifySurfaceSizeChanged(/* width= */ 0, /* height= */ 0); + } } } @@ -283,6 +296,7 @@ public class SimpleExoPlayer implements ExoPlayer, Player.VideoComponent, Player this.textureView = textureView; if (textureView == null) { setVideoSurfaceInternal(null, true); + maybeNotifySurfaceSizeChanged(/* width= */ 0, /* height= */ 0); } else { if (textureView.getSurfaceTextureListener() != null) { Log.w(TAG, "Replacing existing SurfaceTextureListener."); @@ -290,7 +304,13 @@ public class SimpleExoPlayer implements ExoPlayer, Player.VideoComponent, Player textureView.setSurfaceTextureListener(componentListener); SurfaceTexture surfaceTexture = textureView.isAvailable() ? textureView.getSurfaceTexture() : null; - setVideoSurfaceInternal(surfaceTexture == null ? null : new Surface(surfaceTexture), true); + if (surfaceTexture == null) { + setVideoSurfaceInternal(/* surface= */ null, /* ownsSurface= */ true); + maybeNotifySurfaceSizeChanged(/* width= */ 0, /* height= */ 0); + } else { + setVideoSurfaceInternal(new Surface(surfaceTexture), /* ownsSurface= */ true); + maybeNotifySurfaceSizeChanged(textureView.getWidth(), textureView.getHeight()); + } } } @@ -973,6 +993,16 @@ public class SimpleExoPlayer implements ExoPlayer, Player.VideoComponent, Player this.ownsSurface = ownsSurface; } + private void maybeNotifySurfaceSizeChanged(int width, int height) { + if (width != surfaceWidth || height != surfaceHeight) { + surfaceWidth = width; + surfaceHeight = height; + for (com.google.android.exoplayer2.video.VideoListener videoListener : videoListeners) { + videoListener.onSurfaceSizeChanged(width, height); + } + } + } + private final class ComponentListener implements VideoRendererEventListener, AudioRendererEventListener, TextOutput, MetadataOutput, SurfaceHolder.Callback, TextureView.SurfaceTextureListener { @@ -1126,12 +1156,13 @@ public class SimpleExoPlayer implements ExoPlayer, Player.VideoComponent, Player @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { - // Do nothing. + maybeNotifySurfaceSizeChanged(width, height); } @Override public void surfaceDestroyed(SurfaceHolder holder) { setVideoSurfaceInternal(null, false); + maybeNotifySurfaceSizeChanged(/* width= */ 0, /* height= */ 0); } // TextureView.SurfaceTextureListener implementation @@ -1139,16 +1170,18 @@ public class SimpleExoPlayer implements ExoPlayer, Player.VideoComponent, Player @Override public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) { setVideoSurfaceInternal(new Surface(surfaceTexture), true); + maybeNotifySurfaceSizeChanged(width, height); } @Override public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width, int height) { - // Do nothing. + maybeNotifySurfaceSizeChanged(width, height); } @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) { setVideoSurfaceInternal(null, true); + maybeNotifySurfaceSizeChanged(/* width= */ 0, /* height= */ 0); return true; } @@ -1156,7 +1189,6 @@ public class SimpleExoPlayer implements ExoPlayer, Player.VideoComponent, Player public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) { // Do nothing. } - } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/video/VideoListener.java b/library/core/src/main/java/com/google/android/exoplayer2/video/VideoListener.java index ab09e0bbc2..f73f61a160 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/video/VideoListener.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/video/VideoListener.java @@ -37,6 +37,19 @@ public interface VideoListener { void onVideoSizeChanged( int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio); + /** + * Called each time there's a change in the size of the surface onto which the video is being + * rendered. + * + * @param width The surface width in pixels. May be {@link + * com.google.android.exoplayer2.C#LENGTH_UNSET} if unknown, or 0 if the video is not rendered + * onto a surface. + * @param height The surface height in pixels. May be {@link + * com.google.android.exoplayer2.C#LENGTH_UNSET} if unknown, or 0 if the video is not rendered + * onto a surface. + */ + default void onSurfaceSizeChanged(int width, int height) {} + /** * Called when a frame is rendered for the first time since setting the surface, and when a frame * is rendered for the first time since a video track was selected.