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"/> + +