1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "content/browser/android/content_video_view.h" 6 7 #include "base/command_line.h" 8 #include "base/logging.h" 9 #include "content/browser/media/android/browser_media_player_manager.h" 10 #include "content/browser/power_save_blocker_impl.h" 11 #include "content/common/android/surface_texture_peer.h" 12 #include "content/public/common/content_switches.h" 13 #include "jni/ContentVideoView_jni.h" 14 15 using base::android::AttachCurrentThread; 16 using base::android::CheckException; 17 using base::android::ScopedJavaGlobalRef; 18 19 namespace content { 20 21 namespace { 22 // There can only be one content video view at a time, this holds onto that 23 // singleton instance. 24 ContentVideoView* g_content_video_view = NULL; 25 26 } // namespace 27 28 static jobject GetSingletonJavaContentVideoView(JNIEnv*env, jclass) { 29 if (g_content_video_view) 30 return g_content_video_view->GetJavaObject(env).Release(); 31 else 32 return NULL; 33 } 34 35 bool ContentVideoView::RegisterContentVideoView(JNIEnv* env) { 36 return RegisterNativesImpl(env); 37 } 38 39 bool ContentVideoView::HasContentVideoView() { 40 return g_content_video_view; 41 } 42 43 ContentVideoView::ContentVideoView( 44 const ScopedJavaLocalRef<jobject>& context, 45 const ScopedJavaLocalRef<jobject>& client, 46 BrowserMediaPlayerManager* manager) 47 : manager_(manager) { 48 DCHECK(!g_content_video_view); 49 JNIEnv *env = AttachCurrentThread(); 50 j_content_video_view_ = JavaObjectWeakGlobalRef(env, 51 Java_ContentVideoView_createContentVideoView(env, context.obj(), 52 reinterpret_cast<intptr_t>(this), client.obj()).obj()); 53 g_content_video_view = this; 54 CreatePowerSaveBlocker(); 55 } 56 57 ContentVideoView::~ContentVideoView() { 58 DCHECK(g_content_video_view); 59 DestroyContentVideoView(true); 60 g_content_video_view = NULL; 61 } 62 63 void ContentVideoView::OpenVideo() { 64 JNIEnv* env = AttachCurrentThread(); 65 ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env); 66 if (!content_video_view.is_null()) { 67 CreatePowerSaveBlocker(); 68 Java_ContentVideoView_openVideo(env, content_video_view.obj()); 69 } 70 } 71 72 void ContentVideoView::OnMediaPlayerError(int error_type) { 73 JNIEnv* env = AttachCurrentThread(); 74 ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env); 75 if (!content_video_view.is_null()) { 76 power_save_blocker_.reset(); 77 Java_ContentVideoView_onMediaPlayerError(env, content_video_view.obj(), 78 error_type); 79 } 80 } 81 82 void ContentVideoView::OnVideoSizeChanged(int width, int height) { 83 JNIEnv* env = AttachCurrentThread(); 84 ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env); 85 if (!content_video_view.is_null()) { 86 Java_ContentVideoView_onVideoSizeChanged(env, content_video_view.obj(), 87 width, height); 88 } 89 } 90 91 void ContentVideoView::OnBufferingUpdate(int percent) { 92 JNIEnv* env = AttachCurrentThread(); 93 ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env); 94 if (!content_video_view.is_null()) { 95 Java_ContentVideoView_onBufferingUpdate(env, content_video_view.obj(), 96 percent); 97 } 98 } 99 100 void ContentVideoView::OnPlaybackComplete() { 101 JNIEnv* env = AttachCurrentThread(); 102 ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env); 103 if (!content_video_view.is_null()) { 104 power_save_blocker_.reset(); 105 Java_ContentVideoView_onPlaybackComplete(env, content_video_view.obj()); 106 } 107 } 108 109 void ContentVideoView::OnExitFullscreen() { 110 DestroyContentVideoView(false); 111 } 112 113 void ContentVideoView::UpdateMediaMetadata() { 114 JNIEnv* env = AttachCurrentThread(); 115 ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env); 116 if (!content_video_view.is_null()) 117 UpdateMediaMetadata(env, content_video_view.obj()); 118 } 119 120 int ContentVideoView::GetVideoWidth(JNIEnv*, jobject obj) const { 121 media::MediaPlayerAndroid* player = manager_->GetFullscreenPlayer(); 122 return player ? player->GetVideoWidth() : 0; 123 } 124 125 int ContentVideoView::GetVideoHeight(JNIEnv*, jobject obj) const { 126 media::MediaPlayerAndroid* player = manager_->GetFullscreenPlayer(); 127 return player ? player->GetVideoHeight() : 0; 128 } 129 130 int ContentVideoView::GetDurationInMilliSeconds(JNIEnv*, jobject obj) const { 131 media::MediaPlayerAndroid* player = manager_->GetFullscreenPlayer(); 132 return player ? player->GetDuration().InMilliseconds() : -1; 133 } 134 135 int ContentVideoView::GetCurrentPosition(JNIEnv*, jobject obj) const { 136 media::MediaPlayerAndroid* player = manager_->GetFullscreenPlayer(); 137 return player ? player->GetCurrentTime().InMilliseconds() : 0; 138 } 139 140 bool ContentVideoView::IsPlaying(JNIEnv*, jobject obj) { 141 media::MediaPlayerAndroid* player = manager_->GetFullscreenPlayer(); 142 return player ? player->IsPlaying() : false; 143 } 144 145 void ContentVideoView::SeekTo(JNIEnv*, jobject obj, jint msec) { 146 manager_->FullscreenPlayerSeek(msec); 147 } 148 149 void ContentVideoView::Play(JNIEnv*, jobject obj) { 150 CreatePowerSaveBlocker(); 151 manager_->FullscreenPlayerPlay(); 152 } 153 154 void ContentVideoView::Pause(JNIEnv*, jobject obj) { 155 power_save_blocker_.reset(); 156 manager_->FullscreenPlayerPause(); 157 } 158 159 void ContentVideoView::ExitFullscreen( 160 JNIEnv*, jobject, jboolean release_media_player) { 161 power_save_blocker_.reset(); 162 j_content_video_view_.reset(); 163 manager_->ExitFullscreen(release_media_player); 164 } 165 166 void ContentVideoView::SetSurface(JNIEnv* env, jobject obj, 167 jobject surface) { 168 manager_->SetVideoSurface( 169 gfx::ScopedJavaSurface::AcquireExternalSurface(surface)); 170 } 171 172 void ContentVideoView::UpdateMediaMetadata(JNIEnv* env, jobject obj) { 173 media::MediaPlayerAndroid* player = manager_->GetFullscreenPlayer(); 174 if (player && player->IsPlayerReady()) 175 Java_ContentVideoView_onUpdateMediaMetadata( 176 env, obj, player->GetVideoWidth(), player->GetVideoHeight(), 177 player->GetDuration().InMilliseconds(), player->CanPause(), 178 player->CanSeekForward(), player->CanSeekBackward()); 179 } 180 181 ScopedJavaLocalRef<jobject> ContentVideoView::GetJavaObject(JNIEnv* env) { 182 return j_content_video_view_.get(env); 183 } 184 185 gfx::NativeView ContentVideoView::GetNativeView() { 186 JNIEnv* env = AttachCurrentThread(); 187 ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env); 188 if (content_video_view.is_null()) 189 return NULL; 190 191 return reinterpret_cast<gfx::NativeView>( 192 Java_ContentVideoView_getNativeViewAndroid(env, 193 content_video_view.obj())); 194 195 } 196 197 void ContentVideoView::CreatePowerSaveBlocker() { 198 if (power_save_blocker_) return; 199 200 power_save_blocker_ = PowerSaveBlocker::Create( 201 PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep, 202 "Playing video").Pass(); 203 static_cast<PowerSaveBlockerImpl*>(power_save_blocker_.get())-> 204 InitDisplaySleepBlocker(GetNativeView()); 205 } 206 207 void ContentVideoView::DestroyContentVideoView(bool native_view_destroyed) { 208 JNIEnv* env = AttachCurrentThread(); 209 ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env); 210 if (!content_video_view.is_null()) { 211 j_content_video_view_.reset(); 212 Java_ContentVideoView_destroyContentVideoView(env, 213 content_video_view.obj(), native_view_destroyed); 214 j_content_video_view_.reset(); 215 } 216 } 217 } // namespace content 218