summaryrefslogtreecommitdiff
path: root/core/java/android/webkit/HTML5VideoView.java
diff options
context:
space:
mode:
authorTeng-Hui Zhu <ztenghui@google.com>2011-03-16 16:42:32 -0700
committerTeng-Hui Zhu <ztenghui@google.com>2011-03-16 22:06:28 -0700
commit10ab654943b386c0816a33dbd639c3b8d6260b01 (patch)
tree8bef832f1a682ed94ec6a0e048394f5146da8b23 /core/java/android/webkit/HTML5VideoView.java
parent3913c131c61288c5b4eedb063d9eb6b6204d2a1f (diff)
Support html5 video switching b/t full screen and inline mode
bug:2126902 Change-Id: I5c4b25358c76e35f0f51794d6d04fcc5098a0d70
Diffstat (limited to 'core/java/android/webkit/HTML5VideoView.java')
-rw-r--r--core/java/android/webkit/HTML5VideoView.java226
1 files changed, 143 insertions, 83 deletions
diff --git a/core/java/android/webkit/HTML5VideoView.java b/core/java/android/webkit/HTML5VideoView.java
index 2312160f5c66..ade7106fb093 100644
--- a/core/java/android/webkit/HTML5VideoView.java
+++ b/core/java/android/webkit/HTML5VideoView.java
@@ -4,72 +4,93 @@ package android.webkit;
import android.graphics.SurfaceTexture;
import android.media.MediaPlayer;
import android.util.Log;
+import android.view.SurfaceView;
import android.webkit.HTML5VideoViewProxy;
-import android.widget.MediaController;
-import android.opengl.GLES20;
import java.io.IOException;
+import java.util.HashMap;
import java.util.Map;
+import java.util.Timer;
+import java.util.TimerTask;
/**
* @hide This is only used by the browser
*/
public class HTML5VideoView implements MediaPlayer.OnPreparedListener{
- // Due to the fact that SurfaceTexture consume a lot of memory, we make it
- // as static. m_textureNames is the texture bound with this SurfaceTexture.
- private static SurfaceTexture mSurfaceTexture = null;
- private static int[] mTextureNames;
- // Only when the video is prepared, we render using SurfaceTexture.
- // This in fact is used to avoid showing the obsolete content when
- // switching videos.
- private static boolean mReadyToUseSurfTex = false;
+ protected static final String LOGTAG = "HTML5VideoView";
+
+ protected static final String COOKIE = "Cookie";
+ protected static final String HIDE_URL_LOGS = "x-hide-urls-from-log";
// For handling the seekTo before prepared, we need to know whether or not
// the video is prepared. Therefore, we differentiate the state between
// prepared and not prepared.
// When the video is not prepared, we will have to save the seekTo time,
// and use it when prepared to play.
- private static final int STATE_NOTPREPARED = 0;
- private static final int STATE_PREPARED = 1;
+ protected static final int STATE_NOTPREPARED = 0;
+ protected static final int STATE_PREPARED = 1;
- // We only need state for handling seekTo
- private int mCurrentState;
+ protected int mCurrentState;
- // Basically for calling back the OnPrepared in the proxy
- private HTML5VideoViewProxy mProxy;
+ protected HTML5VideoViewProxy mProxy;
// Save the seek time when not prepared. This can happen when switching
// video besides initial load.
- private int mSaveSeekTime;
+ protected int mSaveSeekTime;
// This is used to find the VideoLayer on the native side.
- private int mVideoLayerId;
+ 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().
- private MediaPlayer mPlayer;
+ // Switching between inline and full screen will also create a new instance.
+ protected MediaPlayer mPlayer;
+
+ // This will be set up every time we create the Video View object.
+ // Set to true only when switching into full screen while playing
+ protected boolean mAutostart;
+
+ // We need to save such info.
+ protected String mUri;
+ protected Map<String, String> mHeaders;
- private static HTML5VideoView mInstance = new HTML5VideoView();
+ // The timer for timeupate events.
+ // See http://www.whatwg.org/specs/web-apps/current-work/#event-media-timeupdate
+ protected static Timer mTimer;
- // Video control FUNCTIONS:
+ // The spec says the timer should fire every 250 ms or less.
+ private static final int TIMEUPDATE_PERIOD = 250; // ms
+
+ // common Video control FUNCTIONS:
public void start() {
if (mCurrentState == STATE_PREPARED) {
mPlayer.start();
- mReadyToUseSurfTex = true;
}
}
public void pause() {
- mPlayer.pause();
+ if (mCurrentState == STATE_PREPARED && mPlayer.isPlaying()) {
+ mPlayer.pause();
+ }
+ if (mTimer != null) {
+ mTimer.purge();
+ }
}
public int getDuration() {
- return mPlayer.getDuration();
+ if (mCurrentState == STATE_PREPARED) {
+ return mPlayer.getDuration();
+ } else {
+ return -1;
+ }
}
public int getCurrentPosition() {
- return mPlayer.getCurrentPosition();
+ if (mCurrentState == STATE_PREPARED) {
+ return mPlayer.getCurrentPosition();
+ }
+ return 0;
}
public void seekTo(int pos) {
@@ -88,54 +109,51 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener{
}
public void stopPlayback() {
- mPlayer.stop();
+ if (mCurrentState == STATE_PREPARED) {
+ mPlayer.stop();
+ }
}
- private void reset(int videoLayerId) {
+ public boolean getAutostart() {
+ return mAutostart;
+ }
+
+ // Every time we start a new Video, we create a VideoView and a MediaPlayer
+ public void init(int videoLayerId, int position, boolean autoStart) {
mPlayer = new MediaPlayer();
mCurrentState = STATE_NOTPREPARED;
mProxy = null;
mVideoLayerId = videoLayerId;
- mReadyToUseSurfTex = false;
+ mSaveSeekTime = position;
+ mAutostart = autoStart;
}
- public static HTML5VideoView getInstance(int videoLayerId) {
- // Every time we switch between the videos, a new MediaPlayer will be
- // created. Make sure we call the m_player.release() when it is done.
- mInstance.reset(videoLayerId);
- return mInstance;
+ protected HTML5VideoView() {
}
- private HTML5VideoView() {
- // This is a singleton across WebViews (i.e. Tabs).
- // HTML5VideoViewProxy will reset the internal state every time a new
- // video start.
- }
+ protected static Map<String, String> generateHeaders(String url,
+ HTML5VideoViewProxy proxy) {
+ boolean isPrivate = proxy.getWebView().isPrivateBrowsingEnabled();
+ String cookieValue = CookieManager.getInstance().getCookie(url, isPrivate);
+ Map<String, String> headers = new HashMap<String, String>();
+ if (cookieValue != null) {
+ headers.put(COOKIE, cookieValue);
+ }
+ if (isPrivate) {
+ headers.put(HIDE_URL_LOGS, "true");
+ }
- public void setMediaController(MediaController m) {
- this.setMediaController(m);
+ return headers;
}
- public void setVideoURI(String uri, Map<String, String> headers) {
+ public void setVideoURI(String uri, HTML5VideoViewProxy proxy) {
// When switching players, surface texture will be reused.
- mPlayer.setTexture(getSurfaceTextureInstance());
+ mUri = uri;
+ mHeaders = generateHeaders(uri, proxy);
- // When there is exception, we could just bail out silently.
- // No Video will be played though. Write the stack for debug
- try {
- mPlayer.setDataSource(uri, headers);
- mPlayer.prepareAsync();
- } catch (IllegalArgumentException e) {
- e.printStackTrace();
- } catch (IllegalStateException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
+ mTimer = new Timer();
}
- // TODO [FULL SCREEN SUPPORT]
-
// Listeners setup FUNCTIONS:
public void setOnCompletionListener(HTML5VideoViewProxy proxy) {
mPlayer.setOnCompletionListener(proxy);
@@ -150,43 +168,47 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener{
mPlayer.setOnPreparedListener(this);
}
- // Inline Video specific FUNCTIONS:
+ // Normally called immediately after setVideoURI. But for full screen,
+ // this should be after surface holder created
+ public void prepareDataAndDisplayMode(HTML5VideoViewProxy proxy) {
+ // SurfaceTexture will be created lazily here for inline mode
+ decideDisplayMode();
- public SurfaceTexture getSurfaceTexture() {
- return mSurfaceTexture;
- }
+ setOnCompletionListener(proxy);
+ setOnPreparedListener(proxy);
+ setOnErrorListener(proxy);
- public void deleteSurfaceTexture() {
- mSurfaceTexture = null;
- return;
- }
-
- // SurfaceTexture is a singleton here , too
- private SurfaceTexture getSurfaceTextureInstance() {
- // Create the surface texture.
- if (mSurfaceTexture == null)
- {
- mTextureNames = new int[1];
- GLES20.glGenTextures(1, mTextureNames, 0);
- mSurfaceTexture = new SurfaceTexture(mTextureNames[0]);
+ // When there is exception, we could just bail out silently.
+ // No Video will be played though. Write the stack for debug
+ try {
+ mPlayer.setDataSource(mUri, mHeaders);
+ mPlayer.prepareAsync();
+ } catch (IllegalArgumentException e) {
+ e.printStackTrace();
+ } catch (IllegalStateException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
}
- return mSurfaceTexture;
}
- public int getTextureName() {
- return mTextureNames[0];
- }
+ // Common code
public int getVideoLayerId() {
return mVideoLayerId;
}
- public boolean getReadyToUseSurfTex() {
- return mReadyToUseSurfTex;
- }
+ private static final class TimeupdateTask extends TimerTask {
+ private HTML5VideoViewProxy mProxy;
- public void setFrameAvailableListener(SurfaceTexture.OnFrameAvailableListener l) {
- mSurfaceTexture.setOnFrameAvailableListener(l);
+ public TimeupdateTask(HTML5VideoViewProxy proxy) {
+ mProxy = proxy;
+ }
+
+ @Override
+ public void run() {
+ mProxy.onTimeupdate();
+ }
}
@Override
@@ -195,6 +217,9 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener{
seekTo(mSaveSeekTime);
if (mProxy != null)
mProxy.onPrepared(mp);
+
+ mTimer.schedule(new TimeupdateTask(mProxy), TIMEUPDATE_PERIOD, TIMEUPDATE_PERIOD);
+
}
// Pause the play and update the play/pause button
@@ -205,7 +230,42 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener{
proxy.dispatchOnPaused();
}
}
- mReadyToUseSurfTex = false;
+ }
+
+ // Below are functions that are different implementation on inline and full-
+ // screen mode. Some are specific to one type, but currently are called
+ // directly from the proxy.
+ public void enterFullScreenVideoState(int layerId,
+ HTML5VideoViewProxy proxy, WebView webView) {
+ }
+
+ public boolean isFullScreenMode() {
+ return false;
+ }
+
+ public SurfaceView getSurfaceView() {
+ return null;
+ }
+
+ public void decideDisplayMode() {
+ }
+
+ public void prepareForFullScreen() {
+ }
+
+ public boolean getReadyToUseSurfTex() {
+ return false;
+ }
+
+ public SurfaceTexture getSurfaceTexture() {
+ return null;
+ }
+
+ public void deleteSurfaceTexture() {
+ }
+
+ public int getTextureName() {
+ return 0;
}
}