Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b198dbaf authored by Alan Viverette's avatar Alan Viverette Committed by Android Git Automerger
Browse files

am 013634cc: Merge "Add WebVTT caption renderer" into klp-dev

* commit '013634cc':
  Add WebVTT caption renderer
parents f2a24a06 013634cc
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -29053,12 +29053,12 @@ package android.view.accessibility {
  }
  public class CaptioningManager {
    method public void addCaptioningStateChangeListener(android.view.accessibility.CaptioningManager.CaptioningChangeListener);
    method public void addCaptioningChangeListener(android.view.accessibility.CaptioningManager.CaptioningChangeListener);
    method public final float getFontScale();
    method public final java.util.Locale getLocale();
    method public android.view.accessibility.CaptioningManager.CaptionStyle getUserStyle();
    method public final boolean isEnabled();
    method public void removeCaptioningStateChangeListener(android.view.accessibility.CaptioningManager.CaptioningChangeListener);
    method public void removeCaptioningChangeListener(android.view.accessibility.CaptioningManager.CaptioningChangeListener);
  }
  public static final class CaptioningManager.CaptionStyle {
@@ -29072,7 +29072,7 @@ package android.view.accessibility {
    field public final int foregroundColor;
  }
  public abstract class CaptioningManager.CaptioningChangeListener {
  public static abstract class CaptioningManager.CaptioningChangeListener {
    ctor public CaptioningManager.CaptioningChangeListener();
    method public void onEnabledChanged(boolean);
    method public void onFontScaleChanged(float);
+4 −4
Original line number Diff line number Diff line
@@ -140,7 +140,7 @@ public class CaptioningManager {
     *
     * @param listener the listener to add
     */
    public void addCaptioningStateChangeListener(CaptioningChangeListener listener) {
    public void addCaptioningChangeListener(CaptioningChangeListener listener) {
        synchronized (mListeners) {
            if (mListeners.isEmpty()) {
                registerObserver(Secure.ACCESSIBILITY_CAPTIONING_ENABLED);
@@ -163,11 +163,11 @@ public class CaptioningManager {

    /**
     * Removes a listener previously added using
     * {@link #addCaptioningStateChangeListener}.
     * {@link #addCaptioningChangeListener}.
     *
     * @param listener the listener to remove
     */
    public void removeCaptioningStateChangeListener(CaptioningChangeListener listener) {
    public void removeCaptioningChangeListener(CaptioningChangeListener listener) {
        synchronized (mListeners) {
            mListeners.remove(listener);

@@ -366,7 +366,7 @@ public class CaptioningManager {
     * Listener for changes in captioning properties, including enabled state
     * and user style preferences.
     */
    public abstract class CaptioningChangeListener {
    public static abstract class CaptioningChangeListener {
        /**
         * Called when the captioning enabled state changes.
         *
+68 −94
Original line number Diff line number Diff line
@@ -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();
                }
            };
        }

        if (mOverlays.isEmpty()) {
            setWillNotDraw(false);
        }
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);

        mOverlays.add(overlay);
        overlay.addOnLayoutChangeListener(mOverlayLayoutListener);
        measureAndLayoutOverlays();
        if (mSubtitleWidget != null) {
            measureAndLayoutSubtitleWidget();
        }

    /**
     * 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);
        }

        mSubtitleWidget = subtitleWidget;

        if (subtitleWidget != null) {
            if (mSubtitlesChangedListener == null) {
                mSubtitlesChangedListener = new RenderingWidget.OnChangedListener() {
                    @Override
                    public void onChanged(RenderingWidget renderingWidget) {
                        invalidate();
                    }
                };
            }
        mSubtitleView = view;
        if (mSubtitleView != null) {
            addOverlay(mSubtitleView);

            setWillNotDraw(false);
            subtitleWidget.setOnChangedListener(mSubtitlesChangedListener);

            if (attachedToWindow) {
                subtitleWidget.onAttachedToWindow();
                requestLayout();
            }
        } else {
            setWillNotDraw(true);
        }

    private View mSubtitleView;
        invalidate();
    }
}
+4 −0
Original line number Diff line number Diff line
@@ -74,6 +74,10 @@ public class SubtitleView extends View {
    private float mSpacingAdd = 0;
    private int mInnerPaddingX = 0;

    public SubtitleView(Context context) {
        this(context, null);
    }

    public SubtitleView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
+11 −15
Original line number Diff line number Diff line
@@ -20,8 +20,7 @@ import java.util.Locale;
import java.util.Vector;

import android.content.Context;
import android.media.MediaPlayer.OnSubtitleDataListener;
import android.view.View;
import android.media.SubtitleTrack.RenderingWidget;
import android.view.accessibility.CaptioningManager;

/**
@@ -32,7 +31,6 @@ import android.view.accessibility.CaptioningManager;
 * @hide
 */
public class SubtitleController {
    private Context mContext;
    private MediaTimeProvider mTimeProvider;
    private Vector<Renderer> mRenderers;
    private Vector<SubtitleTrack> mTracks;
@@ -50,7 +48,6 @@ public class SubtitleController {
            Context context,
            MediaTimeProvider timeProvider,
            Listener listener) {
        mContext = context;
        mTimeProvider = timeProvider;
        mListener = listener;

@@ -79,11 +76,11 @@ public class SubtitleController {
        return mSelectedTrack;
    }

    private View getSubtitleView() {
    private RenderingWidget getRenderingWidget() {
        if (mSelectedTrack == null) {
            return null;
        }
        return mSelectedTrack.getView();
        return mSelectedTrack.getRenderingWidget();
    }

    /**
@@ -110,7 +107,7 @@ public class SubtitleController {
        }

        mSelectedTrack = track;
        mAnchor.setSubtitleView(getSubtitleView());
        mAnchor.setSubtitleWidget(getRenderingWidget());

        if (mSelectedTrack != null) {
            mSelectedTrack.setTimeProvider(mTimeProvider);
@@ -268,17 +265,16 @@ public class SubtitleController {
    }

    /**
     * Subtitle anchor, an object that is able to display a subtitle view,
     * Subtitle anchor, an object that is able to display a subtitle renderer,
     * e.g. a VideoView.
     */
    public interface Anchor {
        /**
         * Anchor should set the subtitle view to the supplied view,
         * or none, if the supplied view is null.
         *
         * @param view subtitle view, or null
         * Anchor should use the supplied subtitle rendering widget, or
         * none if it is null.
         * @hide
         */
        public void setSubtitleView(View view);
        public void setSubtitleWidget(RenderingWidget subtitleWidget);
    }

    private Anchor mAnchor;
@@ -290,11 +286,11 @@ public class SubtitleController {
        }

        if (mAnchor != null) {
            mAnchor.setSubtitleView(null);
            mAnchor.setSubtitleWidget(null);
        }
        mAnchor = anchor;
        if (mAnchor != null) {
            mAnchor.setSubtitleView(getSubtitleView());
            mAnchor.setSubtitleWidget(getRenderingWidget());
        }
    }

Loading