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

Commit c2b06d5a authored by Teng-Hui Zhu's avatar Teng-Hui Zhu
Browse files

Avoid inline->fullscreen reload for html5 video.

Now when a user start inline play and then switch to full screen, there is no
reload any more.
Basically, we change mediaplayer as a static member, and detect possible
situation to skip the prepare work.

bug:5710646

Change-Id: Ida34cf2e919a6cc8e0d52cd1175d51b5f5d527f7
parent f4c77df0
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -104,7 +104,9 @@ public class HTML5VideoFullScreen extends HTML5VideoView
            // After we return from this we can't use the surface any more.
            // The current Video View will be destroy when we play a new video.
            pauseAndDispatch(mProxy);
            // TODO: handle full screen->inline mode transition without a reload.
            mPlayer.release();
            mPlayer = null;
            mSurfaceHolder = null;
            if (mMediaController != null) {
                mMediaController.hide();
@@ -128,12 +130,12 @@ public class HTML5VideoFullScreen extends HTML5VideoView
        return mVideoSurfaceView;
    }

    HTML5VideoFullScreen(Context context, int videoLayerId, int position) {
    HTML5VideoFullScreen(Context context, int videoLayerId, int position, boolean skipPrepare) {
        mVideoSurfaceView = new VideoSurfaceView(context);
        mFullScreenMode = FULLSCREEN_OFF;
        mVideoWidth = 0;
        mVideoHeight = 0;
        init(videoLayerId, position);
        init(videoLayerId, position, skipPrepare);
    }

    private void setMediaController(MediaController m) {
@@ -156,8 +158,6 @@ public class HTML5VideoFullScreen extends HTML5VideoView
    }

    private void prepareForFullScreen() {
        // So in full screen, we reset the MediaPlayer
        mPlayer.reset();
        MediaController mc = new FullScreenMediaController(mProxy.getContext(), mLayout);
        mc.setSystemUiVisibility(mLayout.getSystemUiVisibility());
        setMediaController(mc);
@@ -243,7 +243,7 @@ public class HTML5VideoFullScreen extends HTML5VideoView

                // Don't show the controller after exiting the full screen.
                mMediaController = null;
                mCurrentState = STATE_RELEASED;
                mCurrentState = STATE_RESETTED;
            }
        };

