diff options
author | Teng-Hui Zhu <ztenghui@google.com> | 2011-02-25 15:18:51 -0800 |
---|---|---|
committer | Teng-Hui Zhu <ztenghui@google.com> | 2011-03-10 16:58:48 -0800 |
commit | 331fdb1964135091e1a4f5508cbff6a9dab0ea97 (patch) | |
tree | 202b12444776ce3fe8795867166c5c0a49bc08b2 /WebKit | |
parent | ad5136a701b6100295270b62040f2cfb8fecb053 (diff) | |
download | external_webkit-331fdb1964135091e1a4f5508cbff6a9dab0ea97.zip external_webkit-331fdb1964135091e1a4f5508cbff6a9dab0ea97.tar.gz external_webkit-331fdb1964135091e1a4f5508cbff6a9dab0ea97.tar.bz2 |
webkit support for inline video
Basically we provide a Video Layer for the inline video.
The java side change is at 101311.
bug:3506407,2126902
Change-Id: I9cc1b910f502595d6be7ac81e448343ca6ca9100
Diffstat (limited to 'WebKit')
-rw-r--r-- | WebKit/android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp | 149 |
1 files changed, 110 insertions, 39 deletions
diff --git a/WebKit/android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp b/WebKit/android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp index f5dd567..3abb813 100644 --- a/WebKit/android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp +++ b/WebKit/android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp @@ -28,29 +28,34 @@ #if ENABLE(VIDEO) +#include "BaseLayerAndroid.h" #include "DocumentLoader.h" #include "Frame.h" #include "FrameLoader.h" #include "FrameView.h" #include "GraphicsContext.h" #include "SkiaUtils.h" +#include "VideoLayerAndroid.h" #include "WebCoreJni.h" #include "WebViewCore.h" - #include <GraphicsJNI.h> #include <JNIHelp.h> #include <JNIUtility.h> #include <SkBitmap.h> +#include <gui/SurfaceTexture.h> using namespace android; +// Forward decl +namespace android { +sp<SurfaceTexture> SurfaceTexture_getSurfaceTexture(JNIEnv* env, jobject thiz); +}; namespace WebCore { static const char* g_ProxyJavaClass = "android/webkit/HTML5VideoViewProxy"; static const char* g_ProxyJavaClassAudio = "android/webkit/HTML5Audio"; -struct MediaPlayerPrivate::JavaGlue -{ +struct MediaPlayerPrivate::JavaGlue { jobject m_javaProxy; jmethodID m_play; jmethodID m_teardown; @@ -120,8 +125,8 @@ void MediaPlayerPrivate::seek(float time) checkException(env); } - -void MediaPlayerPrivate::prepareToPlay() { +void MediaPlayerPrivate::prepareToPlay() +{ // We are about to start playing. Since our Java VideoView cannot // buffer any data, we just simply transition to the HaveEnoughData // state in here. This will allow the MediaPlayer to transition to @@ -136,7 +141,7 @@ void MediaPlayerPrivate::prepareToPlay() { MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) : m_player(player), m_glue(0), - m_duration(6000), + m_duration(1), // keep this minimal to avoid initial seek problem m_currentTime(0), m_paused(true), m_hasVideo(false), @@ -149,31 +154,33 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) { } -void MediaPlayerPrivate::onEnded() { +void MediaPlayerPrivate::onEnded() +{ m_currentTime = duration(); m_player->timeChanged(); m_paused = true; m_hasVideo = false; m_networkState = MediaPlayer::Idle; - m_readyState = MediaPlayer::HaveNothing; } -void MediaPlayerPrivate::onPaused() { +void MediaPlayerPrivate::onPaused() +{ m_paused = true; m_hasVideo = false; m_networkState = MediaPlayer::Idle; - m_readyState = MediaPlayer::HaveNothing; m_player->playbackStateChanged(); } -void MediaPlayerPrivate::onTimeupdate(int position) { +void MediaPlayerPrivate::onTimeupdate(int position) +{ m_currentTime = position / 1000.0f; m_player->timeChanged(); } class MediaPlayerVideoPrivate : public MediaPlayerPrivate { public: - void load(const String& url) { + void load(const String& url) + { m_url = url; // Cheat a bit here to make sure Window.onLoad event can be triggered // at the right time instead of real video play time, since only full @@ -185,7 +192,8 @@ public: m_player->readyStateChanged(); } - void play() { + void play() + { JNIEnv* env = JSC::Bindings::getJNIEnv(); if (!env || !m_url.length() || !m_glue->m_javaProxy) return; @@ -201,13 +209,16 @@ public: m_currentTime = 0; jstring jUrl = wtfStringToJstring(env, m_url); - env->CallVoidMethod(m_glue->m_javaProxy, m_glue->m_play, jUrl, static_cast<jint>(m_currentTime * 1000.0f)); + env->CallVoidMethod(m_glue->m_javaProxy, m_glue->m_play, jUrl, + static_cast<jint>(m_currentTime * 1000.0f), + m_videoLayer.uniqueId()); env->DeleteLocalRef(jUrl); checkException(env); } bool canLoadPoster() const { return true; } - void setPoster(const String& url) { + void setPoster(const String& url) + { if (m_posterUrl == url) return; @@ -220,7 +231,8 @@ public: env->CallVoidMethod(m_glue->m_javaProxy, m_glue->m_loadPoster, jUrl); env->DeleteLocalRef(jUrl); } - void paint(GraphicsContext* ctxt, const IntRect& r) { + void paint(GraphicsContext* ctxt, const IntRect& r) + { if (ctxt->paintingDisabled()) return; @@ -244,7 +256,8 @@ public: canvas->drawBitmapRect(*m_poster, 0, targetRect, 0); } - void onPosterFetched(SkBitmap* poster) { + void onPosterFetched(SkBitmap* poster) + { m_poster = poster; if (m_naturalSizeUnknown) { // We had to fake the size at startup, or else our paint @@ -258,7 +271,8 @@ public: } } - void onPrepared(int duration, int width, int height) { + void onPrepared(int duration, int width, int height) + { m_duration = duration / 1000.0f; m_naturalSize = IntSize(width, height); m_naturalSizeUnknown = false; @@ -270,7 +284,8 @@ public: bool hasAudio() { return false; } // do not display the audio UI bool hasVideo() { return m_hasVideo; } - MediaPlayerVideoPrivate(MediaPlayer* player) : MediaPlayerPrivate(player) { + MediaPlayerVideoPrivate(MediaPlayer* player) : MediaPlayerPrivate(player) + { JNIEnv* env = JSC::Bindings::getJNIEnv(); if (!env) return; @@ -283,18 +298,19 @@ public: m_glue = new JavaGlue; m_glue->m_getInstance = env->GetStaticMethodID(clazz, "getInstance", "(Landroid/webkit/WebViewCore;I)Landroid/webkit/HTML5VideoViewProxy;"); m_glue->m_loadPoster = env->GetMethodID(clazz, "loadPoster", "(Ljava/lang/String;)V"); - m_glue->m_play = env->GetMethodID(clazz, "play", "(Ljava/lang/String;I)V"); + m_glue->m_play = env->GetMethodID(clazz, "play", "(Ljava/lang/String;II)V"); m_glue->m_teardown = env->GetMethodID(clazz, "teardown", "()V"); m_glue->m_seek = env->GetMethodID(clazz, "seek", "(I)V"); m_glue->m_pause = env->GetMethodID(clazz, "pause", "()V"); - m_glue->m_javaProxy = NULL; + m_glue->m_javaProxy = 0; env->DeleteLocalRef(clazz); // An exception is raised if any of the above fails. checkException(env); } - void createJavaPlayerIfNeeded() { + void createJavaPlayerIfNeeded() + { // Check if we have been already created. if (m_glue->m_javaProxy) return; @@ -308,7 +324,7 @@ public: if (!clazz) return; - jobject obj = NULL; + jobject obj = 0; FrameView* frameView = m_player->frameView(); if (!frameView) @@ -335,14 +351,16 @@ public: checkException(env); } - float maxTimeSeekable() const { + float maxTimeSeekable() const + { return m_duration; } }; class MediaPlayerAudioPrivate : public MediaPlayerPrivate { public: - void load(const String& url) { + void load(const String& url) + { m_url = url; JNIEnv* env = JSC::Bindings::getJNIEnv(); if (!env || !m_url.length()) @@ -360,7 +378,8 @@ public: checkException(env); } - void play() { + void play() + { JNIEnv* env = JSC::Bindings::getJNIEnv(); if (!env || !m_url.length()) return; @@ -377,7 +396,8 @@ public: bool hasAudio() { return true; } - float maxTimeSeekable() const { + float maxTimeSeekable() const + { if (m_glue->m_javaProxy) { JNIEnv* env = JSC::Bindings::getJNIEnv(); if (env) { @@ -390,7 +410,8 @@ public: return 0; } - MediaPlayerAudioPrivate(MediaPlayer* player) : MediaPlayerPrivate(player) { + MediaPlayerAudioPrivate(MediaPlayer* player) : MediaPlayerPrivate(player) + { JNIEnv* env = JSC::Bindings::getJNIEnv(); if (!env) return; @@ -408,13 +429,14 @@ public: m_glue->m_teardown = env->GetMethodID(clazz, "teardown", "()V"); m_glue->m_seek = env->GetMethodID(clazz, "seek", "(I)V"); m_glue->m_pause = env->GetMethodID(clazz, "pause", "()V"); - m_glue->m_javaProxy = NULL; + m_glue->m_javaProxy = 0; env->DeleteLocalRef(clazz); // An exception is raised if any of the above fails. checkException(env); } - void createJavaPlayerIfNeeded() { + void createJavaPlayerIfNeeded() + { // Check if we have been already created. if (m_glue->m_javaProxy) return; @@ -428,7 +450,7 @@ public: if (!clazz) return; - jobject obj = NULL; + jobject obj = 0; // Get the HTML5Audio instance obj = env->NewObject(clazz, m_glue->m_newInstance, this); @@ -441,7 +463,8 @@ public: checkException(env); } - void onPrepared(int duration, int width, int height) { + void onPrepared(int duration, int width, int height) + { // Android media player gives us a duration of 0 for a live // stream, so in that case set the real duration to infinity. // We'll still be able to handle the case that we genuinely @@ -469,28 +492,32 @@ MediaPlayerPrivateInterface* MediaPlayerPrivate::create(MediaPlayer* player) namespace android { -static void OnPrepared(JNIEnv* env, jobject obj, int duration, int width, int height, int pointer) { +static void OnPrepared(JNIEnv* env, jobject obj, int duration, int width, int height, int pointer) +{ if (pointer) { WebCore::MediaPlayerPrivate* player = reinterpret_cast<WebCore::MediaPlayerPrivate*>(pointer); player->onPrepared(duration, width, height); } } -static void OnEnded(JNIEnv* env, jobject obj, int pointer) { +static void OnEnded(JNIEnv* env, jobject obj, int pointer) +{ if (pointer) { WebCore::MediaPlayerPrivate* player = reinterpret_cast<WebCore::MediaPlayerPrivate*>(pointer); player->onEnded(); } } -static void OnPaused(JNIEnv* env, jobject obj, int pointer) { +static void OnPaused(JNIEnv* env, jobject obj, int pointer) +{ if (pointer) { WebCore::MediaPlayerPrivate* player = reinterpret_cast<WebCore::MediaPlayerPrivate*>(pointer); player->onPaused(); } } -static void OnPosterFetched(JNIEnv* env, jobject obj, jobject poster, int pointer) { +static void OnPosterFetched(JNIEnv* env, jobject obj, jobject poster, int pointer) +{ if (!pointer || !poster) return; @@ -501,20 +528,62 @@ static void OnPosterFetched(JNIEnv* env, jobject obj, jobject poster, int pointe player->onPosterFetched(posterNative); } -static void OnBuffering(JNIEnv* env, jobject obj, int percent, int pointer) { +static void OnBuffering(JNIEnv* env, jobject obj, int percent, int pointer) +{ if (pointer) { WebCore::MediaPlayerPrivate* player = reinterpret_cast<WebCore::MediaPlayerPrivate*>(pointer); - //TODO: player->onBuffering(percent); + // TODO: player->onBuffering(percent); } } -static void OnTimeupdate(JNIEnv* env, jobject obj, int position, int pointer) { +static void OnTimeupdate(JNIEnv* env, jobject obj, int position, int pointer) +{ if (pointer) { WebCore::MediaPlayerPrivate* player = reinterpret_cast<WebCore::MediaPlayerPrivate*>(pointer); player->onTimeupdate(position); } } +// This is called on the UI thread only. +// The video layers are composited on the webkit thread and then copied over +// to the UI thread with the same ID. For rendering, we are only using the +// video layers on the UI thread. Therefore, on the UI thread, we have to use +// the videoLayerId from Java side to find the exact video layer in the tree +// to set the surface texture. +// Every time a play call into Java side, the videoLayerId will be sent and +// saved in Java side. Then every time setBaseLayer call, the saved +// videoLayerId will be passed to this function to find the Video Layer. +// Return value: true when the video layer is found. +static bool SendSurfaceTexture(JNIEnv* env, jobject obj, jobject surfTex, + int baseLayer, int videoLayerId, + int textureName, bool updateTexture) { + if (!surfTex) + return false; + + sp<SurfaceTexture> texture = android::SurfaceTexture_getSurfaceTexture(env, surfTex); + if (!texture.get()) + return false; + + BaseLayerAndroid* layerImpl = reinterpret_cast<BaseLayerAndroid*>(baseLayer); + if (!layerImpl) + return false; + if (!layerImpl->countChildren()) + return false; + LayerAndroid* compositedRoot = static_cast<LayerAndroid*>(layerImpl->getChild(0)); + if (!compositedRoot) + return false; + + VideoLayerAndroid* videoLayer = + static_cast<VideoLayerAndroid*>(compositedRoot->findById(videoLayerId)); + if (!videoLayer) + return false; + + // Set the SurfaceTexture to the layer we found + videoLayer->setSurfaceTexture(texture, textureName, updateTexture); + return true; +} + + /* * JNI registration */ @@ -527,6 +596,8 @@ static JNINativeMethod g_MediaPlayerMethods[] = { (void*) OnPaused }, { "nativeOnPosterFetched", "(Landroid/graphics/Bitmap;I)V", (void*) OnPosterFetched }, + { "nativeSendSurfaceTexture", "(Landroid/graphics/SurfaceTexture;IIIZ)Z", + (void*) SendSurfaceTexture }, { "nativeOnTimeupdate", "(II)V", (void*) OnTimeupdate }, }; |