content_video_view.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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 "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"
16
17using base::android::AttachCurrentThread;
18using base::android::CheckException;
19using base::android::ScopedJavaGlobalRef;
20
21namespace content {
22
23namespace {
24// There can only be one content video view at a time, this holds onto that
25// singleton instance.
26ContentVideoView* g_content_video_view = NULL;
27
28}  // namespace
29
30static jobject GetSingletonJavaContentVideoView(JNIEnv*env, jclass) {
31  if (g_content_video_view)
32    return g_content_video_view->GetJavaObject(env).Release();
33  else
34    return NULL;
35}
36
37bool ContentVideoView::RegisterContentVideoView(JNIEnv* env) {
38  return RegisterNativesImpl(env);
39}
40
41ContentVideoView* ContentVideoView::GetInstance() {
42  return g_content_video_view;
43}
44
45ContentVideoView::ContentVideoView(
46    BrowserMediaPlayerManager* manager)
47    : manager_(manager),
48      weak_factory_(this) {
49  DCHECK(!g_content_video_view);
50  j_content_video_view_ = CreateJavaObject();
51  g_content_video_view = this;
52  CreatePowerSaveBlocker();
53}
54
55ContentVideoView::~ContentVideoView() {
56  DCHECK(g_content_video_view);
57  DestroyContentVideoView(true);
58  g_content_video_view = NULL;
59}
60
61void 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());
67  }
68}
69
70void 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(),
76        error_type);
77  }
78}
79
80void 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(),
85        width, height);
86  }
87}
88
89void 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(),
94        percent);
95  }
96}
97
98void 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());
104  }
105}
106
107void 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();
113  }
114}
115
116void ContentVideoView::UpdateMediaMetadata() {
117  JNIEnv* env = AttachCurrentThread();
118  ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
119  if (content_video_view.is_null())
120    return;
121
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());
128  }
129}
130
131int ContentVideoView::GetVideoWidth(JNIEnv*, jobject obj) const {
132  media::MediaPlayerAndroid* player = manager_->GetFullscreenPlayer();
133  return player ? player->GetVideoWidth() : 0;
134}
135
136int ContentVideoView::GetVideoHeight(JNIEnv*, jobject obj) const {
137  media::MediaPlayerAndroid* player = manager_->GetFullscreenPlayer();
138  return player ? player->GetVideoHeight() : 0;
139}
140
141int ContentVideoView::GetDurationInMilliSeconds(JNIEnv*, jobject obj) const {
142  media::MediaPlayerAndroid* player = manager_->GetFullscreenPlayer();
143  return player ? player->GetDuration().InMilliseconds() : -1;
144}
145
146int ContentVideoView::GetCurrentPosition(JNIEnv*, jobject obj) const {
147  media::MediaPlayerAndroid* player = manager_->GetFullscreenPlayer();
148  return player ? player->GetCurrentTime().InMilliseconds() : 0;
149}
150
151bool ContentVideoView::IsPlaying(JNIEnv*, jobject obj) {
152  media::MediaPlayerAndroid* player = manager_->GetFullscreenPlayer();
153  return player ? player->IsPlaying() : false;
154}
155
156void ContentVideoView::SeekTo(JNIEnv*, jobject obj, jint msec) {
157  manager_->FullscreenPlayerSeek(msec);
158}
159
160void ContentVideoView::Play(JNIEnv*, jobject obj) {
161  CreatePowerSaveBlocker();
162  manager_->FullscreenPlayerPlay();
163}
164
165void ContentVideoView::Pause(JNIEnv*, jobject obj) {
166  power_save_blocker_.reset();
167  manager_->FullscreenPlayerPause();
168}
169
170void 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);
175}
176
177void ContentVideoView::SetSurface(JNIEnv* env, jobject obj,
178                                  jobject surface) {
179  manager_->SetVideoSurface(
180      gfx::ScopedJavaSurface::AcquireExternalSurface(surface));
181}
182
183void ContentVideoView::RequestMediaMetadata(JNIEnv* env, jobject obj) {
184  base::MessageLoop::current()->PostTask(
185      FROM_HERE,
186      base::Bind(&ContentVideoView::UpdateMediaMetadata,
187                 weak_factory_.GetWeakPtr()));
188}
189
190ScopedJavaLocalRef<jobject> ContentVideoView::GetJavaObject(JNIEnv* env) {
191  return j_content_video_view_.get(env);
192}
193
194gfx::NativeView ContentVideoView::GetNativeView() {
195  JNIEnv* env = AttachCurrentThread();
196  ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
197  if (content_video_view.is_null())
198    return NULL;
199
200  return reinterpret_cast<gfx::NativeView>(
201      Java_ContentVideoView_getNativeViewAndroid(env,
202                                                 content_video_view.obj()));
203
204}
205
206JavaObjectWeakGlobalRef 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(
212      env,
213      Java_ContentVideoView_createContentVideoView(
214          env,
215          content_view_core->GetContext().obj(),
216          reinterpret_cast<intptr_t>(this),
217          content_view_core->GetContentVideoViewClient().obj(),
218          legacyMode).obj());
219}
220
221void ContentVideoView::CreatePowerSaveBlocker() {
222  if (power_save_blocker_) return;
223
224  power_save_blocker_ = PowerSaveBlocker::Create(
225      PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
226      "Playing video").Pass();
227  static_cast<PowerSaveBlockerImpl*>(power_save_blocker_.get())->
228      InitDisplaySleepBlocker(GetNativeView());
229}
230
231void 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();
238  }
239}
240}  // namespace content
241