summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTeng-Hui Zhu <ztenghui@google.com>2011-12-12 14:39:04 -0800
committerTeng-Hui Zhu <ztenghui@google.com>2011-12-13 11:12:40 -0800
commitd649883ce629c0de432e075254b517a50685792e (patch)
tree4fcce956db39661a16d5e002715b8ef3ad772feb
parentd07292c75082db457ad498747c0b05d38a14e8d7 (diff)
downloadexternal_webkit-d649883ce629c0de432e075254b517a50685792e.zip
external_webkit-d649883ce629c0de432e075254b517a50685792e.tar.gz
external_webkit-d649883ce629c0de432e075254b517a50685792e.tar.bz2
Tap to play/pause for html5 video with UI
bug:4232704 Change-Id: Ice99bc0fa19de93627fe8ffb91085838fa682315
-rw-r--r--Source/WebCore/html/HTMLMediaElement.cpp6
-rw-r--r--Source/WebCore/platform/android/RenderThemeAndroid.cpp8
-rw-r--r--Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp132
-rw-r--r--Source/WebCore/platform/graphics/android/VideoLayerAndroid.h7
-rw-r--r--Source/WebCore/platform/graphics/android/VideoLayerManager.cpp36
-rw-r--r--Source/WebCore/platform/graphics/android/VideoLayerManager.h15
-rw-r--r--Source/WebKit/android/RenderSkinMediaButton.cpp8
-rw-r--r--Source/WebKit/android/RenderSkinMediaButton.h2
8 files changed, 156 insertions, 58 deletions
diff --git a/Source/WebCore/html/HTMLMediaElement.cpp b/Source/WebCore/html/HTMLMediaElement.cpp
index 023e8d2..6407f9f 100644
--- a/Source/WebCore/html/HTMLMediaElement.cpp
+++ b/Source/WebCore/html/HTMLMediaElement.cpp
@@ -2402,6 +2402,12 @@ void HTMLMediaElement::defaultEventHandler(Event* event)
}
#endif
+#if PLATFORM(ANDROID)
+ // It is really hard to hit the play/pause button on mobile devices.
+ // This allows user to click the video area to toggle play/pause state.
+ if (event->type() == eventNames().clickEvent)
+ togglePlayState();
+#endif
HTMLElement::defaultEventHandler(event);
#endif
}
diff --git a/Source/WebCore/platform/android/RenderThemeAndroid.cpp b/Source/WebCore/platform/android/RenderThemeAndroid.cpp
index 93c99a4..843068a 100644
--- a/Source/WebCore/platform/android/RenderThemeAndroid.cpp
+++ b/Source/WebCore/platform/android/RenderThemeAndroid.cpp
@@ -336,7 +336,9 @@ bool RenderThemeAndroid::paintMediaControlsBackground(RenderObject* o, const Pai
bool translucent = false;
if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
translucent = true;
- RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::BACKGROUND_SLIDER, translucent);
+ RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect,
+ RenderSkinMediaButton::BACKGROUND_SLIDER,
+ translucent, 0, false);
return false;
}
@@ -355,7 +357,9 @@ bool RenderThemeAndroid::paintMediaSliderThumb(RenderObject* o, const PaintInfo&
bool translucent = false;
if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
translucent = true;
- RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::SLIDER_THUMB, translucent);
+ RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect,
+ RenderSkinMediaButton::SLIDER_THUMB,
+ translucent, 0, false);
return false;
}
diff --git a/Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp
index 482d711..3ec28e2 100644
--- a/Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp
@@ -53,6 +53,8 @@ GLuint VideoLayerAndroid::m_spinnerOuterTextureId = 0;
GLuint VideoLayerAndroid::m_spinnerInnerTextureId = 0;
GLuint VideoLayerAndroid::m_posterTextureId = 0;
GLuint VideoLayerAndroid::m_backgroundTextureId = 0;
+GLuint VideoLayerAndroid::m_playTextureId = 0;
+GLuint VideoLayerAndroid::m_pauseTextureId = 0;
bool VideoLayerAndroid::m_createdTexture = false;
double VideoLayerAndroid::m_rotateDegree = 0;
@@ -102,6 +104,16 @@ GLuint VideoLayerAndroid::createPosterTexture()
return createTextureFromImage(RenderSkinMediaButton::VIDEO);
}
+GLuint VideoLayerAndroid::createPlayTexture()
+{
+ return createTextureFromImage(RenderSkinMediaButton::PLAY);
+}
+
+GLuint VideoLayerAndroid::createPauseTexture()
+{
+ return createTextureFromImage(RenderSkinMediaButton::PAUSE);
+}
+
GLuint VideoLayerAndroid::createTextureFromImage(int buttonType)
{
SkRect rect = SkRect(buttonRect);
@@ -112,7 +124,8 @@ GLuint VideoLayerAndroid::createTextureFromImage(int buttonType)
SkCanvas canvas(bitmap);
canvas.drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode);
- RenderSkinMediaButton::Draw(&canvas, buttonRect, buttonType, true);
+ RenderSkinMediaButton::Draw(&canvas, buttonRect, buttonType, true, 0,
+ false);
GLuint texture;
glGenTextures(1, &texture);
@@ -142,6 +155,31 @@ GLuint VideoLayerAndroid::createBackgroundTexture()
return texture;
}
+void VideoLayerAndroid::showPreparingAnimation(const SkRect& rect,
+ const SkRect innerRect)
+{
+ ShaderProgram* shader = TilesManager::instance()->shader();
+ shader->drawLayerQuad(m_drawTransform, rect, m_backgroundTextureId, 1, true);
+
+ TransformationMatrix addReverseRotation;
+ TransformationMatrix addRotation = m_drawTransform;
+ addRotation.translate(innerRect.fLeft, innerRect.fTop);
+ addRotation.translate(IMAGESIZE / 2, IMAGESIZE / 2);
+ addReverseRotation = addRotation;
+ addRotation.rotate(m_rotateDegree);
+ addRotation.translate(-IMAGESIZE / 2, -IMAGESIZE / 2);
+
+ SkRect size = SkRect::MakeWH(innerRect.width(), innerRect.height());
+ shader->drawLayerQuad(addRotation, size, m_spinnerOuterTextureId, 1, true);
+
+ addReverseRotation.rotate(-m_rotateDegree);
+ addReverseRotation.translate(-IMAGESIZE / 2, -IMAGESIZE / 2);
+
+ shader->drawLayerQuad(addReverseRotation, size, m_spinnerInnerTextureId, 1, true);
+
+ m_rotateDegree += ROTATESTEP;
+}
+
bool VideoLayerAndroid::drawGL()
{
// Lazily allocated the textures.
@@ -150,6 +188,8 @@ bool VideoLayerAndroid::drawGL()
m_spinnerOuterTextureId = createSpinnerOuterTexture();
m_spinnerInnerTextureId = createSpinnerInnerTexture();
m_posterTextureId = createPosterTexture();
+ m_playTextureId = createPlayTexture();
+ m_pauseTextureId = createPauseTexture();
m_createdTexture = true;
}
@@ -162,69 +202,63 @@ bool VideoLayerAndroid::drawGL()
innerRect.offset((rect.width() - IMAGESIZE) / 2 , (rect.height() - IMAGESIZE) / 2);
+ ShaderProgram* shader = TilesManager::instance()->shader();
+ VideoLayerManager* manager = TilesManager::instance()->videoLayerManager();
+
+ // When we are drawing the animation of the play/pause button in the
+ // middle of the video, we need to ask for redraw.
+ bool needRedraw = false;
+
// Draw the poster image, the progressing image or the Video depending
// on the player's state.
if (m_playerState == PREPARING) {
// Show the progressing animation, with two rotating circles
- TilesManager::instance()->shader()->drawLayerQuad(m_drawTransform, rect,
- m_backgroundTextureId,
- 1, true);
-
- TransformationMatrix addReverseRotation;
- TransformationMatrix addRotation = m_drawTransform;
- addRotation.translate(innerRect.fLeft, innerRect.fTop);
- addRotation.translate(IMAGESIZE / 2, IMAGESIZE / 2);
- addReverseRotation = addRotation;
- addRotation.rotate(m_rotateDegree);
- addRotation.translate(-IMAGESIZE / 2, -IMAGESIZE / 2);
-
- SkRect size = SkRect::MakeWH(innerRect.width(), innerRect.height());
- TilesManager::instance()->shader()->drawLayerQuad(addRotation, size,
- m_spinnerOuterTextureId,
- 1, true);
-
- addReverseRotation.rotate(-m_rotateDegree);
- addReverseRotation.translate(-IMAGESIZE / 2, -IMAGESIZE / 2);
-
- TilesManager::instance()->shader()->drawLayerQuad(addReverseRotation, size,
- m_spinnerInnerTextureId,
- 1, true);
-
- m_rotateDegree += ROTATESTEP;
-
+ showPreparingAnimation(rect, innerRect);
} else if (m_playerState == PLAYING && m_surfaceTexture.get()) {
// Show the real video.
m_surfaceTexture->updateTexImage();
m_surfaceTexture->getTransformMatrix(surfaceMatrix);
- GLuint textureId =
- TilesManager::instance()->videoLayerManager()->getTextureId(uniqueId());
- TilesManager::instance()->shader()->drawVideoLayerQuad(m_drawTransform,
- surfaceMatrix,
- rect, textureId);
- TilesManager::instance()->videoLayerManager()->updateMatrix(uniqueId(),
- surfaceMatrix);
+ GLuint textureId = manager->getTextureId(uniqueId());
+ shader->drawVideoLayerQuad(m_drawTransform, surfaceMatrix,
+ rect, textureId);
+ manager->updateMatrix(uniqueId(), surfaceMatrix);
+
+ // Use the scale to control the fading the sizing during animation
+ double scale = manager->drawIcon(uniqueId(), PlayIcon);
+ if (scale != 0) {
+ innerRect.inset(IMAGESIZE / 4 * scale, IMAGESIZE / 4 * scale);
+ shader->drawLayerQuad(m_drawTransform, innerRect,
+ m_playTextureId, scale, true);
+ needRedraw = true;
+ }
+
} else {
- GLuint textureId =
- TilesManager::instance()->videoLayerManager()->getTextureId(uniqueId());
- GLfloat* matrix =
- TilesManager::instance()->videoLayerManager()->getMatrix(uniqueId());
+ GLuint textureId = manager->getTextureId(uniqueId());
+ GLfloat* matrix = manager->getMatrix(uniqueId());
if (textureId && matrix) {
// Show the screen shot for each video.
- TilesManager::instance()->shader()->drawVideoLayerQuad(m_drawTransform,
- matrix,
- rect, textureId);
+ shader->drawVideoLayerQuad(m_drawTransform, matrix,
+ rect, textureId);
} else {
// Show the static poster b/c there is no screen shot available.
- TilesManager::instance()->shader()->drawLayerQuad(m_drawTransform, rect,
- m_backgroundTextureId,
- 1, true);
- TilesManager::instance()->shader()->drawLayerQuad(m_drawTransform, innerRect,
- m_posterTextureId,
- 1, true);
+ shader->drawLayerQuad(m_drawTransform, rect, m_backgroundTextureId,
+ 1, true);
+ shader->drawLayerQuad(m_drawTransform, innerRect, m_posterTextureId,
+ 1, true);
}
- }
- return drawChildrenGL();
+ // Use the scale to control the fading and the sizing during animation.
+ double scale = manager->drawIcon(uniqueId(), PauseIcon);
+ if (scale != 0) {
+ innerRect.inset(IMAGESIZE / 4 * scale, IMAGESIZE / 4 * scale);
+ shader->drawLayerQuad(m_drawTransform, innerRect,
+ m_pauseTextureId, scale, true);
+ needRedraw = true;
+ }
+
+ }
+ // Don't short circuit here since we still want to draw the children.
+ return drawChildrenGL() || needRedraw;
}
}
diff --git a/Source/WebCore/platform/graphics/android/VideoLayerAndroid.h b/Source/WebCore/platform/graphics/android/VideoLayerAndroid.h
index 8a064bb..cdb37f3 100644
--- a/Source/WebCore/platform/graphics/android/VideoLayerAndroid.h
+++ b/Source/WebCore/platform/graphics/android/VideoLayerAndroid.h
@@ -30,6 +30,7 @@
#include "GLUtils.h"
#include "LayerAndroid.h"
+#include "ShaderProgram.h"
#include <jni.h>
namespace android {
@@ -62,10 +63,14 @@ public:
GLuint createSpinnerOuterTexture();
GLuint createSpinnerInnerTexture();
GLuint createPosterTexture();
+ GLuint createPlayTexture();
+ GLuint createPauseTexture();
private:
GLuint createTextureFromImage(int buttonType);
void init();
+ void showPreparingAnimation(const SkRect& rect,
+ const SkRect innerRect);
// Surface texture for showing the video is actually allocated in Java side
// and passed into this native code.
sp<android::SurfaceTexture> m_surfaceTexture;
@@ -78,6 +83,8 @@ private:
static GLuint m_posterTextureId;
static GLuint m_spinnerOuterTextureId;
static GLuint m_spinnerInnerTextureId;
+ static GLuint m_playTextureId;
+ static GLuint m_pauseTextureId;
static double m_rotateDegree;
diff --git a/Source/WebCore/platform/graphics/android/VideoLayerManager.cpp b/Source/WebCore/platform/graphics/android/VideoLayerManager.cpp
index cec4d67..d0fc873 100644
--- a/Source/WebCore/platform/graphics/android/VideoLayerManager.cpp
+++ b/Source/WebCore/platform/graphics/android/VideoLayerManager.cpp
@@ -25,6 +25,7 @@
#include "config.h"
#include "VideoLayerManager.h"
+#include <wtf/CurrentTime.h>
#if USE(ACCELERATED_COMPOSITING)
@@ -42,6 +43,10 @@
#endif // DEBUG
+// The animation of the play/pause icon will last for PLAY_PAUSE_ICON_SHOW_TIME
+// seconds.
+#define PLAY_PAUSE_ICON_SHOW_TIME 1
+
// Define the max sum of all the video's sizes.
// Note that video_size = width * height. If there is no compression, then the
// maximum memory consumption could be 4 * video_size.
@@ -105,6 +110,8 @@ void VideoLayerManager::registerTexture(const int layerId, const GLuint textureI
pInfo->videoSize = 0;
m_currentTimeStamp++;
pInfo->timeStamp = m_currentTimeStamp;
+ pInfo->lastIconShownTime = 0;
+ pInfo->iconState = Registered;
m_videoLayerInfoMap.add(layerId, pInfo);
XLOG("GL texture %d regisered for layerId %d", textureId, layerId);
@@ -238,5 +245,34 @@ void VideoLayerManager::removeLayerInternal(const int layerId)
return;
}
+double VideoLayerManager::drawIcon(const int layerId, IconType type)
+{
+ // When ratio 0 is returned, the Icon should not be drawn.
+ double ratio = 0;
+
+ android::Mutex::Autolock lock(m_videoLayerInfoMapLock);
+ if (m_videoLayerInfoMap.contains(layerId)) {
+ VideoLayerInfo* pInfo = m_videoLayerInfoMap.get(layerId);
+ // If this is state switching moment, reset the time and state
+ if ((type == PlayIcon && pInfo->iconState != PlayIconShown)
+ ||(type == PauseIcon && pInfo->iconState != PauseIconShown)) {
+ pInfo->lastIconShownTime = WTF::currentTime();
+ pInfo->iconState = (type == PlayIcon) ? PlayIconShown : PauseIconShown;
+ }
+
+ // After switching the state, we calculate the ratio depending on the
+ // time interval.
+ if ((type == PlayIcon && pInfo->iconState == PlayIconShown)
+ || (type == PauseIcon && pInfo->iconState == PauseIconShown)) {
+ double delta = WTF::currentTime() - pInfo->lastIconShownTime;
+ ratio = 1.0 - (delta / PLAY_PAUSE_ICON_SHOW_TIME);
+ }
+ }
+
+ if (ratio > 1 || ratio < 0 )
+ ratio = 0;
+ return ratio;
+}
+
}
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/VideoLayerManager.h b/Source/WebCore/platform/graphics/android/VideoLayerManager.h
index de2dafc..a427269 100644
--- a/Source/WebCore/platform/graphics/android/VideoLayerManager.h
+++ b/Source/WebCore/platform/graphics/android/VideoLayerManager.h
@@ -34,6 +34,17 @@
namespace WebCore {
+enum IconState {
+ Registered,
+ PlayIconShown,
+ PauseIconShown
+};
+
+enum IconType {
+ PlayIcon,
+ PauseIcon
+};
+
// Every video layer can use its uniqueId to query VideoLayerManager about such
// info globally.
struct VideoLayerInfo {
@@ -41,6 +52,9 @@ struct VideoLayerInfo {
int videoSize; // The size of the video.
int timeStamp; // Used to decide which VideoLayerInfo is the oldest one.
GLfloat surfaceMatrix[16];
+
+ double lastIconShownTime;
+ IconState iconState;
};
@@ -68,6 +82,7 @@ public:
// Delete the GL textures
void deleteUnusedTextures();
+ double drawIcon(const int layerId, IconType type);
private:
// Get the sum of all the video size stored in m_videoLayerInfoMap.
int getTotalMemUsage();
diff --git a/Source/WebKit/android/RenderSkinMediaButton.cpp b/Source/WebKit/android/RenderSkinMediaButton.cpp
index ef4b313..b92336e 100644
--- a/Source/WebKit/android/RenderSkinMediaButton.cpp
+++ b/Source/WebKit/android/RenderSkinMediaButton.cpp
@@ -89,7 +89,7 @@ void RenderSkinMediaButton::Decode()
}
void RenderSkinMediaButton::Draw(SkCanvas* canvas, const IntRect& r, int buttonType,
- bool translucent, RenderObject* o)
+ bool translucent, RenderObject* o, bool drawBackground)
{
if (!gDecoded) {
Decode();
@@ -102,7 +102,6 @@ void RenderSkinMediaButton::Draw(SkCanvas* canvas, const IntRect& r, int buttonT
bool drawsNinePatch = false;
bool drawsImage = true;
- bool drawsBackgroundColor = true;
int ninePatchIndex = 0;
int imageIndex = 0;
@@ -136,13 +135,11 @@ void RenderSkinMediaButton::Draw(SkCanvas* canvas, const IntRect& r, int buttonT
case SPINNER_INNER:
case VIDEO:
{
- drawsBackgroundColor = false;
imageIndex = buttonType + 1;
break;
}
case BACKGROUND_SLIDER:
{
- drawsBackgroundColor = false;
drawsImage = false;
break;
}
@@ -155,7 +152,6 @@ void RenderSkinMediaButton::Draw(SkCanvas* canvas, const IntRect& r, int buttonT
}
case SLIDER_THUMB:
{
- drawsBackgroundColor = false;
imageMargin = 0;
imageIndex = buttonType + 1;
break;
@@ -164,7 +160,7 @@ void RenderSkinMediaButton::Draw(SkCanvas* canvas, const IntRect& r, int buttonT
return;
}
- if (drawsBackgroundColor) {
+ if (drawBackground) {
canvas->drawRect(r, paint);
}
diff --git a/Source/WebKit/android/RenderSkinMediaButton.h b/Source/WebKit/android/RenderSkinMediaButton.h
index d8b7c8d..484b90c 100644
--- a/Source/WebKit/android/RenderSkinMediaButton.h
+++ b/Source/WebKit/android/RenderSkinMediaButton.h
@@ -42,7 +42,7 @@ public:
* State to determine which skin to use, i.e. focused or not focused.
*/
static void Draw(SkCanvas* , const IntRect& , int buttonType, bool translucent = false,
- RenderObject* o = 0);
+ RenderObject* o = 0, bool drawBackground = true);
/**
* Button types
*/