diff options
Diffstat (limited to 'core/java/android/webkit/HTML5VideoView.java')
| -rw-r--r-- | core/java/android/webkit/HTML5VideoView.java | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/core/java/android/webkit/HTML5VideoView.java b/core/java/android/webkit/HTML5VideoView.java new file mode 100644 index 000000000000..2312160f5c66 --- /dev/null +++ b/core/java/android/webkit/HTML5VideoView.java @@ -0,0 +1,211 @@ + +package android.webkit; + +import android.graphics.SurfaceTexture; +import android.media.MediaPlayer; +import android.util.Log; +import android.webkit.HTML5VideoViewProxy; +import android.widget.MediaController; +import android.opengl.GLES20; +import java.io.IOException; +import java.util.Map; + +/** + * @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; + + // 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; + + // We only need state for handling seekTo + private int mCurrentState; + + // Basically for calling back the OnPrepared in the proxy + private HTML5VideoViewProxy mProxy; + + // Save the seek time when not prepared. This can happen when switching + // video besides initial load. + private int mSaveSeekTime; + + // This is used to find the VideoLayer on the native side. + private 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; + + private static HTML5VideoView mInstance = new HTML5VideoView(); + + // Video control FUNCTIONS: + public void start() { + if (mCurrentState == STATE_PREPARED) { + mPlayer.start(); + mReadyToUseSurfTex = true; + } + } + + public void pause() { + mPlayer.pause(); + } + + public int getDuration() { + return mPlayer.getDuration(); + } + + public int getCurrentPosition() { + return mPlayer.getCurrentPosition(); + } + + public void seekTo(int pos) { + if (mCurrentState == STATE_PREPARED) + mPlayer.seekTo(pos); + else + mSaveSeekTime = pos; + } + + public boolean isPlaying() { + return mPlayer.isPlaying(); + } + + public void release() { + mPlayer.release(); + } + + public void stopPlayback() { + mPlayer.stop(); + } + + private void reset(int videoLayerId) { + mPlayer = new MediaPlayer(); + mCurrentState = STATE_NOTPREPARED; + mProxy = null; + mVideoLayerId = videoLayerId; + mReadyToUseSurfTex = false; + } + + 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; + } + + private HTML5VideoView() { + // This is a singleton across WebViews (i.e. Tabs). + // HTML5VideoViewProxy will reset the internal state every time a new + // video start. + } + + public void setMediaController(MediaController m) { + this.setMediaController(m); + } + + public void setVideoURI(String uri, Map<String, String> headers) { + // When switching players, surface texture will be reused. + mPlayer.setTexture(getSurfaceTextureInstance()); + + // 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(); + } + } + + // TODO [FULL SCREEN SUPPORT] + + // Listeners setup FUNCTIONS: + public void setOnCompletionListener(HTML5VideoViewProxy proxy) { + mPlayer.setOnCompletionListener(proxy); + } + + public void setOnErrorListener(HTML5VideoViewProxy proxy) { + mPlayer.setOnErrorListener(proxy); + } + + public void setOnPreparedListener(HTML5VideoViewProxy proxy) { + mProxy = proxy; + mPlayer.setOnPreparedListener(this); + } + + // Inline Video specific FUNCTIONS: + + public SurfaceTexture getSurfaceTexture() { + return mSurfaceTexture; + } + + 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]); + } + return mSurfaceTexture; + } + + public int getTextureName() { + return mTextureNames[0]; + } + + public int getVideoLayerId() { + return mVideoLayerId; + } + + public boolean getReadyToUseSurfTex() { + return mReadyToUseSurfTex; + } + + public void setFrameAvailableListener(SurfaceTexture.OnFrameAvailableListener l) { + mSurfaceTexture.setOnFrameAvailableListener(l); + } + + @Override + public void onPrepared(MediaPlayer mp) { + mCurrentState = STATE_PREPARED; + seekTo(mSaveSeekTime); + if (mProxy != null) + mProxy.onPrepared(mp); + } + + // Pause the play and update the play/pause button + public void pauseAndDispatch(HTML5VideoViewProxy proxy) { + if (isPlaying()) { + pause(); + if (proxy != null) { + proxy.dispatchOnPaused(); + } + } + mReadyToUseSurfTex = false; + } + +} |
