From 8277999b16894a5c54035d5b025d7c65bf9b35ec Mon Sep 17 00:00:00 2001 From: Drew Hill Date: Sat, 17 Dec 2016 13:39:47 -0500 Subject: [PATCH 1/6] add imageview into simpleexoplayerview to display subtitles that are image based --- .../android/exoplayer2/text/ImageCue.java | 15 +++ .../exoplayer2/ui/SimpleExoPlayerView.java | 94 +++++++++++++++++-- .../res/layout/exo_simple_player_view.xml | 6 ++ 3 files changed, 109 insertions(+), 6 deletions(-) create mode 100644 library/src/main/java/com/google/android/exoplayer2/text/ImageCue.java diff --git a/library/src/main/java/com/google/android/exoplayer2/text/ImageCue.java b/library/src/main/java/com/google/android/exoplayer2/text/ImageCue.java new file mode 100644 index 0000000000..6274493780 --- /dev/null +++ b/library/src/main/java/com/google/android/exoplayer2/text/ImageCue.java @@ -0,0 +1,15 @@ +package com.google.android.exoplayer2.text; + +import android.graphics.Bitmap; + +public class ImageCue extends Cue { + + public ImageCue() { super(""); } + + public Bitmap getBitmap() { return null; } + public int getX() { return 0; } + public int getY() { return 0; } + public int getWidth() { return 0; } + public int getHeight() { return 0; } + public boolean isForcedSubtitle() { return false; } +} diff --git a/library/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java b/library/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java index 97c564a3a6..e01956c803 100644 --- a/library/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java +++ b/library/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java @@ -40,6 +40,7 @@ import com.google.android.exoplayer2.metadata.Metadata; import com.google.android.exoplayer2.metadata.id3.ApicFrame; import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.text.Cue; +import com.google.android.exoplayer2.text.ImageCue; import com.google.android.exoplayer2.text.TextRenderer; import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelectionArray; @@ -171,6 +172,7 @@ public final class SimpleExoPlayerView extends FrameLayout { private final View surfaceView; private final ImageView artworkView; private final SubtitleView subtitleView; + private final ImageView subtitleImageView; private final PlaybackControlView controller; private final ComponentListener componentListener; private final FrameLayout overlayFrameLayout; @@ -178,6 +180,7 @@ public final class SimpleExoPlayerView extends FrameLayout { private SimpleExoPlayer player; private boolean useController; private boolean useArtwork; + private boolean subtitlesEnabled = false; private int controllerShowTimeoutMs; public SimpleExoPlayerView(Context context) { @@ -253,6 +256,8 @@ public final class SimpleExoPlayerView extends FrameLayout { subtitleView.setUserDefaultTextSize(); } + subtitleImageView = (ImageView) findViewById(R.id.exo_subtitles_image); + // Playback control view. View controllerPlaceholder = findViewById(R.id.exo_controller_placeholder); if (controllerPlaceholder != null) { @@ -523,14 +528,26 @@ public final class SimpleExoPlayerView extends FrameLayout { return; } TrackSelectionArray selections = player.getCurrentTrackSelections(); + boolean quickExit = false; for (int i = 0; i < selections.length; i++) { - if (player.getRendererType(i) == C.TRACK_TYPE_VIDEO && selections.get(i) != null) { - // Video enabled so artwork must be hidden. If the shutter is closed, it will be opened in - // onRenderedFirstFrame(). - hideArtwork(); - return; + switch(player.getRendererType(i)) { + case C.TRACK_TYPE_VIDEO: + if (selections.get(i) != null) { + // Video enabled so artwork must be hidden. If the shutter is closed, it will be opened in + // onRenderedFirstFrame(). + + hideArtwork(); + quickExit = true; + } + break; + case C.TRACK_TYPE_TEXT: + if (selections.get(i) != null) + subtitlesEnabled = true; + break; } } + if (quickExit) + return; // Video disabled so the shutter must be closed. if (shutterView != null) { shutterView.setVisibility(VISIBLE); @@ -597,20 +614,85 @@ public final class SimpleExoPlayerView extends FrameLayout { private final class ComponentListener implements SimpleExoPlayer.VideoListener, TextRenderer.Output, ExoPlayer.EventListener { + + private int sourceWidth = 0; + private int sourceHeight = 0; + // TextRenderer.Output implementation @Override public void onCues(List cues) { - if (subtitleView != null) { + + boolean skipNormalCues = false; + if (subtitleImageView != null) { + + final ImageCue cue = (cues != null && !cues.isEmpty() && cues.get(0) instanceof ImageCue) ? (ImageCue) cues.get(0) : null; + skipNormalCues = (cue != null); + if (cue == null || (!subtitlesEnabled && !cue.isForcedSubtitle())) { + subtitleImageView.setImageBitmap(null); + subtitleImageView.setVisibility(View.INVISIBLE); + } + else { + handleImageCue(cue); + } + } + if (!skipNormalCues && subtitleView != null) { subtitleView.onCues(cues); } } + private void handleImageCue(ImageCue cue) { + Bitmap bitmap = cue.getBitmap(); + if (bitmap != null && surfaceView != null) { + int surfaceAnchorX = (int) surfaceView.getX(); + int surfaceAnchorY = (int) surfaceView.getY(); + int surfaceWidth = surfaceView.getWidth(); + int surfaceHeight = surfaceView.getHeight(); + int subAnchorX = cue.getX(); + int subAnchorY = cue.getY(); + int subScaleWidth = cue.getWidth(); + int subScaleHeight = cue.getHeight(); + + // they should change together as we keep the aspect ratio + if ((surfaceHeight != sourceHeight || surfaceWidth != sourceWidth) + && sourceHeight > 0 && sourceWidth > 0) { + double scale; + if (surfaceWidth != sourceWidth) + scale = (double) surfaceWidth / (double) sourceWidth; + else + scale = (double) surfaceHeight / (double) sourceHeight; + subScaleHeight = (int) (scale * subScaleHeight); + subScaleWidth = (int) (scale * subScaleWidth); + } + if (surfaceAnchorX != 0) + subAnchorX += surfaceAnchorX; + if (subAnchorY != 0) + subAnchorY += surfaceAnchorY; + + ViewGroup.LayoutParams params = subtitleImageView.getLayoutParams(); + params.width = subScaleWidth; + params.height = subScaleHeight; + subtitleImageView.setX(subAnchorX); + subtitleImageView.setY(subAnchorY); + subtitleImageView.setLayoutParams(params); + subtitleImageView.setImageBitmap(bitmap); + subtitleImageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); + subtitleImageView.setVisibility(View.VISIBLE); + } + else { + subtitleImageView.setImageBitmap(null); + subtitleImageView.setVisibility(View.INVISIBLE); + } + } + // SimpleExoPlayer.VideoListener implementation @Override public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) { + + sourceWidth = width; + sourceHeight = height; if (contentFrame != null) { float aspectRatio = height == 0 ? 1 : (width * pixelWidthHeightRatio) / height; contentFrame.setAspectRatio(aspectRatio); diff --git a/library/src/main/res/layout/exo_simple_player_view.xml b/library/src/main/res/layout/exo_simple_player_view.xml index 1f59b7796d..bfd5638713 100644 --- a/library/src/main/res/layout/exo_simple_player_view.xml +++ b/library/src/main/res/layout/exo_simple_player_view.xml @@ -36,6 +36,12 @@ android:layout_width="match_parent" android:layout_height="match_parent"/> + + Date: Sat, 17 Dec 2016 14:43:07 -0500 Subject: [PATCH 2/6] less interfacy.. more classy --- .../android/exoplayer2/text/ImageCue.java | 32 +++++++++++++++---- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/library/src/main/java/com/google/android/exoplayer2/text/ImageCue.java b/library/src/main/java/com/google/android/exoplayer2/text/ImageCue.java index 6274493780..2dc0c97238 100644 --- a/library/src/main/java/com/google/android/exoplayer2/text/ImageCue.java +++ b/library/src/main/java/com/google/android/exoplayer2/text/ImageCue.java @@ -4,12 +4,30 @@ import android.graphics.Bitmap; public class ImageCue extends Cue { - public ImageCue() { super(""); } + final private long start_display_time; + final private int x; + final private int y; + final private int height; + final private int width; + final private Bitmap bitmap; + final private boolean isForced; - public Bitmap getBitmap() { return null; } - public int getX() { return 0; } - public int getY() { return 0; } - public int getWidth() { return 0; } - public int getHeight() { return 0; } - public boolean isForcedSubtitle() { return false; } + public ImageCue(Bitmap bitmap, long start_display_time, int x, int y, int width, int height, boolean isForced) { + super(""); + this.bitmap = bitmap; + this.start_display_time = start_display_time; + this.x = x; + this.y = y; + this.width = width; + this.height = height; + this.isForced = isForced; + } + + public long getStartDisplayTime() { return start_display_time; } + public Bitmap getBitmap() { return bitmap; } + public int getX() { return x; } + public int getY() { return y; } + public int getWidth() { return width; } + public int getHeight() { return height; } + public boolean isForcedSubtitle() { return isForced; } } From 47d8b7ff164ae2b162913ec9fea92bcc7fa58839 Mon Sep 17 00:00:00 2001 From: Drew Hill Date: Sun, 18 Dec 2016 22:37:37 -0500 Subject: [PATCH 3/6] get source dimensions from plane stored in subs --- .../android/exoplayer2/text/ImageCue.java | 22 +++++++++++++------ .../exoplayer2/ui/SimpleExoPlayerView.java | 12 ++++------ 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/library/src/main/java/com/google/android/exoplayer2/text/ImageCue.java b/library/src/main/java/com/google/android/exoplayer2/text/ImageCue.java index 2dc0c97238..b5906cf41d 100644 --- a/library/src/main/java/com/google/android/exoplayer2/text/ImageCue.java +++ b/library/src/main/java/com/google/android/exoplayer2/text/ImageCue.java @@ -7,19 +7,25 @@ public class ImageCue extends Cue { final private long start_display_time; final private int x; final private int y; - final private int height; - final private int width; + final private int bitmap_height; + final private int bitmap_width; + final private int plane_height; + final private int plane_width; final private Bitmap bitmap; final private boolean isForced; - public ImageCue(Bitmap bitmap, long start_display_time, int x, int y, int width, int height, boolean isForced) { + public ImageCue(Bitmap bitmap, long start_display_time, + int x, int y, int bitmap_width, int bitmap_height, boolean isForced, + int plane_width, int plane_height) { super(""); this.bitmap = bitmap; this.start_display_time = start_display_time; this.x = x; this.y = y; - this.width = width; - this.height = height; + this.bitmap_width = bitmap_width; + this.bitmap_height = bitmap_height; + this.plane_width = plane_width; + this.plane_height = plane_height; this.isForced = isForced; } @@ -27,7 +33,9 @@ public class ImageCue extends Cue { public Bitmap getBitmap() { return bitmap; } public int getX() { return x; } public int getY() { return y; } - public int getWidth() { return width; } - public int getHeight() { return height; } + public int getBitmapWidth() { return bitmap_width; } + public int getBitmapHeight() { return bitmap_height; } + public int getPlaneWidth() { return plane_width; } + public int getPlaneHeight() { return plane_height; } public boolean isForcedSubtitle() { return isForced; } } diff --git a/library/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java b/library/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java index e01956c803..ffe2ca31e0 100644 --- a/library/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java +++ b/library/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java @@ -614,10 +614,6 @@ public final class SimpleExoPlayerView extends FrameLayout { private final class ComponentListener implements SimpleExoPlayer.VideoListener, TextRenderer.Output, ExoPlayer.EventListener { - - private int sourceWidth = 0; - private int sourceHeight = 0; - // TextRenderer.Output implementation @Override @@ -648,10 +644,12 @@ public final class SimpleExoPlayerView extends FrameLayout { int surfaceAnchorY = (int) surfaceView.getY(); int surfaceWidth = surfaceView.getWidth(); int surfaceHeight = surfaceView.getHeight(); + int sourceWidth = cue.getPlaneWidth(); + int sourceHeight = cue.getPlaneHeight(); int subAnchorX = cue.getX(); int subAnchorY = cue.getY(); - int subScaleWidth = cue.getWidth(); - int subScaleHeight = cue.getHeight(); + int subScaleWidth = cue.getBitmapWidth(); + int subScaleHeight = cue.getBitmapHeight(); // they should change together as we keep the aspect ratio if ((surfaceHeight != sourceHeight || surfaceWidth != sourceWidth) @@ -691,8 +689,6 @@ public final class SimpleExoPlayerView extends FrameLayout { public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) { - sourceWidth = width; - sourceHeight = height; if (contentFrame != null) { float aspectRatio = height == 0 ? 1 : (width * pixelWidthHeightRatio) / height; contentFrame.setAspectRatio(aspectRatio); From 44b21f2e3b65787aa6b5b547d5ac67e97a924a61 Mon Sep 17 00:00:00 2001 From: Drew Hill Date: Tue, 20 Dec 2016 22:49:18 -0500 Subject: [PATCH 4/6] remove imagecue and add bitmap to cue with size_height, change to painter for displaying --- .../google/android/exoplayer2/text/Cue.java | 45 ++++++++ .../android/exoplayer2/text/ImageCue.java | 41 ------- .../exoplayer2/ui/SimpleExoPlayerView.java | 65 +---------- .../exoplayer2/ui/SubtitlePainter.java | 104 +++++++++++++----- .../res/layout/exo_simple_player_view.xml | 6 - 5 files changed, 125 insertions(+), 136 deletions(-) delete mode 100644 library/src/main/java/com/google/android/exoplayer2/text/ImageCue.java diff --git a/library/src/main/java/com/google/android/exoplayer2/text/Cue.java b/library/src/main/java/com/google/android/exoplayer2/text/Cue.java index 93b1dc1d9a..23cce573f7 100644 --- a/library/src/main/java/com/google/android/exoplayer2/text/Cue.java +++ b/library/src/main/java/com/google/android/exoplayer2/text/Cue.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer2.text; +import android.graphics.Bitmap; import android.support.annotation.IntDef; import android.text.Layout.Alignment; import java.lang.annotation.Retention; @@ -78,6 +79,10 @@ public class Cue { * The alignment of the cue text within the cue box, or null if the alignment is undefined. */ public final Alignment textAlignment; + /** + * The cue image. + */ + public final Bitmap bitmap; /** * The position of the {@link #lineAnchor} of the cue box within the viewport in the direction * orthogonal to the writing direction, or {@link #DIMEN_UNSET}. When set, the interpretation of @@ -85,6 +90,8 @@ public class Cue { *

* For horizontal text and {@link #lineType} equal to {@link #LINE_TYPE_FRACTION}, this is the * fractional vertical position relative to the top of the viewport. + *

+ * If {@link #bitmap} is not null then this value is used to indicate the top position */ public final float line; /** @@ -119,6 +126,8 @@ public class Cue { * For horizontal text, this is the horizontal position relative to the left of the viewport. Note * that positioning is relative to the left of the viewport even in the case of right-to-left * text. + *

+ * If {@link #bitmap} is not null then this value is used to indicate the left position */ public final float position; /** @@ -134,9 +143,25 @@ public class Cue { /** * The size of the cue box in the writing direction specified as a fraction of the viewport size * in that direction, or {@link #DIMEN_UNSET}. + *

+ * If {@link #bitmap} is not null then this value is used to indicate the width */ public final float size; + /** + * The height size of the cue box when a {@link #bitmap} is set specified as a fraction of the + * viewport size in that direction, or {@link #DIMEN_UNSET}. + */ + public final float size_height; + + /** + * + */ + public Cue(Bitmap bitmap, float left, float top, float size, float size_height) { + this(null, null, top, LINE_TYPE_FRACTION, TYPE_UNSET, left, TYPE_UNSET, size, size_height, + bitmap); + } + /** * Constructs a cue whose {@link #textAlignment} is null, whose type parameters are set to * {@link #TYPE_UNSET} and whose dimension parameters are set to {@link #DIMEN_UNSET}. @@ -159,6 +184,24 @@ public class Cue { */ public Cue(CharSequence text, Alignment textAlignment, float line, @LineType int lineType, @AnchorType int lineAnchor, float position, @AnchorType int positionAnchor, float size) { + this(text, textAlignment, line, lineType, lineAnchor, position, positionAnchor, size, + DIMEN_UNSET, null); + } + /** + * @param text See {@link #text}. + * @param textAlignment See {@link #textAlignment}. + * @param line See {@link #line}. + * @param lineType See {@link #lineType}. + * @param lineAnchor See {@link #lineAnchor}. + * @param position See {@link #position}. + * @param positionAnchor See {@link #positionAnchor}. + * @param size See {@link #size}. + * @param size_height See {@link #size_height}. + * @param bitmap See {@link #bitmap}. + */ + private Cue(CharSequence text, Alignment textAlignment, float line, @LineType int lineType, + @AnchorType int lineAnchor, float position, @AnchorType int positionAnchor, float size, + float size_height, Bitmap bitmap) { this.text = text; this.textAlignment = textAlignment; this.line = line; @@ -167,6 +210,8 @@ public class Cue { this.position = position; this.positionAnchor = positionAnchor; this.size = size; + this.size_height = size_height; + this.bitmap = bitmap; } } diff --git a/library/src/main/java/com/google/android/exoplayer2/text/ImageCue.java b/library/src/main/java/com/google/android/exoplayer2/text/ImageCue.java deleted file mode 100644 index b5906cf41d..0000000000 --- a/library/src/main/java/com/google/android/exoplayer2/text/ImageCue.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.google.android.exoplayer2.text; - -import android.graphics.Bitmap; - -public class ImageCue extends Cue { - - final private long start_display_time; - final private int x; - final private int y; - final private int bitmap_height; - final private int bitmap_width; - final private int plane_height; - final private int plane_width; - final private Bitmap bitmap; - final private boolean isForced; - - public ImageCue(Bitmap bitmap, long start_display_time, - int x, int y, int bitmap_width, int bitmap_height, boolean isForced, - int plane_width, int plane_height) { - super(""); - this.bitmap = bitmap; - this.start_display_time = start_display_time; - this.x = x; - this.y = y; - this.bitmap_width = bitmap_width; - this.bitmap_height = bitmap_height; - this.plane_width = plane_width; - this.plane_height = plane_height; - this.isForced = isForced; - } - - public long getStartDisplayTime() { return start_display_time; } - public Bitmap getBitmap() { return bitmap; } - public int getX() { return x; } - public int getY() { return y; } - public int getBitmapWidth() { return bitmap_width; } - public int getBitmapHeight() { return bitmap_height; } - public int getPlaneWidth() { return plane_width; } - public int getPlaneHeight() { return plane_height; } - public boolean isForcedSubtitle() { return isForced; } -} diff --git a/library/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java b/library/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java index ffe2ca31e0..0e63ee9ba4 100644 --- a/library/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java +++ b/library/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java @@ -40,7 +40,6 @@ import com.google.android.exoplayer2.metadata.Metadata; import com.google.android.exoplayer2.metadata.id3.ApicFrame; import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.text.Cue; -import com.google.android.exoplayer2.text.ImageCue; import com.google.android.exoplayer2.text.TextRenderer; import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelectionArray; @@ -172,7 +171,6 @@ public final class SimpleExoPlayerView extends FrameLayout { private final View surfaceView; private final ImageView artworkView; private final SubtitleView subtitleView; - private final ImageView subtitleImageView; private final PlaybackControlView controller; private final ComponentListener componentListener; private final FrameLayout overlayFrameLayout; @@ -256,8 +254,6 @@ public final class SimpleExoPlayerView extends FrameLayout { subtitleView.setUserDefaultTextSize(); } - subtitleImageView = (ImageView) findViewById(R.id.exo_subtitles_image); - // Playback control view. View controllerPlaceholder = findViewById(R.id.exo_controller_placeholder); if (controllerPlaceholder != null) { @@ -619,70 +615,11 @@ public final class SimpleExoPlayerView extends FrameLayout { @Override public void onCues(List cues) { - boolean skipNormalCues = false; - if (subtitleImageView != null) { - - final ImageCue cue = (cues != null && !cues.isEmpty() && cues.get(0) instanceof ImageCue) ? (ImageCue) cues.get(0) : null; - skipNormalCues = (cue != null); - if (cue == null || (!subtitlesEnabled && !cue.isForcedSubtitle())) { - subtitleImageView.setImageBitmap(null); - subtitleImageView.setVisibility(View.INVISIBLE); - } - else { - handleImageCue(cue); - } - } - if (!skipNormalCues && subtitleView != null) { + if (subtitleView != null) { subtitleView.onCues(cues); } } - private void handleImageCue(ImageCue cue) { - Bitmap bitmap = cue.getBitmap(); - if (bitmap != null && surfaceView != null) { - int surfaceAnchorX = (int) surfaceView.getX(); - int surfaceAnchorY = (int) surfaceView.getY(); - int surfaceWidth = surfaceView.getWidth(); - int surfaceHeight = surfaceView.getHeight(); - int sourceWidth = cue.getPlaneWidth(); - int sourceHeight = cue.getPlaneHeight(); - int subAnchorX = cue.getX(); - int subAnchorY = cue.getY(); - int subScaleWidth = cue.getBitmapWidth(); - int subScaleHeight = cue.getBitmapHeight(); - - // they should change together as we keep the aspect ratio - if ((surfaceHeight != sourceHeight || surfaceWidth != sourceWidth) - && sourceHeight > 0 && sourceWidth > 0) { - double scale; - if (surfaceWidth != sourceWidth) - scale = (double) surfaceWidth / (double) sourceWidth; - else - scale = (double) surfaceHeight / (double) sourceHeight; - subScaleHeight = (int) (scale * subScaleHeight); - subScaleWidth = (int) (scale * subScaleWidth); - } - if (surfaceAnchorX != 0) - subAnchorX += surfaceAnchorX; - if (subAnchorY != 0) - subAnchorY += surfaceAnchorY; - - ViewGroup.LayoutParams params = subtitleImageView.getLayoutParams(); - params.width = subScaleWidth; - params.height = subScaleHeight; - subtitleImageView.setX(subAnchorX); - subtitleImageView.setY(subAnchorY); - subtitleImageView.setLayoutParams(params); - subtitleImageView.setImageBitmap(bitmap); - subtitleImageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); - subtitleImageView.setVisibility(View.VISIBLE); - } - else { - subtitleImageView.setImageBitmap(null); - subtitleImageView.setVisibility(View.INVISIBLE); - } - } - // SimpleExoPlayer.VideoListener implementation @Override diff --git a/library/src/main/java/com/google/android/exoplayer2/ui/SubtitlePainter.java b/library/src/main/java/com/google/android/exoplayer2/ui/SubtitlePainter.java index 8c3ac77cb2..73c465fe95 100644 --- a/library/src/main/java/com/google/android/exoplayer2/ui/SubtitlePainter.java +++ b/library/src/main/java/com/google/android/exoplayer2/ui/SubtitlePainter.java @@ -18,11 +18,13 @@ package com.google.android.exoplayer2.ui; import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; +import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Paint.Join; import android.graphics.Paint.Style; +import android.graphics.Rect; import android.graphics.RectF; import android.text.Layout.Alignment; import android.text.StaticLayout; @@ -63,6 +65,7 @@ import com.google.android.exoplayer2.util.Util; private final Paint paint; // Previous input variables. + private Bitmap cueBitmap; private CharSequence cueText; private Alignment cueTextAlignment; private float cueLine; @@ -74,6 +77,7 @@ import com.google.android.exoplayer2.util.Util; @Cue.AnchorType private int cuePositionAnchor; private float cueSize; + private float cueSizeHeight; private boolean applyEmbeddedStyles; private int foregroundColor; private int backgroundColor; @@ -93,6 +97,7 @@ import com.google.android.exoplayer2.util.Util; private int textLeft; private int textTop; private int textPaddingX; + private Rect bitmapRect; @SuppressWarnings("ResourceType") public SubtitlePainter(Context context) { @@ -142,40 +147,43 @@ import com.google.android.exoplayer2.util.Util; float bottomPaddingFraction, Canvas canvas, int cueBoxLeft, int cueBoxTop, int cueBoxRight, int cueBoxBottom) { CharSequence cueText = cue.text; - if (TextUtils.isEmpty(cueText)) { + boolean textIsEmpty = TextUtils.isEmpty(cueText); + if (textIsEmpty && cue.bitmap == null) { // Nothing to draw. return; } - if (!applyEmbeddedStyles) { + if (!applyEmbeddedStyles && !textIsEmpty) { // Strip out any embedded styling. cueText = cueText.toString(); } - if (areCharSequencesEqual(this.cueText, cueText) - && Util.areEqual(this.cueTextAlignment, cue.textAlignment) - && this.cueLine == cue.line - && this.cueLineType == cue.lineType - && Util.areEqual(this.cueLineAnchor, cue.lineAnchor) - && this.cuePosition == cue.position - && Util.areEqual(this.cuePositionAnchor, cue.positionAnchor) - && this.cueSize == cue.size - && this.applyEmbeddedStyles == applyEmbeddedStyles - && this.foregroundColor == style.foregroundColor - && this.backgroundColor == style.backgroundColor - && this.windowColor == style.windowColor - && this.edgeType == style.edgeType - && this.edgeColor == style.edgeColor - && Util.areEqual(this.textPaint.getTypeface(), style.typeface) - && this.textSizePx == textSizePx - && this.bottomPaddingFraction == bottomPaddingFraction - && this.parentLeft == cueBoxLeft - && this.parentTop == cueBoxTop - && this.parentRight == cueBoxRight - && this.parentBottom == cueBoxBottom) { + if (((cue.bitmap != null && cue.bitmap == cueBitmap) || + (!textIsEmpty && areCharSequencesEqual(this.cueText, cueText))) + && Util.areEqual(this.cueTextAlignment, cue.textAlignment) + && this.cueLine == cue.line + && this.cueLineType == cue.lineType + && Util.areEqual(this.cueLineAnchor, cue.lineAnchor) + && this.cuePosition == cue.position + && Util.areEqual(this.cuePositionAnchor, cue.positionAnchor) + && this.cueSize == cue.size + && this.applyEmbeddedStyles == applyEmbeddedStyles + && this.foregroundColor == style.foregroundColor + && this.backgroundColor == style.backgroundColor + && this.windowColor == style.windowColor + && this.edgeType == style.edgeType + && this.edgeColor == style.edgeColor + && Util.areEqual(this.textPaint.getTypeface(), style.typeface) + && this.textSizePx == textSizePx + && this.bottomPaddingFraction == bottomPaddingFraction + && this.parentLeft == cueBoxLeft + && this.parentTop == cueBoxTop + && this.parentRight == cueBoxRight + && this.parentBottom == cueBoxBottom) { // We can use the cached layout. drawLayout(canvas); return; } + this.cueBitmap = cue.bitmap; this.cueText = cueText; this.cueTextAlignment = cue.textAlignment; this.cueLine = cue.line; @@ -184,6 +192,7 @@ import com.google.android.exoplayer2.util.Util; this.cuePosition = cue.position; this.cuePositionAnchor = cue.positionAnchor; this.cueSize = cue.size; + this.cueSizeHeight = cue.size_height; this.applyEmbeddedStyles = applyEmbeddedStyles; this.foregroundColor = style.foregroundColor; this.backgroundColor = style.backgroundColor; @@ -198,6 +207,32 @@ import com.google.android.exoplayer2.util.Util; this.parentRight = cueBoxRight; this.parentBottom = cueBoxBottom; + if (this.cueBitmap != null) + setupBitmapLayout(); + else + setupTextLayout(); + + drawLayout(canvas); + } + + /** + * Setup {@link #textLayout} for later drawing. + */ + private void setupBitmapLayout() { + + int parentWidth = parentRight - parentLeft; + int parentHeight = parentBottom - parentTop; + int x = parentLeft + (int) ((float) parentWidth * cuePosition); + int y = parentTop + (int) ((float) parentHeight * cueLine); + bitmapRect = new Rect(x,y, + x + (int)((float) parentWidth * cueSize),y + (int)((float) parentHeight * cueSizeHeight)); + } + + /** + * Setup {@link #textLayout} for later drawing. + */ + private void setupTextLayout() { + int parentWidth = parentRight - parentLeft; int parentHeight = parentBottom - parentTop; @@ -275,8 +310,27 @@ import com.google.android.exoplayer2.util.Util; this.textLeft = textLeft; this.textTop = textTop; this.textPaddingX = textPaddingX; + } - drawLayout(canvas); + /** + * Draws {@link #textLayout} or {@link #cueBitmap} into the provided canvas. + * + * @param canvas The canvas into which to draw. + */ + private void drawLayout(Canvas canvas) { + if (cueBitmap != null) + drawBitmapLayout(canvas); + else + drawTextLayout(canvas); + } + + /** + * Draws {@link #cueBitmap} into the provided canvas. + * + * @param canvas The canvas into which to draw. + */ + private void drawBitmapLayout(Canvas canvas) { + canvas.drawBitmap(cueBitmap, null, bitmapRect, null); } /** @@ -284,7 +338,7 @@ import com.google.android.exoplayer2.util.Util; * * @param canvas The canvas into which to draw. */ - private void drawLayout(Canvas canvas) { + private void drawTextLayout(Canvas canvas) { final StaticLayout layout = textLayout; if (layout == null) { // Nothing to draw. diff --git a/library/src/main/res/layout/exo_simple_player_view.xml b/library/src/main/res/layout/exo_simple_player_view.xml index bfd5638713..1f59b7796d 100644 --- a/library/src/main/res/layout/exo_simple_player_view.xml +++ b/library/src/main/res/layout/exo_simple_player_view.xml @@ -36,12 +36,6 @@ android:layout_width="match_parent" android:layout_height="match_parent"/> - - Date: Wed, 21 Dec 2016 07:54:23 -0500 Subject: [PATCH 5/6] remove unneeded changes --- .../exoplayer2/ui/SimpleExoPlayerView.java | 25 ++++--------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/library/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java b/library/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java index 0e63ee9ba4..97c564a3a6 100644 --- a/library/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java +++ b/library/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java @@ -178,7 +178,6 @@ public final class SimpleExoPlayerView extends FrameLayout { private SimpleExoPlayer player; private boolean useController; private boolean useArtwork; - private boolean subtitlesEnabled = false; private int controllerShowTimeoutMs; public SimpleExoPlayerView(Context context) { @@ -524,26 +523,14 @@ public final class SimpleExoPlayerView extends FrameLayout { return; } TrackSelectionArray selections = player.getCurrentTrackSelections(); - boolean quickExit = false; for (int i = 0; i < selections.length; i++) { - switch(player.getRendererType(i)) { - case C.TRACK_TYPE_VIDEO: - if (selections.get(i) != null) { - // Video enabled so artwork must be hidden. If the shutter is closed, it will be opened in - // onRenderedFirstFrame(). - - hideArtwork(); - quickExit = true; - } - break; - case C.TRACK_TYPE_TEXT: - if (selections.get(i) != null) - subtitlesEnabled = true; - break; + if (player.getRendererType(i) == C.TRACK_TYPE_VIDEO && selections.get(i) != null) { + // Video enabled so artwork must be hidden. If the shutter is closed, it will be opened in + // onRenderedFirstFrame(). + hideArtwork(); + return; } } - if (quickExit) - return; // Video disabled so the shutter must be closed. if (shutterView != null) { shutterView.setVisibility(VISIBLE); @@ -614,7 +601,6 @@ public final class SimpleExoPlayerView extends FrameLayout { @Override public void onCues(List cues) { - if (subtitleView != null) { subtitleView.onCues(cues); } @@ -625,7 +611,6 @@ public final class SimpleExoPlayerView extends FrameLayout { @Override public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) { - if (contentFrame != null) { float aspectRatio = height == 0 ? 1 : (width * pixelWidthHeightRatio) / height; contentFrame.setAspectRatio(aspectRatio); From 0468a80d4125af669c0dadf66bd53144db323423 Mon Sep 17 00:00:00 2001 From: Drew Hill Date: Thu, 5 Jan 2017 21:27:24 -0500 Subject: [PATCH 6/6] just use original plane width to calculate width proportion to use later as size and keep aspect ratio for height --- .../google/android/exoplayer2/text/Cue.java | 25 ++++--------------- .../exoplayer2/ui/SubtitlePainter.java | 7 +++--- 2 files changed, 8 insertions(+), 24 deletions(-) diff --git a/library/src/main/java/com/google/android/exoplayer2/text/Cue.java b/library/src/main/java/com/google/android/exoplayer2/text/Cue.java index 23cce573f7..5acb29da33 100644 --- a/library/src/main/java/com/google/android/exoplayer2/text/Cue.java +++ b/library/src/main/java/com/google/android/exoplayer2/text/Cue.java @@ -90,8 +90,6 @@ public class Cue { *

* For horizontal text and {@link #lineType} equal to {@link #LINE_TYPE_FRACTION}, this is the * fractional vertical position relative to the top of the viewport. - *

- * If {@link #bitmap} is not null then this value is used to indicate the top position */ public final float line; /** @@ -126,8 +124,6 @@ public class Cue { * For horizontal text, this is the horizontal position relative to the left of the viewport. Note * that positioning is relative to the left of the viewport even in the case of right-to-left * text. - *

- * If {@link #bitmap} is not null then this value is used to indicate the left position */ public final float position; /** @@ -143,23 +139,15 @@ public class Cue { /** * The size of the cue box in the writing direction specified as a fraction of the viewport size * in that direction, or {@link #DIMEN_UNSET}. - *

- * If {@link #bitmap} is not null then this value is used to indicate the width */ public final float size; - /** - * The height size of the cue box when a {@link #bitmap} is set specified as a fraction of the - * viewport size in that direction, or {@link #DIMEN_UNSET}. - */ - public final float size_height; - /** * */ - public Cue(Bitmap bitmap, float left, float top, float size, float size_height) { - this(null, null, top, LINE_TYPE_FRACTION, TYPE_UNSET, left, TYPE_UNSET, size, size_height, - bitmap); + public Cue(Bitmap bitmap, float left, float top, int plane_width) { + this(null, null, top, LINE_TYPE_FRACTION, ANCHOR_TYPE_START, left, ANCHOR_TYPE_START, + (float) bitmap.getWidth() / plane_width, bitmap); } /** @@ -184,8 +172,7 @@ public class Cue { */ public Cue(CharSequence text, Alignment textAlignment, float line, @LineType int lineType, @AnchorType int lineAnchor, float position, @AnchorType int positionAnchor, float size) { - this(text, textAlignment, line, lineType, lineAnchor, position, positionAnchor, size, - DIMEN_UNSET, null); + this(text, textAlignment, line, lineType, lineAnchor, position, positionAnchor, size, null); } /** * @param text See {@link #text}. @@ -196,12 +183,11 @@ public class Cue { * @param position See {@link #position}. * @param positionAnchor See {@link #positionAnchor}. * @param size See {@link #size}. - * @param size_height See {@link #size_height}. * @param bitmap See {@link #bitmap}. */ private Cue(CharSequence text, Alignment textAlignment, float line, @LineType int lineType, @AnchorType int lineAnchor, float position, @AnchorType int positionAnchor, float size, - float size_height, Bitmap bitmap) { + Bitmap bitmap) { this.text = text; this.textAlignment = textAlignment; this.line = line; @@ -210,7 +196,6 @@ public class Cue { this.position = position; this.positionAnchor = positionAnchor; this.size = size; - this.size_height = size_height; this.bitmap = bitmap; } diff --git a/library/src/main/java/com/google/android/exoplayer2/ui/SubtitlePainter.java b/library/src/main/java/com/google/android/exoplayer2/ui/SubtitlePainter.java index 73c465fe95..b8b55e27ce 100644 --- a/library/src/main/java/com/google/android/exoplayer2/ui/SubtitlePainter.java +++ b/library/src/main/java/com/google/android/exoplayer2/ui/SubtitlePainter.java @@ -77,7 +77,6 @@ import com.google.android.exoplayer2.util.Util; @Cue.AnchorType private int cuePositionAnchor; private float cueSize; - private float cueSizeHeight; private boolean applyEmbeddedStyles; private int foregroundColor; private int backgroundColor; @@ -192,7 +191,6 @@ import com.google.android.exoplayer2.util.Util; this.cuePosition = cue.position; this.cuePositionAnchor = cue.positionAnchor; this.cueSize = cue.size; - this.cueSizeHeight = cue.size_height; this.applyEmbeddedStyles = applyEmbeddedStyles; this.foregroundColor = style.foregroundColor; this.backgroundColor = style.backgroundColor; @@ -224,8 +222,9 @@ import com.google.android.exoplayer2.util.Util; int parentHeight = parentBottom - parentTop; int x = parentLeft + (int) ((float) parentWidth * cuePosition); int y = parentTop + (int) ((float) parentHeight * cueLine); - bitmapRect = new Rect(x,y, - x + (int)((float) parentWidth * cueSize),y + (int)((float) parentHeight * cueSizeHeight)); + int width = (int) (parentWidth * cueSize); + int height = (int) (width * ((float) cueBitmap.getHeight() / cueBitmap.getWidth())); + bitmapRect = new Rect(x, y, x + width, y + height); } /**