summaryrefslogtreecommitdiff
path: root/core/java/android/widget/VideoView.java
diff options
context:
space:
mode:
authorAlan Viverette <alanv@google.com>2013-09-05 16:34:30 -0700
committerLajos Molnar <lajos@google.com>2013-09-06 18:06:23 -0700
commitd43daf361e993457e64eeeddab6d1a0ebc828c99 (patch)
tree88f4e2eb3cac28bf5c31909b814f116a78fa57fa /core/java/android/widget/VideoView.java
parent171c63db9253e77c2bd11c53eb89b7c3c983669f (diff)
Add WebVTT caption renderer
Currently missing support for region anchor points, robust layout when snapping to lines, and vertical text. BUG: 10260603 Change-Id: I3463b4aa0039442159144e66922d67f5dfee58ed
Diffstat (limited to 'core/java/android/widget/VideoView.java')
-rw-r--r--core/java/android/widget/VideoView.java162
1 files changed, 68 insertions, 94 deletions
diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java
index f449797d8053..009b729ffc75 100644
--- a/core/java/android/widget/VideoView.java
+++ b/core/java/android/widget/VideoView.java
@@ -30,6 +30,7 @@ import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnInfoListener;
import android.media.Metadata;
import android.media.SubtitleController;
+import android.media.SubtitleTrack.RenderingWidget;
import android.media.WebVttRenderer;
import android.net.Uri;
import android.util.AttributeSet;
@@ -46,7 +47,6 @@ import android.widget.MediaController.MediaPlayerControl;
import java.io.IOException;
import java.io.InputStream;
-import java.util.ArrayList;
import java.util.Map;
import java.util.Vector;
@@ -100,14 +100,11 @@ public class VideoView extends SurfaceView
private boolean mCanSeekBack;
private boolean mCanSeekForward;
- /** List of views overlaid on top of the video. */
- private ArrayList<View> mOverlays;
+ /** Subtitle rendering widget overlaid on top of the video. */
+ private RenderingWidget mSubtitleWidget;
- /**
- * Listener for overlay layout changes. Invalidates the video view to ensure
- * that captions are redrawn whenever their layout changes.
- */
- private OnLayoutChangeListener mOverlayLayoutListener;
+ /** Listener for changes to subtitle data, used to redraw when needed. */
+ private RenderingWidget.OnChangedListener mSubtitlesChangedListener;
public VideoView(Context context) {
super(context);
@@ -302,11 +299,10 @@ public class VideoView extends SurfaceView
mMediaPlayer = new MediaPlayer();
// TODO: create SubtitleController in MediaPlayer, but we need
// a context for the subtitle renderers
- SubtitleController controller = new SubtitleController(
- getContext(),
- mMediaPlayer.getMediaTimeProvider(),
- mMediaPlayer);
- controller.registerRenderer(new WebVttRenderer(getContext(), null));
+ final Context context = getContext();
+ final SubtitleController controller = new SubtitleController(
+ context, mMediaPlayer.getMediaTimeProvider(), mMediaPlayer);
+ controller.registerRenderer(new WebVttRenderer(context));
mMediaPlayer.setSubtitleAnchor(controller, this);
if (mAudioSession != 0) {
@@ -792,117 +788,95 @@ public class VideoView extends SurfaceView
}
@Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
- // Layout overlay views, if necessary.
- if (changed && mOverlays != null && !mOverlays.isEmpty()) {
- measureAndLayoutOverlays();
+ if (mSubtitleWidget != null) {
+ mSubtitleWidget.onAttachedToWindow();
}
}
@Override
- public void draw(Canvas canvas) {
- super.draw(canvas);
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
- final int count = mOverlays.size();
- for (int i = 0; i < count; i++) {
- final View overlay = mOverlays.get(i);
- overlay.draw(canvas);
+ if (mSubtitleWidget != null) {
+ mSubtitleWidget.onDetachedFromWindow();
}
}
- /**
- * Adds a view to be overlaid on top of this video view. During layout, the
- * view will be forced to match the bounds, less padding, of the video view.
- * <p>
- * Overlays are drawn in the order they are added. The last added overlay
- * will be drawn on top.
- *
- * @param overlay the view to overlay
- * @see #removeOverlay(View)
- */
- private void addOverlay(View overlay) {
- if (mOverlays == null) {
- mOverlays = new ArrayList<View>(1);
- }
-
- if (mOverlayLayoutListener == null) {
- mOverlayLayoutListener = new OnLayoutChangeListener() {
- @Override
- public void onLayoutChange(View v, int left, int top, int right, int bottom,
- int oldLeft, int oldTop, int oldRight, int oldBottom) {
- invalidate();
- }
- };
- }
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
- if (mOverlays.isEmpty()) {
- setWillNotDraw(false);
+ if (mSubtitleWidget != null) {
+ measureAndLayoutSubtitleWidget();
}
-
- mOverlays.add(overlay);
- overlay.addOnLayoutChangeListener(mOverlayLayoutListener);
- measureAndLayoutOverlays();
}
- /**
- * Removes a view previously added using {@link #addOverlay}.
- *
- * @param overlay the view to remove
- * @see #addOverlay(View)
- */
- private void removeOverlay(View overlay) {
- if (mOverlays == null) {
- return;
- }
-
- overlay.removeOnLayoutChangeListener(mOverlayLayoutListener);
- mOverlays.remove(overlay);
+ @Override
+ public void draw(Canvas canvas) {
+ super.draw(canvas);
- if (mOverlays.isEmpty()) {
- setWillNotDraw(true);
+ if (mSubtitleWidget != null) {
+ final int saveCount = canvas.save();
+ canvas.translate(getPaddingLeft(), getPaddingTop());
+ mSubtitleWidget.draw(canvas);
+ canvas.restoreToCount(saveCount);
}
-
- invalidate();
}
/**
* Forces a measurement and layout pass for all overlaid views.
*
- * @see #addOverlay(View)
+ * @see #setSubtitleWidget(RenderingWidget)
*/
- private void measureAndLayoutOverlays() {
- final int left = getPaddingLeft();
- final int top = getPaddingTop();
- final int right = getWidth() - left - getPaddingRight();
- final int bottom = getHeight() - top - getPaddingBottom();
- final int widthSpec = MeasureSpec.makeMeasureSpec(right - left, MeasureSpec.EXACTLY);
- final int heightSpec = MeasureSpec.makeMeasureSpec(bottom - top, MeasureSpec.EXACTLY);
+ private void measureAndLayoutSubtitleWidget() {
+ final int width = getWidth() - getPaddingLeft() - getPaddingRight();
+ final int height = getHeight() - getPaddingTop() - getPaddingBottom();
- final int count = mOverlays.size();
- for (int i = 0; i < count; i++) {
- final View overlay = mOverlays.get(i);
- overlay.measure(widthSpec, heightSpec);
- overlay.layout(left, top, right, bottom);
- }
+ mSubtitleWidget.setSize(width, height);
}
/** @hide */
@Override
- public void setSubtitleView(View view) {
- if (mSubtitleView == view) {
+ public void setSubtitleWidget(RenderingWidget subtitleWidget) {
+ if (mSubtitleWidget == subtitleWidget) {
return;
}
- if (mSubtitleView != null) {
- removeOverlay(mSubtitleView);
+ final boolean attachedToWindow = isAttachedToWindow();
+ if (mSubtitleWidget != null) {
+ if (attachedToWindow) {
+ mSubtitleWidget.onDetachedFromWindow();
+ }
+
+ mSubtitleWidget.setOnChangedListener(null);
}
- mSubtitleView = view;
- if (mSubtitleView != null) {
- addOverlay(mSubtitleView);
+
+ mSubtitleWidget = subtitleWidget;
+
+ if (subtitleWidget != null) {
+ if (mSubtitlesChangedListener == null) {
+ mSubtitlesChangedListener = new RenderingWidget.OnChangedListener() {
+ @Override
+ public void onChanged(RenderingWidget renderingWidget) {
+ invalidate();
+ }
+ };
+ }
+
+ setWillNotDraw(false);
+ subtitleWidget.setOnChangedListener(mSubtitlesChangedListener);
+
+ if (attachedToWindow) {
+ subtitleWidget.onAttachedToWindow();
+ requestLayout();
+ }
+ } else {
+ setWillNotDraw(true);
}
- }
- private View mSubtitleView;
+ invalidate();
+ }
}