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.
5 #include "content/browser/android/content_video_view.h"
7 #include "base/command_line.h"
8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h"
10 #include "content/browser/android/content_view_core_impl.h"
11 #include "content/browser/media/android/browser_media_player_manager.h"
12 #include "content/browser/power_save_blocker_impl.h"
13 #include "content/common/android/surface_texture_peer.h"
14 #include "content/public/common/content_switches.h"
15 #include "jni/ContentVideoView_jni.h"
17 using base::android::AttachCurrentThread;
18 using base::android::CheckException;
19 using base::android::ScopedJavaGlobalRef;
24 // There can only be one content video view at a time, this holds onto that
25 // singleton instance.
26 ContentVideoView* g_content_video_view = NULL;
30 static jobject GetSingletonJavaContentVideoView(JNIEnv*env, jclass) {
31 if (g_content_video_view)
32 return g_content_video_view->GetJavaObject(env).Release();
37 bool ContentVideoView::RegisterContentVideoView(JNIEnv* env) {
38 return RegisterNativesImpl(env);
41 ContentVideoView* ContentVideoView::GetInstance() {
42 return g_content_video_view;
45 ContentVideoView::ContentVideoView(
46 BrowserMediaPlayerManager* manager)
49 DCHECK(!g_content_video_view);
50 j_content_video_view_ = CreateJavaObject();
51 g_content_video_view = this;
52 CreatePowerSaveBlocker();
55 ContentVideoView::~ContentVideoView() {
56 DCHECK(g_content_video_view);
57 DestroyContentVideoView(true);
58 g_content_video_view = NULL;
61 void ContentVideoView::OpenVideo() {
62 JNIEnv* env = AttachCurrentThread();
63 ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
64 if (!content_video_view.is_null()) {
65 CreatePowerSaveBlocker();
66 Java_ContentVideoView_openVideo(env, content_video_view.obj());
70 void ContentVideoView::OnMediaPlayerError(int error_type) {
71 JNIEnv* env = AttachCurrentThread();
72 ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
73 if (!content_video_view.is_null()) {
74 power_save_blocker_.reset();
75 Java_ContentVideoView_onMediaPlayerError(env, content_video_view.obj(),
80 void ContentVideoView::OnVideoSizeChanged(int width, int height) {
81 JNIEnv* env = AttachCurrentThread();
82 ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
83 if (!content_video_view.is_null()) {
84 Java_ContentVideoView_onVideoSizeChanged(env, content_video_view.obj(),
89 void ContentVideoView::OnBufferingUpdate(int percent) {
90 JNIEnv* env = AttachCurrentThread();
91 ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
92 if (!content_video_view.is_null()) {
93 Java_ContentVideoView_onBufferingUpdate(env, content_video_view.obj(),
98 void ContentVideoView::OnPlaybackComplete() {
99 JNIEnv* env = AttachCurrentThread();
100 ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
101 if (!content_video_view.is_null()) {
102 power_save_blocker_.reset();
103 Java_ContentVideoView_onPlaybackComplete(env, content_video_view.obj());
107 void ContentVideoView::OnExitFullscreen() {
108 JNIEnv* env = AttachCurrentThread();
109 ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
110 if (!content_video_view.is_null()) {
111 Java_ContentVideoView_onExitFullscreen(env, content_video_view.obj());
112 j_content_video_view_.reset();
116 void ContentVideoView::UpdateMediaMetadata() {
117 JNIEnv* env = AttachCurrentThread();
118 ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
119 if (content_video_view.is_null())
122 media::MediaPlayerAndroid* player = manager_->GetFullscreenPlayer();
123 if (player && player->IsPlayerReady()) {
124 Java_ContentVideoView_onUpdateMediaMetadata(
125 env, content_video_view.obj(), player->GetVideoWidth(),
126 player->GetVideoHeight(), player->GetDuration().InMilliseconds(),
127 player->CanPause(),player->CanSeekForward(), player->CanSeekBackward());
131 int ContentVideoView::GetVideoWidth(JNIEnv*, jobject obj) const {
132 media::MediaPlayerAndroid* player = manager_->GetFullscreenPlayer();
133 return player ? player->GetVideoWidth() : 0;
136 int ContentVideoView::GetVideoHeight(JNIEnv*, jobject obj) const {
137 media::MediaPlayerAndroid* player = manager_->GetFullscreenPlayer();
138 return player ? player->GetVideoHeight() : 0;
141 int ContentVideoView::GetDurationInMilliSeconds(JNIEnv*, jobject obj) const {
142 media::MediaPlayerAndroid* player = manager_->GetFullscreenPlayer();
143 return player ? player->GetDuration().InMilliseconds() : -1;
146 int ContentVideoView::GetCurrentPosition(JNIEnv*, jobject obj) const {
147 media::MediaPlayerAndroid* player = manager_->GetFullscreenPlayer();
148 return player ? player->GetCurrentTime().InMilliseconds() : 0;
151 bool ContentVideoView::IsPlaying(JNIEnv*, jobject obj) {
152 media::MediaPlayerAndroid* player = manager_->GetFullscreenPlayer();
153 return player ? player->IsPlaying() : false;
156 void ContentVideoView::SeekTo(JNIEnv*, jobject obj, jint msec) {
157 manager_->FullscreenPlayerSeek(msec);
160 void ContentVideoView::Play(JNIEnv*, jobject obj) {
161 CreatePowerSaveBlocker();
162 manager_->FullscreenPlayerPlay();
165 void ContentVideoView::Pause(JNIEnv*, jobject obj) {
166 power_save_blocker_.reset();
167 manager_->FullscreenPlayerPause();
170 void ContentVideoView::ExitFullscreen(
171 JNIEnv*, jobject, jboolean release_media_player) {
172 power_save_blocker_.reset();
173 j_content_video_view_.reset();
174 manager_->ExitFullscreen(release_media_player);
177 void ContentVideoView::SetSurface(JNIEnv* env, jobject obj,
179 manager_->SetVideoSurface(
180 gfx::ScopedJavaSurface::AcquireExternalSurface(surface));
183 void ContentVideoView::RequestMediaMetadata(JNIEnv* env, jobject obj) {
184 base::MessageLoop::current()->PostTask(
186 base::Bind(&ContentVideoView::UpdateMediaMetadata,
187 weak_factory_.GetWeakPtr()));
190 ScopedJavaLocalRef<jobject> ContentVideoView::GetJavaObject(JNIEnv* env) {
191 return j_content_video_view_.get(env);
194 gfx::NativeView ContentVideoView::GetNativeView() {
195 JNIEnv* env = AttachCurrentThread();
196 ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
197 if (content_video_view.is_null())
200 return reinterpret_cast<gfx::NativeView>(
201 Java_ContentVideoView_getNativeViewAndroid(env,
202 content_video_view.obj()));
206 JavaObjectWeakGlobalRef ContentVideoView::CreateJavaObject() {
207 ContentViewCoreImpl* content_view_core = manager_->GetContentViewCore();
208 JNIEnv* env = AttachCurrentThread();
209 bool legacyMode = !CommandLine::ForCurrentProcess()->HasSwitch(
210 switches::kEnableOverlayFullscreenVideoSubtitle);
211 return JavaObjectWeakGlobalRef(
213 Java_ContentVideoView_createContentVideoView(
215 content_view_core->GetContext().obj(),
216 reinterpret_cast<intptr_t>(this),
217 content_view_core->GetContentVideoViewClient().obj(),
221 void ContentVideoView::CreatePowerSaveBlocker() {
222 if (power_save_blocker_) return;
224 power_save_blocker_ = PowerSaveBlocker::Create(
225 PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
226 "Playing video").Pass();
227 static_cast<PowerSaveBlockerImpl*>(power_save_blocker_.get())->
228 InitDisplaySleepBlocker(GetNativeView());
231 void ContentVideoView::DestroyContentVideoView(bool native_view_destroyed) {
232 JNIEnv* env = AttachCurrentThread();
233 ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
234 if (!content_video_view.is_null()) {
235 Java_ContentVideoView_destroyContentVideoView(env,
236 content_video_view.obj(), native_view_destroyed);
237 j_content_video_view_.reset();
240 } // namespace content