+6 −8
Original line number Diff line number Diff line
@@ -21,7 +21,7 @@ public class HTML5VideoInline extends HTML5VideoView{
    // associated with the surface texture can be used for showing the screen
    // shot when paused, so they are not singleton.
    private static SurfaceTexture mSurfaceTexture = null;
    private int[] mTextureNames;
    private static int[] mTextureNames = null;
    // Every time when the VideoLayer Id change, we need to recreate the
    // SurfaceTexture in order to delete the old video's decoder memory.
    private static int mVideoLayerUsingSurfaceTexture = -1;
@@ -35,8 +35,7 @@ public class HTML5VideoInline extends HTML5VideoView{
    }

    HTML5VideoInline(int videoLayerId, int position) {
        init(videoLayerId, position);
        mTextureNames = null;
        init(videoLayerId, position, false);
    }

    @Override
@@ -69,15 +68,14 @@ public class HTML5VideoInline extends HTML5VideoView{

    // Inline Video specific FUNCTIONS:

    @Override
    public SurfaceTexture getSurfaceTexture(int videoLayerId) {
    public static SurfaceTexture getSurfaceTexture(int videoLayerId) {
        // Create the surface texture.
        if (videoLayerId != mVideoLayerUsingSurfaceTexture
            || mSurfaceTexture == null
            || mTextureNames == null) {
            if (mTextureNames != null) {
                GLES20.glDeleteTextures(1, mTextureNames, 0);
            }
            // The GL texture will store in the VideoLayerManager at native side.
            // They will be clean up when requested.
            // The reason we recreated GL texture name is for screen shot support.
            mTextureNames = new int[1];
            GLES20.glGenTextures(1, mTextureNames, 0);
            mSurfaceTexture = new SurfaceTexture(mTextureNames[0]);
+49 −34
Original line number Diff line number Diff line
@@ -31,11 +31,10 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener {
    // NOTE: these values are in sync with VideoLayerAndroid.h in webkit side.
    // Please keep them in sync when changed.
    static final int STATE_INITIALIZED        = 0;
    static final int STATE_NOTPREPARED        = 1;
    static final int STATE_PREPARING          = 1;
    static final int STATE_PREPARED           = 2;
    static final int STATE_PLAYING            = 3;
    static final int STATE_RELEASED           = 4;
    protected int mCurrentState;
    static final int STATE_RESETTED           = 4;

    protected HTML5VideoViewProxy mProxy;

@@ -46,11 +45,11 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener {
    // This is used to find the VideoLayer on the native side.
    protected int mVideoLayerId;

    // Every video will have one MediaPlayer. Given the fact we only have one
    // SurfaceTexture, there is only one MediaPlayer in action. Every time we
    // switch videos, a new instance of MediaPlayer will be created in reset().
    // Switching between inline and full screen will also create a new instance.
    protected MediaPlayer mPlayer;
    // Given the fact we only have one SurfaceTexture, we cannot support multiple
    // player at the same time. We may recreate a new one and abandon the old
    // one at transition time.
    protected static MediaPlayer mPlayer = null;
    protected static int mCurrentState = -1;

    // We need to save such info.
    protected Uri mUri;
@@ -60,10 +59,12 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener {
    // See http://www.whatwg.org/specs/web-apps/current-work/#event-media-timeupdate
    protected static Timer mTimer;

    protected boolean mPauseDuringPreparing;

    // The spec says the timer should fire every 250 ms or less.
    private static final int TIMEUPDATE_PERIOD = 250;  // ms
    private boolean mSkipPrepare = false;

    protected boolean mPauseDuringPreparing;
    // common Video control FUNCTIONS:
    public void start() {
        if (mCurrentState == STATE_PREPARED) {
@@ -83,7 +84,7 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener {
    public void pause() {
        if (isPlaying()) {
            mPlayer.pause();
        } else if (mCurrentState == STATE_NOTPREPARED) {
        } else if (mCurrentState == STATE_PREPARING) {
            mPauseDuringPreparing = true;
        }
        // Delete the Timer to stop it since there is no stop call.
@@ -124,11 +125,11 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener {
        }
    }

    public void release() {
        if (mCurrentState != STATE_RELEASED) {
            mPlayer.release();
    public void reset() {
        if (mCurrentState != STATE_RESETTED) {
            mPlayer.reset();
        }
        mCurrentState = STATE_RELEASED;
        mCurrentState = STATE_RESETTED;
    }

    public void stopPlayback() {
@@ -142,9 +143,16 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener {
    }

    // Every time we start a new Video, we create a VideoView and a MediaPlayer
    public void init(int videoLayerId, int position) {
    public void init(int videoLayerId, int position, boolean skipPrepare) {
        if (mPlayer == null) {
            mPlayer = new MediaPlayer();
            mCurrentState = STATE_INITIALIZED;
        }
        mSkipPrepare = skipPrepare;
        // If we want to skip the prepare, then we keep the state.
        if (!mSkipPrepare) {
            mCurrentState = STATE_INITIALIZED;
        }
        mProxy = null;
        mVideoLayerId = videoLayerId;
        mSaveSeekTime = position;
@@ -195,7 +203,9 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener {
    }

    public void prepareDataCommon(HTML5VideoViewProxy proxy) {
        if (!mSkipPrepare) {
            try {
                mPlayer.reset();
                mPlayer.setDataSource(proxy.getContext(), mUri, mHeaders);
                mPlayer.prepareAsync();
            } catch (IllegalArgumentException e) {
@@ -205,7 +215,16 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener {
            } catch (IOException e) {
                e.printStackTrace();
            }
        mCurrentState = STATE_NOTPREPARED;
            mCurrentState = STATE_PREPARING;
        } else {
            // If we skip prepare and the onPrepared happened in inline mode, we
            // don't need to call prepare again, we just need to call onPrepared
            // to refresh the state here.
            if (mCurrentState >= STATE_PREPARED) {
                onPrepared(mPlayer);
            }
            mSkipPrepare = false;
        }
    }

    public void reprepareData(HTML5VideoViewProxy proxy) {
@@ -294,10 +313,6 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener {
        return false;
    }

    public SurfaceTexture getSurfaceTexture(int videoLayerId) {
        return null;
    }

    public void deleteSurfaceTexture() {
    }

@@ -332,14 +347,14 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener {
        return false;
    }

    private boolean m_startWhenPrepared = false;
    private boolean mStartWhenPrepared = false;

    public void setStartWhenPrepared(boolean willPlay) {
        m_startWhenPrepared  = willPlay;
        mStartWhenPrepared  = willPlay;
    }

    public boolean getStartWhenPrepared() {
        return m_startWhenPrepared;
        return mStartWhenPrepared;
    }

}
+14 −8
Original line number Diff line number Diff line
@@ -112,13 +112,14 @@ class HTML5VideoViewProxy extends Handler
                mBaseLayer = layer;

                int currentVideoLayerId = mHTML5VideoView.getVideoLayerId();
                SurfaceTexture surfTexture = mHTML5VideoView.getSurfaceTexture(currentVideoLayerId);
                SurfaceTexture surfTexture =
                        HTML5VideoInline.getSurfaceTexture(currentVideoLayerId);
                int textureName = mHTML5VideoView.getTextureName();

                if (layer != 0 && surfTexture != null && currentVideoLayerId != -1) {
                    int playerState = mHTML5VideoView.getCurrentState();
                    if (mHTML5VideoView.getPlayerBuffering())
                        playerState = HTML5VideoView.STATE_NOTPREPARED;
                        playerState = HTML5VideoView.STATE_PREPARING;
                    boolean foundInTree = nativeSendSurfaceTexture(surfTexture,
                            layer, currentVideoLayerId, textureName,
                            playerState);
@@ -145,6 +146,7 @@ class HTML5VideoViewProxy extends Handler
                HTML5VideoViewProxy proxy, WebViewClassic webView) {
                // Save the inline video info and inherit it in the full screen
                int savePosition = 0;
                boolean canSkipPrepare = false;
                if (mHTML5VideoView != null) {
                    // We don't allow enter full screen mode while the previous
                    // full screen video hasn't finished yet.
@@ -156,15 +158,20 @@ class HTML5VideoViewProxy extends Handler
                    // save the current position.
                    if (layerId == mHTML5VideoView.getVideoLayerId()) {
                        savePosition = mHTML5VideoView.getCurrentPosition();
                        int playerState = mHTML5VideoView.getCurrentState();
                        canSkipPrepare = (playerState == HTML5VideoView.STATE_PREPARING
                                || playerState == HTML5VideoView.STATE_PREPARED
                                || playerState == HTML5VideoView.STATE_PLAYING)
                                && !mHTML5VideoView.isFullScreenMode();
                    }
                    if (!canSkipPrepare) {
                        mHTML5VideoView.reset();
                    }
                    mHTML5VideoView.release();
                }
                mHTML5VideoView = new HTML5VideoFullScreen(proxy.getContext(),
                        layerId, savePosition);
                        layerId, savePosition, canSkipPrepare);
                mCurrentProxy = proxy;

                mHTML5VideoView.setVideoURI(url, mCurrentProxy);

                mHTML5VideoView.enterFullScreenVideoState(layerId, proxy, webView);
        }

@@ -217,8 +224,7 @@ class HTML5VideoViewProxy extends Handler
                    if (!backFromFullScreenMode) {
                        mHTML5VideoView.pauseAndDispatch(mCurrentProxy);
                    }
                    // release the media player to avoid finalize error
                    mHTML5VideoView.release();
                    mHTML5VideoView.reset();
                }
                mCurrentProxy = proxy;
                mHTML5VideoView = new HTML5VideoInline(videoLayerId, time);